Рубрики
Uncategorized

AWS Elastic Kubernetes Service: автоматизация создания кластера, часть 2 — Anisible, eksctl

AWS Elastic Cubernetes Service: Автоматизация создания кластера, часть 2 — Anisible, eksctl … Теги с Кубернетами, AWS, DEVOPS, Учебником.

AWS Elastic Kubernetes Service: автоматизация создания кластера, часть 2 — Anisible, eksctl

Первая часть — AWS Elastic Kubernetes Service: автоматизация создания кластера, часть 1 — облачность Отказ

Напомнить всю идею состоит в том, чтобы создать процесс автоматизации для создания кластера EKS:

  1. Anisible использует Модуль CloudFormation создать инфраструктуру
  2. Используя выходы создания стека CloudFormation — Anisible из шаблона будет генерировать файл Cluster-Config для eksctl
  3. Аналимые вызовы eksctl с этим конфигурацией для создания кластера EKS

Все это будет сделано с работы Jenkins с использованием документа докера с AWS CLI, Anbible и eksctl. Может быть, это будет третья часть этой серии.

Все приведенные файлы после написания этого поста доступны в eksctl-cf-ansible Репозиторий GitHub. Ссылка здесь состоит в отделении с точной копией кода ниже.

Содержание

Аутентификация AWS.

Стоит задуматься о аутентификации заранее, чтобы не переделать все с нуля (я сделал).

Кроме того, настоятельно рекомендуется читать Kubernetes: Часть 4 — Аутентификация AWS EKS, AWS-IAM-Authenticator, а AWS IAM Пост, так как в этом текущем посте будет использоваться много вещей, описанных там.

Итак, нам нужно иметь некоторый механизм аутентификации AWS, потому что нам нужно аутентифицировать:

  • Обязательный для его облачность роль
  • Обязательный для его Экктл роль
  • Anbible для выполнения команд AWS CLI

Наиболее неочевидной проблемой вот тот факт, что пользователь IAM используется для создания кластера EKS, становится его «Super-admin», и вы не можете его изменить.

Например, в предыдущей части мы создали кластер с помощью следующей команды:

$ eksctl --profile arseniy create cluster -f eks-cluster-config.yml

Теперь вы можете проверить журналы Authenticator в CloudWatch, самые первые записи там — и вы увидите корневицу из системы: Masters Group с разрешениями Kubernetes-Admin:

Ну — что мы можем использовать для аутентификации AWS ??

  1. Ключи доступа — AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY
  2. AWS CLI по имени профили
  3. AWS IAM EC2 Профили экземпляра (См. Также AWS: IAM Присётчик — Описание, Примеры , Рус Несомненно

Но, как мы будем использовать Jenkins здесь — мы можем использовать свою роль экземпляра IAM EC2 с необходимыми разрешениями.

На данный момент я понял следующую схему:

  • Вручную создать IAM пользователь под названием Eks-root С политикой администратора EKS
  • Jenkins создаст необходимые ресурсы, используя свою роль экземпляра IAM с помощью политики администратора EKS и станут «Super-admin» для всех кластеров EKS в учетной записи AWS
  • И в Anisible мы добавим eksctl create iamidentitymapping (см. Управление IAM пользователей и ролей ) добавить дополнительные пользователи.

Проверьте aws-auth. Configmap сейчас:

$ eksctl --profile arseniy --region eu-west-2 get iamidentitymapping --cluster eks-dev
ARN USERNAME GROUPS
arn:aws:iam::534***385:role/eksctl-eks-dev-nodegroup-worker-n-NodeInstanceRole-UNGXZXVBL3ZP system:node:{{EC2PrivateDNSName}} system:bootstrappers,system:nodes

Или с этим:

$ kubectl -n kube-system get cm aws-auth -o yaml
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::534***385:role/eksctl-eks-dev-nodegroup-worker-n-NodeInstanceRole-UNGXZXVBL3ZP
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
[]
kind: ConfigMap
…

Давайте сделаем все вручную сейчас, чтобы избежать удивления во время создания автоматизации:

  1. Создайте пользователь IAM
  2. Создайте политику «EKS Admin»
  3. Прикрепите эту политику этого пользователя
  4. Настройте локальный профиль AWS CLI с этим пользователем
  5. Настроить локальный Kubectl для этого профиля AWS CLI
  6. Выполнить eksctl Создать iAmidentitymapping
  7. Выполнить kubectl Получить узлы для проверки доступа

Продолжай — создайте пользователя:

$ aws --profile arseniy --region eu-west-2 iam create-user --user-name eks-root
{
"User": {
"Path": "/",
"UserName": "eks-root",
"UserId": "AID***PSA",
"Arn": "arn:aws:iam::534***385:user/eks-root",
"CreateDate": "2020–03–30T12:24:28Z"
}
}

Его ключи доступа:

$ aws --profile arseniy --region eu-west-2 iam create-access-key --user-name eks-root
{
"AccessKey": {
"UserName": "eks-root",
"AccessKeyId": "AKI****45Y",
"Status": "Active",
"SecretAccessKey": "Qrr***xIT",
"CreateDate": "2020–03–30T12:27:28Z"
}
}

Настроить локальный профиль AWS CLI:

$ aws configure --profile eks-root
AWS Access Key ID [None]: AKI***45Y
AWS Secret Access Key [None]: Qrr***xIT
Default region name [None]: eu-west-2
Default output format [None]: json

Попробуйте доступ сейчас — должно быть отклонено:

$ aws --profile eks-roo eks list-clusters
An error occurred (AccessDeniedException) when calling the ListClusters operation […]

Создать политику, вот некоторые Примеры >>> (Позже его можно добавить в стопку облака в виде вложенного стека, таким же образом, безопасные группы будут управляться), сохраните его в выделенном файле ../../CloudFormation/files/eks-root-policy.json:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "eks:*"
            ],
            "Resource": "*"
        }
    ]
}

