Загрузка кластера Kubernetes в AWS EKS с помощью eksctl

Как это ни удивительно, но создание кластера Kubernetes на AWS EKS некоторое время назад оказалось не такой уж простой задачей, тем более по сравнению с другими облачными провайдерами, такими как GCP. Именно тогда появился eksctl — инструмент, разработанный в Go сообществом, а теперь спонсируемый компанией Weave и являющийся официальным AWS CLI для управления EKS. С его помощью мы можем создавать и управлять кластерами с помощью файлов YAML, а для управления необходимыми ресурсами используются стеки в CloudFormation.

Установка

Как и другие двоичные файлы, написанные на Go, установка очень проста:

curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv m/tmp/eksctl /usr/local/bin
eksctl version
Войдите в полноэкранный режим Выход из полноэкранного режима

Настройка учетной записи AWS

Не используйте учетную запись root для создания кластера. На самом деле, не используйте учетную запись root ни для чего, кроме создания других учетных записей или включения и управления очень специфическими функциями AWS.

Если это ваша личная учетная запись, создайте другого пользователя. Теперь, если это корпоративная учетная запись, я предлагаю включить AWS Organizations.

Создайте нового пользователя в IAM со следующими политиками, прикрепленными к нему:

  • AmazonEC2FullAccess

  • AWSCloudFormationFullAccess

  • EksAllAccess

  • IamLimitedAccess

Первые две политики управляются самой AWS, и вам не нужно их создавать. Последние два будут иметь следующее содержание:

ЭкаАллах:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "eks:*",
            "Resource": "*"
        },
        {
            "Action": [
                "ssm:GetParameter",
                "ssm:GetParameters"
            ],
            "Resource": [
                "arn:aws:ssm:*:<account_id>:parameter/aws/*",
                "arn:aws:ssm:*::parameter/aws/*"
            ],
            "Effect": "Allow"
        },
        {
             "Action": [
               "kms:CreateGrant",
               "kms:DescribeKey"
             ],
             "Resource": "*",
             "Effect": "Allow"
        },
        {
             "Action": [
               "logs:PutRetentionPolicy"
             ],
             "Resource": "*",
             "Effect": "Allow"
        }        
    ]
}
Войдите в полноэкранный режим Выход из полноэкранного режима

IamLimitedAccess:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateInstanceProfile",
                "iam:DeleteInstanceProfile",
                "iam:GetInstanceProfile",
                "iam:RemoveRoleFromInstanceProfile",
                "iam:GetRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:AttachRolePolicy",
                "iam:PutRolePolicy",
                "iam:ListInstanceProfiles",
                "iam:AddRoleToInstanceProfile",
                "iam:ListInstanceProfilesForRole",
                "iam:PassRole",
                "iam:DetachRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:GetRolePolicy",
                "iam:GetOpenIDConnectProvider",
                "iam:CreateOpenIDConnectProvider",
                "iam:DeleteOpenIDConnectProvider",
                "iam:TagOpenIDConnectProvider",
                "iam:ListAttachedRolePolicies",
                "iam:TagRole",
                "iam:GetPolicy",
                "iam:CreatePolicy",
                "iam:DeletePolicy",
                "iam:ListPolicyVersions"
            ],
            "Resource": [
                "arn:aws:iam::<account_id>:instance-profile/eksctl-*",
                "arn:aws:iam::<account_id>:role/eksctl-*",
                "arn:aws:iam::<account_id>:policy/eksctl-*",
                "arn:aws:iam::<account_id>:oidc-provider/*",
                "arn:aws:iam::<account_id>:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup",
                "arn:aws:iam::<account_id>:role/eksctl-managed-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetRole"
            ],
            "Resource": [
                "arn:aws:iam::<account_id>:role/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:AWSServiceName": [
                        "eks.amazonaws.com",
                        "eks-nodegroup.amazonaws.com",
                        "eks-fargate.amazonaws.com"
                    ]
                }
            }
        }
    ]
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Замените <account_id> на идентификатор вашей учетной записи AWS.

