问题描述
正在编写一个Ansible playbook,用于在集群环境中部署服务。有3种类型的主机(应用程序、负载均衡器、数据库)。服务是通过docker-compose在每个主机上分别部署的。
以下是部署到数据库主机的playbook示例:
- name: Deploy database node.
hosts: databases
become: yes
become_method: sudo
roles:
- common
- zabbix-agent
- database
- backup
Ansible play需要根据在主机上调用的角色动态生成一个docker-compose文件。因此,这个示例需要生成一个列出这些角色的docker-compose文件。
如何根据已调用的角色自动生成一个docker-compose.yml文件?
我已经考虑过:
– Ansible facts
– Tags
– 全局布尔变量 [yuck],但是我觉得这些都不是正确的方法。
如果有更好的方法来实现我的目标,我也愿意听取任何其他建议。
编辑:
你能解释一下容器里面有什么吗?
‘common’角色当前在目标主机上安装Docker和docker-compose。
‘database’启动一个mariadb容器。
‘zabbix-agent’在主机上安装zabbix agent。
‘backup’复制一些shell脚本。
数据库是在容器中还是与数据库并行运行的容器?
数据库是一个mariadb Docker容器。因此,我的compose文件将需要包含一个’mariadb’部分。
对于你来说,一个好的docker-compose.yml文件应该是什么样子的?
好问题。像这样:
version: '2.2'
services:
terracotta:
image: terracotta/terracotta-server-oss:5.5.1
container_name: terracotta
restart: always
networks:
- skyNet
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
mariadb:
image: mariadb/server:{{docker_mariadb_version}}
container_name: mariadb
restart: always
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
networks:
- skyNet
ports:
- 127.0.0.1:3306:3306/tcp
volumes:
- /opt/mariadb/data:/var/lib/mysql
environment:
MARIADB_ROOT_PASSWORD: "{{database_root_password}}"
# Network
networks:
skyNet:
driver: bridge
我需要能够通过标签或其他方式切换将哪些服务添加到compose文件中。也许我应该改变我的问题的措辞?
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
根据你的问题描述,你不需要动态生成docker-compose.yml文件。你已经在一个明确的网络上部署了东西;只需将其作为单独的compose文件外部化即可。也就是说,执行以下等效操作:
docker network create skyNet
然后修改你的compose配置文件,将其作为外部网络引用:
services:
mariadb:
image: mariadb/server:{{docker_mariadb_version}}
container_name: mariadb
restart: always
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
networks:
- skyNet
ports:
- 127.0.0.1:3306:3306/tcp
volumes:
- /opt/mariadb/data:/var/lib/mysql
environment:
MARIADB_ROOT_PASSWORD: "{{database_root_password}}"
networks:
skyNet:
external: true
你可以让每个角色管理自己的docker-compose.yaml文件(并负责启动堆栈)。因为它们共享一个网络,即使它们在不同的文件中定义,名称查找也会按预期工作。
方案2
使用脚本或工具来管理容器的启动顺序可能会增加复杂性,并且需要确保容器A和容器B之间的依赖关系正确设置。
另一种方法是编写脚本或使用工具来控制容器的运行顺序。你可以使用docker run
命令来手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。
示例:
以下是一个简单的bash脚本示例,可以在容器A启动后启动容器B:
#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b
在这个示例中,我们首先使用docker run
命令启动容器A,并将其命名为container_a
。然后,使用一个循环来等待容器A完全启动(这里是通过在容器内运行echo
命令来测试)。一旦容器A就绪,我们再使用docker run
命令启动容器B,并将其命名为container_b
。