This project creates a custom Kubertenes controller to automate the process of updating the Istio Gateway resource.
The Gateway Servive Operator protects your Istio Gateway object from changes that could potentially break Ingres/Egress within a Kubernetes cluster, teams can utalise the CRD that defines a server block definition within the Gateway object. It supports most of the key Istio functionality and adds additional validation and automation.
Segregation of duties is critical when provisioning Istio in a Kubernetes cluster - The Gateway object should be managed by the same team that is responsible for Istio in the cluster, however, to ensure engineers are able to continue to acheive without breaking their workflow this operator provides them with a secure way to update the Gateway object without directly mutating the resource.
The following is an example of how to structure the required CRD.
apiVersion: gatewayservice.xunholy.github.com/v1alpha1
kind: GatewayService
metadata:
name: example-gateway-service
namespace: default
spec:
hosts:
- "*.example.com"
port: 443
protocol: HTTPS
mode: SIMPLE
trafficType: ingress
tlsOptions: {}
A list of hosts exposed by this gateway service. Standard DNS wildcard prefix syntax is permitted, however, wildcard prefix should be used with caution with a multi-tenancy cluster.
Note: A VirtualService that is bound to a gateway must having a matching host in its default destination. Specifically one of the VirtualService destination hosts is a strict suffix of a gateway host or a gateway host is a suffix of one of the VirtualService hosts.
The Port on which should be used to listen for incoming connections.
Note: The name
field in the Gateway server block uses the following convention: "<protocol-name-namespace>"
This is an Example of how the CRD will generate the name
field automatically as it is not explicitly defined:
port:
name: http-example-default
number: 80
protocol: HTTP
The following protocols are supported and can be specified: HTTP
, HTTPS
, GRPC
, HTTP2
. MONGO
and TCP
.
The following modes are supported and can be specified: SIMPLE
, PASSTHROUGH
and MUTUAL
.
Note: For additional information see the following link HERE.
The following modes are supported and can be specified: INGRESS
and EGRESS
.
TLSOptions that are currently supported are TLSSecret
, TLSSecretRef
and TLSSecretPath
. Please ensure you understand these options so that you choose the method best suited for your situation.
If the TLSSecret option is specified it is implying that the CredentialName
field in the Gateway is going to use the secrets explicitly provided by the CRD. When TLSSecret is being used you MUST provide the certificate and key that will be used for TLS termination, these secrets must be in base64 format (In future these values will be required to be encrpyed).
This method uses the provided secrets and will create a Kubernetes tls secret resource with those explicit values. The Mode will impact which namespace the tls secret is created within. If the SIMPLE
mode is specified the tls termination occurs at the Gateway resource, which will be the Ingress/Egress gateway pod running, therefore the tls secret will be created in the namespace where these pods are currently running (usually in istio-system namespace). However, if the PASSTHROUGH
mode is specified the tls termination occurs at the Pod resource, therefore the tls secret will be created in the namespace that the Pod resource is being executed.
If the TLSSecretRef option is specified it is implied that the tls secret already exists in the namespace the Ingress/Egress pods are running within.
The tls secret object being referenced MUST exist otherwise the CRD will be rejected and the server block will not be added to the Gateway object. The rationale behind this behaviour is because even if a single reference to a tls secret that does not exist is intantiated in the Gateway object it will cause your Ingress/Egress to not work within the entire cluster.
Note: This option only supports using the SIMPLE
mode.
If the TLSSecretRef option is specified it is implied that the Ingress/Egress Pod will mount the tls secret within the Pod and you're referencing a tls secret that already exists. This method might be used if SDS is not available due to using Kubernetes <1.13.0.
However, if SDS is available within your Kubernetes cluster this method is not recommended.
Using TLSSecretPath also requires that the Pods deployment is updated to mount the tls secret into the Pod.
Note: This option is still a work in progress.
The following diagrams will demonstrate both SIMPLE
and PASSTHROUGH
architecture.
If SIMPLE
mode is definted....
If PASSTHROUGH
mode is definted....
The following steps will assume you have a Kubernetes cluster available and are leveraging Istio as a service mesh.
Build the gatewayservice-operator Docker image
operator-sdk build xunholy/k8s-operator:latest
Push the gatewayservice-operator Docker image to a registry
docker push xunholy/k8s-operator:latest
Update the operator.yaml manifest to use the built image name.
Note: If you do NOT have a ingress and/or egress gateway object the following CRD's will not work as expected. To deploy a Gateway object please review gateway.yaml as an example.
Deploy CRDs to a Kubernetes cluster to extend the API server and create the required objects
kubectl apply -f deploy/ -R -n istio-system
Note: This will also deploy the three TLSOptions examples into the Kubernetes cluster. View the file HERE
Verify the gatewayservice operator is running
kubectl get pod -l name=gatewayservice-operator
Congratulations! You will now have the gatewayservice operator up and running locally.
Generate default operator project.
operator-sdk new gatewayservice-operator --repo github.com/xUnholy/k8s-istio-gateway-service-operator
Add a new API for the custom resource
operator-sdk add api --api-version=gatewayservice.xunholy.github.com/v1alpha1 --kind=GatewayService
Add a new controller that watches for GatewayService
operator-sdk add controller --api-version=gatewayservice.xunholy.github.com/v1alpha1 --kind=GatewayService