Как я внедряю культуру DevOps в webapp — часть 1

В этом посте я собираюсь показать вам реальное решение для создания среды, использующей технологии и практики DevOps для развертывания приложений и облачных сервисов/облачной инфраструктуры на AWS.
Я разобью эту серию статей на две части, где это будет первая часть, а вторую часть вам лучше поискать. Однако я размещу ссылку на вторую часть в конце этого поста.

Полное раскрытие информации — как стажер DevOps с разрешения, мне пришлось использовать исходный код целевой страницы ruralx.africa и начальные практики и технологии DevOps.

Почему DevOps?
Представьте, что вы сейчас работаете в организации, которая очень монолитна. В ней много голого металла, виртуализации, ручного развертывания приложений и старых методов, основанных на знаниях текущей команды в области ИТ.

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

Решение?
Решение в этом посте — это реальный пример того, как добавить немного DevOps в существующий исходный код. DevOps — это набор практик, объединяющих разработку программного обеспечения и ИТ-операции. Его цель — сократить жизненный цикл разработки систем и обеспечить непрерывную доставку с высоким качеством программного обеспечения.

Предварительные условия
Для создания среды DevOps я буду использовать следующие технологии и платформы.

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

  • AWS CLI
    AWS CLI — это способ взаимодействия со всеми службами AWS на программном уровне с помощью терминала.

  • GitHub
    Для хранения кода приложения и инфраструктуры/автоматизации

  • Nodejs
    Nodejs будет использоваться для веб-приложения (оно написано на JavaScript).

  • Docker
    Создайте образ Docker
    Храните образ Docker в AWS ECR

  • Terraform
    Создайте ведро S3 для хранения файлов Terraform State
    Создайте репозиторий AWS ECR с помощью Terraform
    Создайте кластер EKS

  • Kubernetes
    Чтобы запустить образ Docker, созданный для контейнеризированного приложения ruralx. Kubernetes, в данном случае EKS, будет использоваться для оркестровки контейнера.

  • CI/CD
    Используйте GitHub Actions для создания кластера EKS

  • Автоматизированное тестирование
    Тестирование кода Terraform с помощью Checkov

  • Prometheus
    Система мониторинга с открытым исходным кодом с размерной моделью данных, гибким языком запросов, эффективной базой данных временных рядов и современным подходом к оповещению.

В этой первой части я покажу вам, как я применяю практику DevOps в непрерывной разработке; используя AWS, Docker и Terraform. А в последней части я покажу вам, как я применяю непрерывную интеграцию и непрерывное развертывание; используя GitHub Action, Kubernetes и Prometheus.
Давайте приступим к этому.

1.0 AWS
Установка AWS CLI
Шаги по установке AWS довольно просты и понятны, следуйте каждому шагу из документации AWS. Обратите внимание, что установка основных инструментов, таких как AWS, текстовый редактор, Docker и другие, выходит за рамки данного поста. В противном случае, это сделает этот пост неоправданно длинным, поэтому я буду считать, что у вас есть все необходимые знания, упомянутые выше.
Для получения документации по AWS CLI, вот ссылка

Настройка учетных данных для доступа к AWS на программном уровне
Цель — настроить учетные данные IAM на моем локальном компьютере, чтобы вы могли получить доступ к AWS на программном уровне (SDK, CLI, Terraform и т.д.).

  • Откройте консоль управления AWS и перейдите в IAMSign in to the organization account, на вкладке Ваше имя пользователя в правом верхнем углу выберите Security Credential;
  • Создайте нового пользователя или используйте существующего пользователя AWSДля этого доступа настоятельно рекомендуется создать нового пользователя. Особенно для проекта организации, где каждая команда имеет отдельный доступ к определенным активам организации и контролируется пользователем root.

Щелкните User (Пользователь) в строке меню IAM в левом верхнем углу;

  • Предоставьте пользователю программный доступ
    На панели Security Credential выберите выпадающий список Access Key, затем нажмите на Create New Access Key;

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

Настройка AWS CLI

  • Откройте окно терминала
    Попробуйте проверить, правильно ли установлен aws, выполнив эту команду.

    Если отображение отличается от примера ниже, знайте, что вам нужно переустановить систему, чтобы избежать дальнейших осложнений;

  • Выполните команду configure
    Для конфигурирования выполните команду aws configure.
    Заполните идентификатор ключа доступа и секретный ключ доступа.
    Если вы не уверены в имени региона по умолчанию, просто оставьте его как есть, нажав кнопку Enter.
    Для формата вывода я советую использовать JSON, нажмите кнопку Enter.
    Вот так просто мы закончили настройку AWS.

    Однако, если вам нужна дополнительная информация об установке и настройке AWS CLI, я рекомендую эту ссылку

