Cómo configurar el clúster de Kubernetes (k8s) en HA con Kubeadm

Cuando configuramos Kubernetes (k8s) clúster local para el entorno de producción, se recomienda implementarlo en alta disponibilidad. Aquí, alta disponibilidad significa instalar el maestro o plano de control de Kubernetes en HA. En este artículo, demostraré cómo configurar el clúster de Kubernetes (k8s) en HA (alta disponibilidad) con la utilidad kubeadm.

Para la demostración, he usado cinco sistemas CentOS 7 con los siguientes detalles:

  • k8s-master-1 – CentOS 7 mínimo – 192.168.1.40 – 2 GB de RAM, 2 vCPU, disco de 40 GB
  • k8s-master-2 – CentOS 7 mínimo – 192.168.1.41 – 2 GB de RAM, 2 vCPU, disco de 40 GB
  • k8s-master-3 – CentOS 7 mínimo – 192.168.1.42 – 2 GB de RAM, 2 vCPU, disco de 40 GB
  • k8s-worker-1 – CentOS 7 mínimo – 192.168.1.43 – 2 GB de RAM, 2 vCPU, disco de 40 GB
  • k8s-worker-2 – CentOS 7 mínimo – 192.168.1.44 – 2 GB de RAM, 2 vCPU, disco de 40 GB

Configuración de clúster de HA-Kubernetes

Nota: el clúster de etcd también se puede formar fuera de los nodos maestros, pero para eso necesitamos hardware adicional, por lo que estoy instalando etcd dentro de mis nodos maestros.

Requisitos mínimos para configurar un clúster Highly K8s

  • Instalar en pc Kubeadm, kubelet y kubectl en todos los nodos maestros y trabajadores
  • Conectividad de red entre nodos maestros y trabajadores
  • Conectividad a Internet en todos los nodos
  • Usuario con credenciales de root o privilegios sudo en todos los nodos

Pasemos a los pasos de instalación y configuración.

Paso 1) Establezca el nombre de host y agregue entradas en el archivo /etc/hosts

Ejecute el comando hostnamectl para establecer el nombre de host en cada nodo, se muestra un ejemplo para el nodo k8s-master-1,

$ hostnamectl set-hostname "k8s-master-1"
$ exec bash

Del mismo modo, ejecute el comando anterior en los nodos restantes y establezca su respectivo nombre de host. Una vez que el nombre de host esté configurado en todos los nodos maestros y trabajadores, agregue las siguientes entradas en /etc/hosts archivo en todos los nodos.

192.168.1.40   k8s-master-1
192.168.1.41   k8s-master-2
192.168.1.42   k8s-master-3
192.168.1.43   k8s-worker-1
192.168.1.44   k8s-worker-2
192.168.1.45   vip-k8s-master

He usado una entrada adicional «192.168.1.45 vip-k8s-master» en el archivo de host porque usaré esta IP y nombre de host mientras configuro el haproxy y el keepalive en todos los nodos maestros. Esta IP será utilizada como kube-apiserver balanceador de carga ip. Todas las solicitudes de kube-apiserver llegarán a esta IP y luego la solicitud se distribuirá entre los kube-apiservers reales del backend.

Paso 2) Instale y configure Keepalive y HAProxy en todos los nodos del plano maestro/de control

Instale keepalived y haproxy en cada nodo maestro usando el siguiente comando yum,

$ sudo yum install haproxy keepalived -y

Configure Keepalived en k8s-master-1 primero, cree el script check_apiserver.sh con el siguiente contenido,

[[email protected] ~]$ sudo vi /etc/keepalived/check_apiserver.sh
#!/bin/sh
APISERVER_VIP=192.168.1.45
APISERVER_DEST_PORT=6443

errorExit() {
    echo "*** $*" 1>&2
    exit 1
}

curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://localhost:${APISERVER_DEST_PORT}/"
if ip addr | grep -q ${APISERVER_VIP}; then
    curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/"
fi

Guardar y salir del archivo.

