zaki work log

作業ログやら生活ログやらなんやら

既存のGitLab CE on Dockerに、Runnerコンテナも追加してCI/CD環境をつくる

Dockerで動かしてるGitLab CEにGitLab Runnerもコンテナで追加して、GitLab CE本体とRunnerを同じDocker上(別コンテナ)で動かして、初めてのGitLab Runnerお試し。

構成の概要としてはこんな感じ。

f:id:zaki-hmkc:20200313213644p:plain

お題

以前つくったGitLab CE on Dockerに、Runnerも同じDocker上でうごかす。

zaki-hmkc.hatenablog.com

zaki-hmkc.hatenablog.com

$ sudo docker-compose ps
         Name                Command          State               Ports         
--------------------------------------------------------------------------------
gitlab-                  /assets/wrapper   Up (healthy)   22/tcp, 0.0.0.0:25000-
compose_gitlab-                                           >25000/tcp, 443/tcp,
registry_1                                                80/tcp,
                                                          0.0.0.0:8443->8443/tcp

Runnerコンテナの起動

docs.gitlab.com

以下、runnerのコンテナ定義を追加

  gitlab-runner:
    image: gitlab/gitlab-runner:v12.7.1
    restart: always
    volumes:
      - /opt/gitlab-runner/config:/etc/gitlab-runner:Z
      - /var/run/docker.sock:/var/run/docker.sock

docker-compose up -dすると、Runnerのコンテナが起動。

$ sudo docker-compose ps
        Name                 Command             State              Ports       
--------------------------------------------------------------------------------
gitlab-                /assets/wrapper        Up (healthy)   22/tcp, 0.0.0.0:250
compose_gitlab-                                              00->25000/tcp,
registry_1                                                   443/tcp, 80/tcp, 0.
                                                             0.0.0:8443->8443/tc
                                                             p
gitlab-                /usr/bin/dumb-init     Up
compose_gitlab-        /entryp ...
runner_1

こんな感じ。
Runnerをただ動かすだけなら、特になんでもない。

Runnerの設定

GitLab CEでトークン確認

Runnerを試してみるプロジェクトのSettings -> CI/CD -> RunnersをExpandして、"registration token"を確認する。

f:id:zaki-hmkc:20200313071943p:plain

(※: プロジェクト単位でなくGitLab CE全体の設定も可能だけど、ひとまずプロジェクト単位でお試し)

Runnerのregister実行

コンテナのbashを起動し、登録コマンドであるgitlab-runner registerを実行する。

docs.gitlab.com

雑に動かすとぽろぽろとエラーが出てくる。

connect: no route to host

$ sudo docker-compose exec gitlab-runner bash
root@1ccbe6c850f1:/# 
root@1ccbe6c850f1:/# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=29 revision=003fe500 version=12.7.1
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab-ce.example.org:8443/       # GitLab CEのURL入力
Please enter the gitlab-ci token for this runner:
oQyQbs-qbp3sMYdn8MLM                      # webで確認したregistration tokenを入力
Please enter the gitlab-ci description for this runner:
[1ccbe6c850f1]: sample-runner             # runnerの名前
Please enter the gitlab-ci tags for this runner (comma separated):
                                          # tagは(とりあえず)空欄
ERROR: Registering runner... failed                 runner=oQyQbs-q status=couldn't execute POST against https://gitlab-ce.example.org:8443/api/v4/runners: Post https://gitlab-ce.example.org:8443/api/v4/runners: dial tcp 192.168.0.21:8443: connect: no route to host
PANIC: Failed to register this runner. Perhaps you are having network problems 
root@1ccbe6c850f1:/# 

おや…

root@1ccbe6c850f1:/# curl -I http://gitlab-ce.example.org/yum-repo/
HTTP/1.1 200 OK
:

gitlab-ce.example.orgに対して全く通信できないわけではなさそう。(ホストOS上で動作してるhttpdサーバへは普通にアクセスできる)

いろいろ確認した結果、「コンテナAの中から」「ホストOSのIPアドレス-pでpublishしたポート番号指定で別のコンテナBに対して」直接通信はできないっぽい。
Dockerの通信仕様というか、Dockerの通信を制御しているiptablesの仕様というか、、だいたいその辺の理由。たぶん。

f:id:zaki-hmkc:20200313215801p:plain

というわけで、RunnerのコンテナからGitLab CEのコンテナへのコンテナ間通信で、HTTPS通信するためにFQDNでアクセスしたいけど、うまい方法を思いつかないので…

