Docker Stack 部署应用
概述
单机模式下,可以使用 Docker Compose 来编排多个服务。Docker Swarm 只能实现对单个服务的简单部署。而Docker Stack 只需对已有的 docker-compose.yml 配置文件稍加改造就可以完成 Docker 集群环境下的多服务编排。
stack是一组共享依赖,可以被编排并具备扩展能力的关联service。
Docker Stack和Docker Compose区别
- Docker stack会忽略了“构建”指令,无法使用stack命令构建新镜像,它是需要镜像是预先已经构建好的。 所以docker-compose更适合于开发场景;
- Docker Compose是一个Python项目,在内部,它使用Docker API规范来操作容器。所以需要安装Docker -compose,以便与Docker一起在您的计算机上使用;Docker Stack功能包含在Docker引擎中。你不需要安装额外的包来使用它,docker stacks 只是swarm mode的一部分。
- Docker stack不支持基于第2版写的docker-compose.yml ,也就是version版本至少为3。然而Docker Compose对版本为2和3的 文件仍然可以处理;
- docker stack把docker compose的所有工作都做完了,因此docker stack将占主导地位。同时,对于大多数用户来说,切换到使用
- 单机模式(Docker Compose)是一台主机上运行多个容器,每个容器单独提供服务;集群模式(swarm + stack)是多台机器组成一个集群,多个容器一起提供同一个服务;
compose.yml deploy 配置说明
docker-compose.yaml文件中deplo参数下的各种配置主要对应了swarm中的运维需求。
docker stack deploy不支持的参数:
(这些参数,就算yaml中包含,在stack的时候也会被忽略,当然也可以为了docker-compose up
留着这些配置)
build
cgroup_parent
container_name
devices
tmpfs
external_links
links
network_mode
restart
security_opt
userns_mode
deploy:指定与服务的部署和运行有关的配置。注:只在 swarm 模式和 stack 部署下才会有用。且仅支持 V3.4 及更高版本。
可以选参数:
endpoint_mode:访问集群服务的方式。3.2版本开始引入的配置。用于指定服务发现,以方便外部的客户端连接到swarm
- vip:默认的方案。即通过 Docker 集群服务一个对外的虚拟 ip对外暴露服务,所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器,客户端无法察觉有多少个节点提供服务,也不知道实际提供服务的IP和端口。
- dnsrr:DNS的轮询调度。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。客户端访问的时候,Docker集群会通过DNS列表返回对应的服务一系列IP地址,客户连接其中的一个。这种方式通常用于使用自己的负载均衡器,或者window和linux的混合应用。
- labels:在服务上设置标签,并非附加在service中的容器上。如果在容器上设置标签,则在
deploy
之外定义labels。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下的 labels。 mode:用于指定是以副本模式(默认)启动还是全局模式
- replicated:副本模式,复制指定服务到集群的机器上。默认。
- global:全局模式,服务将部署至集群的每个节点。类似于k8s中的DaemonSet,会在每个节点上启动且只启动一个服务。
- replicas:用于指定副本数,只有mode为副本模式的时候生效。
placement:主要用于指定
约束
和偏好
。这个参数在运维的时候尤为关键constraints(约束):表示服务可以部署在符合约束条件的节点上,包含了:
node attribute matches example node.id 节点id node.id == 2ivku8v2gvtg4 node.hostname 节点主机名 node.hostname != node-2 node.role 节点角色 (manager/worker) node.role == manager node.platform.os 节点操作系统 node.platform.os == windows node.platform.arch 节点架构 node.platform.arch == x86_64 node.labels 用户定义的labels node.labels.security == high engine.labels Docker 引擎的 labels engine.labels.operatingsystem == ubuntu-14.04 - preferences(偏好):表示服务可以均匀分布在指定的标签下。
- preferences 只有一个参数,就是spread,其参数值为节点的属性,即约束表中的内容
例如:
node.labels.zone
这个标签在集群中有三个值,分别为west、east、north,那么服务中的副本将会等分为三份,分布到带有三个标签的节点上。 - max_replicas_per_node:3.8版本中开始引入的配置。控制每个节点上最多的副本数。
注意:当 最大副本数*集群中可部署服务的节点数<副本数,会报错
resources:用于限制服务的资源,这个参数在运维的时候尤为关键。
示例:配置 redis 集群运行需要的 cpu 的百分比 和 内存的占用。避免占用资源过高出现异常。
limit:用于限制最大的资源使用数量
- cpus:cpu占比,值的格式为百分比的小数格式
- memory:内存的大小。示例:512M
reservation:为最低的资源占用量。
- cpus
- memory
restart_policy:容器的重启策略
- condition:重启的条件。可选 none,on-failure 或者 any。默认值:any
- delay:尝试重启的时间间隔(默认值:5s)。
- max_attempts:最大尝试重启容器的次数,超出次数,则不再尝试(默认值:一直重试)。
- window:判断重启是否成功之前的等待时间(一个总的时间,如果超过这个时间还没有成功,则不再重启)。
- rollback_config:更新失败时的回滚服务的策略。3.7版本加入。和升级策略相关参数基本一致。
update_config:配置应如何更新服务,对于配置滚动更新很有用。
- parallelism:同时升级[回滚]的容器数
- delay:升级[回滚]一组容器的时间间隔
- failure_action:若更新[回滚]失败之后的策略:continue、 pause、rollback(仅在update_config中有) 。默认 pause
- monitor:容器升级[回滚]之后,检测失败的时间检测 (支持的单位:ns|us|ms|s|m|h)。默认为 5s
- max_failure_ratio:最大失败率
- order:升级[回滚]期间的操作顺序。可选:stop-first(串行回滚,先停止旧的)、start-first(并行回滚,先启动新的)。默认 stop-first 。注意:只支持v3.4及更高版本
compose.yml 文件示例
version: "3" # 版本号,deploy功能是3版本及以上才有的
services: # 服务,每个服务对应配置相同的一个或者多个docker容器
redis: # 服务名,自取
image: redis:alpine # 创建该服务所基于的镜像。使用stack部署,只能基于镜像
ports: # 容器内外的端口映射情况
- "1883:1883"
- "9001:9001"
networks: # 替代了命令行模式的--link选项
- fiware
volumes: # 容器内外数据传输的对应地址
- "/srv/mqtt/config:/mqtt/config:ro"
- "/srv/mqtt/log:/mqtt/log"
- "/srv/mqtt/data/:/mqtt/data/"
command: -dbhost stack_mongo # 命令行模式中跟在最后的参数,此条没有固定的格式,建议参照所部署的docker镜像的说明文档来确定是否需要该项、需要写什么
deploy:
mode: replicated
replicas: 6 # replicas模式, 副本数目为1
endpoint_mode: vip
labels:
description: "This redis service label"
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- "node.role==worker" # 部署位置,只在工作节点部署
- "engine.labels.operatingsystem==ubuntu 18.04"
preferences:
- spread: node.labels.zone
update_config:
parallelism: 2
delay: 10s
order: stop-first
networks: # 定义部署该项目所需要的网络
fiware:
stack 常用命令
docker stack:编排部署应用
# 部署一个新的stack(堆栈)或更新现有的stack。别名:deploy, up
docker stack deploy [OPTIONS] 自定义STACK名称
# 选项:
-c, --compose-file strings # Compose文件的路径,或从标准输入中读取的“-”
--prune # 表示削减不再引用的服务。可以把一些down掉的service进行自动清理。
--orchestrator string # 指定编排模式 (swarm|kubernetes|all)
--resolve-image string # 请求仓库来重新解析镜像的摘要和支持的平台。("always"|"changed"|"never") (默认 "always")
--with-registry-auth # 发送仓库的授权详情到Swarm代理
--orchestrator # 使用的容器编排服务
# 通过compose.yml文件指令部署
docker stack deploy -c 文件名.yml 自定义STACK名称
# 列出现有堆栈。别名:ls, list
docker stack ls [OPTIONS]
# 列出堆栈中的任务
docker stack ps [OPTIONS] STACK
# 选项:
--no-trunc # 输出完整信息
# 删除一个或多个堆栈。别名:rm, remove, down
docker stack rm [OPTIONS] STACK [STACK...]
# 选项
--orchestrator string # 指定适配器 (swarm|kubernetes|all)
# 列出堆栈中的服务
docker stack services [OPTIONS] STACK
搭建Docker私有仓库--自签名方式
为了能集中管理创建好的镜像,方便部署服务,可以部署私有的Docker仓库。Docker为了确保安全使用TLS,需要CA认证,可以使用自签名方式。
准备环境
环境:两台Centos 7 虚拟机
- 服务器IP:10.57.220.244 ,作为Docker仓库使用
- 客户端IP:10.57.220.220 ,作为客户端来上传或拉取镜像
- 域名:harbor.paic.com.cn(修改所有主机的 /etc/hosts 文件,添加域名和ip的对应, 格式:ip 域名)
两台机器上均已安装好Docker 版本为 17.03.0-ce
生成自签名证书
在服务器主机上生成自签名证书,创建一个文件夹用于存放证书
mkdir -p certs
# 生成自签名证书
openssl req -newkey rsa:4096 -nodes -sha256 -x509 -days 1825 -keyout `pwd`/certs/harbor.key -out `pwd`/certs/harbor.crt -config openssl_req.cnf
openssl_req.cnf
# 定义输入用户信息选项的"特征名称"字段名,该扩展字段定义了多项用户信息。
distinguished_name = req_distinguished_name
# 如果设为no,那么 req 指令将直接从配置文件中读取证书字段的信息,而不提示用户输入。
prompt = no
[req_distinguished_name]
#国家代码,一般都是CN(大写)
C = CN
#省份
ST = []
#城市
L = City
#企业/单位名称
O = YZT
#企业部门
OU = []
#证书的主域名。注意要和仓库的域名一致
CN = harbor.paic.com.cn
分发自签名证书、指定私有仓库位置
把生成的的 harbor.crt 复制到服务器端和客户端上的 /etc/pki/ca-trust/source/anchors 目录下
\cp ./certs/harbor.crt /etc/pki/ca-trust/source/anchors
指定私有仓库地址。
vi /etc/docker/daemon.json
------------------------------------------------------------------------
{
"insecure-registries": ["harbor.paic.com.cn"]
}
------------------------------------------------------------------------
# 注意:若仓库的容器的5000端口不是绑定到宿主机的443端口上,则需要指定绑定的宿主机端口
{
"insecure-registries": ["harbor.paic.com.cn:5000"]
}
更新证书,然后重新启动docker
update-ca-trust;systemctl restart docker
启动容器
运行仓库镜像,如果本地没有相应的镜像会从Docker服务器上下载,然后才启动,可以用docker ps命令查看是否已经有窗口在运行。
docker run -d -p 443:5000 \
--restart=always \
--name registry_https \
-v `pwd`/dockerregister:/var/lib/registry \
-v `pwd`/certs:/home/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/home/certs/harbor.crt \
-e REGISTRY_HTTP_TLS_KEY=/home/certs/harbor.key \
registry
# 说明:
# -p 443:5000 :将仓库的容器的5000端口绑定到宿主机443端口上。
# 因docker访问镜像仓库地址的默认端口号为443,
# 若仓库的容器的5000端口不绑定到宿主机的443端口上,则push/pull时需指定绑定的宿主机端口
# 若仓库的容器的5000端口不绑定到宿主机的443端口上,又不想push/pull时指定绑定的宿主机端口,可以使用ngnix进行端口映射
# -v `pwd`/dockerregister:/var/lib/registry :指定宿主机的目录保存上传好的docker镜像
# -v `pwd`/certs:/home/certs :挂载自签名证书目录
查看容器是否启动成功
# docker ps | grep 容器名
docker ps | grep registry_https
验证:
# 使用curl查看一下仓库的镜像列表。
curl -XGET https://harbor.paic.com.cn:443/v2/_catalog
# {"repositories":[]}
# 使用curl查看一下仓库中某镜像的版本。
curl https://harbor.paic.com.cn:443/v2/redis/tags/list
push/pull 镜像
注意:若仓库的容器的5000端口不是绑定到宿主机的443端口上,则需要指定绑定的宿主机端口
# 打tag
docker tag redis harbor.paic.com.cn/redis
# 指定端口号 示例:
# docker tag redis harbor.paic.com.cn:5000/redis
# push镜像
docker push harbor.paic.com.cn/redis
# pull镜像
docker pull harbor.paic.com.cn/redis