クラスタ構築(3)リソースの登録と運用コマンド

Pacemaker + Corosync で構成したクラスタ内にリソースを登録し、サービスの冗長化を行う。

リソースの登録

  • 仮想IPリソースの登録
    リソースタイプocf:heartbeat:IPaddr2は、仮想IPv4アドレスを意味する。以下の例では、30秒ごとにリソースの監視を行う。
pcs resource create myvip ocf:heartbeat:IPaddr2 ip=192.168.0.11 cidr_netmask=24 op monitor interval=30s
  • Systemdリソースの登録
    以下の例では、10秒ごとにリソースの監視を行い、20秒で動作失敗と判断する。
pcs resource create httpd systemd:httpd params op monitor interval=10s timeout=20s
  • グループ登録
    複数のリソースを1つのグループに登録することができる。
    グループに登録すると、各リソースの起動や乗り換えは、グループ単位で行われる。
pcs resource group add mygroup enq_ext_vip myvip httpd

リソースの制約

各リソースには、起動順序や起動場所、起動条件などのリソース制約を課すことができる。

  • 起動場所の制約
    以下の例では、httpdリソースはホストcluster01で優先して起動する。
pcs constraint location httpd prefers cluster01
  • 起動順序の制約
    以下の例では、httpdリソースはmariadb-cloneの起動のあとに起動する。
pcs constraint order mariadb-clone then httpd
  • 起動条件の制約
    以下の例では、httpdリソースはマスターDBが起動している場所で起動する。
pcs constraint colocation add httpd with master mariadb-clone

運用コマンド

Pacemaker + Corosync によるクラスタ構成の監視および運用で使用するコマンドは以下の通り。

  • クラスタの起動と終了
pcs cluster start --all
pcs cluster stop --all
  • クラスタの状態監視
# 状態表示
pcs status
# リアルタイム状態表示
crm_mon
# クラスタ間通信の状態表示
corosync-cfgtool -s
# 設定確認
pcs config

クラスタ構築(2)MySQL/MariaDBレプリケーション

前回PacemakerCorosync を用いてクラスタ環境のセットアップを行った。今回は、MySQL/MariaDBをリソースに設定し、レプリケーション設定を行う。

MySQL/MariaDBレプリケーション

レプリケーションの実行環境を以下のように定義する。

項目 内容
マスター 192.168.0.11
スレーブ 192.168.0.12
対象データベース mydatabase
レプリケーションユーザ repl
レプリケーションユーザパスワード replpass

レプリケーションユーザは、REPLICATION SLAVE もしくは REPLICATION CLIENT の権限を必要とする。なお、Pacemaker と Corosyncでレプリケーションを行う場合は、これに加えて、GRANT, SUPER, RELOAD, PROCESS の権限も必要とする。

レプリケーション設定

マスターDBに対して以下の操作を行う。

  • server-idの設定
vi /etc/my.cnf

# レプリケーション対象DBの指定
replicate-do-db=mydatabase
# サーバ固有のIDを設定
server-id=1
# バイナリログを出力
log-bin=mysql-bin
  • データベースをロック
FLUSH TABLES WITH READ LOCK;
  • データベースの内容をダンプファイルに吐き出し
mysqldump --skip-lock-tables -h 192.168.0.11 -u repl -preplpass mydatabase > /tmp/database.sql
  • バイナリログの状態を確認
    スレーブDBにマスターDBのバイナリログの位置を指定するために事前に確認しておく。
SHOW MASTER STATUS;

+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      245 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

スレーブDBに対して以下の操作を行う。

  • server-idの設定
vi /etc/my.cnf

# レプリケーション対象DBの指定
replicate-do-db=mydatabase
# サーバ固有のIDを設定
server-id=2
# バイナリログを出力
log-bin=mysql-bin
# マスターDBの更新もバイナリログに記録する
log_slave_updates
  • 既存のDBを削除と再作成
DROP DATABASE IF EXISTS mydatabase;
CREATE DATABASE IF NOT EXISTS mydatabase;
  • ダンプファイルの読み込み
    さきほどダンプしたマスターDBのダンプファイルをスレーブDBに読み込ませる。