GitLab CEのコンテナ名をFQDNと同じにしよう(・∀・)
(「コンテナ間通信はコンテナ名でアクセスできる」動作によって、FQDNでRunnerからGitLab CEにアクセスする)

--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,7 +1,7 @@
 ---
 version: '3'
 services:
-  gitlab-registry:
+  gitlab-ce.example.org:
     image: gitlab/gitlab-ce:12.7.4-ce.0
     hostname: gitlab-ce.example.org
     restart: always

これでdocker-compose up -d

[zaki@registry gitlab-compose]$ sudo docker-compose ps
       Name               Command               State                Ports
--------------------------------------------------------------------------------
gitlab-              /assets/wrapper      Up (health:          22/tcp, 0.0.0.0:2
compose_gitlab-                           starting)            5000->25000/tcp,
ce.example.org_1                                               443/tcp, 80/tcp,
                                                               0.0.0.0:8443->844
                                                               3/tcp
gitlab-              /usr/bin/dumb-init   Up
compose_gitlab-      /entryp ...
runner_1

こんな感じ。
healthyになるまで待つ。

x509: certificate signed by unknown authority

[zaki@registry gitlab-compose]$ sudo docker-compose exec gitlab-runner bash
root@32511c7a3352:/# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=29 revision=003fe500 version=12.7.1
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab-ce.example.org:8443/
Please enter the gitlab-ci token for this runner:
oQyQbs-qbp3sMYdn8MLM
Please enter the gitlab-ci description for this runner:
[32511c7a3352]: sample-runner
Please enter the gitlab-ci tags for this runner (comma separated):

ERROR: Registering runner... failed                 runner=oQyQbs-q status=couldn't execute POST against https://gitlab-ce.example.org:8443/api/v4/runners: Post https://gitlab-ce.example.org:8443/api/v4/runners: x509: certificate signed by unknown authority
PANIC: Failed to register this runner. Perhaps you are having network problems 
root@32511c7a3352:/# 

今度のエラーはわりと予想通り。

docs.gitlab.com

  gitlab-runner:
    image: gitlab/gitlab-runner:v12.7.1
    restart: always
    volumes:
      - /opt/gitlab-runner/config:/etc/gitlab-runner:Z
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/gitlab-cert:/etc/gitlab-runner/certs

GitLab CE本体でも使用している証明書ファイルが/opt/gitlab-certにあるので、Runnerでも使い回す。
volumesを使ってマウントするホストのディレクトリに、/opt/gitlab-cert:/etc/gitlab-runner/certsを追加。

まぁRun GitLab Runner in a containerのドキュメントよくよく見たら"Installing trusted SSL server certificates"の章に書いてあるんだけど…()

成功編

$ sudo docker-compose exec gitlab-runner bash
root@365f57ba0691:/# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=28 revision=003fe500 version=12.7.1
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab-ce.example.org:8443/
Please enter the gitlab-ci token for this runner:
oQyQbs-qbp3sMYdn8MLM
Please enter the gitlab-ci description for this runner:
[365f57ba0691]: sample-runner
Please enter the gitlab-ci tags for this runner (comma separated):

Registering runner... succeeded                     runner=oQyQbs-q
Please enter the executor: docker, ssh, docker-ssh+machine, custom, docker-ssh, parallels, shell, virtualbox, docker+machine, kubernetes:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

お、うまくいった。
(executorの設定は、dockerkubernetesなど試したくなる項目あるけど、とりあえずshellを設定している)

webで設定の"Runners activated for this project"の部分を見ると、追加したRunnerの項目が追加されてることを確認できる。

f:id:zaki-hmkc:20200313072008p:plain

追加した設定は、GitLab Runnerコンテナ内の/etc/gitlab-runner/config.tomlに作成される。これはDockerのボリューム設定によってホストOSの/opt/gitlab-runner/config/config.tomlになっている。

concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "sample-runner"
  url = "https://gitlab-ce.example.org:8443/"
  token = "PUSws8kkxEnz5Qn4npye"
  executor = "shell"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]

Runnerお試し

こんなファイルを用意

---
stages:
  - runner-test

job01:
  stage: runner-test
  script:
    - id
    - uname -r
    - ps auxwwf
    - hostname
    - ls -alF

pushする

% git add .gitlab-ci.yml
% git commit -m "add: gitlab-ciお試し"
% git push

すると、GitLab CE上でpipelineが動き始める。 (中身はコマンド実行するだけなのですぐ完了する)

f:id:zaki-hmkc:20200313075702p:plain

statusの列("passed"などのリザルト)はリンクになってて、内容を確認できる。

f:id:zaki-hmkc:20200313080002p:plain

