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}