Эта статья является частью нашего курса Академии под названием Docker Tutorial для разработчиков Java .
В этом курсе мы предлагаем серию руководств, чтобы вы могли разрабатывать свои собственные приложения на основе Docker. Мы охватываем широкий спектр тем, от Docker через командную строку, до разработки, тестирования, развертывания и непрерывной интеграции. С нашими простыми учебными пособиями вы сможете запустить и запустить собственные проекты за минимальное время. Проверьте это здесь !
Содержание
1. Введение
Многие компании использовали виртуализацию на основе контейнеров для развертывания приложений (в том числе на основе JVM) в производственном режиме до появления Docker на горизонте. Однако, в первую очередь из-за Docker , практика развертывания с использованием контейнеров в наши дни стала основной.
В этом разделе руководства мы рассмотрим некоторые из наиболее популярных механизмов оркестровки и управления кластерами (включая несколько облачных предложений), которые изначально поддерживают развертывание и жизненный цикл контейнерных приложений.
Темы, о которых мы поговорим, стоят нескольких книг (по крайней мере!), Поэтому цель этой части — служить введением. Если вы испытываете особый интерес к любому из них, в открытом доступе есть огромное количество ресурсов.
2. Контейнеры как единицы развертывания
В наши дни контейнеры (в частности, контейнеры Docker ) стали стандартизированными единицами развертывания программного обеспечения. Они упакованы со всем, что может понадобиться приложениям: кодом (или двоичным кодом), средой выполнения, системными инструментами и библиотеками, как вы это называете.
Управление и организация развертываний на основе контейнеров — довольно актуальная тема, и, как мы увидим через мгновение, каждое имеющееся решение предлагает ее с самого начала.
3. Оркестровка с использованием Kubernetes
В редких случаях вы еще не слышали об этом, Kubernetes — это система с открытым исходным кодом для автоматизации развертывания, масштабирования и управления контейнерными приложениями. Это один из самых интересных, инновационных и активно развивающихся проектов в сообществе открытого кода. Возможно, если вы или ваша компания ищете решение для контейнерной оркестровки, Kubernetes является де-факто выбором в наши дни.
Kubernetes может сделать для вас много вещей, но в этой части руководства мы увидим, как легко развернуть наш контейнер приложений Spring Boot , включая MySQL , с использованием лишь минимального подмножества функций Kubernetes .
Настройка полноценного кластера Kubernetes на локальном компьютере может показаться нецелесообразной, но, к счастью, Kubernetes может быть развернут в режиме разработки через Minikube . Этот удивительный инструмент порождает кластер Kubernetes с одним узлом внутри виртуальной машины, чтобы вы могли разрабатывать его на повседневной основе, например, на своем ноутбуке или настольном компьютере.
Предполагая, что вы установили minikube в выбранной вами операционной системе, давайте перейдем к следующему шагу и развернем на нем пару контейнеров Docker .
1
|
$ minikube start |
Когда Minikube запущен, мы можем сразу же начать развертывание MySQL , придерживаясь той же версии 8.0.2
которую мы использовали в этом руководстве.
1
|
$ kubectl run mysql --image=mysql:8.0.2 -- env = 'MYSQL_ROOT_PASSWORD=p$ssw0rd' -- env = 'MYSQL_DATABASE=my_app_db' -- env = 'MYSQL_ROOT_HOST=%' --port=3306 |
Это займет некоторое время, и в конце вы сможете увидеть, что MySQL контейнер (или, точнее, Kubernetes pod) запущен и работает:
1
2
3
|
$ kubectl get pod NAME READY STATUS RESTARTS AGE mysql-5d4dbfcd58-6fmck 1 /1 Running 0 22m |
Отлично, теперь нам нужно перестроить образ Docker нашего приложения Spring Boot, которое мы разработали ранее , используя настройки Docker развернутого кластера Kubernetes (в качестве альтернативы, мы могли бы использовать частный реестр).
1
2
3
4
5
6
|
$ eval $(minikube docker- env ) $ docker image build \ --build-arg BUILD_VERSION=0.0.1-SNAPSHOT \ -f Dockerfile.build \ -t jcg /spring-boot-webapp :latest \ -t jcg /spring-boot-webapp :0.0.1-SNAPSHOT . |
По завершении этого шага у нас есть образ Docker, доступный для развертывания в Kubernetes, и мы можем запустить его как еще один модуль.
1
|
$ kubectl run spring-boot-webapp --image=jcg /spring-boot-webapp :latest -- env = 'DB_HOST=mysql.default.svc.cluster.local' --port=19900 --image-pull-policy=Never |
Давайте проверим, что у нас есть два модуля:
1
2
3
4
|
$ kubectl get pod NAME READY STATUS RESTARTS AGE mysql-5d4dbfcd58-6fmck 1 /1 Running 0 33m spring-boot-webapp-5ff8456bf5-gf5qv 1 /1 Running 0 31m |
И последнее, но не менее важное: мы должны представить развертывание нашего приложения Spring Boot как сервис Kubernetes, чтобы сделать его доступным:
1
|
$ kubectl expose deployment spring-boot-webapp -- type =NodePort |
И быстро проверьте, что это перечислено среди других услуг:
1
2
3
4
|
$ kubectl.exe get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S AGE kubernetes ClusterIP 10.96.0.1 443 /TCP 4d spring-boot-webapp NodePort 10.109.108.87 19900:30253 /TCP 40s |
И это в основном то, что за несколько простых шагов мы запустили и запустили наши контейнеры Docker , которыми все управляет Kubernetes . Давайте удостоверимся, что приложение фактически проходит все проверки работоспособности:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
$ curl $(minikube service spring-boot-webapp --url) /application/health { "status" : "UP" , "details" : { "diskSpace" : { "status" : "UP" , "details" : { "total" :17293533184, "free" :14476333056, "threshold" :10485760 } }, "db" : { "status" : "UP" , "details" : { "database" : "MySQL" , "hello" :1 } } } } |
И это действительно так! Чтобы завершить нашу дискуссию о Kubernetes , стоит упомянуть, что Docker уже включает раннюю встроенную интеграцию с Kubernetes на некоторых пограничных каналах .
4. Оркестровка с использованием Apache Mesos
Apache Mesos , возможно, является одной из самых старых используемых сред управления ресурсами и кластерами. Он эффективно отводит ресурсы (ЦП, память, хранилище) от физического или виртуального оборудования, позволяя создавать и эксплуатировать отказоустойчивые и эластичные распределенные системы. Одна из его сильных сторон — исключительный уровень расширяемости и поддержки развертываний приложений в контейнерах, однако он также известен как довольно сложный и сложный в эксплуатации.
Архитектурно Apache Mesos состоит из master
который управляет agents
(работает на каждом узле кластера), и frameworks
(которые выполняют tasks
на этих агентах). Мастер позволяет детально распределять ресурсы (ЦП, ОЗУ и т. Д.) В разных средах, resource offers
им resource offers
. Ограничив себя только необходимыми компонентами, давайте посмотрим, как кластер Apache Mesos можно определить с помощью спецификации docker-compose .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
version: "3" services: zookeeper: image: zookeeper networks: - mesos-network environment: ZOO_TICK_TIME: 2000 ZOO_INIT_LIMIT: 10 ZOO_SYNC_LIMIT: 5 ZOO_MAX_CLIENT_CNXNS: 128 ZOO_PORT: 2181 ZOO_MY_ID: 1 mesos-master: image: mesosphere /mesos-master :1.3.2 networks: - mesos-network ports: - "5050:5050" environment: MESOS_ZK: zk: //zookeeper :2181 /mesos MESOS_QUORUM: 1 MESOS_CLUSTER: docker-compose MESOS_REGISTRY: replicated_log volumes: - /var/run/docker .sock: /run/docker .sock depends_on: - zookeeper mesos-slave: image: mesosphere /mesos-slave :1.3.2 privileged: true networks: - mesos-network ports: - "5051:5051" links: - zookeeper - mesos-master environment: - MESOS_CONTAINERIZERS=docker - MESOS_ISOLATOR=cgroups /cpu , cgroups /mem - MESOS_LOG_DIR=var /log - MESOS_MASTER=zk: //zookeeper :2181 /mesos - MESOS_PORT=5051 - MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins - MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs - MESOS_DOCKER_STOP_TIMEOUT=90secs - MESOS_RESOURCES=cpus:2;mem:2080;disk:5600;ports(*):[19000-19999] - MESOS_WORK_DIR= /var/lib/mesos - MESOS_SYSTEMD_ENABLE_SUPPORT= false volumes: - /var/run/docker .sock: /run/docker .sock dns: - mesos-dns depends_on: - mesos-master - mesos-dns marathon: image: mesosphere /marathon :v1.5.6 networks: - mesos-network environment: - MARATHON_ZK=zk: //zookeeper :2181 /marathon - MARATHON_MASTER=zk: //zookeeper :2181 /mesos ports: - "8080:8080" depends_on: - mesos-master mesos-dns: image: mesosphere /mesos-dns :v0.6.0 command : [ "/usr/bin/mesos-dns" , "-v=2" , "-config=/config.json" ] ports: - 53:53 /udp - 8123:8123 volumes: - . /config .json: /config .json - /tmp links: - zookeeper dns: - 8.8.8.8 - 8.8.4.4 networks: - mesos-network networks: mesos-network: driver: bridge |
Как мы видим, там довольно много движущихся частей, кроме Apache Mesos (и Apache Zookeeper ). В основе этого лежит платформа Marathon , платформа оркестровки контейнеров. Marathon предоставляет прекрасный веб-интерфейс, а также REST (ful) API для управления развертыванием приложений и использует собственный формат спецификаций на основе JSON . Следуя нашему стеку приложений Spring Boot , давайте рассмотрим пример дескриптора развертывания MySQL (который хранится в файле mysql.json
):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
{ "id" : "/jcg/mysql" , "container" : { "type" : "DOCKER" , "docker" : { "image" : "mysql:8.0.2" , "network" : "BRIDGE" , "portMappings" : [ { "containerPort" : 3306, "servicePort" : 3306, "hostPort" : 0, "protocol" : "tcp" } ], "parameters" : [ { "key" : "hostname" , "value" : "mysql" } ] } }, "env" : { "MYSQL_ROOT_PASSWORD" : "p$ssw0rd" , "MYSQL_DATABASE" : "my_app_db" , "MYSQL_ROOT_HOST" : "%" }, "instances" : 1, "cpus" : 0.1, "mem" : 500, "healthChecks" : [ { "protocol" : "COMMAND" , "command" : { "value" : "ss -ltn src :3306 | grep 3306" }, "gracePeriodSeconds" : 10, "intervalSeconds" : 10, "timeoutSeconds" : 5, "maxConsecutiveFailures" : 2 } ] } |
Теперь, чтобы запустить MySQL- контейнер, нам просто нужно отправить этот дескриптор в Marathon , используя его REST (ful) API (при условии, что наш Apache Mesos запущен и работает), например:
1
2
3
4
5
6
7
8
9
|
$ curl -X POST http: //localhost :8080 /v2/apps -d @mysql.json -H "Content-type: application/json" { "id" : "/jcg/mysql" , "container" :{ … }, … } |
Выглядит хорошо, давайте сделаем то же самое для приложения Spring Boot , начиная с дескриптора развертывания Marathon и spring-webapp.json
файле spring-webapp.json
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
{ "id" : "/jcg/spring-webapp" , "container" : { "type" : "DOCKER" , "docker" : { "image" : "jcg/spring-boot-webapp:latest" , "network" : "BRIDGE" , "portMappings" : [ { "containerPort" : 19900, "servicePort" : 19900, "hostPort" : 19900 } ], "parameters" : [ { "key" : "hostname" , "value" : "spring-webapp" } ] } }, "env" : { "DB_HOST" : "172.17.0.2" }, "instances" : 1, "cpus" : 0.1, "mem" : 512, "healthChecks" : [ { "protocol" : "COMMAND" , "command" : { "value" : "nc -z localhost 19900" }, "gracePeriodSeconds" : 25, "intervalSeconds" : 10, "timeoutSeconds" : 5, "maxConsecutiveFailures" : 3 } ] } |
Следующим шагом будет отправить его на Марафон :
1
2
3
4
5
6
7
8
9
|
$ curl -X POST http: //localhost :8080 /v2/apps -d @spring-webapp.json -H "Content-type: application/json" { "id" : "/jcg/spring-webapp" , "container" :{ … }, … } |
И мы эффективно сделали! Как только развертывание будет завершено, мы сможем увидеть наш стек приложений в рабочем состоянии, используя, например, веб-интерфейс Marathon , доступный по адресу http: // localjost: 8080 / ui / .
Любопытный читатель может задаться вопросом, как мы связали эти два приложения Marathon , Spring Boot и MySQL , вместе. В этом конкретном случае мы использовали возможности Apache Mesos для обнаружения служб и распределения нагрузки, выполняемые Mesos-DNS . Чтобы проиллюстрировать их в действии, мы можем запросить IP-адрес экземпляра MySQL по его имени mysql-jcg.marathon.mesos
.
1
2
3
4
5
6
7
|
$ curl http: //localhost :8123 /v1/hosts/mysql-jcg .marathon.mesos [ { "host" : "mysql-jcg.marathon.mesos." , "ip" : "172.17.0.2" } ] |
Как обычно, давайте подтвердим, что приложение Spring Boot запущено и работает, отправив HTTP-запрос на конечную точку работоспособности:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$ curl http: //localhost :19900 /application/health { "details" : { "db" : { "details" : { "database" : "MySQL" , "hello" : 1 }, "status" : "UP" }, "diskSpace" : { "details" : { "free" : 44011802624, "threshold" : 10485760, "total" : 49536962560 }, "status" : "UP" } }, "status" : "UP" } |
5. Оркестровка с использованием Docker Swarm
Прошло некоторое время с тех пор, как Docker имеет встроенные в движок функции управления кластером и его оркестровки. Этот оркестровочный слой раньше назывался Docker Swarm, но позже превратился, по сути, в специальный режим ( режим роя ) для запуска Docker Engine .
Если вы делаете большие ставки на Docker и предпочитаете не искать ничего другого, запуск Docker Engine в режиме роя может быть хорошим вариантом для оркестра. С ним довольно легко начать.
1
|
$ docker swarm init |
Концептуально, существует довольно много различий, которые вводит режим роя, помимо просто изменений в самом Docker Engine . Прежде всего, вы должны начать думать с точки зрения услуг, а не контейнеров. Предположения о том, что все выполняется внутри одного хоста Docker, больше не будут точными, поскольку рой очень хотел бы состоять из множества хостов Docker, распределенных по сети.
При запуске Docker Engine в режиме роя мы можем развернуть полный стек приложений (сервисов), используя уже знакомую спецификацию docker-compose . Однако существует только одно ограничение: формат файла docker-compose должен быть версии 3 (or above)
чтобы быть совместимым между Docker Compose и режимом роя Docker Engine .
Чтобы увидеть режим роя в действии, давайте немного переделаем наш стек приложений Spring Boot в соответствии с форматом файла docker-compose версии 3.3
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
version: '3.3' services: mysql: image: mysql:8.0.2 environment: - MYSQL_ROOT_PASSWORD=p$$ssw0rd - MYSQL_DATABASE=my_app_db - MYSQL_ROOT_HOST=% healthcheck: test : [ "CMD-SHELL" , "ss -ltn src :3306 | grep 3306" ] interval: 10s timeout: 5s retries: 3 networks: - my-app-network java-app: image: jcg /spring-boot-webapp :latest environment: - DB_HOST=mysql ports: - 19900:19900 depends_on: - mysql healthcheck: test : [ "CMD-SHELL" , "nc -z localhost 19900" ] interval: 10s timeout: 5s retries: 3 networks: - my-app-network networks: my-app-network: driver: overlay |
Честно говоря, нам не нужно было делать много изменений. Специально для поддержки режима роя существует специальное семейство команд, которое было введено в инструментальные средства docker stack
: docker stack
. Мы не говорили о них во второй части этого урока , но сейчас самое время это сделать.
С помощью команды deploy и спецификации docker-compose мы могли бы инициировать развертывание стека приложений в кластере swarm.
1
|
$ docker stack deploy --compose- file docker-compose.yml springboot-webapp |
Чтобы увидеть состояние развертываний, а также всех развернутых сервисов, мы могли бы использовать команду services , как в примере ниже (вывод был немного сокращен):
1
2
3
4
|
$ docker stack services springboot-webapp NAME IMAGE REPLICAS PORTS springboot-webapp_java-app jcg /spring-boot-webapp :latest 1 /1 *:19900->19900 /tcp springboot-webapp_mysql mysql:8.0.2 1 /1 |
Круто, похоже, что наше приложение Spring Boot запущено и работает, давайте подтвердим это, отправив HTTP-запрос на конечную точку работоспособности:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$ curl http: //localhost :19900 /application/health { "details" : { "db" : { "details" : { "database" : "MySQL" , "hello" : 1 }, "status" : "UP" }, "diskSpace" : { "details" : { "free" : 3606978560, "threshold" : 10485760, "total" : 19195224064 }, "status" : "UP" } }, "status" : "UP" } |
Это выглядит именно то, что мы ожидали. В заключение следует отметить, что Docker Engine в режиме роя представляет интересный вариант, но стоит отметить, что он не так популярен, как Kubernetes или Apache Mesos .
6. Контейнеры в облаке
Каждый крупный игрок в облачном пространстве спешит на рынок со своими собственными управляемыми предложениями, которые намереваются поддержать развертывание и оркестровку контейнеров, чтобы вы могли просто уронить один из них и волшебство случилось. Давайте быстро взглянем на них.
6.1. Amazon Эластичный Контейнерный Сервис
Amazon Elastic Container Service (или просто Amazon ECS ) — это масштабируемая, быстрая служба управления контейнерами, которая позволяет легко запускать, останавливать и управлять контейнерами Docker в кластере. Как вы можете ожидать, Amazon ECS прекрасно интегрируется со многими другими облачными предложениями из портфолио Amazon Web Services , включая:
- Управление идентификацией и доступом AWS
- Amazon EC2 с автоматическим масштабированием
- Упругая балансировка нагрузки
- Amazon Elastic Container Registry
- AWS CloudFormation
Amazon ECS — это региональная служба, которая упрощает запуск контейнеров приложений с высокой степенью доступности в нескольких зонах доступности в регионе.
6.2. Google Kubernetes Engine
Google Kubernetes Engine (ранее известный как Google Container Engine) — это управляемая среда для развертывания контейнерных приложений. Он привносит уникальный опыт Google и последние инновации в продуктивности разработчиков, эффективности использования ресурсов, автоматизированных операциях и гибкости открытого исходного кода для ускорения выхода на рынок.
Google очень долго выполнял производственные рабочие нагрузки в контейнерах и включил лучшее из того, что они узнали, в Kubernetes , ведущего в отрасли оркестратора контейнеров с открытым исходным кодом, который работает с Kubernetes Engine . Он предлагает (но не ограничивается) следующие отличительные особенности:
- Управление идентификацией и доступом
- Гибридная сеть
- Безопасность и соответствие
- Интегрированная регистрация и мониторинг
- Авто Масштаб
- Автообновление
- Авто Ремонт
- Пределы ресурса
- Поддержка приложений с отслеживанием состояния
- Поддержка изображений Docker
- Полностью управляемый
- ОС, созданная для контейнеров
- Реестр частных контейнеров
- Быстрая согласованная сборка
- Портативность открытого исходного кода
6.3. Служба контейнеров Azure
Служба контейнеров Azure (AKS) управляет размещенной средой Kubernetes , обеспечивая быстрое и простое развертывание и управление контейнеризованными приложениями без опыта управления контейнерами. Он также устраняет бремя текущих операций и обслуживания за счет предоставления, обновления и масштабирования ресурсов по требованию без необходимости переводить приложения в автономный режим.
Как управляемая служба Kubernetes , контейнерная служба Azure предоставляет:
- Автоматизированные обновления и исправления версии Kubernetes
- Простое масштабирование кластера
- Самовосстанавливающееся управление самолетом (мастера)
- Платите только за работающие узлы пула агентов
7. Выводы
В этом разделе руководства мы рассмотрели ряд ведущих решений для управления кластерами и их оркестровки, которые предлагают всестороннюю поддержку развертывания приложений в контейнерах. В целом, Kubernetes играет ведущую роль, однако у каждого варианта есть свои плюсы и минусы.
8. Что дальше
В следующей, заключительной части урока мы поговорим об очень важном предмете практики непрерывной интеграции и о том, как Docker вписывается в картину.
Полный набор файлов конфигурации и спецификации доступен для скачивания .