Развертывание простого приложения на EKS с помощью Fargate.

В этой заметке я опишу, как развернуть серверное приложение на EKS с помощью Fargate. Я также рассмотрю все проблемы, с которыми я столкнулся во время развертывания. Это мой первый раз, когда я использую EKS!

Шаг (1) — Настройка учетных данных и окружения

  • Ниже приведены необходимые инструменты, которые нам понадобятся для успешного развертывания EKS в этом посте.

    • AWS CLI v2: Установите, следуя этой документации.
    • kubectl: установите версию 1.23.6, поскольку мы будем развертывать с помощью kubernetes версии 1.21.
  curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.22.6/2022-03-09/bin/darwin/amd64/kubectl
  cd ~/.kube
  chmod +x ./kubectl
  mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && 
  export PATH=$HOME/bin:$PATH
  echo 'export PATH=$PATH:$HOME/bin' >> ~/.bash_profile
  kubectl version --short --client
Войдите в полноэкранный режим Выход из полноэкранного режима
  • eksctl: Следуйте этой документации для установки eksctl.

После установки всех трех вышеперечисленных инструментов создайте пользователя IAM с разрешенным доступом к программированию для использования в локальном терминале и выполните несколько задач. В моем случае я создал временного IAM пользователя и прикрепил к нему политику AdministratorAccess.

Мы также будем использовать KMS, которая предоставляет простые способы настройки и управления ключами шифрования, используемыми различными службами AWS.

aws kms create-alias --alias-name alias/demo-eks --target-key-id $(aws kms create-key --query KeyMetadata.Arn --output text)
Вход в полноэкранный режим Выход из полноэкранного режима
  • В дальнейшем мы будем использовать ARN созданного CMK, поэтому давайте сохраним его как переменную окружения.
export MASTER_ARN=$(aws kms describe-key --key-id alias/demo-eks --query KeyMetadata.Arn --output text)
echo $MASTER_ARN > master_arn.txt
Войти в полноэкранный режим Выйти из полноэкранного режима

Шаг (2) — Настройка VPC

  • Теперь мы создадим новый VPC, который будет использоваться кластером EKS, который мы создадим позже.

  • eks-vpc-3az.yaml — это файл, который будет использоваться CloudFormation для создания ресурсов ниже.

    • VPC.
    • 3 публичные подсети.
    • 3 частные подсети.
    • 1 интернет-шлюз.
    • 3 NAT-шлюза.
    • 3 публичные таблицы маршрутов и 3 частные таблицы маршрутов для каждой подсети соответственно.
    • Группы безопасности для кластера EKS.
  • Давайте создадим этот VPC с помощью следующей команды.

  aws cloudformation deploy 
    --stack-name "demo-eks-vpc"
    --template-file "eks-vpc-3az.yaml"
    --capabilities CAPABILITY_NAMED_IAM
Войти в полноэкранный режим Выход из полноэкранного режима
  • Примерно через 5 минут мы видим, что в AWS Management Console был создан совершенно новый VPC.

  • Перейдя на страницу CloudFormation, после выбора стека «demo-eks-vpc», мы можем увидеть результаты, как показано ниже на вкладке output.


(3) Обеспечение кластера EKS с помощью eksctl

Установка переменных окружения

  • ID VPC, который мы создали в шаге (2), и ID подсети будут часто использоваться в этом шаге, поэтому запустим скрипт, как показано ниже, чтобы использовать их в качестве переменных окружения.
#VPC ID
export vpc_ID=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=demo-eks-vpc | jq -r '.Vpcs[].VpcId')
echo $vpc_ID

#Subnet ID, CIDR, Subnet Name
aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)'
echo $vpc_ID > vpc_subnet.txt
aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' >> vpc_subnet.txt
cat vpc_subnet.txt

