無理をしないansible

#
効率的なシステム構築と運用をめざすためのツールとして


* 関連記事:ansibleのコマンド実行時の冪等性を簡単にするためのモジュール
http://qiita.com/suicacello/items/fcab058b77b9460f4b27

# 1. はじめに

###筆者の昔話
>サーバ構築職人の朝は早い。   
>◯◯社で使われるサーバは、職人が一つ一つ手作業で構築している。
>そのため日に数台が限度だという。
>「まぁ好きではじめた仕事ですから」
>最近は手順が複雑だと愚痴をこぼした。職人の一日は、
>まず手順書の入念なチェックから始まる。
>「一つ一つ仕上がりに微妙な差が出る。機械では出来ない」
>さりげなく語るが、そこには年季と、確たる信念が見えた
 
http://www.slideshare.net/akagisho/ansible-52618704
Ansible ではじめるインフラのコード化入門

**これは美談や自慢話ではない。悲劇であり、解決するべき課題である。 **

### 解決するべき課題としては、

 * サーバーの設定を構築時に手動でやっている.**（構築コストの問題）**
 * 長年動作しているサーバーどういう設定なっているか分からない。再構築や、サーバー増設が困難。操作のエビデンスや過去の変更履歴でトレースは理論的にできるが、限界はある。**（品質の問題）**
 * 個々のプログラムの保守作業が手動でミスが起こりやすい。ミスをおこらないようにするために工数がかかりすぎている。**（品質、保守コストの問題）**

### 解決するには

　無理せずにansibleでできること

 * サーバーの設定を、簡単にスクリプトで記載して、複数台のサーバー設定を一括でできる。**（構築コストの削減）**
 * スクリプトとDRY RUN機能(後述)によって、現在のサーバーの設定情報が確認できる。**（品質の向上）**
 * 操作手順をansibleにすることで簡単なオペレーションにできる。**（品質の向上、保守コストの削減）** 

 その他で使用するべきツール
 
 * etckeeper  
 　/etcを誰かが勝手に変えてしまった場合を防ぐため

 * systeminfo  
 　windowsのシステム情報を管理するため
 　
 * git,subversion  
   コード化された設定情報のバージョン管理
 

### *「無理をしない」*とは

 * chef,ansibleなどのdevopsのツールは、 「開発者がインフラ設定をするためのもの」と解釈されがちだ。
 
 * しかし、少なくとも自分の周りでは、開発者がイキナリ、インフラ設定をすることは想定していない。インフラの知識や構成管理の知識がないためだ。これらのツールを使う人は、通常、**インフラ担当者や運用担当者**が想定される。
 
 * 開発を生業にしていない人（インフラ担当者や運用担当者）が、使うツールとして、ゴリゴリとしたコーディングではなく、設定ベースや手順ベースでできる事が重要。

 * 開発している人が忌み嫌う**ベタ書きを是とした記述で可読性を上げる**という考え方です。  
   要は**「コーディングではなく、手順書の延長としてのツール」**が重要です。 
  
 

