Einrichten 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
Kubernetes. 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.
Alles installieren und dann cert-manager anwenden. Ganz 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, möchten 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). 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 Cilium installieren, welches das Flannel-CNI ersetzen wird.
kubectl get pods -A
Helm ist der Paketmanager für Kubernetes. 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:
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 — 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:
helm repo add cilium https://helm.cilium.io/helm repo updatehelm 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:
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
Anschließend 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 im Status Running
sein.
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 das k3s-Cluster verwalten möchten. Später können Sie auch einige hubble- und prometheus-bezogene Eigenschaften hinzufügen, wenn Sie Grafana oder Ähnliches verwenden möchten (ö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 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 Cloudflare 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:
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 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 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 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
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!
apiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>
Sie können diesen Issuer jetzt 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"
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.
kubectl describe certificaterequests.cert-manager.io -n mutanuq
Die Option -n
steht für Namespace.
Beispielanwendung 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 spezifische 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 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)
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
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/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 mit mir virtuell einen Kaffee teilen möchten, können Sie meine Arbeit gerne auf Ko-fi unterstützen. Vielen Dank!
Stellen Sie sicher, dass der ip-pool
die in der Datei config.yaml
angegebenen Adressen enthält.
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 nehmen andere Ingress-Controller die annotierte Adresse, bevor der Cilium IC darauf zugreifen kann, sodass sie weiterhin ausstehend ist…
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.
Es kann Probleme geben, wenn das Zertifikat von Cloudflare nicht genehmigt wird.
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: 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 können Sie jetzt loslegen!