Добавьте эту политику в AWS IAM:

$ aws --profile arseniy --region eu-west-2 iam create-policy --policy-name eks-root-policy --policy-document file://../../cloudformation/files/eks-root-policy.json
{
"Policy": {
"PolicyName": "eks-root-policy",
"PolicyId": "ANPAXY5JMBMEROIOD22GM",
"Arn": "arn:aws:iam::534***385:policy/eks-root-policy",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2020–03–30T12:44:58Z",
"UpdateDate": "2020–03–30T12:44:58Z"
}
}

Прикрепите политику пользователю, созданному выше:

$ aws --profile arseniy --region eu-west-2 iam attach-user-policy --user-name eks-root --policy-arn arn:aws:iam::534***385:policy/eks-root-policy

Проверять:

$ aws --profile arseniy --region eu-west-2 iam list-attached-user-policies --user-name eks-root --output text
ATTACHEDPOLICIES arn:aws:iam::534***385:policy/eks-root-policy eks-root-policy

Попробуйте получить доступ снова:

$ aws --profile eks-root --region eu-west-2 eks list-clusters --output text
CLUSTERS eks-dev

И в другом регионе:

$ aws --profile eks-root --region us-east-2 eks list-clusters --output text
CLUSTERS eksctl-bttrm-eks-production-1
CLUSTERS mobilebackend-dev-eks-0-cluster

Следующие задачи будут лучше сделать из коробки без сконфигурированного доступа вообще, например — с сервера блога RTFM:-)

Установите AWS CLI:

root@rtfm-do-production:/home/setevoy# pip install awscli

Настройте профиль по умолчанию:

root@rtfm-do-production:/home/setevoy# aws configure

Проверьте доступ к AWS EKS в целом — в нашей политике IAM мы предоставили разрешения на EKS: ListClusters API-call, поэтому он должен работать:

root@rtfm-do-production:/home/setevoy# aws eks list-clusters — output text
CLUSTERS eks-dev

Хорошо.

Установите eksctl:

root@rtfm-do-production:/home/setevoy# curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
root@rtfm-do-production:/home/setevoy# mv /tmp/eksctl /usr/local/bin

Повторите EKS: ListClusters — также должен работать, так как Eksctl будет использовать по умолчанию Профиль AWS CLI настроен выше:

root@rtfm-do-production:/home/setevoy# eksctl get cluster
NAME REGION
eks-dev eu-west-2

Установите Kubectl:

root@rtfm-do-production:/home/setevoy# curl -LO [https://storage.googleapis.com/kubernetes-release/release/`curl](https://storage.googleapis.com/kubernetes-release/release/%60curl) -s [https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl](https://storage.googleapis.com/kubernetes-release/release/stable.txt%60/bin/linux/amd64/kubectl)

root@rtfm-do-production:/home/setevoy# chmod +x ./kubectl

root@rtfm-do-production:/home/setevoy# mv ./kubectl /usr/local/bin/kubectl

Установите AWS-IAM-Authenticator, чтобы позволить Kubectl выполнять аутентификацию в AWS:

root@rtfm-do-production:/home/setevoy# curl -o aws-iam-authenticator [https://amazon-eks.s3.us-west-2.amazonaws.com/1.15.10/2020-02-22/bin/linux/amd64/aws-iam-authenticator](https://amazon-eks.s3.us-west-2.amazonaws.com/1.15.10/2020-02-22/bin/linux/amd64/aws-iam-authenticator)

root@rtfm-do-production:/home/setevoy# chmod +x ./aws-iam-authenticator

root@rtfm-do-production:/home/setevoy# mv aws-iam-authenticator /usr/local/bin/

Настроить kubectl:

root@rtfm-do-production:/home/setevoy# aws eks update-kubeconfig --name eks-dev
Updated context arn:aws:eks:eu-west-2:534***385:cluster/eks-dev in /root/.kube/config

Попробуйте выполнить команду в кластере — должна быть ошибка авторизации:

root@rtfm-do-production:/home/setevoy# kubectl get nodes
error: You must be logged in to the server (Unauthorized)

root@rtfm-do-production:/home/setevoy# kubectl get pod
error: You must be logged in to the server (Unauthorized)

Вернитесь на рабочий компьютер и добавьте Eks-root Пользователь к AWS-AUTH Configmap:

