Slide 1

Slide 1 text

Сборка сервисов в Docker через Docker-в-Docker Шамбир Сергей Ведущий инженер iSpring

Slide 2

Slide 2 text

Продукт X: переход к микросервисам Величайший враг прячется там, где вы будете меньше всего его искать. Гай Юлий Цезарь

Slide 3

Slide 3 text

REST REST REST сокеты Структура продукта X (до перехода на Docker) Монолит на PHP Монолит на PHP Frontend Микросервис на Go Микросервис на Node.js SPA iframe

Slide 4

Slide 4 text

REST REST REST сокеты Структура продукта X (в скором будущем) Монолит на PHP Монолит на PHP Frontend Микросервис на Go Микросервис на Node.js SPA SPA Микросервис на Go Микросервис на Go Микросервис на Go Микросервис на Go Микросервис на Node.js iframe iframe SPA Микросервис на Go

Slide 5

Slide 5 text

Deploy X kustomize Реестр dev Реестр prod

Slide 6

Slide 6 text

Build X Service X Frontend X Service Y Frontend Y Service Z Container x:v1.2.3 Container y:??? Container z:???

Slide 7

Slide 7 text

Резюмируя Не надо ограничиваться унификацией развёртывания образов  Подумайте об унификации сборки контейнеров из git  Используйте docker, чтобы упростить разработку

Slide 8

Slide 8 text

Сборка отдельно, деплой совместно Разделяй и властвуй. Гай Юлий Цезарь

Slide 9

Slide 9 text

Сборка: make + docker build docker build -t {branch.buildNo} . docker push {branch.buildNo} Makefile build: dep ensure go build -o ... ... Dockerfile FROM debian ADD ... /go/bin/outyet ENTRYPOINT /go/bin/outyet EXPOSE 8080 make build Сервис на Go

Slide 10

Slide 10 text

Сборка: только docker build https://blog.golang.org/docker docker build -t {branch.buildNo} . docker push {branch.buildNo} Dockerfile FROM golang ADD . /go/src/.../outyet RUN go install .../outyet ENTRYPOINT /go/bin/outyet EXPOSE 8080 Сервис на Go

Slide 11

Slide 11 text

Сборка: multi-stage docker build https:// blog.codeship.com/building-minimal-docker-c ontainers-for-go-applications/ docker build -t {branch.buildNo} . docker push {branch.buildNo} Dockerfile FROM golang:alpine as builder COPY . $GOPATH/src/outyet WORKDIR $GOPATH/src/outyet RUN go build -o /go/bin/outyet FROM scratch COPY --from=builder /go/bin/outyet /go/bin/outyet ENTRYPOINT ["/go/bin/outyet"] Сервис на Go

Slide 12

Slide 12 text

Нюансы сборки из scratch Проблемы:  У вас нет пакетного менеджера и командной оболочки  У вас нет SSL сертификатов (нельзя выполнять https запросы)  У вас нет данных о часовых поясах (tzdata) Решения: 1. github.com/jeremyhuiskamp/golang-docker-scratch 2. использовать alpine

Slide 13

Slide 13 text

Добавим трудностей  Пусть фронтенд будет сложным SPA  Установка зависимостей через npm install  Сборка через npm run dist  Запуск модульных тестов и linter через npm run test

Slide 14

Slide 14 text

Сборка: добавляем frontend docker build -t {branch.buildNo} . docker push {branch.buildNo} Dockerfile FROM node:11-alpine as frontend COPY ./www /usr/src/www RUN npm install && npm run dist FROM golang:alpine as builder COPY . $GOPATH/src/outyet WORKDIR $GOPATH/src/outyet RUN go build -o /go/bin/outyet FROM scratch COPY --from=builder /go/bin/outyet /go/bin/outyet COPY –from=frontend /usr/src/www/dist/ /go/bin/outyet/www ENTRYPOINT ["/go/bin/outyet"] Сервис на Go

Slide 15

Slide 15 text

Добавим трудностей  Пусть фронтенд будет сложным SPA  Установка зависимостей через npm install  Сборка через npm run dist  Запуск модульных тестов и linter через npm run test  Пусть фронтенд лежит в отдельном репозитории А в чём проблема? git submodule add git@git.x.com/frontend

Slide 16

Slide 16 text

Немного о сабмодулях Измени подмодуль в ветке A Как возненавидеть свою работу Измени подмодуль в ветке B Сделай merge Ты ещё считаешь, что git submodule – это круто? Да! Нет

Slide 17

Slide 17 text

Сборка: добавление frontend через скрипт docker build -t {branch.buildNo} . docker push {branch.buildNo} Dockerfile FROM node:11-alpine as frontend COPY ./www /usr/src/www RUN npm install && npm run dist if ! [ -d ${DIR} ]; then git clone ${REPO} ${DIR} fi cd ${DIR} git reset --hard git clean -fdx git fetch origin git checkout origin/${BRANCH} Скрипт обновления frontend Сервис на Go

Slide 18

Slide 18 text

Сборка: docker-контейнер с frontend docker build -t {branch.buildNo} . --build- arg "FRONT=harbour.x.com/frontend:$ {BRANCH.BUILD_NO}" docker push {branch.buildNo} Dockerfile ARG FRONT=nil FROM ${FRONT} as frontend FROM golang:alpine as builder COPY . $GOPATH/src/outyet WORKDIR $GOPATH/src/outyet RUN go build -o /go/bin/outyet FROM scratch Сервис на Go Фронтенд docker build -t {branch.buildNo} . docker push {branch.buildNo}

