Deploy Service for Ingress/Egress Actions to Grey Matter on Kubernetes
Last updated
Was this helpful?
Last updated
Was this helpful?
This is an example of deploying a new service into the mesh and configuring it for ingress and egress actions using SPIFFE/SPIRE identities.
An existing Grey Matter deployment following the guide.
This guide assumes you've followed the step to configure a load balancer for ingress access to the mesh. If so, you should have a URL to access the Grey Matter Intelligence 360 application (e.g. a2832d300724811eaac960a7ca83e992-749721369.us-east-1.elb.amazonaws.com:10808
).
Make note of your load balancer ingress URL and use it wherever this guide references {your-gm-ingress-url}
.
setup with a running Fabric mesh.
Generate k8s deployment with the service and sidecar
Configure the sidecar for ingress actions
Configure the sidecar for egress actions
The service we will be using for this walkthrough is a simple egress/ingress service with two endpoints. The /ingress
endpoint will return Ingress request to simple-service successful!
. The /egress
endpoint takes an environment variable EGRESS_ROUTE
, generates a request to that route, and returns its response.
There are a few things to note before generating the deployment file:
The value of the pod label that Grey Matter Control is discovering, environment variable GM_CONTROL_KUBERNETES_CLUSTER_LABEL
The value of the kubernetes port name that Grey Matter Control is discovering, environment variable GM_CONTROL_KUBERNETES_PORT_NAME
The trust_domain of the SPIRE server
The SPIRE server registrar service configuration
Using the Grey Matter Helm Charts, the values of the first and second points are greymatter.io/control
and proxy
by default. The deployment will then need that pod label greymatter.io/control
with a value identifying the service to Grey Matter Control, and its sidecar container will need a port labeled proxy
.
Note: If the registrar service in your setup is configured without the
pod_label
specification, it will generate entries with the SPIRE server in a different form, which will determine both the way that the mesh is configured and the deployment. The entries in this setup will be of the formspiffe://<trust_domain>/ns/<namespace>/sa/<service_account>
, and thus the secrets in the mesh configurations will need to reflect this format instead.
Based on the defaults described, the deployment for the simple-service
will look like the following:
Save the deployment as deployment.yaml
and apply the deployment:
Run kubectl get pods -l=greymatter.io/control=simple-service
and make sure that the containers are running 2/2
before moving on the the mesh configuration.
Now, we will generate the mesh configurations in order to route from edge to the sidecar of the deployment and from the sidecar to the simple-service itself. At the end of this step, the /ingress
endpoint of the simple service should be accessible through the edge and properly return Ingress request to simple-service successful!
.
The first object to generate is the ingress domain of the service.
Save this file as ingress-domain.json
and apply the domain object using the greymatter cli:
Next, create the corresponding ingress listener of the service.
Save this file as ingress-listener.json
and apply it:
The proxy object will indicate that the above domain and listener are meant to configure this specific sidecar. In order to link these objects to the deployment, the name
field of this proxy object must equal the value of the deployment label greymatter.io/control
, which in this case is simple-service
.
Save this file as proxy.json
and apply it:
There are two clusters necessary for ingress connections. The first is the edge-to-simple-service-cluster
. This cluster will be used to locate and route to the simple-service sidecar from edge. In opposition to the listener secret above, the secret
on the edge-to-simple-service-cluster
specifies then that when connecting to the sidecar, use the spiffe certificate with identity spiffe://quickstart.greymatter.io/edge
and only connect to certificate with SAN equal to spiffe://quickstart.greymatter.io/simple-service
.
The instances
field is left empty because Grey Matter Control will discover the sidecar with label greymatter.io/control: simple-service
, and add the instances to this cluster because the name
field matches. Thus, like the proxy object, it is important to note that the name field must equal the greymatter.io/control
label.
The second cluster connects the sidecar to the simple-service
, which is running on port 8080
as specified in the deployment. Because the two containers share a pod, this connection is plaintext over localhost
and needs no secret
. Because we know where the service is running in connection to the sidecar, localhost:8080
, we can hardcode the instance.
Save these files as edge-to-simple-service-cluster.json
and simple-service-cluster.json
, respectively, and apply them:
The two clusters created above, edge-to-simple-service-cluster
and simple-service-cluster
need two shared_rules objects to allow routes to connect to them.
When specifying routes from edge to the simple-service sidecar, we'll use edge-to-simple-service-rules
, and when specifying routes from the simple-service sidecar to the service, we'll use simple-service-rules
.
Save these files as edge-to-simple-service-rules.json
and simple-service-rules.json
, respectively, and apply them:
The last step in the ingress configuration is routes. There will be three routes for ingress to the service.
The first two specify when and how edge should connect to the simple-service sidecar. These two routes will be configured on the edge sidecar, and when a request comes in with path
prefix equal to /services/simple-service/
or /services/simple-service
, it will strip off that value from the path and forward the request to the cluster specified in the shared_rules object that it links to.
The last route configures the simple-service sidecar to route any incoming requests with path prefix "/"
to the simple-service.
Save these files as edge-route.json
, edge-route-slash.json
, and service-route.json
and apply them:
Once all of the configurations are applied, you should be able to access the simple-service at https://{your-gm-ingress-url}/services/simple-service/
and the ingress route at https://{your-gm-ingress-url}/services/simple-service/ingress
. Note that if you try to hit https://{your-gm-ingress-url}/services/simple-service/egress
, the request will fail with upstream connect error or disconnect/reset before headers. reset reason: connection termination
. This is because we have not yet configured the service for egress actions.
For any service being deployed in place of simple-service
that generates requests to other services in the mesh, there is another set of configurations necessary.
For this walkthrough, we have configured the simple-service
with environment variable EGRESS_ROUTE=http://localhost:10909/catalog/summary
. The example that this will show is the simple-service
/egress
endpoint generating a request to the Grey Matter Catalog service, which is also running inside the mesh, and returning the json response from a GET
request of its /summary
endpoint.
In order to allow the simple-service to make requests inside the mesh, we need to open up a second domain/listener combo on the sidecar, this time on a different port than the ingress at 10808
. We will use 10909
. In a non-SPIFFE/SPIRE setup, this second domain/listener is not necessary.
This is necessary for a SPIFFE/SPIRE setup because all of the sidecars are using SPIFFE certificates, fetched by the sidecar using Envoy SDS and not through a physical mount into the service or sidecar containers. Thus, the containers themselves can not have and do not need certificates mounted into them. Because of this, any request generated from within the service (service-A
) can only be http
. But, all incoming requests to a service (say service-B
) within the mesh must go through it's sidecar, and the sidecar is only accepting https
requests with specific SPIFFE certificates.
The services service-A
and service-B
can talk plaintext to their own sidecars. All sidecars have access to their SPIFFE identities via Envoy SDS, so two sidecars can communicate with each other over https
. Thus, the flow of a request generated by service-A
to service-B
looks like the following:
For this example, where simple-service
wants to make a request to the Grey Matter Catalog service for its /summary
endpoint, the flow will look like:
The egress domain object will have force_https
set to false, as we want the sidecar to accept plaintext connections on 10909
. It will add the custom header x-forwarded-proto: https
to requests coming from the domain.
Save this file as egress-domain.json
and apply it:
Save this file as egress-listener.json
and apply it:
The egress cluster must have name
equal to the greymatter.io/control
pod label for the service it is trying to reach in order to Grey Matter Control to give it the instance for the service. In our case, this is the Grey Matter Catalog service, which has greymatter.io/control
label "catalog"
.
The secret
on this cluster will use the SPIFFE certificate with id spiffe://quickstart.greymatter.io/simple-service
and connect only over connections with SAN spiffe://quickstart.greymatter.io/catalog
.
Save this file as simple-service-to-catalog-cluster.json
and apply it:
To configure the egress route to send requests to the simple-service-to-catalog-cluster, we'll generate a shared_rules.
Save this file as simple-service-to-catalog-rules.json
and apply it:
For this example, the egress route we want is to the Grey Matter Catalog service. The way we have chosen to specify this is using path prefix /catalog
on the request. This route will take requests into the simple-service-domain-egress
with path prefix math /catalog
, strip the prefix and forward the request through the cluster specified in shared_rules object simple-service-to-catalog-rules
.
Save this file as simple-service-to-catalog-route.json
and apply it:
Now there are several updates to existing Grey Matter objects that need to be made. First, we know that the simple-service-to-catalog-cluster
will send requests to the Catalog service using SPIFFE certificate with id (or SAN) spiffe://quickstart.greymatter.io/simple-service
. The Catalog service ingress listener secret
will need to have this id added to its subject_names
in order to accept this request.
Locate the secret field. The subject_names
should contain only the edge identity, spiffe://quickstart.greymatter.io/edge
. Change the subject names field to also allow our simple-service identity,
and add simple-service-domain-egress
to the domain_keys
and simple-service-listener-egress
to the listener_keys
. It should look like:
Now, the simple-service
should be configured to successfully make requests to the Grey Matter Catalog service. Go to https://{your-gm-ingress-url}/services/simple-service/egress
to test this out. The egress request should return a string of json, and if you hit the catalog /summary
endpoint directly through edge, https://{your-gm-ingress-url}/services/catalog/latest/summary
, you should see the same result.
For any internal services that your service needs to be able to connect to in the above way will need their own service-a-to-service-b
cluster, route, and shared_rules like the egress ones above. They will connect to the egress domain.
The SPIRE trust domain, by default, is quickstart.greymatter.io
. This will be important for . The SPIRE registrar service, by default, is configured to register entries with the SPIRE server for every pod that is created with the same label that Grey Matter Control is looking for, greymatter.io/control
. It will generate SPIFFE identities for these pods in the form spiffe://<trust_domain>/<greymatter.io/control-value>
. For example, for a pod in the default setup with label greymatter.io/control: control-api
, the registrar will generate an entry with SPIFFE ID spiffe://quickstart.greymatter.io/control-api
.
Note: we set the environment for the service container EGRESS_ROUTE
to https://localhost:10909/catalog/summary
. This will be important when
The combination of the ingress domain and listener opens 0.0.0.0:10808
to accept connections. The secret
set on the listener specifies the SPIFFE identity for the simple-service
pod, spiffe://quickstart.greymatter.io/simple-service
. The sidecar will fetch the certificate for this identity via . The subject_names
field of the secret specifies that only incoming connections with certificate SAN equal to spiffe://quickstart.greymatter.io/edge
will be accepted by the listener.
Note: the domain_keys
and listener_keys
fields take a list of strings. When we add a second domain and listener in , we will add their keys to this proxy.
This allows us to break down the need for the second, "egress" / combo on port 10909
, and how the EGRESS_ROUTE
is formed. With the sidecar for service-A
(or in this example the simple-service
sidecar), listening for plaintext connections over localhost at 10909
, the simple-service
itself can direct requests to its own sidecar at http://localhost:10909
. The sidecar, then, can use path_matching
on a configured to forward specific requests to an . As described below, this egress cluster will be configured with the correct SPIFFE identity for service-A
, and the request will be sent to the ingress domain/listener for service-B
at 10808
.
Lastly, we need to tell the object for the simple-service to add the egress domain and listener to the service configuration.