.gitlab-ci.yml の needs についてのメモ

gitlab-ci にて needs を使いたくなったのでその際にドキュメントを見ながら試したメモ

needs

document link

needs は、あるjobが他のjobの実行後に動く必要がある。という順序を指定するもので、DAGである必要があります。

gitlab-ci pipelne では、通常、stage ごとに実行されていきますが、 needs 指定があると、 前のstageのjobが完了していなくてもneeds指定されたjobが完了していれば動き始めます。

needsに空リストを設定すると、即開始されます。

依存の記載として、特定jobのartifactsを利用する dependenciesがありますが、 needsはそれの強化版の様なイメージです。

jobA:
  stage: test
  script:
    - script

jobB:
  stage: deploy
  needs:
    - jobA
  script:
    - script

みたいな使いかたをすると、 jobAが終わったあとにjobBが動きます。

jobA:
  stage: test
  script:
    - script
  rules:
    - if:  '$CI_COMMIT_BRANCH == "main"'

jobB:
  stage: deploy
  needs:
    - jobA
  script:
    - script

こんな書き方をすると、 branchが "main" 以外の時に jobBをpipelineに追加しようとしてエラーが出てしまうので jobAとjobB では 同じ rules を使うことが重要です。

ただし、jobBを main 以外でも実行したい、jobAがなくても動かしたい という場合は

jobA:
  stage: test
  script:
    - script
  rules:
    - if:  '$CI_COMMIT_BRANCH == "main"'

jobB:
  stage: deploy
  needs:
    - job: jobA
      optional: true
  script:
    - script

と、 needs に optional: true を加えると、 jobAがなくても動くようになります。(gitlab 13.10以降、 13.10 では feature enable する必要あり)

また、 stage は必須となり、 needs に設定するjobのstageは、 needsを記載するjobのstageより前のstageである必要があります。これはDAGであることを保証するための制約です。

jobA:
  stage: test
  script:
    - script

jobB:
  stage: test
  needs:
    - jobA
  script:
    - script

つまり、たとえばこのように stageが両方ともtestであるとエラーとなります。

dependencies と同様にartifactsを利用したい場合は

jobA:
  stage: test
  script:
    - script
  artifacts:
    paths:
      - artifacts/
jobB:
  stage: deploy
  needs:
    - jobA
  script:
    - script

と前段のjobでartifactsを指定すれば良いです。

artifactsを利用しない場合は

jobA:
  stage: test
  script:
    - script
  artifacts:
    paths:
      - artifacts/
jobB:
  stage: deploy
  needs:
    - job: jobA
      artifacts: false
  script:
    - script

とneedsに artifacts: false と記載することでartifacts のダウンロードを抑止できます。

たまにはプログラミングをしている話

仕事では、主にITインフラと呼ばれる領域で仕事をしており、プログラミングをする機会がほぼない。

なくてもたまにはコードを書きたい。

ということで、細かな手元の処理の自動化などのためにプログラミングしています。

使っているのはPython、Goあたりです。

手元の処理の自動化という意味では、Webアクセスをして何らかの処理をする。ということが多く、Go、Pythonどちらもその時の気分で使っています。

ただ、webアクセスが、ブラウザでないとうまくいかないようなもの往々にしてあり、そういったものはpython +selenium (chrome) で行っています。

headlessモードだとどうしてもうまく動かないものもあり、そういったものはheadlessにもせず動かしています。

定期実行させる場合は、母艦がWindowsですので、タスクスケジューラを利用しています。

処理結果を通知したいのですが、それには twitterのDMを自分から自分に送るというていで行っています。

なんだかんだでtwitterが一番早く気付けるので。

こういったもろもろでしかプログラムを書くということをしていないので、データベースの扱いが一向にうまくなりません。

なにかいい方法はないものでしょうかね。

AWSで動かすGitLab CI runner の改善

AWS で GitLab Runnerを動かしているのですが、いろいろ改善している話です。

dockerhub registry mirror

みなさんご存じの通り、 dockerhubは、anonymous pull に制限をかけました。CIで dockerhubのイメージを利用していると、すぐ制限にひっかかります。

また、近いほうがimage pull が速いということもあります。

そこで、 dockerhub registry の mirrorを設置しました。

詳細は Docker Registry | Docker Documentation を見ていただくとして。

AWSなので、ストレージにはS3を利用しています。 s3 を利用する際、

package manager

JAVA系を利用していると maven central からパッケージをダウンロードしてくることが多いのですが、 maven central には dockerhub同様 ダウンロード制限がかかっており、 CIで大量にダウンロードしていると、制限にひっかかります。

そこで、パッケージマネージャ Nexus Repository OSS - Software Component Management | Sonatype を利用しています。

maven centralのほかにも、よく使うものを mirrorしておくことで、安定した環境を用意しています。

vpc endpoint

ci runner 自体に外からアクセスする必要はまずないので、 private subnet に置いています。 すると、 s3 からデータを取得するたびに、nat-gatewayを経由することになり、AWS内通信なのに通信料がすごくかかる。

ということもあり s3 のvpc endpoint を設置しています。 上記 dockerhub registry mirror のほか、 AWS ECRからの image pull もs3 経由ですので、それなりに効果があります。

vpc endpoint service

GitLab Server と CI runner は、AWSの別アカウントで管理しています。そのため、 CI runner から GitLab Serverへの通信がやはり internet経由となりnat-gateway を経由しており、ここでも通信料がかさんでしまう状態なので

GitLab Serverを vpc endpoint service として別アカウントに公開できるようにし、 CI runner の動いているアカウントで vpc endpoint として 利用しています。

auto scale

CI runner については Autoscaling GitLab Runner on AWS EC2 | GitLab のドキュメントに従い、docker-machine によるSpot instance を利用した auto scale で動かしています。

終わりに

値段とスケーリング、速度に関して、改善を行っている現状を記載しました。

これからもいろんな状況に応じて、いろんな改善を行っていくつもりです。