Dans cet article, nous allons voir comment installer un cluster Kubernetes sur un ou plusieurs noeuds “physiques”. On est sur de l’auto-hébergement. MetalLB sera utilisé pour remplacer les load balancers des “clouders”. MetalLB est une implémentation de Load Balancer pour les clusters Kubernetes Bare Metal, utilisant des protocoles de routage standard. Rancher 2 sera également utilisé. On aurait pu utiliser kubeadm mais cette solution nous simplifie clairement la vie.


Pré-requis

  • Docker

Lancer Rancher 2 via Docker

sudo docker run -d --privileged --restart=unless-stopped -p 8443:443 rancher/rancher

Provisionner un cluster k8s

Une fois le serveur Rancher démarré, connectez-vous en créant un compte admin puis créez un cluster Kubernetes. Pour faire simple dans cet article, cochez les cases etcd, controle-plane, worker. Cela va générer une commande Docker qu’il suffira d’exécuter sur le noeud que vous avez à disposition pour installer votre cluster.


La commande va ressembler à ceci:

export IP_LOCAL=
export TOKEN=6r5q7w5wnzk95g84bv2zclc4qn5k5dwvc8m9vxgdqjgcvf2vgxbcm8
export CA_CHECKSUM=e768299cdfb443db9b772a23519030f49ad93deaeaedb8064d9aaf2e9b260f77
sudo docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run rancher/rancher-agent:v2.5.2 --server https://$IP_LOCAL:8443 --token $TOKEN --ca-checksum $CA_CHECKSUM --etcd --controlplane --worker

Installer helm 3+

Télécharger le package helm 3.4.1 depuis l’adresse suivante puis exécutez les commandes suivantes:

tar -zxvf helm-v3.4.1-linux-amd64.tar.gz
sudo chmod +x linux-amd64/helm
mv linux-amd64/helm /usr/local/bin/helm

Installer kubectl

curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version --client

Depuis l’interface admin de Rancher, récupérez le kubectl config. Collez le dans le fichier ~/.kube/config de votre poste local pour que kubectl puisse communiquer avec votre cluster. Cela vous permettra d’exécuter des commandes kubernetes et installer metalLB depuis votre poste local.


Installer et configurer metalLB

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml

# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

Vérifier que metalLB tourne bien:

kubectl get pods -n metallb-system

Créer un confimap config.yaml permettant de configurer metalLB en mode Layer 2. Ce mode est le plus simple à configurer. Il suffit de configurer uniquement les adresses IP. Le mode Layer 2 ne requiert pas d’avoir les adresses IP attachées à l’interface réseau du noeud worker.


Remplacer - 192.168.15.120-192.168.15.250 du configmap ci-dessous par le range d’IP de votre réseau.

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.15.120-192.168.15.250

Appliquer le configmap

kubectl apply -f config.yaml

Maintenant, retourner dans l’interface Rancher, Cluster, Namespaces et déplacer metallb-system dnas le project “System”.

image

image

image


Test demo app

git clone https://github.com/jodykpw/metallb-nginx-demo.git
cd metallb-nginx-demo
helm install --name nginx-demo ./

Facultatif: éditer values.yaml, changer le type de service à LoadBalancer. Je n’ai pas eu besoin de faire cela mais c’est recommandé. J’ai suivi la procédure qui suit.


Deployer Nginx comme Ingress Controller

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml

Editer l’ingress-controller et changer spec.type de NodePort à LoadBalancer.

kubectl edit svc ingress-nginx-controller -n ingress-nginx

Créer un ingress via l’interface Rancher. J’ai associé un hostname dans l’ingress. Créer soit une entrée dans votre /etc/hosts ou un CNAME sur votre DNS.

image

image


Vérifier que le pod est bien “running”:

kubectl get svc --all-namespaces

Depuis votre navigateur, rendez-vous sur nuc.com pour voir le résultat suivant:

image


Test grafana app

Il vous est possible de provisionner un grafana directement depuis le catalogue Rancher. Instanciez en un puis créez un ingress avec un hostname comme par example grafana.leandeep.com et ajoutez l’entrée dans votre /etc/hosts

image

image


Facultatif: Let’s encrypt

Installer le cert-manager

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.0.3/cert-manager.yaml

Vérifier que les pods sont running:

kubectl get pods --namespace cert-manager

Configurer l’env staging. Créer un fichier staging_issuer.yaml et ajouter le contenu suivant:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
 name: letsencrypt-staging
spec:
 acme:
   # The ACME server URL
   server: https://acme-staging-v02.api.letsencrypt.org/directory
   # Email address used for ACME registration
   email: [email protected]
   # Name of a secret used to store the ACME account private key
   privateKeySecretRef:
     name: letsencrypt-staging
   # Enable the HTTP-01 challenge provider
   solvers:
   - http01:
       ingress:
         class:  nginx

Appliquer la ressource:

kubectl apply -f staging_issuer.yaml

Mettez à jour l’ingress. Voici un example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/issuer: letsencrypt-staging
  name: home-ingress
  namespace: default
spec:
  tls:
  - hosts:
    - example.io
    secretName: home-example-io-tls
  rules:
  - host: example.io
    http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80
        path: /

Vérifier le bon fonctionnement:

kubectl describe certificate

Configurer le certif de prod.

Créer le fichier production-issuer.yaml et ajouter le contenu suivant:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
 name: letsencrypt-prod
spec:
 acme:
   # The ACME server URL
   server: https://acme-v02.api.letsencrypt.org/directory
   # Email address used for ACME registration
   email: [email protected]
   # Name of a secret used to store the ACME account private key
   privateKeySecretRef:
     name: letsencrypt-prod
   # Enable the HTTP-01 challenge provider
   solvers:
   - http01:
       ingress:
         class:  nginx

Appliquer le issuer:

kubectl apply -f production-issuer.yaml

Editer votre ingress. Voici un example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/issuer: letsencrypt-prod
  name: home-ingress
  namespace: default
spec:
  tls:
  - hosts:
    - example.io
    secretName: home-example-io-tls
  rules:
  - host: example.io
    http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80
        path: /

Attention, l’obtention du certificat peut prendre entre 2 et 5 minutes.


Checker le certificat:

kubectl describe certificate

Alternative:

pfSense + Let’s Encrypt Wildcard + HA Proxy comme Reverse Proxy: solution prometteuse à tester