Custom Default Backend
Wir erstellen ein Default Backend für den gesamten Microk8s Cluster
Custom Default Backend Dockerfile
Docker Image für das Custom default Backend mit Certbot für Letsencypt
FROM nginx:alpine RUN apk update RUN apk add certbot nano COPY ./html /usr/share/nginx/html COPY secret-patch-template.json / COPY deployment-patch-template.json / COPY entrypoint.sh / RUN chmod +x /entrypoint.sh #CMD ["sh","/entrypoint.sh"]
PHP 7.2 fpm App Dockerfile
Docker Image für PHP 7.2 mit Mysql und GD Extensions
FROM php:7.2-fpm RUN apt-get update && apt-get install -y \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ && docker-php-ext-configure gd \ && docker-php-ext-install -j$(nproc) gd RUN docker-php-ext-install mysqli pdo pdo_mysql RUN mkdir /app COPY hello.php /app
Config Map
Configuration für den Nginx Server
apiVersion: v1 kind: ConfigMap metadata: annotations: name: nginx-config namespace: default data: default.conf: | map $http_upgrade $connection_upgrade { default upgrade; '' close; } # Add upstream for letsencrypt job #upstream letsencrypt { # server letsencrypt:80 max_fails=0 fail_timeout=1s; #} server { listen 80 default_server; listen [::]:80 default_server; root /usr/share/nginx/html; index index.html index.php index.htm index.nginx-debian.html; server_name YOURDOMAIN.COM; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include fastcgi_params; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000; } # Redirect all traffic in /.well-known/ to letsencrypt location ^~ /.well-known/acme-challenge/ { try_files $uri $uri/ =404; #proxy_pass http://letsencrypt; } location /sensors/export/data { autoindex on; } }
Persistent Storage Klasse
Das Custom Default Backend mit Persistentem Volume dient als Frontend für den gesamten Cluster
Persistent Storage Klassen sind global und könnenn in jedem Namespace benutzt werden
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: custom provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer
Persistent Volume
Das persistente Storage erstellt einen bleibenden Datenspeicher, in diesem Falle ein Verzeichnis (/mnt/data/custom-default-backend) auf dem Cluster
Dieser Datenspeicher bleibt nach dem Löschen und erneuten Deployen erhalten.
Persistent Volumes sind global und können in jedem Namespace benutzt werden
kind: PersistentVolume apiVersion: v1 metadata: name: custom-default-backend labels: type: local spec: storageClassName: custom capacity: storage: 5Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data/custom-default-backend" type: DirectoryOrCreate
Persistent Volume Claim
Ein Persistent Volume Claim legt fest, welcher Datenspeicher von welchem Deploment benutzt wird
Persistent Volume Claims sind NICHT global und können von Deployments im gleichen Namespace benutzt werden
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: custom-default-backend-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: custom
Deployment
Dieses Deployment nutzt den persistenen Datenspeicher custom-default-backend-pv und bleibt erhalten
apiVersion: apps/v1 kind: Deployment metadata: name: custom-default-backend labels: app: custom-default-backend #Service Selector spec: replicas: 1 selector: matchLabels: app: custom-default-backend template: metadata: labels: app: custom-default-backend spec: containers: - name: phpapp image: localhost:32000/my-php-app:1.0 #php 7.3 fpm im selben Container volumeMounts: - name: docroot mountPath: /usr/share/nginx/html - name: custom-default-backend image: localhost:32000/custom-default-backend:1.0 imagePullPolicy: Always ports: - containerPort: 8080 volumeMounts: - name: nginx-configs mountPath: /etc/nginx/conf.d - name: docroot mountPath: /usr/share/nginx/html # Load the configuration files for nginx volumes: - name: nginx-configs configMap: name: nginx-config - name: docroot persistentVolumeClaim: claimName: custom-default-backend-pvc readOnly: false
Service
apiVersion: v1 kind: Service metadata: annotations: name: custom-default-backend-svc spec: type: ClusterIP selector: app: custom-default-backend ports: - port: 8080 targetPort: 80 name: http
Der Ingress sieht wie folgt aus:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: public nginx.ingress.kubernetes.io/rewrite-target: / name: custom-default-backend-ingress spec: tls: - hosts: - YOURDOMAIN.COM secretName: letsencrypt-tls defaultBackend: service: name: custom-default-backend-svc port: number: 80 rules: - host: YOURDOMAIN.COM http: paths: - path: / pathType: Prefix backend: service: name: custom-default-backend-svc port: number: 80
secret-patch-template.json
{ "kind": "Secret", "apiVersion": "v1", "metadata": { "name": "NAME", "namespace": "NAMESPACE" }, "data": { "tls.crt": "TLSCERT", "tls.key": "TLSKEY" } }
deployment-patch-template.json
{ "kind": "Deployment", "apiVersion": "apps/v1", "metadata": { "name": "NAME", "namespace": "NAMESPACE" }, "spec": { "template": { "metadata": { "annotations": { "tlsUpdated": "TLSUPDATED" } } } } }
entrypoint.sh
#!/bin/bash if [[ -z $EMAIL || -z $DOMAINS || -z $SECRET ]]; then echo "EMAIL, DOMAINS, and SECRET env vars required" env exit 1 fi echo "Inputs:" echo " EMAIL: $EMAIL" echo " DOMAINS: $DOMAINS" echo " SECRET: $SECRET" DEPLOYMENT=custom-default-backend NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) echo "Current Kubernetes namespce: $NAMESPACE" echo "Starting certbot..." certbot certonly --webroot -w /usr/share/nginx/html -n --agree-tos --email ${EMAIL} --no-self-upgrade -d ${DOMAINS} echo "Certbot finished..." echo "Finiding certs. Exiting if certs are not found ..." CERTPATH=/etc/letsencrypt/live/$(echo $DOMAINS | cut -f1 -d',') ls $CERTPATH || exit 1 echo "Creating update for secret..." cat /secret-patch-template.json | \ sed "s/NAMESPACE/${NAMESPACE}/" | \ sed "s/NAME/${SECRET}/" | \ sed "s/TLSCERT/$(cat ${CERTPATH}/fullchain.pem | base64 | tr -d '\n')/" | \ sed "s/TLSKEY/$(cat ${CERTPATH}/privkey.pem | base64 | tr -d '\n')/" \ > /secret-patch.json echo "Checking json file exists. Exiting if not found..." ls /secret-patch.json || exit 1 # Update Secret echo "Updating secret..." curl \ --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ -XPATCH \ -H "Accept: application/json, */*" \ -H "Content-Type: application/strategic-merge-patch+json" \ -d @/secret-patch.json https://kubernetes/api/v1/namespaces/${NAMESPACE}/secrets/${SECRET} \ -k -v echo "Done" cat /deployment-patch-template.json | \ sed "s/TLSUPDATED/$(date)/" | \ sed "s/NAMESPACE/${NAMESPACE}/" | \ sed "s/NAME/${DEPLOYMENT}/" \ > /deployment-patch.json ls /deployment-patch.json || exit 1 # update pod spec on ingress deployment to trigger redeploy curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -k -v -XPATCH -H "Accept: application/json, */*" -H "Content-Type: application/strategic-merge-patch+json" -d @/deployment-patch.json https://kubernetes/apis/apps/v1/namespaces/${NAMESPACE}/deployments/${DEPLOYMENT}