- PVSM.RU - https://www.pvsm.ru -
Продолжение истории про Kubernetes, контейнеры и организацию CI/CD пайплайна. Наконец-то появляется облако Azure и Visual Studio Team Services. Интересно, что CI/CD пайплайн VSTS использует для работы с k8s кластером kubectl, поэтому развёртывать приложение можно не только в Azure Container Services, но и в любой другой инстраляции Kubernetes.
Читайте перевод второй части статьи DevOps с Kubernetes и VSTS.
1. Локальная история [1]
2. Облачная история [2]
В первой части [1] я продемонстрировал подход к разработке многоконтейнерных приложений с использованием Kubernetes [3] (k8s), а точнее minikube [4], полноценной среды k8s, которая запускает один узел на виртуальной машине на вашем ноутбуке. В предыдущей статье я клонировал этот репозиторий [5] (убедитесь, что развернута ветка docker) с двумя контейнерами: DotNet Core API и frontend SPA (Aurelia [6]) (в виде статических файлов в приложении DotNet Core app). Я показал, как создавать контейнеры локально и запускать их в minikube, а также использовать возможности ConfigMaps для работы с конфигурациями.
В этой статье я расскажу вам, как перенести локальную разработку в CI/CD и создать конвейер для автоматизированного формирования сборки/выпуска с использованием VSTS. Мы создадим реестр контейнеров и службы контейнеров в Azure, используя k8s в качестве механизма оркестрации.
Настоятельно рекомендую вам изучить прекрасный начальный курс Найджела Поултона (Nigel Poulton) [7] под названием Getting Started with Kubernetes на PluralSight [8] (прим. переводчика — на английском языке, нужна платная подписка), а также статью [9] Атула Малавия (Atul Malaviya) из Microsoft. Курс Найджела стал превосходным погружением в Kubernetes для новичков, а статья Атула помогла понять принципы взаимодействия VSTS и k8s, но ни курс, ни статья не охватили конвейер полностью. Из них я так и не понял, как в конвейере CI/CD реализовано обновление образов. Что ж, пришлось самому провести ряд экспериментов и подготовить эту статью!
k8s можно запускать локально, в AWS или Google Cloud или Azure. Мы будем использовать службу контейнеров Azure (Azure Container Service). Однако, конвейер CI/CD, который я демонстрирую в этой статье, не зависит от конкретного облачного
Создать кластер k8s можно и на портале Azure. Однако Azure CLI позволяет сделать это быстрее, и вы сохраните ключи, которые понадобятся для подключения, поэтому я решил использовать этот механизм. Я также буду использовать Bash для Windows с kubectl, но подойдет любая платформа с kubectl и Azure CLI.
Вот команды:
# set some variables
export RG="cd-k8s"
export clusterName="cdk8s"
export location="westus"
# create a folder for the cluster ssh-keys
mkdir cdk8s
# login and create a resource group
az login
az group create --location $location --name $RG
# create an ACS k8s cluster
az acs create --orchestrator-type=kubernetes --resource-group $RG --name=$ClusterName --dns-prefix=$ClusterName --generate-ssh-keys --ssh-key-value ~/cdk8s/id_rsa.pub --location $location --agent-vm-size Standard_DS1_v2 --agent-count 2
# create an Azure Container Registry
az acr create --resource-group $RG --name $ClusterName --location $location --sku Basic --admin-enabled
# configure kubectl
az acs kubernetes get-credentials --name $ClusterName --resource-group $RG --file ~/cdk8s/kubeconfig --ssh-key-file ~/cdk8s/id_rsa
export KUBECONFIG="~/cdk8s/kubeconfig"
# test connection
kubectl get nodes
NAME STATUS AGE VERSION
k8s-agent-96607ff6-0 Ready 17m v1.6.6
k8s-agent-96607ff6-1 Ready 17m v1.6.6
k8s-master-96607ff6-0 Ready,SchedulingDisabled 17m v1.6.6
Примечания:
Если вы запустите браузер, перейдете на портал Azure и откроете свою группу ресурсов, то увидите, сколько всего было создано этими простыми командами:
Не беспокойтесь, самостоятельно управлять ресурсами вам не придется. Azure и кластер k8s берут это на себя!
Прежде чем мы создадим сборку и выпуск для наших контейнерных приложений, давайте рассмотрим модель продвижения. Обычно схема примерно такая: разработка → пользовательские приемочные испытания → производственная среда (Dev → UAT → Prod). В случае c k8s, minikube представляет собой локальную среду разработки, и это здорово. Это полноценный кластер k8s на вашем ноутбуке, поэтому вы можете запускать свой код локально, в том числе с помощью таких конструктов k8s, как configMaps. А как быть с UAT и Prod? Вариант — развернуть отдельные кластеры, но такой подход может оказаться дорогостоящим. Также вы можете обеспечить совместное использование ресурсов кластера с помощью пространств имен.
Пространства имен в k8s выступают в качестве рубежей безопасности, но они также могут стать границами изоляции. Я могу развернуть новые версии моего приложения в пространстве имен dev, которое будет использовать ресурсы пространства имен prod, но при этом останется полностью невидимым (собственные IP-адреса и т. д.). Разумеется, не следует проводить нагрузочное тестирование в рамках такой конфигурации, поскольку мы будем потреблять значительные ресурсы, предназначенные для приложений в производственной среде. Эта концепция напоминает слоты развертывания в службах приложений Azure, которые используются для незаметного тестирования приложений перед их передачей в производственную среду.
Если вы создаете кластер k8s, то помимо пространств имен kube-system и kube-public (с подами k8s) получаете пространство имен по умолчанию. При отсутствии четких указаний с вашей стороны любые службы, развертывания или поды, которые вы создадите, попадают в это пространство имен. Но мы создадим два дополнительных пространства имен: dev и prod. Вот наш yaml:
apiVersion: v1
kind: Namespace
metadata:
name: dev
---
apiVersion: v1
kind: Namespace
metadata:
name: prod
Этот файл содержит определения для обоих пространств имен. Выполните команду Apply, чтобы создать пространства имен. Завершив все процедуры, вы можете вывести список всех пространств имен в кластере:
kubectl apply -f namespaces.yml
namespace "dev" created
namespace "prod" created
kubectl get namespaces
NAME STATUS AGE
default Active 27m
dev Active 20s
kube-public Active 27m
kube-system Active 27m
prod Active 20s
Прежде чем переходить к коду, выполним заключительные настройки: когда кластер k8s извлекает образы для запуска, он должен обращаться к созданному нами реестру контейнеров. К этому реестру организован защищенный доступ, поскольку реестр частный. Поэтому нам нужно настроить секрет реестра, на который можно будет просто ссылаться в наших файлах развертывания yaml. Вот команды:
az acr credential show --name $ClusterName --output table
USERNAME PASSWORD PASSWORD2
---------- -------------------------------- --------------------------------
cdk8s some-long-key-1 some-long-key-2
kubectl create secret docker-registry regsecret --docker-server=$ClusterName.azurecr.io --docker-username=$ClusterName --docker-password=<some-long-key-1> --docker-email=admin@azurecr.io
secret "regsecret" created
Первая команда использует az, чтобы получить ключи для пользователя с правами администратора (имя пользователя с правами администратора совпадает с именем реестра контейнеров, поэтому я создал cdk8s.azurecr.io, и имя пользователя-администратора будет cdk8s). Передайте один из ключей (неважно, какой) в качестве пароля. Адрес электронной почты не используется, поэтому можете указать какой угодно. Теперь у нас есть секрет реестра с именем regsecret, на который мы можем ссылаться, выполняя развертывание в кластере k8s. K8s будет использовать этот секрет для проверки подлинности в реестре.
Мы настроили кластер k8s и реестр контейнеров. Теперь добавим эти конечные точки в VSTS, чтобы мы могли передавать контейнеры в реестр при создании сборки и выполнять команды в отношении кластера k8s во время подготовки выпуска. Конечные точки позволяют нам абстрагировать проверку подлинности, чтобы не хранить учетные данные непосредственно в определениях наших выпусков. Вы также можете создать роли, чтобы ограничить доступ на просмотр и использование конечных точек.
Запустите VSTS и откройте командный проект (или просто создайте новый). Перейдите в командный проект и нажмите значок шестеренки, чтобы открыть узел настроек для этого командного проекта. Щелкните Services. Щелкните + New Services и создайте новую конечную точку Docker Registry. Введите те же учетные данные, которые вы использовали для создания секрета реестра в k8s с помощью kubectl:
Теперь создайте конечную точку k8s. Введите URL: https://$ClusterName.$location.cloudapp.azure.com (clustername и location — переменные, которые мы использовали при создании кластера). Необходимо скопировать в текстовое поле для учетных данных все содержимое файла ~/cdk8s/kubeconfig (вы могли назвать его по-другому), который был создан после выполнения команды az acs kubernetes get-credential:
Теперь у нас есть две конечные точки, которые мы можем использовать в определениях сборки и выпуска:
Теперь мы можем создать сборку, которая будет компилировать/тестировать наш код, создавать образы docker и помещать их в реестр контейнеров, соответствующим образом помечая их. Щелкните Build & Release, а затем — Builds, чтобы открыть узел сборки. Создайте новое определение сборки. Выберите шаблон ASP.NET Core и нажмите Apply. Необходимо выполнить следующие настройки:
Итоговый список задач должен выглядеть следующим образом:
Теперь можно нажать Save and Queue, чтобы сохранить сборку и поставить ее в очередь. По завершении процесса создания сборки вы увидите сводную информацию о тестировании/покрытии.
Вы также можете просмотреть содержимое своего реестра контейнеров, чтобы увидеть вновь перенесенные образы служб с меткой, соответствующей номеру сборки.
Теперь мы можем настроить выпуск, который будет создавать/обновлять нужные службы. Для этого следует обеспечить управление конфигурацией. Можно было просто включить конфигурацию в код, но в таком случае конфиденциальные данные (например, пароли) попали бы в инструмент управления версиями. Я предпочитаю «токенизировать» любую конфигурацию, чтобы решение для управления выпусками размещало конфиденциальные данные за пределами зоны, контролируемой инструментом управления версиями. Решение VSTS Release Management позволяет создавать секреты для отдельных сред или выпусков, также вы можете создавать их в группах переменных с поддержкой повторного использования. Кроме того, теперь поддерживается бесшовная интеграция с Azure Key Vault [11].
Чтобы вместо токенов использовать значения, специфичные для среды, нам нужна задача для замены токена. К счастью, у меня есть кросс-платформенная задача ReplaceTokens из модуля расширения Colin's ALM Corner Build & Release Tasks [12], который я скачал из магазина VSTS Marketplace. Щелкните ссылку, чтобы перейти на нужную страницу, затем нажмите Install, чтобы установить расширение для своей учетной записи.
На странице сводной информации о сборке прокрутите бегунок справа до раздела Deployments и щелкните ссылку Create release. Также можете щелкнуть Releases и создать новое определение оттуда. Начните с пустого шаблона (Empty), выберите свой командный проект и сборку, которую вы только что создали, в качестве исходной сборки. Поставьте флажок Continuous Deployment, чтобы выпуск создавался автоматически для каждой правильной сборки.
В качестве имени для определения укажите k8s или что-то описательное. На вкладке General измените формат номера выпуска на $(Build.BuildNumber)-$(rev:r), чтобы по имени выпуска всегда можно было без труда определить номер сборки. Вернитесь в раздел Environments и вместо Environment 1 введите dev. Щелкните ссылку Run on Agent и убедитесь, что в поле Deployment queue выбрано Hosted Linux Preview.
Добавьте следующие задачи:
Так задаются специфичные для среды значения для всех переменных в файлах yml. Задача Replace Tokens запишет для нас нужные значения в файлы. Давайте быстро посмотрим на один из токенизированных файлов (токенизированные строки выделены):
apiVersion: v1
kind: Service
metadata:
name: demo-frontend-service
labels:
app: demo
spec:
selector:
app: demo
tier: frontend
ports:
- protocol: TCP
port: 80
nodePort: __FrontendServicePort__
type: LoadBalancer
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: demo-frontend-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: demo
tier: frontend
spec:
containers:
- name: frontend
image: __ContainerRegistry__/frontend
ports:
- containerPort: 80
env:
- name: "ASPNETCORE_ENVIRONMENT"
value: "__AspNetCoreEnvironment__"
volumeMounts:
- name: config-volume
mountPath: /app/wwwroot/config/
imagePullPolicy: Always
volumes:
- name: config-volume
configMap:
name: demo-app-frontend-config
imagePullSecrets:
- name: regsecret
Комментарий относительно значения для BackendServiceIP: мы используем 10.0.0.1 в качестве замещающего текста, так как Azure присвоит IP-адрес этой службе, когда k8s запустит службу на стороне сервера (вы увидите общедоступный IP-адрес в группе ресурсов на портале Azure). Нам нужно будет выполнить это один раз, чтобы создать службы, а затем обновить, чтобы получить реальный IP-адрес и обеспечить работоспособность службы на стороне клиента. Мы также используем $(Release.EnvironmentName) в качестве значения для namespace, поэтому для dev (а затем и для prod) пространства имен должны совпадать с теми, что создали мы (включая регистр символов).
Если служба/развертывание и конфигурация не изменяются, то первые три задачи k8s по существу не работают. Какой-то результат даст только команда set. Но это как раз здорово, поскольку файлы службы/развертывания и конфигурации можно применять идемпотентно! Они меняются, когда это необходимо, и не вносят никаких возмущений во всех остальных ситуациях — идеальный подход для повторяющихся выпусков!
Сохраните определение. Щелкните + Release, чтобы создать новый выпуск. Щелкните по номеру выпуска (это будет что-то вроде 1.0.0.1-1), чтобы открыть его. Щелкните logs, чтобы просмотреть журналы.
Когда создание выпуска завершится, вы увидите развертывание на информационной панели Kubernetes. Используйте следующую команду, чтобы открыть информационную панель:
az acs kubernetes browse -n $ClusterName -g $RG --ssh-key-file ~/cdk8s/id_rsa
Proxy running on 127.0.0.1:8001/ui
Press CTRL+C to close the tunnel...
Starting to serve on 127.0.0.1:8001
Последний аргумент — это путь к файлу SSH-ключа, который генерируется при создании кластера (укажите актуальный путь). Теперь можно открыть в браузере страницу http://localhost:8001/ui [13]. В раскрывающемся меню namespace выберите dev и щелкните Deployments. Вы должны увидеть два успешных развертывания с двумя работоспособными подами в каждом. Вы также можете увидеть образы, которые запускаются в развертываниях. Обратите внимание на номер сборки, указанный в качестве тега!
Чтобы увидеть службы, щелкните Services.
Теперь у нас есть IP-адрес службы на стороне сервера, поэтому мы можем обновить переменную в выпуске. Затем мы можем поставить в очередь новую версию, и на этот раз в конфигурации клиента будет указан правильный IP-адрес для службы на стороне сервера (в нашем случае это 23.99.58.48). Мы можем ввести IP-адрес нашей клиентской службы в браузере и убедиться, что теперь все работает!
Теперь, когда мы убедились в работоспособности среды dev, мы можем вернуться к выпуску, клонировать среду dev и назвать копию prod. Укажите одобрение постфактум для dev (или предварительное одобрение для prod), чтобы между двумя средами была контрольная точка.
Затем мы можем просто изменить порты для узлов, а также значения переменных AspNetCoreEnvironment и BackendServiceIP, и готово! Разумеется, нам нужно сначала выполнить развертывание в пространстве имен prod, прежде чем мы увидим IP-адрес, назначенный k8s/Azure для сервера prod. Затем необходимо повторно запустить процедуру создания выпуска, чтобы обновить конфигурацию.
Мы могли бы удалить параметр nodePort из определений и позволить платформе k8s самой выбрать порт узла, но если порт указан явным образом, то мы будем точно знать, какой порт служба будет использовать в кластере (не для доступа извне).
Мне не нравится указывать --namespace для каждой команды, настолько не нравится, что я создал запрос Pull Request [14] в репозитории vsts-tasks на Github, чтобы дать доступ к пространству имен в качестве дополнительного элемента пользовательского интерфейса!
Теперь, когда наши среды dev и prod в конвейере CI/CD настроены, мы можем внести изменения в код. Я поменяю текст под версией на «K8s demo» и применю изменения. Так мы инициируем сборку, создание более нового образа контейнера и выполнение тестов, что, в свою очередь, запустит выпуск в среде dev. Теперь я вижу изменение в среде dev (версия 1.0.0.3 или более новая, то есть больше, чем 1.0.0.1), в то время как версия prod все еще равна 1.0.0.1.
Одобрите dev в решении для управления выпусками, и процесс для prod запустится, через несколько секунд версия prod также будет равна 1.0.0.3.
Я экспортировал определения json для сборки и выпуска в этот каталог, вы можете попытаться импортировать их (я не уверен, что это сработает, но использовать их для справки можно в любом случае).
k8s имеет большой потенциал как надежный механизм оркестрации контейнеров. Технология yml позволяет реализовать концепцию «инфраструктура как код» и отлично подходит для управления версиями. Механизм развертывания сводит к минимуму или вовсе устраняет время простоя при развертывании, а возможность использования configMaps и секретов обеспечивает безопасность всего процесса. Интерфейс командной строки Azure CLI позволяет создать кластер k8s и реестр контейнеров Azure при помощи пары простых команд. Интеграция с VSTS с помощью задач k8s упрощает настройку конвейера CI/CD, вместе они формируют оптимальный рабочий процесс разработки. А с учетом решения minikube, о котором я писал в первой части этой серии статей и который предоставляет вам полноценный кластер k8s для локальной разработки на вашем ноутбуке, вы получаете отличный рабочий процесс разработки, непрерывной интеграции и непрерывного развертывания (Dev/CI/CD).
Разумеется, конвейер CI/CD не проводит нагрузочное тестирование реальных приложений в производственной среде! Я хотел бы узнать о вашем опыте применения k8s в производственных средах. Пишите в комментариях, если у вас есть опыт запуска приложений в кластере k8s в производственной среде!
Удачи вам с k8sing!
Автор: Стас Павлов
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/264079
Ссылки в тексте:
[1] Локальная история: https://habrahabr.ru/company/microsoft/blog/337626/
[2] Облачная история: https://habrahabr.ru/company/microsoft/blog/337708/
[3] Kubernetes: https://kubernetes.io/
[4] minikube: https://github.com/kubernetes/minikube
[5] клонировал этот репозиторий: https://github.com/colindembovsky/AzureAureliaDemo
[6] Aurelia: http://aurelia.io/
[7] Найджела Поултона (Nigel Poulton): https://twitter.com/nigelpoulton
[8] Getting Started with Kubernetes на PluralSight: https://www.pluralsight.com/courses/getting-started-kubernetes
[9] статью: https://blogs.msdn.microsoft.com/devops/2017/06/09/deploying-applications-to-azure-container-service/
[10] хостинга: https://www.reg.ru/?rlink=reflink-717
[11] интеграция с Azure Key Vault: https://www.visualstudio.com/en-us/docs/build/concepts/library/variable-groups#link-secrets-from-an-azure-key-vault-as-variables
[12] Colin's ALM Corner Build & Release Tasks: http://bit.ly/cacbuildtasks
[13] http://localhost:8001/ui: http://localhost:8001/ui
[14] Pull Request: https://github.com/Microsoft/vsts-tasks/pull/4657
[15] Quantum Quintum: https://t.me/quantumquintum
[16] Источник: https://habrahabr.ru/post/337708/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.