Establecer los permisos ejecutables

$ sudo chmod +x /etc/keepalived/check_apiserver.sh

Tome la copia de seguridad del archivo keepalived.conf y luego trunque el archivo.

[[email protected] ~]$ sudo cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf-org
[[email protected] ~]$ sudo sh -c '> /etc/keepalived/keepalived.conf'

Ahora pegue el siguiente contenido en el archivo /etc/keepalived/keepalived.conf

[[email protected] ~]$ sudo vi /etc/keepalived/keepalived.conf
! /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id LVS_DEVEL
}
vrrp_script check_apiserver {
  script "/etc/keepalived/check_apiserver.sh"
  interval 3
  weight -2
  fall 10
  rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface enp0s3
    virtual_router_id 151
    priority 255
    authentication {
        auth_type PASS
        auth_pass [email protected]##D321!
    }
    virtual_ipaddress {
        192.168.1.45/24
    }
    track_script {
        check_apiserver
    }
}

Guarde y cierre el archivo.

Nota: Solo es necesario cambiar dos parámetros de este archivo para los nodos master-2 y 3. Expresar se convertirá ESCLAVO para el master 2 y 3, la prioridad será 254 y 253 respectivamente.

Configure HAProxy en el nodo k8s-master-1, edite su archivo de configuración y agregue los siguientes contenidos:

[[email protected] ~]$ sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg-org

Elimine todas las líneas después de la sección predeterminada y agregue las siguientes líneas

[[email protected] ~]$ sudo vi /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# apiserver frontend which proxys to the masters
#---------------------------------------------------------------------
frontend apiserver
    bind *:8443
    mode tcp
    option tcplog
    default_backend apiserver
#---------------------------------------------------------------------
# round robin balancing for apiserver
#---------------------------------------------------------------------
backend apiserver
    option httpchk GET /healthz
    http-check expect status 200
    mode tcp
    option ssl-hello-chk
    balance     roundrobin
        server k8s-master-1 192.168.1.40:6443 check
        server k8s-master-2 192.168.1.41:6443 check
        server k8s-master-3 192.168.1.42:6443 check

Guardar y salir del archivo

haproxy-kubeapiserver-linux

Ahora copie estos tres archivos (check_apiserver.sh, keepalived.conf y haproxy.cfg) de k8s-master-1 a k8s-master-2 y 3

Ejecute el siguiente bucle for para scp estos archivos para dominar 2 y 3

[[email protected] ~]$ for f in k8s-master-2 k8s-master-3; do scp /etc/keepalived/check_apiserver.sh /etc/keepalived/keepalived.conf [email protected]$f:/etc/keepalived; scp /etc/haproxy/haproxy.cfg [email protected]$f:/etc/haproxy; done

Nota: No olvide cambiar dos parámetros en el archivo keepalived.conf que discutimos anteriormente para k8s-master-2 y 3

En caso de que el firewall se esté ejecutando en los nodos maestros, agregue las siguientes reglas de firewall en los tres nodos maestros

$ sudo firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent
$ sudo firewall-cmd --permanent --add-port=8443/tcp
$ sudo firewall-cmd --reload

Ahora finalmente inicie y habilite el servicio keepalived y haproxy en los tres nodos maestros usando los siguientes comandos:

$ sudo systemctl enable keepalived --now
$ sudo systemctl enable haproxy --now

Una vez que estos servicios se inicien con éxito, verifique si VIP (IP virtual) está habilitado en el nodo k8s-master-1 porque hemos marcado k8s-master-1 como nodo MAESTRO en el archivo de configuración de keepalive.

vip-keepalived-kubernetes-linux

Perfecto, la salida anterior confirma que VIP se ha habilitado en k8s-master-1.

Paso 3) Deshabilite el intercambio, configure SELinux como permisivo y reglas de firewall para los nodos maestro y trabajador

Deshabilite el espacio de intercambio en todos los nodos, incluidos los nodos trabajadores. Ejecute los siguientes comandos

