ksaitoの日記

日々試したことの覚え書き

ansibleのインベントリに指定したホスト名

ansibleのインベントリに指定したホスト名を参照するサンプルです。

---
- hosts: all
  vars:
    hostname: "{{inventory_hostname}}"
  tasks:
    - debug: msg="{{hostname}}"

実行するとインベントリに指定した名前を参照できます。

$ ansible-playbook sample.yml

PLAY [vagrant] *****************************************************************

TASK [setup] *******************************************************************
ok: [vagrant1]
ok: [vagrant3]
ok: [vagrant2]

TASK [debug] *******************************************************************
ok: [vagrant1] => {
    "msg": "vagrant1"
}
ok: [vagrant2] => {
    "msg": "vagrant2"
}
ok: [vagrant3] => {
    "msg": "vagrant3"
}

PLAY RECAP *********************************************************************
vagrant1                   : ok=2    changed=0    unreachable=0    failed=0
vagrant2                   : ok=2    changed=0    unreachable=0    failed=0
vagrant3                   : ok=2    changed=0    unreachable=0    failed=0

$

awsのホスト名を設定するときに便利です。

makeのオプション

ストアドプロシージャのコンパイルなどファイルとしてオブジェクトができないものをmakeでビルドする時によく使うオプションです。

エラーが起きてもできる限り実行を継続する。

-kは、コンパイルエラーが起こっても依存関係のないビルドを継続します。

同じようなオプションでエラーを無視する-iがありますが、jenkinsを使って自動化する場合、-iだと終了ステータスは常に正常終了なので、コンパイルエラーを検知できません。

-kがお勧めです。

強制的にビルドする。

-Bオプションをつけると強制的にコンパイルを行います。

コンパイルを実行したことにする。

-tオプションをつけるとターゲットをtouchします。 makeコマンドは、すべてのターゲットがコンパイル済みと勘違いします。

ansibleで自動起動をセットアップするときの判断

ansibleで自動起動をセットアップするときに、ディストリビュージョンの種類やバージョンを判断基準にするのにどうも違和感がありました。

いろいろ調べた結果、ansibleのansible_service_mgrで判断するのが正解です。

試す

下記のソースを使って検証します。

$ cat sample.yml
- hosts: localhost
  tasks:
    - debug: msg="{{ansible_service_mgr}}"

$ 

ubuntu 14.04で実行するとupstartでサービス起動していることがわかります。

$ ansible-playbook -i "localhost," sample.yml

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "upstart"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

$

Ubuntu 15.04で実行するとsystemsなのがわかります。

$ ansible-playbook -i "localhost," sample.yml 

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "systemd"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   

$ 

もう、ディストリビューションで判断する必要はありません。

jenkinsにインストールしたプラグイン

jenkinsにインストールしたプラグインの覚書

Timestamper

コンソールにタイムスタンプをつけるプラグインです。

JobConfigHistory

ジョブの設定変更履歴を残してくれるプラグインです。

Build Trigger Badge Plugin

ビルドのトリガをアイコンで表示してくれるプラグインです。

JavaMelody

Jenkinsの負荷状況をモニタして表示するプラグインです。

URLに"/monitoring"を追加したパスでアクセスできます。

Sidebar-Link

任意のリンクを追加できるプラグインです。

dockerのデータの永続化

dockerでデータを永続化するために--volumes-fromを使ってみました。

やりたいこと

dockerのオフシャルコンテナでmysqlやjenkinsを手軽に立ち上げることができます。

データについては、-vオプションでホストOSのディレクトリにマッピングしていたのですが、ファイルオーナやパーミッションの違いでアプリケーションが起動しなかったりするので--volumes-fromを使ってデータもコンテナ化してホストOSの依存をなくしたい。

単純なパターン

オフシャルドキュメントのManage data in containersを参考にします。

データコンテナの作成

データを保管するコンテナをdocker createコマンドで作成します。イメージは、busyboxを使って-vオプションでデータを保管するパスを指定します。

$ docker create -v /var/jenkins_home --name jenkins_test busybox /bin/true
a028f489ae189002030b8ecb7e96b371cf66ea005fcfcc694575f8ab6bb2832e
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a028f489ae18        busybox             "/bin/true"         3 minutes ago       Created                                 jenkins_test
$ 

データの作成

次に一連のコマンドでコンテナを起動してファイルを作成し、コンテナを削除します。

$ docker run -it --rm --volumes-from jenkins_test ubuntu /bin/bash
root@12c4596d222f:/# cd /var/jenkins_home/
root@12c4596d222f:/var/jenkins_home# ls
root@12c4596d222f:/var/jenkins_home# touch data-saved
root@12c4596d222f:/var/jenkins_home# ls -l
total 0
-rw-r--r-- 1 root root 0 Apr  9 09:50 data-saved
root@12c4596d222f:/var/jenkins_home# exit
$ 

通常は、/var/jenkins_homeに作成したファイルは、--rmオプションを付けているのでコンテナ終了とともに削除されます。

先ほど作成したデータコンテナを--volumes-fromで指定しているのでファイルは、データコンテナに作成されます。

再度、同じコマンドで新しいコンテナを起動してファイルがあることを確認します。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
a028f489ae18        busybox             "/bin/true"         11 minutes ago      Created                                 jenkins_test
$ docker run -it --rm --volumes-from jenkins_test ubuntu /bin/bash
root@560e5c11911d:/# ls /var/jenkins_home/
data-saved
root@560e5c11911d:/# 

データのバックアップ

オフシャルドキュメントには、コンテナを使ってデータをホストOSにtar.gzする方法が記載されています。

docker commitでimageを作る方法は、volumeのデータは対象外となるようです。

$ docker run -it --rm --volumes-from test ubuntu ls /var/jenkins_home
data-saved
$ docker commit test jenkins_test:3.0
c9ab350ba0dd011a6db95dd725edc43a7a0ceebaccc2c95ffbd6afbe1654bda5
$ docker create --name test3 jenkins_test:3.0
86e771c33d849d51d062ce5a63ab3e39765523f31cda6b4a705c70a6bc54b176
$ docker run -it --rm --volumes-from test3 ubuntu ls /var/jenkins_home
$ 

ドキュメント通りバックアップします。

$ docker run --rm --volumes-from test -v $(pwd):/backup busybox tar cfz /backup/backup.tar.gz /var/jenkins_home
tar: removing leading '/' from member names
$ tar tfz backup.tar.gz
var/jenkins_home/
var/jenkins_home/data-saved
$ 

そして、リストアしてみます。

$ docker run --rm --volumes-from test3 -v $(pwd):/backup ubuntu bash -c "cd /var/jenkins_home && tar xfz /backup/backup.tar.gz --strip 2"
$ docker run -it --rm --volumes-from test3 ubuntu ls /var/jenkins_home/jenkins_home
data-saved
$

おまけ

docker inspectでボリュームのデータを確認することができます。

$ docker inspect test | grep Source
            "Source": "/var/lib/docker/volumes/ef00bd2a22796753979728951c2e802fc2446befbad2f64f3a15be2353775774/_data",
$ sudo ls /var/lib/docker/volumes/ef00bd2a22796753979728951c2e802fc2446befbad2f64f3a15be2353775774/_data
data-saved
$ 

リストア後なので、同じデータがありますがチェックサムが異なるので別データとなっていることがわかります。

$ docker inspect test3 | grep Source
            "Source": "/var/lib/docker/volumes/dc93f38d20643b7aaaf02c554cfeb9786b3feee44ce4ac64430cbfaedbd1b140/_data",
$ sudo ls             "Source": "/var/lib/docker/volumes/d7c133c44da4b03dce4ef8cec8736e4ac4893d4c82ea9c7ddd16fcabe3c17801/_data",
$ sudo ls /var/lib/docker/volumes/d7c133c44da4b03dce4ef8cec8736e4ac4893d4c82ea9c7ddd16fcabe3c17801/_data
$ 

Makefileでできること

Makefileでよく使うパターンを検証しました。

検証用のファイルは、下記の通りです。

ソースがtest1ディレクトリの*.txtでtest2ディレクトリの*.objがターゲットファイルという想定です。

できるだけ、Makefileがシンプルになるように工夫してみました。

$ tree ./test?
./test1
├── a.txt
└── b.txt
./test2
└── a.obj

0 directories, 3 files
$ 

ワイルドカード

ワイルドカードで指定したファイルに対して操作をする場合、$(wildcard)を使います。

$(wildcard 正規表現)でソースファイルのリストを作ることができます。そのリストに対して$(SRC:.txt=.obj)でソースファイルの拡張子を変更したリストを作ることができます。

