momota.txt

hello, hello, hello, how low?

Ansible でノートPCをセットアップ

CentOS 7 を USB メモリからインストール で書いたが、まっさらなCentOSが手元にあったので ansible を使っていろいろインストールしてみた。

ちょっと前に、Ansible 2.0 Has Arrived という記事も話題になってたし。

ansible は Chef のような構成管理ツール。 システムの設定や、ソフトウェアのデプロイ、オーケストレーションなどが可能なIT自動化ツール。 管理対象ノードが多いほどメリットが大きい。

Chef と比較すると、エージェントレスのアーキテクチャで、Chefのように特定言語(Ruby)を学ぶ必要はなく、YAMLで構成を表現する。 これは、Playbookと呼ばれる。Chef でいうレシピ。

マネージャ側は最近は大抵プリインストールされている python とansible さえインストールすればよい。 クライアント側は、マネージャから SSH アクセスさえできればよい。

これを1回やってファイル群をリポジトリで管理しておけば、環境の複製が楽になるし、Infrastructure as a Code ですね。

まず、環境の説明。

ansible_diag

本稿では、ansible実行サーバをコントローラ (Control Machine)、ansibleによる 管理対象ノードを管理ノード (Managed Node) と呼ぶことにする。

役割 ホスト名 物理マシン IPアドレス
コントローラ (Control Machine) controller mac mini 192.168.11.9/24
管理ノード (Managed Node) managed_node TOSHIBA laptop 192.168.11.14/24

ansible のバージョンは 2.0.0.2

0. 準備

0-1. コントローラ

  1. ansible をインストールする
1
controller$ brew install ansible

0-2. 管理ノード

コントローラ~管理ノード間は、ネットワークを介して管理される。 コントローラから管理ノードへSSHアクセスできる必要があるので、以下の設定を事前に行っておく。

  1. 管理ノードのネットワーク設定
  2. コントローラのSSH公開鍵の登録
1
2
3
4
5
6
7
8
9
10
11
12
13
# コントローラ側no-pass SSH key を生成
controller$ ssh-keygen -t rsa
# mac には ssh-copy-id がないので、scpで公開鍵をコピー
controller$ scp ~/.ssh/id_dsa.pub 192.168.11.14:/home/momota

# 管理ノード側でauthorized_keysの登録
managed_node$ mkdir ~/.ssh
managed_node$ chmod 700 ~/.ssh
managed_node$ cat id_dsa.pub >> ~/.ssh/authorized_keys
managed_node$ chmod 600 ~/.ssh/authorized_keys

# SSH アクセス確認
controller$ ssh 192.168.11.14

1. ansible 設定

まずは、管理ノードへOSアカウント (guestユーザ) を追加作成してみる。

ディレクトリ構成は、Ansible オレオレベストプラクティス を参考にして以下のように作成。

1
2
3
4
5
6
7
8
9
10
11
12
13
controller$ tree laptop_build
laptop_build
|-- centos
|   |-- hosts
|   `-- site.yml
|-- common
|   |-- guest_account
|   |   `-- tasks
|   |       `-- main.yml
|-- private_vars
|   `-- common.yml
`-- vars
    `-- common.yml

それぞれのディレクトリの位置づけは、Ansibleチュートリアルとかを参照するとわかりやすい。

まずは、centos/hosts へ管理ノードのIPアドレスを登録する。 クライアントが複数ある場合は、このエントリーで複数のアドレスを列挙すればよい。

1
2
[laptops]
192.168.11.14

次に、メイン処理を centos/site.yml に記述する。 外部ファイルをインクルードして、roleの実行順序を指定するだけ。 hosts のところで、対象を絞れるが、今回は all。うまく使えば、production用とdevelopment用を使い分けたりグループ単位で実行できる。

1
2
3
4
5
6
- hosts: all
  vars_files:
    - ../vars/common.yml
    - ../private_vars/common.yml
  roles:
    - ../common/guest_account