mysql -u repl -h 192.168.0.12 -preplpass mydatabase < /tmp/database.sql
  • マスターDBの指定
CHANGE MASTER TO MASTER_HOST='192.168.0.11', MASTER_USER='repl', MASTER_PASSWORD='replpass', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=245;
  • スレーブの開始
SLAVE START;

最後にマスターDBで以下の操作を行う

  • データベースのロックを解除
UNLOCK TABLES;

Pacemaker と Corosyncを用いたレプリケーション設定

Pacemaker と Corosync を用いてレプリケーションを設定する場合は、以下の手順で行う。

  • DBリソースの登録
    mariadb-replという名前でDBリソースを登録する。
pcs resource create mariadb-repl ocf:heartbeat:mysql binary=/usr/bin/mysqld_safe pid=/var/run/mariadb/mariadb.pid datadir=/var/lib/mysql log=/var/log/mariadb/mariadb.log replication_user=repl replication_passwd=replpass op start interval=0 timeout=120s op stop interval=0 timeout=120s op monitor interval=20s timeout=30s op monitor interval=10s role=Master timeout=30s op monitor interval=30s role=Slave timeout=30s op promote interval=0 timeout=120s op demote interval=0 timeout=120s op notify interval=0 timeout=90s
  • レプリケーションリソースの登録
    mariadb-cloneという名前でレプリケーションリソースを登録する。
pcs resource master mariadb-clone mariadb-repl master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true"
  • リソース制約の設定
    192.168.0.11がマスターDBとなるようにリソース制約を設定する。
pcs constraint location mariadb-clone prefers 192.168.0.11

クラスタ構築(1)Pacemaker + Corosync の設定

障害が発生した場合でも継続してサービスを稼働可能な冗長性の高いサーバを構築する手法の1つに、複数のサーバを連携させるHAクラスタリングが存在する。今回は、PacemakerCorosyncという2つのOSSを使用して、HAクラスタリングを実現させる。1つのサーバに障害が発生した場合でも他方のサーバで処理をカバーするために、ダウンタイムを減少させることができる。

Pacemakerは、死活監視を行って、障害の発生を検知するサービスで、障害発生時にはシステムチェンジを行って待機系が処理を継続する。対象となるネットワークインタフェースや各サービスなどをリソースと呼び、リソース単位で障害検知や障害時の挙動を指定できる。ただし、Pacemakerは、Heartbeatプロジェクトの一部機能が切り出されたサービスであるため、これ単独では機能しない。そこで、ノードの監視を行うCorosyncというサービスと組み合わせて使用することが多い。

環境構築

Pacemaker + Corosync でクラスタを構築する手順は以下の通り。

必要なパッケージのインストール

yum install -y pacemaker, corosync, pcs, elfutils-libelf-devel

haclusterユーザの追加

PacemakerやCorosyncを制御するpcsコマンドを実行するためのユーザを作成する。

useradd hacluster  
passwd hacluster  

hostsファイルの編集

ホスト名でノードを指定できるようにするために、hostsファイルを編集する。今回の例では、cluster01 と cluster02 の2つのノードが存在するものとする。

vi /etc/hosts
192.168.0.11 cluster01
192.168.0.12 cluster02

クラスタ設定の初期化

念のため全てのクラスタ設定を一度初期化する。

pcs cluster destroy

クラスタサービスの起動

systemctl start pcsd
systemctl enable pcsd

クラスタのセットアップ

以下の作業は、クラスタを構成する複数のサーバのうちプライマリとなる1つのサーバのみで行う。

ユーザの認証

各ノードに対して、pcsコマンドを実行するhaclusterユーザの認証を行う。一度認証すると次から認証は求められない。なお、トークンなどの認証情報は/var/lib/pcsd/tokensに格納される。

pcs cluster auth cluster01 cluster02 -u hacluster -p hacluster

クラスタの作成

クラスタの生成を行う。今回の例では、cluster01 と cluster02 の2つのノードから構成される mycluster というクラスタを生成するものとする。

