Ansible

【サンプルで学ぶansible】Ubuntu+Nginxで証明書作成&https

前提

Ubuntu 2 台を以下の記事に沿って設定済であること。

【図解/入門】Ansible の仕組み,環境構築, Ubuntu 構成自動化のサンプル
Ansible の仕組み Ansible は NW 機器や各種サーバーの設定を管...

学べる事

  • vars の使い方
  • 繰り返し処理を行いたいときの loop の使い方
  • ファイル作成コマンドの冪等性の保ち方
  • handlers の使い方

playbook の中身

ubuntu-1 に task2.yml として以下を作成する。

- name: Nginx https setup
  hosts: ubuntu-2
  gather_facts: false
  become: true
  vars:
    fqdn: www.example.com
  tasks:
    - name: Set ufw
      community.general.ufw:
        rule: allow
        to_port: "{{ item }}"
        proto: tcp
        state: enabled
      loop:
        - 22
        - 80
        - 443

    - name: Install apt Package
      ansible.builtin.apt:
        name:
          - nginx

    - name: Make server.key
      ansible.builtin.shell: openssl genrsa -out server.key 3072
      args:
        chdir: /etc/nginx/
        creates: /etc/nginx/server.key

    - name: Make CSR
      ansible.builtin.shell: "openssl req -new -key server.key -out server.csr -subj '/C=JP/ST=Tokyo/L=Default City/O=Default Company Ltd/CN={{ fqdn }}'"
      args:
        chdir: /etc/nginx/
        creates: /etc/nginx/server.csr

    - name: Make sans.txt
      ansible.builtin.shell: echo "subjectAltName = IP:192.168.1.14, DNS:{{ fqdn }}" > sans.txt
      args:
        chdir: /etc/nginx/
        creates: /etc/nginx/sans.txt

    - name: Make certificate
      ansible.builtin.shell: openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt -extfile sans.txt
      args:
        chdir: /etc/nginx/
        creates: /etc/nginx/server.crt

    - name: Set nginx https conf
      ansible.builtin.shell: |
        cat << EOF > /etc/nginx/conf.d/tls.conf
        server {
                listen       443 ssl http2;
                server_name  {{ fqdn }};

                ssl_certificate "/etc/nginx/server.crt";
                ssl_certificate_key "/etc/nginx/server.key";
                ssl_protocols TLSv1.2 TLSv1.3;
                ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA";
                ssl_prefer_server_ciphers off;
                ssl_session_cache shared:SSL:1m;
                ssl_session_timeout 120m;

                root    /usr/share/nginx/html;
        }
        EOF
      args:
        creates: /etc/nginx/conf.d/tls.conf
      notify: Restart nginx Service

  handlers:
    - name: Restart nginx Service
      ansible.builtin.service:
        name: nginx
        state: restarted

上記を作成後、ansible-playbook task2.yml を実行すると、nginx が https で動作するようになります。

ブラウザで https で IP を指定して接続してみましょう。

また、ansible-playbook を 2 回連続実行して冪等性を確認してみましょう。

解説

vars の使い方

vars では ansible で扱える変数を定義することができます。定義した変数は {{ }} の中に変数名を入れることで呼び出せます。

上記のサンプルでは vars で fqdn: www.example.com を指定していますので、tasks の各所で {{ fqdn }} と書くことで "www.example.com" を呼び出すことができています。

なのでもし fqdn を変更したい場合はこの vars の fqdn だけを変更すればよいのです。

ansible は自分で変数を定義するだけでなく、内部で用意されているものもあります。例えば gather_facts: trueを設定した play については ansible 変数と呼ばれるものが使えます。

ubuntu-2 で使える ansible 変数を事前に確認するには以下コマンドを実行します。

$ ansible ubuntu-2 -m setup

また、次に紹介する loop も内部で用意されている変数 {{ item }} を使います。

繰り返し処理を行いたいときの loop の使い方

ufw を設定する際、モジュールとしては 1 つのルールを作ることしかできませんが、それを複数タスクに分けて書くと効率も悪いし視認性も悪いです。

ansible では繰り返し処理を loop で行うことができます。今回の ufw の例では、to_port の箇所に変数 "{{ item }}" を配置し、loop の箇所で "{{ item }}" に入るポート番号を指定しています。これにより ansible は to_port: 22, to_port: 80, to_port: 443 を順番に実行していきます。

なお、YAML ではこのような変数を使う場合は必ず "" でダブルクォーテートする必要があります。{{ }} だけを囲むわけではなく、{{ }} が含まれるよう全体を囲みます。

なので 例えば上記で to_port: "10{{ item }}" と記述した場合、ufw で開くポートは 1022, 1080, 10443 になります。

| を使った場合はダブルクォーテーションと同じ効果があります。

ファイル作成コマンドの冪等性の保ち方

args には色々な引数を入れられますが、冪等性を担保する手段として creates と removes がよく使われます。

creates: <<file名>> と指定すると、そのファイルが存在するときはそのコマンドは実行せず、changed は返さず ok のみを返します。

同様に removes: <<file名>> と指定した場合は、そのファイルが存在しないときはそのコマンドは実行せず changed は返しません。

今回は一度ファイルを作成したらその後は再作成はしないようにしています。

handlers の使い方

設定ファイルを変更した後、サービスにその設定を反映させるためにはサービス再起動が必要になることが多いです。このようなときに使えるのが handlers です。

今回の例では、nginx はインストール時にサービス起動してしまいます。その後に conf.d/tls.conf という設定を格納した後は nginx の再起動が必要になりますが、これを task として入れてしまうと毎回サービス再起動するため、不要なサービス再起動が毎回行われるだけでなく、冪等性の評価指標である changed が毎回付いてしまいます。

なのでこれを task ではなく handlers に含めることによって、「notify: Restart nginx Service」が指定された task が changed になった場合に限り、その play が実行された後に「name: Restart nginx Service」のハンドラーが 1 回だけ実行されます。

なのでその play の中で複数の nginx 設定ファイルを変更したとしても、サービス再起動になるのは 1 回だけで済みます。

逆に、タスク毎に handlers を動作させたいなら以下のように play を分けるしかありません。

- name: Nginx https setup1
  hosts: ubuntu-2
  gather_facts: false
  become: true
  tasks:
    - name: Set nginx https conf
      ansible.builtin.shell: echo hoge
      notify: Restart nginx Service
  handlers:
    - name: Restart nginx Service
      ansible.builtin.service:
        name: nginx
        state: restarted

- name: Nginx https setup2
  hosts: ubuntu-2
  gather_facts: false
  become: true
  tasks:
    - name: Set nginx https conf
      ansible.builtin.shell: echo fuga
      notify: Restart nginx Service
  handlers:
    - name: Restart nginx Service
      ansible.builtin.service:
        name: nginx
        state: restarted

この書き方であれば echo hoge ⇒ nginx 再起動 ⇒ echo fuga ⇒ nginx 再起動 という順番で処理を行います。

コメント

タイトルとURLをコピーしました