Seamos sinceros, gestionar clústers de Kubernetes no es una tarea sencilla, incluso cuando se usan servicios 'gestionados'. Mantener la infraestructura, llevar a cabo los upgrades de los clústers y controlar la configuración de cada uno de ellos puede convertirse en un auténtico reto. La Infraestructura como código (IaC) es bastante útil en estos casos, con lenguajes declarativos como Terraform y CloudFormation. No obstante, el proceso de aprendizaje para este tipo de lenguajes puede ser bastante complejo para aquellos sin experiencia previa en IaC. Por ello, tiene bastante sentido el poder gestionar clústers de la misma forma en la que se gestionan los recursos de Kubernetes: con manifiestos y un CLI.

En este post, presentamos eksctl, un CLI para gestionar clústers de EKS en AWS desarrollado por Weaveworks. Eksctl está escrito en Go, utiliza una sintaxis similar a kubectl y se basa en CloudFormation para el despliegue y la gestión de la infraestructura. Además, la configuración de los clústers puede especificarse con ficheros yaml, habilitando el versionado de la infraestructura gracias a los sistemas de gestión de código fuente (SCM).
Al igual que en otros posts, se ha preparado un repositorio de ejemplo para que puedas probar eksctl con configuraciones existentes. Puedes encontrar el repositorio aquí.
Instalando eksctl 📥
Antes de instalar eksctl, necesitarás instalar el AWS CLI y el aws-iam-authenticator si no los tienes ya instalados en tu máquina. El aws-iam-authenticator se instala automáticamente a partir de la versión 1.16.156 o superior del AWS CLI, y es necesario para poder generar el token del Kubeconfig en base las IAM policies.
Una vez que hayas instalado estas dos herramientas, instala eksctl con los siguientes comandos. Si no estás utilizando Linux, puedes encontrar los comandos de instalación para tu SO en aquí.
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
Desplegando un clúster sencillo 🕹️
El siguiente código muestra un fichero de configuración empleado para generar un clúster de EKS con un único nodo. El clúster desplegado utiliza Kubernetes 1.17.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: simple-cluster
region: eu-west-1
version: '1.17'
nodeGroups:
- name: ng-1
instanceType: m5.large
desiredCapacity: 1
privateNetworking: true
availabilityZones: ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
labels: { tier: new }
Antes de desplegar, necesitarás configurar tus credenciales de AWS, utilizando el AWS CLI. Para ello, necesitarás un par de access key y secret key de AWS. Si no dispones de uno, puedes generarlo en la consola de IAM de AWS. Consulta la documentación oficial como referencia si lo necesitas.
aws configure
Ten en cuenta que el usuario al que se le asignen dichas claves de acceso debe tener permisos para crear la infraestructura. Para este ejemplo puedes utilizar la policy gestionada AdministratorAccess . Guarda bien el par de claves, y una vez que termines de probar estos ejemplos y este usuario no se vaya a utilizar de nuevo, elimínala, para evitar riesgos innecesarios.

Cuando hayas configurado tus credenciales, puedes empezar a utilizar eksctl. Al ejecutar el siguiente comando, eksctl comenzará a desplegar el clúster de EKS. Tómatelo con calma porque puede tardar un rato ⌛.
eksctl create cluster -f simple_cluster.yaml

Una vez que el clúster haya sido desplegado, eksctl actualizará automáticamente tu kubeconfig local y el contexto a utilizar por kubectl, de forma que apunten a este nuevo clúster.

Recuerda que la sintaxis de eksctl es bastante similar a la que emplea kubectl. Puedes probar a ejecutar los siguientes comandos. El último muestra las identidades IAM que se mapean al RBAC de Kubernetes en el clúster. Estas identidades se encuentran almacenadas en el ConfigMap aws-auth en el namespace kube-system .
eksctl get cluster --region eu-west-1
eksctl get nodegroup --cluster simple-cluster --region eu-west-1
eksctl get iamidentitymapping --cluster simple-cluster --region eu-west-1
Como se ha comentado anteriormente, eksctl utiliza CloudFormation para generar la infraestructura de AWS y los recursos. Por ello, si inspeccionas los stacks de CloudFormation podrás ver los diferentes recursos generados por eksctl durante el proceso de despliegue.

