本文是我们学院课程中名为《 面向Java开发人员的Docker教程 》的一部分。
在本课程中,我们提供了一系列教程,以便您可以开发自己的基于Docker的应用程序。 我们涵盖了广泛的主题,从通过命令行的Docker到开发,测试,部署和持续集成。 通过我们简单易懂的教程,您将能够在最短的时间内启动并运行自己的项目。 在这里查看 !
目录
-
1.简介 2.容器作为部署单位 3.使用Kubernetes进行编排 4.使用Apache Mesos进行编排 5.使用Docker Swarm进行编排 6.云中的容器
-
-
6.1。 亚马逊弹性容器服务 6.2。 Google Kubernetes引擎 6.3。 Azure容器服务
7.结论 8.接下来
1.简介
在Docker出现之前,许多公司一直在使用基于容器的虚拟化以生产方式部署应用程序(包括基于JVM的应用程序)。 但是,主要由于Docker的缘故, 如今使用容器的部署实践已成为主流。
在本教程的这一部分中,我们将浏览一些本地支持容器化应用程序的部署和生命周期的最流行的业务流程和集群管理引擎(也包括几个云产品)。
我们将要讨论的主题值得(至少!)几本书,因此这部分的目的是作为介绍。 如果您对其中任何一种有特别的兴趣,则可以通过公共访问获得大量资源。
2.容器作为部署单位
如今 ,容器(尤其是Docker容器)已成为软件部署的标准化单位。 它们预先打包了应用程序可能需要运行的所有内容:代码(或二进制文件),运行时,系统工具和库,随便命名。
管理和编排基于容器的部署是一个非常热门的话题,并且正如我们稍后将看到的那样,那里的每个解决方案都从一开始就提供了解决方案。
3.使用Kubernetes进行编排
在极少数情况下,您还没有听说过, Kubernetes是一个开源系统,用于自动化容器化应用程序的部署,扩展和管理。 这是开源社区中最令人兴奋,创新和积极发展的项目之一。 也许,如果您或您的公司正在寻找容器编排解决方案, 那么Kubernetes是当今的事实选择。
Kubernetes可以为您做很多事情,但是在本部分的教程中,我们将了解仅使用Kubernetes功能的最小子集来部署我们的容器化Spring Boot应用程序堆栈(包括MySQL)是多么容易。
建立一个全面的Kubernetes在本地机器上集群听起来有点不切实际,但幸运的是, Kubernetes能够在发展的模式,通过部署minikube 。 这个很棒的工具在虚拟机内部产生一个单节点Kubernetes集群,因此您可以使用笔记本电脑或台式机在其上进行日常开发。
假设您在选择的操作系统上安装了minikube ,让我们继续下一步,并在其上部署几个Docker容器。
$ minikube start
当启动minikube时,我们可以立即启动MySQL部署,并坚持使用与本教程相同的版本8.0.2
。
$ 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)正在运行:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-5d4dbfcd58-6fmck 1/1 Running 0 22m
太好了,现在我们需要使用已部署的Kubernetes集群的Docker设置来重建我们先前开发的 Spring Boot应用程序的Docker映像(或者,我们可以使用私有注册表)。
$ 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 .
完成此步骤后,我们就可以在Kubernetes中部署我们的Docker映像,并且可以将其作为另一个pod运行。
$ 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
让我们检查一下是否有两个Pod已启动并正在运行:
$ 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服务,以使其可访问:
$ kubectl expose deployment spring-boot-webapp --type=NodePort
并快速检查它是否在其他服务中列出:
$ 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管理。 让我们确保应用程序实际上通过了所有运行状况检查:
$ 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可以说是最古老的资源和集群管理框架之一。 它有效地从物理或虚拟硬件中提取资源(CPU,内存,存储),从而允许构建和运行容错和弹性的分布式系统。 它的优点之一是出色的可扩展性和对容器化应用程序部署的支持,但是,众所周知它非常复杂且难以操作。
从结构上讲 , Apache Mesos由管理agents
(在每个群集节点上运行)的master
和frameworks
(在这些代理上运行tasks
)组成。 主服务器通过为框架resource offers
资源来实现细粒度的资源共享(CPU,RAM等)。 仅限于必要的组件,让我们看一下如何使用docker-compose规范定义Apache Mesos集群。
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提供了漂亮的Web UI以及REST(ful)API来管理应用程序部署,并使用自己的基于JSON的规范格式。 在我们的Spring Boot应用程序堆栈之后,让我们看一下MySQL部署描述符的示例(存储在mysql.json
文件中):
{
"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容器生效,我们只需要利用其REST(ful)API (假设我们的Apache Mesos已启动并正在运行)就向Marathon提交此描述符,例如:
$ curl -X POST http://localhost:8080/v2/apps -d @mysql.json -H "Content-type: application/json"
{
"id":"/jcg/mysql",
"container":{
…
},
…
}
看起来不错,让我们从Marathon部署描述符开始,对Spring Boot应用程序执行相同的操作,并将其保存在spring-webapp.json
文件中。
{
"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
}
]
}
下一步是将其提交给Marathon :
$ curl -X POST http://localhost:8080/v2/apps -d @spring-webapp.json -H "Content-type: application/json"
{
"id":"/jcg/spring-webapp",
"container":{
…
},
…
}
我们已经完成了! 部署完成后,我们应该能够使用例如Marathon的Web UI (可从http:// localjost:8080 / ui /访问)来查看处于运行状态的应用程序堆栈。
好奇的读者可能想知道我们如何将这两个Marathon应用程序( Spring Boot和MySQL )链接在一起。 对于这种特殊情况,我们一直在使用Mesos-DNS实现的Apache Mesos的 服务发现和负载平衡功能。 为了说明它们的实际作用,这是我们如何通过其名称mysql-jcg.marathon.mesos
查询MySQL实例的IP地址。
$ curl http://localhost:8123/v1/hosts/mysql-jcg.marathon.mesos
[
{
"host": "mysql-jcg.marathon.mesos.",
"ip": "172.17.0.2"
}
]
与往常一样,让我们通过将HTTP请求发送到其运行状况端点来确认Spring Boot应用程序已启动并正在运行:
$ 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的一种特殊模式( swarm模式 )。
如果您将大量赌注押在Docker上并且不愿寻找其他东西,那么以编排模式运行Docker Engine可能是一个不错的选择。 入门也很容易。
$ docker swarm init
从概念上讲,除了Docker Engine本身的变化之外,群集模式还引入了很多差异。 首先,您应该开始考虑服务而不是容器。 在单个Docker主机中运行所有内容的假设不再准确,因为该集群很可能由分布在网络上的许多Docker主机组成。
当以集群 模式运行Docker Engine时,我们可以使用已经熟悉的docker-compose规范部署完整的应用程序(服务)堆栈。 但是只有一个限制,即docker-compose文件格式应为版本3 (or above)
版本3 (or above)
,以便在Docker Compose和Docker Engine的swarm模式之间兼容。
要查看运行中的swarm模式 ,让我们稍微修改一下Spring Boot应用程序堆栈以符合docker-compose文件格式3.3
版。
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
公平地讲,我们不必做很多更改。 为了专门支持swarm模式 ,在docker工具中引入了一系列专用命令: docker stack
。 在本教程的第二部分中我们没有讨论它们,但是现在是时候了。
有了deploy命令和docker-compose规范,我们可以启动将应用程序堆栈部署到swarm集群中。
$ docker stack deploy --compose-file docker-compose.yml springboot-webapp
要查看部署以及所有已部署服务的状态,我们可以使用services命令,如下面的示例所示(输出缩短了一点):
$ 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请求发送到其运行状况端点来确认这一点:
$ 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.云中的容器
云空间中的每个主要参与者都在向市场推出自己的托管产品,这些产品旨在支持容器的部署和编排,因此您只需丢下一个容器,魔术就可以发生。 让我们快速浏览一下它们。
亚马逊弹性容器服务
Amazon Elastic Container Service (或简称为Amazon ECS )是一种高度可扩展,快速的容器管理服务,可轻松在集群中运行,停止和管理Docker容器。 如您所料, Amazon ECS与Amazon Web Services产品组合中的许多其他云产品很好地集成在一起,包括:
- AWS身份和访问管理
- Amazon EC2自动扩展
- 弹性负载平衡
- Amazon Elastic Container注册
- AWS CloudFormation
Amazon ECS是一项区域服务,可在区域内的多个可用性区域中以高可用性的方式简化正在运行的应用程序容器。
Google Kubernetes引擎
Google Kubernetes Engine (以前称为Google Container Engine)是用于部署容器化应用程序的托管环境。 它带来了Google的独特经验和开发人员生产力,资源效率,自动化操作和开源灵活性方面的最新创新,从而加快了产品上市时间。
Google一直在容器中运行生产工作负载,并将他们学到的最好的知识整合到Kubernetes中 , Kubernetes是为Kubernetes Engine提供动力的行业领先的开源容器编排器。 它提供(但不限于)以下区别功能:
- 身份和访问管理
- 混合网络
- 安全与合规
- 集成日志记录和监控
- 自动缩放
- 自动升级
- 自动修理
- 资源限制
- 有状态的应用程序支持
- Docker映像支持
- 完全托管
- 专为容器打造的操作系统
- 私人集装箱登记处
- 快速一致的构建
- 开源可移植性
Azure容器服务
Azure容器服务 (AKS)管理托管的Kubernetes环境,无需容器编排专业知识,即可快速轻松地部署和管理容器化的应用程序。 它还通过按需配置,升级和扩展资源来消除正在进行的操作和维护的负担,而无需使应用程序脱机。
作为托管的Kubernetes服务, Azure容器服务提供:
- 自动化的Kubernetes版本升级和修补
- 易于集群扩展
- 自愈式托管控制平面(主机)
- 只为运行中的代理程序池节点付费
7.结论
在本教程的这一部分中,我们研究了许多领先的集群管理和编排解决方案,它们为容器化应用程序部署提供了全面的支持。 总的来说, Kubernetes在这里处于领先地位,但是每种选择都有其优点和缺点。
8.接下来
在本教程的最后部分中,我们将讨论持续集成实践中非常重要的主题,以及Docker如何适应其中的情况。
完整的配置和规范文件集可供下载 。
翻译自: https://www.javacodegeeks.com/2018/02/docker-java-developers-deploy-docker.html