【Ansible】備忘録【環境構築】
こんばんは、マークアップエンジニアの でございます。
最近なぜかVagrantとAnsibleを使って開発環境を作る事が多いです。
その為Ansibleで困ったときの備忘録。
- 他の人の環境で動かない(Installing Ansible...で止まってしまう)
- 環境変数が存在する状態で実行させたい。
- .bashrcを読み込んでほしい。
- 変数をごにょごにょにしたい。
- playbookの一部を暗号化したい。
- tasks/main.ymlが長い。
- tasksを途中から実行したい。デバッグしたい。
- blockinfileで`{`を文字列リテラルとして扱いたい
他人の環境で動かない。(Installing Ansible...で止まってしまう)
The Ansible software could not be found! Please verify
とかでて止まっちゃう。
これはVagrantの問題じゃないかなと思います。
Vagrantfileに下記を記述して解決
config.vm.provision :shell, inline: <<SCRIPT GALAXY=/usr/local/bin/ansible-galaxy echo '#!/usr/bin/env python2 import sys import os args = sys.argv if args[1:] == ["--help"]: args.insert(1, "info") os.execv("/usr/bin/ansible-galaxy", args) ' | sudo tee $GALAXY sudo chmod 0755 $GALAXY SCRIPT
参考: https://github.com/mitchellh/vagrant/issues/6793
環境変数が存在する状態で実行させたい。
MySQLとかでSQL実行させたい時、「MySQL-python」や「python-mysqldb」が入っている環境ならmysql_user moduleを使えば良いと思いますが
いれれない場合、新しいMySQLだとpasswordを引数に渡して実行
- shell: "mysql -u root -ppassword hoge < test.sql"
を実行する時に警告が発生しちゃったりします。
そのため、環境変数からパスワードをいれてあげましょう。
- shell: "mysql -u root hoge < test.sql" environment: MYSQL_PWD: "password"
environmentで渡す事ができます。
参考: http://docs.ansible.com/ansible/playbooks_environment.html
.bashrcを読み込んでほしい。
become_userを使ってユーザーが切り替えて作業している時に
.bashrcにはPATHを追記したけど、shellモジュールで.bashrcの内容を読み込んでくれない時に
- shell: "forever start test.js"
とか実行しても「foreverなんてないよ!」となる場合があります。
- shell: "/bin/bash -lc \"forever start test.js\""
もはやAnsible関係ないけど/bin/bashのオプションに「-l」をつけて「.bashrc」を読み込んだ状態で実行させます。
変数をごにょごにょにしたい。
例えば、PHPのバージョンを変数に保持してるけど
5.6以上か判定したいとき
- shell: "[ $(echo {{ php_version }} | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1\2/') -ge 56 ] && echo '1' || echo '0'" register: 56over
わざわざregisterに保存しなければいけないところとか非常にめんどくさい。
jinja2 filterが非常に便利です。
- shell: "echo '56over!!!!!'" when: {{ php_version | version_compare('5.6', operator='ge', strict=False) }}
こんな感じで変数に制御を行う事ができます。
他にも、大文字の文字列を取得したい場合は
- debug: var={{ lower_str | upper }}
これで変数lower_strに入っている小文字の英語が大文字に変更されて出力されます。
参考: http://docs.ansible.com/ansible/playbooks_filters.html
playbookの一部を暗号化したい。
例えば、
playbookのhost_vars/db_serverに下記の内容がある。
host_vars/db_server
mysql: host: localhost user: hogehoge password: hogehoge
- サーバー上に置いてサーバーから実行したい。
- 他人に見られたくない。
そんな時、ansible-vaultが便利です。
$ echo 'ここ暗号化パスワード' > ~/.vault_password $ ansible-vault decrypt host_vars/db_server.yml --vault-password-file=~/.vault_password
こんな感じでplaybookの一部を暗号化する事ができます。
また、editで複合して編集も可能です。
$ ansible-vault edit host_vars/db_server.yml --vault-password-file=~/.vault_password
playbookを実行するときも「--vault-password-file」でファイル指定か「--ask-vault-pass」でパスワードを対話式にもできます。
tasks/main.ymlが長い。
includeでファイルを分割、blockみたいにwhenやwith_items等もincludeに指定してしまえば一括管理も簡単です。
2018/01/09
include_taskが追加されましたのでinclude_taskを利用すると良いと思います。
roles/php/task/main.yml
- name: php make install include_task: php_make_install.yml when: {{ php_make_install }} - name: php remi install include_task: php_remi_install.yml when: {{ php_make_install == false }} - name: php config setting include_task: php_config_setting.yml - name: install composer xdebug other include_task: php_other_install.yml
参考:
https://docs.ansible.com/ansible/2.4/include_tasks_module.html
tasksを途中から実行したい。デバッグしたい。
Ansibleのstart-at-taskオプションstepオプションを使う事で解決できます。
start-at-task | 特定のタスクから実行する事ができます。 |
step | タスク実行毎にどうする?って聞いてくれます。 |
特定のタスクはnameを各タスク毎に振っていればそれがタスク名になります。
$ ansible-playbook -i hosts site.yml --start-at-task="Run from this task" --step
ベストプラクティクスに沿って作成してある場合は、「ロール名 : タスク名」みたいな感じで
半角スペースを両サイドにおいた「:」でロール名とタスク名を区切る事で「特定のロール」の「特定のタスク」から始めることができます。
その為、mysqldロールのnameにRun from this taskと付与してあるタスクから始めたい場合は下記のような指定でできます。
$ ansible-playbook -i hosts site.yml --start-at-task="mysqld : Run from this task" --step
blockinfileで`{`を文字列リテラルとして扱いたい
- name: 上書き可能な変数を定義 blockinfile: dest: "{{ httpd.sysconfig.path }}" marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.key }}" content: | if [ \"$\{{{ item.key }}\}x\" = \"x\" ];then export {{ item.key }}=\"{{ item.value }}\" fi with_dict: "{{ httpd.sysconfig.overridable_params }}"
こうすると`if [ \"$\{{{ item.key }}\}x\" = \"x\" ];then`の`\{{{ item.key }}\}`のおかげで
fatal: [node_1]: FAILED! => { "msg": "Unexpected failure during module execution.", "stdout": "" }
この様にエラーが発生するのでこの様にして解決しました。
- name: 上書き可能な変数を定義 blockinfile: dest: "{{ httpd.sysconfig.path }}" marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.key }}" content: | if [ "${{ '{' }}{{ item.key }}{{ '}' }}x" = "x" ];then export {{ item.key }}="{{ item.value }}" fi with_dict: "{{ httpd.sysconfig.overridable_params }}"
{{ 'ここが文字列リテラルとして扱われる' }}