Here you will learn how to expose Spring Cloud Gateway for Kubernetes outside of your clusters using Contour ingress on the Tanzu Application Platform (commonly known as TAP).
The high-level steps are:
Contour is a supported Kubernetes ingress controller for Tanzu Application Platform and is available as a package. You can check the version with:
$ tanzu package available list contour.tanzu.vmware.com -n tap-install
For full details about the installation see Install Contour in the TAP documentation. The installation requires the pre-installation of cert-manager, available in TAP too, see also Install cert-manager.
We can check if Spring Cloud Gateway package is already installed with.
$ tanzu package installed list --all-namespaces
If it's installed, we'll see the package spring-cloud-gateway.tanzu.vmware.com
and the installation namespace for spring-cloud-gateway.tanzu.vmware.com
.
NAME PACKAGE-NAME PACKAGE-VERSION STATUS NAMESPACE
accelerator accelerator.apps.tanzu.vmware.com 1.5.1 Reconcile succeeded tap-install
api-auto-registration apis.apps.tanzu.vmware.com 0.3.0 Reconcile succeeded tap-install
api-portal api-portal.tanzu.vmware.com 1.3.0 Reconcile succeeded tap-install
...
spring-cloud-gateway spring-cloud-gateway.tanzu.vmware.com 2.0.0-tap.4 Reconcile succeeded tap-install
...
If it's not listed, proceed with the installation. Your cluster will already be prepared for the installation of Spring Cloud Gateway for Kubernetes from the Tanzu Application Platform package repository. You can begin Spring Cloud Gateway for Kubernetes installation from the checking packages available for installation step.
Now that we have Contour and Spring Cloud Gateway for Kubernetes installed, we need to deploy a Gateway instance pointing to a valid service or application.
Only for testing, here is an simple configuration to create an instance with a single route configuration pointing to the public service https://httpbingo.org.
kubectl apply -f - <<EOF
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGateway
metadata:
name: my-gateway
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGatewayRouteConfig
metadata:
name: my-gateway-routes
spec:
routes:
- uri: https://httpbingo.org
predicates:
- Path=/httpbingo/**
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGatewayMapping
metadata:
name: test-gateway-mapping
spec:
gatewayRef:
name: my-gateway
routeConfigRef:
name: my-gateway-routes
---
EOF
We can check the status of the Gateway with
$ kubectl get springcloudgateways
After some time, the instance will be READY
.
NAME READY REASON
my-gateway True Updated
Contour already supports standard Kubernetes ingress configurations, and Spring Cloud Gateway for Kubernetes operator will provided a Kubernetes service on port 80. So, the next step is creating an Ingress resource using the Gateway service provided.
kubectl apply -f - <<EOF
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-gateway-ingress
labels:
app: my-gateway-ingress
spec:
defaultBackend:
service:
name: my-gateway
port:
number: 80
---
EOF
To check availability of the services run.
$ kubectl get services -n {gateway_namespace}
The following service should appear.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-gateway ClusterIP 10.20.12.98 <none> 80/TCP 10m
We can obtain the public IP with
$ kubectl get ingress scg-k8s-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
scg-k8s-ingress <none> my-gateway.demo 34.106.39.12 80, 443 3h55m
Now, we can access the service from a web browser with http:///httpbingo/get.
Finally, you can activate TLS in your Ingress and automate the certificate generation in TAP.
To complete the previous example:
Certificate
request to create a certificate using TAP-provided infrastructure.Note that cert-manager is included in the TAP package repository, and is a requirement for Contour, so it should already be available. You can validate if its installed the same way we did for Spring Cloud Gateway for Kubernetes.
$ tanzu package installed list --all-namespaces
You will see the package cert-manager.tanzu.vmware.com
and the installation namespace.
NAME PACKAGE-NAME PACKAGE-VERSION STATUS NAMESPACE
accelerator accelerator.apps.tanzu.vmware.com 1.5.1 Reconcile succeeded tap-install
api-auto-registration apis.apps.tanzu.vmware.com 0.3.0 Reconcile succeeded tap-install
api-portal api-portal.tanzu.vmware.com 1.3.0 Reconcile succeeded tap-install
...
cert-manager cert-manager.tanzu.vmware.com 2.3.0 Reconcile succeeded tap-install
...
Alongside it, Tanzu Application Platform includes a ClusterIssuer
resource called tap-ingress-selfsigned
that we can use for our example. Create the following Certificate
request to obtain a secret called my-gateway-ingress-tls-secret
. Pay attention to the configuration of commonName
and dnsNames
, those must match the domain name we'll use in Ingress later.
kubectl apply -f - <<EOF
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-gateway-ingress-tls
spec:
secretName: my-gateway-ingress-tls-secret
duration: 2160h
renewBefore: 360h
subject:
organizations:
- example
commonName: my-gateway.demo
isCA: false
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
usages:
- server auth
- client auth
dnsNames:
- my-gateway.demo
issuerRef:
name: tap-ingress-selfsigned
kind: ClusterIssuer
---
EOF
Next, create the final Ingress resource using the secret obtained my-gateway-ingress-tls-secret
.
kubectl apply -f - <<EOF
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: scg-k8s-ingress
labels:
app: scg-k8s-ingress
spec:
tls:
- hosts:
- my-gateway.demo
secretName: my-gateway-ingress-tls-secret
rules:
- host: my-gateway.demo
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-gateway
port:
number: 80
---
EOF
For the next part to work, we need to invoke the service using the domain name in the certificate. If you don't have a domain resolution service, you can fake it adding the Ingress public IP to your hosts file.
As seen before, run kubectl get ingress scg-k8s-ingress
to obtain the IP address. Then, add an entry like the one below in you /etc/hosts configuration file (%SystemRoot%\System32\drivers\etc\hosts in Windows).
34.106.39.12 my-gateway.demo
Finally, if we call the TLS endpoint with
$ curl -vk "https://my-gateway.demo/httpbingo/get"
We can see the response certificate matches the configuration we provided initially (see subject and issuer).
* Connected to my-gateway.demo (34.106.39.12) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: O=example; CN=my-gateway.demo
* start date: Apr 3 12:53:28 2023 GMT
* expire date: Jul 2 12:53:28 2023 GMT
* issuer: CN=tap-ingress-selfsigned-root-ca
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multiplexing
...