Как мы настроили Continuous Delivery в Kubernetes с помощью TFS
Мы продолжаем наш путь к Continuous Delivery (CD) и High Availability (HA), основанной на избыточности. В предыдущей серии мы перевели API для мобильного приложения на .NET Core. Следующий логичный шаг для достижения CD — настроить сборку в Docker-контейнер.
Сегодня поделимся нашим getting-started гайдом по настройке сборки docker-образов и деплоя в Kubernetes в TFS для разработчиков .NET.

Настройка ASP.NET приложения на работу с Docker
1. В Visual Studio 2017 правой кнопкой по web проекту -> Add -> Docker Support;
2. Для VS2015 нужно дополнительно поставить расширение.
3. В папку с проектом добавится файл Dockerfile – это конфиг для создания образа нашего приложения.
4. Подробнее о Docker можно почитать здесь.
5. Добавится новый проект *docker-compose*.
6. Сама по себе docker-compose – это утилита для управления мульти-контейнерными приложениями. Например, вы запускаете приложение и СУБД к нему.
7. Файлы в проекте:
a. *docker-compose.yml* – описание ваших сервисов/зависимостей.
Вот пример ASP.NET приложения в связке с SQL Server:
version: '3'
services:
agentrequests.webapp:
image: agentrequests.webapp
build:
context: .
dockerfile: AgentRequests.WebApp/Dockerfile
depends_on:
- agentrequests-db
agentrequests-db:
image: microsoft/mssql-server-linux
environment:
SA_PASSWORD: "1"
ACCEPT_EULA: "Y"
ports:
- "1401:1433"
volumes:
- agent-requests-db-data:/var/opt/mssql
volumes:
agent-requests-db-data:
Имена сервисов (в примере БД - agentrequests-db) можно использовать напрямую в вашем приложении, этакий Server Side Service Discovery.
К примеру, строка соединения до базы – "Server=agentrequests-db;Database=AgentRequests;User=sa;Password=1;"
b. *docker-compose.override.yml* – этот файл используется при разработке. Visual Studio мержит эти файлы, когда жмёте F5.
HINT: При каждом изменении docker-compose.yml приложению будет назначаться новый локальный порт, что быстро надоедает при дебаге. Поэтому в docker-compose.override.yml полезно зафиксировать порт вашего приложения:
version: '3'
services:
agentrequests.webapp:
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "40005:80"
c. *docker-compose.ci.build.yml* – с этим конфигом можно сбилдить ваше приложение на CI, и результат будет аналогичным локальному билду. Этот файл нужен, если вы просто деплоите готовые файлы, например, в IIS. Мы же собираемся поставлять готовые docker-образы и будем использовать Dockerfile напрямую.
Промежуточный итог: делаем проект docker-compose стартовым, жмём F5 и радуемся. NOTE: Первый запуск может оказаться долгим, поскольку докеру нужно скачать образы SQL/ASP.Net Core.
Также при дебаге Visual Studio не создаёт новый докер-образ при каждом изменении кода приложения – на самом деле, создаётся только один контейнер из вашего Dockerfile, к которому монтируется папка c вашими исходниками на хост-машине. Таким образом, каждое изменение, например, js-файла, мгновенно отразится даже на запущенном контейнере.
Сборка и деплой Docker-образов в TFS
CI предполагает, что у нас есть build-машина для выполнения автоматизированных сборок независимо от разработчика. Разработчики заливают свои изменения в систему контроля версиями, build-машина берет последние изменения и пересобирает проект. Таким образом, на build-машине должны быть все необходимые инструменты для сборки проекта. В нашем случае она должна иметь доступ к Docker, чтобы собирать Docker-образы.
Есть несколько вариантов:
1. Мы можем поставить Docker непосредственно на build-машину либо удаленно подключаться к Docker на другой машине через Docker-клиент. Изначально у нас была стандартная разработка .Net на Windows, поэтому все build-машины представляли собой виртуальные машины Windows с одним или несколькими build-агентами. Чтобы Docker мог собирать Linux-контейнеры на Windows-машине, докер устанавливает виртуальную машину с Linux. Получается, что у нас будет несколько вложенных друг в друга виртуальных машин. Но что-то не хочется начинать городить огороды, и Docker официально не поддерживает такой режим.
2. Чтобы подключиться к Docker на другой машине, нужно настраивать удаленный доступ, по умолчанию он выключен. Также рекомендуется обеспечить безопасность TLS сертификатам. Еще есть инструкция от Microsoft, в которой предлагается упрощенный вариант настройки с помощью windows-контейнера с предустановленной LibreSSL.
3. Наиболее простой способ: build-агент можно запустить прямо в Docker-контейнере, и он будет иметь доступ к Docker, на котором запущен. Достаточно выбрать нужный контейнер из репозитория microsoft/vsts-agent.
Настройка билд-агента
1. Скачиваем билд-агент.
2. Про различия версий образов и параметры можно прочитать [тут](https://github.com/Microsoft/vsts-agent-docker).
3. Нужна версия c docker'ом на борту, к примеру: docker pull microsoft/vsts-agent:ubuntu-16.04-tfs-2017-u1-docker-17.12.0-ce
4. Генерим Personal Access Token (PAT) в на странице Security в TFS:

5. Можно добавить новый Agent Pool для сборок докера. Делается это здесь:

6. Запускаем контейнер:
docker run \
-e TFS_URL= \
-e VSTS_TOKEN= \
-e VSTS_POOL= \
-e VSTS_AGENT=$(hostname)-agent \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart=always \
-it microsoft/vsts-agent:ubuntu-16.04-tfs-2017-u1-docker-17.12.0-ce
Настройка CI
1. В проекте в TFS добавляем новый Build Definition с темплейтом – Container (PREVIEW)
2. Таска build image:
a. Container Registry Type – Container Registry;
b. Docker Registry Connection – здесь настраиваем путь до вашего реестра образов. Можно использовать и Docker Hub, но мы в компании используем Nexus Registry;
c. Docker File – путь до докер файла. Лучше указать путь явно, без маски;
d. Use Default Build Context – снимаем галочку;
e. Build Context – путь до папки, в которой лежит ваш .sln файл;
f. Image-name – лучше задать явно, все символы в нижнем регистре. Пример: groups/agent-requests:$(Build.BuildId);
g. Можно поставить include latest tag – будет обновляться latest тег в реестре.
3. Таска push an image - аналогично второму пункту. Главное, не забыть поменять image name.
4. Добавить таску с темплейтом Publish Build Artifacts. Поскольку мы планируем деплоить в kubernetes, нашим артефактом будет конфиг для kubectl:
a. Path to Publish – путь до вашего yaml файла с конфигом kubernetes. Можно указать папку, если конфигов несколько;
b. Artifact Name – на ваш вкус. К примеру, kubernetes;
c. Artifact Type – Server.
Настройка CD и Kubernetes
Вначале небольшое отступление. Грубо говоря, docker-compose (swarm) – это конкурент kubernetes. Но поскольку в VS нет удобного тулинга для билда и дебага в kubernetes, то используем оба варианта: compose при разработке, kubernetes на бою.
Приятная новость в том, что есть утилита [Kompose](http://kompose.io/) – она умеет конвертить Kubernetes конфиги в/из docker-compose.yaml файлы.
Впрочем, не обязательно для девелопа вообще использовать docker/compose – можно настроить всё по старинке и руками менять урлы/конфиги или хранить по десять web.config для разных окружений.
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
type: LoadBalancer
selector:
app: webapp
ports:
- port: 80
Пример deployment.yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 1
template:
metadata:
labels:
app: webapp
spec:
imagePullSecrets:
- name: <название соединения с Docker Registry>
containers:
- image: webapp
name: webapp
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: database-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: database-secret
key: password
- name: SQLCONNSTR_<Название сроки подключения>
#например SQLCONNSTR_DefaultConnection
value: "Server=<адрес SQL сервера>;Initial Catalog=<название БД>;Persist Security Info=False;User ID=$(DB_USER);Password=$(DB_PASSWORD);"
ports:
- containerPort: 80
Для настройки CD мы использовали [Kubernetes extension](https://marketplace.visualstudio.com/items?itemName=tsuyoshiushio.k8s-endpoint) для нашего TFS сервера, так как стандартная таска Deploy to Kubernetes, которая идет из коробки, в нашей версии TFS оказалась нерабочей.
1. Добавьте в Kubernetes настройки подключения к нашему Docker Registry
kubectl create secret docker-registry\
<название соединения с Docker Registry>\
--docker-server=<адрес сервера>\
--docker-username=<логин>\
--docker-password=<пароль>\
--docker-email=<почта>
2. Добавьте логин и пароль для подключения к базе
kubectl create secret generic database-secret\
--from-literal=username=<логин>\
--from-literal=password=<пароль>
ASP.NET Core приложения под Linux в продакшене
3. Добавьте Kubernetes endpoint в TFS:

4. Создайте новый Release Defenition:
a. Выберите проект и Build definition
b. Поставьте галочку Continuous deployment

5. Добавьте таску kubernetes downloader:
a. В поле “kubernetes end point” выберите ваш kubernetes endpoint
b. В поле “kubectl download version” укажите необходимую версию или оставьте поле пустым, в этом случае будет установлена последняя версия клиента.

6. Добавьте таску kubectl exec:
a. В поле “Sub Command” пишем: apply
b. В поле “Arguments” пишем: -f $(System.DefaultWorkingDirectory)/<путь к папке с конфигами>/deployment.yaml

7. Добавьте таску kubectl exec:
a. В поле “Sub Command” пишем: apply
b. В поле “Arguments” пишем: image -f $(System.DefaultWorkingDirectory)/<путь к папке с конфигами>/service.yaml
8. Добавьте таску kubectl exec:
a. В поле “Sub Command” пишем: set
b. В поле “Arguments” пишем: image -f $(System.DefaultWorkingDirectory)/<путь к папке с конфигами>/deployment.yaml webapp=webapp:$(Build.BuildID)
Итоги
За сим всё. Используйте docker, автоматизируйте развёртывание и наслаждайтесь лёгким релизом хоть в вечер пятницы, даже перед вашим отпуском.
Нопоследок несколтко ссылок которые мы нашли полезными
Оригинал опубликован на Habr.com