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:

  • Install Contour package in your TAP cluster
  • Install Spring Cloud Gateway for Kubernetes, if not already installed
  • Deploy an instance of Spring Cloud Gateway for Kubernetes
  • Setup a Kubernetes Ingress
  • (Optional) For TLS support, automate your certificates using cert-manager
Gateway resources and TAP packages.

Installing Contour ingress controller

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.

Installing Spring Cloud Gateway for Kubernetes

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.

Deploying an instance of Spring Cloud Gateway for Kubernetes

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

Setting up a Kubernetes ingress

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.

Automating TLS configuration with cert-manager

Finally, you can activate TLS in your Ingress and automate the certificate generation in TAP.

Automate certificate generation in TAP from Contour Ingress.

To complete the previous example:

  1. Create a cert-manager Certificate request to create a certificate using TAP-provided infrastructure.
  2. 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 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
...
check-circle-line exclamation-circle-line close-line
Scroll to top icon