本記事は東京学芸大学 櫨山研究室 Advent Calendar 2020の20日目の記事になります.
はじめに
Ansibleは構成管理ツールの一つです.
本記事ではAnsibleを使ったインフラ構築の自動化について扱います.
構成管理ツールを導入するメリット
そもそも構成管理ツールの導入にどのようなメリットがあるのかを簡単にまとめておきます.
構成管理ツールが必要となった大きな背景としてはクラウドの登場があります.
クラウドの登場によりネットワークやストレージなどのインフラリソースの変更がソフトウェアを通して行えるようになり,インフラリソースのライフサイクルが短くかつ頻繁に変更されるようになりました.
インフラリソースのライフサイクルが短くかつ頻繁に変更されるということは,システムの構築管理の変更頻度も増大します.変更頻度の多いクラウド環境のシステムの構築管理を手動で行うことは運用コストを肥大化させることになり非効率です.
そこで構成管理ツールの出番という訳です.
オンプレミス環境で構成管理ツールを導入するメリット
ここまでだと構成管理ツールはクラウド環境のためのモノのような印象を受けるかもしれません,しかしオンプレミス環境でも構成管理ツールを導入することで多くのメリットを享受することができます.
ここでは特に研究室のサーバ管理活動で構成管理ツールを導入するメリットを載せておきます.
所属研究室では大学の講義で開発するWebアプリケーションのデプロイ環境や研究活動のために物理サーバを購入して管理しています.
まず前提として研究室のサーバは壊れます.
今年は2台がお陀仏になりました(泣)
壊れるたびに既存のインフラ環境を整えることは結構しんどいですし,動作していたシステムにはダウンタイムが発生します.
これらのことはなるべく早く対処したいです.
構成管理ツールを導入することによって頻繁にシステムの構築と破棄を繰り返しても同じクオリティの環境を提供できます.
なので機器が購入してからの環境の復帰が高速にできます.
もう一つのメリットとしてはInfrastructure as Code (IoC)の仕組みを導入できることです.
Infrastructure as Codeの定義は以下の通りです.
インフラの構成管理をコードで記述し,ソフトウェア開発で実施されてきた開発プロセスをインフラシステム,アプリケーション,ミドルウェアのデプロイメントやコンフィギューレーションの管理に適用すること.
Infrastructure as Codeの考え方は端的に言ってしまえば,「アプリケーション開発のノウハウをインフラの管理でも応用しましょう」というものです.
これによりGitHubなどを利用してバージョン管理された状態でインフラ構成を保管することもできます.
2~4年の周期で大きく人が入れ替わってしまう研究室のサーバ管理活動において,引き継ぎを容易にするためにもこの仕組みは大事です.
Ansibleの動作原理
ここまでダラダラと構成管理ツールを導入するメリットについて解説しましたが,ここから本題のAnsibleについて書こうと思います.
Ansibleでは大きくイベントリとプレイブックというファイルを利用します.
イベントリは操作対象を記述するファイル,プレイブックは具体的な操作内容を記述するファイルになります.
Ansibleではクライアント(コントロールノード・管理サーバとも呼ばれます)からサーバ(ターゲットノード)にssh接続を介してプレイブックに記述された処理フローを実行します.
このフローを図にすると以下のようになります.
コード例
次に実際にAnsibleを使った構成管理を行ってみます.
ここではVagrantを使って立ち上げた仮想マシン(centOS 7)に対しAnsibleで環境構築をします.
Ansibleのインストール方法やVagrantのインストール方法などは公式サイトや他の情報を参考にしてください🙇♂️
Ansible ドキュメント(日本語), https://docs.ansible.com/ansible/2.9_ja/index.html
Vagrabt, https://www.vagrantup.com/
仮想マシンの用意
まず仮想マシンのテンプレートとなるBox
を追加します.
vagrant box add centos/7
プロバイダにはvirtualbox
を選択します.
次に作業を行うディレクトリansible-sample
を作成して仮想マシンの管理ファイルとなるVagrantfile
を作成します.
mkdir ansible-sample && cd ansible-sample
vagrant init centos/7
これでansible-sample
ディレクトリ配下にVagrantfile
ができました.
vagrant up
コマンドで仮想マシンを起動しましょう.
vagrabt up
イベントリの用意
ansibleのイベントリファイルを用意しましょう.
ファイル名はhosts
とします.
Vagrantはデフォルトではlocalhostの2222
ポートでssh接続を受け付けます.
今回はあくまでサンプルなのでホスト名をsample
としています.
[sample]
127.0.0.1
[sample:vars]
ansible_port=2222
ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key
ansible_become=yes
ansible_user=vagrant
ansible_become_methods=su
ansible_become_user=root
プレイブックの用意
実際にプレイブックを用意していきます.
Ansibleのプレイブックは単一のファイルではなくロール毎に整理して配置するのが一般的です.
今回は以下のような内容を想定して用意していきます.
- サーバのロケールの設定
- NTPサーバの設定
- パッケージ管理の設定
これらを以下のようなディレクトリ構成で記述します.
.
├── Vagrantfile
├── hosts
├── roles
│ └── common
│ ├── locale // 1. サーバのロケールの設定
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── ntp // 2. NTPサーバの設定
│ │ ├── handlers
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ └── packages // 3. パッケージ管理の設定
│ ├── tasks
│ │ └── main.yml
│ └── vars
│ └── RedHat.yml
├── site.yml
└── webservers.yml
サーバのロケールの設定
まずdefaults/main.yml
に設定する値を記述します.
---
locale_timezone: "Asia/Tokyo"
locale_locale: "ja_JP.UTF-8"
locale_keymap: "jp"
そしてtasks/main.yml
で操作を記述します.
この時defaults/main.yml
の値を{{ 変数名 }}
で取り出すことができます.
---
- name: Setup timezone
timezone:
name: "{{ locale_timezone }}"
- name: Setup locale
command: localectl set-locale LANG={{ locale_locale }}
changed_when: false
- name: Setup keymap
command: localectl set-keymap {{ locale_keymap }}
changed_when: false
パッケージ管理の設定
次にパッケージ管理の設定をします.
パッケージ管理は対象とするLInuxディストリビューションによって異なるので柔軟性を持たせたいです.
今回対象とする仮想マシンはcentOS
なのでRedHat
系になります.
そこでまずvars/RedHat.yml
にRedHat
系のディストリビューションで管理したい値を記述しておきます.
---
required_packages:
- "@Development Tools"
次に実際の操作をtasks/main.yml
に記述します.
---
- name: Add the OS specific variables
include_vars: "{{ ansible_os_family }}.yml"
- name: Update yum packages
yum:
name: "{{ item }}"
state: present
update_cache: yes
loop:
- "epel-release"
- "*"
when: ansible_os_family == 'RedHat'
- name: Instrall the required packages
package:
name: "{{ required_packages }}"
state: present
ansible_os_family
の情報を利用してvar
配下から読み取るymlファイルを変化させるのがポイントです.
Debian系ならDebian,yml
を用意することで柔軟な記述が可能です.
NTPサーバの設定
chorony
を使ったNTPサーバの設定を行います.
NTPサーバの設定はchoronyの再起動が必要なタスクになります.
この再起動の操作についてはansibleではhandlers/main.yml
に記述します.
---
- name: Restart chrony
service:
name: chronyd
state: restarted
具体的なNTPサーバの操作についてはtasks/main.yml
に記述します.
---
- name: Install chorony
package:
name: chrony
state: present
when: not (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
become: yes
- name: Disable default servers
replace:
dest: /etc/chrony.conf
regexp: '^(server \d+.centos.pool.ntp.org iburst)'
replace: '# \1'
become: yes
- name: Add ntp servers
blockinfile:
dest: /etc/chrony.conf
content: |
# ntp servers
server ntp.nict.jp iburst
# disabel ntp server only use client
port 0
notify:
- Restart chrony
become: yes
- name: Execute chorony makestep
command: chronyc -a makestep
changed_when: false
become: yes
- name: Enable chorony service
service:
name: chronyd
enabled: yes
become: yes
choronyの再起動が必要な操作を行ったあとはnotify
でhandlers/main.yml
の操作を呼び出します.
site.ymlの設定
ここまで個別のロールやタスクを設定してきました.
Ansibleではどのホストにどのロールを実行するかを設定することができます.
これらの設定をsite.yml
にまとめます.
- hosts: sample
roles:
- common/locale
- common/packages
- common/ntp
実行
それでは実行しましょう,といきたいところですが文法的な間違いがないかやタスクの確認をしておきましょう.
文法のチェックとタスクの一覧の確認は以下のコマンドで行うことができます.
# 文法チェック
ansible-playbook -i hosts site.yml --syntax-check
# タスクの一覧を確認
ansible-playbook -i hosts site.yml --list-tasks
playbook: site.yml
play #1 (sample): sample TAGS: []
tasks:
common/locale : Setup timezone TAGS: []
common/locale : Setup locale TAGS: []
common/locale : Setup keymap TAGS: []
common/packages : Add the OS specific variables TAGS: []
common/packages : Update yum packages TAGS: []
common/packages : Instrall the required packages TAGS: []
common/ntp : Install chorony TAGS: []
common/ntp : Disable default servers TAGS: []
common/ntp : Add ntp servers TAGS: []
common/ntp : Execute chorony makestep TAGS: []
common/ntp : Enable chorony service TAGS: []
では実際に実行してみましょう.
以下のコマンドで実行可能です.
# リハーサル
ansible-playbook -i hosts site.yml --check
# 本番実行
ansible-playbook -i hosts site.yml
最終的に以下のよう出力でエラーなく実行できていれば問題ありません.
PLAY RECAP **********************************************************************************************************************************************************
127.0.0.1 : ok=12 changed=6 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
なおスキップされていたタスクはTASK [common/ntp : Install chorony]
でchoronyのインストールでした.
おわりに
本記事では構成管理ツールの概要からAnsibleを使った構成管理の例をサンプルコード付きで解説しました.
何かに役立てば幸いです🙏
参考
- Ansible実践ガイド 第3版 (impress top gear) , https://www.amazon.co.jp/Ansible%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E7%AC%AC3%E7%89%88-impress-top-gear/dp/4295007641/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=ansible&qid=1609311074&sr=8-1
- Playbookの使用 - ベストプラクティス, https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks_best_practices.html