Spinnaker : Cluster Kubernetes Façonnable. Concevoir son Lab en 10min avec YaKEL
Sommaire
Le focus du présent billet concerne l’installation du cluster. Kubernetes sera notre terrain de jeu, et afin de partir du même pied, je vous propose "YaKEL". YaKEL (Yet Another Kubernetes Environment Lab) est un projet à base de playbook Ansible léger pour l’installation rapide (moins de 10 minutes) d’un cluster Kubernetes de 3 noeuds pouvant tenir sur un laptop, que j’ai réalisé pour mes propres besoins d’expérimentation.
Les prérequis
Le cluster est simple à “customiser” et nécessite les pré-requis suivants :
✓ système d’exploitation : MacOS / Linux
✓ virtualbox : 5.2.8
✓ Vagrant : 2.0.3
✓ Ansible : 2.5.0 sera installé de manière isolé en utilisant python virtualenv afin de ne pas perturber votre version courante d’Ansible si vous l’avez sur votre machine
✓ Visual Studio code (optionnel) : ou tout autre éditeur de code supportant la coloration syntaxique yaml pour plus de lisibilité.
A la fin de l’installation, 5 à 10 minutes selon votre connexion internet et la capacité de votre laptop, nous obtiendrons le cluster tel que décrit sur le schéma ci-dessous.
Schéma
Ci-dessous le schéma de principe représentant la cinématique d'installation du cluster kubernetes.
La stack YaKEL est composée de :
✓ Traefik : L'ingress controller Traefik assure le routage du flux http entrant dans le cluster vers les pods applicatifs
✓ CoreDNS : Le Server DNS flexible et extensible qui permet à kubernetes d'assurer le service discovery
✓ Calico : Notre cni (Container Network Interface) network driver, pour la connectivité réseaux et les network policies
✓ Docker : le "container runtime" qu'on ne présente plus
✓ Kubernetes : l'orchestrateur "prod ready" pour les environnements conteneurisés.
Configuration
Pour la configuration du cluster kubernetes, j’ai regroupé dans le fichier clustervars.yml l’ensemble des paramètres Vagrant, Ansible et Kubernetes qui nous serviront lors des phases de provisioning vagrant up, playbook run Ansible et déploiement de Kubernetes pour que le tout soit plus "DRY" (Don’t Repeat Yourself) et sans tomber dans l’effet "WET" (Waste Everyone’s Time) y compris pour moi :). Je vais vous décrire les blocs de configuration qui ont leur importance pour la suite des actions.
Pour accéder aux applications du cluster kubernetes via un domaine personnalisable, il vous faudra renseigner la variable ci-dessous.
vagrant:
domain_tld: "roklab.ops"
Puis dans le bloc de configuration qui suit, c’est la définition des noeuds (instance de vm) de notre cluster kubernetes et les rôles que chacun se voit attribuer. Indiquez ici également ce même nom de domaine "fictif" utilisé pour la variable précédente "domain_tld" accessible uniquement de manière locale sur votre machine (laptop).
ingress: <1>
edge:
route: apps.roklab.ops
address: 192.168.32.8
nodename: node02
### -- kubernetes / ansible extra vars / vagrant box variables
server:
etcd: ## etcd is for ansible only. etcd is on same vm as master <2>
nodes:
- nodename: node01
fqdn: 'node01.roklab.ops'
vagrant_enabled: false # no need to create the etcd vm
ip: 192.168.32.7
controlplane: <3>
nodes:
- nodename: node01
fqdn: 'node01.roklab.ops'
aliases: 'node01'
vagrant_enabled: true
ip: 192.168.32.7
cpu: 2
ram: 2048
worker: <4>
nodes:
- nodename: node02
fqdn: 'node02.roklab.ops'
aliases: node02
vagrant_enabled: true
ip: 192.168.32.8
cpu: 1
ram: 1024
- nodename: node03
fqdn: 'node03.roklab.ops'
aliases: node03
vagrant_enabled: true
ip: 192.168.32.9
cpu: 1
ram: 1024
<1> Ingress : permet l’accès à l'applicatif via des urls du type *.apps.roklab.ops ( *.apps.votrefake.domain.local). Il faut savoir que n’importe quel noeud peut assumer le role d’ingress controller (même le master) grâce aux directives “toleration” et “affinity”. Ici j'ai choisi le node02 pour le déploiement de l'ingress controler (Traefik), mais pour votre propre lab il n'y a aucune contre indication de le mettre sur le master par exemple.
<2> Etcd : pour le "cluster state" déployé sur le même noeud que le master, à cet effet, notez la présence du paramètre "vagrant_enabled: false". J’ai implémenté une logique de "skip" dans le fichier Vagrantfile. Lorsque ce paramètre est à "false" cela indique à Vagrant de ne pas créer de vm pour cette instance.
<3> Controlplane : l'instance de déploiement de l’apiserver, scheduler, controller manager. "vagrant_enabled: true" indique la création d’une vm Vagrant.
<4> Worker : ces noeuds auront principalement le rôle de worker et au choix le rôle d’ingress.
Dans ce deuxième bloc, le provisionner Ansible Vagrant est défini pour l'exécution des playbooks :
provisioner:
type: 'ansible'
limit: "ROK8LABZ:localhost"
extra_vars: 'clustervars.yml'
verbose: "vv"
config_file: 'provisioning/ansible.cfg'
play:
clusterplan: 'provisioning/clusterplan.yml' <1>
clusterkube: 'provisioning/clusterkube.yml' <2>
clusterapps: 'provisioning/clusterapps.yml' <3>
tags:
plan: ["nmcli", "ipvs", "ntp", "hosts", "repo", "sysctl", "yum"]
kube: ["controlplane", "certs", "certs_upload", "worker", "network", "dns", "kubeconfig"]
apps: ["heapster", "dashboard", "traefik"]
Vagrant passera le fichier clustervars.yml sous forme d’extra_vars au provisionner Ansible
<1> Clusterplan : installe des packages et configure l’OS de sorte à améliorer l’experience Vagrant + Kube + CentOS 7
<2> Clusterkube : lance l’installation de tous les composants kube : controlplane, worker, network, dns
<3> Clusterapps : installe des applications dans le cluster kube telles que : Traefik, heapster, dashboard.
Ce troisième bloc, permet de définir les éléments d'inventory classiques d’Ansible:
ansible_groups: {
ROK8LABZ: ["node01", "node02", "node03"],
'ROK8LABZ:children': ["cluster", "etcd", "storage", "ingress"],
'ROK8LABZ:vars': { ansible_become: true, ansible_user: 'vagrant' },
'cluster:children': ["controlplane", "worker"],
'cluster:vars': { docker_version: '18.03.0', authorization_modes: ['RBAC', 'Node'] },
controlplane: ["node01"],
'controlplane:vars': { secure_port: '6443', insecure_port: '8080' },
worker: ["node02", "node03"],
etcd: ["node01"],
storage: ["node01"],
ingress: ["node02"]
}
ansible_host_vars: {
node01: { prefered_iface: '192.168.32.7', prefered_device: 'eth1'},
node02: { prefered_iface: '192.168.32.8', prefered_device: 'eth1'},
node03: { prefered_iface: '192.168.32.9', prefered_device: 'eth1'}
}
ansible_groups : pas la peine de présenter ce paramètre qui définit les group_vars d’Ansible ; c'est-à-dire les variables inventory attachées à un même groupe logique d'instances.
ansible_host_vars : de même, ici le paramètre parle de lui-même, avec les host_vars d’Ansible. Il rassemble des variables attachées specifiquement à une instance particulière.
Je termine avec ce bloc de configuration qui concerne Kubernetes. Ici je précise les éléments qui ont un impact global sur le cluster kube, tels que le range d’ip pour l’adressage des pods et des services, avec respectivement les variables "pod_cidr_address" et "service_cidr_address". J’indique également la version de Kubernetes à déployer et l’ip du service dns fournit dans cette configuration par coreDNS :
cluster:
name: "local"
domain: "cluster.local"
kubernetes_version: 'v1.10.0'
networking:
pod_cidr_address: "172.16.0.0/16"
service_cidr_address: "172.20.0.0/16"
dns_service_ip: "172.20.0.2"
Hands-On
Première étape : activé l'environnement virtualenv et installation d’Ansible. Pour ce faire, récupérer les sources depuis github comme indiqué ci-dessous ou à partir du lien suivant YaKEL.
Setup Environment
$ git clone "https://github.com/jamroks/YaKEL.git"
$ cd YaKEL
$ source setupenv.sh
Les trois noeuds de mon cluster, sont composé d’un master et deux workers. Pour les impatients il suffit de lancer la commande Vagrant habituelle "vagrant up". Dans la suite de ce tutoriel nous allons, par souci de clarté, décomposé l’installation en trois commandes.
✓ clusterplan
✓ clusterkube
✓ clusterapps
ClusterPlan
Première étape, provisionner les 3 noeuds et configurer le système s'exploitation centOS 7.
$ vagrant up --provision-with clusterplan
ClusterKube
Deuxième étape, installation du cluster Kubernetes. Lancer la commande Vagrant ci-dessous, afin de déclencher l'exécution du playbook Ansible d’installation de Kubernetes.
$ vagrant provision --provision-with clusterkube
Si tout s’est bien déroulé, vous devriez obtenir les fichiers supplémentaires ci-dessous en surbrillance :
tree -L 1
.
├── Vagrantfile
├── ansible-2.5.4
├── clustervars.yml
├── "*kubectl*"
├── "*kubectl.kubeconfig*"
├── provisioning
├── requirements.txt
└── setenv.sh
Vérifions que le cluster est opérationnel en tapant les commandes suivantes :
$ ./kubectl --kubeconfig kubectl.kubeconfig get cs
- Affiche le status du cluster, cs = componentstatuses
Vous devriez obtenir ceci :
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
En entrant les commandes ci-dessous :
$ export KUBECONFIG=kubectl.kubeconfig
$ ./kubectl cluster-info
Nous devrions obtenir ce qui suit :
Kubernetes master is running at https://192.168.32.7:6443
CoreDNS is running at https://192.168.32.7:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
ClusterApps
Troisième étape, installation des apps Kubernetes, ici Traefik (l’ingress controller) et le dashboard Kubernetes sont les deux apps que vous pouvez déployer optionnellement. Je vous recommande de déployer au moins Traefik ça rend les choses beaucoup plus simple pour l'accès aux applications.
$ vagrant provision --provision-with clusterapps
Après environ 1 minute, vous pourrez accéder aux interfaces web des kube apps :
Traefik : traefik.apps.roklab.ops
Dashboard : dashboard.apps.roklab.ops
Ce qui nous donne pour http://dashboard.apps.roklab.ops depuis votre navigateur :
Ce qui nous donne pour http://traefik.apps.roklab.ops :
Conclusion
Le cluster Kubernetes est opérationnel, nous sommes prêts à déployer Spinnaker, notre plateforme de continuous delivery multi-cloud. Dans le prochain épisode, nous aborderons la mise en place de la configuration des microservices Spinnaker ainsi que la création d’un premier pipeline de déploiement.