# Store VPC ID, Subnet IDs as environment variables.
export PublicSubnet01=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PublicSubnet01/{print $1}')
export PublicSubnet02=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PublicSubnet02/{print $1}')
export PublicSubnet03=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PublicSubnet03/{print $1}')
export PrivateSubnet01=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PrivateSubnet01/{print $1}')
export PrivateSubnet02=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PrivateSubnet02/{print $1}')
export PrivateSubnet03=$(aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_ID | jq -r '.Subnets[]|.SubnetId+" "+.CidrBlock+" "+(.Tags[]|select(.Key=="Name").Value)' | awk '/demo-eks-vpc-PrivateSubnet03/{print $1}')
echo "export vpc_ID=${vpc_ID}" | tee -a ~/.bash_profile
echo "export PublicSubnet01=${PublicSubnet01}" | tee -a ~/.bash_profile
echo "export PublicSubnet02=${PublicSubnet02}" | tee -a ~/.bash_profile
echo "export PublicSubnet03=${PublicSubnet03}" | tee -a ~/.bash_profile
echo "export PrivateSubnet01=${PrivateSubnet01}" | tee -a ~/.bash_profile
echo "export PrivateSubnet02=${PrivateSubnet02}" | tee -a ~/.bash_profile
echo "export PrivateSubnet03=${PrivateSubnet03}" | tee -a ~/.bash_profile
source ~/.bash_profile
Войти в полноэкранный режим Выйти из полноэкранного режима
  • После выполнения всех команд, приведенных выше, идентификаторы VPC и подсети будут сохранены в переменных окружения. Также будет создан файл vpc_subnet.txt, который будет выглядеть следующим образом.
vpc-0e88a2ed7a32c0336
subnet-02b5356084f4355cb 10.11.16.0/20 demo-eks-vpc-PublicSubnet02
subnet-0ea280f1567234a3b 10.11.253.0/24 demo-eks-vpc-TGWSubnet03
subnet-0a79d22a3acf610bf 10.11.32.0/20 demo-eks-vpc-PublicSubnet03
subnet-0c96f4c64e724524b 10.11.251.0/24 demo-eks-vpc-TGWSubnet01
subnet-0d5d255e8542cf405 10.11.64.0/20 demo-eks-vpc-PrivateSubnet02
subnet-0c3c37774542ac95c 10.11.252.0/24 demo-eks-vpc-TGWSubnet02
subnet-07f97eaa984b5ced2 10.11.0.0/20 demo-eks-vpc-PublicSubnet01
subnet-0ebb353a91c36ab17 10.11.48.0/20 demo-eks-vpc-PrivateSubnet01
subnet-0e3c3abe52dbe07e8 10.11.80.0/20 demo-eks-vpc-PrivateSubnet03
Вход в полноэкранный режим Выход из полноэкранного режима
  • Давайте также сохраним код региона AWS.
export AWS_REGION=ap-northeast-2 # in my case
Вход в полноэкранный режим Выход из полноэкранного режима

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

  • Имя кластера и версия Kubernetes будут использоваться в yaml-файлах, поэтому давайте сохраним их как переменные окружения.
export ekscluster_name="demo-eks"
export eks_version="1.21"
Вход в полноэкранный режим Выход из полноэкранного режима
  • Для создания кластера EKS мы будем использовать файл eks-cluster-3az.yaml.

  • Мы настроим узлы на использование Fargate вместо EC2, и, согласно этой документации, Fargate должен быть предоставлен в частных подсетях.

  • Выполним приведенную ниже команду, чтобы заполнить переменные окружения фактическими значениями в eks-cluster-3az.yaml

cat << EOF > eks-cluster-3az.yaml
# A simple example of ClusterConfig object:
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: ${ekscluster_name}
  region: ${AWS_REGION}
  version: "${eks_version}"

vpc:
  id: ${vpc_ID}
  subnets:
    private:
      PrivateSubnet01:
        az: ${AWS_REGION}a
        id: ${PrivateSubnet01}
      PrivateSubnet02:
        az: ${AWS_REGION}b
        id: ${PrivateSubnet02}
      PrivateSubnet03:
        az: ${AWS_REGION}c
        id: ${PrivateSubnet03}

secretsEncryption:
  keyARN: ${MASTER_ARN}

fargateProfiles:
  - name: demo-dev-fp
    selectors:
      - namespace: demo-dev
      - namespace: kube-system
    subnets:
      - ${PrivateSubnet01}
      - ${PrivateSubnet02}
      - ${PrivateSubnet03}

cloudWatch:
  clusterLogging:
    enableTypes:
      ["api", "audit", "authenticator", "controllerManager", "scheduler"]

EOF
Войти в полноэкранный режим Выйти из полноэкранного режима

