Red Hat Certified Engineer (RHCE) #14 RHCSA 自動化 1: ユーザー/グループ、パッケージ/repository
#13 system roles まで Ansible の文法と構造化ツールをすべて身につけました。ここからの 4 編は、そのツールを武器に RHCSA の手作業をプレイブックで自動化する 総合区間です。RHCE 試験の比重の半分ほどがこの「RHCSA の作業を Ansible で自動化」なので、ここからが実質的に本番です。
この記事では、RHCSA で useradd・groupadd・dnf install で手作業していたことを、user・group・dnf・yum_repository モジュールに置き換えて冪等に処理します。手作業が気になるなら、RHCSA #8 ユーザーとグループ、RHCSA #11 パッケージと repository を先に確認すると、自動化する対象がはっきりします。
group モジュール: まずグループを作る #
ユーザーをグループに入れるには、グループが先に存在している必要があります。RHCSA で groupadd developers でしていたことを ansible.builtin.group モジュールで処理します。
- name: developers グループを保証
ansible.builtin.group:
name: developers
gid: 5000
state: present主なオプションはシンプルです。
| オプション | 意味 |
|---|---|
name | グループ名 (必須) |
gid | 指定する GID。省略するとシステムが自動割り当て |
state | present (作成・維持) または absent (削除) |
system | true ならシステムグループとして作成 |
state: present はグループがなければ作り、すでにあればそのままにします。2 回回しても 2 回目には changed が 0 になる冪等性が、モジュールの既定の動作です。
user モジュール: ユーザー作成の中心 #
ansible.builtin.user モジュールは RHCE で最もよく使うモジュールの 1 つです。RHCSA の useradd・usermod を 1 つのモジュールにまとめます。
- name: ユーザーを作成
hosts: all
become: true
tasks:
- name: 開発者アカウントを作成
ansible.builtin.user:
name: jdoe
uid: 5001
comment: "John Doe"
group: developers
groups: wheel
append: true
shell: /bin/bash
state: present主要なオプションを整理します。
| オプション | 意味 |
|---|---|
name | ユーザー名 (必須) |
uid | 指定する UID |
group | 基本グループ (primary group) |
groups | 補助グループ (supplementary)。カンマ区切りまたはリスト |
append | true なら groups を既存に追加。false (既定) なら上書き |
password | 暗号化されたパスワードハッシュ (平文ではない) |
shell | ログインシェル。例として /bin/bash、/sbin/nologin |
state | present または absent |
remove | state: absent と一緒に true ならホームディレクトリまで削除 |
append の落とし穴 #
groups だけ与えて append を抜かすと、既定値が false なので 既存の補助グループをすべて上書きして 指定したグループだけを残します。「ユーザーを wheel グループに追加せよ」という問題で append: true を抜かすと、他のグループが消えて減点されます。補助グループを足す意図なら、append: true を必ず一緒に書きます。
password: パスワードはハッシュで扱う #
user モジュールの password は平文ではなく 暗号化されたハッシュ を受け取ります。平文をそのまま入れると、その文字列自体がハッシュとして保存されてログインできません。ハッシュは password_hash フィルターで作ります。
- name: パスワードと一緒にユーザーを作成
hosts: all
become: true
vars:
user_password: "{{ vault_user_password }}"
tasks:
- name: jdoe の作成とパスワード設定
ansible.builtin.user:
name: jdoe
password: "{{ user_password | password_hash('sha512') }}"
shell: /bin/bash
state: presentここで平文パスワード vault_user_password は、#10 Ansible Vault で扱ったとおり Vault で暗号化した変数ファイル (ansible-vault create group_vars/all/vault.yml) に置くのが定石です。平文パスワードをプレイブックにそのまま書くと、試験で減点の対象です。実行時には --vault-password-file ~/.vault_pass でロックを解きます。
password_hash('sha512') は呼び出すたびに salt が変わってハッシュが変わるので、そのままにすると毎回の実行が changed に見えることがあります。冪等性を厳密に合わせる必要があるなら固定 salt を与える方法もありますが、試験ではパスワードが正しく設定されてログインできるかが採点の核心です。
loop で複数ユーザーを作成: 試験定番 #
RHCE で最もよく出る形は、ユーザーの一覧を変数で受け取り loop で一度に作成する パターンです。#9 loop で身につけた loop をそのまま活用します。ユーザーの一覧を変数ファイルに置きます。
# group_vars/all/users.yml
users:
- { name: alice, groups: developers }
- { name: bob, groups: developers }
- { name: carol, groups: ops }続いて、ユーザーを loop で一括作成します。
- name: ユーザーを一括作成
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
append: true
password: "{{ default_password | password_hash('sha512') }}"
shell: /bin/bash
state: present
loop: "{{ users }}"loop: "{{ users }}" はリストの各要素を item として受け取り、item.name・item.groups で dictionary のフィールドにアクセスします。ユーザーが数十人いても変数の一覧を増やすだけで済みます。条件を足したいなら、when: item.state | default('present') == 'present' のようにフィールドごとに分岐することもできます。下の統合 playbook でこのパターンをそのまま活用します。
dnf モジュール: パッケージ管理 #
パッケージのインストール・削除は ansible.builtin.dnf モジュールで処理します。RHCSA の dnf install・dnf remove に対応します。
- name: パッケージ管理
hosts: all
become: true
tasks:
- name: 複数パッケージをインストール
ansible.builtin.dnf:
name:
- httpd
- mariadb-server
- vim-enhanced
state: present
- name: パッケージを最新の状態に
ansible.builtin.dnf:
name: tmux
state: latest
- name: パッケージを削除
ansible.builtin.dnf:
name: telnet
state: absent主なオプションは次のとおりです。
| オプション | 意味 |
|---|---|
name | パッケージ名。リストで複数を一度に |
state | present (インストール)、latest (最新に更新)、absent (削除) |
enablerepo | 特定の repository だけを有効化してインストール |
disablerepo | 特定の repository を無効化 |
state: present はなければインストールしてあればそのままにするので、冪等性が保証されます。一方 state: latest は新しいバージョンがあれば毎回更新するので、「特定のパッケージをインストールするだけ」という問題には present を使う方が意図に合います。
パッケージグループのインストール #
複数のパッケージをまとめたグループは @ 接頭辞でインストールします。RHCSA で dnf group install していたことです。
- name: 開発ツールグループをインストール
ansible.builtin.dnf:
name: "@Development Tools"
state: presentmodule stream #
AppStream の module stream は @モジュール:ストリーム 形式で指定します。例として nginx の 1.22 ストリームをインストールします。
- name: nginx 1.22 module stream をインストール
ansible.builtin.dnf:
name: "@nginx:1.22"
state: present@nginx:1.22 は nginx モジュールの 1.22 ストリームを有効化し、既定のプロファイルをインストールします。特定のバージョンストリームを固定しなければならない問題で、この表記をそのまま活用します。
yum_repository モジュール: repository の追加 #
インターネットや内部サーバーの repository を登録するには ansible.builtin.yum_repository モジュールを使います。RHCSA で /etc/yum.repos.d/ に .repo ファイルを手で作っていたことを自動化します。
- name: 社内 repository を登録
hosts: all
become: true
tasks:
- name: BaseOS repo を追加
ansible.builtin.yum_repository:
name: internal-baseos
description: "Internal BaseOS Repository"
baseurl: http://repo.example.com/baseos
gpgcheck: true
gpgkey: http://repo.example.com/RPM-GPG-KEY-internal
enabled: true
state: present主なオプションを整理します。
| オプション | 意味 |
|---|---|
name | repo ID。.repo ファイル内のセクション名になる |
description | 人が読む説明。.repo の name= 項目 |
baseurl | パッケージを取得する基準 URL |
gpgcheck | true なら GPG 署名を検証 |
gpgkey | 検証に使う GPG キーの場所 |
enabled | この repo の有効化の可否 |
file | 保存する .repo ファイル名 (省略すると name を使用) |
name は .repo ファイルのセクション ID になり、description はその中の name= 項目として入ります。2 つのフィールドは紛らわしいので、表で対を覚えておきます。gpgcheck: true にすると gpgkey も一緒に指定しないと、インストール時に検証を通りません。
試験定番: 統合 playbook #
実際の試験では、上のモジュールが 1 つのプレイブックに集まります。「repository を追加し、その repo からパッケージをインストールし、ユーザーの一覧を loop で作れ」という形が典型です。1 つのファイルにまとめてみます。
- name: RHCSA 自動化統合
hosts: webservers
become: true
vars_files:
- group_vars/all/users.yml
- group_vars/all/vault.yml
tasks:
- name: 社内 repository を登録
ansible.builtin.yum_repository:
name: internal-appstream
description: "Internal AppStream"
baseurl: http://repo.example.com/appstream
gpgcheck: false
enabled: true
- name: ウェブパッケージをインストール
ansible.builtin.dnf:
name:
- httpd
- "@nginx:1.22"
state: present
enablerepo: internal-appstream
- name: 運用グループを作成
ansible.builtin.group:
name: ops
state: present
- name: ユーザーを一括作成
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
append: true
password: "{{ vault_default_password | password_hash('sha512') }}"
shell: /bin/bash
state: present
loop: "{{ users }}"この 1 つのプレイブックに、この記事のモジュールがすべて入っています。repository を登録し、enablerepo でその repo からパッケージをインストールし、グループを先に作ってからユーザーを loop で作成する順序が自然です。
試験ポイント #
passwordはハッシュだけを受け取る。 平文を入れるとログインできません。password_hash('sha512')フィルターでハッシュを作り、平文パスワードは Vault で暗号化した変数に置きます。append: trueを忘れない。 補助グループを足せという問題でappendを抜かすと、既存の補助グループがすべて消えます。足す意図なら常に一緒に書きます。yum_repositoryのnameとdescriptionを区別する。nameは repo ID、descriptionは.repoのname=説明です。対を取り違えると検証がずれます。- module stream は
@モジュール:ストリーム表記。 例として@nginx:1.22のように書きます。 state: presentとlatestを区別する。 「インストールだけ」ならpresent、「最新に」ならlatestです。- グループをユーザーより先に作る。 ユーザーの補助グループがなければ task が失敗します。1 つのプレイブックの中で group task を user task の上に置きます。
まとめ #
この記事で自動化したこと:
- group モジュール。
name・gid・stateでグループを冪等に作成 - user モジュール。
name・uid・group・groups・append・shell・state。パスワードはpassword_hash+ Vault - dnf モジュール。
name・state(present/latest/absent)・enablerepo。パッケージグループは@グループ、module stream は@モジュール:ストリーム - yum_repository モジュール。
name・description・baseurl・gpgcheck・gpgkey・enabledで repo を登録 - loop パターン。ユーザーの一覧変数を loop で一括作成する試験定番
- 統合 playbook。repo 登録 → パッケージインストール → グループ・ユーザー作成を 1 つのファイルで
次へ: RHCSA 自動化 2 #
ユーザー・グループとパッケージ・repository をプレイブックに移しました。次はその上で動くサービスを自動化する番です。
#15 RHCSA 自動化 2: サービス、chronyd、log では、service・systemd モジュールでサービスを起動・有効化する方法、chronyd の時刻同期を plays で構成する方法、そしてログ関連の設定まで、手作業をモジュールに置き換えて整理します。