Zum Inhalt springen
A beautiful cover image with the text "Kubernetes"

Die Arbeit mit dockerDocker-Containern kann schwierig sein. Es gibt jedoch Tools, die das Management von Containern verbessern, wie kubernetesKubernetes. Tatsächlich ist Kubernetes meines Wissens das einzige Tool, das als Management-Software für Docker-Container fungiert. Kubernetes ist in fast allen Cloud-Anbietern wie Google Cloud, Azure und AWS gut integriert. Dadurch hat es eine standardisierte yaml-Syntax, was für kleine Entwickler großartig ist, da sie mit geringem Aufwand zwischen The Big Three wechseln können.

tl;dr

Alles installieren und dann cert-manager anwenden. Ganz einfach.

Terminal-Fenster
curl -sfL https://get.k3s.io | sh -s - \
--flannel-backend=none \
--disable-kube-proxy \
--disable servicelb \
--disable-network-policy \
--disable traefik \
--cluster-init
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add cilium https://helm.cilium.io/
helm repo update
helm install cilium cilium/cilium
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz
cilium install \
--set k8sServiceHost=${API_SERVER_IP} \
--set k8sServicePort=6443 \
--set kubeProxyReplacement=true
cilium status --wait
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
cert-manager.yaml
# secret-cloudflare.yaml
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key-secret
namespace: cert-manager
type: Opaque
stringData:
api-key: <Cloudflare API Token (not encrypted)>
---
# cert-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: acme-issuer
namespace: cert-manager
spec:
acme:
email: <Email for updates>
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: acme-issuer
solvers:
- dns01:
cloudflare:
email: <Cloudflare account Email>
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token

k3s installieren

Wie Hagen in seinem Artikel erklärt, möchten wir k3s ohne Konfigurationen und mit deaktivierten Komponenten installieren. Er beschreibt im Detail, welche Komponenten nicht installiert werden.

Terminal-Fenster
curl -sfL https://get.k3s.io | sh -s - \
--flannel-backend=none \
--disable-kube-proxy \
--disable servicelb \
--disable-network-policy \
--disable traefik \
--cluster-init

Nach der Installation sollten einige Pods laufen (3). Nicht schockiert sein, wenn die Pods im Status ContainerCreating oder Pending sind. Das liegt daran, dass die Pods nicht miteinander kommunizieren können, da wir das CNI deaktiviert haben (--flannel-backend=none). Später werden wir ciliumCilium installieren, welches das Flannel-CNI ersetzen wird.

Terminal-Fenster
kubectl get pods -A

Helm installieren

Helm ist der Paketmanager für kubernetesKubernetes. Sie können es entweder direkt installieren (siehe die Helm-Dokumentation) oder Teile von Helm verwenden, die mit Cilium ausgeliefert werden. Wir haben uns entschieden, Helm direkt zu installieren, was mit folgendem Befehl problemlos möglich ist:

Terminal-Fenster
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

Cilium installieren

ciliumCilium ist eine Netzwerk- und Sicherheitssoftware für Kubernetes. Cilium ist sehr schnell, skalierbar und sicher, da es auf eBPF basiert — einer revolutionären Technologie, die sandboxed Programme im Linux-Kernel ausführen kann, ohne den Kernel neu zu kompilieren oder Kernelmodule zu laden.

Wir könnten Cilium mit Helm wie hier gezeigt installieren:

Terminal-Fenster
helm repo add cilium https://helm.cilium.io/
helm repo update
helm install cilium cilium/cilium

Wir wollten es jedoch mit deren CLI installieren, und so funktioniert das. Zuerst installieren Sie die Cilium-CLI, indem Sie diesen Code-Schnipsel ausführen:

Terminal-Fenster
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz

Anschließend können Sie Cilium mit Ihrer Server-IP-Adresse installieren:

Terminal-Fenster
cilium install \
--set k8sServiceHost=${API_SERVER_IP} \
--set k8sServicePort=6443 \
--set kubeProxyReplacement=true

Jetzt warten wir, bis Cilium meldet, dass alles OK oder disabled ist:

Terminal-Fenster
cilium status --wait

Nach einer Weile sollten alle Pods im Status Running sein.

Terminal-Fenster
kubectl get pods -A

Zu guter Letzt können Sie einige Ressourcen für Cilium anwenden:

announce.yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumL2AnnouncementPolicy
metadata:
name: default-l2-announcement-policy
namespace: kube-system
spec:
externalIPs: true
loadBalancerIPs: true
ip-pool.yaml
apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
name: "first-pool"
spec:
blocks:
- start: "192.168.0.240"
stop: "192.168.0.249"