Профиль Fargate необходим для запуска ресурсов на Fargate.(fargateProfiles). Любые ресурсы, которые соответствуют критериям, определенным в fargateProfiles.selectors, будут запускаться на Fargate.
В примере выше мы использовали demo-dev, пространство имен, которое будут использовать ресурсы, связанные с приложением, и kube-system.
kube-system будет использоваться для предоставления дополнительных ресурсов, таких как aws-load-balancer-controller, который мы установим позже.
Если мы исключим пространство имен kube-system, то при установке aws-load-balancer-controller мы получим ошибку, как показано ниже.

ingress 0/2 nodes are available: 2 node(s) had taint {eks.amazonaws.com/compute-type: fargate}, that the pod didn't tolerate.
  • Теперь выполним приведенную ниже команду для создания кластера!
eksctl create cluster --config-file=eks-cluster-3az.yaml
Вход в полноэкранный режим Выход из полноэкранного режима

Подключение к кластеру EKS

  • Когда мы выполним команду kubectl get svc, мы получим результат, как показано ниже, что означает, что кластер EKS готов!
# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP   43m
Вход в полноэкранный режим Выход из полноэкранного режима

Значение PORT(S) может быть другим, но не волнуйтесь.


(4) Развертывание приложения!

  • Во-первых, давайте создадим пространство имен Kubernetes, где мы будем создавать ресурсы для нашего приложения.

Выше, когда мы создавали профиль faragte, мы поместили namespace: demo-dev в поле fargateProfiles.selectors.

kubectl create ns demo-dev
Вход в полноэкранный режим Выход из полноэкранного режима

Установка дополнения AWS Load Balancer Controller

  • AWS Load Balancer Controller управляет AWS Elastic Load Balancers(ELB), используемыми кластером Kubernetes. Этот контроллер обеспечивает:

    • Предоставление нового AWS ALB при создании Kubernetes Ingress.
    • Предоставление нового AWS NLB при создании Kubernetes LoadBalancer.
  • Перед установкой AWS Load Balancer Controller необходимо сначала интегрировать провайдера OIDC.

  • Настройка OIDC ID Provider(IdP) в кластере EKS позволяет использовать роли AWS IAM для учетных записей служб Kubernetes, а это требует наличия провайдера IAM OIDC в кластере. Выполним приведенную ниже команду для интеграции OIDC в кластер.

eksctl utils associate-iam-oidc-provider --cluster demo-eks --approve
# 2022-08-23 16:04:39 [ℹ]  will create IAM Open ID Connect provider for cluster "demo-eks" in "ap-northeast-2"
# 2022-08-23 16:04:40 [✔]  created IAM Open ID Connect provider for cluster "demo-eks" in "ap-northeast-2"
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь мы готовы к установке дополнения AWS Load Balancer Controller! Установите его, следуя шагам, описанным в этой документации.

Развертывание приложения

  • В моем случае я использовал приложение, которое по умолчанию использовало порт номер 8080. Я не хотел менять номер порта по умолчанию, поэтому я создал простой yaml файл (deployment.yaml) для развертывания Kubernetes, а также создал yaml файл для Kubernetes Service, как показано ниже.
apiVersion: v1
kind: Service
metadata:
  name: demo-dev-svc
  namespace: demo-dev
spec:
  selector:
    app: demo
  ports:
   -  protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort
Вход в полноэкранный режим Выход из полноэкранного режима
  • Как вы можете видеть, тип сервиса NodePort, и тип должен быть NodePort при использовании Fargate на EKS.

  • Кроме того, сервис будет получать запросы с порта номер 80, и перенаправлять запрос в pods, используя порт pod’s номер 8080.

  • Наконец, давайте создадим Kubernetes Ingress, который в конечном итоге создаст AWS ALB с помощью дополнения AWS Load Balancer Controller.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-dev-ingress
namespace: demo-dev
annotations:
  alb.ingress.kubernetes.io/load-balancer-name: demo-dev-lb
  alb.ingress.kubernetes.io/scheme: internet-facing
  alb.ingress.kubernetes.io/target-type: ip
  alb.ingress.kubernetes.io/subnets: ${PUBLIC_SUBNET_IDS}
  alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
  alb.ingress.kubernetes.io/certificate-arn: ${ACM_CERT_ARN}
  alb.ingress.kubernetes.io/security-groups: ${SECURITY_GROUP_FOR_ALB}
  alb.ingress.kubernetes.io/healthcheck-port: "8080"
  alb.ingress.kubernetes.io/healthcheck-path: /actuator/health
  alb.ingress.kubernetes.io/success-codes: "200"
