1. But
On souhaite pouvoir créer des clusters Kubernetes à la demande, en les mutualisant sur une infrastructure unique afin de réduire les coûts. On veut pouvoir gérer et fournir des environnements multiples dans un cadre sécurisé bien isolé et contrôlé.
2. Composants utilisés
-
Cluster Kubernetes Hôte, il faudra avoir un cluster suffisamment puissant pour offrir un service efficace. Utilisez des environnements fournissant de l'autoscaling au niveau des nœuds de compute. Dans mon billet de blog je vais utiliser un kuberneets en service managé sur Azure (AKS).
-
Un ingress controller déployé sur votre cluster kubernetes
-
Un certificate manager déployé et configuré si vous souhaitez exposer les vcluster et leur api en https
-
Pour la partie "virtualisation" de cluster sur un cluster existant, nous allons utiliser vcluster. Vous pouvez consulter le billet de blog sur la solution vcluster
-
Pour la partie création des clusters en mode cloud-native et declaratif, nous allons utiliser la cluster-api car elle propose un support de vcluster. Vous pouvez trouver toutes les informations sur cette solution ici (https://cluster-api.sigs.k8s.io/) et plus précisément ici (https://cluster-api.sigs.k8s.io/user/quick-start.html)
3. Installation des composants
3.1 Ingress Controller
Toute la documentation est ici : (https://kubernetes.github.io/ingress-nginx/deploy/)
# Spécifiquement pour aure nous avons besoin d'une annotation
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--version 4.6.1 \
--create-namespace \
--namespace ingress-nginx \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.extraArgs.enable-ssl-passthrough=
Note : j'ai pris la version 4.6.1 car il y actuellement (4.8.3) un problème avec le ssl-passthrough qui bug
3.2 Cert-Manager
3.2.1 Déploiement
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Version est mise mais vous pouvez utiliser la latest, la premiere fois utilisez le flag installCRDs=true
helm upgradec --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.12.0 \
--set installCRDs=true
3.2.2 Configuration
Je vais utiliser letsencrypt et ce en mode ClusterIssuer
Par exemple
Le domaine de référence sera "*.caas.fr"
cat <<EOF | kubectl apply --filename -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: herve.leclerc@alterway.fr
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
EOF
❯ k get clusterissuer
NAME READY AGE
letsencrypt True 8h
3.3. Installation de la CLI pour la cluster-api : clusterctl
Vous avez dans la page du quick-start toutes les informations pour installer cette CLI sur différents OS manuellement ou avec des gestionnaire de package (homebrew)
Une fois la CLI installée le programme clusterctl
est disponible
exemple
❯ clusterctl version -o short
v1.5.3
Il faudra initialiser le contrôleur de la capi pour vcluster
❯ clusterctl init --infrastructure vcluster
Fetching providers
Skipping installing cert-manager as it is already installed
Installing Provider="cluster-api" Version="v1.5.3" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v1.5.3" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v1.5.3" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-vcluster" Version="v0.1.3" TargetNamespace="cluster-api-provider-vcluster-system"
Your management cluster has been initialized successfully!
You can now create your first workload cluster by running the following:
clusterctl generate cluster [name] --kubernetes-version [version] | kubectl apply -f -
3.4 Création de l'environnement de management dans notre cluster
3.4.2 Préparation - Test unitaire
Avant de créer des template utilisables pour automatiser et industrialiser notre usine à cluster nous allons faire un déploiement de manière unitaire pour vérifier que tout est ok
- Créer si besoin un fichier values pour la variable d'environnement HELM_VALUES
ex: "
syncer:
extraArgs:
- --tls-san=${CLUSTER_NAME}.${CLUSTER_DOMAIN}
- --out-kube-config-server=https://${CLUSTER_NAME}.${CLUSTER_DOMAIN}
ingress:
enabled: true
pathType: ImplementationSpecific
ingressClassName: nginx
host: ${CLUSTER_NAME}.${CLUSTER_DOMAIN}
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/ssl-passthrough: 'true'
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
cert-manager.io/cluster-issuer: letsencrypt
tls:
- secretName: ${CLUSTER_NAME}.${CLUSTER_DOMAIN}-tls
hosts:
- ${CLUSTER_NAME}.${CLUSTER_DOMAIN}
Vous pouvez éditer le fichier pour enlever les \n et les remplacer par \n (dans vi :%s/\n/\\n/g
)
Copier coller la ligne pour la mettre dans la variable d'environnement
- Créer un fichier d'environnement que vous pourrez utiliser en utilisant la commande
source
# file env.sh
# On active cette Feature
export CLUSTER_TOPOLOGY=true
# Pour configurer la cluster api pour générer des Vcluster (https://github.com/loft-sh/cluster-api-provider-vcluster/blob/main/docs/quick-start.md)
export CLUSTER_NAME=dev0
export CLUSTER_NAMESPACE=dev0-ns
export KUBERNETES_VERSION="1.27.6"
export CLUSTER_DOMAIN=caas.fr
export HELM_VALUES=$(cat n2n.yaml| envsubst | sed -z 's/\n/\\n/g')
# ou ...
#export HELM_VALUES="syncer:\n extraArgs:\n - --tls-san=${CLUSTER_NAME}.${CLUSTER_DOMAIN}\n - --out-kube-config-server=https://${CLUSTER_NAME}.${CLUSTER_DOMAIN}\ningress:\n enabled: true\n pathType: ImplementationSpecific\n ingressClassName: nginx\n host: ${CLUSTER_NAME}.${CLUSTER_DOMAIN}\n annotations:\n nginx.ingress.kubernetes.io/backend-protocol: HTTPS\n nginx.ingress.kubernetes.io/ssl-passthrough: 'true'\n nginx.ingress.kubernetes.io/ssl-redirect: 'true'\n cert-manager.io/cluster-issuer: letsencrypt\n tls:\n - secretName: ${CLUSTER_NAME}.${CLUSTER_DOMAIN}-tls\n hosts:\n - ${CLUSTER_NAME}.${CLUSTER_DOMAIN}"
Vérifiez que la structure de la variable HELM_VALUES est ok echo ${HELM_VALUES}
3.4.2 génération du template de création du cluster
On ne va pas générer directement le cluster mais préparer un template pouvant être "kustomisé" par la suite
source env.sh
clusterctl generate cluster ${CLUSTER_NAME} \
--infrastructure vcluster \
--kubernetes-version ${KUBERNETES_VERSION} \
--target-namespace ${CLUSTER_NAMESPACE} > ${CLUSTER_NAME}.yaml
Affichage des Custom resources créées
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: dev0
namespace: dev0-ns
spec:
controlPlaneRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: VCluster
name: dev0
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: VCluster
name: dev0
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: VCluster
metadata:
name: dev0
namespace: dev0-ns
spec:
controlPlaneEndpoint:
host: ""
port: 0
helmRelease:
chart:
name: null
repo: null
version: null
values: |
syncer:
extraArgs:
- --tls-san=dev0.vclusters.caas.fr
- --out-kube-config-server=https://dev0.vclusters.caas.fr
ingress:
enabled: true
pathType: ImplementationSpecific
ingressClassName: nginx
host: dev0.vclusters.caas.fr
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/ssl-passthrough: 'true'
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
cert-manager.io/cluster-issuer: letsencrypt
tls:
- secretName: dev0.vclusters.caas.fr-tls
hosts:
- dev0.vclusters.caas.fr
kubernetesVersion: 1.27.4
Si vous souhaitez déployer une autre distribution que k3s
par défaut il faudra modifier le bloc
helmRelease:
chart:
name: null
repo: null
version: null
avec les bonnes valeurs
Par exemple pour déployer un k8s vanilla
helmRelease:
chart:
name: vcluster-k8s
repo: https://charts.loft.sh
version: null
3.4.3 Test de création du cluster
Simplement appliquez le manifeste généré
❯ kubectl apply -f dev0.yaml
cluster.cluster.x-k8s.io/dev0 created
vcluster.infrastructure.cluster.x-k8s.io/dev0 created
# vérification
❯ kubectl get cluster -n ${CLUSTER_NAMESPACE}
NAME PHASE AGE VERSION
dev0 Provisioning 63s
❯ kubectl get cluster -n ${CLUSTER_NAMESPACE}
NAME PHASE AGE VERSION
dev0 Provisioned 1m
Si vous avez installé la CLI de vcluster vous pouvez aussi le cluster
❯ vcluster list
NAME | CLUSTER | NAMESPACE | STATUS | VERSION | CONNECTED | CREATED | AGE | DISTRO
-------+---------------+-----------+---------+---------+-----------+-------------------------------+-------+---------
dev0 | k8s-ims-admin | dev0-ns | Running | 0.11.1 | | 2023-11-29 14:54:39 +0100 CET | 14m2s | OSS
3.4.4 Récupération du kubeconfig
Le kubeconfig du cluster se trouve dans un secrets ayant comme règle de nommage vc-[nom du cluster]
❯ kubectl get secret vc-$CLUSTER_NAME -n $CLUSTER_NAMESPACE --template={{.data.config}} | base64 -d > kubeconfig.yaml
3.4.5 Tests de requêtes sur l'api
❯ KUBECONFIG=./kubeconfig.yaml k get nodes
NAME STATUS ROLES AGE VERSION
aks-sys-17083323-vmss00001c Ready <none> 18m v1.24.1+k3s1
❯ KUBECONFIG=./kubeconfig.yaml k get ns
NAME STATUS AGE
kube-system Active 19m
default Active 19m
kube-public Active 19m
kube-node-lease Active 19m
❯ KUBECONFIG=./kubeconfig.yaml k create deploy test --image=nginx -n default
deployment.apps/test created
❯ KUBECONFIG=./kubeconfig.yaml k get po
NAME READY STATUS RESTARTS AGE
test-764c85dd84-pgmz7 1/1 Running 0 24s
❯ KUBECONFIG=./kubeconfig.yaml k expose deploy test --port 80 -n default
service/test exposed
❯ KUBECONFIG=./kubeconfig.yaml k port-forward -n default svc/test 9000:80
Forwarding from 127.0.0.1:9000 -> 80
Forwarding from [::1]:9000 -> 80
❯ curl localhost:9000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
....
Tout fonctionne parfaitement, nous avons le socle pour créer notre usine à cluster !
Suite à la partie 2
Découvrez les derniers articles d'alter way
- Big Data & AI Paris 2024 : L'IA au cœur de toutes les transformations.
- Un retour vers l'open-source ? Vos outils DevOps préférés et leurs equivalents open-source.
- Prowler : L'outil de sécurité multi-cloud indispensable pour renforcer votre infrastructure
- Kubernetes : plateforme "star" de l'IT et levier d'innovation des entreprises
- AI_dev2024
- : DirectPV : Avoir du stockage bloc distribué facilement dans kubernetes