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

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}}"