読者です 読者をやめる 読者になる 読者になる

新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:Ansible

[学習記録] Ansible

参考書籍

入門Ansible

入門Ansible

はじめに

Ansibleとは?
  • クラウド上で多数のサーバを作成・管理することも多くなった
    • 新規作成したサーバにソフトウェアをインストールしたり設定ファイルを管理したりする必要
    • 構成管理ツールを用いて対象サーバの構成を適切に管理
    • Ansibleは構成管理ツールの一つ
    • 構成管理・デプロイ・任意のコマンドを複数サーバで実行・他システムとの連携などが可能
Ansibleの特徴
  • 以下のような特徴を持つ
    • 操作対象にはssh(とPython)だけあればOK
    • 必要なファイルはinventory(管理したいホストのIPアドレスを記載)のみ
    • (実際には他にplaybookと呼ばれるファイルを使うが、必須なのはinventoryのみ)
    • 設定ファイルに書いた順に上から下へと動作する
    • 基本的に冪等性(操作を何度行っても同じ結果になる)がある
    • 既存のシェルスクリプトも使える
    • YAML形式のファイルを書くだけ(プログラム不要)

1章:Ansibleを使ってみよう

インストール
  • インストールすると使えるコマンド
    • ansible:ansibleのモジュールを実行
    • ansible-playbook:モジュールをまとめたPlaybookを実行
    • ansible-vault:ファイルの暗号化を行う
    • ansible-galaxy:ユーザが投稿しているPlaybookを使う
    • 主にansible-playbookを使う
  • Ansibleの設定ファイル
    • inventory:実行対象のホストを設定
    • playbook:taskと呼ばれる一つ一つの動作をまとめて記述
    • ansible.cfg:Ansible自体の設定を記述
inventoryファイル
  • ini形式で実行対象のホスト記述する ファイル
    • コマンド実行時に指定しなかった場合のデフォルトは/etc/ansible/hosts
    • []で囲むとグループ、それ以外はホストを表す
    • 下の例だとwebグループにweb[12].example.comが、どこにも属さないhoge.example.comが存在
    • 正規表現やor/not/and指定なども可能
hoge.example.com

[web]
web1.example.com
web2.example.com

[db]
db1.example.com
  • ホストの設定
    • 下の例だと192.168.10.3のポート5022で繋ぎに行く設定
    • ansible_ssh_user(ユーザ名)、ansible_ssh_private_key_file(秘密鍵のファイル指定)なども可能
web01.example.com ansible_ssh_port=5022 ansible_ssh_host=192.168.10.3
  • グループの設定
    • [グループ名:vars]と書くとグループ単位で設定可能
    • [グループ名:children]でグループを入れ子にできる
[testservice:children]
testweb
testdb

[testweb]
web.example.com

[testdb]
db.example.com

[testservice:vars]
ansible_ssh_port=5022
モジュール
  • inventoryファイルで実行対象のホストを指定
    • 対象ホストで実行するものをmoduleと呼ぶ
    • 例)setupモジュール:実行したホストのIPアドレスなどの状態を得るモジュール
    • inventoryで実行対象を指定し、moduleを実行するのがansible
$ ansible all -m setup

2章:playbookを作ってみよう

  • 前章ではansibleコマンドで一つのモジュールを実行したが、本章では複数のモジュールを実行する方法を紹介
    • task:モジュールとその引数をまとめた設定
    • playbook:taskを複数まとめて一連の動作を記す
    • ansible-playbookコマンドでplaybookを実行
YAMLの文法
  • 基本的な書き方
    • シーケンス:リストや配列。行頭に"-"をつけるとシーケンスになる
    • インデントでデータの階層構造を表す。文字数は決められていないが2文字のことが多い(タブは使えない)
    • マッピング連想配列。":"のあとに半角スペースを一つ以上入れて書く
    • シーケンスとマッピングを組み合わせて階層構造を作る
    • "#"でコメント
    • 改行して複数行にまたがって書くことも可能(その場合インデントが必要)
    • 形式がおかしいとAnsibleのコマンド実行時にSyntax Errorが出る
- hosts: web
  sudo: yes
  vars:
    - required: ['docker', 'pyyaml'] # シーケンスを指定
  tasks:
    - name: create docker image
      docker_image: name="my/app"
playbookを書いてみる
  • inventoryの全ホストにnewuserというユーザを追加するweb.ymlを作成
- hosts: all                # 対象を指定
  sudo: yes               # sudoで実行
  remote_user: user  # 実行ユーザ名
  vars:                       # 変数の指定
    username: newuser
  tasks:                        # 実行タスクの指定
    - name: ユーザ追加  # 実行タスク名
      user: name={{ username }} group=admin shell=/bin/bash
  • 実行時はansible-playbookを使う
    • 1回目はchanged、2回目以降はokと出る(べき等性、何回実行してもnewuserがいる状態になる)
$ ansible-playbook web.yml
  • targetセクション
    • 実行対象を設定するセクション。先の例では以下の部分。
    • hostsで対象を指定し、sudoの実行とログインユーザを指定している。
    • 最低限必要なのはhostsのみ。
