ちょっと話題の記事

Ansible入門しました。【入門編】

2015.07.06

こんにちは。半瀬です。初投です。

これから業務で利用する機会が増えるということで、Ansibleに入門しました。 せっかくなので、私が学んだ過程をまとめて晒そうかと思います。

この記事の位置づけ

ご存知のとおり、すでに当ブログでも多くの記事がたっていますので、Ansible導入のメリットなどは他の記事内容にお任せしようかと思います。ひとまず簡単にまとめさせていただきます。

以下の4本は導入編として位置づけられるかと思います。 構成管理ツール Ansibleを使ってみる | Developers.IO Using Ansible on AWS - EC2インスタンスを作成する | Developers.IO Ansibleでよく使う操作モジュール | Developers.IO Ansible初心者のつまづきポイント | Developers.IO

弊社社員によるAnsibleの紹介や勉強会のレポートも掲載しています。 AWSチーム社内勉強会「Ansible」レポート | Developers.IO 【セッションレポート】AnsibleとPackerとCloudFormationの話をしてきました #cmdevio2015H | Developers.IO

以下はAnsibleを使いこなした例で応用編です。こういった記事の理解にも本稿がお役に立つことを祈りつつ。。 AutoScaling時にAnsibleで環境構築を行う | Developers.IO Jenkins + Ansible + PackerでAMI作成を自動化する | Developers.IO Ansible Vaultを利用して秘密情報を暗号化する | Developers.IO 【要するに】osxcでMac環境の構成を記述管理する【MacでAnsible】 | Developers.IO

以上のとおり、すでに情報は豊富ですので入門用でまとめても同じ様な記事となってしまいます。 そこで今回は、単なる転載となることを避けるためにも、環境の手配→実際に手を動かしてコマンド練習→環境の撤収までをお手軽に完了する、「目標30分!コピペで時短Ansible入門」を意識してみました。

とりかかっていきます。

前置きが長くなりましたが、ここからスタートです。

▪️練習のゴール

Ansibleは1つのホストから複数のリモートホストに対して、同時に処理実行させることができます。 この基本動作の練習のために、Ansible実行元となるログインホスト(管理インスタンスとします)1台と、実際に処理実行を行うリモートのホスト(WEBインスタンスとします)を2台用意します。また、ELBを1つ用意し、2つのWEBインスタンスをぶら下げておきます。 練習のゴールを、プレーンな状態で立ち上げたWEBインスタンス2台に対して、管理インスタンスからのAnsible実行で同時にapacheをインストール→ELB経由でアクセス可能となることを確認すること、と決めます。

▪️必要なもの

・基本的なLinuxの知識 ・AWSアカウント ※無料枠が残っているもの ・VPCとCloudFormation(以下、CF)の基本的な理解 ※ CFに慣れていない方は本稿の記述どおりに進めて頂ければ大丈夫かと思います。

※出力結果は基本的に省略します。ファイル名とパスを合わせておいていただければコピペが可能ですが、Public_IPやファイル編集などは手入力をお願いします。

下準備。

1. VPCで練習用の構成を準備

上でお話しした構成です。 AWS Design これらをCloudFormationで作っていきます。CFテンプレートをご用意していますので、 1. コチラよりダウンロード 2. EC2キーペアを一つ作成 3. AWSマネジメントコンソールのCloudFormationから「Create New Stack」 4. 作成ステップ内でテンプレートをアップロード(「Upload a template to Amazon S3」) 5. Stack Nameは任意に決め、あとはデフォルト記述のまま作成 の順で、作成をしてみてください。 ※インスタンスは t2.micro で立ち上げますが、12ヶ月間の無料期間が過ぎていないかご注意ください。

3分ほどでStackが出来上がります。各インスタンスのPrivate_IPは下記のように作成しました。 ・管理インスタンス(ip-10-0-0-10) : 10.0.0.10 ・WEBインスタンス1(ip-10-0-1-10) : 10.0.1.10 ・WEBインスタンス2(ip-10-0-2-10) : 10.0.2.10