jobの詳細で、CIで実行された処理の出力を確認できる。

f:id:zaki-hmkc:20200313080107p:plain

$ id
 uid=999(gitlab-runner) gid=999(gitlab-runner) groups=999(gitlab-runner)
 $ uname -r
 3.10.0-1062.9.1.el7.x86_64
 $ ps auxwwf
 USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
 root         14  0.0  0.0  18496  1940 pts/0    Ss+  22:09   0:00 bash
 root          1  0.0  0.0    164     4 ?        Ss   22:08   0:00 /usr/bin/dumb-init /entrypoint run --user=gitlab-runner --working-directory=/home/gitlab-runner
 root          6  0.1  0.5 137040 19668 ?        Ssl  22:08   0:02 gitlab-runner run --user=gitlab-runner --working-directory=/home/gitlab-runner
 root        109  0.0  0.0  49260  1628 ?        S    22:41   0:00  \_ su -s /bin/bash gitlab-runner -c bash --login
 gitlab-+    110  0.0  0.0   9908  1544 ?        Ss   22:41   0:00      \_ bash --login
 gitlab-+    114  0.0  0.0  10040   908 ?        S    22:41   0:00          \_ bash --login
 gitlab-+    118  0.0  0.0  34392  1528 ?        R    22:41   0:00              \_ ps auxwwf
 $ hostname
 365f57ba0691
 $ ls -alF
 total 4
 drwxrwxr-x. 3 gitlab-runner gitlab-runner  57 Mar 12 22:41 ./
 drwxrwxr-x. 4 gitlab-runner gitlab-runner  40 Mar 12 22:41 ../
 drwxrwxr-x. 6 gitlab-runner gitlab-runner 113 Mar 12 22:41 .git/
 -rw-rw-r--. 1 gitlab-runner gitlab-runner 136 Mar 12 22:41 .gitlab-ci.yml
 -rw-rw-r--. 1 gitlab-runner gitlab-runner   0 Mar 12 22:41 README.md

こんな感じで、gitlab-runner register時にshellを指定しているので、「Runnerが動いてるホスト上でshell実行」されていることが確認できた。
今回Runner自体をコンテナで実行してるので、「Runnerが動いているホスト」が、Runner自身のコンテナ内になってる。


全体のdocker-compose.yml

---
version: '3'
services:
  gitlab-ce.example.org:
    image: gitlab/gitlab-ce:12.7.4-ce.0
    hostname: gitlab-ce.example.org
    restart: always
    ports:
      - "8443:8443"
      - "25000:25000"
    environment:
      GITLAB_OMNIBUS_CONFIG: "external_url 'https://gitlab-ce.example.org:8443'; nginx['listen_port']=8443; gitlab_rails['registry_enabled']=true; registry_external_url 'https://gitlab-ce.example.org:25000'"
    volumes:
      - /opt/gitlab-reg/config:/etc/gitlab:Z
      - /opt/gitlab-reg/logs:/var/log/gitlab:Z
      - /opt/gitlab-reg/data:/var/opt/gitlab:Z
      - /opt/gitlab-reg/registry:/var/opt/gitlab/gitlab-rails/shared/registry:Z
      - /opt/gitlab-cert:/etc/gitlab/ssl
  gitlab-runner:
    image: gitlab/gitlab-runner:v12.7.1
    restart: always
    volumes:
      - /opt/gitlab-runner/config:/etc/gitlab-runner:Z
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/gitlab-cert:/etc/gitlab-runner/certs

shellじゃなくてdockerについてはこちら
(dindでさらにコンテナ間通信がcompose管理外の構成)

zaki-hmkc.hatenablog.com

dind(Docker in Docker)については、ホストの/var/run/docker.sockをボリューム設定で共用してる関係で、何も問題なかった。


というかdocker run -p host-port:container-portしたコンテナ、ホストOS外のリモートからの接続は問題ないけど、同じホスト上の別のDockerコンテナからは「ホストのアドレス:port」だと接続できないのね…知らなかった…(というか、何かセオリーあるのかな)

"GitLab CE contaienr"は-pを使ってホストOSからのポートフォワードを設定 f:id:zaki-hmkc:20200313215845p:plain

この設定でリモートからのアクセスが可能になる。 f:id:zaki-hmkc:20200313215933p:plain

でもこの構成だと、別のコンテナからホストOSのIPアドレス:ポート番号のアクセスができなかった。(コンテナ間通信はdocker networkの設定でイケる) f:id:zaki-hmkc:20200313215801p:plain


参考文献はGitLab実践ガイド

PDF版はインプレスで購入すればOK

book.impress.co.jp