ローカルAnsible GalaxyでプライベートなCollection管理


※2021/01/31追記
今からやるならGalaxy NG版 の方がおすすめです。

はじめに

Ansibleでロールを共有する仕組みとしてAnsible Galaxyがありますが、社内でしか使えないプライベートなロールなど、世界中に晒せないような物を載せるのは躊躇してしまいます。
幸いにしてAnsible GalaxyはOSSとして公開されているので、ローカルで管理することが可能です。
Contributor Guideに起動方法が記載されているので、試してみました。
(ちょっと触ってみただけなので、間違いなどあってもご容赦を…)

前提

実はロールについては(Ansible Galaxyでは)プライベートな管理ができません。Githubでの公開が必須なようです。(Privateなリポジトリではダメでした)
※3/25追記 Galaxyを利用しない前提であれば、Gitを直接参照することでRoleの管理自体は可能です。↑で書いているのは、あくまで「ローカルで立てたAnsible Galaxyでは」という前提です。

ですが、表題にあるコレクションであればtar ballをアップロードする形で管理できるので、プライベートな管理が可能です。
認証のためにGithubのアカウントは必須となるので注意。
環境面として、Docker + Docker Composeが動く環境が必要です。

環境構築

コンテナ起動

まずはリポジトリをクローンし、コンテナイメージをビルドします。

$ git clone https://github.com/ansible/galaxy
$ cd galaxy
$ make dev/build

「galaxy-dev」というイメージが出来上がっていればOK。

$ docker images
REPOSITORY                                                  TAG                 IMAGE ID            CREATED             SIZE
galaxy-dev                                                  latest              e73986ff5fbf        2 hours ago         1.02GB
...

以下のコマンドで起動します。

$ make dev/up_detached

ビルドしたイメージ以外に、PostgreSQL, rabbitMQ, influxDB, redisのコンテナが起動します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                NAMES
d8a0135542d8        galaxy-dev:latest   "/entrypoint start t…"   2 hours ago         Up 2 hours          0.0.0.0:8000->8000/tcp               galaxy_galaxy_1
5c7cdba1e404        postgres:9.5        "docker-entrypoint.s…"   3 hours ago         Up 3 hours          0.0.0.0:2345->5432/tcp               galaxy_postgres_1
67210023161e        rabbitmq:latest     "docker-entrypoint.s…"   3 hours ago         Up 3 hours          4369/tcp, 5671-5672/tcp, 25672/tcp   galaxy_rabbitmq_1
9028fbe7fec6        influxdb:latest     "/entrypoint.sh infl…"   3 hours ago         Up 3 hours          0.0.0.0:8086->8086/tcp               galaxy_influxdb_1
2906df012857        redis:latest        "docker-entrypoint.s…"   3 hours ago         Up 3 hours          6379/tcp                             galaxy_redis_1

しばらく待ってからhttp://<DockerホストのIP>:8000/ にアクセスすると、

こんな画面になっているはずです。

初期設定

このままだとログインできないため、Githubアカウントへのアプリ登録が必要となります。
まずは管理用ユーザーを作成します。この時、Githubアカウントで利用しているEmailアドレスを使用してはいけません。

$ make dev/createsuperuser
Create Superuser

Username: <管理ユーザー名>
Email address: <Githubに登録している以外のメールアドレス>
Password: <パスワード>
Password (again): <パスワード再入力>
Superuser created successfully.

Githubにログインし、右上の自分のアイコンをクリック→Settingsを選択。
左メニューからDeveloper settingsを選び、OAuth Appsの「Register a new application」をクリックします。

Application name: 任意の名前
Homepage URL: http://<DockerマシンのIP>:8000
Authorization callback URL: http://<DockerホストのIP>:8000/accounts/github/login/callback/
を入力して、「Register application」ボタンをクリックし、

表示されるClient IDとClient Secretの値を控えておきます。

http://<DockerホストのIP>:8000/adminを開くと、Djangoのログイン画面になるので、先ほど作成した管理用ユーザーでログインします。

SITES->Sitesの項目へ飛び、example.comとなっている行のDomain nameとDisplay nameをDockerマシンのIPに書き換えます。

次にSOCIAL ACCOUNTS->Social applicationsのAddをクリックし、以下のように入力します。
Provider: Github
Name: Github
Client id: Githubで表示されたClient ID
Secret key: Githubで表示されたClient Secret
Sites: Available sitesの中のIPアドレスを選んで右ボタンをクリック

登録が終わったら、右上のVIEW SITEからGalaxyのトップページに戻り、管理ユーザーからログアウトしてから右上のログインをクリックします。

OctocatのアイコンをクリックするとGithubの連携確認画面が表示されるので、Authorizeボタンを押すとログインできます。

これでローカルAnsible Galaxyの準備は完了です。

試してみる

サンプルのコレクションとPlaybookを作って実行してみます。

コレクション作成

以下コマンドを実行し雛形を作成します。Githubユーザー名(=Galaxyのログイン名)はNamespaceとして使われます。

$ ansible-galaxy collection init <Githubユーザー名>.sample_collection

以下のような構造でディレクトリ・ファイルが作成されます。

.
└── ussvgr
    └── sample_collection
        ├── README.md
        ├── docs
        ├── galaxy.yml
        ├── plugins
        │   └── README.md
        └── roles

適当なロールを作成

$ cd ussvgr/sample_collection/
$ mkdir -p roles/sample_role/tasks
$ mkdir -p roles/sample_role/meta
$ vi roles/sample_role/tasks/main.yml
$ vi roles/sample_role/meta/main.yml
roles/sample_role/tasks/main.yml
---
  - name: say hello
    debug:
      msg: "Hello World!"
roles/sample_role/meta/main.yml
galaxy_info:
  author: ussvgr
  description: sample role

galaxy.ymlを適宜編集してから、以下コマンドを実行しtar ballを作成します。

$ ansible-galaxy collection build

出来上がったtar ballはGalaxyのメニューのMy ContentからAdd Contentでアップロードします。

Playbook作成

AWX(Ansible Tower)で実行する場合、collections/requirements.ymlを以下のように作成することで自動でGalaxyからコレクションを取得してくれます。

collections/requirements.yml
---
collections:
  - ussvgr.sample_collection

取得したコレクション内のロールを実行するには以下のようなPlaybookを作成します。

site.yml
---
- hosts: all
  tasks:
    - name: import roles
      import_role:
        name: ussvgr.sample_collection.sample_role

AWX設定

設定->ジョブ内のプライマリー GALAXY SERVER URLにDockerホストのIP:ポートを設定、ロールとコレクションのダウンロードを有効にしておきます。

これで作成したPlaybookを実行すると、

ローカルのAnsible Galaxyからコレクションを取得して実行してくれました。

終わりに

ちゃんと使う場合はPostgreSQLコンテナのPGDATAボリュームを永続化すればいいのかな?

社内でのPlaybookの共有・再利用方法を悩んでいましたが、ちょっと道筋が立ちそうです。
コレクションについてはもっと勉強せねば。