2.0 VPC — виртуальное частное облако
Чтобы создать мой кластер VPC с публичной и частной подсетями

  • Откройте консоль AWS CloudFormation, введите CloudFormation в поле службы.
  • Выберите Create stack.
  • Выберите Шаблон готов и, Amazon S3 URL. Затем вставьте следующий URL в текстовую область и выберите Next:https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml.

  • На странице Specify Stack Details заполните следующее и выберите Next:
  • Имя стека: Я выбираю имя стека для своего стека AWS CloudFormation. Например, я называю его ruralx-vpc.
  • VpcBlock: Выберите диапазон CIDR для моего VPC. Каждому рабочему узлу, капсуле и балансировщику нагрузки, которые я развертываю, присваивается IP-адрес из этого блока. Значение по умолчанию обеспечивает достаточное количество IP-адресов для большинства реализаций, но если это не так, то я могу его изменить. Для получения дополнительной информации смотрите раздел Размер VPC и подсети в руководстве пользователя Amazon VPC. Я также могу добавить дополнительные блоки CIDR в VPC после его создания.
  • PublicSubnet01Block: Укажите блок CIDR для публичной подсети 1. Значение по умолчанию обеспечивает достаточное количество IP-адресов для большинства реализаций, но если это не так, то я могу его изменить.
  • PublicSubnet02Block: Укажите блок CIDR для публичной подсети 2. Значение по умолчанию обеспечивает достаточное количество IP-адресов для большинства реализаций, но если это не так, то я могу его изменить.
  • PrivateSubnet01Block: Укажите блок CIDR для частной подсети 1. Значение по умолчанию обеспечивает достаточное количество IP-адресов для большинства реализаций, но если это не так, то я могу изменить его.
  • PrivateSubnet02Block: Укажите блок CIDR для частной подсети 2. Значение по умолчанию обеспечивает достаточное количество IP-адресов для большинства реализаций, но если это не так, то я могу изменить его.
  • (Необязательно) На странице Параметры отметьте ресурсы стека. Выберите Далее.
  • На странице Обзор выберите Создать.
  • Когда мой стек будет создан, выберите его в консоли и выберите Outputs.
  • Запишите значение Security Groups для созданной группы безопасности. Когда я добавляю узлы в свой кластер, я должен указать идентификатор группы безопасности. Группа безопасности применяется к эластичным сетевым интерфейсам, которые создаются Amazon EKS в моих подсетях, что позволяет плоскости управления взаимодействовать с моими узлами. В описании этих сетевых интерфейсов указано Amazon EKS.
  • Запишите VpcId для созданного VPC. Он понадобится мне при запуске шаблона группы узлов.
  • Запишите SubnetIds для созданных подсетей и то, как я их создал — как публичные или частные подсети. Когда я добавляю узлы в свой кластер, я должен указать идентификаторы подсетей, в которые я хочу запустить узлы.

3.0 Terraform
Цель раздела Terraform — создать все облачные сервисы AWS, которые понадобятся мне с точки зрения среды/инфраструктуры для работы приложения ruralx.

Создание ведра S3 для хранения файлов TFSTATE
Здесь я создам ведро S3, которое будет использоваться для хранения файлов состояния Terraform.
Я создал файл main.tf внутри каталога, напишите в нем этот код;

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-state-rurlax"
  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Terraform main.tf будет делать следующее:

  1. Создайте ведро S3 в регионе us-east-1.
  2. Убедитесь, что для параметра включения версии установлено значение True.
  3. Использовать шифрование AES256.
  • Создайте ведро, выполнив следующие действия:

terraform init — для инициализации рабочего каталога и извлечения провайдера.

Создание реестра эластичных контейнеров
Идея заключается в том, чтобы создать репозиторий для хранения образа Docker, который я создал для приложения ruralx.
Затем я добавляю в main.tf следующее;

terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "ecr-terraform.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_ecr_repository" "ruralx-ecr-repo" {
  name                 = var.ruralx-ecr
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Также создаю файл variables.tf внутри директории, в основном для хранения env репо. Затем я пишу этот код;

variable ruralx-ecr {
  type        = string
  default     = "ruralx"
  description = "ECR repo to store a Docker image"
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что Terraform main.tf будет делать это:

  1. Используйте бэкенд Terraform для хранения .tfstate в ведре S3.
  2. Используйте ресурс aws_ecr_repository Terraform для создания нового хранилища.
  • Создайте ведро, выполнив следующие действия:

terraform init — Для инициализации рабочего каталога и извлечения провайдера.

Создание кластера EKS и роли/политики IAM
Здесь я собираюсь создать кластер EKS, написав следующий код;

terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "ecr-terraform.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-state-ruralx"
  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

resource "aws_ecr_repository" "ruralx-africa-ecr-repo" {
  name                 = var.ruralx-africa-ecr
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}

terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "eks-terraform-workernodes.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}


# IAM Role for EKS to have access to the appropriate resources
resource "aws_iam_role" "eks-iam-role" {
  name = "ruralx-eks-iam-role"

  path = "/"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

}

## Attach the IAM policy to the IAM role
resource "aws_iam_role_policy_attachment" "AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.eks-iam-role.name
}
resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly-EKS" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.eks-iam-role.name
}

