GitとAWX(Ansible Tower)のワークフローテンプレートで設定ファイルの自動切り戻しオペレーションをやってみた

GitとAWX(Ansible Tower)のワークフローテンプレートを使って自動切り戻しをやってみました。

# 1. やりたいこと

* Gitのタグで設定ファイルのバージョン管理をしている前提
* AWX(Ansible Tower)のジョブで設定ファイルを更新し反映するためにデーモンのリロード（または再起動）をする
* その時に設定ファイルの内容が間違っていて失敗した場合、自動で指定したタグのバージョンに切り戻したい

# 2. 処理フロー

今回はPostfixを例にしてやってみました。

* Postfixの設定ファイルを更新
* 失敗したらプロジェクトのリポジトリへ移動し指定したタグのブランチを作成
* タグのブランチから設定ファイルをコピーしPostfixのデーモンをリロード
* 最後に一時的に作成したタグのブランチを削除しmasterへ戻す

![postfix_config_update_flow.png](https://qiita-image-store.s3.amazonaws.com/0/180118/fbf8a897-5f24-4e85-a292-e3ecb3b65cb2.png)

# 3. 検証環境

|   項目  |        バージョン        |
|---------|--------------------------|
| CentOS  | 7.4                      |
| AWX     | 2018/07/22時点での最新版 |

# 4. リポジトリ構成

リポジトリは `mailserver` と `common_tools` の2つを作りました。

## 4-1. mailserver

postfixの設定ファイルとロールを管理するリポジトリです。

```
mailserver/
├── main.yml
└── postfix
    ├── files
    │   ├── access
    │   ├── canonical
    │   ├── generic
    │   ├── header_checks
    │   ├── main.cf
    │   ├── master.cf
    │   ├── relocated
    │   ├── transport
    │   └── virtual
    └── tasks
        └── main.yml
```

### 4-1-1. Playbook

#### 4-1-1-1. main.yml

Postfixの設定ファイルを更新するロールを呼び出すPlaybookです。

```yaml
---
- name: postfix operation
  hosts: all
  gather_facts: no
  roles:
    - postfix
```

#### 4-1-1-2. tasks/main.yml

Postfixの設定ファイルを更新するタスクです。

```yaml
# プロジェクトが保存されているディレクトリパスを `repo_path` 変数へ格納
- set_stats:
    data:
      repo_path: "{{ playbook_dir }}"

# 設定を指定したtagのバージョンに戻す場合の処理
# 標準だと同期したリビジョンで実行されてしまうためbranchの変更をする必要がある
# 実行条件は `switch_flag` が定義されている場合
- name: switch branch
  local_action: shell cd {{ repo_path}} ; git checkout {{ git_tag }}
  when: switch_flag is defined

# Postfixの設定ファイルをコピー
- name: copy postfix config
  copy:
    src: "{{ item }}"
    dest: /etc/postfix
  with_fileglob:
    - "{{ role_path }}/files/*"

# Postfixのプロセス状態確認
- name: check postfix process
  shell: systemctl status postfix
  ignore_errors: yes
  register: postfix_service_status

# Postfixのプロセスが起動中であればreloadを実行
- name: reload postfix
  systemd:
    name: postfix
    state: reloaded
  when: postfix_service_status.rc == 0

# Postfixのプロセスが停止していればrestartを実行
- name: restart postfix
  systemd:
    name: postfix
    state: restarted
  when: postfix_service_status.rc != 0
```

## 4-2. common_tools

common_toolsのPlaybookを管理するリポジトリです。
common_toolsには他でも使える共通のPlaybookを保存する形になります。
ここでは、Gitのタグのブランチを作成するものと削除するものを作成しています。

```
common_tools/
├── delete_tag_branch.yml
└── switch_back.yml
```

### 4-2-1. Playbook

#### 4-2-1-1. switch_back.yml

指定したタグのブランチを作成するPlaybookです。

```yaml
---
- name: switch back of tag
  hosts: all
  gather_facts: no
  tasks:
    # 切り戻しに指定したtagのブランチを作成
    - shell: "git checkout -b {{ git_tag }} {{ git_tag }}"
      args:
        chdir: "{{ repo_path }}"

    # `switch_flag` を定義
    - set_stats:
        data:
          switch_flag: 1
```

#### 4-2-1-2. delete_tag_branch.yml

指定したタグのブランチを削除するPlaybookです。

```yaml
---
- name: delete tag branch
  hosts: all
  gather_facts: no
  tasks:
    # branchをmasterに戻す
    - shell: git checkout master
      args:
        chdir: "{{ repo_path }}"

    # 指定したtab branchを削除
    - shell: "git branch -d {{ git_tag }}"
      args:
        chdir: "{{ repo_path }}"
```

# 5. AWX設定

## 5-1. ジョブテンプレート

### 5-1-1. postfix config update

Postfixの設定ファイルを更新(切り戻し)してデーモンのリロード or 再起動するジョブテンプレート

![スクリーンショット 2018-07-22 16.53.54.png](https://qiita-image-store.s3.amazonaws.com/0/180118/0a527f48-0f47-39ec-1833-107e9db966b7.png)

### 5-1-2. switch back of tag

指定したタグのブランチを作成するジョブテンプレート

![スクリーンショット 2018-07-22 16.54.35.png](https://qiita-image-store.s3.amazonaws.com/0/180118/10d86cdc-7a46-af84-6360-ccb6a6e71f50.png)

### 5-1-3. delete tag branch

指定したタグのブランチを削除するジョブテンプレート

![スクリーンショット 2018-07-22 16.55.47.png](https://qiita-image-store.s3.amazonaws.com/0/180118/ee604c79-02f0-ba52-eb83-2afd640b4e1b.png)

## 5-2. ワークフローテンプレート

### 5-2-1. postfix config update flow

上記3つのジョブテンプレートを組み合わせたフローです。

![スクリーンショット 2018-07-22 16.57.21.png](https://qiita-image-store.s3.amazonaws.com/0/180118/5d2564db-ccd1-9ce7-7cae-39f12a24ca38.png)

ここでは `追加変数` に切り戻すタグを指定しています。
本番の運用では `extra_vars` としてAPI経由から渡すというやり方でもいいかもしれません。

![スクリーンショット 2018-07-22 17.01.06.png](https://qiita-image-store.s3.amazonaws.com/0/180118/9879636b-6be5-d57f-239f-3704b1a9233b.png)

# 6. 実行

`postfix config update flow` を実行してみます。
AWXの処理と一緒にローカルブランチの変化も見れるようにしています。
postfixの設定ファイル更新が失敗してGitの指定したタグから切り戻しがされています。

![postfix_config_update_flow.gif](https://qiita-image-store.s3.amazonaws.com/0/180118/3c2315a8-6fa6-acb2-c203-4fd394faaa06.gif)

設定がミスっていても無事復旧していることが確認できました :)

# 7. 最後に

運用の自動化をするのであれば切り戻しまで自動化しておくことで失敗した時のサービス復旧も迅速に行えますね。