Außerdem sollten Sie die Cilium-Konfiguration aktualisieren. Um dies mit den richtigen Werten zu tun, erstellen Sie zunächst diese Datei im Root-Verzeichnis, in dem Sie das k3s-Cluster verwalten möchten. Später können Sie auch einige hubble- und prometheus-bezogene Eigenschaften hinzufügen, wenn Sie GrafanaGrafana oder Ähnliches verwenden möchten (öffnen Sie die ausgeblendeten Zeilen, wenn Sie unsere Konfiguration ebenfalls verwenden möchten).

cilium-config.yaml
k8sServiceHost: 127.0.0.1
k8sServicePort: 6443
kubeProxyReplacement: true
l2announcements:
enabled: true
externalIPs:
enabled: true
k8sClientRateLimit:
qps: 50
burst: 200
operator:
replicas: 1
rollOutPods: true
prometheus:
enabled: true
rollOutCiliumPods: true
ingressController:
enabled: true
default: true
loadbalancerMode: shared
service:
annotations:
io.cilium/lb-ipam-ips: 192.168.0.240
28 ausgeblendete Zeilen
hubble:
relay:
enabled: true
ui:
enabled: true
metrics:
serviceMonitor:
enabled: true
enableOpenMetrics: true
enabled:
- dns
- drop
- tcp
- icmp
- port-distribution
- "flow:sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity"
- "kafka:labelsContext=source_namespace,source_workload,destination_namespace,destination_workload,traffic_direction;sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity"
- "httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction;sourceContext=workload-name|reserved-identity;destinationContext=workload-name|reserved-identity"
dashboards:
enabled: true
namespace: monitoring
annotations:
grafana_folder: "Hubble"
prometheus:
enabled: true
serviceMonitor:
enabled: true

Führen Sie diesen Befehl aus, um ein Upgrade durchzuführen:

Terminal-Fenster
cilium upgrade -f cilium-config.yaml

Zertifikatsmanager mit Cloudflare einrichten

Um in der Lage zu sein, Zertifikate für jede Subdomain zu erstellen, ist es wichtig, einen Zertifikatsaussteller anzuwenden, der Zertifikatsanfragen bearbeitet und sie bei einem Anbieter einlöst. Wir haben cloudflareCloudflare als unseren Aussteller gewählt, und hier ist die Konfiguration, die Sie auf Ihr Kubernetes-Cluster anwenden müssen. Weitere Informationen finden Sie in der cert-manager-Dokumentation.

Zuerst müssen wir den cert-manager installieren, indem wir den folgenden Befehl ausführen:

Terminal-Fenster
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
cert-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: acme-issuer
namespace: cert-manager
spec:
acme:
email: <Email for updates>
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: acme-issuer
solvers:
- dns01:
cloudflare:
email: <Cloudflare account Email>
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token

Sie können eine Datei auf den kubernetesKubernetes-Cluster anwenden, indem Sie diesen k8s- (oder k3s-) Befehl ausführen:

Terminal-Fenster
kubectl apply -f cluster-issuer.yaml

Wenn Sie die Ressource im Kubernetes-Cluster löschen möchten, ist der Befehl ziemlich einfach:

Terminal-Fenster
kubectl delete -f cluster-issuer.yaml

Wie Sie oben vielleicht bemerkt haben, benötigen wir auch ein Geheimnis für das API-Token, das die Authentifizierung durchführt, dass dieser Issuer berechtigt ist, Zertifikate anzufordern. Daher erstellen wir ein Geheimnis mit einem unverschlüsselten API Token von Cloudflare.

Heutzutage erstellen wir ein Token, indem wir zu Ihrem cloudflareCloudflare-Dashboard gehen, dann auf Ihr Profil klicken und die Registerkarte API Tokens auswählen. Hier können Sie ein spezifisches Token für Ihren Issuer generieren oder den globalen API-Schlüssel (nicht mehr empfohlen) verwenden. Die empfohlene Lösung ist, ein API-Token mit zwei Berechtigungen (benutzerdefiniertes Token) zu erstellen:

  • Zone - DNS - Bearbeiten
  • Zone - Zone - Lesen

Cloudflare API-Token

Eine detailliertere Beschreibung der Tokens finden Sie in den Cloudflare-Dokumenten.

Nachdem Sie dieses Geheimnis auf Kubernetes angewendet haben, sollte der Issuer bereit sein, unangenehme Fälle zu lösen!

secret-cloudflare.yaml
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key-secret
namespace: cert-manager
type: Opaque
stringData:
api-key: <Cloudflare API Token (not encrypted)>