$ sudo swapoff -a 
$ sudo sed -i '/ swap / s/^(.*)$/#1/g' /etc/fstab

Establezca SELinux como Permisivo en todos los nodos maestros y trabajadores, ejecute los siguientes comandos,

$ sudo setenforce 0
$ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

Reglas de firewall para nodos maestros:

En caso de que el firewall se esté ejecutando en los nodos maestros, permita los siguientes puertos en el firewall,

Firewall-Ports-Master-nodes-kubernetes

Ejecute el siguiente comando firewall-cmd en todos los nodos maestros,

$ sudo firewall-cmd --permanent --add-port=6443/tcp
$ sudo firewall-cmd --permanent --add-port=2379-2380/tcp
$ sudo firewall-cmd --permanent --add-port=10250/tcp
$ sudo firewall-cmd --permanent --add-port=10251/tcp
$ sudo firewall-cmd --permanent --add-port=10252/tcp
$ sudo firewall-cmd --permanent --add-port=179/tcp
$ sudo firewall-cmd --permanent --add-port=4789/udp
$ sudo firewall-cmd --reload
$ sudo modprobe br_netfilter
$ sudo sh -c "echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables"
$ sudo sh -c "echo '1' > /proc/sys/net/ipv4/ip_forward"

Reglas de firewall para nodos de trabajo:

En caso de que el firewall se esté ejecutando en los nodos trabajadores, permita los siguientes puertos en el firewall en todos los nodos trabajadores

Firewall-puertos-Worker-Nodes-Kubernetes

Ejecute los siguientes comandos en todos los nodos trabajadores,

$ sudo firewall-cmd --permanent --add-port=10250/tcp
$ sudo firewall-cmd --permanent --add-port=30000-32767/tcp                                                   
$ sudo firewall-cmd --permanent --add-port=179/tcp
$ sudo firewall-cmd --permanent --add-port=4789/udp
$ sudo firewall-cmd --reload
$ sudo modprobe br_netfilter
$ sudo sh -c "echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables"
$ sudo sh -c "echo '1' > /proc/sys/net/ipv4/ip_forward"

Paso 4) Instale la ventana acoplable Container Run Time (CRI) en los nodos maestro y trabajador

Instale Docker (Container Run Time) en todos los nodos maestros y trabajadores, ejecute el siguiente comando,

$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce -y

Ejecute el siguiente comando systemctl para iniciar y habilitar el servicio docker (ejecute este comando también en todos los nodos maestros y trabajadores)

$ sudo systemctl enable docker --now

Ahora, instalemos kubeadm, kubelet y kubectl en el siguiente paso

Paso 5) Instale Kubeadm, kubelet y kubectl

Instale kubeadm, kubelet y kubectl en todos los nodos maestros, así como en los nodos trabajadores. Antes de instalar estos paquetes primero, debemos configurar el repositorio de Kubernetes, ejecutar el siguiente comando en cada nodo maestro y trabajador,

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

Ahora ejecute debajo del comando yum para instalar estos paquetes,

$ sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

Ejecute el siguiente comando systemctl para habilitar el servicio kubelet en todos los nodos (nodos maestros y trabajadores)

$ sudo systemctl enable kubelet --now

Paso 6) Inicialice el clúster de Kubernetes desde el primer nodo maestro

Ahora muévase al primer nodo maestro / plano de control y emita el siguiente comando,

[[email protected] ~]$ sudo kubeadm init --control-plane-endpoint "vip-k8s-master:8443" --upload-certs

En el comando anterior, –punto final del plano de control establezca el nombre de dns y el puerto para el balanceador de carga (kube-apiserver), en mi caso, el nombre de dns es «vip-k8s-master» y el puerto es «8443», aparte de esto ‘–upload-certsLa opción ‘ compartirá los certificados entre los nodos maestros automáticamente,

La salida del comando kubeadm sería algo como lo siguiente:

Kubeadm-success-ha-cluster

