20 февраля 2018
Хардкор

Как мы настроили 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