TRUQUILLO: Puedes obtener una visualización esquemática de la infraestructura desplegada por cada stack utilizando el AWS CloudFormation Designer. La siguiente imagen muestra los elementos creados por el stack del clúster.

Una vez que hayas acabado de jugar con tu clúster de EKS, elimínalo junto con los recursos asociados ejecutando el siguiente comando.
eksctl delete cluster -f simple_cluster.yaml
Configuración Avanzada ⚙️
En esta sección presentaremos ejemplos más complejos, con configuraciones y características propias de entornos productivos.
Autoescalado 🤖
Seleccionar el tamaño adecuado para un clúster no es siempre fácil, y como sabes, la carga computacional de un clúster fluctúa en el tiempo. eksctl puede utilizarse para escalar grupos de nodos cuando es necesario, pero es un proceso manual.
eksctl scale nodegroup --cluster=<cluster-name> --nodes=5 <nodegroup>
No obstante, el servicio de autoescalado de AWS puede ser de gran ayuda aquí, pues permite un uso más eficiente de los recursos, garantizando que se incremente o reduzca el número de nodos automáticamente cuando sea necesario. Fíjate en que las policies de IAM requeridas por el servicio de autoescalado para hacer llamadas a la API de AWS se especifican bajo la directiva iam.withAddonPolicies . Además, se indica el tamaño máximo y mínimo del grupo de autoescalado.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: as-cluster
region: eu-west-1
version: '1.17'
nodeGroups:
- name: ng-1
instanceType: m5.large
iam:
withAddonPolicies:
autoScaler: true
ebs: true
desiredCapacity: 1
minSize: 1
maxSize: 3
volumeSize: 50
labels: { role: workers }
privateNetworking: true
availabilityZones: ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
Crea el clúster ejecutando el siguiente domando.
eksctl create cluster -f asg_cluster.yaml
Una vez que el clúster esté funcionando, tendrás que desplegar el cluster autoscaler. Se trata de un componente que corre dentro del clúster como un deployment de Kubernetes y detecta si el número de nodos en el clúster es el adecuado para servir a todas la aplicaciones y servicios definidos, escalando cuando es necesario.
El siguiente comando despliega el cluster autoscaler en el clúster de Kubernetes. Ten en cuenta que el cluster autoscaler necesita conocer el nombre del clúster para poder actuar sobre el mismo. El deployment presente en el manifiesto autoscaler_basic.yaml ha sido configurado para funcionar dentro de este mismo clúster. Por ello, solo tendrás que ejecutar el siguiente comando sin ninguna configuración adicional para hacer que el cluster autoscaler comience a funcionar.
kubectl apply -f autoscaler_basic.yaml
Si todo ha ido bien, deberías ser capaz de ver el pod del cluster autoscaler corriendo en el namespace kube-system .

Prueba tu nuevo autoscaler! Primero verifica que tu clúster utiliza un único nodo tal y como especifica la directiva desiredCapacity: 1 en el fichero de configuración.

Ahora es el momento de darle caña al clúster desplegando muchas réplicas de nginx.
kubectl create deployment nginx --image nginx
kubectl scale deployment nginx --replicas 70
Si compruebas el estado de los pods segundos después de ejecutar el comando anterior, verás que varios se quedan en el estado Pending . Dale unos minutos al cluster autoscaler para obrar su magia 🧙 y verás como se añaden nuevos nodos a tu clúster!

