概念
节点
运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。
节点分为管理 (manager) 节点和工作 (worker) 节点。
docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。
一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现。
工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。
服务和任务
Task 是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。
Service 是指一组 Task 的集合,Service 定义了任务的属性。服务有两种模式:
1)replicated services 按照一定规则在各个工作节点上运行指定个数的任务。
2)global services 每个工作节点上运行一个任务
两种模式通过 docker service create 的 –mode 参数指定。
常用命令
docker swarm init --advertise-addr <MANAGER-IP> #在管理节点初始化一个 Swarm 集群 docker node ls #查看集群 docker node rm iue #移除指定节点 docker service ls #查看当前 Swarm 集群运行的服务 docker service ps nginx #查看nginx服务的详情(加 --no-trunc 可显示全error信息等字段) docker service logs -f nginx #查看nginx服务的日志 docker service rm nginx #从Swarm集群移除nginx服务 docker service update --update-parallelism 1 --update-delay 10s falstorm_fallogstash #更新服务 docker service inspect 8se docker swarm join-token [OPTIONS] (worker|manager) #显示join token docker swarm join-token manager #显示manager join token docker swarm leave #在worker节点上执行此命令,此worker从swarm中移除 docker swarm join --token SWMTKN-1-2maijudaypf5cg1y7cmo7yzt5cpapjfbc96bj5mxeogmjyuf1y-avqwv24g0pw7odenasc4jehu7 192.168.1.188:2377 docker stack ls docker stack rm test # swarm 中重启 kafka 容器(不能用 restart,否则会导致相同的容器多出来一个) docker stop $(docker container ls | grep 'kafka' | awk '{print $1}')
使用 compose 文件
使用 docker service create 一次只能部署一个服务,使用 docker-compose.yml 我们可以一次启动多个关联的服务。
经测试,如果手工删除了 volumn 映射的目录,重启 swarm 的 service 是不会成功的,需要先重启docker才行,如:service docker restart
。
这里,我仅贴出一些工作中用到的compose.yml文件供参考。出于保密这些文件仅对一些敏感字眼作了修改。
falpolicy-compose.yml
version: '3.6' services: falpolicy: image: 192.168.1.166:8083/centos7-jdk8-tomcat8-tools-falpos volumes: - "falhome:/falhome" ports: - "8080:8080" - "8443:8443" - "2331:2331" networks: - falnet depends_on: - falmongo - falsolr deploy: placement: constraints: - node.role == manager falsolr: image: 192.168.1.166:8083/solr-falsec volumes: - "solr_home:/solr_home" expose: - "8983" ports: - "8983:8983" depends_on: - falmongo networks: - falnet deploy: placement: constraints: - node.role == manager falmongo: image: 192.168.1.166:8083/mongo-falsec volumes: - "mongo-data:/data/db" - "mongo-config:/data/configdb" ports: - "27017:27017" networks: - falnet deploy: placement: constraints: - node.role == manager falinfluxdb: image: 192.168.1.166:8083/influxdb-falsec volumes: - "influxdb:/var/lib/influxdb" ports: - "8086:8086" networks: - falnet deploy: placement: constraints: - node.role == manager volumes: mongo-data: mongo-config: solr_home: falhome: influxdb: networks: falnet: driver: overlay attachable: true
falstorm-compose.yml
version: '3.6' services: falzookeeper: image: 192.168.1.166:8083/zookeeper-falsec volumes: - "zoodata:/data" - "zoodatalog:/datalog" - "zoologs:/logs" networks: - falnet deploy: placement: constraints: - node.role == worker falkafka: image: 192.168.1.166:8083/kafka-falsec volumes: - "kafka:/kafka" depends_on: - falzookeeper networks: - falnet ports: - "9092:9092" deploy: placement: constraints: - node.role == worker fallogstash: image: 192.168.1.166:8083/logstash-falsec volumes: - "logstash:/logstash" depends_on: - falzookeeper - falkafka networks: - logstash # environment: #default is 127.0.0.1 # KAFKA_SERVER: "127.0.0.1" # KAFKA_PORT: "9092" deploy: placement: constraints: - node.role == worker falstorm: image: 192.168.1.166:8083/storm-falsec volumes: - "storm-data:/data" - "storm-logs:/logs" # - "storm-falhome:/falhome" depends_on: - falzookeeper - falinfluxdb - falkafka - fallogstash - falmongo networks: - falnet # command: storm jar /falhome/topology/falstorm-log.jar com.falsec.storm.FalStormLogApplication deploy: placement: constraints: - node.role == worker volumes: influxdb: zoodata: zoodatalog: zoologs: kafka: logstash: storm-data: storm-logs: networks: falnet: external: true name: falpolicy_falnet #need to expose the 514 port directly on the host #otherwise the source ip will be docker bridge ip logstash: external: true name: host
- external :If set to
true
, specifies that this volume has been created outside of Compose.docker-compose up
does not attempt to create it, and raises an error if it doesn’t exist.
docker stack deploy 尝试 pull 镜像导致一起起不来
现象:容器起不来,查看日志没有输出任何日志。
overlay 网络
介绍
overlay 网络驱动程序在多个 Docker 守护进程主机之间创建一个分布式网络。这个网络在允许容器连接并进行安全通信的主机专用网络之上(overlay 覆盖在上面)。Docker 透明地处理每个 Docker 守护进程与目标容器之间的数据包的路由。
我们可以将 swarm 服务和独立容器连接到同一个 overlay 网络。当初始化swarm集群或将一个Docker主机加入已经存在的swarm集群时,Docker主机上会创建两个新网络:
- 一个称为 ingress 的 overlay 网络,用来处理与 swarm 服务相关的控制和数据流。当创建的 swarm 服务没有连接到用户自定义的 overlay 网络时,这个服务会默认连接到 ingress 网络。
- 一个称为 docker_gwbridge 的bridge 网络,用来将单个的 Docker 守护进程连接到 swarm 中的其他守护进程。
连接到同一 overlay 网络的 swarm 服务可以有效地将所有端口暴露给对方。要使端口可以在服务之外访问,必须在 Surround with spaces
或 docker service update
命令中使用 -p 标志发布该端口,如 -p 8080:80。
要创建可以用于 swarm 服务和独立容器跟其他 Docker 守护进程中运行的独立容器通信的 overlay 网络,需要添加 –attachable 标志docker network create -d overlay --attachable my-attachable-overlay
防火墙端口开放
当我们使用swarm overlay网络在多台服务器上部署service,如果服务器启用了防火墙(firewalld、iptables等),那么需要开启下面几个端口才能访问overlay网络上的每个主机:
- TCP 端口 2377:用于集群管理通信
- TCP 和 UDP 端口 7946:用于节点之间通信
- UDP 端口 4789:overlay 网络流量
以firewalld为例,开放端口命令如下
sudo firewall-cmd --zone=public --add-port=2377/tcp --permanent sudo firewall-cmd --zone=public --add-port=7946/tcp --permanent sudo firewall-cmd --zone=public --add-port=7946/udp --permanent sudo firewall-cmd --zone=public --add-port=4789/udp --permanent sudo firewall-cmd --reload
部署伸缩
当业务处于高峰期时,我们需要扩展服务运行的容器数量。
docker service scale nginx=5
当业务平稳时,我们需要减少服务运行的容器数量。
docker service scale nginx=2
实践
Allow HTTP connection to falnas private docker registry
- Turn off https for docker
Edit the “daemon.json” file, whose default location is /etc/docker/daemon.json on Linux or C:\ProgramData\docker\config\daemon.json on Windows Server.
{ "insecure-registries" : ["192.168.1.166:8083"] }
- Restart Docker for the changes to take effect.
systemctl restart docker
Docker login to 192.168.1.166:8083
#用户名docker 密码china.123 docker login http://192.168.1.166:8083
Create docker swarm
docker swarm init --advertise-addr <MANAGER-IP>
如果要将其他机器上的worker节点加入进来,可以在那台机器上执行此命令:docker swarm join --token SWMTKN-1-2maijudaypf5cg1y7cmo7yzt5cpapjfbc96bj5mxeogmjyuf1y-avqwv24g0pw7odenasc4jehu7 192.168.1.200:2377
注意:必须开放相关防火墙端口,开发时可以先禁用 firewalld,否则会报错:Error while dialing dial tcp xxx.xxx.xxx.xxx: connect: no route to host。一切顺利的话,执行 docker node ls
查看新加入的node节点的STATUS为”Ready”并且MANAGER STATUS为空,不能是Reachable,说明可以使用了。
参考文档:https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm
Run the following compose file
docker stack deploy -c /home/admin/dev/compose/test-compose.yml --with-registry-auth falpolicy docker stack deploy -c /home/admin/dev/compose/falstorm-compose.yml --with-registry-auth falstorm
注:使用 –with-registry-auth 需要先 “docker login http://192.168.1.166:8083”。
如果修改了 falstorm-compose.yml,目前是先执行docker stack rm falstorm,再重启部署的。
运维人员在客户现场部署时,需要将application.properites文件中127.0.0.1地址改为服务器地址,以便外部服务器可以访问,文件位于/var/lib/docker/volumes/falpolicy_falhome/_data/falpolicy/config/application.properties
,然后修改falpolicy.server.access.host
键的值为 host 主机的IP即可。