Предоставление кластера EKS и применение конфигурации Kubernetes с помощью CloudFormation

CloudFormation — отличное решение для инициализации инфраструктуры AWS. Но когда речь заходит о создании кластера Amazon Elastic Kubernetes Service (EKS) с помощью CloudFormation и его загрузке для применения конфигурации Kubernetes, мы сталкиваемся с некоторыми интересными проблемами.

В этой статье мы обсудим эти проблемы более подробно. Я объясню, как мое бессерверное решение на базе CloudFormation может помочь автоматизировать предоставление ресурсов EKS (кластер, группа узлов) и автоматически применить конфигурацию Kubernetes после создания кластера.

Эта статья также была опубликована на Medium.

Самообслуживание Amazon EKS Cluster provisioning with Kubernetes configuration applied | by Chandranath Mondal | Aug, 2022 | Medium

Чандранат Мондал ・・・
Medium

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

В соответствии с документацией AWS:

Когда вы создаете кластер Amazon EKS, пользователь или роль AWS Identity and Access Management (IAM) entity, например, федеративный пользователь, который создает кластер, автоматически получает разрешения system:masters в конфигурации управления доступом на основе ролей (RBAC) кластера в плоскости управления Amazon EKS. Чтобы предоставить дополнительным пользователям или ролям AWS возможность взаимодействовать с кластером, необходимо отредактировать aws-auth ConfigMap в Kubernetes и создать Kubernetes rolebinding или clusterrolebinding с именем группы, которую вы укажете в aws-auth ConfigMap.

Это означает, что мы не можем указать, какие пользователи/группы должны иметь доступ к кластеру во время его инициализации. Он всегда инициализируется только вызывающей идентификацией. В качестве следующего шага мы должны применить конфигурацию Kubernetes для обновления aws-auth ConfigMap. Это достигается выполнением команды kubectl.

А вот и наша первая задача!

ЗАДАЧА 1: Как выполнить команду kubectl из CloudFormation?

Нам нужно заставить CloudFormation вызывать выполнение команды kubectl после создания кластера.

CodeBuild
Это платформа для сборки, где мы можем установить kubectl.

Пользовательский ресурс
Мы можем развернуть пользовательский ресурс CloudFormation с поддержкой Lambda сразу после создания кластера. Пользовательский ресурс выполнит вызов функции Lambda, которая может запустить сборку в проекте CodeBuild для инициализации ConfigMap.

Но теперь перед нами стоит более сложная задача!

ЗАДАЧА 2: Проблема идентификации

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

Следовательно, когда мы создаем кластер EKS через CloudFormation, EKS инициализирует RBAC нового кластера так, чтобы доступ к нему был только у роли CloudFormation Service Role. В качестве следующего шага необходимо выполнить команду kubectl на CodeBuild, но в этот момент только роль CloudFormation Service Role может это сделать. Тогда, как CodeBuild может принять роль CloudFormation Service Role?

Роль службы с несколькими принципами службы
Мы можем создать общую роль службы с несколькими принципами службы, например, CloudFormation, CodeBuild и т.д. В этом случае идентификатор, создающий кластер, будет тем же идентификатором, который выполняет команду kubectl на CodeBuild.

Обзор решения

EKS-Factory автоматизирует предоставление ресурсов EKS (кластер, группа узлов) и настройку этих ресурсов в режиме самообслуживания. Как объяснялось выше, мы используем CloudFormation для предоставления этих ресурсов. Мы также используем Lambda и CodeBuild для конфигурирования предоставленных ресурсов.

Весь исходный код и детали конфигурации, обсуждаемые здесь, доступны в репозитории Github. Инструкции по установке см. в файле README.md.

Архитектура решения

Ниже приведена схема архитектуры решения на высоком уровне, показывающая различные компоненты и базовые ресурсы, которые предоставляются:

Когда мы предоставляем какие-либо ресурсы EKS, мы предоставляем их в логической границе, которую мы называем «окружением». Существует два различных типа стеков, которые мы предоставляем для любой среды EKS:

СТАК 1: План управления/окружение EKS.

Это будет первый стек, созданный для среды EKS, и для каждой среды будет только один стек EKS Control Plane. В этом стеке развертывается фактический кластер EKS вместе с другими ресурсами. Ниже приведен рабочий процесс предоставления различных ресурсов в этом стеке. На каждом из этих этапов создается дочерний/вложенный стек, что упрощает обслуживание базовых ресурсов.