Si borras el deployment de nginx y todas sus réplicas asociadas, y esperas unos minutos, podrás ver como el cluster autoscaler reduce el número de nodos.
kubectl delete deployment nginx
Una vez que hayas acabado de jugar con tu clúster de EKS, elimínalo junto con los recursos asociados ejecutando el siguiente comando.
eksctl delete cluster -f asg_cluster.yaml
Logging en el clúster 📝
El plano de control de Kubernetes está formado por diferentes componentes y sus logs son bastante útiles, especialmente para procesos de depuración y troubleshooting. El logging del plano de control se puede activar utilizando la directiva clusterLogging dentro de la sección cloudWatch . El siguiente ejemplo activa la recogida de logs de todos los elementos del plano de control por parte de CloudWatch.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: logging-cluster
region: eu-west-1
nodeGroups:
- name: ng-1
instanceType: m5.large
desiredCapacity: 2
cloudWatch:
clusterLogging:
enableTypes: ["audit", "authenticator", "scheduler", "api", "controllerManager"]
# enableTypes: ["*"]
Crea tu clúster con el logging del plano de control activado.
eksctl create cluster -f logging_cluster.yaml
Una vez que el clúster se haya desplegado, si compruebas los logs de CloudWatch, podrás ver las diferentes entradas de los componentes del plano de control.

Limpia todo una vez que hayas chequeado los logs.
eksctl delete cluster -f logging_cluster.yaml
Node groups y cosas chulas 😎
Vamos a desplegar ahora algo más interesante ¿Qué tal algo así como un clúster con múltiples node groups de forma que diferentes despliegues corran en el node group más apropiado? ¿Y si añadimos spot instances para aquellos procesos 'batch' que son menos prioritarios? Añadamos también claves SSH para conectarnos a los workers, así como diferentes IAM policies.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: multi-cluster
region: eu-west-1
nodeGroups:
- name: ng-1
instanceType: m5.large
iam:
withAddonPolicies:
imageBuilder: true
autoScaler: true
externalDNS: true
ebs: true
efs: true
albIngress: true
cloudWatch: true
desiredCapacity: 1
minSize: 1
maxSize: 3
volumeSize: 50
labels: { role: workers }
privateNetworking: true
ssh:
publicKeyPath: ~/.ssh/eksctl_pub
availabilityZones: ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
- name: ng-2
instanceType: m5.large
iam:
withAddonPolicies:
imageBuilder: true
autoScaler: true
externalDNS: true
ebs: true
efs: true
albIngress: true
cloudWatch: true
desiredCapacity: 2
minSize: 1
maxSize: 3
volumeSize: 100
labels: { role: builders }
privateNetworking: true
ssh:
publicKeyPath: ~/.ssh/eksctl_pub
availabilityZones: ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
- name: ng-3
minSize: 1
maxSize: 2
labels: { role: ephemeral-workers}
volumeSize: 50
ssh:
publicKeyPath: ~/.ssh/eksctl_pub
iam:
withAddonPolicies:
imageBuilder: true
autoScaler: true
externalDNS: true
ebs: true
efs: true
albIngress: true
cloudWatch: true
instancesDistribution:
maxPrice: 0.017
instanceTypes: ["t3.small", "t3.medium"] # At least one instance type should be specified
onDemandBaseCapacity: 0
onDemandPercentageAboveBaseCapacity: 50
spotInstancePools: 2
Crea tu nuevo clúster super potente 😄.
eksctl create cluster -f multi_ng_cluster.yaml
Si todo va bien, deberías poder ver tres node groups diferentes, corriendo un total de 4 workers. Tómate tu tiempo para investigar el nuevo clúster, y recuerda que si quieres conectarte por SSH a los nodos, deberás permitir el tráfico al entrante al puerto 22 en Security Group de los workers.

No te olvides de borrar el clúster una vez que hayas acabado de curiosear.
eksctl delete cluster -f multi_ng_cluster.yaml
TRUQUILLO: Si estás pensando en correr procesos en spot instances, ten en cuenta la posibilidad de desplegar el AWS Node Termination Handler en tu clúster, ya que se encarga de reasignar los procesos que corren spot instances cuando van a ser terminados, para minimizar posibles indisponibilidades en el servicio.
Subiendo de Versión 🆕
Por último, veamos como llevar a cabo un upgrade del clúster utilizando ekscl. Para ello, desplegaremos un clúster sencillo con la versión 1.16 de Kubernetes, y posteriormente subiremos de versión utilizando un fichero de configuración diferente. Fíjate en que los node groups de cada fichero de configuración tienen un nombre diferente.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: simple-cluster-upgrade
region: eu-west-1
version: '1.16'
nodeGroups:
- name: ng-1-pre-upg
instanceType: m5.large
desiredCapacity: 1
privateNetworking: true
availabilityZones: ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
labels: { tier: old }
En primer lugar, crea el clúster de EKS con la versión 1.16, y verifica la versión.
eksctl create cluster -f upgrade_cluster.yaml