Sie können diesen Issuer jetzt verwenden, indem Sie diese Datei anwenden, die hoffentlich ein Zertifikat erstellt:

mutanuq-certificat.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: mutanuq
namespace: mutanuq
spec:
secretName: mutanuq
issuerRef:
name: acme-issuer
kind: ClusterIssuer
dnsNames:
- "mutanuq.trueberryless.org"

Normalerweise dauert es etwa 90 Sekunden, um die Anfrage nach dem Anwenden zu authentifizieren. Sie können den aktuellen Status der Anfrage überprüfen, indem Sie diesen Kubernetes-Befehl ausführen. Wenn es länger als 2 Minuten dauert, können möglicherweise einige Tipps unter #Fehlerbehebung hilfreich sein.

Terminal-Fenster
kubectl describe certificaterequests.cert-manager.io -n mutanuq

Beispielanwendung mutanuq

Dann können Sie dieses Zertifikat in Ihrem Ingress-Controller verwenden:

mutanuq.yaml
41 ausgeblendete Zeilen
apiVersion: apps/v1
kind: Deployment
metadata:
name: mutanuq
namespace: mutanuq
labels:
app: mutanuq
annotations:
keel.sh/policy: all
keel.sh/trigger: poll
keel.sh/pollSchedule: "@every 10s"
keel.sh/releaseNotes: "https://github.com/trueberryless-org/mutanuq/releases"
spec:
replicas: 3
selector:
matchLabels:
app: mutanuq
template:
metadata:
labels:
app: mutanuq
spec:
containers:
- name: mutanuq
image: trueberryless/mutanuq
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: mutanuq
namespace: mutanuq
annotations:
cert-manager.io/issuer: acme-issuer
spec:
selector:
app: mutanuq
ports:
- name: http
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mutanuq
namespace: mutanuq
spec:
rules:
- host: mutanuq.trueberryless.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mutanuq
port:
number: 80
tls:
- hosts:
- mutanuq.trueberryless.org
secretName: mutanuq

Einrichtung von Keel

Wir wollten schon immer eine saubere Continuous Integration (CI) und Continuous Delivery (CD) Lösung für unsere Websites. Das bedeutet, dass eine spezifische Commit-Nachricht einen automatisierten Prozess über githubGitHub, Docker Hub und unseren Server auslösen sollte, der am Ende die entsprechende Website nach etwa zwei Minuten aktualisiert.

Keel ist ein robustes Software-Tool, das diese Funktion für Kubernetes ermöglicht. Wir haben Keel verwendet, um neue Docker-Images von Docker Hub durch regelmäßige Abfragen zu holen. Außerdem bietet Keel ein schönes Dashboard, auf dem Sie die Abfragen steuern können.

Um Keel mit dem Administrations-Dashboard einzurichten, haben wir folgende Dateien erstellt:

  • secret-dashboard.yaml für den Admin-Benutzernamen und das Passwort (nicht jeder sollte auf das Dashboard zugreifen können)
  • keel.yaml für die eigentlichen k3s-Konfigurationen (kopiert und angepasst von KeelHQ)
secret-dashboard.yaml
apiVersion: v1
kind: Secret
metadata:
name: keel-dashboard-secrets
namespace: keel
type: Opaque
stringData:
username: <username>
password: <password>
keel.yaml
154 ausgeblendete Zeilen
---
apiVersion: v1
kind: Namespace
metadata:
name: keel
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: keel
namespace: keel
labels:
app: keel
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: keel
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- watch
- list
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- watch
- list
- apiGroups:
- ""
- extensions
- apps
- batch
resources:
- pods
- replicasets
- replicationcontrollers
- statefulsets
- deployments
- daemonsets
- jobs
- cronjobs
verbs:
- get
- delete # required to delete pods during force upgrade of the same tag
- watch
- list
- update
- apiGroups:
- ""
resources:
- configmaps
- pods/portforward
verbs:
- get
- create
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: keel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: keel
subjects:
- kind: ServiceAccount
name: keel
namespace: keel
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: keel
namespace: keel
spec:
rules:
- host: keel.trueberryless.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: keel
port:
number: 9300
tls:
- hosts:
- keel.trueberryless.org
secretName: keel
---
apiVersion: v1
kind: Service
metadata:
name: keel
namespace: keel
labels:
app: keel
spec:
type: LoadBalancer
ports:
- port: 9300
targetPort: 9300
protocol: TCP
name: keel
selector:
app: keel
sessionAffinity: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: keel
namespace: keel
labels:
app: keel
spec:
replicas: 1
selector:
matchLabels:
app: keel
template:
metadata:
labels:
app: keel
spec:
serviceAccountName: keel
containers:
- name: keel
# Note that we use appVersion to get images tag.
image: "keelhq/keel:latest"
imagePullPolicy: Always
command: ["/bin/keel"]
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
# Basic auth (to enable UI/API)
- name: BASIC_AUTH_USER
valueFrom:
secretKeyRef:
name: keel-dashboard-secrets
key: username
- name: BASIC_AUTH_PASSWORD
valueFrom:
secretKeyRef:
name: keel-dashboard-secrets
key: password
29 ausgeblendete Zeilen
ports:
- containerPort: 9300
livenessProbe:
httpGet:
path: /healthz
port: 9300
initialDelaySeconds: 30
timeoutSeconds: 10
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
---
# Source: keel/templates/pod-disruption-budget.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: keel
namespace: keel
spec:
maxUnavailable: 1
selector:
matchLabels:
app: keel

