Zwindler sur GithubAllez faire un tour sur mes dépôts Git !

Installer Kubernetes avec Kubespray (Ansible)

Kubeadm quand on a pas ou mal accès à Internet

Rapidement pour resituer un peu le sujet, Kubernetes est un produit permettant de gérer des clusters de machines exécutant des containers en production. Un moyen simple d’installer cet outil complexe est d’utiliser l’outil kubeadm, qui était jusqu’à il y a peu déconseillé pour la production (la documentation de la version 1.8 ne le mentionne pas mais le message apparait toujours lors du « kubeadm init »). Pour y voir plus clair, vous pouvez lire les articles que j’ai écris à ce sujet.

Dans le cadre d’un déploiement d’un cluster Kubernetes on-premise, j’ai été assez ennuyé par le proxy. En théorie, on peut utiliser kubeadm derrière un proxy mais de nombreux utilisateurs remontent des difficultés de ce côté là (je ne suis pas le seul, ouf). Si vous voulez plus d’info à ce sujet j’ai mis un paragraphe en fin d’article.

Kubespray à la rescousse

Depuis quelques mois, il existe une nouvelle manière de déployer Kubernetes, qui s’appelle Kubespray. Et cerise sur le MacDo, ce méthode utilise Ansible (et vous savez comme je suis friand d’Ansible).

J’ai donc décidé de tester et, vous vous en doutez puisque j’en fais un article, j’ai réussi à installer Kubernetes avec Kubespray derrière mon proxy capricieux ;-).

A noter, Kubespray ne se limite pas à déployer un Kubernetes on premise, puisqu’il supporte aussi AWS et OpenStack via l’utilisation de scripts Terraform (outil qui fera l’objet d’un petit article à venir).

Vous pouvez trouver la documentation sur les sites suivants :

Installation des prérequis

Un petit tour sur le Github nous donne les prérequis :

Kubespray nécessite l’installation des outils de développements sur la machine qui exécute le script Ansible, ainsi que Python 3. Sur les CentOS / RHEL 7, la version de Python est la 2.7, qui n’est donc pas compatible avec le script Python 3 qui génère le fichier d’inventaire pour le déploiement Ansible.

En soit, ce n’est pas vital, mais ça facilite quand même le travail donc ça vaut le coup.

yum -y install yum-utils
yum -y groupinstall development
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
yum -y install python36u
pip install --upgrade Jinja2

Récupération et configuration de kubespray

Les sources de Kubespray sous sur Github, on les récupère

git clone https://github.com/kubernetes-incubator/kubespray

On copie le dossier inventory d’origine pour se faire sa propre conf :

cd kubespray
cp -r inventory inventaire_kubernetes

On déclare les adresses IPs des futurs noeuds kubernetes puis on lance le script pour générer l’inventaire :

declare -a IPS=(192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104)
CONFIG_FILE=inventaire_kubernetes/inventory.cfg python3.6 contrib/inventory_builder/inventory.py ${IPS[@]}

On peut regarder le contenu de modifier le fichier inventaire_kubernetes/inventory.cfg si nécessaire :

[all]
master01         ansible_host=192.168.1.101 ip=192.168.1.101
worker01        ansible_host=192.168.1.102 ip=192.168.1.102
worker02        ansible_host=192.168.1.103 ip=192.168.1.103
worker03        ansible_host=192.168.1.104 ip=192.168.1.104
[kube-master]
master01
worker01
[kube-node]
master01
worker01
worker02
worker03
[etcd]
master01
worker01
worker02
[k8s-cluster:children]
kube-node
kube-master
[calico-rr]
[vault]
master01
worker01
worker02

Typiquement ici dans mon cas, n’ayant que 4 machines et ne souhaitant pas faire tourner de container sur les masters (bien que ce soit possible), j’ai prévu de ne mettre qu’un master et 3 workers.

Du coup, les groupes sont à adapter en fonction des rôles de chacun. J’ai retiré worker01 du groupe kube-master. Idéalement bien entendu, il aurait fallu avoir plus d’un master (3 idéalement ou au moins 2).

Idem pour la répartition du vault et du etcd sur les workers. Le mieux serait d’avoir un peu de haute disponibilité supplémentaire sur ces composants et donc de les répartir comme le propose le script d’inventaire, mais rien ne vous y oblige.

Déploiement du cluster

Maintenant que notre inventaire est prêt, Kubespray déploie le cluster avec ce oneliner :

ansible-playbook -i inventaire_kubernetes/inventory.cfg cluster.yml -b -v --private-key=~/.ssh/id_rsa

Pas mal hein ? Par rapport à l’installation avec kubeadm que je décris dans Installer un cluster Kubernetes sur des VMs CentOS 7, c’est quand même bien plus simple !

Oui oui, vous avez compris, c’est déjà fini !

Bonus : Trial and error

Bon… j’ai quand même eu quelques erreurs 😉

Too many nameservers

Pas de bol pour moi, ça a planté directement avec l’erreur « Too many nameservers ». O-kay…

Effectivement, j’ai plusieurs serveurs DNS renseignés sur mon OS et Kubespray ne supporte pas plus de 2 out of the box.