Genial, el resultado anterior confirma que el clúster de Kubernetes se ha inicializado correctamente. En la salida también obtuvimos los comandos para que otros nodos maestros y trabajadores se unan al clúster.

Nota: Se recomienda copiar este resultado en un archivo de texto para referencia futura.

Ejecute los siguientes comandos para permitir que el usuario local use el comando kubectl para interactuar con el clúster,

[[email protected] ~]$ mkdir -p $HOME/.kube
[[email protected] ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[[email protected] ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
[[email protected] ~]$

Ahora, implementemos la red de pod (CNI – Interfaz de red de contenedores), en mi caso voy a implementar el complemento calico como red de pod, ejecute el siguiente comando kubectl

[[email protected] ~]$ kubectl apply -f https://docs.projectcalico.org/v3.14/manifests/calico.yaml

Una vez que la red de módulos se haya implementado correctamente, agregue los dos nodos principales restantes al clúster. Simplemente copie el comando para que el nodo maestro se una al clúster desde la salida y péguelo en k8s-master-2 y k8s-master-3, el ejemplo se muestra a continuación.

[[email protected] ~]$ sudo kubeadm join vip-k8s-master:8443 --token tun848.2hlz8uo37jgy5zqt  --discovery-token-ca-cert-hash sha256:d035f143d4bea38d54a3d827729954ab4b1d9620631ee330b8f3fbc70324abc5 --control-plane --certificate-key a0b31bb346e8d819558f8204d940782e497892ec9d3d74f08d1c0376dc3d3ef4

La salida sería:

Master-2-Join-K8s-Cluster

También ejecute el mismo comando en k8s-master-3,

[[email protected] ~]$ sudo kubeadm join vip-k8s-master:8443 --token tun848.2hlz8uo37jgy5zqt  --discovery-token-ca-cert-hash sha256:d035f143d4bea38d54a3d827729954ab4b1d9620631ee330b8f3fbc70324abc5 --control-plane --certificate-key a0b31bb346e8d819558f8204d940782e497892ec9d3d74f08d1c0376dc3d3ef4

La salida sería:

Master-3-Join-K8s-Cluster

El resultado anterior confirma que k8s-master-3 también se unió al clúster con éxito. Verifiquemos el estado de los nodos desde el comando kubectl, vaya al nodo master-1 y ejecute el siguiente comando,

[[email protected] ~]$ kubectl get nodes
NAME           STATUS   ROLES    AGE     VERSION
k8s-master-1   Ready    master   31m     v1.18.6
k8s-master-2   Ready    master   10m     v1.18.6
k8s-master-3   Ready    master   3m47s   v1.18.6
[[email protected] ~]$

Perfecto, nuestros tres nodos del plano maestro o de control están listos y se unen al clúster.

Paso 7) Unir los nodos de trabajo al clúster de Kubernetes

Para unir nodos de trabajo al clúster, copie el comando para el nodo de trabajo de la salida y péguelo en ambos nodos de trabajo, el ejemplo se muestra a continuación:

[[email protected] ~]$ sudo kubeadm join vip-k8s-master:8443 --token tun848.2hlz8uo37jgy5zqt --discovery-token-ca-cert-hash sha256:d035f143d4bea38d54a3d827729954ab4b1d9620631ee330b8f3fbc70324abc5

[[email protected] ~]$ sudo kubeadm join vip-k8s-master:8443 --token tun848.2hlz8uo37jgy5zqt --discovery-token-ca-cert-hash sha256:d035f143d4bea38d54a3d827729954ab4b1d9620631ee330b8f3fbc70324abc5

La salida sería algo como a continuación:

trabajador-2-unirse-kubernetes-cluster

Ahora diríjase al nodo k8s-master-1 y ejecute debajo del comando kubectl para obtener los nodos trabajadores de estado,

[[email protected] ~]$ kubectl get nodes
NAME           STATUS   ROLES    AGE     VERSION
k8s-master-1   Ready    master   43m     v1.18.6
k8s-master-2   Ready    master   21m     v1.18.6
k8s-master-3   Ready    master   15m     v1.18.6
k8s-worker-1   Ready    <none>   6m11s   v1.18.6
k8s-worker-2   Ready    <none>   5m22s   v1.18.6
[[email protected] ~]$

El resultado anterior confirma que ambos trabajadores también se han unido al clúster y están listos.

Ejecute el siguiente comando para verificar los pods de infraestructura de estado que se implementan en el espacio de nombres del sistema kube.

[[email protected] ~]$ kubectl get pods -n kube-system

Kubernetes-infra-pods

Paso 8) Pruebe el clúster de Kubernetes de alta disponibilidad

