[Ansible]オンプレ環境のAAP設定を効率化: GitLab Runnerの新しい使い方

# はじめに

[以前の記事](https://qiita.com/miyuk/items/d0d21bd0175b875aebe1)でGitLab Runnerからオンプレ環境AAPの設定を行う方法を試しました。

その際、インターネットからオンプレ環境にあるAAPへの通信手段としてCloudflare Zero Tunnelを使い、AAPのWebhookを実行していました。

しかし、この方法ではAAP側にPlaybookを実行するためのジョブテンプレートを用意しておく必要があり、また投入結果をGitLab側から確認することができませんでした。

その後、色々調べてみるとGitLab Runnerをオンプレ環境側に置いてそこから処理できるらしく、今回はGitLab RunnerからPlaybookを実行してAAP設定変更をやってみました。

全体構成は下図のとおり。
特徴としては、GitLab Runnerのexecutorとしてpodmanを利用し、podman-in-podman構成にしてEEによるPlaybook実行環境を構築しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335255/e3bcaf64-4c31-c512-6e0f-8b5621d002a1.png)

# 環境

## AAP
- OS: RHEL 8.6
- AAP: 2.2
- ansible.controller collection: 4.4.0

## GitLab Runner

- OS: RHEL9
- GitLab Runner: 16.4.1

# 構築

## GitLab Runnerサーバ構築

まずは、オンプレ環境にGitLab Runnerを構築します。
前提として、SELinuxはdisableにします。

基本的には、[GitLab Runnerドキュメント](https://docs.gitlab.com/runner/install/)を参考に構築しています。

### GitLab Runnerのインストール

以下コマンドでYUMレポジトリを追加します。

```bash
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash
```

その後、dnfコマンドでgitlab-runnerをインストールします。

```bash
dnf install gitlab-runner
```

インストールされると、`gitlab-runner`コマンドとユーザが作成されます。

### podmanのインストール

以下コマンドより、podmanをインストールします。

```bash
dnf install podman
```

インストールできたら、~~本来は`gitlab-runner`ユーザとしてrootlessモードとしたほうがいいですが面倒なので~~rootfullモードとして`podman.socket`を立ち上げます。

```bash
systemctl --now enable podman.socket
```

## GitLab Runner登録

GitLab RunnerとGitLabを紐づけるための設定を行います。

まずは、GitLabでRunnerを利用したイレポジトリにアクセスし、
`設定` > `CI/CD` > `Runner`より`新規プロジェクトRunner`
を選択します。

ここでは、tagに`tokyo`を指定して、ワークフローでタグ指定された際に、当該Runnerを動かすように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335255/bd99cd91-512a-8cb6-1504-2d6facd8d0e4.png)

`ランナーを作成`を押すと、以下画面が出てGitlab Runnerを登録するためのトークン情報が含まれたコマンドが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335255/06d0d080-3784-53cd-5755-f13fedcc471b.png)


これを、Runnerサーバで実行すると以下ガイダンスプロンプトが始まります。
ぽちぽち進めていけばいいですが、`Enter an executor`は`docker`を選択してください。

```bash
# gitlab-runner register --url https://gitlab.com --token ************
Runtime platform                                    arch=amd64 os=linux pid=16918 revision=d89a789a version=16.4.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
[https://gitlab.com]:
Verifying runner... is valid                        runner=BCiv6Tvms
Enter a name for the runner. This is stored only in the local config.toml file:
[hostname.local]:
Enter an executor: docker-windows, shell, ssh, virtualbox, docker-autoscaler, docker+machine, custom, docker, instance, parallels, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.7):
quay.io/podman/stable
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
```

## podman-in-podman利用するための設定変更

今回実行するパイプラインはpodman-in-podman利用するため、podman上からpodmanを実行するための権限が必要になります。
そのため、設定ファイル(`/etc/gitlab-runner/config.toml`)を直接編集する必要があります。

変更箇所としては、`privileged`を`true`にするのみでOK！

```toml:/etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "hostname.local"
  url = "https://gitlab.com"
  id = *******
  token = "**************"
  token_obtained_at = 2023-10-13T13:15:44Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  [runners.cache]
    MaxUploadedArchiveSize = 0
  [runners.docker]
    tls_verify = false
    image = "quay.io/podman/stable"
    #privileged = false
    privileged = true # ★trueに変更
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
```

## CI/CDパイプラン定義

まずは、CI/CDパイプラインで利用する変数を定義します。
今回は以下のような変数を用意しました。

registryへの認証情報は、[Registry Service Accounts](https://access.redhat.com/terms-based-registry/accounts)を作成して今回のレポジトリ専用のものを入力しました。

- `CONTROLLER_HOST`: AAPのURL
- `CONTROLLER＿OAUTH_TOLEN`: AAPのadmin権限トークン(事前にAAP側で作成)
- `REDHAT_REGISTRY`: registry.redhat.io(EEダウンロードのために利用)
- `REDHAT_REGISTRY_USER`: registryへのログインユーザ名
- `REDHAT_REGISTRY_PASSWORD`: registryへのログインパスワード


次にパイプライン本体ですが、以下のとおりです。

```yaml:.gitlab.yml
workflow:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

stages:
  - deploy

deploy-aap:
  stage: deploy
  tags:
    - tokyo
  image: quay.io/podman/stable:latest
  script:
    - podman login -u $REDHAT_REGISTRY_USER -p $REDHAT_REGISTRY_PASSWORD $REDHAT_REGISTRY
    - dnf install -y python3 python3-pip
    - pip install ansible-navigator
    - >-
      ansible-navigator run configure_aap.yml
      --eei registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel8:latest
      --penv CONTROLLER_HOST
      --penv CONTROLLER_OAUTH_TOKEN
      --mode stdout
      --pae false
      --lf /dev/null
```

tagsで先ほど作成したRunnerのtagを指定することで実行するRunnerを指定することができます。

AAPを設定変更するために、`ansible.controller`コレクションが必要となり二通りを検討しました。

①Automation Hubからコレクションとして取得する
②Red Hat RegistryからAAP用のEEの中にあるものを使う

どちらも、認証が必要となるのですが①は30日利用しないと失効するトークンを使う必要があるので、運用しやすさから②の方法にしました。

EEからの実行となるため、Ansible Navigatorを使ってEEから実行するようにしました。
環境変数はそのままでは使えないのでAAPへの接続情報を`--penv`で渡しています。
デフォルトだと、ユーザインターフェースモードが`interactive`となり、Runnerではエラーとなってしまうので`--mode stdout`にしています。
あとは、出力されるファイルをゼロにするためオプションを追加しています。

# 実行結果

レポジトリのmainにpushすると、パイプラインが実行され、オンプレ側のGitLab Runnerから実行されました。
特に、CPU負荷も上がらず実行完了。

時間についても、通常のGitLab Runnerを使うぐらいのスピードで

- 実行準備～実行開始：10秒
- 実行開始～Ansible Navigator準備：180秒
- Playbook実行：100秒

と大体4分程度で実行完了しました。

Playbookログも色付きで出力されるので証跡としても十分使いやすくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335255/281e681a-157a-8bea-26f3-612339766ace.png)


# おわりに

GitLab Runnerでpodmanを使う方法ですが以前はドキュメントになく、トリッキーな方法でしたがGitLab 15.3で方法追加されたようでかなり使いやすくなったみたいです。

podman-in-podmanはとても便利で、使い方次第ではなんでもできると感じたので使い方を探っていきたいと思います。

セキュリティ的にも外向きに穴をあけるわけでもないので十分堅牢かと思うので今後もGitLab Runnerを活用したいと思います。
ただ、rootless podman使っていないのは個人的には気になるのでそこは今後修正します。

# 参考リンク

https://docs.gitlab.com/runner/install/linux-manually.html

https://docs.gitlab.com/runner/executors/docker.html

https://rheb.hatenablog.com/entry/podman-in-podman