Cada día más los entornos plantean una migración/utilización Cloud o entornos Kubernetes/Openshift y se necesita cumplir dichos requisitos de los clientes para la realización de demostraciones para clientes.
Kubernetes no es un entorno amigable para llevarlo en un portatil de media capacidad (8GB a 16 GB de RAM) y menos con una demo que requiera ciertos recursos.
Table of Contents
Desplegar Kubernetes basandonos en kubeadm, containerd, metallb y weave
Este caso se basa en el despliegue basado en Kubeadm (https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) para el despliegue de Kubernetes, usando containerd (https://containerd.io/) como gestor del ciclo de vida de los contenedores y para poder disponer de una gestión de red mínima usaremos metallb (https://metallb.universe.tf/) que nos permitirá emular la potencia de los balanceadores de los entornos Cloud y Weave (https://www.weave.works/blog/weave-net-kubernetes-integration/) que nos permite la gestión de red de los contenedores y se integra sin problemas con metallb.
Por último y aprovechando la infraestructura desplegamos el gestor en tiempo real de los recursos K8dash (https://github.com/herbrandson/k8dash) que nos permitirá un seguimiento de estado de la infraestructura y de las aplicaciones que desplegamos en la misma.
Aunque los roles de Ansible que hemos utilizado con anterioridad (ver https://github.com/aescanero/disasterproject) nos permiten desplegar el entorno con facilidad y limpieza vamos a examinar el mismo para entender como los cambios que usaremos en siguientes capítulos (usar k3s y microk8s) repercuten de manera importante en la disponibilidad y rendimiento del entorno de demo/desarrollo.
Primer paso: Instalar Containerd
El primer paso en la instalación son las dependencias que tiene Kubernetes y una muy buena referencia sobre las mismas es la documentación que Kelsey Hightower pone a disposición de aquellos que necesitan conocer a fondo Kubernetes (https://github.com/kelseyhightower/kubernetes-the-hard-way), especialmente de todos aquellos que están interesados en certificaciones Kubernetes como CKA (https://www.cncf.io/certification/cka/).
Empezamos por una serie de paquetes de red
#Debian
sudo apt-get install -y ebtables ethtool socat libseccomp2 conntrack ipvsadm
#Centos
sudo yum install -y ebtables ethtool socat libseccomp conntrack-tools ipvsadm
Instalamos el gestor de vida de los contenedores (Containerd que incluye CRI y CNI) y aprovechamos el paquetes que viene con los interfaces de red de Kubernetes (CNI o Container Network Interface)
sudo sh -c "curl -LSs https://storage.googleapis.com/cri-containerd-release/cri-containerd-cni-1.2.7.linux-amd64.tar.gz |tar --no-overwrite-dir -C / -xz"
El paquete incluye el servicio para systemd por lo que basta con iniciar el servicio:
sudo systemctl enable containerd
sudo systemctl start containerd
Segundo Paso: kubeadm y kubelet
Ahora descargamos los ejecutables de kubernetes, en el caso de la primera máquina a configurar será el master y tenemos que descargar los binarios kubeadm (el instalador de kubernetes), kubelet (el agente que se conectará con containerd en cada máquina, para saber cual es la versión estable de kubernetes ejecutamos:
VERSION=`curl -sSL https://dl.k8s.io/release/stable.txt`
Y descargamos los binarios (en el master todos y en los nodos solo es necesario kubelet)
sudo curl -Ol https://storage.googleapis.com/kubernetes-release/release/$VERSION/bin/linux/amd64/{"kubectl","kubelet","kubeadm"} -o /usr/bin/"#1"
sudo chmod u+x /usr/bin/{"kubectl","kubelet","kubeadm"}
Configuramos un servicio para kubelet en cada máquina creando el archivo /etc/systemd/system/kubelet.service que dependerá de si la máquina tiene la función de master o nodo. Para el master tenemos:
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
Environment="KUBELET_EXTRA_ARGS='--network-plugin=cni --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --node-ip={{ vm_ip }}'"
Environment="KUBELET_KUBECONFIG_ARGS='--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf'"
Environment="KUBELET_CONFIG_ARGS='--config=/var/lib/kubelet/config.yaml'"
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
Para el resto de nodos:
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
Environment="KUBELET_EXTRA_ARGS='--network-plugin=cni --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --node-ip={{ vm_ip }}'"
Environment="KUBELET_KUBECONFIG_ARGS='--bootstrap-kubeconfig=/var/lib/kubelet/bootstrap-kubeconfig --kubeconfig=/var/lib/kubelet/kubeconfig'"
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_EXTRA_ARGS
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
Una vez cargada la configuración procedemos a utilizar kubeadm en el primer node (master), indicando la ip que se va a publicar, la red interna de los pods (un /16, aunque no olvidemos que es un entorno de demo/desarrollo por lo que no debe ser un problema). No vamos a utilizar kubeadm en el resto de nodos, así que no necesitamos recoger información de la ejecución de este comando.
$ sudo kubeadm init --apiserver-advertise-address {{ vm_ip }} --pod-network-cidr=10.244.0.0/16 --cri-socket /run/containerd/containerd.sock
Tercer paso: MetalLB (balanceador carga capa 4) y Weave (gestión de red)
Antes de preparar los nodos procedemos a cargar dos elementos, el primero “metallb” nos permitirá tener servicios “balanceables por carga: loadbalancer” accesibles en el mismo rango que las máquinas virtuales y el segundo “weave” es un gestor de red que permitirá la comunicación entre pods que se ejecutan entre máquinas diferentes dentro de la red que hemos definido anteriormente. Ambos servicios se cargan con los siguientes comandos ejecutados en master:
$ sudo mkdir ~/.kube
$ sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config
$ sudo kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(sudo kubectl version | base64 | tr -d '\n')"
$ sudo kubectl apply -f "https://raw.githubusercontent.com/danderson/metallb/master/manifests/metallb.yaml"
Cuarto paso: Añadir nodos
Para añadir los nodos hemos de crear un usuario, como no disponemos de integración con ldap o directorio activo, usaremos las cuentas de sistema o sa, generamos la cuenta initnode para añadir los nodos con el siguiente yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: initnode
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: initauth
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:node-bootstrapper
subjects:
- kind: ServiceAccount
name: initnode
namespace: kube-system
Una vez generada la cuenta de servicio ejecutamos kubectl get serviceaccount -n kube-system initnode -o=jsonpath="{.secrets[0].name}"
que nos dará el nombre del token y kubectl get secrets "NOMBRE_TOKEN" -n kube-system -o=jsonpath="{.data.token}"|base64 -d
nos dará el valor del mismo que hemos de guardar.
Además de crear el usuario hay que crear una configuración de inicio para los nodos, para ello ejecutamos los siguientes comandos:
$ sudo kubectl config set-cluster kubernetes --kubeconfig=~/bootstrap-kubeconfig --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs --server
$ sudo kubectl config set-credentials initnode --kubeconfig=~/bootstrap-kubeconfig --token=VALOR_TOKEN
$ sudo kubectl config set-context initnode@kubernetes --cluster=kubernetes --user=initnode --kubeconfig=~/bootstrap-kubeconfig
$ sudo kubectl config use-context initnode@kubernetes --kubeconfig=~/bootstrap-kubeconfig
El archivo generado hemos de copiarlo en todos los nodos en /var/lib/kubelet/bootstrap-kubeconfig
y procedemos a iniciar el servicio kubelet en cada nodo que se encargará de contactar con el master y pedir acceso.
sudo systemctl enable kubelet
sudo systemctl start kubelet
Para autorizar el o los nodos en el master hemos de ir al mismo y consultar por las peticiones con el comando kubectl get certificatesigningrequests.certificates.k8s.io
, y autorizarlas con el comando kubectl certificate approve
Una vez autorizados los nodos dispondremos de capacidad de utilizar está plataforma.