$ eksctl --profile arseniy --region eu-west-2 create iamidentitymapping --cluster eks-dev --arn arn:aws:iam::534***385:user/eks-root --group system:masters --username eks-root
[ℹ] eksctl version 0.16.0
[ℹ] using region eu-west-2
[ℹ] adding identity "arn:aws:iam::534***385:user/eks-root" to auth ConfigMap

Проверь это:

$ eksctl --profile arseniy --region eu-west-2 get iamidentitymapping --cluster eks-dev
ARN USERNAME GROUPS
arn:aws:iam::534***385:role/eksctl-eks-dev-nodegroup-worker-n-NodeInstanceRole-UNGXZXVBL3ZP system:node:{{EC2PrivateDNSName}} system:bootstrappers,system:nodes
arn:aws:iam::534***385:user/eks-root eks-root system:masters

Вернитесь к хосту тестирования и попробуйте снова получить доступ:

root@rtfm-do-production:/home/setevoy# kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10–0–40–30.eu-west-2.compute.internal Ready  133m v1.15.10-eks-bac369
ip-10–0–63–187.eu-west-2.compute.internal Ready  133m v1.15.10-eks-bac369

И давайте проверим что-то еще, то же самое aws-auth. Например configmap:

root@rtfm-do-production:/home/setevoy# kubectl -n kube-system get cm aws-auth -o yaml
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::534***385:role/eksctl-eks-dev-nodegroup-worker-n-NodeInstanceRole-UNGXZXVBL3ZP
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- groups:- system:masters
userarn: arn:aws:iam::534***385:user/eks-root
username: eks-root
kind: ConfigMap
…

Mapusers с нашим пользователем добавили — все хорошо здесь.

Позже мы можем использовать это AWS-AUTH Чтобы добавить новых пользователей или добавить задачу доступным для выполнения eksctl Создать iAmidentitymapping, или мы можем создать нашу собственную конфигурацию и загрузить его на экс.

Я приступим к задачам от наших хостов Дженкинса, как у нас есть погибший доступно в любом месте.

Обязательная облачность

Параметры облака и аналимыми переменными

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

Первое, что имеется в виду, это акт, что у нас будет Dev , Этап , Производство Cluster + Dynamic для команды QA (чтобы позволить им возможность создавать выделенный пользовательский кластер из задания Jenkins для проверки чего-либо), поэтому параметры должны быть достаточно гибкими, чтобы создать стек в любом регионе с любыми сетями VPC.

Таким образом, у нас будет:

  • Общие параметры для всех:
  • область, край
  • AWS Access/Secret (или IAM EC2 Профиль экземпляра )
  • Выделенные параметры для окружающей среды:
  • Env (Dev, Stage, Prod)
  • VPC CIDR (10.0.0.0/16, 10.1.0.0.0/16 и т. Д.)
  • SSH Ключ для Kubernetes Working Ussies Access
  • AWS ES2 Типы экземпляров для рабочих узлов Kubernetes (T3.NANO, C5.9xLarge и т. Д.)

В частности, стоит обратить внимание на именования стеков и кластеров.

Итак, мы будем иметь для имена, которые используются «глобально» над непредвиденным PlayBook и ролями, и которые мы увидим позже в консоли AWS:

  1. Имя окружающей среды — dev , Этап , продлицо
  2. Имя стека облака, созданное нами из облачность Роль (корневой стек и его вложенные стеки)
  3. Имя стека облака, созданное eksctl при создании кластера и его работников узлов
  4. и Название кластера EKS

Эккт, конечно, сделает некоторые вещи за сценой и добавит некоторые префиксы-постфиксы на имена здесь.

Например, при создании стека для самого кластера EKS — он добавит свое имя стека облака с помощью eksctl- префикс и добавлю a -Кустер Postfix, а для его Wokernodes Stacks — будет использовать префикс Экктл- и постфикс -нодегруппа + Имя группы рабочих пользователей из кластера Config-файл.

Но все же сам кластер будет назван именно так, как мы устанавливаем его в EKS-Cluster-Config.yml.

Итак, давайте вообще схватим — какие переменные мы будем использовать:

  • env:
  • Формат: строка » dev «
  • Описание: Используется для составных значений для других переменных
  • Результат: дев
  • eks_cluster_name:
  • Формат: BTTRM-EKS — $ {ENV}
  • Описание: Установите метаданные: name: в Eks-Cluster-Config.yml Cluster-Config будет использоваться для состоить значения для других переменных и Облачные метки
  • Результат: bttrm-eks-dev
  • cf_stack_name:
  • Формат: eksctl — $ {eks_cluster_name} -stack
  • Описание: С — куча Здесь мы отмечаем, что это содержит только доступные ресурсы AWS, Нет экс
  • результат: eksctl-bttrm-eks-dev-stack
  • (Авто) eks_cluster_stack_name:
  • Формат: eksctl — $ {cluster_name} -Cluster
  • Описание: будет создан сам EksCtl для стека облака, просто помня
  • результат: eksctl-bttrm-eks-dev-cluster
  • (Авто) eks_nodegroup_stack_name:
  • Формат: eksctl — $ {cluster_name} -nodegroup — $ {рабочие-узлов-имя}, где Рабочий-узлов-имя — это значение из узлов: — Имя: из кластерной конфигурации EKS-Cluster-Config.yml
  • Описание: будет создан сам EksCtl для стека облака, просто помня
  • результат: eksctl-bttrm-eks-dev-cluster