Slide 19

Slide 19 text

Резюмируя Для каждого микросервиса: 1. Использовать multi-stage docker builds + build args 2. Конфигурировать сервис CI для сбороки frontend, сборки сервиса и развёртывания продукта по цепочке

Slide 20

Slide 20 text

Согласованный deploy kustomize Container x:v1.2.3 Container x:TASK-981 Container x:master Container x:v1.2.4 Кто выбирает версии контейнеров? Где хранятся конфиги kustomize и k8s?

Slide 21

Slide 21 text

Согласование версий: подход от 2GIS Service X Frontend X Service Y Frontend Y Service Z Монорепозиторий: Service X Frontend X Service Y Fronten Y Service Z https://youtu.be/RSTHex_rKBU Подход к Continuous Deployment в микросервисной архитектуре / Алексей Баитов (2ГИС) Container x:v1.2.3 Container y:v2.0.19 Container z:master Сервис деплоя на Python С конфигами на Python

Slide 22

Slide 22 text

Резюмируя  Собирайте проекты в Docker-контейнере  Подумайте, как автоматизировать согласование версий микросервисов

Slide 23

Slide 23 text

Наше решение: X Platform Великие дела надо совершать, а не обдумывать их бесконечно. Гай Юлий Цезарь

Slide 24

Slide 24 text

Схема сборки Скрипт на Bash Запускает в Docker контейнере скрипт на Python3 X Platform bin x-platform src сервис сервис k8s … x-platform.yml x-platform.py Скрипт на Python3 ~600 строк Читает x-platform.yml Выполняет сборку и деплой

Slide 25

Slide 25 text

Схема сборки … services: zbackend: dir: src/zbackend git: remote: git@git.x.com/zbackend reference: origin/master dockerBuilder: image: builders/zbackend:newest workdir: /go/src/x/zbackend docker: image: zbackend scripts: build: - make build test: - make test X Platform bin x-platform src сервис сервис k8s … x-platform.yml x-platform.py

Slide 26

Slide 26 text

Схема сборки docker pull "${XBUILDER_IMAGE}" >/dev/null docker run --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --user $USER_ID:$DOCKER_GROUP_ID \ --volume /etc/passwd:/etc/passwd:ro \ --volume /etc/group:/etc/group:ro \ --volume ${SSH_DIR}:${SSH_DIR}:ro \ --volume ${KUBE_DIR}:${KUBE_DIR}:ro \ -e "CACHE_DIR=$CACHE_DIR" \ --volume "$CACHE_DIR":/app/cache \ --volume "$PLATFORM_DIR":/usr/src/app \ -e "PLATFORM_DIR=$PLATFORM_DIR" \ -w /usr/src/app \ "${XBUILDER_IMAGE}" /usr/src/app/bin/x-platform.py "$@" X Platform bin x-platform src сервис сервис k8s … x-platform.yml x-platform.py

Slide 27

Slide 27 text

Контейнеры для сборки контейнеров Каталог с контейнерами для сборки контейнеров X Platform bin x-update-builder builders zbackend zfrontend k8s x-platform.yml x-platform.py Dockerfile Файл описания контейнера-сборщика Исходников нет Только база + apt-get Скрипт для сборки контейнеров, собирающего контейнеры x-update-builder zbackend

Slide 28

Slide 28 text

Тег образа – это sha-1 последнего коммита Схема сборки x-platform build --services zbackend Обновление репозитория Сборка Unit тесты docker build docker push docker push В реестре или локально есть образ с таким sha-1? docker pull Нет Да

Slide 29

Slide 29 text

Плюсы X Platform как системы сборки контейнеров  Не требует монорепозитория  Тегирует образ по sha-1 коммита  Быстрая локальная сборка  Быстрая сборка на сервере  Относительно прост в реализации: 600 строк на Python, 2-3 недели разработки

Slide 30

Slide 30 text

Резюмируя  Свой велосипед – это хорошо, если его код минималистичен, а выгоды от автоматизации много  Положите свой велосипед в Docker

Slide 31

Slide 31 text

Альтернатива: flant/dapp Не господство устранено, а переменили господина. Марк Юний Брут

Slide 32

Slide 32 text

Что такое Dapp  https://flant.github.io/dapp/  Открытый проект компании Flant  Написан на Go  Выполняет сборку образов и согласованный deploy  Умеет работать с моно- и мультирепозиториями  Умеет кешировать все шаги сборки всех контейнеров  Умеет тегировать контейнеры по sha-1 коммита, по ветке, по номеру билда

Slide 33

Slide 33 text

Сомнительные особенности Dapp  Заменяет Dockerfile  Поддерживает Ansible  Deploy только через Helm + Kubernetes

Slide 34

Slide 34 text

Резюмируя  Используйте dapp как выбор по умолчанию для автоматизации CI  Пишите свой скрипт, если dapp не подходит  Не полагайтесь на TeamCity, Gitlab CI, Buildbot – они by design не рассчитаны на микросервисы и Docker

Slide 35

Slide 35 text

Спасибо за внимание! Вопросы?