パッケージと動作するサービスを管理する

AnsibleBeginner
オンラインで実践に進む

はじめに

パッケージがインストールされていること、設定ファイルが存在すること、サービスが応答することは、それぞれ異なる成果です。ユーティリティのインストールと削除、nginx の設定、稼働状態の宣言、ハンドラーによる変更済み設定の再読み込みを、それぞれ明示的に管理します。両管理対象ノードからの実際の HTTP 応答で、サービスの動作を確認します。

パッケージのインストール済み状態と削除状態を宣言する

このステップでは、小さなユーティリティをインストールして調べ、再利用可能なパッケージの宣言で削除します。

apt モジュールは、管理対象ホストの Ubuntu パッケージを管理します。state: present はインストール、state: absent は削除を要求します。この環境にはパッケージ一覧とキャッシュ済みのダウンロードが用意されているため、update_cache: false を維持してください。一覧の更新や最新バージョンの要求は、不要なネットワーク依存を加えます。本番環境の更新方針は異なる場合があります。

コントローラーのプロジェクトに移動します。

cd /home/labex/project

変数で tree パッケージの望ましい状態を選択する Playbook を作成します。パッケージ操作には、対象での become が必要です。install_recommends: false は、任意の推奨パッケージをインストールしないようにします。

cat > packages.yml <<'YAML'
- name: Declare a utility package state
  hosts: all
  gather_facts: false
  become: true
  vars:
    utility_state: present
  tasks:
    - name: Converge the tree package
      ansible.builtin.apt:
        name: tree
        state: "{{ utility_state }}"
        update_cache: false
        install_recommends: false
YAML

ユーティリティをインストールします。

ansible-playbook packages.yml

tree コマンドはディレクトリツリーを表示します。ここではバージョンオプションで、各管理対象ノードに実行ファイルが本当にインストールされたことを実証します。

ansible all -m ansible.builtin.command -a 'tree --version'

各対象が tree のバージョンを返すはずです。Playbook を繰り返してください。存在するパッケージに、再インストールは不要なはずです。

ansible-playbook packages.yml

次に、再利用可能なタスクを編集せず、追加変数で削除状態を要求します。

ansible-playbook packages.yml -e utility_state=absent

同じ削除状態の要求を繰り返します。今度は、recap の両行が changed=0、failed=0、unreachable=0 を示すはずです。

ansible-playbook packages.yml -e utility_state=absent

パッケージ状態はインストールに関する宣言であり、サービスが稼働し応答している証拠ではありません。次のステップで nginx を配置する間も、tree は削除したままにしてください。

実際の Web サービスを設定して起動する

このステップでは、nginx をインストールし、完全な検証済み設定を配置して、そのサービスを明示的に稼働状態に保ちます。

2 つの管理対象ノードは、別々の SSH 接続先とファイルシステムを持つコンテナーです。systemd は動作していません。service モジュールは、それらで利用可能なサービスマネージャーを使います。これらの対象で systemctl を実行しないでください。systemd の起動方針を保証するのではなく、現在の稼働状態を管理します。

コントローラーに静的ページを作成します。末尾に改行があるため、管理対象の正確なバイト列を予測できます。

printf 'Ansible service ready\n' > page.txt

完全な nginx 設定を記述します。events と http は nginx の最上位コンテキスト、server は Web サイトの定義、listen はポート 8080 の選択、root はドキュメントディレクトリの選択、index は / リクエストに使うページの選択です。これらは Ansible YAML ではなく、nginx の設定です。

cat > nginx-course.conf <<'NGINX'
events {}
http {
    server {
        listen 8080;
        root /var/www/ansible-site;
        index index.html;
    }
}
NGINX

配置用 Playbook を作成します。apt タスクは policy_rc_d: 101 で、パッケージインストーラーによる暗黙の nginx 起動を防ぎます。後の service タスクが、稼働状態を明示的に宣言します。copy タスクの validate は、コピー先を置き換える前に、一時的な候補ファイル(%s)に対して nginx の設定テストを実行します。

