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
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
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.
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,
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
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:
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:
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:
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:
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
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:
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