ШАГ 1: Развертывание Config Manager
Сначала мы развертываем функцию Lambda, мы называем ее Config Manager, поскольку она выполняет все конфигурации, необходимые на разных этапах предоставления ресурсов. Перед этим мы создаем IAM-роль (роль Config Manager), необходимую для этой функции Lambda. Эта функция Lambda позволяет нам предоставлять пользовательские ресурсы с поддержкой Lambda в CloudFormation, что, в свою очередь, заставляет функцию Lambda вызываться по мере необходимости для выполнения необходимых изменений конфигурации.

ШАГ 2: Развертывание Config Map Manager
Далее мы создаем проект CodeBuild, называем его Config Map Manager, так как он настраивает aws-auth ConfigMap в Kubernetes по мере необходимости. Для этого мы запускаем сборку в проекте CodeBuild через вызов функции Lambda. Мы храним все наши файлы сценариев в S3 и указываем нашему проекту CodeBuild использовать местоположение S3 в качестве хранилища.

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

ШАГ 3: Обеспечение предварительных условий
Здесь мы создаем группу безопасности кластера и группу безопасности узла.

ШАГ 4: Предоставление кластера
Затем мы создаем роль службы кластера и предоставляем реальный кластер EKS.

ШАГ 5: Развертывание дополнительных модулей
Дополнения — это отдельные ресурсы в CloudFormation. Здесь мы предоставляем дополнения vpc-cni, kube-proxy и coredns.

ШАГ 6: Включить логирование
На этом этапе мы предоставляем пользовательский ресурс с поддержкой Lambda, который, в свою очередь, выполняет вызов Config Manager (функция Lambda) и включает логирование API Server, Audit, Authentication, Controller Manager и Scheduler.

ШАГ 7: Инициализация карты конфигурации
На этом этапе мы предоставляем еще один пользовательский ресурс, который вызывает лямбда-функцию Config Manager. Но на этот раз функция Lambda запускает сборку в CodeBuild, где мы на лету выполняем команду kubectl для обновления aws-auth ConfigMap в Kubernetes с нужными привилегиями для стандартных пользователей и групп в вашей организации.

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

ШАГ 0: Подождите, что?
На самом деле нам нужно кое-что очень важное перед выполнением всех вышеперечисленных шагов. Сейчас самое время объяснить это.

Нам нужна роль службы с несколькими принципами службы, как показано в следующем фрагменте шаблона CloudFormation:

Resources:
  EKSFactoryServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub EKSFactory-${AWS::Region}-ServiceRole
      Description: EKS Factory Service Role used by different services e.g. Service Catalog, CloudFormation, and CodeBuild for managing EKS environments.
      AssumeRolePolicyDocument:
        Statement:
        - Action: sts:AssumeRole
          Effect: Allow
          Principal:
            Service:
            - cloudformation.amazonaws.com
            - codebuild.amazonaws.com
            - servicecatalog.amazonaws.com
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/AdministratorAccess
Вход в полноэкранный режим Выход из полноэкранного режима

Мы создадим эту роль в рамках развертывания решения, о котором мы поговорим позже. Нам нужна эта роль до того, как мы создадим что-либо, потому что службы CloudFormation, CodeBuild и Service Catalog (которые вы увидите позже) будут использовать одну и ту же роль.

СТАК 2. EKS Data Plane/Node Group

После создания среды EKS и обеспечения кластера мы можем обеспечить одну или несколько плоскостей данных (группы узлов) с помощью этого стека. Ниже приведен рабочий процесс предоставления различных ресурсов в этом стеке. Как и раньше, на каждом из этих шагов создается дочерний стек.

ШАГ 1: Обеспечение предварительных условий
Сначала мы создаем IAM-роль узла, необходимую для группы узлов.

ШАГ 2: Регистрация IAM-роли узла
Затем мы развертываем пользовательский ресурс, который делает вызов Config Manager (Lambda-функция) и запускает сборку в CodeBuild для выполнения команды kubectl для добавления Node IAM Role в aws-auth ConfigMap в Kubernetes. Это необходимо для того, чтобы узлы могли присоединиться к кластеру.

ШАГ 3: Предоставление группы узлов
На этом шаге обеспечивается группа узлов EKS. Но перед этим создается шаблон запуска, на основе которого создается группа узлов.

ШАГ 4: Применить ярлыки и метки
На этом этапе мы развертываем пользовательский ресурс, который выполняет вызов Config Manager (функция Lambda) для добавления любых дополнительных меток Kubernetes к группе узлов и меток к основной группе автомасштабирования (ASG). Метки, добавленные на этом этапе к ASG, не распространяются на уже запущенные экземпляры EC2 под ASG, поэтому функция Lambda также добавляет метки непосредственно к этим существующим экземплярам.

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

