プロキシやネットワークアドレス重複を乗り越えてGitLab CIでMolecule
はじめに
前回の記事 で「GitLab CIを使った継続的なMoleculeによるRoleのテスト」ができるようになりました。 しかし、プロキシ等がある環境では素直にMoleculeを実行することができないことが多いです。 例に漏れず、自分の環境も素直にいきませんでした。
今回は、自分が直面した プロキシ や ネットワークアドレス重複 といった課題を解決してGitLab CIでMoleculeを実行する方法を記録します。
環境と問題点
プロキシ
今回の環境では、社内LANからインターネットに出る際にプロキシサーバを経由する必要があります。 GitLab CIで使用するビルドコンテナ(今回は docker:19.03.11 を使用)にMoleculeをインストールする際、インターネットに繋ぐためプロキシの設定をする必要があります。
また、GitLab CIのビルドコンテナからサービスコンテナ(dind)にアクセスする際、プロキシサーバを経由することができないため直接アクセスするよう設定が必要です。
ネットワークアドレス重複
今回の環境のネットワークアドレス(サーバセグメント)は 172.17.0.0/16 となっています。 これはDockerがサーバ内で作成して使用するブリッジのネットワークアドレスと同じです。 そのため、デフォルトのままではDockerホストサーバでdockerサービスを起動させるとDocker内部のネットワークへルーティングされてしまい、Dockerホストサーバから社内の別サーバへ繋がりません。
今回はGitLab Runnerコンテナを docker executer としてDockerホストサーバ上で動かしており、このサーバのDockerが使うネットワークアドレスは事前に変更しています。 しかし、GitLab CIの サービスコンテナ として使用する docker:19.03.11-dind コンテナイメージはデフォルトの 172.17.0.0/16 を使うため、社内ネットワークアドレスと重複してしまいます。そのため、サービスコンテナからGitLabサーバへは繋がりません。
今回はMoleculeのテストでGitLabサーバ内プライベートレジストリにあるコンテナイメージをpullしてテストするため、サービスコンテナからGitLabサーバへ繋げる必要があります。
解決策
プロキシとネットワークアドレス重複の問題は以下の方法で解決できました。
【プロキシ】molecule実行用dockerコンテナイメージ作成
Molecule公式 では .gitlab-ci.yml
で apk update
コマンドを実行していますが、
プロキシ環境下ではここで詰まってしまうため、環境変数 http_proxy
にプロキシサーバを指定してあげる必要があります。
また、Moleculeをインストールする際の pip
コマンドは別途 --proxy
オプションをつけて実行する必要があります。
.gitlab-ci.yml
内でプロキシ設定を追加してもよいのですが、Moleculeインストールにそこそこ時間が掛かってしまうため、Moleculeをインストール済みのdockerコンテナをビルドして .gitlab-ci.yml
から呼び出すようにします。
- Dockerfile(docker:19.03.11)
FROM docker:19.03.11 ENV http_proxy="http://proxyserver:proxyport" \ https_proxy="http://proxyserver:proxyport" RUN apk update RUN apk add --no-cache \ python3-dev py3-pip gcc git curl build-base \ autoconf automake py3-cryptography linux-headers \ musl-dev libffi-dev openssl-dev openssh RUN python3 -m pip install ansible molecule[lint] docker --proxy http://proxyserver:proxyport
【プロキシ】dindのプロキシ設定
サービスコンテナ(dind)でdockerdサービスが起動する際に、$HOME/.docker/config.json
が読み込まれて設定されます。
GitLab Runnerの設定ファイル config.toml
に下記の pre_build_script=〜
を追加することで、ビルドコンテナやサービスコンテナ起動時に $HOME/.docker/config.json
を作成することができます。このconfig.jsonにプロキシ設定を記述するように pre_build_script を設定しています。(ワンライナーでjsonが書かれていて見難いですが…)
config.toml
にプロキシを設定することで、このランナーが起動するビルドコンテナやサービスコンテナには常に $HOME/.docker/config.json
が作られることになります。.gitlab-ci.yml
でも同じことができるようですが、その場合はプロジェクト毎にプロキシの設定を .gitlab-ci.yml
に記述する必要があるようです。
[[runners]] name = "gitlab-runner" url = "https://gitlab.nnstt1.work/" token = "TOKEN" executor = "docker" pre_build_script = "mkdir -p $HOME/.docker/ && echo \"{ \\\"proxies\\\": { \\\"default\\\": { \\\"httpProxy\\\": \\\"$HTTP_PROXY\\\", \\\"httpsProxy\\\": \\\"$HTTPS_PROXY\\\", \\\"noProxy\\\": \\\"$NO_PROXY\\\" } } }\" > $HOME/.docker/config.json" [runners.custom_build_dir] [runners.docker] image = "docker:19.03.11" privileged = true disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/certs/client", "/cache"] shm_size = 0 [runners.cache] [runners.cache.s3] [runners.cache.gcs]
【ネットワーク重複】dindコンテナイメージ作成
docker:19.03.11-dind
コンテナイメージ内の /etc/docker/
にネットワークアドレスの設定を記述した daemon.json
を配置したコンテナイメージを使用することで、dind で使用するDocker用ネットワークアドレスを変更することができます。
今回はサービスコンテナ(dind)で使用するネットワークアドレスを 10.10.0.1/16 としています。
{ "bip": "10.10.0.1/16" }
- Dockerfile(docker:19.03.11-dind)
FROM docker:19.03.11-dind COPY daemon.json /etc/docker/daemon.json
.gitlab-ci.yml
最後に、これまで変更したコンテナやGitLab Runnerを使用する .gitlab-ci.yml
の修正をおこないます。
--- image: registry.nnstt1.work/sample/docker:19.03.11-molecule <- (1) variables: <- (2) DOCKER_TLS_CERTDIR: "/certs" HTTP_PROXY: http://proxyserver:proxyport HTTPS_PROXY: http://proxyserver:proxyport NO_PROXY: docker services: <- (3) - name: registry.nnstt1.work/sample/docker:19.03.11-dind alias: docker before_script: <- (4) - docker info - python3 --version - ansible --version - molecule --version - docker login registry.nnstt1.work molecule: stage: test script: - molecule test
image
docker hub で公開されているdocker:19.03.11
から、今回ビルドしたdocker:19.03.11-molecule
コンテナイメージを使用するように変更します。 今回はGitLabに構築したプライベートレジストリregistry.nnstt1.work
上にコンテナイメージを格納しています。variables
HTTP_PROXY と HTTPS_PROXY にプロキシサーバを指定します。
NO_PROXY にはプロキシを経由しないIPアドレスやホスト名を指定しますが、今回はdocker
としています。 これは下記のservicesで指定した alias と同じ文字列にする必要があります。services
imageと同じように今回ビルドしたdocker:19.03.11-dind
コンテナイメージを指定しますが、加えて name というキーを指定します。 また、alias キーでdocker
という文字列を指定します。
servicesで alias を指定していない場合、ビルドコンテナからサービスコンテナにアクセスするためのホスト名は、リポジトリURL+コンテナイメージ名 となります。 (詳しくはこちら) そのため、プライベートレジストリ内のコンテナイメージを指定した場合は、registry.nnstt1.work__docker
となります。
しかし、alias を設定することで任意のホスト名でアクセスすることが可能になります。今回は元々使用していたコンテナイメージと同じになるようにdocker
という文字列を指定します。この alias の設定と、上記の NO_PROXY の設定によって、ビルドコンテナからプロキシを経由せずにdocker
という名前でサービスコンテナ(dind)にアクセスが可能となります。before_script
Moleculeインストール済みのコンテナイメージを使用するようにしたため、元々あったMoleculeをインストールコマンドは削除しています。 また、Molecule実行時にプライベートレジストリのコンテナを使用するため、docker login
コマンドを追加しています。
まとめ
上記の手順でなんとか社内のGitLabでMoleculeを動かすことができました。これで職場でも継続的にPlaybookやRoleのテストができるようになりました。
しかし、これはあくまでも準備段階の話です。Moleculeを活かすには、しっかりとテストを用意する必要があります。テスト作るの苦手ですが滅気ずにがんばります。