search
LoginSignup
2

posted at

updated at

Organization

Ansibleでサーバの構成管理を行う

本記事は東京学芸大学 櫨山研究室 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接続を介してプレイブックに記述された処理フローを実行します.
このフローを図にすると以下のようになります.

image.png

コード例

次に実際に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としています.

hosts
[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のプレイブックは単一のファイルではなくロール毎に整理して配置するのが一般的です.

今回は以下のような内容を想定して用意していきます.

  1. サーバのロケールの設定
  2. NTPサーバの設定
  3. パッケージ管理の設定

これらを以下のようなディレクトリ構成で記述します.

.
├── 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に設定する値を記述します.

roles/common/locale/defaults/main.yml
---
locale_timezone: "Asia/Tokyo"
locale_locale: "ja_JP.UTF-8"
locale_keymap: "jp"

そしてtasks/main.ymlで操作を記述します.
この時defaults/main.ymlの値を{{ 変数名 }}で取り出すことができます.

roles/common/locale/tasks/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.ymlRedHat系のディストリビューションで管理したい値を記述しておきます.

roles/common/packages/vars/RedHat.yml
---
required_packages:
  - "@Development Tools"

次に実際の操作をtasks/main.ymlに記述します.

roles/common/packages/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に記述します.

roles/common/ntp/handlers/main.yml
---
- name: Restart chrony
  service:
    name: chronyd
    state: restarted

具体的なNTPサーバの操作についてはtasks/main.ymlに記述します.

roles/common/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の再起動が必要な操作を行ったあとはnotifyhandlers/main.ymlの操作を呼び出します.

site.ymlの設定

ここまで個別のロールやタスクを設定してきました.
Ansibleではどのホストにどのロールを実行するかを設定することができます.

これらの設定をsite.ymlにまとめます.

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を使った構成管理の例をサンプルコード付きで解説しました.

何かに役立てば幸いです🙏

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2