Amazon EKS — это управляемый сервис, который упрощает запуск Kubernetes на AWS без необходимости установки, эксплуатации и обслуживания мастер нод в Kubernetes.
Не буду рассказывать что такое Кубернетес и для чего он нужен. Наверное и так уже все знают что это и как его юзать. Но может не все знают как можно его настроить в AWS с использованием EKS.
Полезное чтиво:
Установка minikube в Unix/Linux
Команды Kubernetes в Unix/Linux
Установка Kubernetes кластера в Unix/Linux
Установка Spinnaker в Unix/Linux
Поехали….
Предустановка AWS EKS кластера в Unix/Linux
Ставим себе на машину:
- kubectl
- helm
Необходимо знать в какой сети нужен кластер:
- Внутренняя сеть
- Публичная сеть
У меня для примера, я использую внутреннюю сеть. Для того чтобы приступили к установки куба, еще, необходимо создать 2 роли:
- arn:aws:iam::486668976666:role/AmazonEKSClusterRole — это роль со стандартными полисями (например — AmazonEKSClusterPolicy + все то, что необходимо будет для вашего проекта. Для работы с волюмами для подов я создавал отдельную полиси).
- arn:aws:iam::486668976666:role/K8SWorkersRole — это роль с полисями которые необходимы при работе с воркер-нодами (Например — AmazonEKSWorkerNodePolicy и AmazonEKSVPCResourceController + если планируете юзать ECR — стоит приапачить еще и AmazonEC2ContainerRegistryReadOnly, как пример. Для работы с волюмами для подов я создавал отдельную полиси).
Приступим к установки.
Создание AWS EKS кластера через AWC CLI (aws eks) в Unix/Linux
Для начала, необходимо поставить AWS CLI на вашу систему с которой будете запускать команды. У меня MacOS, по этому — я ставил через HOMEBREW:
$ brew install awscli
Для остальных ОС, — не сильно отличаться должно…
Создаем кластер следующим образом (если нужно чтобы он был доступен в рамках VPC или через VPN), т.е internal:
$ aws eks create-cluster \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test \
--kubernetes-version 1.17 \
--role-arn arn:aws:iam::486668976666:role/AmazonEKSClusterRole \
--resources-vpc-config subnetIds=subnet-065292d0e6abb34bc,subnet-0bed681cb074db448,subnet-0352a2addd013b8e2,securityGroupIds=sg-019f0b7291543066c,endpointPublicAccess=false,endpointPrivateAccess=true \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}' \
--tags Name=aws-eks-test,createdby=vnatrov,environment=dev
Или, если необходимо создать кластер для того чтобы он был доступен с интернета, можете использовать следующую команду:
aws eks create-cluster \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test \
--kubernetes-version 1.17 \
--role-arn arn:aws:iam::486668976666:role/AmazonEKSClusterRole \
--resources-vpc-config subnetIds=subnet-065292d0e6abb34bc,subnet-0bed681cb074db448,subnet-0352a2addd013b8e2,securityGroupIds=sg-019f0b7291543066c,endpointPublicAccess=true,endpointPrivateAccess=false \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}' \
--tags Name=aws-eks-test,createdby=vnatrov,environment=dev
AWS EKS кластер создается около 10-15 минут (примерно) и чтобы проверить, можно использовать команду:
$ aws eks describe-cluster \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test \
--query cluster.status
Если надоело играться и не нужен кластер, грохнуть можно так:
$ aws eks delete-cluster \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test
Идем дальше, и следующим шагом будет создание «node group» т.е группы машин, которые будут использоваться в качестве воркеров и на них будут запускаться ПОД-ы (можно и на мастере запускать ПОД-ы, но мастер служит для других целей):
$ aws eks create-nodegroup \
--region us-east-1 \
--profile aws-eks-test \
--nodegroup-name aws-eks-test-nodegroup-1 \
--cluster-name aws-eks-test \
--scaling-config minSize=3,maxSize=3,desiredSize=3 \
--disk-size 128 \
--subnets subnet-065292d0e6abb34bc subnet-0bed681cb074db448 subnet-0352a2addd013b8e2 \
--instance-types m5d.xlarge \
--ami-type AL2_x86_64 \
--remote-access ec2SshKey=aws-eks-test-eks-nodegroup1-key,sourceSecurityGroups=sg-093ee648c274f6e72 \
--node-role arn:aws:iam::486668976666:role/K8SWorkersRole \
--client-request-token $(aws eks get-token --region us-east-1 --profile aws-eks-test --cluster-name aws-eks-test | jq -r '.status.token') \
--kubernetes-version 1.17 \
--labels eks.io/managed-by=eks,eks.io/role=K8SWorkersRole \
--tags Name=aws-eks-test-nodegroup1,createdby=vnatrov,environment=dev
Нужно подождать некоторое время чтобы машины создались. У меня, где-то потребовалось 5-10 минут.
Удалить можно созданные группы, можно так:
$ aws eks delete-nodegroup \
--region us-east-1 \
--profile aws-eks-test \
--nodegroup-name aws-eks-test-nodegroup-1 \
--cluster-name aws-eks-test
Созданный стек уже имеется, но нужно настроить еще необходимые компоненты, о которых я расскажу немного ниже.
Создание AWS EKS кластера через eksctl в Unix/Linux
Протестирую работу, и обязательно дополню статью.
Создание AWS EKS кластера через KOPS в Unix/Linux
Нужно собрать кластер и протестировать создание. После — все обновлю и добавлю.
Создание AWS EKS кластера через Terraform в Unix/Linux
Куда же без моего любимого Terrafrom-а, но у меня нет своего написанного модуля еще, но вот через определенный промежуток прийдется написать стек для работы для деплоя Кубернетеса на ПРОД.
Но готовый модуль давно уже имеется в инете, — terraform-aws-eks.
Создание AWS EKS кластера через другой способ в Unix/Linux
Возможно будет другой способ создания куба. Я знаю что есть еще AWS CloudFormation и через него можно сделать, — но он мне не нравится как сервис и я не хочу описывать его работу.
Настройка AWS EKS кластера в Unix/Linux
Смотрим на кластер:
$ kubectl cluster-info
Для интереса можно посмотреть сервисы которые использует кластер:
$ kubectl get svc
Пред-настройка AWS EKS кластера в Unix/Linux
Когда у нас имеется кластер, первое что необходимо — конечно же — это доступ к нему, а получить, можно его так:
$ aws eks update-kubeconfig \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test
Идем далее, создаем файл с названием (например):
$ vim aws-auth-cm.yaml
И вставляем:
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::486668976666:instance-profile/K8SWorkersRole
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
Деплоим конфиг-мапу себе в куб:
$ kubectl apply -f aws-auth-cm.yaml
Смотрим, появились ли ноды у нас:
$ kubectl get nodes --watch
Данный финт нужен для того чтобы worker ноды присоединились в кубернетес кластер.
Если есть необходимость поправить данный конфиг, можно заюзать:
$ kubectl edit -n kube-system configmap/aws-auth
Но скачать такой файл (но нужно еще поправить параметры для себя), можно так:
$ curl -O aws-auth-cm.yaml https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2019-01-09/aws-auth-cm.yaml
Сеть в AWS EKS кластера в Unix/Linux
У меня, при таком создании, не смогли приатачиться ноды к мастеру и мне нужно было что-то предпринять — и тут мне в голову пришло, — поиграться с сетью.
Устанавливаем weave драйвер следующим образом:
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
После данного действия, у меня появилась связь между AWS EKS и Kubernetes workers.
Собственно, если захотелось удалить:
$ kubectl delete -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
Так же, можно установить и поиграться с calico драйвером следующим образом:
$ kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.7.4/config/v1.7/aws-k8s-cni.yaml &&
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.7.4/config/v1.7/cni-metrics-helper.yaml
Удаление:
$ kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.7.4/config/v1.7/aws-k8s-cni.yaml
Создадим пример для демо:
$ kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.7/config/v1.7/calico.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/00-namespace.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/01-management-ui.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/02-backend.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/03-frontend.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/04-client.yaml
Смотрим, создался ли демонсэт:
$ kubectl get daemonset calico-node --namespace kube-system
Смотрим чтобы создались поды:
$ kubectl get pods --all-namespaces --watch
Открываем другую вкладку в консоле и выполняем:
$ kubectl port-forward service/management-ui -n management-ui 9001
Т.е пробросили порты себе на локальную тачку. Открываем локалхост на 9001 и должны увидеть приложенько.
Давайте играться с калико-драйвером и забаним что-то, например:
$ kubectl apply -n stars -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/default-deny.yaml
kubectl apply -n client -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/default-deny.yaml
Обновляем страничку и увидим что трафик не везде ходит.
Идем дальше и выполняем:
$ kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/allow-ui.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/allow-ui-client.yaml
И сново смотрим что вышло. И можно такое сделать:
$ kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/backend-policy.yaml
Обновите и поглядите что будет. И последнее:
$ kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/policies/frontend-policy.yaml
Удаляем после тестов:
$ kubectl delete -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.7/config/v1.7/calico.yaml
kubectl delete -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/04-client.yaml
kubectl delete -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/03-frontend.yaml
kubectl delete -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/02-backend.yaml
kubectl delete -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/01-management-ui.yaml
kubectl delete -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/tutorials/stars-policy/manifests/00-namespace.yaml
Знаю что имеется еще пару драйверов, но я с ними не пробовал работать. Можно еще настроить sNAT и ходить в мир через Internet Gateway. Документация есть на сайте Амазон.
Storage в AWS EKS кластера в Unix/Linux
Смотрим что используете по-дефолту:
$ kubectl get storageclass
Можно использовать стандартный провайдер и подружить EBS с AWS EKS, для этого создаем StorageClass, например:
$ cat <<EOF | kubectl apply -f -
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs-io1-10iops-per-db
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs-io1-500iops-per-db
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "500"
fsType: ext4
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs-io2-10iops-per-db
provisioner: kubernetes.io/aws-ebs
parameters:
type: io2
iopsPerGB: "10"
fsType: ext4
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: aws-ebs-io2-500iops-per-db
provisioner: kubernetes.io/aws-ebs
parameters:
type: io2
iopsPerGB: "500"
fsType: ext4
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-csi-local-nvme
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: no-provisioner-local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF
Но еще имеется сторонний драйвер который советует сам AWS и для этого, нужно добавить полиси. Их пример можно скачать:
$ curl -O AmazonEbsCsiDriver.json https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/v0.6.0/docs/example-iam-policy.json
Можно создать их руками в консоле Амазона или так:
$ aws iam create-policy \
--region us-east-1 \
--profile aws-eks-test \
--policy-name AmazonEbsCsiDriver \
--policy-document file://AmazonEbsCsiDriver.json
Ну а после, — аттачим их к своей роле:
$ aws iam attach-role-policy \
--region us-east-1 \
--profile aws-eks-test \
--policy-arn arn:aws:iam::486668976666:policy/AmazonEbsCsiDriver \
--role-name arn:aws:iam::486668976666:role/K8SWorkersRole
Ну или через AWS Console можно выполнить аттачмент. Деплоим EBS CSI Driver:
$ kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"
Или можно тоже самое сделать через хелм:
$ helm upgrade --install aws-ebs-csi-driver \
--namespace kube-system \
--set enableVolumeScheduling=true \
--set enableVolumeResizing=true \
--set enableVolumeSnapshot=true \
https://github.com/kubernetes-sigs/aws-ebs-csi-driver/releases/download/v0.7.0/helm-chart.tgz
А далее, можем проверить, все ли впорядке:
$ kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-ebs-csi-driver,app.kubernetes.io/instance=aws-ebs-csi-driver"
После этого можно создать тест и потестировать.
Чтобы подружить AWS EFS и ваш кластер, необходимо установить:
$ kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/ecr/?ref=release-1.0"
Если у вас фаргет под капотом, то стоит установить для работы с EFS-ом:
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/deploy/kubernetes/base/csidriver.yaml
Создаем AWS EFS и берем с него ID, он нам понадобится. Сейчас создаем ресурсы:
$ cat <<EOF | kubectl apply -f -
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: csi-efs
provisioner: efs.csi.aws.com
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: efs-pvc-0
namespace: storage
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: csi-efs
csi:
driver: efs.csi.aws.com
volumeHandle: fs-ea1f3e68 # YOUR CREATED EFS ID HERE!
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/nodegroup
operator: In
values:
- poc-nodegroup-1
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: volume-0
namespace: storage
spec:
accessModes:
- ReadWriteMany
storageClassName: csi-efs
resources:
requests:
storage: 10Gi
EOF
Замечание: Не забываем менять некоторые параметры в файле!
А удалить можно через kubectl delete (по аналогии что и в примерах выше).
Установка Kubernetes Dashboard (Web UI):
-1-
Ставим нужные компоненты:
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml && \
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
PS: Версия может быть не актуальна и необходимо смотреть последний RC.
Создаем ServiceAccount для кластера:
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: eks-admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: eks-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: eks-admin
namespace: kube-system
EOF
Создаем ServiceAccount для входа в борду:
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF
Смотрим деплоймент:
$ kubectl get deployment metrics-server -n kube-system
Для входа в админку, нужен будет токен, по этому — получаем его так:
$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')
Или, только нужное поле:
$ aws eks get-token --cluster-name eksworkshop-eksctl | jq -r '.status.token'
Или вот так:
$ kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
Сейчас можно выполнить прокси с задеплоинного ПОД-а себе на машину:
$ kubectl proxy
В данном случае, дефолтный порт — 8001. Или с указанием дополнительных полей:
$ kubectl proxy --port=8080 --address=0.0.0.0 --disable-filter=true &
Для тестов можно выполнить курл и поглядеть все ли норм:
$ curl http://localhost:8080/api
Чтобы не юзать прокси, можно так же использовать форвардинг-порта:
$ kubectl port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8080:443
Или:
$ kubectl port-forward \
--insecure-skip-tls-verify=true \
--kubeconfig="/Users/vnatarov/.kube/config" \
-n kubernetes-dashboard \
service/kubernetes-dashboard 8080:443
Открываем браузер:
http://localhost:8080/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#!/login
Удаляем созданное барахло:
# pkill -f 'kubectl proxy --port=8080' &&\
kubectl delete -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml && \
kubectl delete -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
-2-
$ helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/ &&\
kubectl create ns kubernetes-dashboard &&\
helm install kubernetes-dashboard -n kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard
Делаем форвардинг порта:
$ export POD_NAME=$(kubectl get pods -n kubernetes-dashboard -l "app.kubernetes.io/name=kubernetes-dashboard,app.kubernetes.io/instance=kubernetes-dashboard" -o jsonpath="{.items[0].metadata.name}")
echo https://127.0.0.1:8443/
kubectl -n kubernetes-dashboard port-forward $POD_NAME 8443:8443
Для апгрейда, можно юзать:
$ helm upgrade -f values.yaml kubernetes-dashboard ./ -n kubernetes-dashboard
Удалить можно так:
$ helm uninstall kubernetes-dashboard -n kubernetes-dashboard
Замечание: список деплойментов, можно вывести:
$ helm list -n kubernetes-dashboard
Если проблемы с сертификатом, то можно решить их одним из способов.
-1-
Можно в Хроме выключить проверку сертификатов с локалхоста (проще простого):
chrome://flags/#allow-insecure-localhost
-2-
На самом кластере можно выкл проверку ТЛС-а:
$ kubectl config set-cluster aws-eks-test --insecure-skip-tls-verify=true
-3-
Генерируем самоподписные серты:
$ mkdir certs &&\
openssl req -nodes -newkey rsa:2048 -keyout certs/dashboard.key -out certs/dashboard.csr -subj "/C=/ST=/L=/O=/OU=/CN=kubernetes-dashboard" &&\
openssl x509 -req -sha256 -days 365 -in certs/dashboard.csr -signkey certs/dashboard.key -out certs/dashboard.crt
Создаем сикрет и пушим ключи в куб:
$ kubectl create secret generic kubernetes-dashboard-certs --from-file=certs -n kubernetes-dashboard
Проверяем все ли зааплоадилось:
$ kubectl describe secret/kubernetes-dashboard-certs -n kubernetes-dashboard
И последним что нужно сделать — это отредактировать деплоймент:
$ kubectl edit deploy kubernetes-dashboard -o yaml -n kubernetes-dashboard
И приводим к виду:
- args:
- --tls-cert-file=/certs/dashboard.crt
- --tls-key-file=/certs/dashboard.key
Перебьем под-ы:
$ kubectl delete pod -n kubernetes-dashboard -l app.kubernetes.io/name=kubernetes-dashboard
Дружим Control plane метрики с Prometheus
Смотрим рав метрики:
$ kubectl get --raw /metrics
Создам новый NS:
$ kubectl create namespace prometheus
Деплоим необходимое:
$ helm install prometheus stable/prometheus \
--namespace prometheus \
--set alertmanager.persistentVolume.storageClass="gp2",server.persistentVolume.storageClass="gp2",grafana.service.type=LoadBalancer
Или:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
helm repo update
helm install prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace prometheus \
--set grafana.service.type=LoadBalancer,grafana.adminPassword="I'mrobot"
Проверяем сервис и можем логинится. Можно проверить, есть ли поды так:
$ kubectl get pods --namespace prometheus -l "release=prometheus-stack"
Если необходимо удалить, можно это сделать так:
$ helm list -n prometheus
$ helm uninstall prometheus-stack -n prometheus
$ kubectl delete namespace prometheus
Еще один способ создать и получать метрики, — это задеплоить через ХЕЛМ:
$ helm install metrics-server stable/metrics-server --set hostNetwork.enabled=true
Смотрим логи деплойменга:
$ kubectl logs -n kube-system deploy/metrics-metrics-server
А сейчас, можно получать метрики с куба (они нужны будут для скейлинга ПОД-ов):
$ kubectl top nodes NAME
Но об скейле — немного позже…
External DNS
Попозже будет. Нет необходимости юзать.
Работаем с serviceaccounts в Kubernetes
TBD.
Создаем масштабирование (автоскейлинг) cluster-autoscaler в AWS EKS кластере
Начну с того, что создам NodeGroup для работы со скейлом:
AWS_EKS_NODEGROUP="nodegroup1" && \
aws eks create-nodegroup \
--region us-east-1 \
--profile aws-eks-test \
--nodegroup-name ${AWS_EKS_NODEGROUP} \
--cluster-name aws-eks-test \
--scaling-config minSize=1,maxSize=5,desiredSize=1 \
--disk-size 30 \
--subnets subnet-065292d0e6abb34bc subnet-0bed681cb074db448 subnet-0352a2addd013b8e2 \
--instance-types m5d.xlarge \
--ami-type AL2_x86_64 \
--remote-access ec2SshKey=aws-eks-test-eks-nodegroup1-key,sourceSecurityGroups=sg-093ee648c274f6e72 \
--node-role arn:aws:iam::486668976666:role/K8SWorkersRole \
--client-request-token $(aws eks get-token --region us-east-1 --profile aws-eks-test --cluster-name aws-eks-test | jq -r '.status.token') \
--kubernetes-version 1.17 \
--labels eks.io/managed-by=eks,eks.io/role=K8SWorkersRole,DeploymentRole=${AWS_EKS_NODEGROUP} \
--tags Name=${AWS_EKS_NODEGROUP},createdby=vnatarov,environment=dev,node-role.kubernetes.io/${AWS_EKS_NODEGROUP}=true,DeploymentRole=${AWS_EKS_NODEGROUP},node-role.kubernetes.io/nodegroup1=nodegroup1,k8s.io/cluster-autoscaler/enabled=true,k8s.io/cluster-autoscaler/nodegroup1=true
PS: Правим под свои нужды, но теги нужно оставить (не все, но все что касается скейла — необходимы).
Смотрим, на состояния машин(ы):
$ kubectl get nodes -o wide
Пока не будет состояние «Ready», можно ждать, но а пока (для удобства) я навешаю лейблы:
$ kubectl label --overwrite nodes ip-10-130-1-205.ec2.internal node-role.kubernetes.io/nodegroup1=nodegroup1
Чтобы отвесить ее, выполняем:
$ kubectl label node ip-10-130-1-240.ec2.internal node-role.kubernetes.io/nodegroup1-
Проверим, что у нас имеется в AWS ASG:
$ NODE_GROUP_NAME="nodegroup1"
aws autoscaling \
describe-auto-scaling-groups \
--region us-east-1 \
--profile aws-eks-test \
--query "AutoScalingGroups[? Tags[? (Key=='eks:nodegroup-name') && Value=='${NODE_GROUP_NAME}']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" \
--output text
Можно пробросить переменные для дальнейшего использования:
$ export NODE_GROUP_NAME="nodegroup1" &&\
export ASG_NAME=$(aws autoscaling describe-auto-scaling-groups --region us-east-1 --profile aws-eks-test --query "AutoScalingGroups[? Tags[? (Key=='eks:nodegroup-name') && Value=='${NODE_GROUP_NAME}']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" --output text | awk '{print $1}')
Обновить ASGб можно так:
$ aws autoscaling \
update-auto-scaling-group \
--region us-east-1 \
--profile aws-eks-test \
--auto-scaling-group-name ${ASG_NAME} \
--min-size 1 \
--desired-capacity 1 \
--max-size 5
И так, сейчас займусь автоскейлом EC2 машинок. Для удобства, создам папку для проекта:
$ mkdir -p ~/environment/cluster-autoscaler
Полиси, будет такая:
$ cat <<EoF > ~/environment/cluster-autoscaler/k8s-asg-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EoF
Создаем ее:
$ aws iam create-policy \
--region us-east-1 \
--profile aws-eks-test \
--policy-name k8s-asg-policy \
--policy-document file://~/environment/cluster-autoscaler/k8s-asg-policy.json
После чего, аттачим даную полись в вашу роль!
Проверим наличие identity в кластере:
$ aws eks describe-cluster \
--region us-east-1 \
--profile aws-eks-test \
--name aws-eks-test \
--query "cluster.identity.oidc.issuer" \
--output text
Создаем ServiceAccount:
cat <<EoF > ~/environment/cluster-autoscaler/ServiceAccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: cluster-autoscaler
namespace: kube-system
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::486668976666:role/K8SWorkersRole
EoF
Применяем найстройки:
$ kubectl apply -f ~/environment/cluster-autoscaler/ServiceAccount.yaml
NOTE: Можно и без нее, т.к я буду использовать ее в другом месте с другим названием, но можно и создать ее тут.
Далее, качаем автоскейлер для AWS EKS:
$ wget -O ~/environment/cluster-autoscaler/ca-autodiscover_nodegroup1.yaml https://www.eksworkshop.com/beginner/080_scaling/deploy_ca.files/cluster-autoscaler-autodiscover.yaml
Или, то что предлагает AWS документация:
$ wget -O ~/environment/cluster-autoscaler/ca-autodiscover_nodegroup1.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
Далее, поправим файл при необходимости, мой выглядит так:
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler-nodegroup-1
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-autoscaler-nodegroup-1
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler-nodegroup-1
rules:
- apiGroups: [""]
resources: ["events", "endpoints"]
verbs: ["create", "patch"]
- apiGroups: [""]
resources: ["pods/eviction"]
verbs: ["create"]
- apiGroups: [""]
resources: ["pods/status"]
verbs: ["update"]
- apiGroups: [""]
resources: ["endpoints"]
resourceNames: ["cluster-autoscaler"]
verbs: ["get", "update"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["watch", "list", "get", "update"]
- apiGroups: [""]
resources:
- "pods"
- "services"
- "replicationcontrollers"
- "persistentvolumeclaims"
- "persistentvolumes"
verbs: ["watch", "list", "get"]
- apiGroups: ["extensions"]
resources: ["replicasets", "daemonsets"]
verbs: ["watch", "list", "get"]
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["watch", "list"]
- apiGroups: ["apps"]
resources: ["statefulsets", "replicasets", "daemonsets"]
verbs: ["watch", "list", "get"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses", "csinodes"]
verbs: ["watch", "list", "get"]
- apiGroups: ["batch", "extensions"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "patch"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create"]
- apiGroups: ["coordination.k8s.io"]
resourceNames: ["cluster-autoscaler"]
resources: ["leases"]
verbs: ["get", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler-nodegroup-1
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create","list","watch"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"]
verbs: ["delete", "get", "update", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-autoscaler-nodegroup-1
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler-nodegroup-1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-autoscaler-nodegroup-1
subjects:
- kind: ServiceAccount
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler-nodegroup-1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cluster-autoscaler-nodegroup-1
subjects:
- kind: ServiceAccount
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler-nodegroup-1
namespace: kube-system
labels:
app: cluster-autoscaler
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '8085'
spec:
serviceAccountName: cluster-autoscaler-nodegroup-1
containers:
- image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.17.3
name: cluster-autoscaler
resources:
limits:
cpu: 100m
memory: 300Mi
requests:
cpu: 100m
memory: 300Mi
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/nodegroup1
- --balance-similar-node-groups
- --skip-nodes-with-system-pods=false
env:
- name: AWS_REGION
value: us-east-1
- name: AWS_ROLE_ARN
value: arn:aws:iam::486668976666:role/AmazonEKSClusterRole
# - name: AWS_WEB_IDENTITY_TOKEN_FILE
# value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt
readOnly: true
imagePullPolicy: "Always"
volumes:
- name: ssl-certs
hostPath:
path: "/etc/ssl/certs/ca-bundle.crt"
Нужно проставить теги с вашими нуждами + поменять имедж!
Идем в AWS ASG и добавляем ключи:
k8s.io/cluster-autoscaler/enabled
k8s.io/cluster-autoscaler/nodegroup1
Значения ставим «true». Сохраняем и… можем деплоить сие-чудо:
$ kubectl apply -f ~/environment/cluster-autoscaler/ca-autodiscover_nodegroup1.yaml
Делаем аннотейшен (как говорит AWS доки):
$ kubectl -n kube-system \
annotate deployment.apps/cluster-autoscaler-nodegroup1 \
cluster-autoscaler.kubernetes.io/safe-to-evict="false"
Смотрим деплоймент, все ли там гладко и хватает всего-ли:
$ kubectl -n kube-system logs -f deployment/cluster-autoscaler-nodegroup1
Для тестирования, можно использовать любой деплоймент. При этом, автоскейлер должен понять что в кубе не хватает ресурсов и проскейлит ноду(ы) еще.
После чего, прибить можно все барахло так:
$ kubectl delete -f ~/environment/cluster-autoscaler/ca-autodiscover_nodegroup1.yaml && \
AWS_EKS_NODEGROUP="nodegroup1" && \
aws eks delete-nodegroup \
--region us-east-1 \
--profile aws-eks-test \
--nodegroup-name ${AWS_EKS_NODEGROUP} \
--cluster-name aws-eks-test
Создаем HPA масштабирование (автоскейлинг POD-ов) в AWS EKS кластере
Создаем файл с таким содержанием:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: hpa-nodegroup-1
namespace: nodegroup-1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: hpa-nodegroup-1
namespace: nodegroup-1
rules:
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: hpa-nodegroup-1
namespace: nodegroup-1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: hpa-nodegroup-1
subjects:
- kind: ServiceAccount
name: hpa-nodegroup-1
namespace: nodegroup-1
---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: hpa-nodegroup-1-autoscaleby-cpu
namespace: nodegroup-1
spec:
minReplicas: 1 # minimum replicas of pods
maxReplicas: 4 # maximum replicas of pods
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: nodegroup-1 # TARGET name of the StatefulSet the autoscaler need to be run on
targetCPUUtilizationPercentage: 30 # CPU maximum amount of use on the pod is set to 30%.
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: hpa-nodegroup-1-autoscaleby-mem
namespace: nodegroup-1
spec:
minReplicas: 1 # minimum replicas of pods
maxReplicas: 4 # maximum replicas of pods
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: nodegroup-1 # StatefulSet name
metrics:
- type: Resource
resource:
name: memory
targetAverageUtilization: 40
# - type: Resource
# resource:
# name: cpu
# targetAverageValue: 20m
Задеплоим его:
kubectl apply -f ~/environment/cluster-autoscaler/hpa_nodergroup-1.yaml
Смотрим на hpa:
$ kubectl get hpa -A
или:
$ kubectl get horizontalpodautoscalers.autoscaling -A
Можно поиграться и сделать реплику:
$ kubectl scale statefulsets -n nodegroup-1 hpa_nodergroup-1 --replicas=2
После некоторого времени, HPA прибьет реплику из-за необходимости (если не будет CPU/Mem утилизации).
Как-то так.
Полезные DEBUG-инг/фичи
Если не деплоили tiller в K8S, то возможно убить ресурсы так (Пример с неймспейсом):
$ export NAM_SPACE="management-ui";
kubectl get ns $NAM_SPACE -o json > tmp.json && \
curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/$NAM_SPACE/finalize
Для удаление всех ресурсов с куба, можно заюзать:
$ kubectl delete daemonsets,replicasets,services,deployments,pods,rc --all
А на этом, у меня все, статья «Создание AWS EKS кластера в Unix/Linux» завершена.