AWS EKS

Documentación aws eks

Configurar kubectl con cluster aws

Al crear un cluster por defecto se añade a kubectl automaticamente, en el caso de que no pase o se quiera acceder desde otro host, lanzar el siguiente comando

aws eks --region eu-west-2 update-kubeconfig --name first-eks

previamente se a de tener aws configurado.

Crear cluster aws eks

En eks se puede crear el cluster con el grupo de nodos directamente o por separado, el resultado es el mismo

Crear cluster con grupo de nodos.

eksctl create cluster \
--name first-eks \
--region eu-west-2 \
--nodegroup-name standard-nodes \
--node-type t3.medium \
--nodes 2 \
--nodes-min 2 \
--nodes-max 2 \
--ssh-access \
--ssh-public-key .ssh/id_rsa.pub \
--managed

Crear cluster

eksctl create cluster \
 --name test-cluster \
 --version auto \
 --without-nodegroup

Añadir nodos

eksctl create nodegroup \
--cluster test-cluster \
--version auto \
--name standard-workers \
--node-type t3.medium \
--node-ami auto \
--nodes 3 \
--nodes-min 1 \
--nodes-max 3 \
--asg-access

Ingress

En eks ingress controller necesita una serie de requisitos para poder desplegar loadbalancer's en aws, como serviceaccount, roles y una politica de aws. Si no se cumplen estos requisitos al tener el cluster dentro de aws, no se puede acceder a las aplicaciones desde el exterior.

En los siguientes pasos seguiré esta guia de requisitos que proporciona aws eks.

                                                +-------------+
                                                | internet    |
                            +--------------->   +-------------+
                            +
                    LoadBalancer aws
                 +------------------+          AWS
        +------------------------------------------------------------+
        |        |                  |                                |
        |        +------------------+                                |
        |                      ^                                     |
        |                      |                                     |
        |           Cluster    |                                     |
        |      +-------------------------------------------+         |
        |      |   ingress controler        ingress rules  |         |
        |      |  +-----------+           +---------+      |         |
        |      |  |           |  <--------+         |      |         |
        |      |  +-----------+           +---------+      |         |
        |      |                                           |         |
        |      |                                           |         |
        |      |                                           |         |
        |      |                                           |         |
        |      |                                           |         |
        |      |                                           |         |
        |      +-------------------------------------------+         |
        +------------------------------------------------------------+

Requisitos

Asociar la IAM al cluster

Esto es necesarió para asociar el usuario con el que se creará los loadbalancers en aws

eksctl utils associate-iam-oidc-provider \
    --region eu-west-2 \
    --cluster first-eks \
    --approve

Crear politica de aws

El tipo de permisos que aporta aws al ingres controller

curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json

aws iam create-policy \
    --policy-name ALBIngressControllerIAMPolicy \
    --policy-document file://iam-policy.json

Serviceaccount

Da permisos para la gestión dentro del cluster al controler

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml

Unir politica con service account

eksctl create iamserviceaccount \
    --region eu-west-2 \
    --name alb-ingress-controller \
    --namespace kube-system \
    --cluster first-eks \
    --attach-policy-arn arn:aws:iam::111122223333:policy/ALBIngressControllerIAMPolicy \
    --override-existing-serviceaccounts \
    --approve
  • el valor de attach-policy-arn se encuentra en IAM --> Policies --> buscar "ALBIngressControllerIAMPolicy" --> policy ARN

Ingress controler

Desplegar controller

Este paso se puede ejecutar directamente y luego editar, o descargar el archivo, editarlo y desplegar. ( da lo mismo )

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml

Editar deployment requerido

kubectl edit deployment.apps/alb-ingress-controller -n kube-system

    spec:
      containers:
      - args:
        - --ingress-class=alb
        - --cluster-name=first-eks
  • se tiene que añadir la línea - --cluster-name=first-eks debajo de - --ingress-class=alb

Ejemplo aplicación