Intentemos conectarnos al clúster desde una máquina remota (sistema CentOS) usando el nombre y el puerto del dns del equilibrador de carga. En la máquina remota primero, debemos instalar el paquete kubectl. Ejecute el siguiente comando para configurar los repositorios de kubernetes.

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

$ sudo yum install -y  kubectl --disableexcludes=kubernetes

Ahora agregue la siguiente entrada en el archivo /etc/host,

192.168.1.45   vip-k8s-master

Cree el directorio kube y copie el archivo /etc/kubernetes/admin.conf del nodo k8s-master-1 a $HOME/.kube/config ,

$ mkdir -p $HOME/.kube
$ scp [email protected]:/etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

Ahora ejecute el comando «kubectl get nodes»,

[[email protected] ~]$ kubectl get nodes
NAME           STATUS   ROLES    AGE    VERSION
k8s-master-1   Ready    master   3h5m   v1.18.6
k8s-master-2   Ready    master   163m   v1.18.6
k8s-master-3   Ready    master   157m   v1.18.6
k8s-worker-1   Ready    <none>   148m   v1.18.6
k8s-worker-2   Ready    <none>   147m   v1.18.6
[[email protected] ~]$

Vamos a crear una implementación con nombre nginx-lab con imagen ‘nginx‘ y luego exponga esta implementación como servicio de tipo «Puerto de nodo

[[email protected] ~]$ kubectl create deployment nginx-lab --image=nginx
deployment.apps/nginx-lab created
[[email protected] ~]$
[[email protected] ~]$ kubectl get deployments.apps nginx-lab
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-lab   1/1     1            1           59s
[[email protected] ~]$ kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
nginx-lab-5df4577d49-rzv9q   1/1     Running   0          68s
test-844b65666c-pxpkh        1/1     Running   3          154m
[[email protected] ~]$

Intentemos escalar las réplicas de 1 a 4, ejecute el siguiente comando,

[[email protected] ~]$ kubectl scale deployment nginx-lab --replicas=4
deployment.apps/nginx-lab scaled
[[email protected] ~]$
[[email protected] ~]$ kubectl get deployments.apps nginx-lab
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-lab   4/4     4            4           3m10s
[[email protected] ~]$

Ahora exponga la implementación como servicio, ejecute

[[email protected] ~]$ kubectl expose deployment nginx-lab --name=nginx-lab --type=NodePort --port=80 --target-port=80
service/nginx-lab exposed
[[email protected] ~]$

Obtenga detalles del puerto e intente acceder al servidor web nginx usando curl,

[[email protected] ~]$ kubectl get svc nginx-lab
NAME        TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-lab   NodePort   10.102.32.29   <none>        80:31766/TCP   60s
[[email protected] ~]$

Para acceder al servidor web nginx, podemos usar cualquier IP y puerto de nodo maestro o trabajador como «31766»

[[email protected] ~]$ curl http://192.168.1.44:31766

La salida sería algo como a continuación:

curl-nginx-servidor-kubernetes-cluster

Perfecto, eso confirma que hemos implementado con éxito un clúster de Kubernetes de alta disponibilidad con kubeadm en servidores CentOS 7. Por favor, no dude en compartir sus valiosos comentarios y opiniones.

Leer también : Cómo configurar el controlador de entrada NGINX en Kubernetes

Entradas relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *