2015年11月29日日曜日

Ansibleお為し中・・・

気がついたら今年も残すところあと1ヶ月ですね。

職場でたった一人のインフラ担当者だったりすると、サーバ構築ラッシュが発生すると土日連休ボランティア活動する羽目になるのですが(ぉぉぉ
どうにも手が回りそうにないので、Chefに続いてAnsibleに手を出してみました。

といってもPython書いたことないんですが(笑)

AnsibleはChefと違い、
  • サーバに特別なエージェントが不要。サーバ側にはSSHとPythonがインストールされていればいい。
  • 基本はプレイブックと呼ばれるYAMLファイルにやりたいことを記述するので、習得が容易。
  • Ansible Galaxyとよばれるサービスがあり、大抵のやりたい事はここにあったりする。
  • 動かすのにサーバなどが不要。
  • Chefほど多くのサーバを管理するのには不向き。(管理サーバがいないので)数台程度

という特徴があります。
特にエージェントレスというのは、Chefと違い、サーバに特別何か仕込まなくて良いので、お客さんの環境にセットアップするとか、不要なものを極力入れたくない場合に便利そうです。
反面エージェントがないということは、サーバの現状を取得するとかが難しい。という面もありますが、Chefと違い繰り返し実行して冪等性を確保。というより、おかしくなったらサーバごと作り変える。という用途に向いています。

Ansibleは習得が容易、というよりChefの登場人物や構成要素が多すぎるという気がしますが(笑)
いくつか用語を知っておく必要が有ります。
  • Inventoryファイル
    • Ansible実行対象サーバを記したINIファイル(のようなもの)。特徴として複数のサーバをグループとして設定することが出来、複数のサーバに設定を行うことが出来る。
  • モジュール
    • ファイルをコピーとか、DBを作成とか実際にサーバを操作する機能をもったもの。自作も勿論可能。
  • プレイブック
    • Chefでいうレシピに相当するもの。複数のモジュールを組み合わせて一連の操作を記述したYAMLファイル。複数に分割してInclude出来たりする。
    • 感じ的にはシェルのDSLっぽい感じ。
  • ロール
    • 権限。という訳ではなく、Chefでいうクックブックに相当するもの。複数のプレイブックをまとめたもの。

まずはこれくらいを押さえておけば良いと思います。
自分もAnsible勉強し始めて1週間程度ですが・・・

ではまずは環境構築です。
自分はCygwin上に構築しました。

インストールにはapt-cygコマンドを使用しますので、もし古いapt-cygをつかわれている場合は以下の要領で最新にしておきます。

wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
chmod 755 apt-cyg
mv apt-cyg /usr/bin/

まずはPythonをインストールします。
apt-cyg install python
python -V (Vは大文字)

python 2.7.10

とかと出ればOKです。
次に、easy_installやpipを使うのに必要なビルドツール一式をまとめて入れます。
apt-cyg install patch gcc4-core gcc4-g++ make autoconf automake m4 bison readline openssl-devel libsqlite3-devel libxml2-devel libxslt-devel zlib-devel libncurses-devel libtool ca-certificates

次にansibleをインストールするのに必要なpipというコマンドをインストールする為のeasy_installをインストールして、pipをインストールします。(な、長い・・・)
apt-cyg install python-setuptools
easy_install-2.7 pip
やっと準備が出来たので、ansibleをインストールします。
pip install ansible
練習がてら、Vagrant上にJenkinsサーバを構築するAnsibleを作りましたので、これを例に説明します。

まずルートディレクトリにあるhostsというファイルがInventoryファイルになります。
中身はサーバのグループ名「jenkins_server」と、そのグループに所属しているサーバのIPやSSHで接続するユーザ名などが書いてあります。

次に、site.ymlですが、これはマスタープレイブックと呼ばれる、すべての起点になるプレイブックです。
ちなみに今回の例ではひとつだけですが、本番とステージング用など、複数作ることも可能です。その場合それぞれを指定して実行します。

これの中身ですが、hosts:の箇所が実行させるサーバグループ名になります。これはInventoryファイルのグループ名になります。Allとすると、Inventoryファイル全部が対象になります。

rols:の箇所は該当hostsのサーバに対し実行するロールになります。
(とりあえず、Zabbix-agentの箇所は置いておきます)

rollsディレクトリの配下にはそれぞれロールが配置されています。
全部解説は大変なので、まずはcommonロールを見ていきます。
このロールにはhaldlersとtasksというディレクトリがあります。
tasksディレクトリ内には複数のプレイブックがありますが、その中のmain.ymlというプレイブックがこのロールのマスタープレイブックになり、基点となります。
この中では、installとcreate_userとsshの3つプレイブックをインクルードしています。

install.ymlを見ていきましょう。
この中にあるyum:とかservice:とかがモジュールになり、yumとかserviceコマンドに相当する機能を持っています。
モジュールは複数の引数をもつことがあり、key=varという形で渡したり、YAML形式で渡したりします。

handlersについては、commonロールでは使っていないのですが、jenkinsロールのhandlersには"restart apache"と"restart jenkins"という二つのハンドラが登録されています。
これは、プレイブック内でConfファイルを変更した場合などサービスを再起動したりとか、アプリをインストールしたらサービスに登録して起動させたい場合があります。そのときにnotifyとしてハンドラ名を渡すと、そのハンドラに規定されたモジュールが動作します。(Jenkinsロールのmain.yml22~37行目参照)

あと、プレイブックはYAMLなのでChefと違いプログラムが書けません。しかし、with_itemsという構文を使うことにより、変数itemに配列の値を入れることが出来ます。{{ item }}のように使います。なお、変数名はitem固定のようです。

後最後においておいたzabbix_agentですが、ここにロールはありません。
では何処にあるかというと、Ansible Galaxyのサービスからロールをインポートして利用しています。
Ansible Galaxyのインポート方法は以下のとおりです。
ansible-galaxy install dj-wasabi.zabbix-agent
role:以下の記述は、zabbix-agentロールが要求する引数たちです。
Apacheのロールで使用しているテンプレートですが、Ansibleではjinja2(そう。神社です)というテンプレートエンジンを使用しています。
色々出来るようですが、拡張子はj2にする。{{ value }}で変数を埋め込める。てのを知っていれば設定ファイルを丸まる置換とか出来るのでとりあえずは使えると思います。

最後に、Apacheのプレイブックでcopyモジュールを使ってSSL証明書をコピーしているのですが、コミットするとき、うっかりダミーファイルを置くのを忘れてしまったので、GitHubにあがっていませんが、templateディレクトリではなく、filesというディレクトリを作成し、そこからのパスを指定します。

以上ざっくりですが、自分が一週間合間見てお試しした感じです。
ついでにAWS上にちょっと本格的なLAMP環境を構築するものや、Python書いたことないのに無謀にもAnsibleモジュールを2時間で作成したものとかを置いておきます。



2015年11月23日月曜日

Cygwinでsudoを使う

地味にハマったのでメモ。

AnsibleをCygWinで使っていた特に、何故かsudoが無いぞ。と怒られました。

そんな馬鹿なとリモートサーバを覗いてみるも、そもそもVagrant使っている段階でsudoないと使えないし。

っと小一時間プレイブックをこねくり回していたのですが、結果から言うとCygWinにsudoがないのが原因でした。
そもそもCygWinにパーミッションの概念がどこまであるのか疑問ですが、ググるとみんな苦労しているようで、解決法も様々あるようです。

自分が試したのは以下のサイトにあるやり方です。

Cygwin で sudo 的コマンドを使うための設定

/bin/sudoというファイルを作成し、以下の内容を張り付け、実行権限を付与します。


#!/bin/sh

function usage_exit() {
    cat << EOF >&2
Usage: $(basename $0) command
       $(basename $0) -e file
       $(basename $0) -v
EOF
    exit 1
}

edit_flg=0
while getopts :veh opt
do
    case $opt in
        v)
            exit 0
            ;;
        e)
            edit_flg=1
            ;;
        h)
            usage_exit
            ;;
        \?)
            usage_exit
            ;;
    esac
done

shift $(($OPTIND - 1))

if [ $edit_flg -eq 1 ]; then
    if [ $# -ne 1 ]; then
        usage_exit
    fi

    sudoedit "$1"
else
    if [ $# -eq 0 ]; then
        usage_exit
    fi

    quote_args=''

    for arg in "$@"
    do
        arg=$(printf '%q' "$arg")
        quote_args="$quote_args $arg"
    done
    quote_args=$(echo "$quote_args" | sed -e "s/\\\\'/'\"&\"'/g" -e 's/\\\\/&&/g')

    quote_pwd=$(printf '%q' "$PWD" | sed "s/\\\\'/'\"&\"'/g")

    cygstart --hide -w -a runas sh -l -c "'exec < /proc/$$/fd/0 > /proc/$$/fd/1 2> /proc/$$/fd/2; cd $quote_pwd; $quote_args'" &

    trap 'trap "" 1 2 3 15; sudo c:/Windows/system32/taskkill /pid $(ps -p $! | awk "NR==2 {print \$4}") /t > /dev/null 2>&1' 1 2 3 15
    wait $!
fi