Kuberneties Networking Notes (Ingress)

The goal of Ingress is to be a L7 Load balancer: Ingress will handel your load-balancing, authentication, SSL, and URL based routing config. This still needs to be exposed using a NodePort.

This uses a LB/reverse-proxy like GCE, NGINX, HAPROXY, Traefik as your Ingress Controller (Doesn’t come with Kube by default, so if you don’t build these your ingress stuff won’t work). GCE and NGINXS are currently being supported/maintained by the Kuberneties project. The rules that are configured are the Ingress Resources.

We will also need the service to expose the Ingress to the outside

apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
spec:
type: LoadBalancer
selector:
app: nginx-ingress
ports:
- protocol: TCP
port: 80
targetPort: 80
- protocol: TCP
port: 443
targetPort: 443

You’ll also need the config-map that is referenced in the Deployment

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration

Next we’ll need to deploy the nginx pod

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-ingress-controller
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: quay.io/repository/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0 # A specal nginx image for kub ingress controllers
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration #config map we made before
          env:
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          resources:
            limits:
              cpu: "500m"
              memory: "512Mi"
            requests:
              cpu: "200m"
              memory: "256Mi"

We’ll also need a service account so that the system can monitor watching for Ingress objects and configure the NGINX to make them work, for that it will need a service account

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount

Well that wasn’t fun at all, but now we should be able to setup the LB features, like routing based on the path name: So going to <node-ip>/pod-a for example

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  # NGINX only, This will remove the /pod-a or /pod-b from the URL
spec:
  rules:
    - http:
        paths:
          - path: /pod-a
            pathType: Prefix   # This sets it up so that /pod-a and /pod-a/info would both go to the pod as /, so it will remove everything in the path if it matches /pod-a/
            backend:
              service:
                name: pod-a-service  
                port:
                  number: 80
          - path: /pod-b
            pathType: Prefix
            backend:
              service:
                name: pod-b-service
                port:
                  number: 80
                  

Please note the line nginx.ingress.kubernetes.io/rewrite-target: / This will re-wite anything that patches the path to /, so /pod-a/info will be re-written and pod-a will get the path /.
If you wanted to keep the /info you could do something like this (This code is un-tested)

nginx.ingress.kubernetes.io/rewrite-target: /$2

paths:
  - path: /pod-a(/|$)(.*)
    pathType: Prefix
    backend:

With this The path regex captures the part after /pod-a into $2, The rewrite-target uses $2 to forward only the remainder of the path to the backend service.

  • Example with Modified Configuration:
    • Request: /pod-a/info
      • Backend Receives: /info
    • Request: /pod-a/
      • Backend Receives: /

But what if you want to host multiple websites on the same Kube server? For that you would want to look into the hosts field.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: pod-a.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: pod-a-service
                port:
                  number: 80
    - host: pod-b.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: pod-b-service
                port:
                  number: 80