【Ansible】GitLab RunnerでAnsible実行環境のコンテナイメージを使いたい～第2章：Runnerの登録・実行～

## はじめに

2021年頃からAnsible実行環境のコンテナ化が進んできています。今回は、Amazon EC2を用いて、GitLab Runner経由でAnsible実行環境のコンテナイメージを使用可能にするまでの流れを紹介します。  
第2章では「Runnerの登録・実行」を実施します。

## TL;DR

- GitLab Runner実行時に、Ansible実行環境のコンテナイメージを指定することが可能
- Ansible実行環境のコンテナイメージを使用することで、開発とプロダクション間の環境差分のリスクが減る
- `execution-environment.yml`には、OSパッケージ・Pythonモジュール・Collectionなどを指定する

## 前提条件

- GitLabの最低限の操作を理解していること（プロジェクトの作成・ファイルの編集）
- AWSにGitLabが構築済みであること（実際に操作する場合）
  - 手順は、前の記事[【Ansible】GitLab RunnerでAnsible実行環境のコンテナイメージを使いたい～第1章：GitLabの構築～][6]を参照

## 実行環境

- Red Hat Enterprise Linux: 9.2
- GitLab: v16.7.0-ee
- GitLab Runner: 16.7.0
- Python: 3.9.16
- Podman: 4.6.1
- Ansible Builder: 3.0.0

## 詳細

GitLab RunnerにおけるGroup Runnerを使用して、`ec2-user`ユーザーが作成したAnsible実行環境のコンテナイメージを使えるようにします

### 1. Group用のToken作成

1. ブラウザからGitLabにログインする
    - URL
      - http://\<GitLab Global IPv4 Address>
    - user
      - root
    - password
      - 設定したパスワード
2. 画面左の[Groups]を選択する
3. [New Group]を選択する
4. [Create group] を選択する
5. 以下の内容を入力し、[Create Group]を選択する
    - Group name
      - test_group
    - Group URL
      - http://\<GitLab Global IPv4 Address\>/test_group
    - Visibility level
      - Private
6. 作成されたGroup（`test_group`）画面左の、[Build] > [Runners]を選択する
7. 右上の`・・・`を選択し、`Registration token`の下にある`Group用のToken`をメモしておく（Runnerの登録時に使用する）

    ![group_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/0d856275-2f6e-4ea3-88c1-3485120f73e0.png)

### 2. Podmanのインストール

1. ターミナルソフト（Tera Termなど）でサーバーにログインする
    - IP Address
      - \<GitLab Global IPv4 Address>
    - user
      - ec2-user

    > :warning: RHEL9に対してRSA鍵でSSHログインする場合、Tera Termのバージョンは5以上にする必要がある

2. podmanをインストールする

    ```console
    $ sudo dnf install -y podman
    ```

3. podmanがインストールされたことを確認する

    ```console
    $ podman --version
    podman version 4.6.1
    ```

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

[Red Hat > Set up GitLab CI and GitLab Runner to configure Ansible automation controller][2]によると、RHEL 8ではDockerの代わりにPodmanを使用するようにGitLab Runnerを構成するのが合理的だそうです。RHEL 9でも同じ手順で可能でした。

1. GitLab Runnerのパッケージをリポジトリに追加する

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

2. GitLab Runnerをインストールする

    ```console
    $ sudo dnf install -y gitlab-runner
    ```

3. GitLab Runnerがインストールされたことを確認する

    ```console
    $ gitlab-runner --version
    Version:      16.7.0
    ～以下、省略～
    ```

4. Podmanソケットを有効にして起動する
    - `ec2-user`ユーザーの状態で以下のコマンドを実行することで、`ec2-user`ユーザーが作成したAnsible実行環境のコンテナイメージを使えるようになる

    ```console
    $ systemctl enable --user --now podman.socket
    ```

5. Podmanソケットがリッスンしていることを確認する

    ```console
    $ systemctl status --user podman.socket
    ● podman.socket - Podman API Socket
        Loaded: loaded (/usr/lib/systemd/user/podman.socket; enabled; preset: disabled)
        Active: active (listening) since Sat 2023-12-30 12:54:31 UTC; 46min ago
          Until: Sat 2023-12-30 12:54:31 UTC; 46min ago
      Triggers: ● podman.service
          Docs: man:podman-system-service(1)
        Listen: /run/user/1000/podman/podman.sock (Stream)
        CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/podman.socket
    ```

    その際に、`Listenに書いてあるパス`をメモしておく（Runnerの登録で使用する）

    ```
    /run/user/1000/podman/podman.sock
    ```

6. `ec2-user`ユーザーがログアウトした後も、Podmanソケットを利用可能にする
    - これを実行しない場合、EC2インスタンスを停止->開始した後に`ec2-user`ユーザーでログインし直さないとpodmanのサービスが起動せず、GitLab Runnerが失敗する

    ```console
    $ sudo loginctl enable-linger ec2-user
    ```

### 4. Ansible Builderのインストール

1. Python仮想環境を作成する

    ```console
    $ python3 -m venv ~/venv
    ```

2. Python仮想環境を起動する

    ```console
    $ source ~/venv/bin/activate
    ```

3. Ansible Builderをインストールする

    ```console
    $ pip install ansible-builder
    ```

4. Ansible Builderがインストールされたことを確認する

    ```console
    $ ansible-builder --version
    3.0.0
    ```

### 5. Ansible BuilderによるAnsible実行環境のコンテナイメージの作成

1. ホームディレクトリ（/home/ec2-user）に移動する

    ```console
    cd ~
    ```

2. 作業用のディレクトリを作成し、移動する

    ```console
    $ mkdir custom-ee && cd custom-ee
    ```

3. 実行環境のコンテナイメージ用のファイルを作成する
    - `execution-environment.yml`には、OSパッケージ・Pythonモジュール・Collectionなどを指定する

    ```console
    $ vi execution-environment.yml
    ```

    ```yaml
    ---
    version: 3

    images:
      base_image:
        name: quay.io/centos/centos:stream9-minimal

    options:
      package_manager_path: /usr/bin/microdnf

    dependencies:
      python_interpreter:
        package_system: python3.11
        python_path: /usr/bin/python3.11
      ansible_core:
        package_pip: ansible-core==2.16.0
      ansible_runner:
        package_pip: ansible-runner==2.3.0
      python:
        - ansible-lint
        - yamllint
      galaxy:
        collections:
          - ansible.utils
    ```

4. Ansible実行環境のコンテナイメージを作成する

    ```console
    $ ansible-builder build -f execution-environment.yml -t ansible216:v1.0 -v 3
    ```

5. Ansible実行環境のコンテナイメージが作成されたことを確認する

    ```console
    $ podman images
    REPOSITORY             TAG              IMAGE ID      CREATED             SIZE
    localhost/ansible216   v1.0             XXXXXXXXXXXX  About a minute ago  295 MB
    <none>                 <none>           XXXXXXXXXXXX  About a minute ago  298 MB
    <none>                 <none>           XXXXXXXXXXXX  About a minute ago  235 MB
    quay.io/centos/centos  stream9-minimal  XXXXXXXXXXXX  2 weeks ago         100 MB
    ```

### 6. Runnerの登録

1. Runnerを登録する
    - [GitLab > GitLab Runner commands][5]によると、`--non-interactive`で一気にコマンド入力が可能
    - ここで、前の手順でメモした`Group用のToken`を使用する

    ```console
    $ sudo gitlab-runner register \
    --non-interactive \
    --url 'http://<GitLab Private IPv4 Address>' \
    --registration-token '<GitLab Group Token>' \
    --executor 'docker' \
    --docker-image centos:stream9-minimal \
    --description 'runner test' \
    --tag-list 'ansible_ee'
    ```

2. config.tomlを編集する

    ```console
    $ sudo vi /etc/gitlab-runner/config.toml
    ```

    - 以下の設定を追加
      - `[[runners]]`セクション

        ```toml
        environment = ["FF_NETWORK_PER_BUILD=1"]
        clone_url = "http://<GitLab Private IPv4 Address>"
        ```

      - `[runners.docker]`セクション
        - GitLab Runnerでは`ec-user`ユーザーで作成したAnsible実行環境のコンテナイメージを使用する
        - ここで、前の手順でメモした`Listenに書いてあるパス`を使用する

        ```toml
        host = "unix:///run/user/1000/podman/podman.sock"
        pull_policy = "never"
        ```

