En este documento aprendereás cómo crear un clúster de Kubernetes
Requisitos
- 3 servidores con el Sistema Operativo Ubuntu 18.04(1 actuará como el panel de control y 2 serán los trabajadores)
- Acceso a Internet en los 3 servidores
- Acceso como súper usuario o root
Procedimiento
Configuración de repositorios (realizar en los 3 servidores)
Necesitaremos agregar 2 repositorios a los servidores, los cuales nos permitirán instalar Docker como motor de contenedores y Kubernetes como orquestrador.
Docker
El primer comando descargará la llave pública del repositorio Docker, la cuál nos ayudará a verificar que los paquetes sean legítimos
user@controlplane:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg
OK
A continuación agregamos el repositorio Docker
user@controlplane:~$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
Hit:1 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic InRelease
Get:2 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:3 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
Hit:4 http://security.ubuntu.com/ubuntu bionic-security InRelease
Get:5 https://download.docker.com/linux/ubuntu bionic InRelease [64.4 kB]
Get:6 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1680 kB]
Get:7 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages [13.0 kB]
Fetched 1921 kB in 1s (2389 kB/s)
Reading package lists... Done
Kubernetes
Agregamos la llave pública de Kubernetes
user@controlplane:~$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
OK
Ahora agregamos el repositio
user@controlplane:~$ cat << EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
deb https://apt.kubernetes.io/ kubernetes-xenial main
Para confirmar que ambos repositorioas se hayan agregado correctamente vamos a actualizar la lista de paquetes
user@controlplane:~$ sudo apt-get update
Hit:1 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic-updates InRelease
Get:3 http://us-west-1.ec2.archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
Hit:4 https://download.docker.com/linux/ubuntu bionic InRelease
Hit:6 http://security.ubuntu.com/ubuntu bionic-security InRelease
Get:5 https://packages.cloud.google.com/apt kubernetes-xenial InRelease [8993 B]
Get:7 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 Packages [41.3 kB]
Fetched 125 kB in 1s (167 kB/s)
Reading package lists... Done
La salida del comando nos muestra que https://download.docker.com/linux/ubuntu bionic InRelease y https://packages.cloud.google.com/apt kubernetes-xenial InRelease se encuentran disponibles
Instalación de Docker (3 servidores)
En esta ocasión utilizaremos Docker como el motor de contenedores en nuestro clúster debido a la amplia adopción y basta documentación, cabe mencionar que existen otras opciones.
Antes de instalar Docker nos aseguraremos de deshabilitar la memoria swap en el servidor
user@controlplane:~$ sudo swapoff -a
Una vez que la memoria swap esté deshabilitada continuaremos con la instalación de Docker
user@controlplane:~$ sudo apt-get install -y docker-ce
Reading package lists... Done
Building dependency tree
Reading state information... Done
....
Created symlink /etc/systemd/system/sockets.target.wants/docker.socket → /lib/systemd/system/docker.socket.
Processing triggers for libc-bin (2.27-3ubuntu1.2) ...
Processing triggers for systemd (237-3ubuntu10.42) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
Processing triggers for ureadahead (0.100.0-21) ...
Ahora agregaremos nuestro usuario al grupo Docker por si queremos analizar algún contenedor en el futuro. Los cambios tomarán efecto después de reiniciar nuestra sesión
user@controlplane:~$ sudo usermod -aG docker $USER
Podemos comprabar que Docker se ha instalado de manera correcta con el siguiente comando
user@controlplane:~$ docker version
Client: Docker Engine - Community
Version: 19.03.13
API version: 1.40
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 17:02:36 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.13
API version: 1.40 (minimum version 1.12)
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 17:01:06 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.3.7
GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
La salida del comando nos muestra la versión actual del cliente (19.03.13) y servidor/motor (19.03.13) de Docker
Instalación de Kubernetes (3 servidores)
Una vez finalizada la instalación del motor de contenedores continuaremos con la instalación de los componentes de nuestro orquestrador. kubelet se encarga de gestionar los pod asignados al nodo, kubeadm se encargará de iniciar y configurar los componentes de nuestro controlador y kubectl nos permitirá interactuar con el clúster a través del API
user@controlplane:~$ sudo apt-get install -y kubelet kubeadm kubectl
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.
Setting up kubectl (1.19.3-00) ...
Setting up kubeadm (1.19.3-00) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
Instalados los paquetes configurarémos las IPTables de los servidores para que la comunicación intra-cluster no tenga ningún problema
echo "net.bridge.bridge-nf-call-iptables=1" | sudo tee -a /etc/sysctl.conf
Configuración del clúster
Inicialización del clúster (servidor controlador/maestro)
Para inicializar los componentes basta con indicarle a kubeadm el rango de red con el que trabajarán los pods de nuestro clúster
user@controlplane:~$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16
W1029 21:59:38.413226 32226 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.19.3
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
....
[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 172.31.39.180:6443 --token 6u51cd.c9mqy58au927fdq2 \
--discovery-token-ca-cert-hash sha256:964b795be9c5f49273608bc3620493bc91022b356cbc3ce63613719392938ed3
La salida del comando nos advierte que para comenzar a utilizar el clúster ejecutemos los comandos
Unir nodos al clúster (2 servidores trabajadores/worker)
Para que los demás servidores se unan al clúster basta con ejecutar el comando mencionado en la inicialización del clúster
user@worker1:~$ sudo kubeadm join 172.31.39.180:6443 --token 6u51cd.c9mqy58au927fdq2 \
> --discovery-token-ca-cert-hash sha256:964b795be9c5f49273608bc3620493bc91022b356cbc3ce63613719392938ed3
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
....
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Podemos verificar que los 2 servidores worker/trabajadores se han unido al clúster ejecuntando el siguiente comando el nodo maestro/controlador
user@controlplane:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
controlplane NotReady master 7m53s v1.19.3
worker1 NotReady <none> 113s v1.19.3
worker2 NotReady <none> 111s v1.19.3
Instalar plugin de red (servidor controlador/maestro)
Los tres nodos se han unido al clúster pero si ponemos atención a la columna de Status del comando anterior nos percataremos que no se encuentran listos. Esto es debido a que nos falta configurar un componente escencial en el clúster, el plugin de red. Sin este plugin no es posible tener comunicación entre los pods del clúster. Existe una gran variedad de plugins disponibles, en esta ocasión instalaremos flannel debido a la facilidad para configurarlo.
user@controlplane:~$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
De esta forma estamos instalando el plugin a través de objetos de Kubernetes. Después de unos segundos, dependiendo de la red en donde se encuentran los servidores, estará lista la comunicación en el clúster y podemos verificarlo checando los nodos del clúster de nueva cuenta
user@controlplane:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
controlplane Ready master 16m v1.19.3
worker1 Ready <none> 10m v1.19.3
worker2 Ready <none> 10m v1.19.3
El Status de los nodos es Ready. Ahora es posible crear objetos de Kubernetes en nuestro ambiente.
Como si se tratara de una introducción a un lenguaje de programación, creaemos un ejemplo Hola Mundo al estilo de Kubernetes.
user@controlplane:~$ kubectl create deployment hola-mundo --image=nginx
deployment.apps/hola-mundo created
Después de unos momentos el deployment estará listo.
user@controlplane:~$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
hola-mundo 1/1 1 1 81s
Para poder acceder al deployment basta con exponerlo de la siguiente forma, con lo cuál será posible consultar en el puerto 30080 del nodo al que se asigne
user@controlplane:~$ kubectl expose deployment hola-mundo --type=NodePort --port=30080
service/hola-mundo exposed
Ahora es posible acceder al deployment. Realizar una petición con curl deberá mostrarnos el documento HTML defecto de nginx
user@controlplane:~$ curl 10.97.228.29:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Contribuciones
Puedes contribuir utilizando Pull Requests en el repositorio correspondiente. De no existir crea un archivo contrib.txt, de existir modifica el archivo para agregar tu nombre de usuario o correo.
Por ejemplo:
- fulano.detal@correo.com
- perengano