Что касается разных файлов для различных сред — на данный момент, можно использовать Common Group_vars/all.yml, а позже увидим, как сделать их разделенными.

Создать каталог:

$ mkdir group_vars

Создайте файл All.yml и установите начальные значения:

###################
# ANSIBLE globals #
###################

ansible_connection: local

#####################
# ENV-specific vars #
#####################

env: "dev"

#################
# ROLES globals #
#################

region: "eu-west-2"

# (THIS) eks_cluster_name: used for EKS service to set an exactly cluster's name - "{{ eks_cluster_name }}"
# (AUTO) eks_cluster_stack_name: used for CloudFormation service to format a stack's name as "eksctl-{{ eks_cluster_name }}-cluster"
# (AUTO) eks_nodegroup_stack_name: used for CloudFormation service to format a stack's name as "eksctl-{{ eks_cluster_name }}-nodegroup-{{ worker-nodes-name }}"
eks_cluster_name: "bttrm-eks-{{ env }}"

# used bythe cloudformation role to st a stack's name
cf_stack_name: "eksctl-{{ eks_cluster_name }}-stack"

##################
# ROLES specific #
##################

# cloudforation role
vpc_cidr_block: "10.0.0.0/16"

Также поставьте общие переменные здесь, как регион — он будет использоваться облачность и Экктл Роли, а VPC_CIDR_BLOCK — только в облачность Отказ

Роль облака

После того, как мы закончили наши шаблоны в Предыдущая часть У нас должны быть следующие каталоги и файлы сооружения:

$ tree
.
└── roles
├── cloudformation
│ ├── files
│ │ ├── eks-azs-networking.json
│ │ ├── eks-region-networking.json
│ │ └── eks-root.json
│ ├── tasks
│ └── templates
└── eksctl
├── tasks
└── templates
└── eks-cluster-config.yml

Теперь, в корне репозитория Создайте новый файл EKS-Cluster.yml — это будет наш наш Anisible Playbook.

Добавьте облачность Исполнение там:

- hosts:
  - all
  become:
    true
  roles:
    - role: cloudformation
      tags: infra

Добавить теги, которые могут быть в состоянии позже запустить роли самостоятельно — будут полезны, когда мы начнем писать роль для Eksctl.

Создать роли/облачность/задачи/задачи/main.yml файл — добавьте облачность Выполнение модуля Здесь и установите необходимые параметры для наших шаблонов через Template_Parameters — VPCCIDRBLOCK из переменной VPC_CIDR_BLOCK и параметр eksclustername из переменной eks_cluster_name:

- name: "Create EKS {{ cf_stack_name | upper }} CloudFormation stack"
  cloudformation:
    region: "{{ region }}"
    stack_name: "{{ cf_stack_name }}"
    state: "present"
    disable_rollback: true
    template: "/tmp/packed-eks-stacks.json"
    template_parameters:
      VPCCIDRBlock: "{{ vpc_cidr_block }}"
      EKSClusterName: {{ eks_cluster_name }},
    tags:
      Stack: "{{ cf_stack_name }}"
      Env: "{{ env }}"
      EKS-cluster: "{{ eks_cluster_name }}"

