発端
awsでサーバ構築に使用する用途にansibleを作成中、いちいちインスタンス建てたり落としたりがめんどくさくなった
vagrant localに建ててそこに流そう
ansible 2.6.2
構成
詳細は公式ドキュメント
.
├── Vagrantfile
├── ansible.cfg
├── inventory
│ └── dev
│ ├── group_vars
│ │ ├── any-group1
│ │ └── any-group2
│ └── hosts.yml
├── playbook
│ ├── any-group1.yml
│ └── any-group2.yml
├── roles
│ └── any-role
└── ssh_config
any-group1がapplicationサーバ、any-group2がミドル用のサーバといった感じ
$ cat ansible.cfg
[defaults]
hash_behaviour = merge
[ssh_connection]
ssh_args = -F ssh_config
scp_if_ssh = True
ssh_config
には実際に流すリモートのホスト情報が入っている
$ cat inventory/dev/group_vars/any-group1
owner: "me"
group: "me"
public: "any-group1"
$ cat inventory/dev/group_vars/any-group2
middle: "any-group2"
この変数の差分が今回の核心
vagrantに流す用のinventoryを用意した
構成
.
├── Vagrantfile
├── ansible.cfg
├── inventory
│ ├── check
│ │ ├── group_vars -> ../dev/group_vars
│ │ └── hosts.yml
│ └── dev
│ ├── group_vars
│ │ ├── any-group1
│ │ └── any-group2
│ └── hosts.yml
├── playbook
│ ├── any-group1.yml
│ └── any-group2.yml
├── roles
│ └── any-role
├── ssh_config
└── ssh_config.vagrant
vagrant ssh-config
をそのまま入れただけの ssh_config.vagrant
$ cat ssh_config.vagrant
Host default
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile <鍵>
IdentitiesOnly yes
LogLevel FATAL
$ cat inventory/check/hosts.yml
---
any-group1: &check
hosts:
default:
any-group2: *check
同一ホストを別グループに指定している(今回の核心2)
結果(失敗した、片方だけ)
ansible-playbook -i inventory/check playbook/any-group1.yml --ssh-common-args='-F ssh_config.vagrant'
ansible-playbook -i inventory/check playbook/any-group2.yml --ssh-common-args='-F ssh_config.vagrant'
any-group1のほうは成功、よしよしと思いながらany-group2を実行すると失敗した
エラーログは取り忘れたけれど内容はディレクトリのグループに存在しないグループをしているぞと言ってた
該当部分は以下の部分で、どちらのグループでも実行されるタスクだった。
- name: Setting directory permission
file:
path: /etc/middle
owner: middle
group: "{{ group | default('root') }}"
mode: 02575
state: directory
なにが起きた?
いろいろと調査してると ansible-inventory
というのを見つけた
インベントリの設定内容を出してくれるということだったので早速ためす
$ ansible-inventory -i inventory/dev --list
{
"_meta": {
"hostvars": {
"any-dev-group1": {
"owner": "me",
"group": "me",
"public": "any-group1"
},
"any-dev-group2": {
"middle": "any-group2"
}
}
},
"all": {
"children": [
"any-group1",
"any-group2",
"ungrouped"
]
},
"any-group1": {
"hosts": [
"any-dev-group1"
]
},
"any-group2": {
"hosts": [
"any-dev-group1"
]
},
"ungrouped": {}
}
$ ansible-inventory -i inventory/check --list
{
"_meta": {
"hostvars": {
"default": {
"owner": "me",
"group": "me",
"middle": "any-group2",
"public": "any-group1"
}
}
},
"all": {
"children": [
"any-group1",
"any-group2",
"ungrouped"
]
},
"any-group1": {
"hosts": [
"default"
]
},
"any-group2": {
"hosts": [
"default"
]
},
"ungrouped": {}
}
注目すべきは
$ ansible-inventory -i inventory/dev --list | jq ._meta.hostvars
"any-dev-group1": {
"owner": "me",
"group": "me",
"public": "any-group1"
},
"any-dev-group2": {
"middle": "any-group2"
}
$ ansible-inventory -i inventory/check --list | jq ._meta.hostvars
"default": {
"owner": "me",
"group": "me",
"middle": "any-group2",
"public": "any-group1"
}
groupが別でも同一ホストだとvarsがマージされるよう
group_varsとして持つんじゃなくて、group_varsをもとにそれぞれのhostごとのhost_varsを持つ感じなのか
とにかくそのために、any-group2でも変数 group
が定義されてしまい、前記のタスク部分でデフォルトが効かず、存在しないグループを指定してしまっていた。
解決
$ cat ssh_config.vagrant
Host any-check-group1
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile <鍵>
IdentitiesOnly yes
LogLevel FATAL
Host any-check-group2
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile <鍵>
IdentitiesOnly yes
LogLevel FATAL
$ cat inventory/check/hosts.yml
---
any-group1:
hosts:
any-check-group1:
any-group2:
hosts:
any-check-group2:
とりあえずホストの設定を別々にして対応した
$ ansible-inventory -i inventory/check --list | jq ._meta.hostvars
"any-check-group1": {
"owner": "me",
"group": "me",
"public": "any-group1"
},
"any-check-group2": {
"middle": "any-group2"
}
期待通りhost_varsが別れて、ansible-playbookも成功した