$ cat Makefile
SRC=$(wildcard test1/*.txt)
OBJ=$(SRC:.txt=.obj)

all:
        @echo src=$(SRC)
        @echo obj=$(OBJ)
$ make
src=test1/a.txt test1/b.txt
obj=test1/a.obj test1/b.obj
$ 

ルールの追加

*.txtから*.objを作るためのルールを追加します。

$ cat Makefile
SRC=$(wildcard test1/*.txt)
OBJ=$(SRC:.txt=.obj)

all: $(OBJ)

%.obj: %.txt
        @echo compile src=$< obj=$@
$ make
compile src=test1/a.txt obj=test1/a.obj
compile src=test1/b.txt obj=test1/b.obj
$ 

ターゲットファイルのディレクトリを変更

ソースがtest1ディレクトリ、ターゲットがtest2ディレクトリで拡張子のルールを使う場合、下記のようにターゲットをtest1ディレクトリに作成してtest2にコピーしました。

コピー先のファイル名を$(addprefix ./test2/, $(notdir $@))でディレクトリ部分のみ変更しています。

$ cat Makefile
SRC=$(wildcard test1/*.txt)
OBJ=$(SRC:.txt=.obj)

all: $(OBJ)

%.obj: %.txt
        @echo compile src=$< obj=$@
        @echo cp -p $@ $(addprefix ./test2/, $(notdir $@))
$ make
compile src=test1/a.txt obj=test1/a.obj
cp -p test1/a.obj ./test2/a.obj
compile src=test1/b.txt obj=test1/b.obj
cp -p test1/b.obj ./test2/b.obj
$ 

仕上げ

echoを実際のコマンドに置き換えて動作をチェックします。 cleanターゲットも追加して動作を確認します。

$ cat Makefile
SRC=$(wildcard test1/*.txt)
OBJ=$(SRC:.txt=.obj)

all: $(OBJ)

%.obj: %.txt
        @echo compile src=$< obj=$@
        touch $@
        cp -p $@ $(addprefix ./test2/, $(notdir $@))

clean:
        -@rm -rf $(OBJ)
$ make -n
echo compile src=test1/a.txt obj=test1/a.obj
touch test1/a.obj
cp -p test1/a.obj ./test2/a.obj
echo compile src=test1/b.txt obj=test1/b.obj
touch test1/b.obj
cp -p test1/b.obj ./test2/b.obj
$ make 
compile src=test1/a.txt obj=test1/a.obj
touch test1/a.obj
cp -p test1/a.obj ./test2/a.obj
compile src=test1/b.txt obj=test1/b.obj
touch test1/b.obj
cp -p test1/b.obj ./test2/b.obj
$ make
make: Nothing to be done for 'all'.
$ make clean
$ make
compile src=test1/a.txt obj=test1/a.obj
touch test1/a.obj
cp -p test1/a.obj ./test2/a.obj
compile src=test1/b.txt obj=test1/b.obj
touch test1/b.obj
cp -p test1/b.obj ./test2/b.obj
$ 

本当は、ターゲットのtest2/*.objtest1/*.txtのタイムスタンプを比較して、test1/*.txtから直接test2/*.objを作りたです。

packerを使う

公開されているboxを使うのは、ちょっと抵抗があるのでpackerを使ってvagrant boxを作りました。

何ができるのか

packerでいろいろなことができるようですが、使っているのは下記です。

  • OSインストール用のISOファイルのダウンロード
  • VirtualBoxVM作成
  • OSのインストール
  • デフォルトユーザの作成
  • vagrant boxの作成

packerにすることで半年に一度のubuntuアップグレードがバージョン番号を変更とISOイメージのチェックサムを変更+packer実行で完了します。

packerのソース

githububuntu 15.10のboxを作るソースをアップしています。

buildersでISOファイルの場所やインストールの操作を書きます。

post-processorsのtypeで作成するタイプを複数指定できます。

使っているのはvagrant boxとatlasの2つですが、AWSのAMIも作れるようです。

atlasとの連携

HashiCorpにatlasのアカウントを作るとローカルPCにVirtualBoxがなくてもOSイメージを作成することができます。

おおよそ下記の手順です。以前に見た時よりメニューはだいぶ変わっていますが...

  • GitHubにアカウントを作りpacker用のリポジトリを作る
  • atlasのvagrant enterpriseにboxを作る
  • altasのpackerにconfigurationを作る

configurationにソースとなるGitHubリポジトリ、ブランチ、ディレクトリ、ファイル名を指定、出力先となるvagrant enterpriseのboxを選択しておくと、GitHubのコミットをトリガにboxが作成されます。

packerで前提となるパッケージのインストールと設定まで行えばvagrantAWSなどメジャーな環境のVMイメージを一気に作ることができるようです。