Не использовал неспособных в течение половины года — забыл все (

Google для » Аналимый инвентарь » — и прочитал Лучшие практики

В корне репозитория создайте файл Ansible.cfg с некоторыми значениями по умолчанию:

[defaults]
gather_facts = no
inventory = hosts.yml

В том же месте создайте файл инвентаризации — Hosts.yml:

all:
  hosts:
    "localhost"

W ERA E Использование localhost Здесь как Anbible не будет использовать ssh где угодно — все задачи будут сделаны локально.

Проверьте синтаксис:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook eks-cluster.yml — syntax-check
playbook: eks-cluster.yml

Выглядит неплохо? Создайте файл шаблона (в трубопроводе Jenkins должен иметь дополнительный этап для этого:

admin@jenkins-production:~/devops-kubernetes$ cd roles/cloudformation/files/

admin@jenkins-production:~/devops-kubernetes/roles/cloudformation/files$ aws --region eu-west-2 cloudformation package --template-file eks-root.json --output-template /tmp/packed-eks-stacks.json --s3-bucket eks-cloudformation-eu-west-2 --use-json

Successfully packaged artifacts and wrote output template to file /tmp/packed-eks-stacks.json.

Выполните следующую команду для развертывания упакованного шаблона

$ aws cloudformation deploy --template-file /tmp/packed-eks-stacks.json --stack-name 

Запустите создание стека:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook eks-cluster.yml
…
TASK [cloudformation : Setting the Stack name] ****
ok: [localhost]
TASK [cloudformation : Create EKS EKSCTL-BTTRM-EKS-DEV-STACK CloudFormation stack] ****
changed: [localhost]
PLAY RECAP ****
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Проверять:

Имя стека было установлено как eksctl-bttrm-eks-dev-стек — красивый.

Теперь можно начать писать роль для eksctl для создания самого кластера.

Обязательный Эккт

У нас уже есть файл конфигурации кластера — давайте переименуем его в .j2 (Чтобы заметить его как файл Jinja — неблагомусный шаблон двигатель):

admin@jenkins-production:~/devops-kubernetes$ mv roles/eksctl/templates/eks-cluster-config.yml roles/eksctl/templates/eks-cluster-config.yml.j2

Из стека облака, созданного в первой роли, нам нужно пройти кучу значений здесь — VPC ID, идентификаторы подсети и т. Д., Чтобы установить значения в Cluster Config для eksctl.

Давайте будем использовать неизбежный модуль cloudformation_info Чтобы собрать информацию о созданном стеке.

Добавьте его, сохраните свой вывод в переменную Stack_info, а затем проверите его содержимое.

Создайте новые файловые роли/eksctl/tasks/main.yml:

- cloudformation_info:
    region: "{{ region }}"
    stack_name: "cf_stack_name"
  register: stack_info

- debug:
    msg: "{{ stack_info }}"

Добавьте исполнение ролей EksCTL в Playbook Eks-Cluster.yml, добавьте теги:

- hosts:
  - all
  become:
    true
  roles:
    - role: cloudformation
      tags: infra
    - role: eksctl
      tags: eks

Запустите использование EKSTAGS EKS, чтобы выполнить только роль EksCTL:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook — tags eks eks-cluster.yml
…
TASK [eksctl : cloudformation_info] ****
ok: [localhost]
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": {
"changed": false,
"cloudformation": {
"eksctl-bttrm-eks-dev-stack": {
"stack_description": {
…
"outputs": [
{
"description": "EKS VPC ID",
"output_key": "VPCID",
"output_value": "vpc-042082cd2d011f44d"
},
…

Прохладно.

Теперь — давайте сократим только блок {«выводы»}.

Обновите задачу — от Stack_info в MSG Pass только Stack_Outputs:

- cloudformation_info:
    region: "{{ region }}"
    stack_name: "{{ cf_stack_name }}"
  register: stack_info

- debug:
    msg: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs }}"

Бежать:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook — tags eks eks-cluster.yml
…
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": {
"APrivateSubnetID": "subnet-0471e7c28a3770828",
"APublicSubnetID": "subnet-07a0259b33ddbcb4c",
"AStackAZ": "eu-west-2a",
"BPrivateSubnetID": "subnet-0fa6eece43b2b6644",
"BPublicSubnetID": "subnet-072c107cef77fe859",
"BStackAZ": "eu-west-2b",
"VPCID": "vpc-042082cd2d011f44d"
}
}
…

НИИЦА!

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

Обновите роли/eksctl/tasks/main.yml, добавьте переменную VPC_ID и распечатайте ее через Debug, чтобы проверить его значение:

- cloudformation_info:
    region: "{{ region }}"
    stack_name: "{{ cf_stack_name }}"
  register: stack_info

- debug:
    msg: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs }}"

- set_fact:
    vpc_id: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.VPCID }}"

- debug:
    msg: "{{ vpc_id }}"

- name: "Check template's content"
  debug:
    msg: "{{ lookup('template', './eks-cluster-config.yml.j2') }}"

В « Проверьте содержимое шаблона »Путем прямого вызова Шаблон Модуль Давайте проверим, что мы будем иметь в качестве приведенного файла из файла шаблона.

Редактировать роли/eksctl/шаблоны/eks-cluster-config.yml.j2 — установите {{vpc_id}} :

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: eks-dev
  region: eu-west-2
  version: "1.15"
nodeGroups:
  - name: worker-nodes
    instanceType: t3.medium
    desiredCapacity: 2
    privateNetworking: true
vpc:
  id: "{{ vpc_id }}"
  subnets:
    public:
      eu-west-2a:
...

