Читать книгу K8s Applications mit MicroK8S auf Raspberry PI - Alfred Sabitzer - Страница 9
ОглавлениеZertifikate und LetsEncrypt
Inspiration:
https://suda.pl/5-minute-home-server-with/
https://faun.pub/wildcard-k8s-4998173b16c8
https://collabnix.github.io/kubetools/
https://forum.netcup.de/netcup-intern/technik/11841-let-s-encrypt-wildcard-zertifikate-via-certbot/
Um den Cluster vernünftig betreiben zu können braucht es Zertificate.
Darum habe ich den Certificate-Manager installiert.
#!/bin/bash
############################################################################################
# $Date: 2021-10-21 21:40:29 +0200 (Do, 21. Okt 2021) $
# $Revision: 659 $
# $Author: alfred $
# $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K5_certmanager.sh $
# $Id: K5_certmanager.sh 659 2021-10-21 19:40:29Z alfred $
#
# cert-manager
#
############################################################################################
#shopt -o -s errexit #—Terminates the shell script if a command returns an error code.
shopt -o -s xtrace #—Displays each command before it’s executed.
shopt -o -s nounset #-No Variables without definition
# Voraussetzung: Scripts in der richtigen Reihenfolge
#
# Definitionen für das Deployment
#
sname=$(basename "$0")
app="mikrok8s/install/${sname}"
pf=\$"Revision: "
sf=" "\$
fr="\$Revision: 659 $"
revision=${fr#*"$pf"}
revision=${revision%"$sf"*}
xd=(`date '+%Y-%m-%d'`)
wd="${HOME}/copy/${app}/${xd}/r${revision}"
id="/opt/cluster/${app}/${xd}/r${revision}"
rm -f -R ${wd}
mkdir -p ${wd}
#
cat <<EOF > ${wd}/install_certmanager.sh
#!/bin/bash
#
# \$Date: 2021-10-21 21:40:29 +0200 (Do, 21. Okt 2021) $
# \$Revision: 659 $
# \$Author: alfred $
# \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K5_certmanager.sh $
# \$Id: K5_certmanager.sh 659 2021-10-21 19:40:29Z alfred $
#
# Installation des cert-managers mit helm
#
#shopt -o -s errexit #—Terminates the shell script if a command returns an error code.
shopt -o -s xtrace #—Displays each command before it’s executed.
shopt -o -s nounset #-No Variables without definition
# Voraussetzung: Scripts in der richtigen Reihenfolge
microk8s kubectl create namespace cert-manager
microk8s helm3 repo add jetstack https://charts.jetstack.io
microk8s helm3 repo update
microk8s helm3 install cert-manager jetstack/cert-manager \
--namespace cert-manager --version v1.5.4 \
--set installCRDs=true \
--set ingressShim.defaultIssuerName=letsencrypt-production \
--set ingressShim.defaultIssuerKind=ClusterIssuer \
--set ingressShim.defaultIssuerGroup=cert-manager.io
#
#wget https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml --output-document=${id}/cert-manager.yaml
#wget https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.crds.yaml --output-document=${id}/cert-manager.crds.yaml
#microk8s kubectl apply -f ${id}/*.yaml
#
sleep 1m
microk8s kubectl get pods --namespace cert-manager
EOF
chmod 755 ${wd}/install_certmanager.sh
#
ansible pc1 -m shell -a ${id}'/install_certmanager.sh'
#
#!/bin/bash
############################################################################################
# $Date: 2021-11-28 11:05:45 +0100 (So, 28. Nov 2021) $
# $Revision: 1404 $apiVersion: networking.k8s.io/v1
# $Author: alfred $
# $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K14_webserver.sh $
# $Id: K14_webserver.sh 1404 2021-11-28 10:05:45Z alfred $
#
# Einspielen der lokalen Konfigurationen - Produktiv ist slainte.
# https://stackoverflow.com/questions/67430592/how-to-setup-letsencrypt-with-kubernetes-microk8s-using-default-ingress
#
############################################################################################
#shopt -o -s errexit #—Terminates the shell script if a command returns an error code.
shopt -o -s xtrace #—Displays each command before it’s executed.
shopt -o -s nounset #-No Variables without definition
#
# Definitionen für das Deployment
#
sname=$(basename "$0")
app="mikrok8s/install/${sname}"
pf=\$"Revision: "
sf=" "\$
fr="\$Revision: 1404 $"
revision=${fr#*"$pf"}
revision=${revision%"$sf"*}
xd=(`date '+%Y-%m-%d'`)
wd="${HOME}/copy/${app}/${xd}/r${revision}"
id="/opt/cluster/${app}/${xd}/r${revision}"
rm -f -R ${wd}
mkdir -p ${wd}
#
cat <<EOF > ${wd}/webserver-depl-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webserver-depl
namespace: slainte
spec:
selector:
matchLabels:
app: webserver-app
template:
metadata:
labels:
app: webserver-app
spec:
containers:
- name: webserver-app
image: nginx:1.20
---
apiVersion: v1
kind: Service
metadata:
name: webserver-svc
namespace: slainte
spec:
selector:
app: webserver-app
ports:
- port: 80
name: http
targetPort: 80
protocol: TCP
- port: 443
name: https
targetPort: 443
protocol: TCP
EOF
ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/webserver-depl-svc.yaml'
cat <<EOF > ${wd}/letsencrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
#change to your email
email: slainte@slainte.at
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: public
EOF
ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/letsencrypt-staging.yaml'
cat <<EOF > ${wd}/letsencrypt-prod.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
#change to your email
email: slainte@slainte.at
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: public
EOF
ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/letsencrypt-prod.yaml'
cat <<EOF > ${wd}/ingress-routes-update.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webserver-routes
namespace: slainte
annotations:
# Class checken mit kubectl -n ingress describe daemonset.apps/nginx-ingress-microk8s-controller
kubernetes.io/ingress.class: public
# Das ist für das Zertifikat
cert-manager.io/cluster-issuer: "letsencrypt-prod"
# Das ist für das http -> https forwarding
# See https://kubernetes.github.io/ingress-nginx/examples/rewrite/
nginx.ingress.kubernetes.io/rewrite-target: /\$1
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-temporary-redirect: "false"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-proxy-headers: "X-Forwarded-Proto: https"
nginx.ingress.kubernetes.io/proxy-body-size: 0m
nginx.ingress.kubernetes.io/proxy-buffering: "off"
# nginx.ingress.kubernetes.io/ssl-passthrough: "true"
# https://github.com/nginxinc/kubernetes-ingress/tree/v1.12.0/examples/ssl-services
# nginx.ingress.kubernetes.io/ssl-services: "\${image}-svc"
# nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- k8s.slainte.at
secretName: k8s-slainte-at-tls
rules:
- host: k8s.slainte.at
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: webserver-svc
port:
number: 80
defaultBackend:
service:
name: webserver-svc
port:
number: 80
EOF
ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/ingress-routes-update.yaml '
# Service PROD
curl -k -v http://k8s.slainte.at
#erreichbar sein.
#Aber auch mit https
curl -k -v https://k8s.slainte.at
#
## Prüfen des Zertifikates
ansible pc1 -m shell -a 'microk8s kubectl get certificate --all-namespaces'
ansible pc1 -m shell -a 'microk8s kubectl describe certificate --all-namespaces'
ansible pc1 -m shell -a 'microk8s kubectl get certificaterequests.cert-manager.io '
ansible pc1 -m shell -a 'microk8s kubectl describe certificaterequests '
ansible pc1 -m shell -a 'microk8s kubectl get certificatesigningrequests.certificates.k8s.io '
ansible pc1 -m shell -a 'microk8s kubectl get Issuer'
ansible pc1 -m shell -a 'microk8s kubectl get ClusterIssuer'
ansible pc1 -m shell -a 'microk8s kubectl describe ClusterIssuer letsencrypt-prod '
ansible pc1 -m shell -a 'microk8s kubectl get challenges.acme.cert-manager.io '
ansible pc1 -m shell -a 'microk8s kubectl describe challenges.acme.cert-manager.io '
##
exit
Die Zertifikate entstehen dann, wenn sie gebraucht werden. Die Definition ist im Ingress. Derzeit gibt es einen URL pro Namespace, und damit ein Zertifikat.
Die Namespaces werden hier definiert.
#!/bin/bash
############################################################################################
# $Date: 2021-11-23 18:03:25 +0100 (Di, 23. Nov 2021) $
# $Revision: 1272 $
# $Author: alfred $
# $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s_app/namespace/slainte_env.sh $
# $Id: slainte_env.sh 1272 2021-11-23 17:03:25Z alfred $
#
# Bauen und deployen
#
############################################################################################
#shopt -o -s errexit #—Terminates the shell script if a command returns an error code.
shopt -o -s xtrace #—Displays each command before it’s executed.
shopt -o -s nounset #-No Variables without definition
export secretName="k8s-slainte-at-tls"
export host="k8s.slainte.at"
export namespace_comment="Namespace für die Produktion"
export cluster_issuer="letsencrypt-prod"
export docker_registry="docker.registry:5000"
#
Bzw.
#!/bin/bash
############################################################################################
# $Date: 2021-11-23 18:03:25 +0100 (Di, 23. Nov 2021) $
# $Revision: 1272 $
# $Author: alfred $
# $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s_app/namespace/default_env.sh $
# $Id: default_env.sh 1272 2021-11-23 17:03:25Z alfred $
#
# Bauen und deployen
#
############################################################################################
#shopt -o -s errexit #—Terminates the shell script if a command returns an error code.
shopt -o -s xtrace #—Displays each command before it’s executed.
shopt -o -s nounset #-No Variables without definition
export secretName="default-k8s-slainte-at-tls"
export host="default.k8s.slainte.at"
export namespace_comment="Namespace zum Testen"
# export cluster_issuer="letsencrypt-staging"
# Auch hier die Prod, wegen HTTP Strict Transport Security (HSTS)
export cluster_issuer="letsencrypt-prod"
export docker_registry="docker.registry:5000"
#
Das sieht dann im Ingress wie folgt aus:
---
# Yaml für ${image}:${tag}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${image}-routes
namespace: ${namespace}
annotations:
kubernetes.io/ingress.class: public
cert-manager.io/cluster-issuer: "${cluster_issuer}"
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-temporary-redirect: "false"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-proxy-headers: "X-Forwarded-Proto: https"
nginx.ingress.kubernetes.io/proxy-body-size: 0m
nginx.ingress.kubernetes.io/proxy-buffering: "off"
# https://github.com/nginxinc/kubernetes-ingress/tree/v1.12.0/examples/ssl-services
nginx.ingress.kubernetes.io/ssl-services: "${image}-svc"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- ${host}
secretName: ${secretName}
rules:
- host: ${host}
http:
paths: # https://github.com/google/re2/wiki/Syntax, https://www.regular-expressions.info/refcapture.html
- path: /${image}(/|$)(.*)
pathType: Prefix
backend:
service:
name: ${image}-svc
port:
number: 443
defaultBackend:
service:
name: default-svc
port:
number: 80
---
Man könnte aber auch mit Wildcard-Zertifikaten arbeiten. Ist aber in unserem Falle ein wenig übertrieben. Nachdem es ja eh für jeden Namespace und jeden host einen Ingress braucht, kann man dafür auch ein eigenes Zertifikat anlegen lassen.