ハンドラーは、handlers の下に記述する名前付きの操作です。変更があった設定タスクは Reload nginx に通知し、これは Play の最後に 1 回実行されます。設定変更がなければ通知はありません。通常の service タスクは started を使用し、無条件に再起動せず、すでに動作中のサービスを稼働状態に保ちます。

cat > web.yml <<'YAML'
- name: Deploy a working web service
  hosts: all
  gather_facts: false
  become: true
  tasks:
    - name: Install nginx without refreshing the prepared package lists
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: false
        install_recommends: false
        policy_rc_d: 101

    - name: Prepare the site directory
      ansible.builtin.file:
        path: /var/www/ansible-site
        state: directory
        owner: root
        group: root
        mode: "0755"

    - name: Deploy the static page
      ansible.builtin.copy:
        src: /home/labex/project/page.txt
        dest: /var/www/ansible-site/index.html
        owner: root
        group: root
        mode: "0644"

    - name: Validate and deploy nginx configuration
      ansible.builtin.copy:
        src: /home/labex/project/nginx-course.conf
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: "0644"
        validate: /usr/sbin/nginx -t -c %s
      notify: Reload nginx

    - name: Keep nginx running
      ansible.builtin.service:
        name: nginx
        state: started

  handlers:
    - name: Reload nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded
YAML

構文をチェックし、配置を適用します。

ansible-playbook web.yml --syntax-check
ansible-playbook web.yml

両ノードに nginx がインストールされ、ファイルが届き、正常に起動するはずです。初回の設定変更は、再読み込みハンドラーも実行予定に入れます。パッケージのバージョン確認だけでは、こうしたサービスの動作は何も確認できません。

curl は HTTP クライアントです。--fail は成功でない HTTP ステータスをコマンド失敗として扱い、--silent は進捗出力を省き、--show-error は失敗の詳細を残します。各管理対象ホストで、そのホスト自身のループバックインターフェースに対して実行します。

ansible all -m ansible.builtin.command -a 'curl --fail --silent --show-error http://127.0.0.1:8080/'

各結果に Ansible service ready が含まれるはずです。コントローラーと各対象のループバックインターフェースは別々です。このコマンドはコントローラーではなく、両対象のサービスを確認します。

ハンドラーを通じて設定変更を適用する

このステップでは、稼働中の nginx 設定を変更し、ハンドラーを観察して、HTTP 応答から設定を確認します。

nginx の server_tokens ディレクティブは、応答ヘッダーで nginx のバージョンを公開するかを制御します。コントローラーの設定を次の完全版に置き換え、http 内に server_tokens off を追加します。

cat > nginx-course.conf <<'NGINX'
events {}
http {
    server_tokens off;
    server {
        listen 8080;
        root /var/www/ansible-site;
        index index.html;
    }
}
NGINX

同じ Playbook を適用します。

ansible-playbook web.yml

設定のコピーは両ホストで changed を報告し、Reload nginx に通知するはずです。新しい設定が検証を通過した後、ハンドラーは稼働中のサービスを再読み込みします。その実行によって設定が有効になります。ファイルをコピーしただけでは、プロセスが何を読み込んだかは確認できません。

curl の -I は HTTP ヘッダーを要求します。両ホストの実際のサービス応答を調べます。

ansible all -m ansible.builtin.command -a 'curl --fail --silent --show-error -I http://127.0.0.1:8080/'

両応答は成功の HTTP ステータスを持ち、Server ヘッダーはバージョンの接尾辞がない nginx になるはずです。日付など、他のヘッダーフィールドは変わります。

完全な Playbook を繰り返します。

ansible-playbook web.yml

両ホストが changed=0、失敗または到達不能のタスクなしを報告し、再読み込みハンドラーは実行予定に入らないはずです。静的ページは引き続き利用でき、tree は削除状態、nginx はインストール済みで稼働中のままです。

まとめ

パッケージの存在と不在を宣言し、インストールとサービスの稼働状態を分けて扱い、候補ファイルの検証を伴う完全な nginx 設定を配置しました。変更された設定は再読み込みハンドラーに通知し、実際の HTTP 応答で稼働中の動作を確認しました。変更のない繰り返し実行では、追加の変更や再読み込みを避けられました。