Теперь сгенерируйте учетные данные для пользователя и сохраните ID ключа доступа и секретный ключ. eksctl требует установки AWS CLI. Если нет, запустите его:

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws configure
Войдите в полноэкранный режим Выход из полноэкранного режима

Вам будет предложено ввести такие данные, как регион AWS по умолчанию (например, us-east-1), идентификатор ключа доступа и секретный ключ для создания профиля по умолчанию. Теперь, если у вас уже установлен и настроен AWS CLI, вы можете создать новый профиль вручную, отредактировав файл ~/.aws/credentials.

Обратите внимание: если в вашем файле ~/.aws/credentials имеется несколько профилей, сообщите нам, какой из них вы хотите использовать, установив значение переменной AWS_PROFILE с помощью команды export AWS_PROFILE=my_profile.

Создание кластера

eksctl по умолчанию создаст кластер в отдельном VPC, используя экземпляры типа m5.large. Это имеет некоторые последствия:

  • Согласно квоте по умолчанию, на одну учетную запись можно иметь не более пяти VPC;

  • Если вы используете учебную, лабораторную или тестовую среду, этот тип экземпляра можно считать немного дорогим;

  • Если вам нужно, чтобы приложения в кластере взаимодействовали с ресурсами AWS — например, с экземпляром RDS, — расположенными в другом VPC, для этого необходимо настроить VPC Peering и маршрутизацию.

Наш кластер будет обладать следующими характеристиками:

  • Он будет называться demo-eks и будет расположен в us-east-1 (Северная Вирджиния);

  • В новом VPC будут созданы четыре подсети, две общедоступные и две частные. По умолчанию eksctl распределяет узлы кластера по частным подсетям;

  • Будет создана узловая группа под названием ng-01 с группой автоматического масштабирования, с минимум одним экземпляром и максимум 5 экземплярами типа t3.medium;

  • Политики IAM для external-dns, auto-scaling, cert-manager, ebs и efs. Подробнее об этих парнях мы поговорим позже.

---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: demo-eks
  region: us-east-1

managedNodeGroups:
  - name: ng-01
    instanceType: t3.medium
    desiredCapacity: 2
    minSize: 1
    maxSize: 5
    iam:
      withAddonPolicies:
        autoScaler: true
        externalDNS: true
        certManager: true
        ebs: true
        efs: true
Войдите в полноэкранный режим Выход из полноэкранного режима

Как вы можете заметить, YAML — это манифест, очень похожий на те, которые используются в Kubernetes.

Сохраните вышеуказанный файл как demo-eks.yaml и теперь просто запустите eksctl cluster create -f demo-eks.yaml --kubeconfig=demo-eks-kubeconfig и позвольте волшебству произойти (естественно). eksctl создаст стек (или стеки) в CloudFormation и создаст все необходимые ресурсы, что займет примерно пятнадцать-двадцать минут (да, это отнимает немного времени), и вуаля, у вас есть кластер Kubernetes для использования в AWS EKS, с учетными данными для доступа к нему в файле demo-eks-kubeconfig.yaml.

Важно: Если опция --kubeconfig опущена, eksctl создаст файл доступа в ~/.kube/config, что может быть проблемой, если у вас уже настроены другие кластеры. В этом случае вы можете создать каталог ~/.kube/configs для хранения файлов и переключаться между ними, устанавливая переменную KUBECONFIG, указывающую на нужный путь к файлу (например, export KUBECONFIG=${HOME}/.kube/configs/demo-eks-kubeconfig). Этот шаг необходим для того, чтобы kubectl смог подключиться к кластеру.

Установка штурвала

Скорее всего, вы слышали о Хелме, но если это не пришло вам в голову, расслабьтесь. Helm — это, по сути, менеджер пакетов для Kubernetes. Эти пакеты доступны в виде диаграмм, и с их помощью мы можем создавать манифесты наших приложений более динамичным, организованным, параметризуемым образом, а затем размещать их в репозиториях для развертывания.

