Kubernetes made easy: Develop and deploy on a cloud cluster
Part 3: Ingress Controller
Table of Contents |
Part 1: Basis
Part 2: Kubernetes Part 3: Ingress Controller Part 4: Design & Conclusions |
Ingress Controller
You often may want to expose multiple services/websites on a single IP (either based on the subdomain or may be on the path in the URL). This could be done manually but often far better is using an Ingress Controller. They offer L7 routing as opposed to L4 LoadBalancer.
Pro:
- You can add a subdomain or certain URLs pointing to an entirely different Service/Pod (without changing your DNS).
- Terminates HTTPS: All services behind your Ingress will be served using TLS/HTTPS from the Internet, while each of your service within your cluster will run on HTTP.
Con:
- Only handle HTTPS: Some Ingress Controllers support HTTP without TLS but at the moment if your service exposes non-HTTP(s) services (e.g. SSH, UDP...) you cannot have it behind an Ingress Controller.
- Because most require TLS, you'll need a TLS certificate.
There are multiple Ingress controllers to choose from. GCE's default Ingress Controller creates a Google Cloud Global LoadBalancer (that costs about $20/month), doesn't support WebSockets at the moment, requires your services to be of type: NodePort
, forces HTTPS... Instead we'll use the Nginx Ingress Controller as follows:
ingress.yml
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
spec:
type: LoadBalancer
loadBalancerIP: 10.10.10.10 # static IP pre-allocated.
ports:
- port: 80
name: http
- port: 443
name: https
selector:
k8s-app: nginx-ingress-lb
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
spec:
replicas: 1
revisionHistoryLimit: 3
template:
metadata:
labels:
k8s-app: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- name: nginx-ingress-controller
# From https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/rc.yaml
image: gcr.io/google_containers/nginx-ingress-controller:0.8.3
imagePullPolicy: Always
args:
- /nginx-ingress-controller
# Ingress controller redirects to the given server for any unknown subdomain, can be any but:
# - Should serve a HTTP/404 on /
# - Must serve a HTTP/200 on /healthz
- --default-backend-service=default/frontend
# Use downward API
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 80
- containerPort: 443
volumeMounts: # Optional
- name: tls-dhparam-vol
mountPath: /etc/nginx-ssl/dhparam
livenessProbe: # Optional
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
resources: # Optional
requests:
memory: "10Mi"
limits:
memory: "100Mi"
volumes: # Optional
- name: tls-dhparam-vol
secret:
secretName: tls-dhparam
- apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
# This tells to only use the Nginx Ingress Controller
# and avoids the creation on a Global LoadBalancer on GKE.
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- secretName: tls-certificate
# List of hosts supported by this certificate:
hosts:
- example.com
- foo.example.com
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: frontend
servicePort: 80
- host: foo.example.com
http:
paths:
- path: /media
backend:
serviceName: my-other-service-name
servicePort: 80
Update the last section with whatever rules you desire.
We also need a TLS (previously called SSL) certificate. We'll generate one but by doing so most browsers will show a big warning unless you've installed locally your certificate as being trusted. What you should do if you don't have a trusted certificate is buy one or get a free one for example on StartSSL. We will also create a DH to enable Perfect Forward Secrecy and further improve security:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj '/CN=*.example.com/O=Example.com'
kubectl create secret tls tls-certificate --key tls.key --cert tls.crt
openssl dhparam -out dhparam.pem 4096
kubectl create secret generic tls-dhparam --from-file=dhparam.pem
kubectl apply -f ingress.yml
We expose to the Internet the Nginx Ingress Controller, which retrieves the Ingress rules we defined and routes accordingly. It'll use our TLS certificate and DH.
There are quite a lot more things you can do with Kubernetes, like running a command once or periodically (cron), and a lot more. We'll just wrap up with some important choices you'll face.