在使用Ansible为EC2环境进行配置时,切换到不同的生产环境或者演示环境等的方法是怎样的?
在对EC2实例进行Ansible配置时,我们可以使用Ansible附带的ec2.py等动态清单工具来获取实例列表。下面是关于配置用于切换生产环境和预发布环境的清单的备忘录。
使用环境变量进行切换
可以通过环境变量AWS_PROFILE在ec2.py脚本中临时指定配置文件,从而切换Dynamic Inventory正在获取实例的AWS账户。
AWS_PROFILE=prod ansible-playbook -i ec2.py site.yml
在这种情况下,如果在ansible.cfg中指定了清单,则它在所有环境中都是通用的,因此不需要在命令行中指定。
# ansible.cfg
[defaults]
inventory = ec2.py
如果在实例上添加了像 Env=prod 这样的标签,ec2.py 将会创建以标签名和值为 tag_Env_prod 的组,因此可以在 group_vars/tag_Env_prod.yml 这样的文件中指定环境的固有变量(例如 ansible_ssh_common_args)。
# group_vars/tag_Env_prod.yml
ansible_ssh_common_args: -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
如果文件名为 group_vars/tag_Env_prod.yml,感觉有点不好,所以我们可以将其按照以下目录结构进行修改:
ansible.cfg
site.yml
roles/
...
group_vars/
# 環境ごとのグループ変数
prod.yml
stage.yml
dev.yml
# その他のグループ変数
ap.yml
web.yml
inventory/
ec2.py
ec2.ini
group.conf
在group.conf中,根据ec2.py创建与现有群组相似的群组。在前半部分,定义了多个空的群组,例如tag_Env_prod,这是必要的,因为如果在:children中指定的群组不存在,将会发出警告。
# inventory/group.conf
[tag_Env_prod]
[tag_Env_stage]
[tag_Env_dev]
[prod:children]
tag_Env_prod
[stage:children]
tag_Env_stage
[dev:children]
tag_Env_dev
[ap:children]
tag_Role_ap
[web:children]
tag_Role_web
在库存中指定目录。
# ansible.cfg
[defaults]
inventory = inventory/
您可以使用此方法来读取 group_vars/prod.yml 等文件。您也可以创建 vars.conf 等清单文件,并在其中编写环境名称的组变量。
# inventory/vars.conf
[prod:vars]
ansible_ssh_common_args = -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
[stage:vars]
ansible_ssh_common_args = -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
[dev:vars]
ansible_ssh_common_args = -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
但是,由于这种方法仅仅通过 AWS_PROFILE 环境变量来切换目标环境,所以如果要在一个 AWS 账户中分别建立不同的区域或 VPC 来构建多个环境就会很困难。
如果区域不同,可以使用 AWS_REGION 环境变量进行指定,但是为了操作特定的VPC实例或带有特定标签的实例,需要指定环境变量 EC2_INI_PATH,将 ec2.ini 文件分开。
我认为与其这样做,还不如直接在后面提到的库存目录进行切换,因此基本上不推荐使用这种方法。
在库存目录中切换
我们将按照以下的目录结构来安排。
ansible.cfg
site.yml
roles/
...
group_vars/
ap.yml
web.yml
envs/
prod/
ec2.py
ec2.ini
group.conf
vars.conf
group_vars/
all.yml
stage/
ec2.py
ec2.ini
group.conf
vars.conf
group_vars/
all.yml
dev/
ec2.py
ec2.ini
group.conf
vars.conf
group_vars/
all.yml
用ec2.ini文件指定配置文件或标签的筛选器。
# envs/${env}/ec2.ini
instance_filters = tag:Env=prod
boto_profile = prod
环境特有变量也可以以如下所示的清单格式写入vars.conf,
# envs/${env}/vars.conf
[all]
ansible_ssh_common_args = -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
可以将group_vars/all.yml作为组变量来写。
# envs/${env}/group_vars/all.yml
ansible_ssh_common_args: -o ProxyCommand='ssh -W %h:%p ore@192.0.2.123'
group.conf用于从类似于ec2.py的tag_Name_Value组中创建类似名称的组。
# envs/${env}/group.conf
[ap:children]
tag_Role_ap
[web:children]
tag_Role_web
在使用 Ansible 时,可以通过 -i 参数来指定清单目录进行执行。
ansible-playbook -i envs/prod/ site.yml
在中国是可以使用环境变量ANSIBLE_INVENTORY作为替代的选项。
ANSIBLE_INVENTORY=envs/prod/ ansible-playbook site.yml
这种方法与通过环境变量 AWS_PROFILE 切换的方法相比,ec2.ini 可以根据每个环境进行编写,因此自由度更高。但是,ec2.py 等在多个目录中散布相同内容的情况有点令人不舒服。