Skip to content

HTTP ingress

Allow public Internet access to an HTTP server running on your pod, using the subdomain

http://mynamespace-myname.icedc.se

Example

Create a Service, Ingress, and a Pod running httpd

httpd-example.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testpod
  namespace: johank-myfirstns
  labels:
    app: testapp
spec:
  containers:
    - name: testweb
      image: httpd # Starts Apache HTTP Server
      ports:
        - name: http-port
          containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "100m"
        limits:
          memory: "64Mi"
---
apiVersion: v1
kind: Service
metadata:
  name: test-http-gateway
  namespace: johank-myfirstns
spec:
  selector:
    app: testapp # Matches `metadata.labels.app` from testpod
  ports:
    - name: my-web-port
      protocol: TCP
      targetPort: http-port # Port 80 in testweb
      port: 8081 # Forward it to 8081 for the rest of the cluster
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: johank-myfirstns
spec:
  ingressClassName: nginx
  rules:
    - host: johank-myfirstns-testapp.icedc.se # Choose a subdomain namespace-appname.icedc.se
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: test-http-gateway
                port:
                  number: 8081

Create the objects with

kubectl create -f httpd-example.yaml
pod/testpod created
service/test-http-gateway created
ingress.networking.k8s.io/test-ingress created

You can now open http://johank-myfirstns-testapp.icedc.se in your web browser, at port 80

$ curl johank-myfirstns-testapp.icedc.se
<html><body><h1>It works!</h1></body></html>

Delete them with

kubectl delete -f httpd-example.yaml
pod "testpod" deleted
service "test-http-gateway" deleted
ingress.networking.k8s.io "test-ingress" deleted

Adding Let's Encrypt signed certificate

By default, you have a self-signed certificate assigned to your ingress. So https://johank-myfirstns-testapp.icedc.se will work.

But if you want to have a signed certificate you can create one using the common cert-manager:

letsencrypt-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: testweb
  namespace: johank-myfirstns
spec:
  secretName: testweb-tls-secret
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt
  commonName: johank-myfirstns-testapp.icedc.se
  dnsNames:
  - johank-myfirstns-testapp.icedc.se

Now you can modify your ingress to use this certificate:

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: johank-myfirstns
spec:
  ingressClassName: nginx
  rules:
    - host: johank-myfirstns-testapp.icedc.se # Choose a subdomain namespace-appname.icedc.se
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: test-http-gateway
                port:
                  number: 8081
  tls:
  - secretName: testweb-tls-secret

Ingress troubleshooting

Access your pod with kubectl exec -it testpod -- /bin/sh, install curl, and run

curl test-http-gateway:8081

If you get 502 Bad Gateway or refused connections, most likely your web server is bound to localhost and not listening to 0.0.0.0 as it should.

kubectl get services

Services should output something similar to

NAME               TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
test-http-gateway   ClusterIP   10.43.7.86    <none>        8081/TCP         21m

And Ingresses should look like

kubectl get ingress
NAME          CLASS   HOSTS                       ADDRESS                           PORTS   AGE
test-ingress  nginx   johank-myfirstns-testapp    10.10.116.10,10.10.116.11,10...   80      23m