Проверять:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook — tags eks eks-cluster.yml
…
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": {
"APrivateSubnetID": "subnet-0471e7c28a3770828",
"APublicSubnetID": "subnet-07a0259b33ddbcb4c",
"AStackAZ": "eu-west-2a",
"BPrivateSubnetID": "subnet-0fa6eece43b2b6644",
"BPublicSubnetID": "subnet-072c107cef77fe859",
"BStackAZ": "eu-west-2b",
"VPCID": "vpc-042082cd2d011f44d"
}
}
TASK [eksctl : set_fact] *****ok: [localhost]
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": "vpc-042082cd2d011f44d"
}
TASK [eksctl : Check the template's content] ****
ok: [localhost] => {
"msg": "apiVersion: eksctl.io/v1alpha5\nkind: ClusterConfig\nmetadata:\n name: eks-dev\n region: eu-west-2\n version: \"1.15\"\nnodeGroups:\n — name: worker-nodes\n instanceType: t3.medium\n desiredCapacity: 2\n privateNetworking: true\nvpc:\n id: \"vpc-042082cd2d011f44d\"\n […]

VPC: \ N ID: \ «VPC-VPC-042082CD2D011F44D \» — Хорошо, мы получили наш VPC ID в шаблоне.

Добавьте другие вариалы, поэтому шаблон будет выглядеть так:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: "{{ eks_cluster_name }}"
  region: "{{ region }}"
  version: "{{ k8s_version }}"
nodeGroups:
  - name: "{{ k8s_worker_nodes_group_name }}"
    instanceType: "{{ k8s_worker_nodes_instance_type }}"
    desiredCapacity: {{ k8s_worker_nodes_capacity }}
    privateNetworking: true
vpc:
  id: "{{ vpc_id }}"
  subnets:
    public:
      {{ a_stack_az }}:
        id: "{{ a_stack_pub_subnet }}"
      {{ b_stack_az }}:
        id: "{{ b_stack_pub_subnet }}"
    private:
      {{ a_stack_az }}:
        id: "{{ a_stack_priv_subnet }}"
      {{ b_stack_az }}:
        id: "{{ b_stack_priv_subnet }}"
  nat:
    gateway: Disable
cloudWatch:
  clusterLogging:
    enableTypes: ["*"]

Далее необходимо добавить дополнительные переменные для Anbible для использования в этом шаблоне:

  • eks_cluster_name — уже добавлено
  • VPC_ID — уже добавлено
  • Для стека доступныхzone-а нужно добавить:
  • a_stack_pub_subnet.
  • a_stack_priv_subnet.
  • Для доступныхzone-™ надо добавить:
  • a_stack_pub_subnet.
  • a_stack_priv_subnet.
  • регион — уже добавляется, будет установлен позже от параметров Jenkins
  • kubernetes_version.
  • kubernetes_worker_nodes_group_name.
  • kubernetes_worker_nodes_instance_type.
  • kubernetes_worker_nodes_capity.

Добавить Set_Facts в ролях/eksctl/tasks/main.yml:

- cloudformation_info:
    region: "{{ region }}"
    stack_name: "{{ cf_stack_name }}"
  register: stack_info

- debug:
    msg: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs }}"

- set_fact:
    vpc_id: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.VPCID }}"
    a_stack_az: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.AStackAZ }}"
    a_stack_pub_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.APublicSubnetID }}"
    a_stack_priv_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.APrivateSubnetID }}"
    b_stack_az: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BStackAZ }}"
    b_stack_pub_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BPublicSubnetID }}"
    b_stack_priv_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BPrivateSubnetID }}"

- name: "Check the template's content"
  debug:
    msg: "{{ lookup('template', './eks-cluster-config.yml.j2') }}"

В Group_vars/All.yml добавляют значения для Экктл роль:

...
##################
# ROLES specific #
##################

# cloudforation role
vpc_cidr_block: "10.0.0.0/16"

# eksctl role
k8s_version: 1.15
k8s_worker_nodes_group_name: "worker-nodes"
k8s_worker_nodes_instance_type: "t3.medium"
k8s_worker_nodes_capacity: 2

Давайте проверим — на данный момент, позвонив каталог шаблона:

…
TASK [eksctl : Check the template's content] ****
ok: [localhost] => {
"msg": "apiVersion: eksctl.io/v1alpha5\nkind: ClusterConfig\nmetadata:\n name: \"bttrm-eks-dev\"\n region: \"eu-west-2\"\n version: \"1.15\"\nnodeGroups:\n — name: \"worker-nodes\"\n instanceType: \"t3.medium\"\n desiredCapacity: 2\n privateNetworking: true\nvpc:\n id: \"vpc-042082cd2d011f44d\"\n subnets:\n public:\n eu-west-2a:\n id: \"subnet-07a0259b33ddbcb4c\"\n eu-west-2b:\n id: \"subnet-072c107cef77fe859\"\n private:\n eu-west-2a:\n id: \"subnet-0471e7c28a3770828\"\n eu-west-2b:\n id: \"subnet-0fa6eece43b2b6644\"\n nat:\n gateway: Disable\ncloudWatch:\n clusterLogging:\n enableTypes: [\"\*\"]\n"
}
…

«Оно работает!» ©.

Ну — не пришло время запустить экккт.

Cluster Config — eks-cluster-config.yml

Перед вызовом eksctl необходимо создать конфигурацию из шаблона.

В конце ролей/eksctl/tasks/main.yml добавьте шаблон и используя роль/eksctl/chumplates/eks-cluster-config.yml.j2, генерируют файл eks-cluster-config.yml в/tmp каталог:

...
- name: "Generate eks-cluster-config.yml"
  template:
    src: "eks-cluster-config.yml.j2"
    dest: /tmp/eks-cluster-config.yml

Eksctl Создать VS обновление

Примечание. На самом деле, обновление для eksctl выполнит обновление версии вместо обновления конфигурации, но я оставлю эту часть здесь только для примера

Кстати, что если кластер уже существует? Работа потерпит неудачу, так как мы передаем создание.

Ну — мы можем добавить проверку, если кластер уже присутствует, а затем создать переменную для хранения значения Создать или Обновление Точно так же я сделал это в Bash: Скрипт Создания AWS CloudFormation Стека Отказ

Таким образом, надо:

  1. Получить список кластеров EKS в регионе AWS
  2. Попробуйте найти имя кластера, создаваемого в этом списке
  3. Если не нашел тогда установить значение Создайте
  4. Если найдено, установите значение Обновить

Давайте попробуем сделать это таким образом:

# populate a clusters_exist list with names of clusters devided by TAB "\t"
- name: "Getting existing clusters list"
  shell: "aws --region {{ region }} eks list-clusters --query '[clusters'] --output text"
  register: clusters_exist

- debug:
    msg: "{{ clusters_exist.stdout }}"

# create a list from the clusters_exist
- set_fact:
    found_clusters_list: "{{ clusters\_exist.stdout.split('\t') }}"

- debug:
    msg: "{{ found_clusters_list }}"

# check if a cluster's name is found in the existing clusters list
- fail:
    msg: "{{ eks_cluster_name }} already exist in the {{ region }}"
  when: eks_cluster_name not in found_clusters_list

- meta: end_play
...

Эти задачи во время тестирования добавляют в начало ролей/eksctl/tasks/main.yml, а для остановки выполнения после них — добавьте — Meta: end_play.

В состоянии сбоя сейчас установлено « не в », как мы просто тестируем сейчас и не имеем созданного кластера:

…
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": "eks-dev"
}
TASK [eksctl : set_fact] ****
ok: [localhost]
TASK [eksctl : debug] ****
ok: [localhost] => {
"msg": [
"eks-dev"
]
}
TASK [eksctl : fail] ****
fatal: [localhost]: FAILED! => {"changed": false, "msg": "bttrm-eks-dev already exist in the eu-west-2"}
…