Bon pas de drame, l’utilitaire nous indique qu’on peut contourner cette « erreur » simplement en modifiant une variable :

You can relax this check by set docker_dns_servers_strict=no and we will only use the first 3.

Dans le fichier cluster.yml, recherchez le block suivant et ajouter les lignes -vars puis – docker_dns_servers_strict: no

vi cluster.yml
[...]
- hosts: k8s-cluster:etcd:calico-rr
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
vars:
- docker_dns_servers_strict: no
roles:
- { role: kubespray-defaults}
- { role: kernel-upgrade, tags: kernel-upgrade, when: kernel_upgrade is defined and kernel_upgrade }
- { role: kubernetes/preinstall, tags: preinstall }
- { role: docker, tags: docker }
- role: rkt
tags: rkt
when: "'rkt' in [etcd_deployment_type, kubelet_deployment_type, vault_deployment_type]"
[...]

Proxy pour pull les images Docker

Comme je l’ai dis en introduction, j’ai été pas mal embêté par le proxy lors de l’installation de mon cluster, notamment avec kubeadm. Il n’y a pas de raison que je ne sois pas aussi embêté avec Kubespray ;-).

Heureusement le contournement est simple, ici il suffit de configurer le proxy sur les démons docker de toutes les machines du cluster. Avec ansible :

ansible -m shell master* worker* -a 'cat > /etc/systemd/system/docker.service.d/http-proxy.conf << EOF
[Service] Environment="HTTP_PROXY=http://mon-super-proxy:8080/"' 
ansible -m shell master* worker* -a "systemctl daemon-reload" 
ansible -m shell master* worker* -a "systemctl restart docker" 

Attention au restart si vous avez des containers qui tournent… mais je vais partir du principe que nous puisque vous êtes en train d’installer un cluster Kubernetes (depuis zéro).

The error was: no test named ‘equalto’

Vous avez probablement oublié un des prérequis : la version de jinja n’est pas pas à jour…

pip install --upgrade Jinja2 

Messages d’information à chaque exécution de kubectl

J’ai aussi eu un petit bug (non bloquant) une fois l’installation terminée. A chaque exécution de kubectl, j’avais les messages suivants qui s’affichaient dans le terminal.

kubectl describe service kubernetes-dashboard --namespace=kube-system 
2017-08-24 10:20:09.035979 I | proto: duplicate proto type registered: google.protobuf.Any 
2017-08-24 10:20:09.036050 I | proto: duplicate proto type registered: google.protobuf.Duration 
2017-08-24 10:20:09.036066 I | proto: duplicate proto type registered: google.protobuf.Timestamp 
[…] 

L’issue a été remontée sur le github de la version de Kubernetes déployée par Azure, à savoir acs-engine, mais est applicable dans notre cas aussi. A priori c’est une version de kubectl qui a le problème.

Le problème devrait être résolu avec la version qu’on trouve sur les repository.

mv /usr/local/bin/kubectl /usr/local/bin/kubectl.old 
yum install -y kubectl 
ln -s /usr/bin/kubectl /usr/local/bin/kubectl 

Bonus : Changer le service du dashboard de kubernetes pour le publier sur un port

Dernier petit point de détail, normalement on préfère accéder au dashboard de Kubernetes avec le kube proxy mais dans mon cas, il est protégé sur un réseau séparé. Du coup je remplace le ClusterIP (interne à Kubernetes uniquement) par un Nodeport en récupérant la configuration du service, en la modifiant et en la réappliquant :

kubectl get svc kubernetes-dashboard --namespace=kube-system -o yaml > kubernetes-dashboard-svc.yaml
vi kubernetes-dashboard-svc.yaml
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
ports:
- port: 80
protocol: TCP
targetPort: 9090
selector:
k8s-app: kubernetes-dashboard
type: NodePort

Une fois les modification faites, on réapplique la configuration et on vérifie que ça a fonctionné

 
kubectl apply -f kubernetes-dashboard-svc.yaml
kubectl get svc --namespace=kube-system
NAME                   CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
kube-dns               10.233.0.3      <none>        53/UDP,53/TCP   97d
kubernetes-dashboard   10.233.33.140   <nodes>       80:30000/TCP    97d

Le Dashboard est disponible sur le port 30000 !

Kubeadm et les proxy internet

Pour faire simple, kubeadm fait des appels à Internet via de multiples canaux (je n’ai pas vérifié si c’était mieux en 1.8) :

  • docker pull pour récupérer les images
  • un accès direct

J’ai eu beau ajouter ''with_proxy, configurer les variables HTTP_PROXY/HTTPS_PROXY/NO_PROXY (et en minuscules) aussi bien au niveau de l’OS que du démon Docker mais rien n’y a fait…

Quelques pistes si vous voulez vous y essayer :

On peut même également installer un cluster Kubernetes avec kubeadm sans accès à Internet en préchargeant les images docker nécessaires, mais là encore, l’outil kubeadm se bloque au moment d’aller vérifier sur Internet s’il existe des images plus récentes à télécharger.

Add a Comment

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *