Docker で動作している AWX を Kubernetes 上に移行する

# 目的

AWX 17.0.1 以降、AWX は Docker での動作が非推奨となった。
そのため、現在 Docker 環境上で動作している AWX を Kubernetes 環境上に移行する。

本記事では下記の条件で動作している 2 つの環境を準備し、移行手順とともに移行作業時に発生したエラーとその対応についてまとめた。

- 既存の環境に Docker の AWX がインストールされており、ジョブテンプレート等の設定がされている
- 新規の環境に Kubernetes の AWX がインストールされており、初期設定である

# AWX の移行手順

以下の手順は既存・新規、両方の AWX 環境に接続できる環境で実施する。

- 既存の AWX 環境 (Docker) 
  - host: http://10.100.0.1/
  - version: AWX 17.0.1 
- 新規の AWX 環境 (Kubernetes)
  - host: http://10.100.0.2/
  - version: AWX 21.9.0

## awx-cli

awx-cli をインストールする。

```
apt install python3.8-venv
python3 -m venv venv
source venv/bin/activate
pip install ansible-tower-cli
```

## 移行元データの取得

既存の AWX 接続するための認証情報設定する。

```
awx-cli config host http://10.100.0.1/
awx-cli config password password
awx-cli config username admin
awx-cli config verify_ssl false
```

設定状況を確認する。

```
$ awx-cli config

# User options (set with `tower-cli config`; stored in ~/.tower_cli.cfg).
host: http://10.100.0.1/
password: password
username: admin
verify_ssl: False

# Defaults.
color: True
certificate:
description_on: False
use_token: False
format: human
oauth_token:
verbose: False
```

既存の環境から情報を取得する。

```
awx-cli receive --all > all_object.json
```

extra_vars が --- 単体の場合、"" に置換する。
extra_vars に --- が単体で存在する場合、インポート時にエラーとなる。(エラーについては付録参照)

```
sed -i 's/"extra_vars": "---",/"extra_vars": "",/g' all_object.json
```

## データ移行

新規の AWX に接続するための認証情報設定する。
Kubernetes の AWX に接続する場合の初期パスワード取得方法がわからない場合は付録を参考にするとよい。

```
awx-cli config host http://10.100.0.2/
awx-cli config password unWchWtlxRsU4wnjyF55cXUbL4Fg6Zjj
awx-cli config username admin
awx-cli config verify_ssl false
```

設定状況を確認する。

```
$ awx-cli config

# User options (set with `tower-cli config`; stored in ~/.tower_cli.cfg).
host: http://10.100.0.2/
username: admin
password: unWchWtlxRsU4wnjyF55cXUbL4Fg6Zjj
verify_ssl: False

# Defaults.
oauth_token:
use_token: False
certificate:
verbose: False
color: True
description_on: False
format: human
insecure: False
```

新規の環境に情報をインポートする。

```
$ awx-cli send all_object.json
JOB TEMPLATE [xxxxxxx] *****************************************************************

...

PLAY RECAP ******************************************************************************
    ok=18    changed=0    warnings=0    failed=0
```

インポート実行時、JOB TEMPLATE でエラーが発生することがある。(エラーについては付録参照)
新規 AWX 環境にブラウザからログインし、下記の手順を実行する。

- [リソース] > [認証情報] 
- [project が接続に利用する認証情報名]
- [編集]
- [SCM 秘密鍵] の更新マーク
- [参照]
  - palybook が配置している箇所に接続するための秘密鍵設定
- [保存]
- [リソース] > [プロジェクト]
- [エラーが発生しているジョブテンプレートのプロジェクト]
- [同期]
  - [最終ジョブステータス] が [成功] となれば問題なし

再度設定をインポートする。
この時、error が発生しなければ問題ない。

```
awx-cli send all_object.json
```

# 付録

## extra_vars が --- 単体の場合に発生したエラー

```
$ awx-cli send all_object.json

JOB TEMPLATE [xxxxxxx] *****************************************************************************************************************************************************************************************************************************************
Failed to create job_template xxxxxxx : failed to parse some of the extra variables.
variables:
---

...
```

extra_vars が空の場合、extra_vars は自動的に `---` となる。
この時、awx-cli receive で取得した all_object.json ファイルも extra_vars も `---` が入力されている。
この状態でインポートを実行すると上記のようにエラーが発生する。
エラーにも記載されている通り、変数の解析ができていないため、そもそも変数を空にすることで対応した。

## Kubernetes の AWX に接続するための初期パスワード取得

AWX が動作している Kubernetes にアクセスできる環境で下記を実行する。
`awx-demo-admin-password` は自分の環境と一致する値に変更する。

```
$ kubectl get secret awx-demo-admin-password -o yaml
apiVersion: v1
data:
  password: dW5XY2hXdGx4UnNVNHduanlGNTVjWFViTDRGZzZaamo=
kind: Secret
...
```

上記のパスワードはエンコードされているため、デコードする。

```
$ echo 'dW5XY2hXdGx4UnNVNHduanlGNTVjWFViTDRGZzZaamo=' | base64 --decode
unWchWtlxRsU4wnjyF55cXUbL4Fg6Zjj
```

## インポート実行時、JOB TEMPLATE で発生したエラー

```
$ awx-cli send all_object.json
JOB TEMPLATE [xxxxxxxxxx] ************************************************************************************************************************************************************************************************************************************************
Failed to create job_template xxxxxxxxxx : The Tower server claims it was sent a bad request.

POST http://10.100.0.2/api/v2/job_templates/
Params: None
Data: {"xxxx": "yyyy"}

Response: {"playbook":["Playbook not found for project."]}
```

インポートを実行することにより、ジョブテンプレート以外にもプロジェクトの設定や認証情報も移行できる。
ただ、認証情報に登録されていた秘密鍵等、移行されない情報も存在する。
その移行されていないものを用いて Git 等にアクセスすると Permission Denied となる。

今回の場合は秘密鍵、パスワード等は移行されない仕様であるにも関わらず、別途秘密鍵などの認証情報を登録する手順を省いた。
これにより、秘密鍵が移行されていないにも関わらず、その秘密鍵を用いて Git にアクセスしようとしていたため、エラーが発生していた。
そのため、手動で秘密鍵を登録することで解決した。

この手順を参考に移行手順を考える方は手順としてパスワード・秘密鍵を設定する手順を組み込むことをお勧めする。

# まとめ

今回は Docker 環境上で動作している AWX を Kubernetes 環境に移行させる手順と移行時に発生したエラー等をまとめた。
本手順では `awx-cli receive --all` とすることで Docker 環境上で設定している Job 等をすべて移行した。
コマンドのオプションとして --user TEXT や --credential など、特定の項目のみを抽出可能であるため、自身の環境に必要なものの移行が可能である。
また、cron 等で定期的に `awx-cli receive --all` を実行し、その結果を日付等のファイルで管理することで、バックアップ管理も可能である。

移行時に移行される設定とされない設定があり、単純にコマンドを実行するだけではすべての設定が移行されるわけではない。
ただ、receive 時に取得した json ファイルに password 等の必要な項目を追加し、send を実行することで password の設定されたユーザ設定が移行できる。
そのため、receive で取得した json ファイルにこれらの必要な情報を追記できるようにすることで、全ての設定のバックアップや以降の自動化も可能であると考える。