spec:
ingressClassName: alb
rules:
  - host: alb-url.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: demo-dev-svc
              port:
                number: 80
Вход в полноэкранный режим Выход из полноэкранного режима
  • В спецификации мы заставим ALB перенаправлять все запросы к сервису demo-dev-svc Kubernetes.

  • Об аннотациях вы можете прочитать в этом документе.

  • Обратите внимание, что alb.ingress.kubernetes.io/target-type должен быть установлен в ip при использовании Fargate.

  • Также ALB, созданный при создании этого Ingress, должен получать трафик из интернета, поэтому его следует разместить в публичных подсетях(alb.ingress.kubernetes.io/subnets: ${PUBLIC_SUBNET_IDS}), и он должен быть ориентирован на интернет(alb.ingress.kubernetes.io/scheme: internet-facing).

  • Теперь, когда мы применим новый Ingress к Kubernetes, будет создан новый ALB с соответствующим настроенным правилом слушателя.

  • Но когда мы просмотрим проверку работоспособности ALB на целевых группах, она завершится неудачей, сообщив 504 gateway timeout.
    поскольку группа безопасности по умолчанию, прикрепленная к стручкам Fargate, не разрешает входящие запросы на порт 8080.

Решение проблемы: 504 таймаут шлюза

  • Это происходит потому, что стандартная группа безопасности, подключенная к капсулам Fargate, не разрешает входящие запросы на порт 8080.

  • Поэтому нам нужно настроить пользовательские группы безопасности для стручков Fargate, что описано в этой документации.

  • Согласно документации выше, новая группа безопасности должна:

    • Разрешить входящий запрос на порт 53(TCP) от группы безопасности кластера EKS.
    • Разрешить входящий запрос на порт 53(UDP) от группы безопасности кластера EKS.
  • Давайте создадим новую группу безопасности и применим приведенный ниже yaml-файл.

apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: dev-sgp
namespace: demo-dev
spec:
podSelector:
  matchLabels:
    app: demo
securityGroups:
  groupIds:
    - ${NEW_CREATED_SECURITY_GROUP_ID}
    - ${EKS_CLUSTER_SECURITY_GROUP_ID}
Вход в полноэкранный режим Выход из полноэкранного режима
  • Когда мы применим yaml-файл, мы должны перезапустить все капсулы, так как новая группа безопасности не повлияет на уже запущенные капсулы.

  • Теперь, когда мы проверяем состояние ALB, мы видим, что проверка состояния целевых групп успешно выполнена, и все цели здоровы.

Подведение итогов

  • Вот и все! В этом посте я не хотел фокусироваться на основах Kubernetes, но хотел поделиться тем, как я устранял проблемы, с которыми столкнулся в процессе развертывания.

  • Кроме того, существует масса документов, с которыми можно ознакомиться, когда мы сталкиваемся с какими-либо проблемами при развертывании ресурсов Kubernetes. Я хотел свести эти документы к тому, что нам действительно нужно увидеть, поэтому я включил в этот пост так много ссылок на документы.

Дополнительно

  • Когда мы войдем в AWS Management Console с учетной записью root и посетим страницу сервиса EKS, мы увидим предупреждение, как показано ниже.
Your current user or role does not have access to Kubernetes objects on this EKS cluster This may be due to the current user or role not having Kubernetes RBAC permissions to describe cluster resources or not having an entry in the cluster’s auth config map.
Войти в полноэкранный режим Выйти из полноэкранного режима
  • Если вы хотите просмотреть свои ресурсы на кластере EKS, выполните следующую команду.
kubectl edit configmap aws-auth -n kube-system
Войти в полноэкранный режим Выйти из полноэкранного режима
  • И добавьте следующие поля на ту же глубину, что и mapRoles.
mapUsers: |
  - userarn: arn:aws:iam::[account_id]:root
  groups:
  - system:masters
Войти в полноэкранный режим Выйти из полноэкранного режима
  • После сохранения и выхода вы сможете просматривать все ресурсы в вашем кластере EKS.

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