Прохладно.

Теперь добавьте переменную Eksctl_action с помощью « Create » или «Обновление », в зависимости от того, был найден кластер или нет:

# populate a clusters_exist list with names of clusters devided by TAB "\t"
- name: "Getting existing clusters list"
  shell: "aws --region {{ region }} eks list-clusters --query '[clusters'] --output text"
  register: clusters_exist

- debug:
    msg: "{{ clusters_exist.stdout }}"

# create a list from the clusters_exist
- set_fact:
    found_clusters_list: "{{ clusters_exist.stdout.split('\t') }}"

- debug:
    msg: "{{ found_clusters_list }}"

- set_fact:
    eksctl_action: "{{ 'create' if (eks_cluster_name not in found_clusters_list) else 'update' }}"

- debug:
    var: eksctl_action

# check if a cluster's name is found in the existing clusters list
- fail:
    msg: "{{ eks_cluster_name }} already exist in the {{ region }}"
  when: eks_cluster_name not in found_clusters_list

...

Проверять:

…
TASK [eksctl : debug] ****
ok: [localhost] => {
"eksctl_action": "create"
}
…

Далее добавьте это на eksctltask — добавьте {{eksctl_action}} Для его аргументов вместо прямых » Создать «:

- cloudformation_info:
    region: "{{ region }}"
    stack_name: "{{ cf_stack_name }}"
  register: stack_info

- set_fact:
    vpc_id: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.VPCID }}"
    a_stack_az: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.AStackAZ }}"
    a_stack_pub_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.APublicSubnetID }}"
    a_stack_priv_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.APrivateSubnetID }}"
    b_stack_az: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BStackAZ }}"
    b_stack_pub_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BPublicSubnetID }}"
    b_stack_priv_subnet: "{{ stack_info.cloudformation[cf_stack_name].stack_outputs.BPrivateSubnetID }}"

- name: "Generate eks-cluster-config.yml"
  template:
    src: "eks-cluster-config.yml.j2"
    dest: /tmp/eks-cluster-config.yml

# populate a clusters_exist list with names of clusters devided by TAB "\t"
- name: "Getting existing clusters list"
  command: "aws --region {{ region }} eks list-clusters --query '[clusters'] --output text"
  register: clusters_exist

# create a list from the clusters_exist
- set_fact:
    found_clusters_list: "{{ clusters_exist.stdout.split('\t') }}"

- name: "Setting eksctl action to either Create or Update"
  set_fact:
    eksctl_action: "{{ 'create' if (eks_cluster_name not in found_clusters_list) else 'update' }}"

- name: "Running eksctl eksctl_action {{ eksctl_action | upper }} cluster with name {{ eks_cluster_name | upper }}"
  command: "eksctl {{ eksctl_action }} cluster -f /tmp/eks-cluster-config.yml"

Момент истины!:-)

Бежать:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook — tags eks eks-cluster.yml
…
TASK [eksctl : cloudformation_info] ****
ok: [localhost]
TASK [eksctl : set_fact] ****
ok: [localhost]
TASK [eksctl : Generate eks-cluster-config.yml] ****
ok: [localhost]
TASK [eksctl : Getting existing clusters list] ****
changed: [localhost]
TASK [eksctl : set_fact] ****
ok: [localhost]
TASK [eksctl : Setting eksctl action to either Create or Update] ****
ok: [localhost]
TASK [eksctl : Running eksctl eksctl_action CREATE cluster with name BTTRM-EKS-DEV]

