こんにちは。
初めまして Ansible アドベントカレンダー
TL;DR
-
roles のあるリポジトリ(たとえば
https://gitlab.com/hogehoge/hoge.git
)、にgalaxy.yml
を作成するgalaxy.ymlnamespace: "hello" name: "world" version: "1.0.0" readme: "README.md" <略>
read_apiとread_repository権限のついた、gitlab Personal Access Tokenを作る
-
~/.netrc
を作る.netrcmachine gitlab.com login yourname@gitlab.com password yourpersonalaccesstoken
-
playbook があるリポジトリで
requirements.yml
を書くrequirements.yml--- collections: - name: https://gitlab.com/hogehoge/hoge.git type: git version: 1.0.0 # あるいは branch 名などでもOK
ansible-galaxy collection install -r ./requirements.yml
する-
playbook の中で collection の roles を参照する
playbook.yaml--- - hosts: - some_host become: true collections: - hello.world roles: - japanese/konnichiwa_sekai
ansible playbook ...
すると実行できます
はじめに
我々のチームでは、ansible スクリプトをチーム内で細々と運用管理してきました。
これまでは、ansible で設定が必要な VM も少なく、公式ベストプラクティスで示される Playbooks のディレクトリ構成の1つのリポジトリに全て突っ込んでいて、特に不自由はありませんでした。
ところが、今年に入ってから ansible で設定(もしくはコンテナをデプロイするなど)したい VM 群が急増し、モノリポでの運用が難しくなってきました。これまでの VM とは用途が異なるものが追加され、inventories はきちんと分けたいけど、これまで作ってきた roles は共有したいというシチュエーションがありました。
また、 ansible-playbook --check
によるいわゆるドライランや、場合によってはデプロイも CICD パイプラインから実施しており、VM 数が増えたことで、パイプラインのコントロールが難しくなったことも、リポジトリを分割したい要因でした。
やりたいこと
roles内もさまざまなカテゴリーのものが入り乱れていたため、下記の方針を立てました。
- roles 側のリポジトリ
- roles は再利用性を高め、専用のリポジトリに分ける
- アプリ開発におけるライブラリ的な位置付け
- コンテナを操作したりアプリケーションをデプロイするものと、マシンをセットアップする系はリポジトリを分ける
- メンテナンス頻度や、メンテナそのものが異なる可能性も考慮して
- roles は再利用性を高め、専用のリポジトリに分ける
- playbook 側のリポジトリ
- roles を参照する playbook は、マシンの用途に応じてリポジトリを分ける
- playbook リポジトリからは、roles リポジトリを git tag で参照できると良い
- もちろん、CICD パイプラインからも roles リポジトリを参照できないといけない
やったこと
お待たせしました。本題です。
我々は、開発にGitLabのプライベートリポジトリを使用しているので、GitLab上の Ansible Playbook リポジトリから、別プライベートリポジトリにある、roles を参照しなくてはなりません。
以前、「gitlab の private repository を go get する」という記事を書きましたが、やらなければいけないことはほとんど同じでした。
roles collection リポジトリ設定
まず、既存のモノリポから roles を引き離し、分類して、それぞれ collection として公式のドキュメントに従って、構成し直しました。
hoge.git/
├── docs/
├── galaxy.yml
├── README.md
├── roles/
│ ├── role1/
│ ├── role2/
│ └── .../
└── tests/
この時、 galaxy.yml
にはここにあるパラメータを含めることができます。
例えば、下記のような collection だと、 インストール後に ansible-galaxy collection list
を実行した際に、 hello.world 1.0.0
という表示になります。
namespace: "hello"
name: "world"
version: "1.0.0"
readme: "README.md"
<略>
collection 側の設定はこれで全てです。
playbook リポジトリ設定
この collection をローカル環境にインストールすることで、playbook 側で参照できるようになります。
プライベートリポジトリにある collection をローカルにインストールするには、認証を行う必要があるのですが、それは ~/.netrc
ファイルを作成することで可能になります。GitLab リポジトリの場合、gitlab Personal Access Tokenを使用して、下記のようなファイルを作成します。
machine gitlab.com
login yourname@gitlab.com
password yourpersonalaccesstoken
実際にインストールできるか確かめてみましょう。
例えば下記のコマンドの場合、git+
で明示的に git リポジトリからのインストールであることを指し、,
以降はブランチ名やタグ名が指定できます。他にもさまざまな形式がサポートされています。
この例の場合、https://gitlab.com/hogehoge/hoge.git
という git リポジトリの dev ブランチをインストールしています。
ansible-galaxy collection install git+https://gitlab.com/hogehoge/hoge.git,dev
hello.world:1.0.0 was installed successfully
というように出力されれば OK です。インストールした collection は ~/.ansible/collections/ansible_collections
に配置されていました。
複数の roles collection をインストールする場合、コマンドを羅列する必要はありません。
playbook 側のリポジトリに、requirements.yml
という yaml ファイルを作成し、下記のコマンドを実行することで、一括インストールすることができます。
ansible-galaxy collection install -r ./requirements.yml
このとき、 requirements.yml
には下記のような内容を記述します。先ほどコマンドで指定した内容が記載されます。
---
collections:
- name: https://gitlab.com/hogehoge/hoge.git
type: git
version: 1.0.0 # あるいは branch 名などでもOK
こちらも先ほどと同様に hello.world:1.0.0 was installed successfully
というように出力されれば OK です。
最後に、playbook の中で、インストールした roles を使う宣言を書きます。
たとえば下記のように collections
に先ほどインストールした collection 名を指定し、roles では、collection 側リポジトリの rols/
ディレクトリ配下のパスを記述します。
---
- hosts:
- some_host
become: true
collections:
- hello.world
roles:
- japanese/konnichiwa_sekai
これで、晴れて collections リポジトリの roles を参照して、playbook が実行できるようになりました
おまけ - CICD パイプラインでの collection インストール
GitLab CICDする際に、動的に collection をインストールするには、下記のように、.gitlab-ci.yml
内で、.netrc
ファイルを作成します。
このときの認証情報には、${CI_JOB_TOKEN}
という runner によって事前に定義された環境変数が使用できます。
ansible-play:
stage: deploy
image: your.registry/ansible:4.9.0
script:
- |
cat <<EOL >> $HOME/.netrc
machine gitlab.com
login gitlab-ci-token
password ${CI_JOB_TOKEN}
EOL
- ansible-galaxy collection install -r ./requirements.yml
- ansible-playbook playbook.yml -i inventories/inventory.yml -u user -D
まとめ
これまで、いわゆる Go や Python などのアプリケーションでは、ライブラリの配布方法や、その形態などを考えることが多かったのですが、ansible でもいい感じに再利用可能な package 配布の仕組みを構築することができました
学び