また、CFのコンソール上の「Outputs」では、以下のように本稿で必要な情報を表示しています。特にマネジメントコンソール上をうろうろする必要はありません。 20150705-01_CfOutputs ・http://〜は最後のELBのアクセステストで使用(作成時点では表示できない状態です) ・IPは管理インスタンスのログイン用PublicIPです。 作成が完了しましたら、インスタンス側の下準備に移ります。

2. キーファイルの準備

Ansible は sshdで接続しますので、インスタンス間の接続環境を整える必要があります。 VPC内のインスタンスは全て同じEC2キーを登録していますので、管理インスタンスにキー(ec2-key.pem とします。※コマンドをコピペで実行するために、ファイル名は合わせておく必要があります。)をアップロードしておくことで、2台のWEBインスタンスへログインが可能な状態となります。 以下は、MAC(OSX 10.10.3)からのコマンド例です。

・ローカルから管理インスタンスにログイン確認(上述した「Outputs」のPublicIP)

$ ssh -i .ssh/ec2-key.pem ec2-user@<管理インスタンスのPublic_IP>

・ローカルから管理インスタンスにEC2キーを上げておく

$ scp -i .ssh/ec2-key.pem .ssh/ec2-key.pem ec2-user@<管理インスタンスのPublic_IP>:/home/ec2-user/.ssh/ 

・管理インスタンスからWEBインスタンスへEC2キーを使ってのログインも確認しておきましょう。

[ec2-user@ip-10-0-0-10 ~]$ ssh -i .ssh/ec2-key.pem ec2-user@10.0.1.10
・・・
[ec2-user@ip-10-0-1-10 ~]$ exit
[ec2-user@ip-10-0-0-10 ~]$ ssh -i .ssh/ec2-key.pem ec2-user@10.0.2.10
・・・
[ec2-user@ip-10-0-2-10 ~]$ exit

ここまで問題なければ、下準備完了です。

3. 管理インスタンスにAnsibleをインストール

していきます。Amazon Linuxではpipからインストールするほうがよさそうです。 *1

[ec2-user@ip-10-0-0-10 ~]$ sudo easy_install pip
Searching for pip
Reading https://pypi.python.org/simple/pip/
・・・
Finished processing dependencies for pip
[ec2-user@ip-10-0-0-10 ~]$ sudo pip install ansible
・・・
Successfully installed ansible-1.9.2 jinja2-2.7.3 markupsafe-0.23

インストールが完了したら、確認をしましょう。libgmp-5を要求されるエラーは今回は我慢してすすめていくことにします(動作上は問題ありません)。

