Einrichtung von Kubernetes mit Cilium und Cloudflare

Die Arbeit mit Docker-Containern kann schwierig sein. Es gibt jedoch Tools, die das Management von Containern verbessern, wie z.B.
Kubernetes. Tatsächlich ist Kubernetes das einzige mir bekannte Tool, das als Verwaltungssoftware für Docker-Container fungiert. Kubernetes ist in fast allen Cloud-Anbietern, wie Google Cloud, Azure und AWS, gut integriert. Dadurch bietet es eine standardisierte
yaml
-Syntax, die für kleine Entwickler großartig ist, da sie mit geringem Aufwand zwischen den Big Three
wechseln können.
Installieren Sie alles und wenden Sie dann den Cert-Manager an. Einfach.
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 updatehelm install cilium cilium/cilium
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)CLI_ARCH=amd64curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gzsudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/binrm 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
# secret-cloudflare.yamlapiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>---# cert-issuer.yamlapiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: acme-issuer namespace: cert-managerspec: 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
Wie Hagen in seinem Artikel erklärt, wollen wir k3s
ohne Konfigurationen und mit deaktivierten Komponenten installieren. Er beschreibt im Detail, welche Komponenten nicht installiert werden.
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). Erschrecken Sie nicht, wenn sich die Pods im Zustand ContainerCreating
oder Pending
befinden. Dies liegt daran, dass die Pods nicht miteinander kommunizieren können, da wir das CNI (--flannel-backend=none
) deaktiviert haben. Später werden wir Cilium installieren, das das Flannel-CNI ersetzen wird.
kubectl get pods -A
Helm ist der Paketmanager für Kubernetes, daher sollten Sie es entweder direkt installieren (folgen Sie den Helm-Dokumentationen) oder Teile von Helm verwenden, die mit Cilium geliefert werden. Wir haben uns entschieden, Helm direkt zu installieren, was mit diesem Befehl problemlos möglich ist:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Cilium ist eine Netzwerk- und Sicherheitssoftware für Kubernetes. Cilium ist sehr schnell, skalierbar und sicher, da es auf eBPF basiert — eine revolutionäre Technologie, die sandboxed Programme im Linux-Kernel ausführen kann, ohne den Kernel neu zu kompilieren oder Kernel-Module zu laden.
Wir könnten Cilium mit Helm wie hier gezeigt installieren:
helm repo add cilium https://helm.cilium.io/helm repo updatehelm install cilium cilium/cilium
Wir wollten jedoch die Installation mit ihrem CLI durchführen, und so geht es. Installieren Sie zunächst das Cilium-CLI, indem Sie diesen Code-Schnipsel ausführen:
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)CLI_ARCH=amd64curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gzsudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/binrm cilium-linux-${CLI_ARCH}.tar.gz
Dann können Sie Cilium mit Ihrer Server-IP-Adresse installieren:
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:
cilium status --wait
Nach einer Weile sollten alle Pods den Status Running
haben.
kubectl get pods -A
Zu guter Letzt können Sie einige Ressourcen für Cilium anwenden:
apiVersion: cilium.io/v2alpha1kind: CiliumL2AnnouncementPolicymetadata: name: default-l2-announcement-policy namespace: kube-systemspec: externalIPs: true loadBalancerIPs: true
apiVersion: "cilium.io/v2alpha1"kind: CiliumLoadBalancerIPPoolmetadata: 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 den k3s-Cluster verwalten möchten. Später könnten Sie auch einige hubble- und prometheus-bezogene Eigenschaften anwenden, wenn Sie Grafana oder ähnliches verwenden wollen (öffnen Sie die ausgeblendeten Zeilen, wenn Sie unsere Konfiguration ebenfalls verwenden möchten).
k8sServiceHost: 127.0.0.1k8sServicePort: 6443
kubeProxyReplacement: truel2announcements: 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:
cilium upgrade -f cilium-config.yaml
Um Zertifikate für jede Subdomain erstellen zu können, ist es wichtig, einen Zertifikatsanbieter anzuwenden, der Zertifikatsanfragen bearbeitet und diese bei einem Anbieter auflöst. Wir haben Cloudflare als unseren Anbieter gewählt, und hier ist die Konfiguration, die Sie auf Ihren Kubernetes-Cluster anwenden müssen. Weitere Informationen finden Sie in den Dokumentationen zum Cert-Manager.
Aber zuerst müssen wir den cert-manager installieren, indem wir den folgenden Befehl ausführen:
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: acme-issuer namespace: cert-managerspec: 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 Kubernetes-Cluster anwenden, indem Sie diesen k8s- (oder k3s-)Befehl ausführen:
kubectl apply -f cluster-issuer.yaml
Wenn Sie die Ressource im Kubernetes-Cluster löschen möchten, ist der Befehl ziemlich einfach:
kubectl delete -f cluster-issuer.yaml
Wie Sie oben vielleicht bemerkt haben, benötigen wir auch ein Geheimnis für das API-Token, das authentifiziert, dass dieser Aussteller berechtigt ist, Zertifikate anzufordern. Daher erstellen wir ein Geheimnis mit einem unverschlüsselten API Token
von Cloudflare.
Heutzutage erstellen wir ein Token, indem wir zum Cloudflare-Dashboard gehen, dann auf Ihr Profil klicken und die Registerkarte
API Tokens
auswählen. Hier können Sie ein spezifisches Token für Ihren Aussteller generieren oder den globalen API-Schlüssel verwenden (nicht mehr empfohlen). Die empfohlene Lösung ist, ein API-Token mit zwei Berechtigungen (benutzerdefiniertes Token) zu erstellen:
- Zone - DNS - Bearbeiten
- Zone - Zone - Lesen
Eine detailliertere Beschreibung der Tokens finden Sie in den Cloudflare-Dokumenten.
Nach der Anwendung dieses Geheimnisses auf Kubernetes sollte der Aussteller bereit sein, ein paar unerwünschte Anfragen zu lösen!
apiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>
Sie können diesen Aussteller nun verwenden, indem Sie diese Datei anwenden, die hoffentlich ein Zertifikat erstellt:
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: mutanuq namespace: mutanuqspec: secretName: mutanuq issuerRef: name: acme-issuer kind: ClusterIssuer dnsNames: - "mutanuq.trueberryless.org"
In der Regel dauert es etwa 90 Sekunden, bis der Antrag nach der Anwendung authentifiziert ist. Sie können den aktuellen Status der Anfrage überprüfen, indem Sie diesen Kubernetes-Befehl ausführen. Falls es länger als 2 Minuten dauert, können möglicherweise einige Tipps unter #Fehlerbehebung helfen.
kubectl describe certificaterequests.cert-manager.io -n mutanuq
Die Option -n
steht für Namespace.
Beispiel-Anwendung mutanuq
Dann können Sie dieses Zertifikat in Ihrem Ingress-Controller verwenden:
41 ausgeblendete Zeilen
apiVersion: apps/v1kind: Deploymentmetadata: 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: v1kind: Servicemetadata: name: mutanuq namespace: mutanuq annotations: cert-manager.io/issuer: acme-issuerspec: selector: app: mutanuq ports: - name: http port: 80---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: mutanuq namespace: mutanuqspec: rules: - host: mutanuq.trueberryless.org http: paths: - path: / pathType: Prefix backend: service: name: mutanuq port: number: 80
tls: - hosts: - mutanuq.trueberryless.org secretName: mutanuq
Wir wollten schon immer eine saubere Continuous Integration (CI)- und Continuous Delivery (CD)-Lösung für unsere Websites. Das bedeutet, dass eine bestimmte Commit-Nachricht einen automatisierten Prozess über GitHub, 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 abzufragen und diese alle paar Minuten zu aktualisieren. Außerdem bietet Keel ein schönes Dashboard, mit dem Sie die Abfragen steuern können.
Um Keel mit dem Admin-Dashboard einzurichten, haben wir diese Dateien erstellt:
secret-dashboard.yaml
für den Admin-Benutzernamen und das Passwort (nicht jeder sollte Zugriff auf das Dashboard haben)keel.yaml
für die eigentlichen k3s-Konfigurationen (kopiert und angepasst von KeelHQ)
apiVersion: v1kind: Secretmetadata: name: keel-dashboard-secrets namespace: keeltype: OpaquestringData: username: <username> password: <password>
154 ausgeblendete Zeilen
---apiVersion: v1kind: Namespacemetadata: name: keel
---apiVersion: v1kind: ServiceAccountmetadata: name: keel namespace: keel labels: app: keel
---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: keelrules: - 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/v1kind: ClusterRoleBindingmetadata: name: keelroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: keelsubjects: - kind: ServiceAccount name: keel namespace: keel
---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: keel namespace: keelspec: 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: v1kind: Servicemetadata: name: keel namespace: keel labels: app: keelspec: type: LoadBalancer ports: - port: 9300 targetPort: 9300 protocol: TCP name: keel selector: app: keel sessionAffinity: None
---apiVersion: apps/v1kind: Deploymentmetadata: name: keel namespace: keel labels: app: keelspec: 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: password29 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/v1kind: PodDisruptionBudgetmetadata: name: keel namespace: keelspec: maxUnavailable: 1 selector: matchLabels: app: keel
Nach der Anwendung beider Dateien und der Verwaltung des zusätzlichen Zertifikats für keel.trueberryless.org
funktioniert das Keel-Dashboard perfekt. Außerdem kann jede Kubernetes Deployment
-Ressource durch Setzen einiger Annotationen für automatisiertes Docker-Hub-Polling aktiviert werden:
apiVersion: apps/v1kind: Deploymentmetadata: 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: 149 ausgeblendete Zeilen
selector: matchLabels: app: mutanuq template: metadata: labels: app: mutanuq spec: containers: - name: mutanuq image: trueberryless/mutanuq imagePullPolicy: Always---apiVersion: v1kind: Servicemetadata: name: mutanuq namespace: mutanuq annotations: cert-manager.io/issuer: acme-issuerspec: selector: app: mutanuq ports: - name: http port: 80---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: mutanuq namespace: mutanuqspec: rules: - host: mutanuq.trueberryless.org http: paths: - path: / pathType: Prefix backend: service: name: mutanuq port: number: 80
tls: - hosts: - mutanuq.trueberryless.org secretName: mutanuq
Herzlichen Glückwunsch, Sie haben erfolgreich Kubernetes mit
Cilium und
Cloudflare eingerichtet! Sie haben sich eine Kaffeepause verdient. Genießen Sie eine wohlverdiente Tasse, und wenn Sie gerne einen virtuellen Kaffee mit mir teilen möchten, unterstützen Sie mich gerne auf Ko-fi. Vielen Dank!
Stellen Sie sicher, dass der ip-pool
die Adresse enthält, die in den Anmerkungen der Datei config.yaml
angegeben ist.
apiVersion: "cilium.io/v2alpha1"kind: CiliumLoadBalancerIPPoolmetadata: name: "first-pool"spec: blocks: - start: "192.168.0.240" # 240 included for ingress stop: "192.168.0.249"
ingressController: enabled: true default: true loadbalancerMode: shared service: annotations: io.cilium/lb-ipam-ips: 192.168.0.240 # this must be within range
In einigen Fällen erhalten andere Ingress-Controller die annotierte Adresse, bevor der Cilium-IC darauf zugreifen kann, sodass sie weiterhin im Wartezustand bleibt…
Wenn Sie nicht lokal, sondern auf einer der “Großen Drei” bereitstellen, prüfen Sie bitte andere Dokumentationen, warum die External-IP noch aussteht. Es ist hauptsächlich deren Verpflichtung, Ihnen eine Adresse bereitzustellen.
Es kann ein Problem auftreten, wenn das Zertifikat von Cloudflare nicht genehmigt wird.
Stellen Sie zunächst sicher, dass der Cloudflare-API-Token korrekt ist. Um 100-prozentige Sicherheit zu haben, erstellen Sie einen neuen und legen Sie ihn (nicht Base64-kodiert) in dieser Datei ab:
apiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>
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:
kubectl delete -f certificate.yamlkubectl apply -f certificate.yaml
Hoffentlich ist jetzt alles in Ordnung!