Kubernetes – Installation d’un cluster privé

Kubernetes

Dans cet article, je décris l’installation d’un cluster Kubernetes privé constitué d’un master, de trois workers et d’un poste client d’administration. Le but est de réaliser un déploiement de Solrcloud dans Kubernetes. J’ai choisi une installation totalement autonome plutôt qu’une solution Google (GKE), Amazon (EKS) ou Azure (AKS) afin d’avoir accès aux couches les plus basses et comprendre le partage des ressources (CPU, mémoire, disque). La procédure d’installation se fait au moyen de kubeadm et est bien documentée sur le site kubernates.io et sur de nombreux blogs. Cet article n’a pas vocation à expliquer les concepts de Kubernetes. J’aborderai certains de ces points dans d’autres articles lors du déploiement de Sorlcloud dans le cluster.

Les caractéristiques de l’infrastructure choisie sont :

  • L’installation se fait sur 5 VMs sous Proxmox.
  • Les VMs sont équipées d’une unique interface réseaux configurée avec des adresses IP en 192.168.x.x. Elles ne sont pas accessibles directement mais uniquement qu’au travers de rebonds et de tunnels ssh.
  • La distribution Linux choisie est CentOS 7.7 car au moment ou j’écris cet article, il n’est pas possible d’utiliser CentOS 8 à cause d’une incompatibilité avec iptables.
  • Les VMs du master et du client sont configurées avec 2 vCPU, 2 Go de RAM et un espace disque de 32 Go
  • Les VMs des workers qui hébergeront les pods Zookeeper et Solr sont configurés avec 4 vCPU, 16 Go de RAM, un premier disque de 32 Go et un second disque de 256 Go

Le schéma d’architecture correspondant est le suivant. Le client est représenté par kubectl.

Architecture du cluster Kubernetes  privé

Procédure commune au master, aux workers et au client

Les prérequis

  • Modification du fichier /etc/hosts des 5 VMs
192.168.xxx.xx0 k8s-master
192.168.xxx.xx2 k8s-worker-node1
192.168.xxx.xx3 k8s-worker-node2
192.168.xxx.xx4 k8s-worker-node3
  • Modification du hostname (exemple pour le master à répéter sur les workers avec les noms indiqués dans le fichier /etc/hosts)
# hostnamectl set-hostname 'k8s-master'
  • Création d’un utilisateur k8s
# useradd -d /home/k8s k8s
  • Désactivation de SELinux et firewalld
# setenforce 0
# sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
# systemctl stop firewalld
# systemctl disable firewalld
  • Désactivation de swap (inutile sur le client)
# swapoff -a
# vi /etc/fstab 
--> commenter la ligne correspondant au volume du swap
  • Installation de dnf et de quelques outils de monitoring (inutile sur le client)
# yum install dnf
# yum install vim tar unzip nmap telnet wget curl sysstat iotop htop atop lsof procps

Installation de docker-ce (inutile sur le client)

# yum install yum-utils device-mapper-persistent-data lvm2<br>
  • Installer la dernière version de containerd
# dnf install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm<br>
  • Installer le dernière version compatible de docker-ce 
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo<br>

Pour obtenir la liste des versions disponibles à croiser avec la liste des versions compatibles 

# dnf list docker-ce --showduplicates | sort -r<br>

Installation

# dnf install docker-ce-3:18.09.9-3.el7

# mkdir /etc/docker
# cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF
# mkdir -p /etc/systemd/system/docker.service.d
# systemctl restart docker && systemctl enable docker

Installation de Kubeadm

# cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
       https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

# yum install kubeadm
# systemctl restart kubelet && systemctl enable kubelet

Sur le master

  • Initialisation du master Kubernetes avec « kubeadm init »
# kubeadm init
[init] Using Kubernetes version: v1.16.3
[preflight] Running pre-flight checks
...
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.xxx.xx0:6443 --token uvcu6j.nie40umoqaulqvrv \
    --discovery-token-ca-cert-hash sha256:044157be8ebfbb99045dd393d74f4f3c022bee14e1dadfe

La fin de l’affichage de la commande est importante car elle donne les consignes pour la configuration du compte utilisateur k8s qui doit être utiliser pour toutes les actions d’administration. Elle indique également la procédure de configuration des workers.

  • Configuration de l’environnement de l’utilisateur k8s
