L'installation d'un cluster Kubernetes sur un serveur Linux est assez peu simple contrairement à son cousin Minikube. Je suis parvenu à trouver une installation qui tient la route après de multiples tests et essais sur différentes versions Linux, Docker ou Kubernetes.

On va donc installer Kubernetes et OpenFaas sur un VPS tournant sur Ubuntu 16.06 Xenial et avec Docker et Docker-compose installés évidemment. Attention la procédure n'est pas très compliquée mais elle requiert pas mal de temps en raison du nombre de commandes à saisir dans votre terminal. Allez on y va :

1_d55xomi-KOPDL48kn_bF4A

On commence par actualiser les dépôts pour installer Docker :

sudo apt-get update

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

On vérifie :

sudo apt-key fingerprint 0EBFCD88

Cela doit ressembler à ça :

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

On ajoute un repository stable :

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Puis on actualise à nouveau :

sudo apt-get update

On cherche la version de Docker que l'on souhaite utiliser :

apt-cache madison docker-ce

docker-ce | 17.09.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.09.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.2~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.2~ce-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages

Et on installe la bonne comme ceci :

sudo apt-get install docker-ce=17.09.1~ce-0~ubuntu  

On checke si Docker fonctionne :

sudo docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/    

Parfait tout fonctionne correctement, pour Docker-compose :

sudo apt-get install docker-compose

Attaquons maintenant la suite :

Installation Kubernetes

Vous pouvez trouver votre adresse IP privée / publique / de centre de données via ifconfig:

ifconfig

   Link encap:Ethernet  HWaddr fa:16:3e:5e:99:7d  
          inet addr:**37.187.180.146**  Bcast:37.187.180.146     Mask:255.255.255.255
          inet6 addr: fe80::f816:3eff:fe5e:997d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:434529 errors:0 dropped:0 overruns:0 frame:0
          TX packets:249821 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:492540441 (492.5 MB)  TX bytes:25314904 (25.3 MB)

1_TG810MeYGAlgQnSxxkDGNQ

Installer l'apt repo de Kubernetes

$ apt-get update && apt-get install -y apt-transport-https \
  && curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list

Maintenant on peut actualiser la liste des paquest avec apt-get update.

Installer kubelet, kubeadm et kubernetes-cni

Le kubelet est responsable de l'exécution des conteneurs sur vos hôtes. kubeadm est un utilitaire pratique pour configurer les différents composants qui composent un cluster de travail et kubernetes-cni représente les composants de mise en réseau.

$ apt-get update \
  && apt-get install -y kubelet kubeadm kubernetes-cni

Initialize your cluster with kubeadm

Depuis la documentation en ligne :

Kubeadm vise à créer un cluster sécurisé hors de la boîte via des mécanismes tels que RBAC.

Nous allons maintenant utiliser l'adresse IP interne pour diffuser l'API Kubernetes - plutôt que l'adresse Internet.

Vous devez remplacer --apiserver-advertise-address par l'adresse IP de votre hôte.

$ kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=37.187.180.146--kubernetes-version stable-1.8

Ce qui va nous donner :