Стек и кластер создают, зовут стека eksctl-bttrm-dev-кластер — Все, как мы планировали:

Ура!

Оставил только еще один тест.

Тест: CloudFormation && EKS Пользовательские параметры

Последняя вещь для тестирования — это гибкость всего, что мы написали.

Например, команда QA хочет создать совершенно новый кластер с именем Qa-test С VPC CIDR 10.1.0.0/16 .

Обновите group_vars/all.yml, набор:

  • env: » dev «> «
  • qa-test» Регион: « ЕС-Запад-2 «> « ЕС-Запад-3
  • » vpc_cidr_block: « 10.0.0.0/16 «> « 10.1.0.0/16
...
env: "qa-test"
...
region: "eu-west-3"
...
vpc_cidr_block: "10.1.0.0/16"

Завершите шаблон, чтобы повторно Geneteare упакованный EKS-Stack.json:

admin@jenkins-production:~/devops-kubernetes$ cd roles/cloudformation/files/

admin@jenkins-production:~/devops-kubernetes/roles/cloudformation/files$ aws — region eu-west-3 cloudformation package — template-file eks-root.json — output-template packed-eks-stacks.json — s3-bucket eks-cloudformation-eu-west-3 — use-json

Запустите Anbible без NOTTAGS, чтобы создать стопки облака и кластеров EKS с нуля:

admin@jenkins-production:~/devops-kubernetes$ ansible-playbook eks-cluster.yml
…
TASK [cloudformation : Create EKS EKSCTL-BTTRM-EKS-QA-TEST-STACK CloudFormation stack] ****
changed: [localhost]
TASK [eksctl : cloudformation_info] ****
ok: [localhost]
TASK [eksctl : set_fact] ****
ok: [localhost]
TASK [eksctl : Generate eks-cluster-config.yml] ****
changed: [localhost]
TASK [eksctl : Getting existing clusters list] ****
changed: [localhost]
TASK [eksctl : set_fact] ****
ok: [localhost]
TASK [eksctl : Setting eksctl action to either Create or Update] ****
ok: [localhost]
TASK [eksctl : Running eksctl eksctl_action CREATE cluster with name BTTRM-EKS-QA-TEST] ****
…

Подождите, проверьте:

Ура!

На самом деле — вот все.

Конечная вещь будет создать Jenkins-Job.

О, подожди! Забыл о конфигурации.

Слияние AWS-AUTH CONFIGMAP

Неважно, как сильно вы пытаетесь — Ты что-то забудет.

Так — надо добавить Eks-root , пользователь, созданный в самом начале этого поста к кластеру, мы создаем.

Это можно сделать с помощью одной команды и две переменные.

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

В group_vars/all.yml добавить ARN пользователя:

...
eks_root_user_name: "eks-root"
eks_root_user_arn: "arn:aws:iam::534***385:user/eks-root"

А в ролях/eksctl/tasks/main.yml — добавь его в кластер:

...
- name: "Update aws-auth ConfigMap with the EKS root user {{ eks_root_user_name | upper }}"
  command: "eksctl create iamidentitymapping --cluster {{ eks_cluster_name }} --arn {{ eks_root_user_arn }} --group system:masters --username {{ eks_root_user_name }}"

Бежать:

…
TASK [eksctl : Running eksctl eksctl_action UPDATE cluster with name BTTRM-EKS-QA-TEST] ****
changed: [localhost]
TASK [eksctl : Update aws-auth ConfigMap with the EKS root user EKS-ROOT] ****
changed: [localhost]
…

Вернитесь на сервер RTFM, где у нас есть «чистый» доступ только к Eks-root Пользователь, обновите его ~/.kube/config:

root@rtfm-do-production:/home/setevoy# aws — region eu-west-3 eks update-kubeconfig — name bttrm-eks-qa-test
Added new context arn:aws:eks:eu-west-3:53***385:cluster/bttrm-eks-qa-test to /root/.kube/config

Попробуйте получить доступ к узлам Info:

root@rtfm-do-production:/home/setevoy# kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10–1–40–182.eu-west-3.compute.internal Ready  94m v1.15.10-eks-bac369
ip-10–1–52–14.eu-west-3.compute.internal Ready  94m v1.15.10-eks-bac369

И стручки:

root@rtfm-do-production:/home/setevoy# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
aws-node-rgpn5 1/1 Running 0 95m
aws-node-xtr6m 1/1 Running 0 95m
coredns-7ddddf5cc7–5w5wt 1/1 Running 0 102m
…

Готово.

Полезные ссылки

Кубернеты

Неизбежный

Aws

Екс

Облачность

Первоначально опубликовано в RTFM: Linux, DevOps и системное администрирование Отказ

Оригинал: «https://dev.to/setevoy/aws-elastic-kubernetes-service-a-cluster-creation-automation-part-2-ansible-eksctl-4afk»