Mise en place de Kubernetes avec Cilium et Cloudflare
Cette traduction a été générée par une IA générative à l'aide de la traduction continue Action. →

Travailler avec les conteneurs Docker peut être difficile. Cependant, il existe des outils qui facilitent la gestion des conteneurs, comme
Kubernetes. En fait, Kubernetes est le seul outil, à ma connaissance, qui agit comme un logiciel de gestion pour les conteneurs Docker. Kubernetes est bien intégré dans presque tous les fournisseurs de cloud, comme Google Cloud, Azure et AWS. Par conséquent, il utilise une syntaxe standardisée en
yaml
, ce qui est idéal pour les petits développeurs, car ils peuvent basculer entre « Les Trois Grands » avec peu d’effort.
Installez tout, puis appliquez cert-manager. Facile.
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
Comme Hagen l’explique dans son article, nous voulons installer k3s
sans configurations et avec tout désactivé. Il décrit en détail quels composants ne sont pas installés.
curl -sfL https://get.k3s.io | sh -s - \ --flannel-backend=none \ --disable-kube-proxy \ --disable servicelb \ --disable-network-policy \ --disable traefik \ --cluster-init
Après l’installation, quelques pods devraient être en cours d’exécution (3). Ne soyez pas choqués si les pods sont dans l’état ContainerCreating
ou Pending
. Cela est dû au fait que les pods ne peuvent pas communiquer entre eux parce que nous avons désactivé le CNI (--flannel-backend=none
). Nous installerons plus tard Cilium, qui remplacera le CNI Flannel.
kubectl get pods -A
Helm est le gestionnaire de packages pour Kubernetes, vous pouvez soit l’installer directement (suivez la documentation Helm), soit utiliser les composants d’Helm inclus avec Cilium. Nous avons choisi d’installer Helm directement, ce qui est facilement faisable avec cette commande :
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Cilium est un logiciel de mise en réseau et de sécurité pour Kubernetes. Cilium est très rapide, évolutif et sécurisé car il repose sur eBPF - une technologie révolutionnaire qui peut exécuter des programmes isolés dans le noyau Linux sans recompiler le noyau ou charger des modules noyau.
Nous pourrions installer Cilium avec Helm comme indiqué ici :
helm repo add cilium https://helm.cilium.io/helm repo updatehelm install cilium cilium/cilium
Cependant, nous avons voulu l’installer avec leur CLI, et voici comment vous pouvez le faire. Tout d’abord, installez la CLI de Cilium en exécutant ce script :
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
Ensuite, vous pouvez installer Cilium avec l’adresse IP de votre serveur :
cilium install \ --set k8sServiceHost=${API_SERVER_IP} \ --set k8sServicePort=6443 \ --set kubeProxyReplacement=true
Nous attendons maintenant que Cilium indique que tout est OK
ou disabled
:
cilium status --wait
Au bout d’un moment, tous les pods devraient être en état Running
.
kubectl get pods -A
Enfin, vous pouvez appliquer certaines ressources pour Cilium :
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"
De plus, vous devriez mettre à jour la configuration de Cilium. Pour cela, créez d’abord ce fichier dans le répertoire racine où vous souhaitez gérer le cluster k3s. Plus tard, vous pourrez également appliquer des propriétés liées à Hubble et Prometheus si vous souhaitez utiliser Grafana ou un outil similaire (ouvrez les lignes repliées si vous souhaitez utiliser notre configuration également).
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 collapsed lines
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
Exécutez cette commande pour mettre à jour :
cilium upgrade -f cilium-config.yaml
Pour pouvoir créer des certificats pour chaque sous-domaine, il est important d’appliquer un émetteur de certificats qui gère les demandes de certificats et les résout auprès d’un fournisseur. Nous avons choisi Cloudflare comme notre émetteur, et voici la configuration que vous devez appliquer à votre cluster Kubernetes. Pour plus d’informations, vous pouvez consulter la documentation de cert-manager.
Mais d’abord, nous devons installer le cert-manager en exécutant la commande suivante :
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
Vous pouvez appliquer un fichier au cluster Kubernetes en exécutant cette commande k8s (également k3s) :
kubectl apply -f cluster-issuer.yaml
Si vous souhaitez supprimer la ressource dans le cluster Kubernetes, la commande est assez simple :
kubectl delete -f cluster-issuer.yaml
Comme vous l’avez peut-être remarqué ci-dessus, nous avons également besoin d’un secret pour le jeton API qui authentifie que ce générateur est autorisé à demander des certificats. Par conséquent, nous créons un secret avec un API Token
non chiffré de Cloudflare.
De nos jours, nous créons un jeton en accédant à votre tableau de bord Cloudflare, puis en cliquant sur votre profil et en sélectionnant l’onglet
API Tokens
. Ici, vous pouvez générer un jeton spécifique pour votre générateur ou utiliser la clé API globale (non recommandée). La solution recommandée est de créer un jeton API avec deux permissions (jeton personnalisé) :
- Zone - DNS - Modifier
- Zone - Zone - Lecture
Une description plus détaillée des jetons peut être trouvée dans les docs Cloudflare.
Après avoir appliqué ce secret à Kubernetes, le générateur devrait être prêt à résoudre quelques vilains problèmes !
apiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>
Vous pouvez maintenant utiliser ce générateur en appliquant ce fichier qui, espérons-le, créera un certificat :
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: mutanuq namespace: mutanuqspec: secretName: mutanuq issuerRef: name: acme-issuer kind: ClusterIssuer dnsNames: - "mutanuq.trueberryless.org"
Cela prend généralement environ 90 secondes pour authentifier la demande une fois appliquée. Vous pouvez vérifier l’état actuel de la demande en exécutant cette commande kubernetes. Si cela prend plus de 2 minutes, peut-être que quelques astuces dans #Dépannage peuvent vous aider.
kubectl describe certificaterequests.cert-manager.io -n mutanuq
L’option -n
signifie namespace.
Exemple d’application mutanuq
Ensuite, vous pouvez utiliser ce certificat dans votre contrôleur Ingress :
41 collapsed lines
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
Nous avons toujours voulu une solution propre d’Intégration Continue (CI) et de Livraison Continue (CD) pour nos sites web. Cela signifie qu’un message de commit spécifique devrait déclencher un processus automatisé via GitHub, Docker Hub et notre serveur, qui, à la fin, met à jour le site web correspondant en environ deux minutes.
Keel est un outil logiciel robuste qui permet cette fonctionnalité pour Kubernetes. Nous avons utilisé Keel pour tirer de nouvelles images Docker de Docker Hub en interrogeant toutes les quelques minutes. De plus, Keel fournit un magnifique tableau de bord où vous pouvez contrôler l’interrogation également.
Pour configurer Keel avec le tableau de bord d’administration, nous avons créé ces fichiers :
secret-dashboard.yaml
pour le nom d’utilisateur et le mot de passe administrateur (tout le monde ne devrait pas pouvoir accéder au tableau de bord)keel.yaml
pour les configurations réelles de k3s (copié et adapté de KeelHQ)
apiVersion: v1kind: Secretmetadata: name: keel-dashboard-secrets namespace: keeltype: OpaquestringData: username: <username> password: <password>
154 collapsed lines
---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 collapsed lines
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
Après avoir appliqué les deux fichiers et géré le certificat supplémentaire pour keel.trueberryless.org
, le tableau de bord Keel fonctionne parfaitement. De plus, chaque Deployment
Kubernetes peut opter pour un sondage Docker Hub automatisé en ajoutant quelques annotations :
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 collapsed lines
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
Félicitations, vous avez réussi à configurer Kubernetes avec
Cilium et
Cloudflare ! Vous méritez une pause café. Profitez d’une tasse bien méritée, et si vous souhaitez partager un café virtuel avec moi, n’hésitez pas à soutenir mon travail sur Ko-fi. Merci !
Assurez-vous que le ip-pool
inclut l’adresse spécifiée par les annotations dans le fichier config.yaml
.
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
Dans certains cas, d’autres contrôleurs d’entrée obtiennent l’adresse annotée avant que le contrôleur d’entrée de Cilium puisse y accéder, donc elle resterait en attente…
Si vous ne déployez pas localement mais sur l’une des Big Three
, veuillez consulter d’autres documentations sur les raisons pour lesquelles l’IP externe reste en attente. Il est principalement de leur responsabilité de vous fournir une adresse.
Il peut y avoir un problème lorsque le certificat ne reçoit pas l’approbation de Cloudflare.
Tout d’abord, assurez-vous que le jeton API Cloudflare est correct. Pour être sûr à 100 %, créez-en un nouveau et insérez-le (non encodé en base64) dans ce fichier :
apiVersion: v1kind: Secretmetadata: name: cloudflare-api-key-secret namespace: cert-managertype: OpaquestringData: api-key: <Cloudflare API Token (not encrypted)>
Nous avons rencontré une fois l’erreur Error: 9109: Max auth failures reached, please check your Authorization header.
. Il suffit d’attendre quelques heures, de supprimer la ressource et de l’appliquer à nouveau :
kubectl delete -f certificate.yamlkubectl apply -f certificate.yaml
Espérons que tout fonctionne maintenant !