# 2. ansibleとは、なぜansibleか？
### ansibleとは
[http://www.ansible.com/](http://www.ansible.com/)

[http://www.kyoshida.jp/ansibledoc-ja/index.html#](http://www.kyoshida.jp/ansibledoc-ja/index.html#)Ansible ドキュメントへようこそ!

>Ansible は IT 自動化ツールです。システムの環境設定やソフトウェアのデプロイ、継続的デプロイや休止時間がゼロのローリングアップデートといった高度な IT タスクを実行可能にします。

>Ansible の目的はシンプルでありながら出来るだけ簡単に使用できる事です。また、セキュリティと信頼性に強くフォーカスをあてていて、移動箇所が最初であるという特色があり、転送に OpenSSH を使用して、人が妥当性を評価しやすい – プログラムには親しみやすくはないけれど – ように設計された言語です。


> 語源：アンシブル（Ansible）とはアーシュラ・K・ル＝グウィンのSFシリーズ、ハイニッシュ・ユニバースに登場する超光速通信技術。

ansibleはchef,puppettと同様の構成管理ツール。サーバーに対する設定作業を自動化できるもの。

構成管理ツールを使うに当たって、「冪等性」という考え方を知っておくと良いでしょう。「べきとうせい」と読みます。ここではサーバなどに対してスクリプトを実行するときに、一回実行するのと複数回実行するので、同じ結果が保証されることとお考えください。

* 自分自身のサーバーの設定を自動化することができますし、
* ansibleがインストールされたサーバーから、他の複数台のサーバーの設定を行うことができます。

Ansibleにはplaybookと言う仕組みがあります。YAMLフォーマットで書かれたファイルにサーバに対する操作を定義していき、それをansible-playbookコマンドで実行することで、サーバを常にplaybookで定義した状態にしておくことができます。




### Chefなどの他の構成管理ツールと比較すると
http://techracho.bpsinc.jp/yamasita-taisuke/2014_05_29/17567  
chefからansibleに乗り換えた5つの理由
> サーバ側に何もインストールする必要がない  
> chefは管理対象ノードにchef-clientをインストールする必要がありますが、
> ansibleはPython 2.4が入っていて、sshでログインできればOKです。

　　　既存のサーバーに追加するなどこれが大きいです。

> シンプルな構造になっている  
>  ansibleはとてもシンプルで動かすだけなら
>  インベントリ(ホスト名を列挙したもの)とymlコードの2つだけあれば動きます
>  とっても覚えることが少ないです。

> コードが分りやすい  
> rubyのシンタックス等を意識しないで済むのでよりシンプル  
> chefのコードが分りにくい点の一つに上から順に実行されるとは限らないというのがあります。

　　　筆者の思うansibleは挙動が想像しやすいです。


###筆者が思うansibleの長所

 - 過去の手順書の資産を流用しやすい  
 
    過去の構築手順は、コマンドラインになっているものが多いはず、それをansbileに置き換えやすい。
 
 - 後で見た時に見やすい。
 
 　　chefだと色々と柔軟にレシピに記載出来てしまう。結果、後々、わけが分からなくなる。anbileは、  
 　　 - playbookに記載できることは制限されており、  
 　　 - 複雑な事をしたい場合は、モジュールを作る  
 　　という形で、綺麗に構造化、ブラックボックス化できる。
 　　

# 3. ansbileを前提とした運用、保守のイメージ

サーバーの設定とは下記の３つに分類される。

1. インフラ構成管理用のplaybook
    インフラ部門にて管理する設定箇所
    * OSの設定、MWの設定 
    * パッケージのインストール、不要サービスの停止
    * セキュリティパッチ 
    継続的に一つのPLAYBOOKの塊をバージョン管理で維持していく。
    サーバーの再構築や、セキュリティ設定の維持管理に使う。
    リストア時に作成する。

2. デプロイ用のPlaybook  
   アプリ開発門から情報をもらって、運用部門にて作成するplaybook
    * テーブルの作成、項目追加
    * アプリケーションのデプロイ

3. インフラ部門作成のシステム運用作業用playbook
    インフラ部門にて管理する設定箇所
　  * 再起動などの定期的な作業
　  * 情報収集
    作業単位で作成するPLAYBOOK
    毎回同じモノを使いまわしていく。そして改定していく。

全てに適応できるかは、状況次第だが、ポイントは

  * 一般的に1.から導入するほうが望ましい。  
  * 1.と2.の境界を明確に分けることが重要。例えば、フォルダで分けるなど。
  * 手動で実施する部分と、ツールを使って実施する部分を分けておくと良い。  
    例えば：Oracleは手動で入れるなど 
  * 1.はansibleで、2.は手動でという考え方や、その逆も十分ありえる。  
  * できる範囲から導入していくことが重要

# 4. ansibleの導入作業

# 4.1 操作する側のサーバー（管理サーバー側）

以下の手順をルート権限で実施。(sudo bash)

1. EPELの登録
 ansibleをダウンロードできるように登録  
 
     yum -y localinstall http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm


2. 編集 
  /etc/yum.repos.d/epel.repoを次のように修正
  

      #baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
      mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
    
      コメントアウト位置を下記に変更
    
      baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
      #mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch


3. ansibleのインストール  

       yum -y install ansible


4. 管理サーバーにansible実行ユーザー(rootではなく)で、
　　操作される側のサーバーにsshで証明書ログインができるようになっていること。


# 4.2 操作される側のサーバー（管理対象サーバー）

1. 管理サーバーからsshで証明書ログインができるようになっていること。  
   管理対象サーバーでsudoが可能なユーザーにする必要がある。

2. etckeeperのインストール(推奨)  
   **ansibleとは無関係**、インストールすることによって、/etc配下の変更履歴を追跡できる。  
   以下の手順をルート権限で実施。(sudo bash)

       yum -y install git
       yum -y install etckeeper
       etckeeper init
       etckeeper vcs status

3. その他は不要        
   クライアントレスで動きます。
      
   
# 5. ansibleの構成

# 5.1 フォルダ構成
ansibleのベストプラクティス（Best Practice）となっているフォルダ構成を参考考えた
下記のフォルダ構成をどこにおいても良い。  このフォルダ構成を本番と検証でコピーして使う。
ただし、gitなどのバージョン管理ソフト下で管理したほうが良い。
　　
    
    |-- site_aps.yml
    |-- site_wbs.yml 
    |-- site_dbs.yml 
    |-- production       # 本番サーバ用インベントリファイル
    |-- staging          # ステージングサーバ用インベントリファイル
    |-- development      # 実験用サーバ用インベントリファイル
    |-- group_vars/
    |   |-- production.yml 　# 本番サーバ用の変数
    |   |-- staging.yml      # ステージングサーバ用の変数
    |   `-- development.yml　# 実験用サーバ用の変数
    |-- host_vars/
    |-- roles/
    |   |-- common/
    |   |   |-- files/
    |   |   |-- handlers/
    |   |   |   `-- main.yml
    |   |   |-- tasks/
    |   |   |   |-- main.yml
    |   |   `-- templates/
    |   `-- wordpress/
    |       |-- files/
    |       |-- handlers/
    |       |   `-- main.yml
    |       |-- meta/
    |       |-- tasks/
    |       |   |-- main.yml
    |       `-- templates/
    |           |-- httpd.conf.j2
    `--library/
        `--commander.py
        

* site_\*.yml
  ansible-playbook コマンドに渡す大元 (root) の playbook ファイルです。　　
  *無理をしないルール*だとサーバー種別ごとにファイルを用意します。

* production,staging,development
  今回のインベントリファイルです。実際の運用では development, staging, production など
  というそれぞれの環境毎のファイルにするのが Best Practice っぽいです
  * production: 本番環境を指します。
  * staging: 検証環境、試験環境を指します。
  * development: Virtualboxなどで担当内部に立てたVM環境を指します。Playbookの動作検証のためです。
  
* group_vars/  
  グループ毎の変数を定義するのに使います。ファイル名はインベントリファイルで設定するグループ名です。インベントリファイルにグループ変数を書くことも可能です。production.yml,staging.yml,development.ymlが存在します。逆に*無理をしないルール*だと他のファイルは存在させません。


* host_vars/  
  ホスト毎の変数を定義するのに使います。group_vars と同じくファイル名はインベントリファイルに設定したホスト名です。インベントリファイルの中でホスト名の右に並べて書くこともできます

* roles/  
  このディレクトリの下に role (役割) 毎のディレクトリを作成し、それぞれの role にさらに files/, handlers/, tasks/, templates/, ~~vars/, meta/ defaults/~~というサブディレクトリを作成します (その role で使うもののみ)  (vars/ meta/ defaults/は「無理をしないルール」では使用しない。)

* roles/\*/files/  
  当該 role の task で使うファイル関連モジュール (copy) が src として使うファイルの置き場所。任意のファイル名で置きます

* roles/\*/handlers/  
  設定変更後にサービスの再起動をさせたりする場合に、notify という定義で処理を呼び出しますが、その呼び出されるハンドラをここで定義します。main.yml というファイルで作成しますが、include という定義で複数ファイルをそこから読み込ませることが可能です

* roles/\*/tasks/　　
  何かをインストールしたり、ユーザーを作成したりする task 定義のファイルをここに置きます。handlers と同じように main.yml というファイルが起点となります

* roles/\*/templates/  
  template モジュールで利用するテンプレートファイルを置きます。このモジュールでは Jinja2 (神社) というテンプレートエンジンが使われていて .j2 という拡張子を使います

* ~~roles/\*/vars/~~  
  ~~role 毎に設定する変数を定義するファイルを置きます。handlers や tasks と同じく main.yml ファイルが起点となります~~

* ~~roles/\*/defaults/~~  
  ~~当該 role で使う変数の default 値を設定します。他で設定されていなければここで設定した値が使われます。main.yml に書きます。この変数が一番低い優先度です 「Ansible の変数の優先順」~~

* ~~roles/\*/meta/~~    
  ~~role の依存設定を書きます。A という role が B という role に依存しているなら roles/A/meta/main.yml に次のように書きます~~

* library/  
  Ansibleモジュールを自作した場合に置くべきフォルダ。自動でロードされる。

* library/commander.py  
  筆者の自作のAnsibleモジュール。コマンドやシェル実行の冪等性を加えた「作業手順書の延長たるPlayBook」を実現するための超便利なモジュール。(後述)

 
# 5.2 インベントリファイル
まずはインベントリファイルです。本番環境やステージング環境など、環境ごとにサーバのホストとグループをまとめます。

    production                # 本番用ホストの一覧
    stage                     # ステージング用ホストの一覧
    development               # 実験用ホストの一覧

production 

    [production:children] #注意、本番と検証と実験を切り分ける行
    # 必ず追加するグループを登録すること。
    webservers
    apservers

    [webservers]
    pxxxwbs01
    pxxxwbs02 
    
    [apservers]
    pxxxaps01 
    pxxxaps02 
    pxxxaps03 
    pxxxaps04 

[webservers][apservers]がグループを表す。

staging 

    [staging:children] #注意、本番と検証と実験を切り分ける行
    # 必ず追加するグループを登録すること。
    webservers
    apservers   

    [webservers]
    vxxxwbs01 
    
    [apservers]
    vxxxaps01 
    vxxxaps02 

development 

    [development:children] #注意、本番と検証と実験を切り分ける行
    # 必ず追加するグループを登録すること。
    webservers
    apservers
       
    [webservers]
    vxxxwbs03 
    
    [apservers]
    vxxxaps03 


# 5.2 site_\*.yml  
   いよいよplaybookの中身です。
   
    ---
    - hosts: webservers
      roles:
      # ./roles/ に対応するフォルダが有り、
      # そのサブフォルダ ./roles/???/tasks/main.ymlが実行される
        -  redmine
        -  redmine_itil
        -  httpd
        -  mail
        -  cdms_itil
        -  margarita