gitlab-runner を Proxy 環境で使う

エンジニアとProxyは切っても切れない関係にあります（そういう会社や環境があります）。

gitlab-runner を proxy環境下で使おうとしたのですが、GitLab公式の解説では十分ではありませんでした。
ここでは、特定の状況を想定した場合のみですが、proxy環境下で使う方法を紹介します。

# gitlab-runner のインストールと実行

gitlab-runnner として、パッケージ版やバイナリ版、Docker版などが提供されています。[Install GitLab Runner](https://docs.gitlab.com/runner/install/)

ここでは、Debian/Ubuntuパッケージ版 を使う場合と、Docker版を使う場合について、Proxy設定からregisterまでの方法を説明します。

# Debian/Ubuntu パッケージ版 を使う場合

[Installing GitLab Runner](https://docs.gitlab.com/runner/install/linux-repository.html#installing-gitlab-runner) に解説があるので参考にしながら進めます。

## Proxy設定

gitlab-runner プログラムは http_proxy環境変数を読み取ってくれるようです。
起動時に毎回ターミナルで`export http_proxy=`とするのも面倒ですし、`sudo gitlab-runner` とsudoする場合は、デフォルトでは環境変数は引き継がれません。（-Eで環境変数を引き継ぐことが可能）
ここでは、/etc/profile でhttp_proxy環境変数を設定することで、Proxy設定をグローバルに設定することとします。

さらに、`apt-get install gitlab-runnner`がProxy経由で可能となるよう、apt の設定ファイルにProxy設定を行います。

```sh
$ cat <<EOF | sudo tee /etc/profile
export http_proxy=http://proxy:8080/
export https_proxy=http://proxy:8080/
export no_proxy=localhost,127.0.0.1
EOF

$ cat <<EOF | sudo tee /etc/apt/apt.conf.d/98proxy
Acquire::http::Proxy "http://proxy:8080";
Acquire::https::Proxy "http://proxy:8080";
EOF
```

## インストール

gitlab-runnnerをインストールします。

```sh
# sudo -i として、/etc/profileの反映した状態でスクリプトを実行する
$ curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo -i bash

$ sudo apt-get install gitlab-runner
```

## register

gitlab-runner を Gitlabにregistします。

```sh
# sudo -i として、/etc/profileの反映した状態でスクリプトを実行する
$ sudo -i gitlab-runner register
Runtime platform arch=amd64 os=linux pid=16 revision=de104fcd version=14.5.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com/
Enter the registration token:
abcdefgabcdefg
Enter a description for the runner:
[b9676290e5c5]: 
Enter tags for the runner (comma-separated):

Registering runner... succeeded runner=sHf2dtHx
Enter an executor: custom, docker, parallels, shell, ssh, docker+machine, docker-ssh+machine, docker-ssh, virtualbox, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.6):
ruby:2.6
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 
```

これで、GitLabからCIを実行できるようになりました。

# gitlab-runner （Docker版）を使う場合

[Install the Docker image and start the container ](https://docs.gitlab.com/runner/install/docker.html#install-the-docker-image-and-start-the-container) に解説があるので参考にしながら進めます。

## Proxy設定

docker サービス自体がProxy経由でインターネットに接続できるように設定します。

```sh
# コンテナイメージをインターネットからダウンロードする（docker pull時）に使うproxyの設定

$ sudo mkdir -p /etc/systemd/system/docker.service.d/

$ cat <<EOF| sudo tee /etc/systemd/system/docker.service.d/10-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy:8080"
Environment="HTTPS_PROXY=http://proxy:8080"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF

$ sudo systemctl daemon-reload
```

```sh
# （必要であれば）コマンドラインで docker build する際に使うproxyの設定
$ mkdir ~/.docker
$ cat <<EOF > ~/.docker/config.json
{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://proxy:8080/",
     "httpsProxy": "http://proxy:8080/",
     "noProxy": "localhost,127.0.0.0/8"
   }
 }
}
EOF
```

## インストール（コンテナ実行）

gitlab-runner コンテナイメージをgit pullし、同時に実行させます。
このとき、`-e http_proxy`を指定することで、コンテナ内にhttp_proxy環境変数を設定します。
gitlab-runner プロセスは、この環境変数を読み取って実行されます。

```sh
# gitlab-runnner が gitlab に接続する際に使うproxyを環境変数で指定して起動する
$ docker run -d --name gitlab-runner --restart always \
     -v /srv/gitlab-runner/config:/etc/gitlab-runner \
     -v /var/run/docker.sock:/var/run/docker.sock \
     -e http_proxy=http://proxy:8080/ \
     -e https_proxy=http://proxy:8080/ \
     gitlab/gitlab-runner:latest
```

## register

gitlab-runner を Gitlabにregistします。
`docker exec`コマンドを使い、先ほど起動したコンテナ内で`gitlab-runner register`コマンドを実行します。
（`docker run`コマンドにhttp_proxy環境変数を追加指定して`gitlab-runner register`コマンドを実行しても同様の結果になります）

```sh
$ docker exec -it gitlab-runner gitlab-runner register
Runtime platform arch=amd64 os=linux pid=16 revision=de104fcd version=14.5.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com/
Enter the registration token:
abcdefgabcdefg
Enter a description for the runner:
[b9676290e5c5]: 
Enter tags for the runner (comma-separated):

Registering runner... succeeded runner=sHf2dtHx
Enter an executor: custom, docker, parallels, shell, ssh, docker+machine, docker-ssh+machine, docker-ssh, virtualbox, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.6):
ruby:2.6
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 
```

これで、GitLabからCIを実行できるようになりました。

# tips
## gitlab-runner docker executer を使う場合で、.gitlab-ci.yml にproxy設定を書きたくない場合

docker executorを使う場合、ここまでの設定を行っても、CIで使われるdockerコンテナ自身にはProxy設定は反映されません。
このままでは、コンテナ内でgit clone したり、インターネットに接続したりするために、.gitlab-ci.yml にProxy設定を書く必要があります。

[Adding the Proxy to the Docker containers](https://docs.gitlab.com/runner/configuration/proxy.html#adding-the-proxy-to-the-docker-containers)には、pre_clone_scriptをconfig.tomlに書くことで、自動的にProxy設定をコンテナに対して行おう方法が紹介されています。

```
# gitlab-runnerコンテナ内の/etc/gitlab-runner/config.toml に対応するファイル（今回の例では/srv/gitlab-runner/config/config.toml）を直接編集します
# gitlab-runner コンテナにvimなどのエディタが含まれていないため

$ sudo vim /srv/gitlab-runner/config/config.toml

[[runners]]
  name = "b9676290e5c5"
  url = "https://gitlab.com/"
  token = "abcdefgabcdefg"
  executor = "docker"
  pre_clone_script = "git config --global http.proxy $HTTP_PROXY; git config --global https.proxy $HTTPS_PROXY"
  environment = ["https_proxy=http://proxy:8080", "http_proxy=http://proxy:8080", "HTTPS_PROXY=proxy:8080", "HTTP_PROXY=proxy:8080"]
```

gitlab-runner がファイルの変更を監視して自動的に再読み込みしてくれるため、コンテナの再起動は不要です。

## gitlab-runner （Docker版）をdocker-composeで実行したい場合

```yaml:docker-compose.yml
version: '2'
services:
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    restart: always
    volumes:
      - /srv/gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - http_proxy=http://proxy:8080/
      - https_proxy=http://proxy:8080/
```

```sh
docker-compose up -d
docker-compose exec gitlab-runner gitlab-runner register
```

## オンプレGitlabへの接続で証明書エラーが発生する場合

オレオレ証明書、もしくは独自CA環境なオンプレGitLabへregister する際、証明書エラーが発生してregisterができません。

```
# gitlab-runner register   
Runtime platform  arch=amd64 os=linux pid=4618 revision=0e5417a3 version=12.0.1
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://mygitlab.example.com/ 
Please enter the gitlab-ci token for this runner:
abcdefgabcdefg
Please enter the gitlab-ci description for this runner:
[b9676290e5c5]: 
Please enter the gitlab-ci tags for this runner (comma separated):

ERROR: Registering runner... failed  runner=b9676290e5c5 status=couldn't execute POST against https://mygitlab.example.com/api/v4/runners: Post https://mygitlab.example.com/api/v4/runners: x509: certificate signed by unknown authority
PANIC: Failed to register this runner. Perhaps you are having network problems 
```

Proxy環境の有無は関係ありませんが、解決方法をメモとして書いておきます。

### Debian/Ubuntu パッケージ版 の場合
後で書く

### gitlab-runner （Docker版）の場合

後で書く


**参考**
- [Self-signed certificates or custom Certification Authorities | GitLab](https://docs.gitlab.com/runner/configuration/tls-self-signed.html)
- [Gitlab runnerをregistをしようとした時のエラーを回避する - ろーてくxyz blog](https://blog.rotek.xyz/entry/2019/08/08/165955)