UPD: тут описывается ALB Controller v1. См. AWS: миграция AWS ALB Ingress Controller (v1) на AWS Load Balancer Controller (v2).
AWS ALB Ingress Controller for Kubernetes – контроллер Kubernetes, который управляет соданием Application Load Balancer (ALB) при создании в кластере ресурса типа Ingress
с аннотацией вида kubernetes.io/ingress.class: alb
.
Ingress
-ресурс в свою очередь определяет настройки ALB для роутинга HTTP или HTTPS трафика к различным подам кластера.
Документация:
- https://kubernetes.io/docs/concepts/services-networking/ingress/
- https://github.com/kubernetes-sigs/aws-alb-ingress-controller
- https://aws.amazon.com/ru/blogs/opensource/kubernetes-ingress-aws-alb-ingress-controller/
Содержание
Ingress controller types
AWS ALB Ingress controller поддерживает два типа передачи трафика – instance mode и ip mode:
- instance mode: трафик попадает на ALB, затем на сервис NodePort, после чего роутится к подам внутри кластера
- ip mode: рафик попадает на ALB, затем попадает напрямую к подам в кластере. В документации говорится, что требуется установка AWS CNI plugin for Kubernetes, но с EKS работает “из коробки”
См. документацию тут>>>.
eksctl – create cluster
Создаём тестовый кластер:
[simterm]
$ eksctl create cluster --profile arseniy --region eu-north-1 --name eks-alb-testing [ℹ] eksctl version 0.15.0 [ℹ] using region eu-north-1 [ℹ] setting availability zones to [eu-north-1b eu-north-1c eu-north-1a] [ℹ] subnets for eu-north-1b - public:192.168.0.0/19 private:192.168.96.0/19 [ℹ] subnets for eu-north-1c - public:192.168.32.0/19 private:192.168.128.0/19 [ℹ] subnets for eu-north-1a - public:192.168.64.0/19 private:192.168.160.0/19 [ℹ] nodegroup "ng-c408bab3" will use "ami-0d40170cbe0b51e62" [AmazonLinux2/1.14] [ℹ] using Kubernetes version 1.14 [ℹ] creating EKS cluster "eks-alb-testing" in "eu-north-1" region with un-managed nodes ... [ℹ] node "ip-192-168-11-166.eu-north-1.compute.internal" is ready [ℹ] node "ip-192-168-35-128.eu-north-1.compute.internal" is ready [ℹ] kubectl command should work with "/home/setevoy/.kube/config", try 'kubectl get nodes' [✔] EKS cluster "eks-alb-testing" in "eu-north-1" region is ready
[/simterm]
IAM OIDC provider
Документация – https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html.
Потребуется для ServiceAccount, см. https://eksctl.io/usage/iamserviceaccounts.
Создаём:
[simterm]
$ eksctl --profile arseniy --region=eu-north-1 utils associate-iam-oidc-provider --cluster eks-alb-testing --approve [ℹ] eksctl version 0.15.0 [ℹ] using region eu-north-1 [ℹ] will create IAM Open ID Connect provider for cluster "eks-alb-testing" in "eu-north-1" [✔] created IAM Open ID Connect provider for cluster "eks-alb-testing" in "eu-north-1"
[/simterm]
Проверяем:
[simterm]
$ aws --profile arseniy. --region=eu-north-1 eks describe-cluster --name eks-alb-testing --query "cluster.identity.oidc.issuer" --output text https://oidc.eks.eu-north-1.amazonaws.com/id/B59F43D7826EB61861FC73EE13216CD8
[/simterm]
Или в панели управления AWS > Identity providers:
ALB IAM policty
Далее требуется добавить IAM политику, которая будет управлять доступами для пода с ALB Ingress Controller, который будет выполнять API-запросы к AWS для создания и настройки Application Load Balancer.
Можно создать вручную так:
[simterm]
$ aws --profile arseniy --region=eu-north-1 iam create-policy --policy-name ALBIngressControllerIAMPolicy --policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json
[/simterm]
Либо добавить ещё один ресурс в CloudFormation используя AWS::IAM::Role
, но это потом (пост пока в черновиках).
В выводе результата будет ARN ресурса – “Arn”: “arn:aws:iam::534***385:policy/ALBIngressControllerIAMPolicy” – он нам сейчас понадобится.
ALB Ingress IAM Role
См. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
1 iamserviceaccount (kube-system/alb-ingress-controller) was excluded
В официальной документации порядок выполнения другой – там сначала создаётся RBAC-роль и RoleBinding, а затем – iamserviceaccount.
На деле это может привести к тому, что создании serviceaccount “kube-system/alb-ingress-controller” eksctl
сообщает, что такой якобы уже есть, и пропускает его:
[simterm]
[ℹ] eksctl version 0.15.0 [ℹ] using region eu-north-1 [ℹ] 1 iamserviceaccount(s) that already exist (kube-system/alb-ingress-controller) will be excluded [ℹ] combined exclude rules: kube-system/alb-ingress-controller [ℹ] 1 iamserviceaccount (kube-system/alb-ingress-controller) was excluded (based on the include/exclude rules) [!] serviceaccounts that exists in Kubernetes will be excluded, use --override-existing-serviceaccounts to override [ℹ] no tasks
[/simterm]
После общения с тех. поддержкой AWS – мы поменяли порядок выполнения – сначала создаём IAM-роль, а уже потом – RBAC Role и биндинг.
Продолжаем.
Проверяем к какому кластеру мы сейчас подключены – just in case:
[simterm]
$ kubectl config current-context [email protected]
[/simterm]
Окей.
Далее, с помощью eksctl
, создаём IAM роль для ALB Ingress контроллера, и используя ARN IAM политики, созданной выше – подключаем к этой роли, для чего будет создан ещё один стек CloudFormation:
[simterm]
$ eksctl --profile arseniy --region=eu-north-1 create iamserviceaccount --name alb-ingress-controller --namespace kube-system --override-existing-serviceaccounts --approve --cluster eks-alb-testing --attach-policy-arn arn:aws:iam::534***385:policy/ALBIngressControllerIAMPolicy [ℹ] eksctl version 0.15.0 [ℹ] using region eu-north-1 [ℹ] 1 task: { 2 sequential sub-tasks: { create IAM role for serviceaccount "kube-system/alb-ingress-controller", create serviceaccount "kube-system/alb-ingress-controller" } } [ℹ] building iamserviceaccount stack "eksctl-eks-alb-testing-addon-iamserviceaccount-kube-system-alb-ingress-controller" [ℹ] deploying stack "eksctl-eks-alb-testing-addon-iamserviceaccount-kube-system-alb-ingress-controller" [ℹ] created serviceaccount "kube-system/alb-ingress-controller"
[/simterm]
Ждём завершения создания стека:
ALB Ingress ServiceAccount
Создаём ServiceAccount с именем alb-ingress-controller в kube-system namespace, к нему ClusterRoleBinding
и ClusterRole
с именем alb-ingress-controller с правилами доступа:
[simterm]
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/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-controller created
[/simterm]
Проверяем:
[simterm]
$ kubectl -n kube-system get serviceaccounts | grep alb alb-ingress-controller 1 32s
[/simterm]
Запуск ALB Ingress Controller
Используем деплоймент https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml, который создаст под с образом docker.io/amazon/aws-alb-ingress-controller.
Копируем к себе на машину:
[simterm]
$ wget https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/alb-ingress-controller.yaml
[/simterm]
Редактируем, и в блоке:
... spec: containers: - name: alb-ingress-controller args: ...
Добавляем параметры:
--cluster-name=eks-alb-testing
--aws-vpc-id=vpc-06a182dd0e5ef1b70
--aws-region=eu-north-1
VPC ID есть в Outputs корневого стека кластера – eksctl-eks-alb-testing-cluster:
Приводим файл к виду:
И запускаем ALB Ingress Controller:
[simterm]
$ kubectl apply -f alb-ingress-controller.yaml deployment.apps/alb-ingress-controller created
[/simterm]
Проверяем его под:
[simterm]
$ kubectl -n kube-system get pod NAME READY STATUS RESTARTS AGE alb-ingress-controller-c47448d84-49tsc 1/1 Running 0 36s
[/simterm]
И логи самого контроллера:
[simterm]
$ kubectl logs -n kube-system deployment.apps/alb-ingress-controller -f ------------------------------------------------------------------------------- AWS ALB Ingress controller Release: v1.1.4 ... I0325 14:18:03.203499 1 leaderelection.go:205] attempting to acquire leader lease kube-system/ingress-controller-leader-alb... I0325 14:18:03.211928 1 leaderelection.go:214] successfully acquired lease kube-system/ingress-controller-leader-alb I0325 14:18:03.312309 1 controller.go:134] kubebuilder/controller "level"=0 "msg"="Starting Controller" "controller"="alb-ingress-controller" I0325 14:18:03.412486 1 controller.go:154] kubebuilder/controller "level"=0 "msg"="Starting workers" "controller"="alb-ingress-controller" "worker count"=1
[/simterm]
Запустился, работает – отлично.
Работает ли?
Проверяем.
Запуск приложения
Для проверки – запустим контейнер с NGINX.
Создаём:
- Kubernetes deployment для управления контейнерами
- добавляем
NodePort
Service для роутинга трафика к контейнерам - и сам
Ingress
объект, которому передаём тип internet-facing ALB – этотIngress
увидит наш ALB Controller, который должен будет запустить создание AWS Application Load Balancer
Деплоймент:
--- apiVersion: apps/v1 kind: Deployment metadata: name: "eks-alb-testing-deployment" spec: selector: matchLabels: app: "eks-alb-testing-web" replicas: 1 template: metadata: labels: app: "eks-alb-testing-web" spec: containers: - image: nginx imagePullPolicy: Always name: "eks-alb-testing-web-nginx" ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: "eks-alb-testing-web-service" spec: ports: - port: 80 targetPort: 80 protocol: TCP type: NodePort selector: app: "eks-alb-testing-web" --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: "eks-alb-testing-web-ingress" annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing labels: app: bttrm-eks-dev-0-web spec: rules: - http: paths: - path: /* backend: serviceName: "eks-alb-testing-web-service" servicePort: 80
Применяем:
[simterm]
$ kubectl apply -f nginx-testing-app.yml deployment.apps/eks-alb-testing-deployment created service/eks-alb-testing-web-service created ingress.extensions/eks-alb-testing-web-ingress created
[/simterm]
Смотрим логи контроллера:
[simterm]
E0325 14:24:06.627453 1 controller.go:217] kubebuilder/controller "msg"="Reconciler error" "error"="no object matching key \"default/eks-alb-testing-web-ingress\" in local store" "controller"="alb-ingress-controller" "request"={"Namespace":"default","Name":"eks-alb-testing-web-ingress"} I0325 14:24:09.257834 1 security_group.go:36] default/eks-alb-testing-web-ingress: creating securityGroup dbd770cc-default-eksalbtes-09fa:managed LoadBalancer securityGroup by ALB Ingress Controller I0325 14:24:09.340734 1 tags.go:69] default/eks-alb-testing-web-ingress: modifying tags { kubernetes.io/namespace: "default", kubernetes.io/ingress-name: "eks-alb-testing-web-ingress", ingress.k8s.aws/cluster: "eks-alb-testing", ingress.k8s.aws/stack: "default/eks-alb-testing-web-ingress", ingress.k8s.aws/resource: "ManagedLBSecurityGroup", kubernetes.io/cluster-name: "eks-alb-testing"} on sg-021899dacc4559be8 I0325 14:24:09.436719 1 security_group.go:75] default/eks-alb-testing-web-ingress: granting inbound permissions to securityGroup sg-021899dacc4559be8: [{ FromPort: 80, IpProtocol: "tcp", IpRanges: [{ CidrIp: "0.0.0.0/0", Description: "Allow ingress on port 80 from 0.0.0.0/0" }], ToPort: 80 }] I0325 14:24:09.665207 1 loadbalancer.go:191] default/eks-alb-testing-web-ingress: creating LoadBalancer dbd770cc-default-eksalbtes-09fa I0325 14:24:10.187386 1 loadbalancer.go:208] default/eks-alb-testing-web-ingress: LoadBalancer dbd770cc-default-eksalbtes-09fa created, ARN: arn:aws:elasticloadbalancing:eu-north-1:534***385:loadbalancer/app/dbd770cc-default-eksalbtes-09fa/979c262ea2e12983 I0325 14:24:10.286302 1 targetgroup.go:119] default/eks-alb-testing-web-ingress: creating target group dbd770cc-fe1e32fc96596dcf2c1 I0325 14:24:10.433821 1 targetgroup.go:138] default/eks-alb-testing-web-ingress: target group dbd770cc-fe1e32fc96596dcf2c1 created: arn:aws:elasticloadbalancing:eu-north-1:534***385:targetgroup/dbd770cc-fe1e32fc96596dcf2c1/ef783b9fead58965 I0325 14:24:10.448670 1 tags.go:43] default/eks-alb-testing-web-ingress: modifying tags { kubernetes.io/ingress-name: "eks-alb-testing-web-ingress", ingress.k8s.aws/cluster: "eks-alb-testing", ingress.k8s.aws/stack: "default/eks-alb-testing-web-ingress", kubernetes.io/service-name: "eks-alb-testing-web-service", kubernetes.io/service-port: "80", ingress.k8s.aws/resource: "default/eks-alb-testing-web-ingress-eks-alb-testing-web-service:80", kubernetes.io/cluster/eks-alb-testing: "owned", kubernetes.io/namespace: "default"} on arn:aws:elasticloadbalancing:eu-north-1:534***385:targetgroup/dbd770cc-fe1e32fc96596dcf2c1/ef783b9fead58965 I0325 14:24:10.636180 1 targets.go:80] default/eks-alb-testing-web-ingress: Adding targets to arn:aws:elasticloadbalancing:eu-north-1:534***385:targetgroup/dbd770cc-fe1e32fc96596dcf2c1/ef783b9fead58965: i-0622ff000570f32c7:31095, i-062329ba6419ba845:31095 I0325 14:24:10.821148 1 listener.go:110] default/eks-alb-testing-web-ingress: creating listener 80 E0325 14:24:10.854943 1 controller.go:217] kubebuilder/controller "msg"="Reconciler error" "error"="failed to reconcile listeners due to failed to reconcile rules due to ListenerNotFound: One or more listeners not found\n\tstatus code: 400, request id: d09ccc73-7f21-4d19-aca3-9fefad546a43" "controller"="alb-ingress-controller" "request"={"Namespace":"default","Name":"eks-alb-testing-web-ingress"} I0325 14:24:12.301420 1 rules.go:60] default/eks-alb-testing-web-ingress: creating rule 1 on arn:aws:elasticloadbalancing:eu-north-1:534***385:listener/app/dbd770cc-default-eksalbtes-09fa/979c262ea2e12983/455a07658116adcd I0325 14:24:12.324525 1 rules.go:77] default/eks-alb-testing-web-ingress: rule 1 created with conditions [{ Field: "path-pattern", Values: ["/*"] }] I0325 14:24:12.561377 1 instance_attachment_v2.go:192] default/eks-alb-testing-web-ingress: granting inbound permissions to securityGroup sg-0005aadfa599d071c: [{ FromPort: 0, IpProtocol: "tcp", ToPort: 65535, UserIdGroupPairs: [{ GroupId: "sg-021899dacc4559be8" }] }] I0325 14:24:13.171590 1 rules.go:82] default/eks-alb-testing-web-ingress: modifying rule 1 on arn:aws:elasticloadbalancing:eu-north-1:534***385:listener/app/dbd770cc-default-eksalbtes-09fa/979c262ea2e12983/455a07658116adcd I0325 14:24:13.192456 1 rules.go:98] default/eks-alb-testing-web-ingress: rule 1 modified with conditions [{ Field: "path-pattern", Values: ["/*"] }]
[/simterm]
Проверяем Ingress
:
[simterm]
$ kubectl get ingress -o wide NAME HOSTS ADDRESS PORTS AGE eks-alb-testing-web-ingress * dbd770cc-default-eksalbtes-09fa-1532296804.eu-north-1.elb.amazonaws.com 80 114s
[/simterm]
И пробуем подключиться:
[simterm]
$ curl -I dbd770cc-default-eksalbtes-09fa-1532296804.eu-north-1.elb.amazonaws.com HTTP/1.1 200 OK Date: Wed, 25 Mar 2020 14:26:27 GMT Content-Type: text/html Content-Length: 612 Connection: keep-alive Server: nginx/1.17.9 Last-Modified: Tue, 03 Mar 2020 14:32:47 GMT ETag: "5e5e6a8f-264" Accept-Ranges: bytes
[/simterm]
Готово.