Aller au contenu
A beautiful cover image with the text "Kubernetes"

Travailler avec les conteneurs dockerDocker peut être difficile. Cependant, il existe des outils qui facilitent la gestion des conteneurs, comme kubernetesKubernetes. 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.

résumé

Installez tout, puis appliquez cert-manager. Facile.

Fenêtre de terminal
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

Installer k3s

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.

Fenêtre de terminal
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 ciliumCilium, qui remplacera le CNI Flannel.

Fenêtre de terminal
kubectl get pods -A

Installer Helm

Helm est le gestionnaire de packages pour kubernetesKubernetes, 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 :

Fenêtre de terminal
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

Installer Cilium

ciliumCilium 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 :

Fenêtre de terminal
helm repo add cilium https://helm.cilium.io/
helm repo update
helm 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 :

Fenêtre de terminal
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

Ensuite, vous pouvez installer Cilium avec l’adresse IP de votre serveur :

Fenêtre de terminal
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 :

Fenêtre de terminal
cilium status --wait

Au bout d’un moment, tous les pods devraient être en état Running.

Fenêtre de terminal
kubectl get pods -A

Enfin, vous pouvez appliquer certaines ressources pour Cilium :

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"

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 GrafanaGrafana ou un outil similaire (ouvrez les lignes repliées si vous souhaitez utiliser notre configuration également).

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 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 :

Fenêtre de terminal
cilium upgrade -f cilium-config.yaml

Configurer le gestionnaire de certificats avec Cloudflare

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 cloudflareCloudflare 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 :

Fenêtre de terminal
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

Vous pouvez appliquer un fichier au cluster kubernetesKubernetes en exécutant cette commande k8s (également k3s) :

Fenêtre de terminal
kubectl apply -f cluster-issuer.yaml

Si vous souhaitez supprimer la ressource dans le cluster Kubernetes, la commande est assez simple :

Fenêtre de terminal
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 cloudflareCloudflare, 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

Jeton API Cloudflare

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 !

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)>

Vous pouvez maintenant utiliser ce générateur en appliquant ce fichier qui, espérons-le, créera un certificat :

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"

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.

Fenêtre de terminal
kubectl describe certificaterequests.cert-manager.io -n mutanuq

Exemple d’application mutanuq

Ensuite, vous pouvez utiliser ce certificat dans votre contrôleur Ingress :

mutanuq.yaml
41 collapsed lines
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

Configurer Keel

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 githubGitHub, 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)
secret-dashboard.yaml
apiVersion: v1
kind: Secret
metadata:
name: keel-dashboard-secrets
namespace: keel
type: Opaque
stringData:
username: <username>
password: <password>
keel.yaml
154 collapsed lines
---
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 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/v1
kind: PodDisruptionBudget
metadata:
name: keel
namespace: keel
spec:
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/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 collapsed lines
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

Célébrez avec un café !

Félicitations, vous avez réussi à configurer kubernetesKubernetes avec ciliumCilium et cloudflareCloudflare ! 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 !

Dépannage

Cilium-ingress n’a pas d’External-IP

Assurez-vous que le ip-pool inclut l’adresse spécifiée par les annotations dans le fichier config.yaml.

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

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.

Pas d’approbation de certificat Cloudflare

Il peut y avoir un problème lorsque le certificat ne reçoit pas l’approbation de Cloudflare.

Jeton API incorrect

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

Maximum d’échecs d’authentification atteint

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 :

Fenêtre de terminal
kubectl delete -f certificate.yaml
kubectl apply -f certificate.yaml

Espérons que tout fonctionne maintenant !