Бесполезное любопытство: «chart» можно перевести как «навигационная карта». «Kubernetes» = «helm». Понял, понял? Хе-хе.

Его установка очень проста:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Войдите в полноэкранный режим Выход из полноэкранного режима

Теперь, если вы используете Debian-подобный дистрибутив и хотите использовать пакет:

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
Войдите в полноэкранный режим Выход из полноэкранного режима

Установка дополнений

Сервер метрик

Сервер метрик является необходимым ресурсом для использования HPA (Horizontal Pod Autoscalers). HPA чрезвычайно полезны, когда мы хотим горизонтально масштабировать наши приложения, когда им требуется больше ресурсов.

helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm upgrade --install --create-namespace -n metrics-server metrics-server metrics-server/metrics-server
Войдите в полноэкранный режим Выход из полноэкранного режима

Прометей

Prometheus — это решение для мониторинга. Если вы используете Lens или другую приборную панель для мониторинга ваших кластеров, она предоставит графики использования процессора, памяти, сети и дисков для кластера, узлов, контроллеров и подсистем. Prometheus обычно используется в сочетании с Grafana.

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install --create-namespace -n kube-prometheus prometheus bitnami/kube-prometheus
Войдите в полноэкранный режим Выход из полноэкранного режима

ExternalDNS

ExternalDNS синхронизирует ресурсы Kubernetes с внешними DNS-записями, размещенными у таких провайдеров, как AWS Route 53, Google Cloud DNS, AzureDNS и др. С ним нам не нужно вручную создавать записи DNS каждый раз, когда мы загружаем новое приложение в наш кластер. Мило, не правда ли?

helm install external-dns stable/external-dns 
  --create-namespace 
  --namespace external-dns 
  --set provider=aws 
  --set aws.zoneType=public 
  --set txtOwnerId=<ZONE_ID>
  --set policy=sync
  --set registry=txt
  --set interval=20s
  --set domainFilters[0]=<DOMAIN>
Войдите в полноэкранный режим Выход из полноэкранного режима

Измените <ZONE_ID> на ID вашей зоны в AWS Route 53 и <DOMAIN> на ваш домен в формате domain.com.

cert-manager

cert-manager — это CRD (Custom Resource Definition), который будет динамически генерировать TLS/SSL сертификаты для наших приложений, используя Let’s Encrypt (хотя он также поддерживает других эмитентов).

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install --create-namespace -n cert-manager cert-manager bitnami/cert-manager 
  --create-namespace 
  --namespace cert-manager 
  --set installCRDs=true
Войдите в полноэкранный режим Выход из полноэкранного режима

После установки диаграммы вам нужно создать два CRD, каждый из которых представляет разных эмитентов Let’s Encrypt, один для production, а другой для staging. Разница между ними заключается в предельном количестве запросов, которые мы можем выполнить. Для тестовых сред отдайте предпочтение среде staging.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <meu_email>
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
Войдите в полноэкранный режим Выход из полноэкранного режима
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: <meu_email>
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
Войдите в полноэкранный режим Выход из полноэкранного режима

Примечание: Замените <my_email> на адрес вашей электронной почты. Если вы используете Ingress, отличный от Nginx, вам необходимо изменить приведенные выше манифесты, установив соответствующий класс.

Выполните команду kubectl apply -f cert-manager-staging.yaml -f cert-manager-prod.yaml, чтобы создать их в кластере.

NGINX Ingress Controller

Именно через NGINX Ingress Controller мы будем разрешать доступ к нашим приложениям. Вы можете рассматривать Ingress как обратный прокси.

helm upgrade --install ingress-nginx ingress-nginx 
  --repo https://kubernetes.github.io/ingress-nginx 
  --namespace ingress-nginx 
  --create-namespace
Войдите в полноэкранный режим Выход из полноэкранного режима

Группа автоматического масштабирования

