Creación de un cluster en EKS (II)
Creación del cluster
Creación de claves de EC2
Elastic Kubernetes Service
permite acceder por SSH a las instancias de EC2 creadas al crear el cluster, pero para ello es necesario asociarles un par de claves pública/privada. En realidad, funciona igual que al crear cualquier instancia normal y corriente de EC2.
La clave debe existir previamente a la creación del cluster y ser usada al crearlo. Si no se hace así, no se podrá acceder nunca a las instancias de los nodos.
El par de claves no está ligado a ningún recurso en particular – y se puede usar en varios, de hecho. Para crearlo, hay que seguir estas instrucciones.
Básicamente se trata de:
- Entrar en la consola de EC2
- Ir a
Network & Security / Key Pairs / Create pair
- Darle un nombre significativo y clarificador
- Elegir el formato:
pem
(preferible) oppk
- Y exportarlo
El formato no es problema, porque se puede convertir el fichero de uno a otro, con herramientas como PuttyGen.
Crear el cluster
Tan sencillo como definir un YAML con su configuración:
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: mycluster region: eu-west-1 version: "1.15" managedNodeGroups: - name: mng-1 instanceType: m5.large desiredCapacity: 1 minSize: 1 maxSize: 3 ssh: publicKeyName: 'k8s-key' # El nombre de la key creada antes iam: withAddonPolicies: autoScaler: true
Hay muchísimos ejemplos de configuraciones de clusters en el repositorio de ekstcl
en GitHub.
Y para crearlo:
eksctl create cluster -f k8s-cluster.yaml
El resultado será algo como esto:
[ℹ] eksctl version 0.15.0 [ℹ] using region eu-west-1 [ℹ] setting availability zones to [eu-west-1b eu-west-1a eu-west-1c] [ℹ] subnets for eu-west-1b - public:192.168.0.0/19 private:192.168.96.0/19 [ℹ] subnets for eu-west-1a - public:192.168.32.0/19 private:192.168.128.0/19 [ℹ] subnets for eu-west-1c - public:192.168.64.0/19 private:192.168.160.0/19 [ℹ] using EC2 key pair "k8s-key" [ℹ] using Kubernetes version 1.15 [ℹ] creating EKS cluster "mycluster" in "eu-west-1" region with managed nodes [ℹ] 1 nodegroup (mng-1) was included (based on the include/exclude rules) [ℹ] will create a CloudFormation stack for cluster itself and 0 nodegroup stack(s) [ℹ] will create a CloudFormation stack for cluster itself and 1 managed nodegroup stack(s) [ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=eu-west-1 --cluster=mycluster' [ℹ] CloudWatch logging will not be enabled for cluster "mycluster" in "eu-west-1" [ℹ] you can enable it with 'eksctl utils update-cluster-logging --region=eu-west-1 --cluster=mycluster' [ℹ] Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "mycluster" in "eu-west-1" [ℹ] 2 sequential tasks: { create cluster control plane "mycluster", create managed nodegroup "mng-1" } [ℹ] building cluster stack "eksctl-mycluster-cluster" [ℹ] deploying stack "eksctl-mycluster-cluster" [ℹ] building managed nodegroup stack "eksctl-mycluster-nodegroup-mng-1" [ℹ] deploying stack "eksctl-mycluster-nodegroup-mng-1" [✔] all EKS cluster resources for "mycluster" have been created [✔] saved kubeconfig as "C:\Users\alpinazo/.kube/config" [ℹ] nodegroup "mng-1" has 1 node(s) [ℹ] node "ip-192-168-xxx-xxx.eu-west-1.compute.internal" is ready [ℹ] waiting for at least 1 node(s) to become ready in "mng-1" [ℹ] nodegroup "mng-1" has 1 node(s) [ℹ] node "ip-192-168-xxx-xxx.eu-west-1.compute.internal" is ready [ℹ] kubectl command should work with "C:\Users\alpinazo/.kube/config", try 'kubectl get nodes' [✔] EKS cluster "mycluster" in "eu-west-1" region is ready
Administración del cluster
Conectar con el cluster tras haberlo creado
La configuración local de kubectl se guarda en el fichero C:\Users\<usuario>\.kube\config
(Windows) o en ~/.kube/.config
(Unix).
La creación del cluster con eksctl habrá creado un modificado la configuración local de Kubenetes, para añadir el acceso al nuevo cluster; y kubectl queda configurado ya para acceder por defecto al cluster de EKS.
Se puede ver cómo se ha añadido el nuevo cluster a la lista de los configurados:
$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO docker-desktop docker-desktop docker-desktop docker-for-desktop docker-desktop docker-desktop * myuser@mycluster.eu-west-1.eksctl.io mycluster.eu-west-1.eksctl.io myuser@mycluster.eu-west-1.eksctl.io
Y se puede cambiar de contexto para conectar con otro cluster, por ejemplo el docker-desktop que tuviéramos en local.
Obviamente, cuando queramos trabajar con el que hemos creado en EKS, cambiaremos el contexto para conectarnos a él:
Conectar con un cluster ya existente
Si se trata de conectar con un EKS que ya fue creado anteriormente desde un lugar diferente a nuestro local – como el local de otra persona o desde la consola web de EKS – hay que descargar a la configuración local las credenciales de ese cluster.
Por suerte es algo muy fácil de hacer con AWS CLI:
aws eks --region region update-kubeconfig --name cluster_name
AWS CLI debe estar configurado con las credenciales del dueño del cluster.
Autoescalado del cluster
El ASG
(Auto Scaling Group) – gestiona el escalado del propio cluster. Es decir, es el responsable de que se añadan más nodos al cluster, cuando ya no haya recursos suficientes para crear más pods.
El primer paso fue configurar el cluster para soportar autoscalado con eksctl, como se indicó en su YAML, definiendo que los nodos fueran gestionados.
Pero ahora hay que crear el ASG para el cluster y hay que hacerlo a mano, siguiendo las instrucciones, en la sección Deploy the Cluster Autoscaler
.
Primero se despliegue el autoscaler en el cluster:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
Luego se le añade la anotación safe-to-evict
:
kubectl -n kube-system annotate deployment.apps/cluster-autoscaler cluster-autoscaler.kubernetes.io/safe-to-evict="false"
Después se edita el despliegue del autoscaler para adecuarlo a nuestro cluster:
kubectl -n kube-system edit deployment.apps/cluster-autoscaler
Ese comando abrirá nuestro editor de texto por defecto con el contenido del yaml del despliegue del autoscaler.
Tenemos que reemplazar el texto <YOUR CLUSTER NAME>
por el nombre de nuestro cluster. Y justo debajo, añadir las líneas:
--balance-similar-node-groups --skip-nodes-with-system-pods=false
Conviene ver el ejemplo en la documentación de Amazon EKS.
Servidor de métricas
Para que puedan autoescalar, es necesario instalar Metrics Server
, que recoge métricas de consumo de CPU y memoria de cada pod. Éstas son usadas posteriormente para contrastarlas con las definiciones de los límites de recursos definidos en los despliegues de los pods.
Creación de un cluster en EKS (I)
Introducción
Elastic Kubernetes Service
(EKS) es el servicio de Amazon para la creación y gestión de clusters de Kubernetes en AWS.
Hay una guía muy completa en el EKS Workshop, aunque no me ha resultado útil. Está todo muy orientado a los ejemplos del taller, pero las explicaciones que se dan no encajan bien con las necesidades reales de un proyecto, cuando se quiere crear un cluster desde cero.
Sin embargo sí me ha convencido la guía oficial de Amazon EKS. He seguido sus pasos cuando he tenido que crear un cluster y me ha ido muy bien. Es cierto que es una guía un poco densa a veces y otras, falta algo de información. Pero investigando un poco, todo se saca.
Vamos al lío. En EKS, un cluster se puede crear:
- Desde la consola de EKS: es visual pero, inesperadamente, bastante tedioso y lioso de hacer
- Usando eksctl: usando comandos, pero más fácil ya que permite usar configuraciones
YAML
para definir el cluster y crea automáticamente todos los recursos de AWS necesarios
Por la sencillez de uso y lo estandarizado de la solución, he encontrado que me es mejor usar eksctl.
Decisiones previas
Estudiar los recursos necesarios
Es muy importante dimensionar correctamente el cluster, para no gastar de más y para no quedarnos cortos. Cuando creemos el cluster, se asignará una instancia EC2 a cada nodo, del tipo que hayamos elegido, pero no la podremos cambiar más adelante. Por eso es muy importante decidir bien en este paso. No obstante, si por lo que fuera nos quedáramos cortos, siempre se puede escalar horizontalmente el cluster, añadiendo más nodos.
Hay un par de cosas fundamentales para para dimensionar la instancia de EC2 adecuada para sus nodos:
- Medir la RAM y CPU que usarán las aplicaciones a desplegar en el cluster, contando con el número total de instancias de cada una
- Contar con lo que consumirá
kubelet
, el sistema operativo y otras aplicaciones
Estudiado eso, elegir una instancia del catálogo de EC2.
Versión del cluster
Siempre es buena idea usar una versión tan alta como sea posible. Así retardaremos el problema de quedarnos desfasados. Pero tampoco hay que pasarse; se elegimos la última versión, puede que las herramientas que necesitemos todavía no estén actualizadas y no sean compatibles.
A día de hoy, la mejor opción es la versión 1.15
. Además, desde marzo del 2020, Amazon EKS la soporta oficialmente.
Valores por defecto
Interesa que el grupo de nodos sea gestionado – managed.
Que sea gestionado es necesario para el autoescalado.
Instalar eksctl
Conceptos
eksctl es la herramienta oficial de AWS que se usa para gestionar clusters de EKS. Su uso se explica profusamente en esta guía.
eksctl permite predefinir configuraciones completas de clusters usando YAML y crear un cluster a partir de ellas, de forma trivial; creando además todos los recursos necesarios en AWS, tales como VPCs, roles, permisos, subredes, instancias de EC2, reglas…
También se crea un EKS Control Plane
, que es una máquina virtual dedicada a ejercer de nodo master del cluster; y tiene un coste, claro.
Instalación de Chocolatey
Para Windows es muy conveniente instalar Chocolatey
para poder instalar eksctl. Vale con seguir estas instrucciones.
Instalación de eksctl con Chocolatey
Ahora hay que instalar aws-iam-authenticator
, la herramienta que se va a integrar con el AWS CLI que ya tenemos configurado en local, para poder crear los roles IAM necesarios para EKS y, posteriormente, conectarse con él. En la misma PowerShell de la instalación de Chocolatey, ejecutamos:
chocolatey install -y eksctl aws-iam-authenticator
La versión que instala es la 0.15.0
y en la documentación dicen que tiene que ser la 0.16.0-rc.1
; sin embargo no he tenido ningún problema durante todo el proceso de creación y gestión del cluster.
Jugando con Amazon ECR
Introducción
Elastic Container Registry
– ECR – es el servicio de registro y repositorio de imágenes Docker propio de Amazon.
ECR se puede usar desde dentro de medios de Amazon, como EC2 o EKS. Y también desde fuera, con Docker CLI. Pero en todos los casos, el acceso a ECR se hace usando un token de autorización.
Requisitos previos
El primer requisito es crear un usuario con permisos, como se indica en la primera parte de la guía oficial. Después, conviene tener instaladas las herramientas de la AWS CLI, ya que los usaré en este artículo.
Creación de un repositorio
Usando la consola de ECR
Un repositorio es el lugar donde se van a guardar todas las versiones y etiquetas (tags) de una misma imagen. Es decir, hay una correspondencia uno a uno entre repositorio y aplicación contenerizada.
Se pueden usar separaciones con /
en el nombre de los repositorios, para crear jerarquías y espacios de nombres. En la consola de AWS, en la sección Servicios
, buscamos por ECR
:
Esto abre la consola de administración de ECR. Ahora, pulsamos en Create repository
y completamos el formulario que se abre:
Hecho eso, se habrá creado un repositorio nuevo. Podemos configurar si:
- Se van a escanear las imágenes nueva cada vez que se suban
- Se permite o prohíbe sobreescribir las imágenes con un tag
Sobreescribir imágenes con tag rompe el versionado de aplicaciones. Debería permitirse únicamente, si acaso, durante el desarrollo y pruebas iniciales de una misma versión.
La URI del repositorio es la que se usará para hacer login en él. Se compone del campo Account de la identidad de la cuenta, de la zona y del nombre del repositorio.
Usando AWS CLI
Si tenemos AWS CLI instalado, usarlo para esto es muy sencillo. Por ejemplo, para crear el repo myapps/redisen Irlanda:
aws ecr create-repository \ --repository-name myapps/redis \ --image-scanning-configuration scanOnPush=true \ --region eu-west-1
Eliminación de un repositorio
Eliminar un repositorio provoca la eliminación de todas las imágenes que contiene.
Usando la consola
Es trivial. Sólo hay que entrar en la consola, marcar el repositorio y pulsar en Delete
.
Usando AWS CLI
Sería tan sencillo como esto:
aws ecr delete-repository \ --repository-name myapps/redis \ --force
También se puede eliminar una imagen y tag concretos:
aws ecr batch-delete-image \ --repository-name myapps/redis \ --image-ids imageTag=1.0.0
Uso del repositorio con Docker CLI
Un repositorio de imágenes de ECR es como otro cualquiera. Para usarlo hay que:
- Hacer login en él con Docker
- Etiquetar las imágenes con la URI del repositorio, para poder subirlas a él
- Usar esa URI, para poder descargarlas
Login en ECR
Para hacer login, hay que obtener un token de acceso general a ECR que da AWS para el usuario configurado en AWS CLI. Después, se hace un login normal y corriente con Docker CLI.
En Linux, o Windows con una shell Linux (como GitBash
):
aws --region <region> ecr get-login-password \
| docker login \
--password-stdin \
--username AWS "<account>.dkr.ecr.<region>.amazonaws.com/<repo>"
En Windows con CMD:
C:\> aws --region <region> ecr get-login-password eyJwYXlsb2FkIjoiTWYrY0F0NVl...etc, etc... C:\> docker login --password-stdin <el token de antes> --username AWS "<account>.dkr.ecr.<region>.amazonaws.com/<repo>"
No es necesario usar --region
pero sí puede serlo si tenemos ECRs creados en varias regiones.
Hecho el login, Docker queda configurado ya para poder utilizarlo.
Si al hacer login da un error 400 Bad Request, puede ser por lo siguiente:
- No hemos indicado la región cuando sí que hacía falta
- La URI del repo está mal, por ejemplo porque no esté indicado el nombre del repo
- El id de la cuenta no sea correcto o no sea el adecuado
Subida de imágenes
Se hace de forma convencional, etiquetando la imagen usando la URI del repositorio. Por ejemplo, si tenemos la imagen redis
en local, primero la etiquetamos para usar el repositorio que tenga asociado, es decir, a donde la queremos subir:
docker tag redis:latest <account>.dkr.ecr.<region>.amazonaws.com/myapps/redis:latest
Donde myapps/redis
es el repositorio en ECR.
El repositorio debe existir previamente y no se crea automáticamente, sólo a mano como antes.
Ahora, para subir la imagen:
docker push <account>.dkr.ecr.<region>.amazonaws.com/myapps/redis:latest
Descarga de imágenes
Funciona exactamente igual que siempre. En nuestro ejemplo, sería así:
docker pull <account>.dkr.ecr.<region>.amazonaws.com/myapps/redis:latest
Eliminación de imágenes
Se puede hacer tanto desde la consola de ECR como por línea de comandos. En el ejemplo, sería ejecutando:
aws ecr batch-delete-image \ --repository-name myapps/redis \ --image-ids imageTag=latest