Ahora, subamos el clúster de versión. El siguiente comando genera el plan de upgrade para el plano de control, y muestra las operaciones a realizar.
eksctl upgrade cluster --config-file simple_cluster.yaml

Si el plan tiene buena pinta, ejecuta el siguiente comando añadiendo el flag –approve y espera que eksctl termine de actualizar el plano de control ⌛😴☕.
eksctl upgrade cluster --approve --config-file simple_cluster.yaml
Lo siguiente es actualizar los workers. Para ello, crea un nuevo node group utilizando el fichero simple_cluster.yaml.
eksctl create nodegroup --config-file simple_cluster.yaml
Ahora, verás que el clúster dispone de dos nodos con versiones de Kubernetes diferentes. Con esta estrategia, puedes migrar tus aplicaciones desde los nodos antiguos a los nuevos reduciendo los posibles cortes de servicio durante el proceso de actualización

Una vez que el nuevo node group esté listo (y en el caso de un escenario productivo, las aplicaciones migradas), elimina el node group antiguo.
eksctl delete nodegroup --approve --config-file upgrade_cluster.yaml --only-missing
Termina actualizando los add-ons por defecto del clúster. Los siguientes comandos actualizan kube-proxy, coreDNS y aws-node a la versión asociada a la nueva versión del clúster.
eksctl utils update-kube-proxy --approve --config-file simple_cluster.yaml
eksctl utils update-aws-node --approve --config-file simple_cluster.yaml
eksctl utils update-coredns --approve --config-file simple_cluster.yaml

Y voilà, tu clúster está funcionando con Kubernetes 1.17!

Por último, haz limpieza y elimina el clúster.
eksctl delete cluster -f simple_cluster.yaml
Sigue aprendiendo👩💻👨💻
Si te ha gustado eksctl, tómate tu tiempo para investigar dentro del repositorio de ejemplos, ya que encontrarás multitud de casos de uso interesantes. También te recomiendo que visites la Página de Github de Weaveworks, ya que encontrarás otros proyectos y herramientas de DevOps muy útiles para seguir aprendiendo.
Otros Artículos
Karpenter vs Cluster Autoscaler ☸️ ⚒️
Getting the size of a Kubernetes cluster right is not an easy task, if the number of nodes provisioned is too high, resources might be…
Read MoreAutenticación a nivel de clúster para tus registries privados 🌐🔐
Using private container image registries is a common practice in the industry, as it ensures applications packaged within the images are just accessible for users…
Read MoreKaniko: construyendo imágenes sin Docker🐳🔫
Building container images is a pretty common stage within the modern CI flows, in which these images are the main artifact used to distribute and…
Read MoreKubernetes en 5 Minutos ⏱️☸️
English https://www.youtube.com/watch?v=N8LDO9pHY8I Spanish https://www.youtube.com/watch?v=TC6VkqQ835U Other Articles
Read MoreKsniff: capturando tráfico en Kubernetes 🕵️♂️📦
Troubleshooting containers in Kubernetes is a recurring topic that you may face regularly. Logging and monitoring tools come in really handy here as they help…
Read MoreHelmfile: superpoderes para Helm ☸️🔧
Helm is definitely one the most used tools in the Kubernetes world. It comes in pretty handy as it is a deployment tool, a package…
Read MoreTerraboard: Gestionando estados de Terrafom visualmente🌍🖥
Dealing with multiple terraform remote states can become a rather complex task. Besides, querying resources with terraform CLI isn’t very visual 😅. In this post…
Read Moreeksctl: el CLI para EKS ☸️ 🎮
Let’s be honest, managing Kubernetes clusters is not an easy task, even when it comes to managed Kubernetes services. Controlling the overall infrastructure, performing cluster…
Read MoreWerf: GitOps totalmente customizable 🛥️⚙️
This is the third post of a collection of GitOps tools articles. In this post, a continuous integration and continuous deployment tool for Kubernetes is…
Read More