# su - k8s
[k8s@k8s-master ~]$ mkdir -p $HOME/.kube
[k8s@k8s-master ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[k8s@k8s-master ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • Installation d’un add-on réseau

Un add-on réseau est nécessaire afin que les pods puissent communiquer les uns avec les autres. Il existe plusieurs add-on réseau et j’ai choisi Weave-Net le plus utilisé.

[k8s@k8s-master ~]$ export kubever=$(kubectl version | base64 | tr -d '\n')
[k8s@k8s-master ~]$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$kubever"
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created

Sur les workers

La commande à exécuter sur les workers a été fournie en fin d’affichage de la configuration du master avec « kubeadm init ». Si cette commande est perdue, il est possible d’en générer une nouvelle valable une heure.

  • Sur le master
# kubeadm token create --print-join-command
kubeadm join 192.168.xxx.xx0:6443 --token 7yfu2q.u0zgwabxyy3uawcu --discovery-token-ca-cert-hash sha256:044157be8ebfbb99045dd393d74f4f3c022bee14e1dadfe81213277f1ae647a0
  • Sur les workers
# kubeadm join 192.168.xxx.xx0:6443 --token 7yfu2q.u0zgwabxyy3uawcu --discovery-token-ca-cert-hash sha256:044157be8ebfbb99045dd393d74f4f3c022bee14e1dadfe81213277f1ae647a0
  • Sur le master (vérification de la présence des nouveaux nodes)
[k8s@k8s-master ~]$ kubectl get nodes
NAME               STATUS   ROLES    AGE     VERSION
k8s-master         Ready    master   19m     v1.16.3
ks8-worker-node1   Ready    <none>   2m7s    v1.16.3
ks8-worker-node2   Ready    <none>   50s     v1.16.3
ks8-worker-node3   Ready    <none>   10s     v1.16.3

Sur le client

Configuration de la connexion au cluster

Le client ne rejoint pas le cluster comme les workers. Il est juste nécessaire de récupérer sur le master les fichiers de configuration afin de pouvoir s’y connecter

# su -k8s
[k8s@k8s-client ~]$ scp -r k8s@k8s-master:/home/k8s/.kube .
[k8s@k8s-client ~]$ kubectl get nodes
NAME               STATUS   ROLES    AGE     VERSION
k8s-master         Ready    master   19m     v1.16.3
ks8-worker-node1   Ready    <none>   2m7s    v1.16.3
ks8-worker-node2   Ready    <none>   50s     v1.16.3
ks8-worker-node3   Ready    <none>   10s     v1.16.3

Installation du dashboard Kubernetes

Les lignes de commandes pour l’administration sont incontournables. Cependant, une interface web pour visualiser l’état du cluster Kubernetes est d’un grand confort.

  • Installation
[k8s@k8s-client ~]$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml

[k8s@k8s-client ~]$ cat > admin-user.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
EOF

[k8s@k8s-master ~]$ cat > admin-role.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
EOF

[k8s@k8s-client ~]$ kubectl apply -f admin-user.yaml
[k8s@k8s-client ~]$ kubectl apply -f admin-role.yaml
  • Récupération du token d’authentification

Ce token est nécessaire pour accéder au dashboard.

[k8s@k8s-client ~]$ kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

Name:         admin-user-token-dpz5x
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: 1981beff-9d19-49db-81a8-547a608fa610

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  20 bytes
token:      xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • Accéder au dashboard

Il faut au préalable sur le master lancer le proxy à l’aide de la commande suinate

[k8s@k8s-master ~]$ kubectl proxy &

Puis, utiliser cette url : http://k8s-master:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/overview?namespace=default

Ci-dessous une copie d’écran du dashboard après avoir installer quelques services dont un ensemble Zookeeper.

Dashboard Kubernetes

Installation d’un pod « Hello-world » de test

A ce stade de l’installation, nous disposons d’un cluster Kubernetes « vide » qui n’héberge pas encore de pod.

[k8s@k8s-client ~]$ kubectl get pod
No ressources found.

Je vous propose de suivre cette procédure afin d’installer un service Apache minimaliste et tester quelques manipulations.

Conclusion

Dans cet article, j’ai décrit l’installation d’un cluster Kubernetes privé qui permettra par la suite d’expérimenter le déploiement et l’administration d’un environnement SolrCloud.