Создание самообслуживания

На данном этапе мы можем предоставить Control Plane и Data Plane, а также все базовые ресурсы со всей автоматизацией, если у нас есть файлы шаблонов CloudFormation. Теперь, если мы упакуем их как продукты каталога услуг, конечные пользователи смогут использовать их в режиме самообслуживания.

Развертывание решения

Решение доступно на Github и может быть развернуто в один клик, выполнив install.sh, как описано в файле README.md. Решение создает портфель каталога услуг под названием EKS Factory и развертывает EKS Control Plane и EKS Data Plane как два отдельных продукта. Решение также создает EKSFactoryServiceRole (как обсуждалось ранее) с несколькими принципами службы, чтобы другие службы (CloudFormation, CodeBuild и Service Catalog) могли использовать ту же роль.

Примечание: Если мы развертываем решение в Service Catalog, технически нам не нужен принципал службы CloudFromation в EKSFactoryServiceRole. Но я сохранил его в исходном коде на случай, если вы не используете Service Catalog и предоставляете все ресурсы напрямую через CloudFormation.

Основные моменты перед развертыванием

Обновите aws-auth.yml.template в соответствии с вашими требованиями. Вам необходимо добавить пользователей/роли IAM, которые будут иметь доступ к предоставленным кластерам. Как правило, это стандартные пользователи/роли, такие как системные администраторы, пользователи аудита, которые должны иметь доступ ко всем ресурсам. Вы можете определить различные разрешения для разных пользователей/ролей, как показано ниже:

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: arn:aws:iam::AWSAccountID:role/EKS-Admin
      username: EKS-Admin
      groups:
      - system:masters
    - rolearn: arn:aws:iam::AWSAccountID:role/EKS-Users
      username: EKS-Users
  mapUsers: |
    - userarn: arn:aws:iam::AWSAccountID:user/Audit-User
      username: audit-user
      groups:
      - reporting:read
Войти в полноэкранный режим Выйти из полноэкранного режима

Ключевые особенности решения

1. Самообслуживание

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

2. IaC

Инфраструктура создается с использованием декларативных шаблонов CloudFormation и подхода «CloudFormation-first». Это очень упрощает как разработчикам, так и системным администраторам дальнейшее обслуживание среды.

Вы можете создать целую инфраструктуру (кластер EKS с двумя группами узлов), используя простой шаблон yaml, как показано ниже:

AWSTemplateFormatVersion: 2010-09-09
Description: Template to create an EKS Cluster and two Node Groups.

Resources:
  Cluster:
    Type: AWS::ServiceCatalog::CloudFormationProvisionedProduct
    Properties:
      ProductName: EKS Control Plane
      ProvisionedProductName: my-prod-EKS-control-plane
      ProvisioningArtifactName: New Cluster
      ProvisioningParameters:
      - Key: EnvironmentName
        Value: my-prod
      - Key: KubernetesVersion
        Value: "1.21"
      - Key: KmsKeyArn
        Value: <YOUR KMS KEY ARN>
      - Key: VpcId
        Value: <YOUR VPC ID>
      - Key: Subnets
        Value: "<YOUR SUBNET IDs SEPARATED BY COMMAS>"
      - Key: VpcCniVersion
        Value: v1.10.1-eksbuild.1
      - Key: CoreDnsVersion
        Value: v1.8.4-eksbuild.1
      - Key: KubeProxyVersion
        Value: v1.21.2-eksbuild.2

