Kops desde 0, nuestro cluster de kubernetes en AWS
Introducción
En este artículo crearemos un clúster desde cero con kops (instalación, actualizaciones y gestión de K8s) en AWS. Configuraremos aws-alb-ingress-controller (tráfico externo hacia nuestros servicios/pods) y external dns (actualizar los registros basados en las reglas de ingreso) y también aprenderemos un poco sobre awscli en el proceso.
Básicamente, tendremos un clúster completamente funcional que podrá manejar tráfico público en minutos. Primero instalaremos el clúster con kops, luego habilitaremos el controlador de ingreso y finalmente external-dns. Después, implementaremos una aplicación básica para probar que todo funcione correctamente. SSL/TLS está fuera del alcance, pero es bastante fácil de implementar si estás usando ACM.
Por si no lo sabías, esta configuración no será gratuita; será económica seguro porque usaremos instancias pequeñas, etc., pero no completamente gratis. Así que antes de comenzar, asegúrate de que puedes gastar unos cuantos dólares probándolo.
Kops
Esta es una herramienta increíble para configurar y mantener tus clústeres, actualmente solo compatible con AWS y GCE. Se planean otras plataformas y algunas también son compatibles en alfa. Usaremos AWS en este ejemplo; requiere kubectl, así que asegúrate de tenerlo instalado:
curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
chmod +x kops-linux-amd64
sudo mv kops-linux-amd64 /usr/local/bin/kops
Exporta las credenciales que usaremos para crear el usuario y las políticas de kops
export AWS_ACCESS_KEY_ID=XXXX && export AWS_SECRET_ACCESS_KEY=XXXXX
Puedes hacerlo de esta manera o simplemente usar aws configure
y configurar un perfil.
Lo siguiente que necesitamos son credenciales IAM para que kops funcione. Necesitarás awscli configurado y funcionando con tu cuenta de tipo administrador de AWS antes de continuar:
# Create iam group
aws iam create-group --group-name kops
# OUTPUT:
# {
# "Group": {
# "Path": "/",
# "GroupName": "kops",
# "GroupId": "AGPAIABI3O4WYM46AIX44",
# "Arn": "arn:aws:iam::894527626897:group/kops",
# "CreateDate": "2019-01-18T01:04:23Z"
# }
# }
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonRoute53FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --group-name kops
aws iam attach-group-policy --policy-arn arn:aws:iam::aws:policy/IAMFullAccess --group-name kops
# Attach policies
aws iam create-user --user-name kops
aws iam add-user-to-group --user-name kops --group-name kops
# OUTPUT:
# {
# "Group": {
# "Path": "/",
# "GroupName": "kops",
# "GroupId": "AGPAIABI3O4WYM46AIX44",
# "Arn": "arn:aws:iam::894527626897:group/kops",
# "CreateDate": "2019-01-18T01:04:23Z"
# }
# }
# Create access key - save the output of this command.
aws iam create-access-key --user-name kops
# OUTPUT:
# {
# "AccessKey": {
# "UserName": "kops",
# "AccessKeyId": "AKIAJE*********",
# "Status": "Active",
# "SecretAccessKey": "zWJhfemER**************************",
# "CreateDate": "2019-01-18T01:05:44Z"
# }
# }
El último comando generará la clave de acceso y la clave secreta para el usuario kops, guarda esa información porque la utilizaremos de ahora en adelante. Ten en cuenta que le dimos mucho poder a kops con ese usuario, así que ten cuidado con las claves.
Permisos adicionales para poder crear ALBs
cat << EOF > kops-alb-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"iam:CreateServiceLinkedRole",
"tag:GetResources",
"elasticloadbalancing:*"
],
"Resource": [
"*"
]
}
]
}
EOF
aws iam create-policy --policy-name kops-alb-policy --policy-document file://kops-alb-policy.json
# OUTPUT:
# {
# "Policy": {
# "PolicyName": "kops-alb-policy",
# "PolicyId": "ANPAIRIYZZZTCPJGNZZXS",
# "Arn": "arn:aws:iam::894527626897:policy/kops-alb-policy",
# "Path": "/",
# "DefaultVersionId": "v1",
# "AttachmentCount": 0,
# "PermissionsBoundaryUsageCount": 0,
# "IsAttachable": true,
# "CreateDate": "2019-01-18T03:50:00Z",
# "UpdateDate": "2019-01-18T03:50:00Z"
# }
# }
cat << EOF > kops-route53-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
EOF
aws iam create-policy --policy-name kops-route53-policy --policy-document file://kops-route53-policy.json
# OUTPUT:
# {
# "Policy": {
# "PolicyName": "kops-route53-policy",
# "PolicyId": "ANPAIEWAGN62HBYC7QOS2",
# "Arn": "arn:aws:iam::894527626897:policy/kops-route53-policy",
# "Path": "/",
# "DefaultVersionId": "v1",
# "AttachmentCount": 0,
# "PermissionsBoundaryUsageCount": 0,
# "IsAttachable": true,
# "CreateDate": "2019-01-18T03:15:37Z",
# "UpdateDate": "2019-01-18T03:15:37Z"
# }
# }
Ten en cuenta que, aunque acabamos de crear estas políticas de kops para alb y route53, no podemos agregarlas ahora mismo. Primero necesitamos crear el clúster. Puedes omitir este paso si no planeas usar estos recursos.
Ahora también exportaremos o configuraremos el nombre del clúster y el almacén de estado de kops como variables de entorno
export NAME=k8s.techsquad.rocks
export KOPS_STATE_STORE=techsquad-cluster-state-store
Usaremos estas variables en varios lugares, así que para no repetirnos es mejor tenerlas como variables de entorno.
Crear la zona para el subdominio en Route53
ID=$(uuidgen) && aws route53 create-hosted-zone --name ${NAME} --caller-reference $ID | jq .DelegationSet.NameServers
# OUTPUT:
# [
# "ns-848.awsdns-42.net",
# "ns-12.awsdns-01.com",
# "ns-1047.awsdns-02.org",
# "ns-1862.awsdns-40.co.uk"
# ]
Como ya estoy utilizando este dominio para el blog con GitHub, podemos crear un subdominio y añadir algunos registros NS en nuestra zona raíz para ese subdominio, en este caso k8s.techsquad.rocks. Para que sea más fácil, te mostraré cómo debería verse: Con este cambio y nuestra nueva zona en Route53 para el subdominio, podemos gestionarlo libremente como si fuera otro dominio. Esto significa que todo lo que vaya a *.k8s.techsquad.rocks será manejado por nuestra zona en Route53.
Crear un bucket para almacenar el estado del clúster
aws s3api create-bucket \
--bucket ${KOPS_STATE_STORE} \
--region us-east-1
# OUTPUT:
# {
# "Location": "/techsquad-cluster-state-store"
# }
Ten en cuenta que los nombres de los buckets son únicos, por lo que siempre es una buena idea prefijarlos con tu nombre de dominio o algo similar.
Habilitar el versionado, en caso de que necesitemos revertir algún cambio
aws s3api put-bucket-versioning --bucket ${KOPS_STATE_STORE} --versioning-configuration Status=Enabled
Habilitar la encriptación para el bucket
aws s3api put-bucket-encryption --bucket ${KOPS_STATE_STORE} --server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
Y finalmente, vamos a crear nuestro clúster
export KOPS_STATE_STORE="s3://${KOPS_STATE_STORE}"
kops create cluster \
--zones us-east-1a \
--networking calico \
${NAME} \
--yes
# OUTPUT:
# I0117 23:14:06.449479 10314 create_cluster.go:1318] Using SSH public key: /home/kainlite/.ssh/id_rsa.pub
# I0117 23:14:08.367862 10314 create_cluster.go:472] Inferred --cloud=aws from zone "us-east-1a"
# I0117 23:14:09.736030 10314 subnets.go:184] Assigned CIDR 172.20.32.0/19 to subnet us-east-1a
# W0117 23:14:18.049687 10314 firewall.go:249] Opening etcd port on masters for access from the nodes, for calico. This is unsafe in untrusted environments.
# I0117 23:14:19.385541 10314 executor.go:91] Tasks: 0 done / 77 total; 34 can run
# I0117 23:14:21.779681 10314 vfs_castore.go:731] Issuing new certificate: "apiserver-aggregator-ca"
# I0117 23:14:21.940026 10314 vfs_castore.go:731] Issuing new certificate: "ca"
# I0117 23:14:24.404810 10314 executor.go:91] Tasks: 34 done / 77 total; 24 can run
# I0117 23:14:26.548234 10314 vfs_castore.go:731] Issuing new certificate: "master"
# I0117 23:14:26.689470 10314 vfs_castore.go:731] Issuing new certificate: "apiserver-aggregator"
# I0117 23:14:26.766563 10314 vfs_castore.go:731] Issuing new certificate: "kube-scheduler"
# I0117 23:14:26.863562 10314 vfs_castore.go:731] Issuing new certificate: "kube-controller-manager"
# I0117 23:14:26.955776 10314 vfs_castore.go:731] Issuing new certificate: "kubecfg"
# I0117 23:14:26.972837 10314 vfs_castore.go:731] Issuing new certificate: "apiserver-proxy-client"
# I0117 23:14:26.973239 10314 vfs_castore.go:731] Issuing new certificate: "kops"
# I0117 23:14:27.055466 10314 vfs_castore.go:731] Issuing new certificate: "kubelet"
# I0117 23:14:27.127778 10314 vfs_castore.go:731] Issuing new certificate: "kubelet-api"
# I0117 23:14:27.570516 10314 vfs_castore.go:731] Issuing new certificate: "kube-proxy"
# I0117 23:14:29.503168 10314 executor.go:91] Tasks: 58 done / 77 total; 17 can run
# I0117 23:14:31.594404 10314 executor.go:91] Tasks: 75 done / 77 total; 2 can run
# I0117 23:14:33.297131 10314 executor.go:91] Tasks: 77 done / 77 total; 0 can run
# I0117 23:14:33.297168 10314 dns.go:153] Pre-creating DNS records
# I0117 23:14:34.947302 10314 update_cluster.go:291] Exporting kubecfg for cluster
# kops has set your kubectl context to k8s.techsquad.rocks
#
# Cluster is starting. It should be ready in a few minutes.
#
# Suggestions:
# * validate cluster: kops validate cluster
# * list nodes: kubectl get nodes --show-labels
# * ssh to the master: ssh -i ~/.ssh/id_rsa [email protected]
# * the admin user is specific to Debian. If not using Debian please use the appropriate user based on your OS.
# * read about installing addons at: https://github.com/kubernetes/kops/blob/master/docs/addons.md.
Hemos configurado KOPS_STATE_STORE
con una URL válida de S3 para kops, y luego creamos el clúster. Esto también configurará el contexto de kubectl
para nuestro nuevo clúster. Es posible que necesitemos esperar unos minutos antes de poder usarlo, pero antes de hacer cualquier cosa, validemos que esté listo y en funcionamiento.
kops validate cluster ${NAME}
# OUTPUT:
# Using cluster from kubectl context: k8s.techsquad.rocks
#
# Validating cluster k8s.techsquad.rocks
#
# INSTANCE GROUPS
# NAME ROLE MACHINETYPE MIN MAX SUBNETS
# master-us-east-1a Master m3.medium 1 1 us-east-1a
# nodes Node t2.medium 2 2 us-east-1a
#
# NODE STATUS
# NAME ROLE READY
# ip-172-20-39-123.ec2.internal node True
# ip-172-20-52-65.ec2.internal node True
# ip-172-20-61-51.ec2.internal master True
#
# Your cluster k8s.techsquad.rocks is ready
La validación fue exitosa y podemos ver que nuestro clúster está listo. Puede tomar varios minutos hasta que el clúster esté completamente funcional; en este caso, tomó aproximadamente de 3 a 5 minutos.
Crearemos una subred adicional para satisfacer los requisitos de nuestro ALB:
aws ec2 create-subnet --vpc-id vpc-06e2e104ad785474c --cidr-block 172.20.64.0/19 --availability-zone us-east-1b
# OUTPUT:
# {
# "Subnet": {
# "AvailabilityZone": "us-east-1b",
# "AvailableIpAddressCount": 8187,
# "CidrBlock": "172.20.64.0/19",
# "DefaultForAz": false,
# "MapPublicIpOnLaunch": false,
# "State": "pending",
# "SubnetId": "subnet-017a5609ce6104e1b",
# "VpcId": "vpc-06e2e104ad785474c",
# "AssignIpv6AddressOnCreation": false,
# "Ipv6CidrBlockAssociationSet": []
# }
# }
aws ec2 create-tags --resources subnet-017a5609ce6104e1b --tags Key=KubernetesCluster,Value=k8s.techsquad.rocks
aws ec2 create-tags --resources subnet-017a5609ce6104e1b --tags Key=Name,Value=us-east-1b.k8s.techsquad.rocks
aws ec2 create-tags --resources subnet-017a5609ce6104e1b --tags Key=SubnetType,Value=Public
aws ec2 create-tags --resources subnet-017a5609ce6104e1b --tags Key=kubernetes.io/cluster/k8s.techsquad.rocks,Value=owned
aws ec2 create-tags --resources subnet-017a5609ce6104e1b --tags Key=kubernetes.io/role/elb,Value=1
Tenga en cuenta que aplicamos algunas etiquetas necesarias para el controlador y creamos una subred adicional. En una configuración HA, esto no sería necesario, ya que kops lo crearía por nosotros, pero como se trata de un clúster pequeño para pruebas/desarrollo, debemos hacerlo manualmente.
Y por último, un grupo de seguridad para nuestro ALB:
aws ec2 create-security-group --group-name WebApps --description "Default web security group" --vpc-id vpc-06e2e104ad785474c
# OUTPUT:
# {
# "GroupId": "sg-09f0b1233696e65ef"
# }
aws ec2 authorize-security-group-ingress --group-id sg-09f0b1233696e65ef --protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id sg-057d2b0f6e288aa70 --protocol all --port 0 --source-group sg-09f0b1233696e65ef
Tenga en cuenta que esta regla abrirá el puerto 80 al mundo. Puede agregar su IP o las IPs de su VPN si desea restringir el acceso. La segunda regla permitirá que el tráfico proveniente del balanceador de carga llegue a los nodos donde nuestra aplicación está funcionando.
Aws-alb-ingress-controller
Usaremos Aws ALB Ingress Controller para servir nuestro tráfico web. Este controlador creará y gestionará un ALB basado en nuestras reglas de ingress.
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/rbac-role.yaml
clusterrole.rbac.authorization.k8s.io "alb-ingress-controller" created
clusterrolebinding.rbac.authorization.k8s.io "alb-ingress-controller" created
serviceaccount "alb-ingress" created
Descargue el manifiesto y luego modifique el nombre del clúster a k8s.techsquad.rocks
y algunos otros parámetros. Puede listar las VPCs con aws ec2 describe-vpcs
, tendrán algunas etiquetas de kops, por lo que es fácil identificarlas.
curl -sS "https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/alb-ingress-controller.yaml" > alb-ingress-controller.yaml
O copie y pegue las siguientes líneas:
cat << EOF > alb-ingress-controller.yaml
# Application Load Balancer (ALB) Ingress Controller Deployment Manifest.
# This manifest details sensible defaults for deploying an ALB Ingress Controller.
# GitHub: https://github.com/kubernetes-sigs/aws-alb-ingress-controller
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: alb-ingress-controller
name: alb-ingress-controller
# Namespace the ALB Ingress Controller should run in. Does not impact which
# namespaces it's able to resolve ingress resource for. For limiting ingress
# namespace scope, see --watch-namespace.
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: alb-ingress-controller
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: alb-ingress-controller
spec:
containers:
- args:
- -v=1
# Limit the namespace where this ALB Ingress Controller deployment will
# resolve ingress resources. If left commented, all namespaces are used.
# - --watch-namespace=your-k8s-namespace
- --feature-gates=waf=false
# Setting the ingress-class flag below ensures that only ingress resources with the
# annotation kubernetes.io/ingress.class: "alb" are respected by the controller. You may
# choose any class you'd like for this controller to respect.
- --ingress-class=alb
# Name of your cluster. Used when naming resources created
# by the ALB Ingress Controller, providing distinction between
# clusters.
- --cluster-name=k8s.techsquad.rocks
# AWS VPC ID this ingress controller will use to create AWS resources.
# If unspecified, it will be discovered from ec2metadata.
- --aws-vpc-id=vpc-06e2e104ad785474c
# AWS region this ingress controller will operate in.
# If unspecified, it will be discovered from ec2metadata.
# List of regions: http://docs.aws.amazon.com/general/latest/gr/rande.html#vpc_region
- --aws-region=us-east-1
# Enables logging on all outbound requests sent to the AWS API.
# If logging is desired, set to true.
# - ---aws-api-debug
# Maximum number of times to retry the aws calls.
# defaults to 10.
# - --aws-max-retries=10
env:
# AWS key id for authenticating with the AWS API.
# This is only here for examples. It's recommended you instead use
# a project like kube2iam for granting access.
#- name: AWS_ACCESS_KEY_ID
# value: KEYVALUE
# AWS key secret for authenticating with the AWS API.
# This is only here for examples. It's recommended you instead use
# a project like kube2iam for granting access.
#- name: AWS_SECRET_ACCESS_KEY
# value: SECRETVALUE
# Repository location of the ALB Ingress Controller.
image: 894847497797.dkr.ecr.us-west-2.amazonaws.com/aws-alb-ingress-controller:v1.0.0
imagePullPolicy: Always
name: server
resources: {}
terminationMessagePath: /dev/termination-log
dnsPolicy: ClusterFirst
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
serviceAccountName: alb-ingress
serviceAccount: alb-ingress
EOF
Tenga en cuenta que solo modifiqué la sección de argumentos si desea compararla con el original.
Finalmente, aplíquelo.
kubectl apply -f alb-ingress-controller.yaml
# OUTPUT:
# deployment.apps "alb-ingress-controller" created
External-dns
External DNS actualizará nuestra zona en Route53 basada en las reglas de ingress, por lo que todo se hará automáticamente una vez que agreguemos un recurso de ingress.
Pero primero, adjuntemos las políticas que creamos antes:
aws iam attach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-route53-policy --role-name nodes.k8s.techsquad.rocks
aws iam attach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-route53-policy --role-name masters.k8s.techsquad.rocks
aws iam attach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-alb-policy --role-name nodes.k8s.techsquad.rocks
aws iam attach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-alb-policy --role-name masters.k8s.techsquad.rocks
Tenga en cuenta que acabamos de utilizar las políticas que creamos anteriormente, pero necesitábamos que el clúster estuviera en funcionamiento porque kops crea los roles nodes.k8s.techsquad.rocks y masters.k8s.techsquad.rocks, y esto es necesario para que aws-alb-ingress-controller y external-dns puedan hacer su trabajo.
Necesitamos descargar los manifiestos y modificar algunos parámetros para que coincidan con nuestra implementación. Los parámetros son domain-filter y txt-owner-id, el resto queda igual:
curl -Ss https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.0/docs/examples/external-dns.yaml > external-dns.yaml
Esta configuración solo actualizará los registros, esa es la política predeterminada (upsert), y solo buscará zonas alojadas públicas.
O copie y pegue las siguientes líneas:
cat << EOF > external-dns.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:v0.5.9
args:
- --source=service
- --source=ingress
- --domain-filter=k8s.techsquad.rocks # limitará ExternalDNS a ver solo las zonas alojadas que coincidan con el dominio proporcionado, omitir para procesar todas las zonas disponibles
- --provider=aws
- --policy=upsert-only # evitaría que ExternalDNS elimine cualquier registro, omitir para habilitar la sincronización completa
- --aws-zone-type=public # solo buscará zonas alojadas públicas (valores válidos: public, private o sin valor para ambos)
- --registry=txt
- --txt-owner-id=k8s.techsquad.rocks
EOF
Y aplíquelo:
kubectl apply -f external-dns.yaml
# OUTPUT:
# serviceaccount "external-dns" unchanged
# clusterrole.rbac.authorization.k8s.io "external-dns" configured
# clusterrolebinding.rbac.authorization.k8s.io "external-dns-viewer" configured
# deployment.extensions "external-dns" created
Valide que todo lo que instalamos esté funcionando:
kubectl get pods
# OUTPUT:
# NAME READY STATUS RESTARTS AGE
# external-dns-7d7998f7bb-lb5kq 1/1 Running 0 2m
kubectl get pods -n kube-system
# OUTPUT:
# NAME READY STATUS RESTARTS AGE
# alb-ingress-controller-5885ddd5f9-9rsc8 1/1 Running 0 12m
# calico-kube-controllers-f6bc47f75-n99tl 1/1 Running 0 27m
# calico-node-4ps9c 2/2 Running 0 25m
# calico-node-kjztv 2/2 Running 0 27m
# calico-node-zs4fg 2/2 Running 0 25m
# dns-controller-67f5c6b7bd-r67pl 1/1 Running 0 27m
# etcd-server-events-ip-172-20-42-37.ec2.internal 1/1 Running 0 26m
# etcd-server-ip-172-20-42-37.ec2.internal 1/1 Running 0 26m
# kube-apiserver-ip-172-20-42-37.ec2.internal 1/1 Running 0 27m
# kube-controller-manager-ip-172-20-42-37.ec2.internal 1/1 Running 0 26m
# kube-dns-756bfc7fdf-2kzjs 3/3 Running 0 24m
# kube-dns-756bfc7fdf-rq5nd 3/3 Running 0 27m
# kube-dns-autoscaler-787d59df8f-c2d52 1/1 Running 0 27m
# kube-proxy-ip-172-20-42-109.ec2.internal 1/1 Running 0 25m
# kube-proxy-ip-172-20-42-37.ec2.internal 1/1 Running 0 26m
# kube-proxy-ip-172-20-54-175.ec2.internal 1/1 Running 0 25m
# kube-scheduler-ip-172-20-42-37.ec2.internal 1/1 Running 0 26m
Podemos ver que alb-ingress-controller está funcionando, al igual que external-dns, y todo se ve bien y saludable, es hora de probarlo con una implementación.
Testing everything
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/2048/2048-namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/2048/2048-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/2048/2048-service.yaml
# OUTPUT:
# namespace "2048-game" created
# deployment.extensions "2048-deployment" created
# service "service-2048" created
Necesitamos descargar y editar el recurso de ingress para que utilice nuestro dominio y podamos ver el registro apuntando al ALB.
curl -Ss https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.0.0/docs/examples/2048/2048-ingress.yaml > 2048-ingress.yaml
O simplemente copie y pegue el siguiente fragmento.
cat << EOF > 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
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/subnets: subnet-017a5609ce6104e1b, subnet-060e6d3c3d3c2b34a
alb.ingress.kubernetes.io/security-groups: sg-09f0b1233696e65ef
# Puede verificar todas las alternativas aquí:
# https://github.com/riccardofreixo/alb-ingress-controller/blob/master/docs/ingress-resources.md
labels:
app: 2048-ingress
spec:
rules:
- host: 2048.k8s.techsquad.rocks
http:
paths:
- backend:
serviceName: "service-2048"
servicePort: 80
path: /*
EOF
Puede usar aws ec2 describe-subnets
para encontrar el primer ID de subred. Esta subred ya tiene algunas etiquetas que necesitamos para que funcione, por ejemplo: kubernetes.io/role/elb: 1
, y la segunda subred es la que creamos manualmente y aplicamos las mismas etiquetas.
Y finalmente aplíquelo:
kubectl apply -f 2048-ingress.yaml
# OUTPUT:
# ingress.extensions "2048-ingress" created
Espere unos momentos y verifique.
Resultados
El ALB
Los registros DNS
Y la aplicación
Clean up
Recuerde que esto no es gratis, y si no quiere que se le cobre después de haber terminado las pruebas, simplemente apague y elimine todo.
kubectl delete -f 2048-ingress.yaml
aws iam detach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-route53-policy --role-name nodes.k8s.techsquad.rocks
aws iam detach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-route53-policy --role-name masters.k8s.techsquad.rocks
aws iam detach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-alb-policy --role-name nodes.k8s.techsquad.rocks
aws iam detach-role-policy --policy-arn arn:aws:iam::894527626897:policy/kops-alb-policy --role-name masters.k8s.techsquad.rocks
kops delete cluster ${NAME} --yes
# OUTPUT:
# ...
# Deleted kubectl config for k8s.techsquad.rocks
#
# Deleted cluster: "k8s.techsquad.rocks"
Este comando es realmente detallado, así que lo resumí al final. Tenga en cuenta que para eliminar el clúster con kops, primero debe desasociar los privilegios adicionales adjuntos. También tenga cuidado de eliminar primero los recursos de ingress para que el ALB se elimine antes de que elimine el clúster, o de lo contrario tendrá un ALB pendiente después. Puede volver a ejecutarlo si se queda atascado y no puede eliminar ningún recurso.
Notas
- Iba a usar helm e implementar una aplicación más compleja aquí, pero el artículo ya era demasiado largo, así que decidí ir con el ejemplo del controlador de ingreso de aws alb.
- Si algo no sale bien o las cosas no suceden, siempre puede verificar los registros de external-dns y aws-alb-ingress-controller, los mensajes suelen ser muy descriptivos y fáciles de entender.
- Para un ALB, necesita dos subredes en dos AZ diferentes de antemano.
- Si va a utilizar ALBs, tenga en cuenta que creará un ALB para cada implementación. Hay un pequeño proyecto que combina todo en un solo ALB, pero necesita tener una forma unificada o consolidada de realizar verificaciones de estado o algunas de las aplicaciones fallarán y el ALB devolverá un 502. El proyecto se puede encontrar aquí.
- Documentar lo que hace y cómo lo hace (y también mantener la documentación actualizada es realmente importante) no solo le ayudará a usted en el futuro (sí, puede agradecer a su yo del pasado cuando lea un documento antiguo), sino que también facilitará compartir el conocimiento y el propósito de lo que sea que esté implementando con su equipo.
- Gasté 3 dólares en todas las instancias y zonas DNS, etc., durante este tutorial, en caso de que le interese :).
- También eliminé todos los $ de los bloques de código y agregué la salida de los comandos con # OUTPUT:. Déjeme saber si esto es claro y fácil de leer, o si tiene alguna sugerencia. <br />
Errata
Si encuentra algún error o tiene alguna sugerencia, envíeme un mensaje para que se corrija.
No tienes cuenta? Regístrate aqui
Ya registrado? Iniciar sesión a tu cuenta ahora.
-
Comentarios
Online: 0
Por favor inicie sesión para poder escribir comentarios.