pcs cluster setup --name mycluster cluster01 cluster02

クラスタの開始

pcs cluster start --all
pcs cluster enable --all

STONITH機能の停止

クラスタ構成自体に異常が起きた場合の影響を最小限に抑えるために、異常が起きたノードのシャットダウンを行うSTONITH機能が存在するが、今回はとりあえず機能の停止を行い、STONITH機能については別途設定を行う。

pcs property set stonith-enabled=false

Ansible(4)データベース操作

mysql_user

データベースユーザの追加と削除を行う

パラメータ 必須 デフォルト 内容
name yes ユーザ名
password no パスワード
priv no 権限
state no present 状態 (present, absent)
- name: "create database user with name '{{ zabbix.mariadb_user }}' and password '{{ zabbix.mariadb_pass }}' with all database privileges"
  mysql_user: name="{{ zabbix.mariadb_user }}" password="{{ zabbix.mariadb_pass }}" priv='*.*:ALL'

Ansible(3)システム管理

command

コマンドの実行を行う。コマンド内にアスタリスク(*)が含まれるコマンドに関しては、shellモジュールを使用する。

- name: "configure the fping programs"
  command: chdir=/usr/local/src/fping-{{ fping.version }} ./configure

chdir=を指定するとディレクトリに遷移してから任意のコマンドを実行する。commandモジュールの実行は冪等性を保てない場合があるため、Ansibleの他のモジュールで代替可能である場合は、そちらを使うことが望ましい。

make

makeを実行する

パラメータ 必須 デフォルト 内容
chdir yes makeを実行する前に遷移するディレクトリ
target no ターゲット (install)
- name: "make the Apache programs"
  make: chdir=/usr/local/src/httpd-{{ httpd.version }}

- name: "install the Apache programs"
  make: chdir=/usr/local/src/httpd-{{ httpd.version }} target=install

user

ユーザアカウントの管理を行う

パラメータ 必須 デフォルト 内容
name yes ユーザ名
password no パスワード
home no ホームディレクトリ
shell no 使用するシェル
- name: "add the user 'hacluster'"
  user: name=hacluster password={{ pacemaker.hacluster_password | password_hash('sha512') }}

cron

crontabの編集を行う

パラメータ 必須 デフォルト 内容
name no ディスクリプション
month no ジョブが実行される月
day no ジョブが実行される日
hour no ジョブが実行される時
minute no ジョブが実行される分
job no 実行されるジョブ
- name: "add crontab to execute {{ centos_repo.sync_sh }}"
  cron: name="syncrepo" minute="0" job="{{ centos_repo.sync_sh }}"

selinux

SELinuxの状態とポリシーを変更する

