Expose your app with Ingress and TLS
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
Deploy your first app left the demo app reachable only from inside the cluster. This guide puts it on the public internet, with a real domain and a valid HTTPS certificate: an ingress controller in front, cert-manager fetching certificates from Let’s Encrypt, and one Ingress object per app. The pattern works on any conformant Kubernetes cluster; we use a paasbox cluster as the example.
What you’ll need
Section titled “What you’ll need”- The demo app from deploy your first app running (namespace
demo, Servicewebon port 80) — or any Service you want to expose. helminstalled locally, alongsidekubectl.- A domain name you control, with access to its DNS records. We’ll use
demo.example.com— substitute your own throughout.
1. Install ingress-nginx
Section titled “1. Install ingress-nginx”The ingress controller is the single front door for all HTTP(S) traffic into the cluster. Its
Service has type LoadBalancer, so the cloud-controller-manager automatically provisions a
Hetzner load balancer in your project when you install it:
helm upgrade --install ingress-nginx ingress-nginx \ --repo https://kubernetes.github.io/ingress-nginx \ --namespace ingress-nginx --create-namespace \ --set controller.service.annotations."load-balancer\.hetzner\.cloud/location"=nbg1Set the location annotation to your cluster’s region (nbg1 here). Wait for the load balancer to
get a public IP:
kubectl -n ingress-nginx get svc ingress-nginx-controller -wAfter a minute or so the EXTERNAL-IP column fills in. Note the IP — your DNS record points at it.
This load balancer appears on your Hetzner bill. Like your worker nodes, it lives in your own Hetzner project and Hetzner bills you for it directly — it’s part of the two bills split, not the paasbox fee. One load balancer serves all the apps behind the ingress controller, so you don’t pay per app. Deleting the Service (see cleanup) deletes the load balancer and stops the charge.
2. Install cert-manager and a Let’s Encrypt issuer
Section titled “2. Install cert-manager and a Let’s Encrypt issuer”cert-manager watches your Ingress objects and keeps valid certificates in place — issuing, renewing, all automatic:
helm upgrade --install cert-manager cert-manager \ --repo https://charts.jetstack.io \ --namespace cert-manager --create-namespace \ --set crds.enabled=trueThen give it an account with Let’s Encrypt. Save this as cluster-issuer.yaml — replace the
email with your own (Let’s Encrypt sends expiry notices there, though cert-manager renews well
before expiry):
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: letsencrypt-prodspec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: you@example.com privateKeySecretRef: name: letsencrypt-prod-account-key solvers: - http01: ingress: ingressClassName: nginxkubectl apply -f cluster-issuer.yamlThis uses the HTTP-01 challenge: Let’s Encrypt verifies you control the domain by fetching a token over plain HTTP through your new ingress. No DNS provider credentials needed — but the domain must resolve to your load balancer first, which is step 3.
3. Point DNS at the load balancer
Section titled “3. Point DNS at the load balancer”At your DNS provider, create an A record for your hostname pointing at the load balancer IP from step 1:
demo.example.com. 300 IN A <EXTERNAL-IP>Confirm it resolves before moving on — the certificate can’t be issued until it does:
dig +short demo.example.com4. Create the Ingress
Section titled “4. Create the Ingress”The Ingress ties it together: route demo.example.com to the web Service, and let cert-manager
handle the certificate. Save as ingress.yaml:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: web namespace: demo annotations: cert-manager.io/cluster-issuer: letsencrypt-prodspec: ingressClassName: nginx tls: - hosts: [demo.example.com] secretName: web-tls rules: - host: demo.example.com http: paths: - path: / pathType: Prefix backend: service: name: web port: { number: 80 }kubectl apply -f ingress.yamlcert-manager spots the annotation, runs the HTTP-01 challenge, and stores the issued certificate
in the web-tls Secret. Watch it happen:
kubectl -n demo get certificate -wREADY flips to True — typically within a minute or two.
Certificate stuck in pending? Almost always DNS: the record doesn’t resolve publicly yet (fresh records and negative caching can take a few minutes), or it points at the wrong IP.
kubectl -n demo describe certificaterequestand the cert-manager logs say exactly which check failed. Fix the record, and issuance proceeds on its own.
5. Verify
Section titled “5. Verify”curl https://demo.example.comA response from the app, over HTTPS, with a valid certificate — check the padlock in a browser, or:
curl -vI https://demo.example.com 2>&1 | grep -E 'subject|issuer'From here, every additional app is just another Ingress object: same controller, same load balancer, same issuer — one manifest per hostname.
Clean up
Section titled “Clean up”If this was just an experiment, delete in reverse order:
kubectl delete -f ingress.yaml # releases the certificate secrethelm -n cert-manager uninstall cert-managerhelm -n ingress-nginx uninstall ingress-nginx # deletes the Hetzner load balancerkubectl delete namespace ingress-nginx cert-managerUninstalling ingress-nginx removes the LoadBalancer Service, and the cloud-controller-manager
deletes the Hetzner load balancer with it — that line item leaves your Hetzner bill. Remember to
remove the DNS record too.
Next steps
Section titled “Next steps”- Scale & autoscale workloads — now that traffic can reach the app, let the cluster grow and shrink it.
- Guides for running Postgres with CloudNativePG and deploying a full Django SaaS behind this ingress setup are on the way.