[ec2-user@ip-10-0-0-10 ~]$ ansible --version
/usr/lib64/python2.6/site-packages/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec.  You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
  _warn("Not using mpz_powm_sec.  You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
ansible 1.9.2
  configured module search path = None
[ec2-user@ip-10-0-0-10 ~]$ 

4. Ansible設定ファイルの準備

以下のようにAnsibleの設定ファイル(./ansible_hosts ← 配置場所と名前を合わせておくことをお勧めします)を用意します。WEBインスタンスのIPを「webs」という名前でグループにまとめて指定。この書き方の場合、管理インスタンスのIPは「webs」に含まれません。

[ec2-user@ip-10-0-0-10 ~]$ cat ./ansible_hosts
10.0.0.10

[webs]
10.0.1.10
10.0.2.10
[ec2-user@ip-10-0-0-10 ~]$

ここまでできると、いよいよAnsibleの動作学習に移ることができます。

練習

5. 練習1 - 設定ファイルのホストグループとモジュールの理解

基本オプションを学びます。「--private-key 」がEC2キーの指定、「-i」が Ansible 設定ファイルの指定、「-m」がモジュール呼び出しとなります(ここでは ping)。 ・「all」がすべてのhost指定

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts all -m ping

・「webs」が設定ファイル内のグループ指定

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -m ping

それぞれの出力結果で違いが理解できるかと思います。

6. 練習2 - copyモジュールとfileモジュールの理解

前項をもとに、いくつかモジュールの動作を確認します。「-a」でモジュールの動作を指定します。fileモジュールではsudo実行するので「-s」を使用します。

・copyモジュール : ファイル転送。srcでローカルファイルパスを指定、destでリモートを指定

[ec2-user@ip-10-0-0-10 ~]$ echo test >> ./test.txt
[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -m copy -a "src=./test.txt dest=/tmp/aaa.txt"

「success」が2インスタンス分出力されれば成功です。ファイルの設定内容やmd5sumなども出力されているかと思います。次に転送ファイルを確認します。

・モジュールなしで「-a」 : リモートホストでコマンド実行

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -a "cat /tmp/aaa.txt"

転送したファイルをcatしています。copyでの転送が確認できるかと思います。

・fileモジュール : ファイルの設定変更。destで対象ファイル指定、owner、group、modeなど

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -m file -a "dest=/tmp/aaa.txt owner=root group=root mode=600" -s

前後のファイル設定は下記で確認できます。

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -a "ls -l /tmp/aaa.txt"

リモートホスト内のファイル設定変更が確認できました。

・syncronizeモジュール : リモートホストに対しrsyncを実行。recursiveで再帰的同期

[ec2-user@ip-10-0-0-10 ~]$ mkdir -p ./test1/test11 ./test1/test12 ./test1/test13
[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs  -m synchronize -a "src=./test1 dest=/tmp/ recursive=yes"

同様に「success」が出力されれば成功です。cmdの箇所に「rsync」したよ、と出力されます。次に確認をします。

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -a "ls -l /tmp/test1"

ローカルに作成したディレクトリが リモートホストの /tmp 配下にrsyncできていることが確認できました。

7. 練習3 - Playbookの理解

AnsibleにはPlaybookという機能があり、モジュール処理を組み合わせて記述したファイル(Playbook)を「ansible-playbook」コマンドで実行し、リモートホストに対して内容通りの処理を行うことが可能です。つまり、Playbookによるサーバー構成管理が可能となります。 前項までで、一連のコマンドによるモジュール動作の基本ついて把握できましたので、playbookについての基本も確認ができるのではないかと思います。「ansible-playbook」コマンドにおける、「-i」、「--private-key」のオプションは「ansible」コマンドと同じです。 それでは以下のようにapacheインストール用のplaybookを用意します。

[ec2-user@ip-10-0-0-10 ~]$ cat install-httpd.yml
- hosts: webs
  sudo: yes
  tasks:
      - name: install httpd
        yum: name=httpd state=present

      - name: run httpd
        service: name=httpd state=running enabled=yes 
[ec2-user@ip-10-0-0-10 ~]$

・「hosts: webs」の項目で「-i」指定したAnsible設定ファイルの「webs」グループを指定。 ・「sudo: yes」は「-s」オプションに相当。 ・「tasks: 」の記載より下に、動作実行順にモジュールを並べていきます。「name: 」は任意。 ・利用モジュール「yum: 」→ yumを実行。nameでパッケージ指定、stateで状態の指定(※「present」でinstall、「absent」でuninstall) ・利用モジュール「service: 」→ serviceを実行。nameがサービス、stateが状態、enableはchkconfigです。 といった要領です。ファイルを実行してみます。

・実行前にタスクリストを確認。「--list-tasks」をつけることで、処理実行されず、ファイル内で実行されるタスク一覧が出力されます。

[ec2-user@ip-10-0-0-10 ~]$ ansible-playbook --private-key=.ssh/ec2-key.pem -i ./ansible_hosts install-httpd.yml --list-tasks

・ファイル内容をリモートホスト内で実行

[ec2-user@ip-10-0-0-10 ~]$ ansible-playbook --private-key=.ssh/ec2-key.pem -i ./ansible_hosts install-httpd.yml

「failed」がなければ、「ansible」コマンドで起動の確認を行います。(何気に説明していないcommandモジュールを使っています。。

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -m command -a "/etc/init.d/httpd status" -s

httpdの起動が確認できるかと思います。

最後に、ELBからのアクセスを届くようにするためのplaybookを書きます。その前に、今いれたばかりのhttpdを一度アンインストールしておきましょう。

[ec2-user@ip-10-0-0-10 ~]$ cat uninstall-httpd.yml
- hosts: webs
  sudo: yes
  tasks:
      - name: stop httpd
        service: name=httpd state=stopped 

      - name: uninstall httpd
        yum: name=httpd state=absent
[ec2-user@ip-10-0-0-10 ~]$ ansible-playbook --private-key=.ssh/ec2-key.pem -i ./ansible_hosts uninstall-httpd.yml

ゴール

8. ゴール - AnsibleでELBからのアクセスを成立させる

前項と公式のモジュール一覧を参考に目標のplaybookを作成しました。 ELBにはデフォルトでドキュメントルートのindex.htmlをヘルスチェックに使用しますので、ファイルを配置&閲覧可能にしておく必要があります。

[ec2-user@ip-10-0-0-10 ~]$ cat install-httpd-elb.yml
- hosts: webs
  sudo: yes
  tasks:
      - name: install httpd
        yum: name=httpd state=present

      - name: run httpd
        service: name=httpd state=running enabled=yes 

      - name: set elb checkfile
        lineinfile: dest=/var/www/html/index.html line={{ ansible_hostname }} mode=0755 owner=apache group=apache state=present create=yes
[ec2-user@ip-10-0-0-10 ~]$

・タスクの上から2つまでは練習で使用したものと同じ ・利用モジュール「lineinfile: 」→ ファイルの記述置換モジュールですが、今回はファイル配置に利用しています。destで配置先を指定、lineでファイル内容を記載(「{{ ansible_hostname }}」にはリモートホストのhostnameが入ります。)、stateで作成(present)/削除(absent)、create=yesで「ファイルがない場合に実行」

・ファイル内容をリモートホスト内で実行

[ec2-user@ip-10-0-0-10 ~]$ ansible-playbook --private-key=.ssh/ec2-key.pem -i ./ansible_hosts install-httpd-elb.yml

「failed」がなければ、「ansible」コマンドで起動の確認を行います。

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs -m command -a "/etc/init.d/httpd status" -s

index.htmlファイルも確認します。(catとlsで)

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs  -a "ls -l /var/www/html/index.html" -s
[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs  -a "cat /var/www/html/index.html" -s

何度かaccess_logをtailしてみましょう。

[ec2-user@ip-10-0-0-10 ~]$ ansible --private-key=.ssh/ec2-key.pem -i ./ansible_hosts webs  -a "tail -n 3 /var/log/httpd/access_log" -s

ELBからのアクセスに対し「200」が返されていればOKです。

最後にブラウザからアクセス確認をして完了です。 index.htmlの内容により、ロードバランシングされていることが確認できます。 20150705-02_110 20150705-03_210 以上で、管理インスタンスからのAnsible実行により、WEBインスタンス両方にapacheをインストールしELBからの疎通を開始させることができました!! お疲れさまでした。

9. おかたづけ

マネージメントコンソール側のスタック削除を忘れないようにしてください。

さいごに

長文気味ですが、コピペで時間計測したところ大体30分強で終わりそうな雰囲気です。(終わらなければごめんなさい)

今回はAnsibleについての勉強内容を晒しました。ある程度慣れて展望が見えてくると、色々試してみたくなります。書籍と公式サイトで引き続き勉強を進めようかと思います。

それでは

脚注