3. GitLab Runnerを再起動する

    ```console
    $ sudo gitlab-runner restart
    ```

### 7. CIパイプラインの実行

1. ブラウザからGitLabにログインする
    - URL
      - http://\<GitLab Global IPv4 Address>
    - user
      - root
    - password
      - 設定したパスワード
2. ホーム画面での`Create a project`を選択する
3. `Create blank project`を選択する
4. 以下の内容を入力し、`Create project`を選択する
    - Project name
      - test_project
    - Project URL
      - http://\<GitLab Global IPv4 Address>/test_group/test_project
    - Visibility Level
      - Private
    - Project Configuration
      - `Initialize repository with a README`にチェック
5. [Edit] > [Web IDE]を選択して、編集画面を開く

    ![web_ide.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/3507bd02-ed29-d632-72b7-5db01b1c3070.png)

6. 以下のような`.gitlab-ci.yml`を作成する

    ```yaml
    ---
    default:
      image: localhost/ansible216:v1.0

    stages:
      - stage_1

    job_1:
      stage: stage_1
      script:
        - ansible --version
        - ansible-galaxy collection list
      tags:
        - ansible_ee
    ```

7. 変更内容をCommitして、Project（`test_project`）の画面に戻る

    ![commit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/bf746daf-8b12-07ab-ade4-acfc1e5f1669.png)

8. 画面左の[Build] > [Jobs]を選択する
    - Job実行時のtag（`ansible_ee`）が確認できる

    ![job.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/60147171-860d-b49e-00ad-e9fefd1c6d74.png)

9. 最新のJobを選択し、成功していることを確認する

    ```console
    $ ansible --version
    ansible [core 2.16.0]
      config file = None
      configured module search path = ['/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
      ansible python module location = /usr/local/lib/python3.11/site-packages/ansible
      ansible collection location = /runner/.ansible/collections:/usr/share/ansible/collections
      executable location = /usr/local/bin/ansible
      python version = 3.11.5 (main, Sep  7 2023, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/usr/bin/python3.11)
      jinja version = 3.1.2
      libyaml = True
    $ ansible-galaxy collection list
    # /usr/share/ansible/collections/ansible_collections
    Collection    Version
    ------------- -------
    ansible.utils 3.0.0
    Job succeeded
    ```

## さいごに

- GitLab Runner実行時に、Ansible実行環境のコンテナイメージを指定することが可能であることがわかりました
- Ansible実行環境のコンテナイメージを使用することで、開発とプロダクション間の環境差分のリスクが減るはずなので積極的に活用しましょう
  - 「あれ？同じPlaybookを実行しているのにエラーになるぞ？」ということが減るはずです

## 参考URL

- [GitLab > Manage runners][1]
  - GitLab Runnerにおけるタイプごとの設定方法
- [Red Hat > Set up GitLab CI and GitLab Runner to configure Ansible automation controller][2]
  - GitLab Runnerで Podman を使用する方法（1）
- [opensource > How to use Podman in GitLab Runners][3]
  - GitLab Runnerで Podman を使用する方法（2）
- [Ansible Builder Documentation > Execution Environment Definition][4]
  - `execution-environment.yml`の記載方法
- [GitLab > GitLab Runner commands][5]
  - gitlab-runnerコマンドの使い方

## 関連記事

- [【Ansible】GitLab RunnerでAnsible実行環境のコンテナイメージを使いたい～第1章：GitLabの構築～][6]

---

[1]: https://docs.gitlab.com/ee/ci/runners/runners_scope.html
[2]: https://www.redhat.com/sysadmin/gitlab-runner-ansible-config-code
[3]: https://opensource.com/article/23/3/podman-gitlab-runners
[4]: https://ansible.readthedocs.io/projects/builder/en/stable/definition/
[5]: https://docs.gitlab.com/runner/commands/
[6]: https://qiita.com/masa2223/items/081302acf9b6f63413b5