Interfaces
This section defines the Go Interfaces needed for the development of the OSM in this repository.
This section adopts the following assumptions:
- 1:1 relationship between a proxy and an instance of a service. (No more than one service fronted by the same proxy.)
- 1:1 relationship between an endpoint (port and IP) and a proxy
Proxy Control Plane
The Proxy control plane handles gRPC connections from the service mesh sidecar proxies and implements Envoy’s go-control-plane
.
For a fully functional Envoy-based service mesh, the proxy control plane must implement the following interface:
- Aggregated Discovery Service - source
// AggregatedDiscoveryServiceServer is the server API for AggregatedDiscoveryService service. type AggregatedDiscoveryServiceServer interface { StreamAggregatedResources(AggregatedDiscoveryService_StreamAggregatedResourcesServer) error DeltaAggregatedResources(AggregatedDiscoveryService_DeltaAggregatedResourcesServer) error }
Aggregated Discovery Service
The StreamAggregatedResources
method is the entrypoint into the ADS vertical of OSM. This is
declared in the AggregatedDiscoveryServiceServer
interface, which is provided by the
Envoy Go control plane. It is declared in ads.pb.go.
Method DeltaAggregatedResources
is used by the ADS REST API. This project
implements gRPC only and this method will not be implemented.
When the Envoy Go control plane evaluates
StreamAggregatedResources
it passes a AggregatedDiscoveryService_StreamAggregatedResourcesServer
server. The
implementation of the StreamAggregatedResources
method will then use server.Send(response)
to send
an envoy.DiscoveryResponce
to all connected proxies.
An MVP implementation of StreamAggregatedResources
would require:
- Depending on the
DiscoveryRequest.TypeUrl
theDiscoveryResponse
struct for CDS, EDS, RDS, LDS or SDS is created. This will provide connected Envoy proxies with a list of clusters, mapping of service name to list of routable IP addresses, list of permitted routes, listeners and secrets respectively. - a method of notifying the system when the method described in #1 needs to be evaluated to refresh the connected Envoy proxies with the latest available resources (endpoints, clusters, routes, listeners or secrets)
Mesh Catalog Interface
In the previous section, we proposed implementation of the StreamAggregatedResources
method. This provides
connected Envoy proxies with a list of clusters, mapping of service name to list of routable IP addresses, list of permitted routes, listeners and secrets for CDS, EDS, RDS, LDS and SDS respectively.
The ListEndpointsForService
, ListTrafficPolicies
methods will be provided by the OSM component, which we refer to
as the Mesh Catalog in this document.
The Mesh Catalog will have access to the MeshSpec
, CertificateManager
, and the list of EndpointsProvider
s.
// MeshCataloger is the mechanism by which the Service Mesh controller discovers all Envoy proxies connected to the catalog.
type MeshCataloger interface {
// GetSMISpec returns the SMI spec
GetSMISpec() smi.MeshSpec
// ListAllowedInboundServiceAccounts lists the downstream service accounts that can connect to the given service account
ListAllowedInboundServiceAccounts(service.K8sServiceAccount) ([]service.K8sServiceAccount, error)
// ListAllowedOutboundServiceAccounts lists the upstream service accounts the given service account can connect to
ListAllowedOutboundServiceAccounts(service.K8sServiceAccount) ([]service.K8sServiceAccount, error)
// ListServiceAccountsForService lists the service accounts associated with the given service
ListServiceAccountsForService(service.MeshService) ([]service.K8sServiceAccount, error)
// ListSMIPolicies lists SMI policies.
ListSMIPolicies() ([]*split.TrafficSplit, []service.K8sServiceAccount, []*spec.HTTPRouteGroup, []*target.TrafficTarget)
// ListEndpointsForService returns the list of provider endpoints corresponding to a service
ListEndpointsForService(service.MeshService) ([]endpoint.Endpoint, error)
// ExpectProxy catalogs the fact that a certificate was issued for an Envoy proxy and this is expected to connect to XDS.
ExpectProxy(certificate.CommonName)
// GetServicesFromEnvoyCertificate returns a list of services the given Envoy is a member of based on the certificate provided,
// which is a cert issued to an Envoy for XDS communication (not Envoy-to-Envoy).
GetServicesFromEnvoyCertificate(certificate.CommonName) ([]service.MeshService, error)
// RegisterProxy registers a newly connected proxy with the service mesh catalog.
RegisterProxy(*envoy.Proxy)
// UnregisterProxy unregisters an existing proxy from the service mesh catalog
UnregisterProxy(*envoy.Proxy)
// GetServicesForServiceAccount returns a list of services corresponding to a service account
GetServicesForServiceAccount(service.K8sServiceAccount) ([]service.MeshService, error)
// GetIngressPoliciesForService returns the inbound traffic policies associated with an ingress service
GetIngressPoliciesForService(service.MeshService, service.K8sServiceAccount) ([]*trafficpolicy.InboundTrafficPolicy, error)
}
Additional types needed for this interface:
// MeshService is a type for a namespaced service
type MeshService struct {
Namespace string
Name string
}
// NamespacedServiceAccount is a type for a namespaced service account
type NamespacedServiceAccount struct {
Namespace string
ServiceAccount string
}
// TrafficPolicy is a struct of the allowed RoutePaths from sources to a destination
type TrafficPolicy struct {
PolicyName string
Destination TrafficResource
Source TrafficResource
PolicyRoutePaths []RoutePolicy
}
// Proxy is a representation of an Envoy proxy connected to the xDS server.
// This should at some point have a 1:1 match to an Endpoint (which is a member of a meshed service).
type Proxy struct {
certificate.CommonName
net.IP
ServiceName service.MeshService
announcements chan announcements.Announcement
lastSentVersion map[TypeURI]uint64
lastAppliedVersion map[TypeURI]uint64
lastNonce map[TypeURI]string
}
Endpoints Providers Interface
The Endpoints providers component provides abstractions around the Go SDKs of various Kubernetes clusters, or cloud vendor’s virtual machines and other compute, which participate in the service mesh. Each endpoint provider is responsible for either a particular Kubernetes cluster, or a cloud vendor subscription. The Mesh catalog will query each Endpoints provider for a particular service, and obtain the IP addresses and ports of the endpoints handling traffic for service.
The Endpoints providers are aware of:
- Kubernetes Service and their own CRD
- vendor-specific APIs and methods to retrieve IP addresses and Port numbers for Endpoints
The Endpoints providers has no awareness of:
- what SMI Spec is
- what Proxy or sidecar is
Note: As of this iteration of OSM we deliberately choose to leak the Mesh Specification implementation into the EndpointsProvider. The Endpoints Providers are responsible for implementing a method to resolve an SMI-declared service to the provider’s specific resource definition. For instance, when Azure EndpointProvider’s
ListEndpointsForService
is invoked with some a service name the provider would use its own method to resolve the service to a list of Azure URIs (example:/resource/subscriptions/e3f0/resourceGroups/mesh-rg/providers/Microsoft.Compute/virtualMachineScaleSets/baz
). These URIs are unique identifiers of Azure VMs, VMSS, or other compute with Envoy reverse-proxies, participating in the service mesh.
In the sample ListEndpointsForService
implementation, the Mesh Catalog loops over a list of Endpoints providers:
for _, provider := range catalog.ListEndpointsProviders() {
For each provider
registered in the Mesh Catalog, we invoke ListEndpointsForService
.
The function will be provided a ServiceName
, which is an SMI-declared service. The provider will
resolve the service to its own resource ID. For example ListEndpointsForService
invoked on the
Azure EndpointsProvider with service webservice
, will resolve webservice
to the URI of an
Azure VM hosting an instance of
the service: /resource/subscriptions/e3f0/resourceGroups/mesh-rg/providers/Microsoft.Compute/virtualMachineScaleSets/baz
.
From the URI the provider will resolve the list of IP addresses of participating Envoy proxies.
package osm
// EndpointsProvider is an interface to be implemented by components abstracting Kubernetes, Azure, and other compute/cluster providers.
type EndpointsProvider interface {
// ListEndpointsForService fetches the IPs and Ports for the given service
ListEndpointsForService(ServiceName) []Endpoint
}
Mesh Specification
This component provides an abstraction around the SMI Spec Go SDK.
The abstraction hides the Kubernetes primitives. This allows us to implement SMI Spec providers
that do not rely exclusively on Kubernetes for storage etc. MeshSpec
Interface provides
a set of methods, listing all services, traffic splits, and policy definitions for the
entire service mesh.
The MeshSpec
implementation has no awareness of:
- what Envoy or reverse-proxy is
- what IP address, Port number, or Endpoint is
- what Azure, Azure Resource Manager etc. is or how it works
// MeshSpec is an interface declaring functions, which provide the specs for a service mesh declared with SMI.
type MeshSpec interface {
// ListTrafficSplits lists SMI TrafficSplit resources
ListTrafficSplits() []*split.TrafficSplit
// ListServiceAccounts lists ServiceAccount resources specified in SMI TrafficTarget resources
ListServiceAccounts() []service.K8sServiceAccount
// GetService fetches a Kubernetes Service resource for the given MeshService
GetService(service.MeshService) *corev1.Service
// ListServices Lists Kubernets Service resources that are part of monitored namespaces
ListServices() []*corev1.Service
// ListHTTPTrafficSpecs lists SMI HTTPRouteGroup resources
ListHTTPTrafficSpecs() []*spec.HTTPRouteGroup
// ListTrafficTargets lists SMI TrafficTarget resources
ListTrafficTargets() []*target.TrafficTarget
// GetBackpressurePolicy fetches the Backpressure policy for the MeshService
GetBackpressurePolicy(service.MeshService) *backpressure.Backpressure
// GetAnnouncementsChannel returns the channel on which SMI client makes announcements
GetAnnouncementsChannel() <-chan interface{}
}
Certificate Manager
The certificate.Manager
as shown below is as simple as having a single method for issuing certificates, and another for obtaining a notification channel.
package certificate
// Manager is the interface declaring the methods for the Certificate Manager.
type Manager interface {
// IssueCertificate issues a new certificate.
IssueCertificate(CommonName, time.Duration) (Certificater, error)
// GetCertificate returns a certificate given its Common Name (CN)
GetCertificate(CommonName) (Certificater, error)
// RotateCertificate rotates an existing certificate.
RotateCertificate(CommonName) (Certificater, error)
// GetRootCertificate returns the root certificate.
GetRootCertificate() (Certificater, error)
// ListCertificates lists all certificates issued
ListCertificates() ([]Certificater, error)
// ReleaseCertificate informs the underlying certificate issuer that the given cert will no longer be needed.
// This method could be called when a given payload is terminated. Calling this should remove certs from cache and free memory if possible.
ReleaseCertificate(CommonName)
// GetAnnouncementsChannel returns a channel, which is used to announce when changes have been made to the issued certificates.
GetAnnouncementsChannel() <-chan interface{}
}
Additionally we define an interface for the Certificate
object, which requires the following methods:
// Certificater is the interface declaring methods each Certificate object must have.
type Certificater interface {
// GetCommonName retrieves the name of the certificate.
GetCommonName() CommonName
// GetCertificateChain retrieves the cert chain.
GetCertificateChain() []byte
// GetPrivateKey returns the private key.
GetPrivateKey() []byte
// GetIssuingCA returns the root certificate for the given cert.
GetIssuingCA() Certificater
// GetExpiration() returns the expiration of the certificate
GetExpiration() time.Time
// GetSerialNumber returns the serial number of the given certificate.
GetSerialNumber() string
}
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.