## Create the EKS cluster
resource "aws_eks_cluster" "ruralx-eks" {
  name = "ruralx-cluster"
  role_arn = aws_iam_role.eks-iam-role.arn

  vpc_config {
    subnet_ids = [var.subnet_id_1, var.subnet_id_2]
  }

  depends_on = [
    aws_iam_role.eks-iam-role,
  ]
}

## Worker Nodes
resource "aws_iam_role" "workernodes" {
  name = "eks-node-group-example"

  assume_role_policy = jsonencode({
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "AmazonEKSWorkerNodePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "AmazonEKS_CNI_Policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "EC2InstanceProfileForImageBuilderECRContainerBuilds" {
  policy_arn = "arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilderECRContainerBuilds"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.workernodes.name
}

resource "aws_eks_node_group" "worker-node-group" {
  cluster_name    = aws_eks_cluster.ruralx-eks.name
  node_group_name = "ruralx-workernodes"
  node_role_arn   = aws_iam_role.workernodes.arn
  subnet_ids      = [var.subnet_id_1, var.subnet_id_2]
  instance_types = ["t3.xlarge"]

  scaling_config {
    desired_size = 1
    max_size     = 1
    min_size     = 1
  }

  depends_on = [
    aws_iam_role_policy_attachment.AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.AmazonEKS_CNI_Policy,
    #aws_iam_role_policy_attachment.AmazonEC2ContainerRegistryReadOnly,
  ]
}
Вход в полноэкранный режим Выход из полноэкранного режима
variable "subnet_id_1" {
  type = string
  default = "subnet-05f2a43d392934382"
}

variable "subnet_id_2" {
  type = string
  default = "subnet-0086dd63b54f54812"
}

Войти в полноэкранный режим Выход из полноэкранного режима
  • Создайте кластер EKS, выполнив следующее:

terraform plan — Пройти «проверку» и подтвердить правильность конфигураций.

Если вы хотите более подробно ознакомиться с terraform, вы можете начать здесь Нажмите на эту ссылку

4.0 Docker
Здесь мы планируем требования к приложению, кодируем, собираем и тестируем приложение.
Я предполагаю, что все эти этапы уже пройдены, так как команда DevOps не отвечает за них единолично, а скорее работает с более крупной командой как разработчиков, так и операторов организации.

Создание образа Docker для приложения ruralx
Цель этой работы — создать образ Docker из исходного кода приложения, который есть у организации, контейнеризировать его и сохранить контейнер в репозитории контейнеров. Здесь я буду использовать репо-контейнер AWS ECR.

  1. В корневом каталоге исходного кода приложения создайте Dockerfile.
  2. Откройте Dockerfile, затем определите инструкцию, это зависит от базового образа и других параметров, вы можете рассматривать это как пример;
# syntax=docker/dockerfile:1
FROM node:10.16.1-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]
Войти в полноэкранный режим Выйти из полноэкранного режима
  1. Чтобы создать образ Docker, выполните следующую команду: docker build -t ruralx:latest .Тег -t означает тег (имя) образа Docker, а . говорит Docker CLI, что Dockerfile находится в текущем каталоге.
  2. После создания образа Docker выполните следующую команду, чтобы убедиться, что образ Docker находится на вашей машине; docker image ls.

Запуск образа Docker локально
Теперь, когда образ Docker создан, вы можете запустить контейнер локально, чтобы убедиться, что он будет работать и не упадет.

  1. Чтобы запустить контейнер Docker, выполните следующую команду: docker run -tid ruralx.
  2. Чтобы подтвердить, что контейнер Docker запущен, выполните следующую команду: docker container ls.

Войдите в репозиторий AWS ECR
Идея заключается в том, чтобы передать изображение в ECR

  • Войдите в ECR с помощью AWS CLI

  • Пометить образ Docker
    Пометьте образ Docker docker tag ruralx 1XX9-6XXX-6XX7.dkr.ecr.us-east-1.amazonaws.com.

  • Передача образа Docker в ECR
    Переместите образ Docker в ECR docker push 1XX9-6XXX-6XX7.dkr.ecr.us-east-1.amazonaws.com/ruralx.

В дополнение к документации Docker, нажмите здесь, чтобы найти еще один полезный ресурс от Нельсона (канал YouTube; Amigoscode).

Чтобы узнать больше, догоните меня во второй части!
Читайте >>>

Спасибо за прочтение! Счастливых облачных вычислений!

Буду рад пообщаться с вами на LinkedIn

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