vars/common.yml には Playbook 共通で使いたい変数を設定している。

private_vars/common.yml には公開したくない変数を設定している。ここでは、guestユーザのパスワードを以下のように指定している。

1
2
---
guest_password: "hogehoge"

こういうパスワードみたいな情報をgithubに上げたくないので、.gitignoreには private_vars/ を追加しておく。

roles には、実際のアカウント追加処理を指定している role ディレクトリcommon/guest_accountを指定する。

common/guest_account/tasks/main.yml には、userモジュールを使って、以下のようにタスクを記述する。

1
2
3
4
5
---
- name: add the user "guest"
  user: name=guest shell=/bin/bash password=
  become: yes
  become_method: sudo

name は任意。タスク内容をコメントとして記述する。

user がモジュール名、それに続いて各モジュールのオプション。

become, become_method で管理ノードで sudo を使って実行することを許可している。

2. ansible 実行

クライアント側で事前にユーザの確認。 guest ユーザは存在しない。

1
managed_node$ grep guest /etc/passwd

まずは、--check オプションを付けてテスト実行(dry run)。実際の構成変更はせず、 Playbook のシンタックスチェックなどを実施する。

1
2
3
4
5
6
7
8
9
10
11
12
13
controller$ ansible-playbook -i centos/hosts centos/site.yml -K --check
SUDO password:

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

TASK [setup] *******************************************************************
ok: [192.168.11.14]

TASK [../common/guest_account : add the user "guest"] **************************
changed: [192.168.11.14]

PLAY RECAP *********************************************************************
192.168.11.14              : ok=1    changed=1    unreachable=0    failed=0

問題ないようなので実行してみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
controller$ ansible-playbook -i centos/hosts centos/site.yml -K
SUDO password:

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

TASK [setup] *******************************************************************
ok: [192.168.11.14]

TASK [../common/guest_account : add the user "guest"] **************************
changed: [192.168.11.14]

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

クライアント側で事後確認してみると、ユーザができている。

1
2
managed_node$ grep guest /etc/passwd
guest:x:1001:1001::/home/guest:/bin/bash

3. 他にもいろいろとインストールする

ruby や zsh などもインストールする。 インストール対象のプロダクト毎に role を作っている。

role の粒度がいまいちどれくらいにしたらよいのかが分からない。

たとえば、ruby role には ruby のインストールだけにとどめておくべきか、 rbenv のような関連ツールまで 1 セットで記述するのが良いか。

まあ、使いながらやりやすい粒度を模索する、でも良いと思う。

また、OS 毎の差異を吸収するため、common/role/HOGE/tasks/ 以下に main.ymlを置いて、 それぞれのOS毎のymlをインクルードした。 ただ、centos/的な大本からディレクトリを分けて、main.ymlでOS判定と 条件分岐しないような配置でも良かったかもなとも思っている。

以下のようなディレクトリ構成となった。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
controller$ tree laptop_build
laptop_build
|-- centos
|   |-- hosts
|   `-- site.yml
|-- common
|   |-- dotfiles
|   |   |-- meta
|   |   |   `-- main.yml
|   |   `-- tasks
|   |       `-- main.yml
|   |-- guest_account
|   |   `-- tasks
|   |       `-- main.yml
|   |-- ruby
|   |   |-- meta
|   |   |   `-- main.yml
|   |   `-- tasks
|   |       `-- main.yml
|   |-- tmux
|   |   `-- tasks
|   |       |-- centos.yml
|   |       |-- main.yml
|   |       `-- ubuntu.yml
|   |-- vim
|   |   `-- tasks
|   |       `-- main.yml
|   `-- zsh
|       `-- tasks
|           |-- centos.yml
|           |-- main.yml
|           `-- ubuntu.yml
|-- private_vars
|   `-- common.yml
`-- vars
    `-- common.yml

公式ドキュメントを見つつ、yum や git モジュールを利用した。

中身の説明は、体力が切れたので割愛。 詳細は、momota/laptop-build を参照。

Comments