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 enIAM --> 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
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