Expose a service with Ingress
If your cluster was provisioned with the optional ingress bundle, it already
runs Traefik (the default traefik IngressClass) and cert-manager with a
letsencrypt-prod ClusterIssuer.
This guide uses the Ingress API, which is the simplest path. For more control (header routing, traffic splitting, multiple backends) see Expose a service with the Gateway API.
We start over plain HTTP to confirm routing works, then add a domain and HTTPS by overwriting the same Ingress.
Deploy a sample app
Section titled “Deploy a sample app”cat <<'EOF' | kubectl apply -f -apiVersion: apps/v1kind: Deploymentmetadata: name: hello-ingressspec: replicas: 1 selector: matchLabels: app: hello-ingress template: metadata: labels: app: hello-ingress spec: containers: - name: hello-ingress image: nginx ports: - containerPort: 80---apiVersion: v1kind: Servicemetadata: name: hello-ingressspec: selector: app: hello-ingress ports: - port: 80 targetPort: 80EOFExpose over plain HTTP
Section titled “Expose over plain HTTP”Create an Ingress. This rule matches any request, so Traefik serves it to anyone hitting the node:
cat <<'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: hello-ingressspec: ingressClassName: traefik rules: - http: paths: - path: / pathType: Prefix backend: service: name: hello-ingress port: number: 80EOFReach it directly at your node IP (the same IP as your API server,
https://<your-node-ip>:6443):
curl http://<your-node-ip>You should get the nginx welcome page.
Add a domain and HTTPS
Section titled “Add a domain and HTTPS”To serve real traffic over HTTPS you need a hostname that resolves to the cluster. Certificates are issued by Let’s Encrypt over an HTTP-01 challenge, so DNS must resolve before you apply.
In your DNS provider, create an A record pointing your hostname at your
cluster’s node IP:
ingress.example.com. A <your-node-ip>Confirm it resolves before continuing:
dig +short ingress.example.comNow overwrite the Ingress with your real hostname, the
cert-manager.io/cluster-issuer annotation, and a tls block. cert-manager
issues a certificate into the hello-ingress-tls secret; Traefik then serves it.
cat <<'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: hello-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt-prodspec: ingressClassName: traefik tls: - hosts: - ingress.example.com secretName: hello-ingress-tls rules: - host: ingress.example.com http: paths: - path: / pathType: Prefix backend: service: name: hello-ingress port: number: 80EOFThe certificate takes a minute or two on first issuance. Watch it become ready:
kubectl get certificate hello-ingress-tls -wOnce READY is True, your app is live over HTTPS:
curl https://ingress.example.comIf issuance stalls, describe the certificate to see the challenge status:
kubectl describe certificate hello-ingress-tlsThe usual cause is DNS that doesn’t yet resolve to your node IP.
Clean up
Section titled “Clean up”kubectl delete ingress hello-ingresskubectl delete service hello-ingresskubectl delete deployment hello-ingresskubectl delete secret hello-ingress-tls --ignore-not-found