Esto es un ejemplo de una aplicación que ejecuta el juego 2048 para probar que todo funciona.

Despliege de la aplicación

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-service.yaml

Crear un tunel al pod que a desplegado y acceder a la aplicación

kubectl port-fordward pod/2048-deployment-58fb54894c-7j6kp -n 2048-game 7000:80

firefox localhost:7000
  • Port-forward crea un tunel desde el puerto 80 del pod al puerto 7000 de mi host local. De esta manera compruebo que la aplicación funciona.

Exponer aplicacion con ingres aws

Ahora despliego las reglas del ingres y automaticamente se creara un LoadBalancer en AWS. Se puede comprobar en EC2 --> LoadBalancer

kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "2048-ingress"
  namespace: "2048-game"
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
  labels:
    app: 2048-ingress
spec:
  rules:
    - http:
        paths:
          - path: /*
            backend:
              serviceName: "service-2048"
              servicePort: 80

Acceder a la aplicación desde ingres

kubectl get ingress -n 2048-game
NAME          HOSTS   ADDRESS                                                                  PORTS
2048-ingres   *       d7fftr876-2048-gameingr-1478-467912149875.eu-west-2.elb.amazonaws.com    80 
  • d7fftr876-2048-gameingr-1478-467912149875.eu-west-2.elb.amazonaws.com es la direción dns pública que a creado el loadbalancer de aws.

Ver aplicación

firefox d7fftr876-2048-gameingr-1478-467912149875.eu-west-2.elb.amazonaws.com
  • Si se quiere cambiar la url, se tienen que gestionar el dns.

Eliminar aplicación y reglas de ingres

kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-ingress.yaml
kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-service.yaml
kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-deployment.yaml
kubectl delete -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/2048/2048-namespace.yaml

HPA

Horizontal pod autoescaler es un objeto que junto a un servidor de métricas, autoescala las replicas de una deployment según la cpu consumida en sus pods. Es decir si una app empieza a tener mucha carga de cpu, HPA basandose en la cpu consumida en los pods, empezará a replicar los pods para intentar desaogarlos.

Esto es muy útil en entornos de producción que en ciertas horas tienen picos de carga, ya que en horas puntas se replicaran los pods necesarios y en horas bajas, se eliminaran los que sobren.

Metric server

Para instalar el servidor de metrica kubernetes ya ofrece un template con todo lo necesario, solo se tiene que desplegar y verificar que funciona.

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.6/components.yaml

# verificar
kubectl get deployment metrics-server -n kube-system
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
metrics-server   1/1     1            1           6m

Probar HPA

Para probar el funcionamiento de HPA, es necesario que el deployment desplegado tenga un limite de recursos en cpu establecido, en el siguiente caso 200m que es un 0,2% de una cpu.

kubectl run httpd --image=httpd --requests=cpu=100m --limits=cpu=200m --expose --port=80

Para probar el HPA creo un autoescalado al deployment httpd de mínimo 1 pod y máximo 5 donde si los pods superan el 50% empezaran a replicarse.

kubectl autoscale deployment httpd --cpu-percent=50 --min=1 --max=5

Esto es un template de ejemplo que simula lo mismo que el comando anterior.

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: httpd
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: httpd
  minReplicas: 1
  maxReplicas: 5
  targetCPUUtilizationPercentage: 50

descripción de hpa

kubectl describe hpa httpd

Name:                                                  httpd
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Fri, 27 Sep 2019 13:32:15 -0700
Reference:                                             Deployment/httpd
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  1% (1m) / 50%
Min replicas:                                          1
Max replicas:                                          5
Deployment pods:                                       1 current / 1 desired
Conditions:
  Type            Status  Reason              Message
  ----            ------  ------              -------
  AbleToScale     True    ReadyForNewScale    recommended size matches current size
  ScalingActive   True    ValidMetricFound    the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  False   DesiredWithinRange  the desired count is within the acceptable range
Events:           <none>

Ahora despliego un deployment que empezara a hacer request al deployment anterior httpd y así aumentar la carga de cpu

kubectl run apache-bench -i --tty --rm --image=httpd -- ab -n 500000 -c 1000 http://httpd.default.svc.cluster.local/

Al empezar a recibir carga se puede ver que los pods superan el 50% de limite establecido de cpu y hpa empieza a desplegar replicas, hasta llegar al limit de 5 replicas desplegadas.

kubectl get hpa
NAME    REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
httpd   Deployment/httpd   76%/50%   1         5         5          4m50s

HPA hace consultas al servidor de metricas por defecto cada 15s, entre que calcula los datos y demas puede tardar entre 30s o 40s a empezar a desplegar nuevas replicas.

Ya hemos comprobado el aumento de replicas al subir la carga, ahora dejamos de mandar request para el proceso inverso ( eliminasr replicas ).

kubectl delete deployment.apps/httpd service/httpd horizontalpodautoscaler.autoscaling/httpd

HPA por defecto deja un timeout de 5m cuando la carga de cpu a bajado del límite establecido en este caso 50%, para prevenir futuras subidas, en caso de seguir 5m por debajo del 50% empieza a eliminar replicas.

kubectl get hpa
NAME    REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
httpd   Deployment/httpd   0%/50%    1         5         1          12m50s

Volumes

https://aws.amazon.com/es/premiumsupport/knowledge-center/eks-persistent-storage/

https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html

Cluster AutoScaler

documentación aws eks

Cluster AutoScaler añade o elimina nodos al cluster según los necesite, en el caso de que el cluster no tenga mas recursos para ejecutar pods, automaticamente añade otro nodo. En el caso contrario de que haya un nodo sin ser utilizado o desperdiciando recursos se movera el contenido a otro nodo y se eliminará el nodo.

En el autoescalado de un cluster siempre se asignara un mínimo y un máximo de nodos, que esto se indica en la creación del nodegroup del cluster.

En el desescalado de nodos autoescaler por defecto espera 10m para verificar que un nodo realmente no se esta utilizando, una vez que un nodo este 10m sin uso y haber echo su verificación, se paará a la eliminación del nodo.

Requisitos

Si has creado el cluster con eksctl y añadido la opción --asg-access en la creación del cluster, los requisitos para esta opción ya estan creados. En caso contrario seguir esta guia aws, que tendras que asignar unos tags y roles a los nodos.

Deplegar autoescaler

kubernetes ya nos proporciona el template con todo lo necesario para el despliegue de autoescaler, solo se tiene que lanzar las siguientes comandos y editar el template para añadir el nombre de nuestro cluster.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

kubectl -n kube-system annotate deployment.apps/cluster-autoscaler cluster-autoscaler.kubernetes.io/safe-to-evict="false"

Al editar el template se busca la siguiente sección y se remplaza <YOUR CLUSTER NAME> por el nombre del cluster, tabién se añade las siguientes líneas - --balance-similar-node-groups - --skip-nodes-with-system-pods=false para su correcto funcionamiento.

kubectl -n kube-system edit deployment.apps/cluster-autoscaler
    spec:
      containers:
      - command:
        - ./cluster-autoscaler
        - --v=4
        - --stderrthreshold=info
        - --cloud-provider=aws
        - --skip-nodes-with-local-storage=false
        - --expander=least-waste
        - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME>
        - --balance-similar-node-groups
        - --skip-nodes-with-system-pods=false

Eliminar cluster

Para eliminar un cluster, primero de todo es recomendable vaciarlo de todos los servicios, deployments, ... que contenga. Después se puede eliminar desde el navegador de aws o desde eksctl, si se elimina desde aws ir a la sección de stacks y eliminar siempre el stack de nodegroup primero, una vez haya finalizado eliminar el stack del cluster.

kubectl get svc --all-namespaces
kubectl delete svc service-name
eksctl delete cluster --name prod