In this topic, 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 by running:
$ 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, which is also available in TAP. See also Install cert-manager.
You can check if Spring Cloud Gateway package is already installed by running:
$ tanzu package installed list --all-namespaces
If Spring Cloud Gateway is installed, you will 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 step called checking packages available for installation.
After you have Contour and Spring Cloud Gateway for Kubernetes installed, you deploy a Gateway instance pointing to a valid service or application.
For testing only: 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
You can check the status of the Gateway by running:
$ kubectl get springcloudgateways
After some time, the instance will show READY
as True
.
NAME READY REASON
my-gateway True Updated
Contour already supports standard Kubernetes ingress configurations, and the Spring Cloud Gateway for Kubernetes operator provides a Kubernetes service on port 80. So, the next step is to create 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
You can obtain the public IP address by running the following:
$ 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, you can access the service from a web browser using http:///httpbingo/get.
You can now activate TLS in your Ingress and automate the certificate generation in TAP.
To complete the example:
Create a cert-manager Certificate
request to create a certificate using the TAP-provided infrastructure.
Configure the Kubernetes Ingress resource with the generated certificate.
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 that it is installed using the same procedure you used to check 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
...
Tanzu Application Platform includes a ClusterIssuer
resource called tap-ingress-selfsigned
that can be used for this example.
Create the following Certificate
request to obtain a secret called my-gateway-ingress-tls-secret
.
Important commonName
and dnsNames
must match the domain name you intend to 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, you 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 you call the TLS endpoint by running:
$ curl -vk "https://my-gateway.demo/httpbingo/get"
You can see that the response certificate matches the configuration you 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
...