NodeGroup1:
    Type: AWS::ServiceCatalog::CloudFormationProvisionedProduct
    Properties:
      ProductName: EKS Data Plane
      ProvisionedProductName: my-prod-EKS-121-141-NodeGroup-1
      ProvisioningArtifactName: New Node Group
      ProvisioningParameters:
      - Key: EnvironmentName
        Value: my-prod
      - Key: KubernetesVersionNumber
        Value: 121
      - Key: BuildNumber
        Value: 141
      - Key: NodeGroupName
        Value: NodeGroup-1
      - Key: AmiId
        Value: <YOUR AMI ID>
      - Key: CapacityType
        Value: ON_DEMAND
      - Key: InstanceType
        Value: m5.2xlarge
      - Key: VolumeSize
        Value: 60
      - Key: VolumeType
        Value: gp3
      - Key: MinSize
        Value: 1
      - Key: MaxSize
        Value: 3
      - Key: DesiredSize
        Value: 3
      - Key: Subnets
        Value: "<YOUR SUBNET IDs SEPARATED BY COMMAS>"
      - Key: EnableCpuCfsQuota
        Value: "true"
      - Key: HttpTokenState
        Value: optional
    DependsOn:
    - Cluster

  NodeGroup2:
    Type: AWS::ServiceCatalog::CloudFormationProvisionedProduct
    Properties:
      ProductName: EKS Data Plane
      ProvisionedProductName: my-prod-EKS-121-141-NodeGroup-2
      ProvisioningArtifactName: New Node Group
      ProvisioningParameters:
      - Key: EnvironmentName
        Value: my-prod
      - Key: KubernetesVersionNumber
        Value: 121
      - Key: BuildNumber
        Value: 141
      - Key: NodeGroupName
        Value: NodeGroup-2
      - Key: AmiId
        Value: <YOUR AMI ID>
      - Key: CapacityType
        Value: ON_DEMAND
      - Key: InstanceType
        Value: m5.2xlarge
      - Key: KeyPair
        Value: <YOUR KEY PAIR NAME>
      - Key: VolumeSize
        Value: 60
      - Key: VolumeType
        Value: gp3
      - Key: MinSize
        Value: 1
      - Key: MaxSize
        Value: 3
      - Key: DesiredSize
        Value: 3
      - Key: Subnets
        Value: "<YOUR SUBNET IDs SEPARATED BY COMMAS>"
      - Key: EnableCpuCfsQuota
        Value: "true"
      - Key: HttpTokenState
        Value: optional
      - Key: TaintKey
        Value: <YOUR TAINT KEY>
      - Key: TaintValue
        Value: <YOUR TAINT VALUE>
      - Key: TaintEffect
        Value: <YOUR TAINT EFFECT>
      - Key: AdditionalLabels
        Value: "label1=value1,label2=value2"
      - Key: AdditionalTags
        Value: "tag1=value1,tag2=value2"
    DependsOn:
    - Cluster
Вход в полноэкранный режим Выйти из полноэкранного режима

3. Интегрированная платформа сборки

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

4. Интегрированный уровень бизнес-логики

Функция Lambda позволяет нам писать любые пользовательские компоненты/логику и интегрировать функции по принципу plug-and-play.

5. Бессерверный

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

6. Cloud-native

Решение не использует никаких третьих инструментов. Это хорошо для организаций, использующих AWS и предпочитающих облачно-нативные решения.

7. Гибкость

Решение гибкое, компоненты могут обновляться отдельно для добавления новых функций. Например, мы можем использовать его для развертывания Cluster Autoscaler или приложений, таких как инструменты мониторинга, после инициализации кластера. Все, что нам нужно сделать, это подготовить шаги в файле сценария оболочки и вызвать сборку с помощью сценария.

Поведение решения по умолчанию

a. Отдельная роль Node IAM для каждой группы узлов

Мы создаем отдельную роль Node IAM для каждой группы узлов. Это основано на предположении, что может возникнуть потребность в том, чтобы разные группы узлов имели разные разрешения. В этом случае вы можете изменить роли Node IAM после предоставления плоскости данных (группы узлов).

b. Метки и теги по умолчанию

Мы добавляем имя среды (environmentName) как в качестве метки Kubernetes, так и в качестве метки EC2 для базовых узлов. Но вы также можете задать любое количество дополнительных меток и тегов для группы узлов при их инициализации.

c. Нулевая/одна ошибка на группу узлов

Шаблон группы узлов eks-node-group.yaml позволяет применить к базовым узлам нулевой или один Taint. Если вы хотите применить больше Taints, то мы можем легко расширить решение для реализации этого, подобно тому, как это сделано для меток и тегов.

Переход решения на новый уровень

Многие организации используют ServiceNow для своих процессов ITIL. Мы можем позволить конечным пользователям запрашивать ресурсы EKS (кластер, группа узлов) через ServiceNow.


Диаграмма взята с официального сайта. В нашем решении мы используем только AWS Service Catalog. AWS Config и AWS Systems Manager не используются.

Это достигается за счет использования AWS Service Management ConnectorforServiceNow (ранее AWS Service Catalog Connector). Этот коннектор позволяет конечным пользователям ServiceNow предоставлять, управлять и эксплуатировать ресурсы AWS через ServiceNow.


Как вы нашли это решение? Не стесняйтесь поделиться своими мыслями в комментариях ниже.

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