Skip to main content
In this guide, we’ll walk through the process of deploying a simple HTTP server secured with TLS and exposed via the Kubernetes Gateway API. To securely deploy your applications on Ubicloud Kubernetes clusters using TLS, set up NGINX Gateway Fabric along with cert-manager. This setup handles all your TLS needs using the Gateway API. Follow this step-by-step guide to deploy and expose an HTTPS application on your Kubernetes cluster.

Prerequisites

To complete this tutorial, kubectl and helm must be installed. You can follow the official installation guides available on the Kubernetes website and Helm website You’ll also need an active domain and access to the control panel for managing DNS records in order to complete this guide.

Creating a Kubernetes Cluster

If you don’t have a Kubernetes cluster yet, you can create one using Ubicloud. Follow the instructions in the Quickstart Guide to set up your cluster and configure kubectl to access it.

Installing the required addons

You’ll need an email to register yourself with letsencrypt.
export CLUSTER_ISSUER_EMAIL=email@yourcompany.com
Next, we’ll install the Gateway API CRDs, NGINX Gateway Fabric, and cert-manager.
kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.4.2" | kubectl apply -f -

helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric --create-namespace -n nginx-gateway

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace \
  --set crds.enabled=true \
  --set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \
  --set config.kind="ControllerConfiguration" \
  --set config.enableGatewayAPI=true
We’ll also create a ClusterIssuer in order to get certificates from letsencrypt for our service. Note the gatewayHTTPRoute solver, which tells cert-manager to use the Gateway API for HTTP-01 challenges.
kubectl apply -f <(cat <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
 name: letsencrypt
spec:
 acme:
   server: https://acme-v02.api.letsencrypt.org/directory
   email: $CLUSTER_ISSUER_EMAIL
   privateKeySecretRef:
     name: letsencrypt
   solvers:
   - http01:
       gatewayHTTPRoute: {}
EOF
)

Create a Gateway

First, create a CNAME record with your DNS provider pointing *.somesubdomain.yourdomain.com to the domain listed in the “Service URL” in the Overview page of your Kubernetes cluster in Ubicloud console. Feel free to use any subdomain that best suits your setup.
export DOMAIN_SUFFIX=somesubdomain.yourdomain.com
Next, create a Gateway resource. NGINX Gateway Fabric will automatically provision a LoadBalancer Service and an NGINX data plane when a Gateway is created.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
  - name: https
    hostname: "hello-world.$DOMAIN_SUFFIX"
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: hello-world-tls
EOF
Once the Gateway is created, a Service named gateway-nginx will appear in the default namespace. This Service is of type LoadBalancer, and the EXTERNAL-IP column will display a domain that resolves to the IPs of your worker nodes. You can see this service using the command below
kubectl get service gateway-nginx
Here’s a sample output of the command:
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP                                  PORT(S)                      AGE
gateway-nginx   LoadBalancer   10.105.61.236   devcluster-services-0b1c1.k8s.ubicloud.com   80:32271/TCP,443:30363/TCP   8m15s
The certificateRefs field points to a Kubernetes Secret named hello-world-tls where the TLS certificate and private key will be stored. This Secret doesn’t exist yet — cert-manager will create it in the next step. You can monitor the certificate status with:
kubectl get certificate hello-world-tls
Wait until the READY column shows True before proceeding.

Deploy the application, Service, and HTTPRoute

Now deploy a simple NGINX web server, expose it as a Service, and create an HTTPRoute to route external HTTPS traffic to it.
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
 name: hello-world-deployment
spec:
 replicas: 1
 selector:
   matchLabels:
     app: hello-world
 template:
   metadata:
     labels:
       app: hello-world
   spec:
     containers:
     - name: hello-world
       image: nginx
       ports:
       - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
 name: hello-world-service
spec:
 selector:
   app: hello-world
 ports:
 - port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: hello-world
spec:
  parentRefs:
  - name: gateway
    sectionName: https
  hostnames:
  - "hello-world.$DOMAIN_SUFFIX"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: hello-world-service
      port: 80
EOF
This creates three resources:
  • Deployment: Runs an NGINX container that serves the default welcome page on port 80.
  • Service: Exposes the Deployment inside the cluster so that the HTTPRoute can forward traffic to it.
  • HTTPRoute: Attaches to the Gateway’s https listener (via sectionName: https) and routes all requests for hello-world.<your-domain> to the hello-world-service. This is the resource that connects your external HTTPS traffic all the way to your application pods.
Now you can visit https://hello-world.somesubdomain.yourdomain.com!