Nachdem beide Dateien angewendet und das zusätzliche Zertifikat für keel.trueberryless.org verwaltet wurden, funktioniert das Keel-Dashboard perfekt. Darüber hinaus kann jedes Kubernetes-Deployment für automatisiertes Docker-Hub-Polling durch Setzen einiger Annotationen aktiviert werden:

apiVersion: apps/v1
kind: Deployment
metadata:
name: mutanuq
namespace: mutanuq
labels:
app: mutanuq
annotations:
keel.sh/policy: all
keel.sh/trigger: poll
keel.sh/pollSchedule: "@every 1m"
keel.sh/releaseNotes: "https://github.com/trueberryless-org/mutanuq/releases"
spec:
replicas: 1
49 ausgeblendete Zeilen
selector:
matchLabels:
app: mutanuq
template:
metadata:
labels:
app: mutanuq
spec:
containers:
- name: mutanuq
image: trueberryless/mutanuq
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: mutanuq
namespace: mutanuq
annotations:
cert-manager.io/issuer: acme-issuer
spec:
selector:
app: mutanuq
ports:
- name: http
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mutanuq
namespace: mutanuq
spec:
rules:
- host: mutanuq.trueberryless.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mutanuq
port:
number: 80
tls:
- hosts:
- mutanuq.trueberryless.org
secretName: mutanuq

Feiern Sie mit einem Kaffee!

Herzlichen Glückwunsch, Sie haben erfolgreich kubernetesKubernetes mit ciliumCilium und cloudflareCloudflare eingerichtet! Sie haben sich eine Kaffeepause verdient. Genießen Sie eine wohlverdiente Tasse, und wenn Sie mit mir virtuell einen Kaffee teilen möchten, können Sie meine Arbeit gerne auf Ko-fi unterstützen. Vielen Dank!

Fehlerbehebung

Cilium-Ingress hat keine External-IP

Stellen Sie sicher, dass der ip-pool die in der Datei config.yaml angegebenen Adressen enthält.

ip-pool.yaml
apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
name: "first-pool"
spec:
blocks:
- start: "192.168.0.240" # 240 included for ingress
stop: "192.168.0.249"
cilium-config.yaml
ingressController:
enabled: true
default: true
loadbalancerMode: shared
service:
annotations:
io.cilium/lb-ipam-ips: 192.168.0.240 # this must be within range

Wenn Sie nicht lokal, sondern auf einer der Big Three bereitstellen, schauen Sie bitte in andere Dokumentationen nach, warum die External IP weiterhin ausstehend ist. Es liegt meistens in deren Verantwortung, Ihnen eine Adresse bereitzustellen.

Keine Cloudflare-Zertifikatsgenehmigung

Es kann Probleme geben, wenn das Zertifikat von Cloudflare nicht genehmigt wird.

Falsches API-Token

Stellen Sie zunächst sicher, dass das Cloudflare API-Token korrekt ist. Erstellen Sie zur hundertprozentigen Sicherheit ein neues und fügen Sie es (nicht Base64-codiert) in diese Datei ein:

apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key-secret
namespace: cert-manager
type: Opaque
stringData:
api-key: <Cloudflare API Token (not encrypted)>

Maximale Authentifizierungsfehler erreicht

Wir sind einmal auf den Fehler Error: 9109: Max auth failures reached, please check your Authorization header. gestoßen. Warten Sie einfach ein paar Stunden, löschen Sie die Ressource und wenden Sie sie erneut an:

Terminal-Fenster
kubectl delete -f certificate.yaml
kubectl apply -f certificate.yaml

Hoffentlich können Sie jetzt loslegen!