ansibleの勉強シリーズ第4回です。
今回は「これは大体みんなハマるだろうなあ」という部分の解決策についてです。
- パッケージのグループインストールしたいんですけど?
- CentOS7でファイヤーウォール止めたいんだけど?
- apacheインストール時にバージョン指定したいんですけど?
- gitモジュール使ってみたらエラー起きたんですけど?
- rbenvのパスと初期化コマンドが・・・
- bundlerは .rbenv 配下にインストールしたいんですけど?
- rbenvで指定したrubyが既にインストール済みか調べたいんですけど?
- ↑こうやったら「rbenv: command not found」って言われた!!
- gemでインストールする時 .rbenv 配下にインストールしたいんだけど?
- subversionでcheckout済みかどうか調べたいんだけど?
- registerした値をechoして確認したいんですけど?
- sudoersを編集してsudoできるようにしたいんだけど?
- sshするユーザをplaybook毎に変えたいんだけど?
- 雑感
パッケージのグループインストールしたいんですけど?
- name: install 'Development tools' package group yum: name="@Development tools" state=present sudo: yes
yum - Manages packages with the yum package manager — Ansible Documentation
「@」つけるとグループインストールになるんだよ!間にスペースが入るパッケージ名の時はちゃんとクォートで囲もうね!
CentOS7でファイヤーウォール止めたいんだけど?
- name: stop firewalld service: name=firewalld enabled=false state=stopped sudo: yes
こう書くと「service firewalld stop」や「systemctl stop firewalld」と同じになるんだよ!
apacheインストール時にバージョン指定したいんですけど?
↓こーやってパッケージのバージョン名を調べて、
[vagrant@node1 ~]$ sudo yum list httpd 読み込んだプラグイン:fastestmirror Loading mirror speeds from cached hostfile * base: www.ftp.ne.jp * extras: ftp.jaist.ac.jp * updates: www.ftp.ne.jp インストール済みパッケージ httpd.x86_64 2.4.6-31.el7.centos @base
↓こーやって指定するんだよ!nameの後ろにハイフン付けてバージョン名を付けてね!
- name: install httpd yum: name={{ item }} state=present with_items: - httpd-2.4.6-31.el7.centos - httpd-devel-2.4.6-31.el7.centos - apr-devel - apr-util-devel - openssl-devel
Package name, or package specifier with version, like name-1.0.
http://docs.ansible.com/yum_module.html
gitモジュール使ってみたらエラー起きたんですけど?
例えばansibleでrbenvをgit cloneしようとしたらこういうエラーが起きました。
TASK: [rbenv | install rbenv] ************************************************* failed: [192.168.33.21] => {"failed": true} msg: github.com has an unknown hostkey. Set accept_hostkey to True or manually add the hostkey prior to running the git module FATAL: all hosts have already failed -- aborting
- name: install ruby build git: repo=git://github.com/sstephenson/ruby-build.git dest=/home/{{ user }}/.rbenv/plugins/ruby-build update=no accept_hostkey=yes
こんな感じに「accept_hostkey=yes」を付けてあげるとエラーが解消するよ!
rbenvのパスと初期化コマンドが・・・
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
こう書くのもぅマヂ無理。 フラグメント化しょ。。。
treeapps.hatenablog.com
bundlerは .rbenv 配下にインストールしたいんですけど?
- name: install bundler gem: name=bundler executable=.rbenv/shims/gem user_install=no
こう書いてあげるとちゃんと.rbenv配下にインストールされるよ!
rbenvで指定したrubyが既にインストール済みか調べたいんですけど?
これは頑張るしか無いですね。私はこうしてるよ!
- name: check whether a specific version of ruby is installed shell: rbenv versions | grep {{ ruby_version }} | tr '*' ' ' | sed -e 's/\s\+//' | cut -f1 -d ' ' register: rbenv_ruby_version - name: install ruby shell: rbenv install {{ ruby_version }} when: rbenv_ruby_version.stdout != '{{ ruby_version }}'
↑こうやったら「rbenv: command not found」って言われた!!
例えば
- name: install ruby shell: rbenv install {{ ruby_version }} when: rbenv_ruby_version.stdout != '{{ ruby_version }}'
↑こう書いたら、↓こういうエラーが置きます。
TASK: [rbenv | install ruby] ************************************************** failed: [192.168.33.21] => {"changed": true, "cmd": "rbenv install 2.1.6", "delta": "0:00:00.002443", "end": "2015-05-22 01:08:44.790851", "rc": 127, "start": "2015-05-22 01:08:44.788408", "warnings": []} stderr: /bin/sh: rbenv: command not found FATAL: all hosts have already failed -- aborting
以下の記事に原因と対策をまとめたよ!
treeapps.hatenablog.com
gemでインストールする時 .rbenv 配下にインストールしたいんだけど?
- name: install passenger gem: name=passenger executable=.rbenv/shims/gem user_install=no
これで .rbenv 配下にインストールされるよ!
subversionでcheckout済みかどうか調べたいんだけど?
statモジュールが使えるよ!
stat - Retrieve file or file system status — Ansible Documentation
完璧でないけど私はこうやってるよ!
- name: register redmine is installed stat: path={{ redmine_dir }} register: redmine_checkouted - name: svn checkout redmine branches subversion: repo={{ redmine_svn_branches_url }} dest={{ redmine_dir }} when: redmine_checkouted.stat.exists == false sudo: yes
.svnをstatしてもいいんですが、それだと .svn フォルダが無いけど redmine フォルダがあると既にチェックアウト対象が存在するよエラーが起きるので、こうしてるよ!
registerした値をechoして確認したいんですけど?
面倒だけどこうするんだよ!
- debug: var=redmine_checkouted.stdout
debug - Print statements during execution — Ansible Documentation
sudoersを編集してsudoできるようにしたいんだけど?
- name: edit sudoers lineinfile: "dest=/etc/sudoers backup=yes state=present regexp='^{{ user }}' line='{{ user }} ALL=(ALL) ALL'" sudo: yes
user変数に追加したい変数を設定して下さい。
ちなみにこれで追加すると、2回連続実行しても追記され続ける事なく、冪等性が保たれます。
sshするユーザをplaybook毎に変えたいんだけど?
なぜplaybook毎に変えたいかというと、例えば以下のような状況があるからです。
- vagrantユーザでworkユーザを作成
- workのホームにrbenvをインストール
- workユーザでrbenv install 2.2.2 等としてrubyをインストール
しかしこれを以下のようにしてしまうと失敗します。
- vagrantユーザでworkユーザを作成
- vagrantユーザでsshし、workユーザでworkのホームにrbenvをインストール
- vagrantユーザでsshし、workユーザでrbenv install 2.2.2 等としてrubyをインストール
この場合、sshしたvagrantユーザでworkユーザのホームディレクトリにrbenvをインストールしようとすると、当然Permission deniedになります。なのでsudoしたいところですが、sudoしてしまうと今度は環境変数が引き継がれず、command not foundのようになります。(remote_userで実行ユーザを変えても、別ユーザのhomeを触ろうとすると権限が無いのでPermission Deniedになる)
こうなってしまう元凶は「vagrantユーザでsshログインしている」点にあるので、ここを「workユーザでsshログインする」事ができれば、Permissionの問題も無くなります。
この問題を解決するために、playbookを2つに分けます。playbook1では単にユーザ・グループを追加するだけ(vagrantユーザでssh)、playbook2は他の処理全て(workユーザでssh)、と分割すれば解決します。ではどうやってplaybook毎にsshするユーザを変更できるでしょうか。以下のようにすると、sshユーザを上書きする事ができます。
inventry
[all:vars] # ユーザ・グループを追加するためだけのsshユーザ custom_ssh_user=vagrant custom_ssh_pass=vagrant # 本来の処理を行う時のデフォルトsshユーザ ansible_ssh_port=22 ansible_ssh_user=work ansible_ssh_pass=work ansible_sudo_pass=work
playbook1
- hosts: test sudo: no vars_files: - group_vars/common.yml vars: - ansible_ssh_user: '{{ custom_ssh_user }}' - ansible_ssh_pass: '{{ custom_ssh_pass }}' roles: - user
playbook2
- hosts: test sudo: no vars_files: - group_vars/common.yml roles: - rbenv - pyenv
このように、playbook内のvarsで「ansible_ssh_user」と「ansible_ssh_pass」を上書きする事ができるのです。上書きしなければ、インベントリで定義した「ansible_ssh_user」「ansible_ssh_pass」が使用されます。
今回はvagrantの例でしたが、awsでec2インスタンスを作成した時に使う「ec2-user」でも同じ事が言えるかと思います。
雑感
この記事はredmineのplaybookを書いていて学んだものです。yum等の場合は複数回実行しても「既にインストール済みなのでスキップ」という処理を自動でやってくれるんですが、svnが既にチェックアウトと済みかどうか調べないと、毎回毎回coされて時間かかって「もぅマヂ無理。statしょ」という結論に行き着いたわけです。
ちなみにstatモジュールですが、これはansibleを使ううえで必ず使うものなので、絶対覚えておきましょう。「このフォルダがあれば」「あのファイルがあれば」は基本的にstatでやります。「ls xxx | wc -l」とかで数えたりする人は骨付き肉持った原始人なので、ちゃんとstatを使ってイケメンになって下さい。
stat - Retrieve file or file system status — Ansible Documentation
playbookを書いていて思ったんですが、みんなsudoの初期値はyesなんですかね。今回rbenvを使っているわけですが、rbenvを$HOME/.rbenvにインストールするので、gemやbundleコマンドはsudoが不要なので、私はsudoは基本noにしておいて、yumする時とかに都度sudo:yesしました。sudoでgemコマンドとか使おうとすると、.bash_profileのパスの環境変数が引き継がれなかったりして面倒なので、rbenvはsudoしなくていい場所にインストールするのが楽かと思います。
redmineのインストールplaybook作成は本当にansibleの基本を学ぶいい教材になり得るので、ぜひやってみて下さい!
ん? もうそのredmineのplaybookくれって?(今中の人はredlineのplaybookをgithubにあげようか迷い中なのです)
↓githubにアップしてみた
github.com
Ansible実践ガイド 第2版 (impress top gear)
- 作者: 北山晋吾,塚本正隆,畠中幸司
- 出版社/メーカー: インプレス
- 発売日: 2018/03/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
ansibleを学ぶ:vol02:Oracle JDK1.8のインストール、ユーザパスワード設定等 - 文系プログラマによるTIPSブログ
ansibleを学ぶ:vol03:実行中のホスト名を書き込む、変数の値に変数を使用する - 文系プログラマによるTIPSブログ
ansibleを学ぶ:vol04:よくハマる部分とその解決法 - 文系プログラマによるTIPSブログ
ansibleを学ぶ:vol05:対象サーバのid_rsa.pubを対象サーバのauthorized_keysに登録する - 文系プログラマによるTIPSブログ
ansibleを学ぶ:vol06:mysql-serverのインストールからcreate databaseまでを自動化する - 文系プログラマによるTIPSブログ
ansibleを学ぶ:vol07:figletで動的にホスト名をmotdに書き込んでニヤニヤする - 文系プログラマによるTIPSブログ