パラメータ 必須 デフォルト 内容
state no 状態 (enforcing, permissive, disabled
- name: "disable SELinux"
  selinux: state=disabled
  when: selinux_conf.stat.exists

timezone

タイムゾーンを指定する

パラメータ 必須 デフォルト 内容
name no タイムゾーン
- name: "set timezone to Asia/Tokyo"
  timezone: name=Asia/Tokyo

sysctl

sysctl.confの編集を行う

パラメータ 必須 デフォルト 内容
name yes 項目名
value yes (インストール) present, installed, latest (削除) absent, removed
state yes present 状態 (present, absent)
reload no yes sysctlを再起動
# 監視可能なファイル数の上限を設定
- name: "set fs.inotify.max_user_watches to {{ lsyncd.inotify_max_user }} in /etc/sysctl.conf"
  sysctl: name=fs.inotify.max_user_watches value={{ lsyncd.inotify_max_user }}

yum

yumパッケージの管理を行う

パラメータ 必須 デフォルト 内容
name yes パッケージ名
state no present (インストール) present, installed, latest (削除) absent, removed
enablerepo no 有効化するリポジトリID
disable_gpg_check no GPG Keyチェックを無効化
- name: "install the latest version of curl, policycoreutils, openssh-server, openssh-clients"
  yum: name={{ item }} state=latest
  with_items:
    - curl
    - policycoreutils
    - openssh-server
    - openssh-clients
- name: "upgrade all packages"
  yum: name=* state=latest
# @Development toolsはstate=presentを指定
- name: "install the latest version of @Development tools"
  yum: name="@Development tools" state=present

yum_repository

yumリポジトリの追加と削除を行う

パラメータ 必須 デフォルト 内容
name yes リポジトリID
description no ディスクリプション
baseurl no リポジトリURL
gpgcheck no no GPGチェックの有無
enabled no yes 有効化
- name: "add epel repository"
  yum_repository: name=epel description=epel baseurl="{{ epel_repo }}" enabled=no

rpm_key

yumリポジトリのGPG Keyの追加や削除を行う

パラメータ 必須 デフォルト 内容
key yes GPG key (URL, パス)
state no present 状態(present, ansent)
- name: "import a rpm key from a url"
  rpm_key: state=present key="{{  jenkins.repokey  }}"

pear

pear/peclパッケージの管理を行う

パラメータ 必須 デフォルト 内容
name yes パッケージ名
state no present (インストール) present, latest (削除) absent
- name: "install MongoDB pecl package"
  pear: name=pecl/mongodb state=present

pip

Pythonライブラリの管理を行う

パラメータ 必須 デフォルト 内容
name yes ライブラリ名
state no present (インストール) present, latest, forcereinstall (削除) absent
- name: "install pip package"
  pip: name=pip state=forcereinstall

- name: "install awscli package"
  pip: name=awscli

service

サービスの管理を行う

パラメータ 必須 デフォルト 内容
name yes パッケージ名
state no 状態 (started, stopped, restarted, reloaded)
enabled no ブート時起動 (yes, no)
- name: "start service sshd, if not running"
  service: name=sshd state=started enabled=yes

systemd

サービスの管理を行う

パラメータ 必須 デフォルト 内容
daemon-reload no デーモンの再読み込み
- name: reload systemd daemon
  systemd: daemon-reload=yes

alternatives

代替可能なプログラムの管理を行う

パラメータ 必須 デフォルト 内容
name yes リンク名
path yes リンク先
# メールサービスにpostfixを選択
- name: "set postfix for mta"
  alternatives: name=mta path=/usr/sbin/sendmail.postfix

Ansible(2)ファイル操作

file

ファイルの属性を指定する

パラメータ 必須 デフォルト 内容
path yes 変更するファイル
mode no ファイルのパーミッション
state no file 状態 (file, link, directory, hard, touch, absent)
owner no 所有ユーザ
group no 所有グループ

ファイルのパーミッションを変更する

パーミッションは、企業表記も数値表記もどちらも可能である。

- name: "set user id to {{ fping.bin }}"
  file: dest={{ fping.bin }} mode=4755
- name: "add mode the {{ centos_repo.sync_sh }} file executable"
  file: dest={{ centos_repo.sync_sh }} mode="ugo+x"

ファイル/ディレクトリを作成する

- name: "create apache log file directory"
  file: path="{{ httpd.log }}" state=directory owner=root group=root mode=0755

ファイル/ディレクトリを削除する

- name: "delete the Apache source files"
  file: path=/usr/local/src/httpd-{{ httpd.version }} state=absent

copy

リモートサーバにファイルをコピーする

パラメータ 必須 デフォルト 内容
src no コピー元ファイル
dest yes コピー先ファイル
mode no ファイルのパーミッション
owner no 所有ユーザ
group no 所有グループ
remote_src no no コピー元ファイルがリモートサーバにあるかどうか

Ansible実行元のサーバからリモートサーバへファイルをコピーする場合、テンプレートファイルは、各Role直下のfilesディレクトリに設置する。remote_srcディレクティブを使うことで、リモートサーバ内でのファイルの移動やコピーを実現可能。ただし、再帰的なコピーに対応していないことに注意が必要である。with_fileglobディレクティブで特定のファイル名のみコピー可能である。

- name: "add a {{ httpd.logrotate }} if it does not exist"
  copy: src=httpd dest={{ httpd.logrotate }} owner=root group=root mode=0644

blockinfile

テキストブロックの挿入や削除を行う

パラメータ 必須 デフォルト 内容
path yes 変更するファイル
backup no no バックアップの有無
block no 挿入するブロック
maker no # {mark} ANSIBLE MANAGED BLOCK 区切り文字
insertafter no EOF 挿入位置

挿入したブロックの前後には区切り文字(デフォルトは、# BEGIN ANSIBLE MANAGED BLOCK, # END ANSIBLE MANAGED BLOCK)が挿入される。単一のファイルに複数のブロックを挿入する場合は、各ブロックに異なる区切り文字を指定しないと、他方のブロックの処理で内容を上書いてしまう可能性がある。また、ファイルによって、コメントアウトの文字(#, -, //)が異なるため、ファイルの指定に合わせて区切り文字の指定を変更する必要がある。

ブロックの挿入位置は、デフォルトはEOFつまりファイル最後に追加される形となるが、insertafterディレクティブによって任意の位置を指定することが可能である。

- name: "add a block to {{ ansible.config }} if it does not exist"
  blockinfile:
    dest: "{{ ansible.config }}"
    backup: yes
    block: |
      [ssh_connection]
      control_path = %(directory)s/%%h-%%r
      ssh_args = -o UserKnownHostsFile=/dev/null
      [defaults]
      host_key_checking = False
      log_path=/var/log/ansible.log
      hash_behaviour = merge

lineinfile

特定の行の挿入や削除を行う

パラメータ 必須 デフォルト 内容
path yes 変更するファイル
backup no no バックアップの有無
line no 挿入する行
- name: "add fping location in {{ zabbix.conf }}"
  lineinfile: 
     dest: "{{ zabbix.conf }}"
     line: "FpingLocation={{ fping.bin }}"
     backup: yes

replace

文字の置換を行う

パラメータ 必須 デフォルト 内容
path yes 変更するファイル
regexp yes 置換対象の文字列
replace no 置換後の文字列
backup no no バックアップ

置換対象の文字列は、正規表現で指定することが可能である。

正規表現 内容
^ 行頭
.* 任意の文字列
$ 行末
- name: "edit nginx listen port in {{ gitlab.conf }}"
  replace: dest="{{ gitlab.conf }}" regexp='.*unicorn\[\'port\'\].*$' replace="unicorn['port'] = {{ gitlab.unicorn_port }}" backup=yes

template

jinja2形式のテンプレートファイルをリモートサーバに設置する

パラメータ 必須 デフォルト 内容
src yes 変更するファイル
dest no no バックアップの有無

テンプレートファイルは、各Role直下のtemplatesディレクトリに設置する。また、変数をファイル内に埋め込むことが可能である。

#
# Server-Pool Management (MPM specific)
# 
<IfModule mpm_prefork_module>
    StartServers			{{ httpd.start_servers }}
    MinSpareServers			{{ httpd.min_spare_servers }}
    MaxSpareServers			{{ httpd.max_spare_servers }}
    MaxRequestWorkers		{{ httpd.max_request_workers }}
    ServerLimit				{{ httpd.server_limit }}
    MaxConnectionsPerChild	{{ httpd.max_connections_per_child }}
</IfModule>
- name: "put {{ gitlab.httpd_conf }}"
  template: src=gitlab.conf.j2 dest="{{ gitlab.httpd_conf }}"

get_url

HTTPやFTPなどでファイルを取得する。

パラメータ 必須 デフォルト 内容
dest yes ダウンロード先
timeout no 10 タイムアウト
url yes 取得先URL
force no no 毎回取得を行う (yes, no)
- name: "download the fping source files"
  get_url: dest=/tmp force=yes timeout={{ get_url_timeout }} url="{{ fping.source_url }}"

unarchive

アーカイブファイルを展開する

パラメータ 必須 デフォルト 内容
remote_src no no 既に存在するリモート先のアーカイブファイル
dest yes 展開先の絶対パス
- name: "unpacks the fping source files"
  unarchive: remote_src=yes src=/tmp/fping-{{ fping.version }}.tar.gz dest=/usr/local/src

CentOS7(2)ロケールとネットワークの設定

Localeの設定

Localeを設定することで、特定に地域に適した言語や時刻、通貨などを設定することができる。Localeの設定や確認には、localectlコマンドやlocaleコマンドを使用する。Localeを表す複数の環境変数が存在する。

環境変数 意味 備考
LANG デフォルトロケール LC_で始まる全ての環境変数に適用される
LC_CTYPE フォールバックロケール 希望する複数のロケールを指定できる
LC_NUMERIC 数字の区切り
LC_TIME 日付形式
LC_COLLATE 正規表現などの照合順序
LC_MONETARY 通貨
LC_MESSAGES メッセージ
LC_ALL トラブルシューティング LANG や LC_よりも優先される変数

localctl

Localeの確認や設定を行う。

  • localeの確認
    # localectl
       System Locale: LANG=en_US.utf8
       VC Keymap: n/a
       X11 Layout: n/a
    

  • Localeの設定

    # localectl set-locale LANG=en_US.utf8
    

locale

Localeの確認を行う。

  • Locale環境変数の表示
    # locale
    LANG=en_US.utf-8
    LC_CTYPE="en_US.utf-8"
    LC_NUMERIC="en_US.utf-8"
    LC_TIME="en_US.utf-8"
    LC_COLLATE="en_US.utf-8"
    LC_MONETARY="en_US.utf-8"
    LC_MESSAGES="en_US.utf-8"
    LC_PAPER="en_US.utf-8"
    LC_NAME="en_US.utf-8"
    LC_ADDRESS="en_US.utf-8"
    LC_TELEPHONE="en_US.utf-8"
    LC_MEASUREMENT="en_US.utf-8"
    LC_IDENTIFICATION="en_US.utf-8"
    LC_ALL=en_US.utf-8
    

  • インストール済みのLocaleの確認

    # locale -a
    

ネットワーク設定

CentOS7からは、ifconfigやnetstatなどのネットワークコマンドが非奨励となり、iproute2パッケージに含まれる、ipコマンドやssコマンドを使うことが奨励されている。また、ネットワークの設定も、これまでのように設定ファイルを直接書き換えるのではなく、nmtuiコマンドを使用して設定変更することが奨励されている。

nmtui

内容 CentOS6 CentOS7 CentOS7(略記)
IP ifconfig ip link ip l
IPアドレスの参照 ifconfig ip addr ip a
ルーティングの参照 route ip route ip r
ARPの参照 arp ip neigh ip n
ne netstat ss

Zabbix(4)設定値チューニング

Zabbixで多くの項目を監視対象にしている場合、インストール時のデフォルトの設定値のままだと処理が追いつかず、指定した間隔で項目を取得できなかったり、そもそもZabbixサーバが起動しないこともある。

欠損グラフの例

例えばこのように取得データに欠損が出たり、

XXX is unreachable for 5 minutes

などのエラーが出たり、

更新待ちアイテムのキュー

キューに未処理の更新待ちアイテムが大量に溜まってしまう場合がある。このときに、Zabbixのプロセスの稼働状況をグラフで確認すると、Data gathering processesの値が大きくなっていることが分かる。

データ収集プロセスグラフ

zabbix_server.confのデフォルトの設定値のままだと、処理すべきデータ量に処理能力が追いつかない場合があるため、以下の項目などの設定値を調整する必要がある。

設定項目 内容 デフォルト値 チューニング後の例 備考
StartPollers Zabbixサーバのプロセス数 10 20 公式ドキュメント内には、「原則として、このパラメータの値はできる限り小さくします。」との記述あり
StartDBSyncers ZabbixサーバからDBにアクセスする際の接続数 4 8
CacheSize キャッシュサイズ 32M 128M

Ansible(1)Ansibleとは

Ansibleは、Infrastructure as Codeを実現可能な自動構成管理ツール。Hedhatが提供するオープンソースソフトウェアである。PuppetやChefと違いエージェントレスで動作し、Ansible自体は中央サーバや実行先のサーバの状態の情報を保有しない。SSHで各サーバにログインし、任意の処理を実行する。Infrastructure as Codeの概念を実現するために、Ansibleでは、同じコードを何度実行しても同じ結果となる、冪等性を重視している。

Ansibleは、各機能を司るコマンド群であるModuleと、それを組み合わせたスクリプトであるPlaybookから構成される。Playbookは、再利用性を高めるために、機能別にRoleに分けて管理される。また、これらのスクリプトは、YAML形式で記述され、変数や分岐処理などは、Pythonのテンプレートエンジンであるjinja2が使用される。AnsibleはPythonで動作するため、Ansibleを実行させるサーバも、実際に処理を行う対象ホストにもPythonがインストールされている必要がある。

Inventory

Ansibleが制御する対象ホストを定義したものをInventoryと呼ぶ。Inventoryは、ini形式で記述する静的なInventoryファイル、もしくは、JSON形式で記述されるDynamic Inventoryで記述する。Inventoryファイルにグループ変数等を記述することが可能だが、Inventoryファイルに真偽値を記述する際には、True/Falseのように大文字で記述する必要がある。また、グループ変数やホスト変数をInventoryファイルに記述すると可読性が下がるために、

  • host_vars
  • group_vars

という名のディレクトリを作成し、この中にYAML形式で変数を記述することが一般的である。YAMLのファイル名は、グループ名・ホスト名と同一の名称にしなければならない。また、全てのグループ、ホストに適用される変数は、group_vars/all.ymlに記述する。Ansibleが取得するOSディストリビューション情報を元に自動的にグループ化することも可能で、この場合は、 group_byモジュールを使用する。

実行するグループ名をPlaybookで指定する場合は、

# 全てのホスト
hosts: all
# 特定のホスト
hosts: 192.168.0.2
# Ansibleを実行しているホスト
hosts: 127.0.0.1
connection: local
# 特定のグループ
hosts: webservers

のように指定する。

変数

Ansibleで使用する変数は、先頭に数字を使用することはできない。またアンダースコアは使用できるがハイフンは使用できない。変数はあらかじめファイル内に記述しておくことが一般的であるが、実行時にextra_varsという引数で動的に与えることも可能である。host_varsやgroup_vars以外に、外部から変数ファイルを取り込む必要がある場合には、

vars_files:
    - ../common_playbook/vars/common.yml

vars_filesディレクティブでファイル名を指定することができる。

また、Ansibleが各ホストなどから取得するマジック変数は、以下のような値が存在する。

変数名 内容
inventory_hostname inventoryに記述されたホスト名 hoge
ansible_default_ipv4.address 対象ホストのIPアドレス 192.168.0.1
ansible_hostname 対象ホストのホスト名 localhost
ansible_architecture 対象ホストのアーキテクチャ x86_64
ansible_distribution 対象ホストのディストリビューション名 CentOS
ansible_distribution_major_version 対象ホストのディストリビューションメジャーバージョン 7
ansible_date_time.epoch エポック秒 1501513200

jinja2

Ansibleでは、変数や分岐処理、真偽値の判定などは、Pythonのテンプレートエンジンであるjinja2が使用される。変数は「{{ 変数名 }}」で記述される。YAMLの文法上の制約から文字列の先頭もしくは終わりに変数を挿入する場合は、文字列全体を””で囲う必要がある。

- name: "show full status of Apache"
  command: "{{ httpd.ctlbin }} fullstatus"

実行制御

実行制御に用いる真偽値判定は以下の記述を用いる。

# 真偽値
when: ansible_os_family == "Debian"
when: val
when: not val
# 値が定義されていた場合
when: val is defined
# 値が定義されていなかった場合
when: val is undefined
# AND/OR
when: a and b
when: a or b
# 値が含まれているか否か
when: a in b
# タスクの実行
when: hogetask | success

タスクの実行結果は以下が用意されている。また、ignore_errorsディレクティブを使用すると、タスクに失敗したとしても処理は継続される。

判定句 内容
succeeded タスク成功
changed タスク変更
failed タスク失敗
skiped タスクスキップ

条件判定句は以下が用意されている。

判定句 内容 備考
changed_when 状態変更(=changed)となる条件を定義 falseに指定すると常に状態変化なし
failed_when 失敗(=failed)となる条件を定義
when taskが実行される条件を定義

notify

taskの状態に変更(=changed)があった場合、handlersで定義しnotifyで指定したtaskが実行される。taskは、playbookの中で複数回呼ばれた場合であっても、全てのtaskが終了した段階で1度だけ実行される。下の例では、httpd.confの書き換えが行われたときのみ、Apacheデーモンの再起動が行われる。

- name: "put a apache config file if it does not exist"
  template: src=httpd.conf.j2 dest="{{ httpd.conf }}" backup=yes
  notify:
    - restart httpd
- name: restart httpd
  service: name=httpd state=restarted

デバッグ

Ansibleでコマンドの出力結果を表示したい場合には、出力結果をregisterオプションで変数に一度格納し、debugコマンドでこれを表示するという手順を取る。このとき、commandコマンドは、実行の度に状態の変更(=changed)が行われてしまうため、changed_whenオプションによって、状態変更を無効化する。また、debugコマンドによる出力結果の表示は、whenオプションを用いて、直前の処理が成功したときのみ実行する設定とする。

- name: "show version number of Apache"
  command: "{{ httpd.ctlbin }} -v"
  register: httpd_version
  changed_when: False

- name: "debug version number of Apache"
  debug: var=httpd_version.stdout_lines
  when: httpd_version | success

Tips

Amazon Linux対応

Amazon LinuxはRHEL6ベースで開発されているため、Amazon Linuxの場合はRHEL6と同じ処理を行う。そのために、ディストリビューション名がAmazonであった場合は、ディストリビューションメジャーバージョンを6に指定する。

  pre_tasks:
    - set_fact: ansible_distribution_major_version=6
      when: ansible_distribution == "Amazon" and ansible_distribution_major_version == "NA"

プロキシの指定

プロキシ環境下で処理を行う場合は、変数ファイルにプロキシ設定情報を記述し、Playbookでプロキシ設定を行う。プロキシ指定から除外するアドレスが存在する場合は、no_proxyディレクティブを追加する。

proxy_env:
  http_proxy: http://XXX.XXX.XXX.XXX:8080
  https_proxy: http://XXX.XXX.XXX.XXX:8080
  environment: 
    - "{{proxy_env}}"

EC2(6)Elastic Load Balancing

ELBとは

ELBとは複数のアベイラビリティゾーンのEC2インスタンスに負荷を分散させるロードバランサである。ELBには、Classic Load BalancerApplication Load Balancerの2種類が存在し、Clasic Load Balancerは、HTTPとHTTPSの他に、TCPSSLにも対応している。一方でApplication Load Balancerは、HTTP/2やWebSocketに対応している。

ロードバランサは、登録されているEC2のうち正常なものだけを選んで負荷を分散する。Clasic Load Balancerは、EC2のインスタンスを直接登録するが、Application Load Balancerは、ターゲットグループをまず生成し、その中にインスタンスを登録する形となる。クロスゾーン負荷分散を無効にしていると、インスタンスがどのようなバランスで配置されていたとしても、アベイラビリティゾーンの数で均等に配分されてしまうので注意が必要である。なお、Application Load Balancerでは、クロスゾーン負荷分散はデフォルトで有効になっている。

ロードバランサに紐付けられているドメイン名に紐づけられたIPアドレスは、負荷に合わせて動的に変化する。DNSエントリは、TTLが60秒に設定されている。また、Application Load Balancerはリクエストタイムアウト値が60秒に設定されている。内側のインスタンスとの通信では、EC2にKeep Aliveを設定しておくことが望ましい。

Application Load Balancer とは

Application Load Balancerは、OSI参照モデルのレイヤー7で動作するロードバランサで、負荷に合わせて自動的にスケールする。ロードバランサには複数のリスナーを紐づけることができ、この下にターゲットグループがぶら下がる。EC2でクライアントの送信先アドレスを取得するためには、x-forwarded-forヘッダフィールドを参照する。またALBが負荷に追従できずスケーリングが間に合わなかった場合は、503を返す。

ELB基本コンポーネント