root@vps447310:~# kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=37.187.180.146--kubernetes-version stable-1.8
[init] Using Kubernetes version: v1.10.2
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
    [WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [vps447310 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 37.187.180.146]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names [localhost] and IPs [127.0.0.1]
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names [vps447310] and IPs [37.187.180.146]
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests".
[init] This might take a minute or longer if the control plane images have to be pulled.
[apiclient] All control plane components are healthy after 58.502413 seconds
[uploadconfig] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[markmaster] Will mark node vps447310 as master by adding a label and a taint
[markmaster] Master vps447310 tainted and labelled with key/value: node-role.kubernetes.io/master=""
[bootstraptoken] Using token: rylfuw.u4irw6ojvuyr1o26
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: kube-dns
[addons] Applied essential addon: kube-proxy

Your Kubernetes master 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/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 37.187.180.146:6443 --token rylfuw.u4irw6ojvuyr1o26 --discovery-token-ca-cert-hash sha256:2c2388fb46560305d4a75fb0f6ef8ed1ca8ae56cdc43b478758bc48e804552c0

Flanel

Flannel fournit un réseau défini par logiciel (SDN) en utilisant les modules overlay et ipvlan du noyau Linux.

Une autre offre populaire de SDN est WeaveNet de WeaveWorks. Pour la déployer :

    $ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
Configurer un compte utilisateur non privilégié

L'installation d'Ubuntu est conçue sans compte utilisateur non-privilégié (root), alors ajoutons-en un.

useradd username -G sudo -m -s /bin/bash
passwd username

Configurer les variables d'environnement en tant que nouvel utilisateur

Vous pouvez maintenant configurer votre environnement avec les instructions à la fin du message init ci-dessus.

Passez au nouveau compte utilisateur avec:

sudo su username

$ cd $HOME
$ sudo whoami
$ sudo cp /etc/kubernetes/admin.conf $HOME/
$ sudo chown $(id -u):$(id -g) $HOME/admin.conf
$ export KUBECONFIG=$HOME/admin.conf
$ echo "export KUBECONFIG=$HOME/admin.conf" | tee -a ~/.bashrc

Appliquez votre réseau de pod (flanel)

Nous allons maintenant appliquer la configuration au cluster en utilisant kubectl et deux entrées des documents flannel:

$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
serviceaccount "flannel" created  
configmap "kube-flannel-cfg" created  
daemonset "kube-flannel-ds" created
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/k8s-manifests/kube-flannel-rbac.yml
clusterrole "flannel" created  
clusterrolebinding "flannel" created

Une alternative à ce stade serait de provisionner une seconde machine et d'utiliser le jointoken à partir de la sortie de kubeadm.

kubeadm join 37.187.180.146:6443 --token rylfuw.u4irw6ojvuyr1o26 --discovery-token-ca-cert-hash sha256:2c2388fb46560305d4a75fb0f6ef8ed1ca8ae56cdc43b478758bc48e804552c0

Vérification
La plupart des composants Kubernetes s'exécutent en tant que conteneurs sur votre cluster dans un espace de noms caché appelé système-kube. Vous pouvez voir s'ils travaillent comme ceci:

gabriel@vps447310:~$ kubectl get all --namespace=kube-system
    NAME                                    READY     STATUS    RESTARTS   AGE
    pod/etcd-vps447310                      1/1       Running   0          11m
    pod/kube-apiserver-vps447310            1/1       Running   0          10m
    pod/kube-controller-manager-vps447310   1/1       Running   0          11m
    pod/kube-dns-86f4d74b45-sdf7m           3/3       Running   0          11m
    pod/kube-flannel-ds-pkhrx               1/1       Running   0          1m
    pod/kube-flannel-ds-tdw7x               1/1       Running   0          45s
    pod/kube-proxy-bcmxk                    1/1       Running   0          45s
    pod/kube-proxy-nxf5r                    1/1       Running   0          11m
    pod/kube-scheduler-vps447310            1/1       Running   0          11m

    NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
    service/kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP   11m

    NAME                             DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
    daemonset.apps/kube-flannel-ds   2         2         2         2            2           beta.kubernetes.io/arch=amd64   1m
    daemonset.apps/kube-proxy        2         2         2         2            2           <none>                          11m

    NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/kube-dns   1         1         1            1           11m

    NAME                                  DESIRED   CURRENT   READY     AGE
    replicaset.apps/kube-dns-86f4d74b45   1         1         1         11m
    gabriel@vps447310:~$ 

Comme vous pouvez le voir tous les services sont dans un état de fonctionnement qui indique un cluster en bonne santé. Si ces composants sont toujours téléchargés à partir d'Internet, ils peuvent apparaître comme non démarrés.

Run Openfaas

Vous pouvez maintenant exécuter un conteneur sur votre cluster. Kubernetes organise les conteneurs en Pods qui partagent une adresse IP commune, sont toujours planifiés sur le même nœud (hôte) et peuvent partager des volumes de stockage.

Vérifiez d'abord que vous n'avez pas de pods (conteneurs) fonctionnant avec:

$ kubectl get pods

Utilisez maintenant l'exécution de kubectl pour déployer un conteneur. Nous allons déployer la solution serverless OpenFaas sur notre cluster.

1_rVpLjxV0ZP3pFxysv-HhTw

Déployez une pile avec une fonctionnalité asynchrone fournie par NATS Streaming.

  • Déployer la pile entière

Cette commande est divisée en deux parties afin que les espaces de noms OpenFaaS soient toujours créés en premier:

openfaas - pour les services OpenFaaS
openfaas-fn - pour les fonctions

$ cd faas-netes && \
kubectl apply -f ./namespaces.yml,./yaml
  • Utilisez la CLI

Installez l'interface de ligne de commande

$ curl -sL https://cli.openfaas.com | sudo sh

Si vous le souhaitez, vous pouvez également exécuter le script via un utilisateur non root. Ensuite, le binaire faas-cli est téléchargé dans le répertoire de travail actuel à la place.

Ensuite, clonez des fonctions à déployer sur votre cluster.

$ git clone https://github.com/openfaas/faas-cli

Modifiez stack.yml et remplacez votre URL de passerelle localhost:8080 par kubernetes-node-ip:31112 ou passez l'indicateur --gateway / -g aux commandes.

c'est à dire :

provider :
  nom: faas
  passerelle: http://37.187.180.146:31112

Maintenant, déployez depuis le dossier faas-cli:

$ faas-cli deploy -f stack.yml

Résultat :

gabriel@vps447310:~/faas-cli$ sudo faas-cli deploy -f stack.yml
Deploying: url-ping.

Deployed. 202 Accepted.
URL: http://37.187.180.146:31112/function/url-ping

Deploying: stronghash.

Deployed. 202 Accepted.
URL: http://37.187.180.146:31112/function/stronghash

Deploying: nodejs-echo.

Deployed. 202 Accepted.
URL: http://37.187.180.146:31112/function/nodejs-echo

Deploying: shrink-image.

Deployed. 202 Accepted.
URL: http://37.187.180.146:31112/function/shrink-image

Deploying: ruby-echo.

Deployed. 202 Accepted.
URL: http://37.187.180.146:31112/function/ruby-echo

gabriel@vps447310:~/faas-cli$ 

Lister les fonctions:

gabriel@vps447310:~/faas-cli$ faas-cli list -f stack.yml
Function                      	Invocations    	Replicas
nodejs-echo                   	0              	1    
ruby-echo                     	0              	1    
shrink-image                  	0              	1    
stronghash                    	0              	1    
url-ping                      	0              	1   

Invoquer une fonction:

$ echo -n "Test" | faas-cli invoke stronghash -g http://127.0.0.1:31112
c6ee9e33cf5c6715a1d148fd73f7318884b41adcb916021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31  -

L'interface utilisateur est exposée sur le port 31112.

Capture-d-e-cran-2018-05-15-a--22.39.04

Cliquez sur "Nouvelle fonction" et sélectionner la fonction que vous avez déployé :

Capture-d-e-cran-2018-05-15-a--22.40.35

Testez la fonction

La fonction peut également être appelée via l'interface de ligne de commande:

$ echo -n "" | faas-cli invoke --gateway http://kubernetes-ip:31112 nodeinfo
$ echo -n "verbose" | faas-cli invoke --gateway http://kubernetes-ip:31112 nodeinfo

Et voilà !