Одна из самых замечательных особенностей облачных вычислений — эластичность. Представьте, что в течение года у нас относительно постоянный спрос, но в определенное время — например, в «черную пятницу» — он может значительно возрасти, и вскоре вам понадобится больше узлов в узловых группах, чтобы удовлетворить потребности ваших капсул. Чтобы нам не пришлось делать это вручную, давайте добавим функцию автоматического масштабирования в нашу узловую группу.

helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm install --create-namespace -n cluster-autoscaler autoscaler/cluster-autoscaler 
  --set 'autoDiscovery.clusterName=<cluster_name>'
Войдите в полноэкранный режим Выход из полноэкранного режима

Примечание: Замените <cluster_name> на имя вашего кластера (в данном случае demo-eks).

Для проверки, после загрузки любого приложения, увеличьте количество реплик до числа, не удовлетворяющего доступным ресурсам в вашей узловой группе. Кластер-автоскалер будет делать доступными новые узлы до максимального количества, заданного в группе узлов. Когда количество стручков потребляет менее 50% ресурсов узла в течение более 10 минут, этот узел будет удален из группы узлов. Мило, да?

Загрузка приложения

Когда наш кластер собран, а дополнения установлены, пришло время загрузить тестовое приложение. Ниже приведены манифесты в одном файле hello-kubernetes.yaml:

apiVersion: v1
kind: Namespace
metadata:
  name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: hello-kubernetes
  name: hello-kubernetes
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-kubernetes
  template:
    metadata:
      labels:
        app: hello-kubernetes
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.5
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  namespace: hello-kubernetes
  name: hello-kubernetes
spec:
  type: ClusterIP
  selector:
    app: hello-kubernetes
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: hello-kubernetes
  name: hello-kubernetes-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    external-dns.alpha.kubernetes.io/hostname: <app.DOMINIO>
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - <app.DOMINIO>
      secretName: <app.DOMINIO>
  rules:
    - host: <app.DOMINIO>
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: hello-kubernetes
              port: 
                number: 80
Войдите в полноэкранный режим Выход из полноэкранного режима

Примечание: Замените ` на домен, который вы хотите использовать в своем приложении, что-то вроде app-01.juquinha.net.

Если все пойдет хорошо, вот что должно произойти:

  • Записи будут созданы в вашей зоне DNS в AWS Route 53 в соответствии с тем, что было настроено в настройках ingress и ExternalDNS, и в течение нескольких минут вы сможете получить доступ к вашему приложению через это имя. Вы можете следить за распространением с помощью инструмента dig;

  • Сертификат будет сгенерирован автоматически для вашего приложения. Для новых приложений это может занять некоторое время;

  • Мы выделили две реплики для приложения, и здесь есть очень важная оговорка: Kubernetes по умолчанию будет выполнять балансировку по кругу между стручками. В большинстве современных веб-приложений мы работаем с сессиями, и, как следствие этого, может возникнуть сценарий, когда пользователь аутентифицируется в одной капсуле, а при следующем запросе перенаправляется в другую, где сессии не существует. Как следствие, пользователю представляется странное поведение, например, перенаправление на экран входа в систему, сообщения «Не авторизован», прерывистый доступ и т.д. Чтобы этого не произошло, мы обычно используем некоторые сервисы, такие как Redis, memcached (они могут быть или не быть на AWS ElastiCache) или функцию sticky-sessions, когда пользователь постоянно отправляется в один и тот же pod.

 Заключение

Kubernetes — чрезвычайно обширная и сложная тема, и с ней связано множество возможностей. Я представил здесь некоторые из них, которые можно использовать не только в AWS EKS, но и в локальных инсталляциях (за исключением cluster-autoscaler, если вы не используете OpenStack на своем предприятии). Существует также ряд улучшений безопасности, которые можно внести в кластер, созданный в этой статье. Надеюсь, вам понравилось!

Ссылки

  • eksctl

Оцените статью
Procodings.ru
Добавить комментарий