Создание AWS EKS кластера в Unix/Linux

Amazon EKS — это управляемый сервис, который упрощает запуск Kubernetes на AWS без необходимости установки, эксплуатации и обслуживания мастер нод в Kubernetes.

Не буду рассказывать что такое Кубернетес и для чего он нужен. Наверное и так уже все знают что это и как его юзать. Но может не все знают как можно его настроить в AWS с использованием EKS.

Полезное чтиво:

Установка minikube в Unix/Linux

Команды Kubernetes в Unix/Linux

Установка Kubernetes кластера в Unix/Linux

Установка Helm в 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» завершена.

This entry was posted in Без рубрики. Bookmark the permalink.

Добавить комментарий

Ваш адрес email не будет опубликован.

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.