GitLab Runnerをプロキシの後ろで実行する方法

このガイドでは、GitLab Runner with Docker executorをプロキシの背後で動作させることに特化しています。

続行する前に、同じマシンにDockerと GitLab Runnerが インストール済みであることを確認してください。

CNTLMの設定

note
すでに認証なしのプロキシを使用している場合、このセクションは省略可能で、そのままDockerの設定に進むことができます。CNTLMの設定は認証のあるプロキシを使用している場合にのみ必要ですが、どのような場合でも使用することをお勧めします。

CNTLMはローカルプロキシとして使用できるLinuxプロキシで、プロキシの詳細を手動であちこちに追加するのに比べて2つの大きな利点があります:

  • クレデンシャルを変更する必要があるソースがひとつであること。
  • 認証情報はDocker Runnerからはアクセスできません。

CNTLMをインストールしたと仮定して、まずそれを設定する必要があります。

CNTLM がdocker0 インターフェースをリッスンするようにします。

さらにセキュリティを高め、コンテナ内部からサーバを保護するために、コンテナ内部から到達可能な IP を持つdocker0 インタフェースをリッスンするように CNTLM をバインドすることができます。DockerホストのCNTLMにこのアドレスにのみバインドするように指示すると、Dockerコンテナはこのアドレスに到達できますが、外部からは到達できません。

  1. Dockerが使用しているIPを見つけてください:

    ip -4 -oneline addr show dev docker0
    

    これは通常172.17.0.1 、ここではdocker0_interface_ip とします。

  2. CNTLM (/etc/cntlm.conf) の設定ファイルを開きます。ユーザー名、パスワード、ドメイン、プロキシホストを入力し、前のステップで見つけたListen の IP アドレスを設定します。以下のようになります:

    Username     testuser
    Domain       corp-uk
    Password     password
    Proxy        10.0.0.41:8080
    Proxy        10.0.0.42:8080
    Listen       172.17.0.1:3128 # Change to your docker0 interface IP
    
  3. 変更を保存し、サービスを再起動します:

    sudo systemctl restart cntlm
    

イメージをダウンロードするためのDockerの設定

note
以下は、systemd をサポートしている OS に適用されます。

プロキシの使い方はDockerのドキュメントに従ってください。

サービスファイルは以下のようになります:

[Service]
Environment="HTTP_PROXY=http://docker0_interface_ip:3128/"
Environment="HTTPS_PROXY=http://docker0_interface_ip:3128/"

GitLab Runner 設定へのプロキシ変数の追加

GitLab Runner の設定にプロキシ変数を追加して、プロキシの後ろで GitLab から割り当てられたビルドを取得できるようにします。

これは、上記の Docker サービスにプロキシを追加するのと基本的には同じです:

  1. gitlab-runner サービス用の systemd ドロップインディレクトリを作成します:

    mkdir /etc/systemd/system/gitlab-runner.service.d
    
  2. HTTP_PROXY 環境変数を追加する/etc/systemd/system/gitlab-runner.service.d/http-proxy.conf というファイルを作成します:

    [Service]
    Environment="HTTP_PROXY=http://docker0_interface_ip:3128/"
    Environment="HTTPS_PROXY=http://docker0_interface_ip:3128/"
    
  3. ファイルを保存し、変更をフラッシュします:

    systemctl daemon-reload
    
  4. GitLab Runnerを再起動します:

    sudo systemctl restart gitlab-runner
    
  5. 設定がロードされたことを確認します:

    systemctl show --property=Environment gitlab-runner
    

    と表示されるはずです:

    Environment=HTTP_PROXY=http://docker0_interface_ip:3128/ HTTPS_PROXY=http://docker0_interface_ip:3128/
    

Dockerコンテナへのプロキシの追加

Runnerを登録した後、プロキシ設定をDockerコンテナに伝搬させたい場合があります(例えば、git clone )。

これを行うには、/etc/gitlab-runner/config.toml を編集し、[[runners]] セクションに以下を追加する必要があります:

pre_get_sources_script = "git config --global http.proxy $HTTP_PROXY; git config --global https.proxy $HTTPS_PROXY"
environment = ["https_proxy=http://docker0_interface_ip:3128", "http_proxy=http://docker0_interface_ip:3128", "HTTPS_PROXY=docker0_interface_ip:3128", "HTTP_PROXY=docker0_interface_ip:3128"]