- hosts: all                # 対象を指定
  sudo: yes               # sudoで実行
  remote_user: user  # 実行ユーザ名
  • varsセクション
    • 変数を設定するセクション。先の例では以下の部分。
    • 先の例ではusernameという変数にnewuserという値を入れている
    • varsは複数指定・入れ子構造が可能
    • 変数の使用時には{{ }}で囲む。入れ子の場合は.で子を指定する(shell.zshなど)
    • 変数を文の先頭で使用する場合は、文全体を""で囲む必要があるので注意
    • var_files: で別ファイルから読み込むことも可能
  vars:                       # 変数の指定
    username: newuser
  • tasksセクション
    • そのplaybookで実行するtaskを指定
    • taskは一つのモジュールとそれに対する引数で構成される、一つの動作を行う最小単位
    • 先の例(下)ではnameでタスク名を指定し、userモジュールとその引数からなるtaskを記述
    • name:必須ではないが、付けておくと後でわかりやすい
    • user:この例での実行モジュール。name, group, shellはuserモジュールの引数
    • もちろん複数のtaskを実行することも可能(インデントを揃える)
  tasks:                        # 実行タスクの指定
    - name: ユーザ追加  # 実行タスク名
      user: name={{ username }} group=admin shell=/bin/bash
#  - name: hogehoge
#    次のtaskを書くときはこんな風に書く
task
  • taskの実行順序
    • hosts: allに対しtaskAとBの二つが定義されているymlファイルを実行すると、
    • 1)全ホストでtask Aを実行
    • 2)全ホストでtask Aが終わるのを待ち、続いて全ホストでtask Bを実行
    • という順序になるため、動作の遅いホストがあるとplaybook全体の実行時間が遅くなる
    • あるホストでtask Aの実行が失敗した場合、そのホスト以外は次のtask Bから実行していく
  • taskごとの設定
    • 先の例ではtargetセクションでsudoなどを設定
    • tasks: の各task以下にsudo: などを書くことでtaskごとに設定をすることも可能
    • 両方設定がある場合、taskごとの設定が優先される
handler
  • 設定ファイルを書き換えた後に再起動したい
    • その場合、複数の設定ファイルを書き換えた後に再起動したくなる
    • このような場合にhandlerを使う
    • notifyが指定されたtaskが実行されうと、指定されたnameが付いているhandlerが実行される
---
- hosts: all
  tasks:
    - name: 設定ファイルをコピー
      copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: reboot apache
    - name: ownerの設定
      file: dest=/etc/httpd/conf/httpd.conf owner=httpd state=file
      notify: reboot apache
  handlers:
    - name: reboot apache
      service: name=httpd state=restarted
  • 上の例
    • 設定ファイルをコピー後、ownerをhttpdに変更
    • 両方のタスクでapacheを再起動するhandlerのnotifyを設定
    • どちらかのタスクで変化があった場合、apacheの再起動が一度だけ実行される
    • 変化がなかった場合は再起動されない
    • handlerの書き方はtaskと同じだが、notifyで指定するのでnameが必須
    • notify: 以下にシーケンスを階層構造で複数配置することで複数のhandlerを起動できる
よく使うモジュール
  • 初期状態で200以上のモジュールが使用可能
    • 以下、よく使うモジュールを説明
  • script
    • 管理ホストにあるスクリプトを対象ホストに転送し、対象ホスト上で実行
    • 対象シェルスクリプトを指定。引数createsでファイルを指定すると、そのファイルがあった場合実行をスキップする
    • スクリプト内部で最後に作るファイルを指定すれば、べき等性も備えられる
  • command
    • 任意のコマンドを対象ホストで実行
    • 実行するコマンドを指定。同じく引数createsがある。またchdir引数はそのディレクトリに移動後コマンドを実行する。
    • リダイレクトやパイプは使用できない
  • shell
    • 任意のコマンドを実行
    • commandモジュールとの違いは、パイプやリダイレクトが使える
  • copy
    • 管理ホストのファイルを対象ホストにコピー
  • fetch
    • 対象ホストから管理ホストにファイルを転送
    • ログの収集などに便利
  • template
    • Jinja2というテンプレート言語を使用して対象ホストでファイルを生成する
  • get_url
    • 指定したURLからファイルをダウンロード
  • lineinfile
    • ファイル中の任意の一行を設定あるいは削除する
    • 設定する行は正規表現で指定
    • 複数行にマッチする置換を実行しても、最後の一つしか置換されない
    • 複数行の置換にはreplaceモジュールを使う
  • unarchive
    • 管理ホストのアーカイブファイルを対象ホストに転送し展開する
  • yum
    • yumコマンドを使ってパッケージをインストールする
  • service
    • serviceコマンドを使ってサービスを管理
    • 引数sleepでstopとstartの間に指定秒数だけ待つ
  • user
    • ユーザを追加・削除する
    • 引数passwordでパスワードを設定可能(ハッシュ可されている必要あり)
  • authorized_key
    • SSHのauthorized keyを追加、削除する
  • wait_for
    • 秒数ではなく、portが開くまで、あるいはファイルが作られるまで待つという動作を行う
    • 例えばsshが使えるようになるまで、あるいはログに"complete"が表示されるまで待つなど
    • 時間で待つならcommandモジュールでsleepを指定するのが簡単
  • debug
    • 任意の内容を表示
    • 引数msgに入力した内容を表示。変数の確認などに使えるが、日本語はNG