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

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

先に進む前に、DockerとGitLab Runnerが同じマシンにインストール済みであることを確認する必要があります。

CNTLMの設定

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

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

  • クレデンシャルを変更する必要がある場合は、1つのソースをご利用ください。
  • Docker Runnerから認証情報にアクセスできません。

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

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

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

  1. Dockerが使用しているIPを検索します:

    ip -4 -oneline addr show dev docker0
    

    これは通常、172.17.0.1docker0_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/"

ランナー設定へのプロキシ変数の追加

プロキシ変数も 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_clone_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 アドレスです。Docker コンテナ内からアクセスできる必要があるので、正しく設定することが重要です。

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

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

Docker-in-Dockerexecutor (dind)を使用する場合、NO_PROXY環境変数にdocker:2375,docker:2376 を指定する必要がある場合があります。これはプロキシがDocker-in-Docker間のTCP接続をインターセプトするためです:

  • dockerd ディンド・コンテナから。
  • docker をクライアントコンテナから削除します。

そうしないと、docker push がDockerにマッピングされたIPから発信されるためブロックされてしまうからです。ただし、その場合はプロキシを経由するようになっています。

dindのdockerddocker クライアントとの間の通信をローカルでテストする場合(ここで説明されているように:https://hub.docker.com/_/docker/)、dindのdockerd はホストシステム上のクライアントとしてrootによって最初に起動され、プロキシ変数は/root/.docker/config.jsonから取得されます。

使用例:

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

しかし、.gitlab-ci.yml スクリプトを実行するために起動されたコンテナでは、gitlab-runner の設定(/etc/gitlab-runner/config.toml)によって環境変数が設定されます。これらは、dockerd をサービスとして実行し、docker クライアントを実行する dind コンテナでは、(上記のローカルテストの.docker/config.json とは対照的に)そのまま環境変数として利用可能です.gitlab-ci.yml。 で .gitlab-ci.yml、環境変数は、デフォルトの環境変数からプロキシ設定を尊重する任意のプログラムによってピックアップされます。 たとえば、wgetaptapkdocker infodocker pull (ただし、docker rundocker build のようにhttps://github.com/moby/moby/issues/24697#issuecomment-366680499)ではありません。

docker rundocker build をDocker executorのコンテナ内部で実行すると、$HOME/.docker/config.jsonにあるプロキシ設定を探します。 は現在、executorコンテナ内部にあります(最初は空です)。したがって、docker rundocker build を実行すると、プロキシ設定はありません。設定を引き継ぐには、executorコンテナ内に$HOME/.docker/config.json を作成する必要があります。 たとえば、 は、 にあるプロキシ設定を探します:

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

プロキシの場合にのみ必要な行を.gitlab-ci.yml ファイルに追加するのは混乱を招くので、$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"
注:TOMLファイル内部で、文字列1つで指定されたシェルを持つJSONファイルを作成するため、" をエスケープする追加レベルが必要です。これはもはやYAMLではないので、:をエスケープしないでください。

NO_PROXY リストを拡張する必要がある場合、ワイルドカード* はサフィックスに対してのみ機能し、プレフィックスや CIDR 表記に対しては機能しないことに注意してください。 詳細については、https://github.com/moby/moby/issues/9145およびhttps://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チェックしますRateLimit-ResetTimeRateLimit-ResetTimeヘッダはWed, 21 Oct 2015 07:28:00 GMTのような有効なHTTP Date (RFC1123) でなければなりません。
    • ヘッダーが存在し、有効な値を持っている場合、Runnerは指定された時間まで 待機し、別のリクエストを発行します。
    • ヘッダが存在するが有効な日付でない場合、1分のフォールバックが使用されます。
    • ヘッダーが存在しない場合、追加のアクションは行われず、応答エラーが返されます。
  3. 上記の処理が5回繰り返され、gave up due to rate limit エラーが返されます。
注意:ヘッダーRateLimit-ResetTime は大文字と小文字を区別しません。 http.CanonicalHeaderKey関数を通して実行されるためです。