docker0_interface_ipdocker0 インターフェースの IP アドレスです。

note
この例では、小文字と大文字の両方の変数を設定していますが、これは、あるプログラムではHTTP_PROXY を想定し、他のプログラムではhttp_proxy を想定しているためです。残念ながら、この種の環境変数に関する標準はありません。

dindサービス使用時のプロキシ設定

Docker-in-Dockerエクゼキュータ(dind)を使用する場合、環境変数NO_PROXYdocker:2375,docker:2376 を指定する必要がある場合があります。このポートは必須で、そうしないとdocker push がブロックされます。

dindからのdockerd とローカルのdocker クライアント(ここで説明されているhttps://hub.docker.com/_/docker/ )の間の通信は、rootのDocker設定に保持されているプロキシ変数を使用します。

これを設定するには、/root/.docker/config.json を編集して、完全なプロキシ設定を含める必要があります:

{
    "proxies": {
        "default": {
            "httpProxy": "http://proxy:8080",
            "httpsProxy": "http://proxy:8080",
            "noProxy": "docker:2375,docker:2376"
        }
    }
}

Docker Executorのコンテナに設定を渡すために、コンテナ内部で$HOME/.docker/config.json 。これは、例えば.gitlab-ci.ymlbefore_script としてスクリプト化することができます:

before_script:
  - mkdir -p $HOME/.docker/
  - 'echo "{ \"proxies\": { \"default\": { \"httpProxy\": \"$HTTP_PROXY\", \"httpsProxy\": \"$HTTPS_PROXY\", \"noProxy\": \"$NO_PROXY\" } } }" > $HOME/.docker/config.json'

あるいは、影響を受けるgitlab-runner (/etc/gitlab-runner/config.toml) の設定でもかまいません:

[[runners]]
  pre_build_script = "mkdir -p $HOME/.docker/ && echo \"{ \\\"proxies\\\": { \\\"default\\\": { \\\"httpProxy\\\": \\\"$HTTP_PROXY\\\", \\\"httpsProxy\\\": \\\"$HTTPS_PROXY\\\", \\\"noProxy\\\": \\\"$NO_PROXY\\\" } } }\" > $HOME/.docker/config.json"
note
これは TOML ファイルの内部で文字列として指定されたシェルを持つ JSON ファイルの作成なので、" をエスケープする追加のレベルが必要です。これはYAMLではないので、: をエスケープしないでください。

NO_PROXY リストを拡張する必要がある場合、ワイルドカード* はサフィックスに対してのみ機能し、プレフィックスや CIDR 表記に対しては機能しないことに注意してください。詳細はhttps://github.com/moby/moby/issues/9145https://unix.stackexchange.com/questions/23452/set-a-network-range-in-the-no-proxy-environment-variableを参照してください。

レート限定リクエストの処理

GitLabインスタンスは、不正使用を防ぐためにAPIリクエストのレート制限を行うリバースプロキシの背後にある可能性があります。GitLab RunnerはAPIに複数のリクエストを送信し、これらのレート制限を超える可能性があります。

そのため、GitLab Runnerはレート制限のあるシナリオを以下のロジックで処理します:

  1. レスポンスコード429 - TooManyRequestsを受信しました。
  2. 応答ヘッダーがチェックされますRateLimit-ResetTime 。この RateLimit-ResetTimeヘッダには、Wed, 21 Oct 2015 07:28:00 GMTのような有効なHTTP Date (RFC1123)の値が必要です。
    • ヘッダーが存在し、有効な値を持つ場合、ランナーは指定された時間まで 待機し、別のリクエストを発行します。
    • ヘッダが存在するが有効な日付でない場合は、1 分のフォールバックが使われます。
    • ヘッダが存在しない場合、追加のアクションは行われず、応答エラーが返されます。
  3. 上記の処理が5回繰り返された後、gave up due to rate limit エラーが返されます。
note
ヘッダーRateLimit-ResetTime は大文字小文字を区別しません。 http.CanonicalHeaderKey関数を通して実行されるためです。