-
Notifications
You must be signed in to change notification settings - Fork 681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auth: Create Envoy clusters from ExtensionServices #2713
Comments
The Internally, the Contour EndpointsTranslator implements a one-to-one mapping between Kubernetes Service endpoints and Envoy ClusterLoadAssignments (i.e. endpoint discovery service). The EndpointsTranslator operates independently of Contour ingress reconciliation. Ingresses (including HTTPProxies) consume the output of the EndpointsTranslator because internally, Contour generates a stable and predictable ClusterLoadAssignment from a Kubernetes Service name. Note well that this means that the ClusterLoadAssignment generation is completely independent of the rest of the ingress reconciliation. Everything works in the end because the ClusterLoadAssignment names are consistent and globally unique, but there is no explicit coordination here. A HTTPProxy Service generates a one or more DAG Services. A DAG Service generates both and Envoy Cluster (for the cluster discovery service) and a RouteAction (for the route configuration discovery service). Since the DAG Service represents Envoy configuration at multiple configuration layers, some fields are valid at only one of the layers. So, to summarize:
The Envoy diff --git apis/projectcontour/v1alpha1/extensionservice.go apis/projectcontour/v1alpha1/extensionservice.go
index 9b41543b..39249494 100644
--- apis/projectcontour/v1alpha1/extensionservice.go
+++ apis/projectcontour/v1alpha1/extensionservice.go
@@ -26,6 +26,31 @@ type ExtensionProtocolVersion string
// SupportProtocolVersion2 requests the "v2" support protocol version.
const SupportProtocolVersion2 ExtensionProtocolVersion = "v2"
+// ExtensionServiceTarget defines an Kubernetes Service to target with
+// extension service traffic.
+type ExtensionServiceTarget struct {
+ // Name is the name of Kubernetes service that will accept service
+ // traffic.
+ //
+ // +required
+ Name string `json:"name"`
+
+ // Port (defined as Integer) to proxy traffic to since a service can have multiple defined.
+ //
+ // +required
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=65536
+ // +kubebuilder:validation:ExclusiveMinimum=false
+ // +kubebuilder:validation:ExclusiveMaximum=true
+ Port int `json:"port"`
+
+ // Weight defines proportion of traffic to balance to the Kubernetes Service.
+ //
+ // +optional
+ // +kubebuilder:validation:Minimum=0
+ Weight int64 `json:"weight,omitempty"`
+}
+
// ExtensionServiceSpec defines the desired state of an ExtensionService resource.
type ExtensionServiceSpec struct {
// Services specifies the set of Kubernetes Service resources that
@@ -33,7 +58,17 @@ type ExtensionServiceSpec struct {
//
// +required
// +kubebuilder:validation:MinItems=1
- Services []contourv1.Service `json:"services"`
+ Services []ExtensionServiceTarget `json:"services"`
+
+ // UpstreamValidation defines how to verify the backend service's certificate
+ // +optional
+ UpstreamValidation *contourv1.UpstreamValidation `json:"validation,omitempty"`
+
+ // Protocol may be used to specify (or override) the protocol used to reach this Service.
+ // Values may be tls, h2, h2c. If omitted, protocol-selection falls back on Service annotations.
+ // +kubebuilder:validation:Enum=h2;h2c;tls
+ // +optional
+ Protocol *string `json:"protocol,omitempty"`
// The policy for load balancing GRPC service requests. Note
// that the `Cookie` load balancing strategy cannot be used here. This change has 2 benefits:
However, we now encounter some substantial structural problems:
|
This should also be clarified that it's also hashed per route. If the same k8s service is used in two different routes, it will end up producing two clusters in Envoy with unique (but similar) names. This was due to weighting that could be different between each use of the service in the ingress document.
I think we can do this since the correlation between CDS<>EDS is just a name. Thinking about this problem before, we need to create clusters in CDS based upon a route (or in this case an extension service usage). That unique name then can be used in endpointsTranslator to match the same name. This means that clusters in CDS are no longer mapped to k8s services (or ExtensionService) The same work needs to be done inside Contour proper since currently if you had two services referenced in a proxy document and all the endpoints in one of the clusters goes unhealthy, Envoy will still route to the cluster. This applies even if the cluster has active health checking enabled.
I like this! However, weren't there other fields that you wanted from |
I don't think that's implementable. Contour Services bind the header transformations to the forwarding weights and destination. If you set the headers in the HTTP route action, then made a weighted forwarding decision in the cluster, that would break the API guarantees.
Header rewrite only happens in route actions, so you can't do that. Forwarding traffic to external services will use external name in the service. |
Contour uses the I think what we need is a is a lookup in the CDS cache to understand what endpoints are referenced. Something like a Just thinking out loud on this right now, it's worth a discussion on the next community meeting I think.
|
Sorry, I don't think I'm following what you mean here. Is there a different way you could explain it? As I see it, the fundamental problem here is that ClusterLoadAssignments are currently coded to emit endpoints from exactly 1 Kubernetes Service. We need a new concept to represent the weighted Kubernetes Service endpoints behind a single ClusterLoadAssignment, which means major changes to EndpointsTranslator. |
Yes this is exactly what I am proposing/discussing. Today: Contour allows for an array of Services to be defined on a Route. Like discussed previously, each Kubernetes service in a route maps to a unique cluster in Envoy (CDS). Then all those unique Envoy clusters map to EDS via the Future: Contour no longer maintains a 1:1 mapping of route+service --> Envoy cluster --> Single k8s service endpoints in one EDS cluster. We need to move to route+service(s) --> Envoy cluster --> Many k8s service endpoints in one EDS cluster using locality based weighting. This would fix the problem described in this issue along with #1119 (comment). |
Ah it looks like Dave was moving towards this model in #1119, but we can't complete that change now because it would break the v1 API (e.g. header rewriting per service). |
Healthchecks were part of the service but was moved up. Could do a similar pattern here (with an API version bump as mentioned). |
Build processors for both the ExtensionService and HTTPProxy types have to deal with `UpstreamValidation`. Move the helpers that look up `UpstreamValidation` and `DownstreamValidation` types to the Kubernetes cache so that they are accessible to all the build processors. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
`(*ServiceCluster).AddWeightedService` didn't copy the service name properly, leading to a failure to match the service endpoints. Copy the correct fields and add tests for `ServiceCluster` type. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
`(*ServiceCluster).AddWeightedService` didn't copy the service name properly, leading to a failure to match the service endpoints. Copy the correct fields and add tests for `ServiceCluster` type. This updates #2713. Signed-off-by: James Peach <jpeach@vmware.com>
Make ServiceCluster weights consistent with HTTPProxy Route weights. If no weights are specified, distribute the load equally, otherwise take the weights as specified by the users. In the latter case, 0 is a valid weight and removes all traffic from that destination. Hoist the 2 helpers for marshaling protobuf uint32 wrappers into the `protobuf` package since they are part of an API family we now use one of them in the endpoints handler. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Build processors for both the ExtensionService and HTTPProxy types have to deal with `UpstreamValidation`. Move the helpers that look up `UpstreamValidation` and `DownstreamValidation` types to the Kubernetes cache so that they are accessible to all the build processors. This updates #2713. Signed-off-by: James Peach <jpeach@vmware.com>
Make ServiceCluster weights consistent with HTTPProxy Route weights. If no weights are specified, distribute the load equally, otherwise take the weights as specified by the users. In the latter case, 0 is a valid weight and removes all traffic from that destination. Hoist the 2 helpers for marshaling protobuf uint32 wrappers into the `protobuf` package since they are part of an API family we now use one of them in the endpoints handler. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Make ServiceCluster weights consistent with HTTPProxy Route weights. If no weights are specified, distribute the load equally, otherwise take the weights as specified by the users. In the latter case, 0 is a valid weight and removes all traffic from that destination. Hoist the 2 helpers for marshaling protobuf uint32 wrappers into the `protobuf` package since they are part of an API family we now use one of them in the endpoints handler. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Make ServiceCluster weights consistent with HTTPProxy Route weights. If no weights are specified, distribute the load equally, otherwise take the weights as specified by the users. In the latter case, 0 is a valid weight and removes all traffic from that destination. Hoist the 2 helpers for marshaling protobuf uint32 wrappers into the `protobuf` package since they are part of an API family we now use one of them in the endpoints handler. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multipe clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy clusger load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Add ExtensionService to the builtin Kubernetes type helpers for accessing the resource kind and version. This updates projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Make ServiceCluster weights consistent with HTTPProxy Route weights. If no weights are specified, distribute the load equally, otherwise take the weights as specified by the users. In the latter case, 0 is a valid weight and removes all traffic from that destination. Hoist the 2 helpers for marshaling protobuf uint32 wrappers into the `protobuf` package since they are part of an API family we now use one of them in the endpoints handler. This updates #2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Add ExtensionService to the builtin Kubernetes type helpers for accessing the resource kind and version. This updates #2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes projectcontour#2713. Signed-off-by: James Peach <jpeach@vmware.com>
Refactor the ExtensionService `.Services` field so that we have enough information to build an EDS cluster load assignment. Dropping the use of the HTTPProxy `Service` type means that the API aligns more closely with the corresponding Envoy resources and we can build a single Envoy cluster that balances across all the configured Kubernetes services. This wasn't previously possible, since Envoy generally expects external services to be a single cluster and has no provision for balancing across multiple clusters in this part of its API. Add a new `dag.Processor` implementation to build ExtensionService objects in the DAG. These are root-level objects that generate Envoy cluster resources. The `.Services` field emits a `dag.ServiceCluster` object that generates an Envoy cluster load assignment resource to balance traffic within the cluster. This fixes #2713. Signed-off-by: James Peach <jpeach@vmware.com>
Please describe the problem you have
Refactor the services code so that it can be substantially shared between Routes and ExtensionServices. Add DDAG support for generating Envoy clusters that from ExtensionServices.
xref #432
xref #2643
The text was updated successfully, but these errors were encountered: