GitLab의 병렬 CI 패턴

9736 단어 GitLab-CIGitLab
GitLab에서 병렬로 CI를 수행하는 방법을 조사했습니다.

GitLab 11.5에서 테스트했지만 현재 (2018년 12월) 최신 버전 11.6에서도 동일해야 합니다.
만약 차이가 발견되면 수시로 반영합니다. (그러므로 자세한 분으로부터의 코멘트도 기다리고 있습니다)

동일한 stage에 여러 job 정의



가장 기본적인 전략으로는 병렬로 빌드 배포하는 처리를 각각 "동일한 stage에 속하는 job"으로 정의하는 방법이 있습니다.

.gitlab-ci.yml 예제


stages:
  - a
  - b

.job_a_common:
  script: mkdir build && touch build/${CI_JOB_NAME}.txt
  artifacts:
    paths:
      - build

job_a1:
  stage: a
  extends: .job_a_common

job_a2:
  stage: a
  extends: .job_a_common

job_a3:
  stage: a
  extends: .job_a_common

job_b:
  stage: b
  script: ls -l build/

실행 결과



아래와 같이 job이 병렬로 동작합니다.



artifacts 를 정리할 수 있고, 나중의 stage 에서 그것들을 취급할 수도 있습니다.
: job_b の出力
$ ls -l build/
total 0
-rw-r--r--    1 root     root             0 Dec 28 04:38 job_a1.txt
-rw-r--r--    1 root     root             0 Dec 28 04:38 job_a2.txt
-rw-r--r--    1 root     root             0 Dec 28 04:38 job_a3.txt
Job succeeded

parallel에 의한 다중도 지정



2018년 11월에 출시된 GitLab 11.5부터 parallel라는 키워드가 도입되었습니다.
htps : // / cs. 기 t b. 코 m / 예 / 시 / 야 ml / # 파라 ㅇ l

지정된 숫자를 다중도로 하여 job을 병렬로 실행할 수 있습니다.
각 작업의 처리 내용은 환경 변수 CI_NODE_INDEX CI_NODE_TOTAL를 사용하여 변경할 수 있습니다.

.gitlab-ci.yml 예제


stages:
  - a
  - b

job_a:
  stage: a
  parallel: 3
  script: mkdir build && touch build/${CI_NODE_INDEX}_of_${CI_NODE_TOTAL}.txt
  artifacts:
    paths:
      - build

job_b:
  stage: b
  script: ls -l build/

실행 결과



Pipeline의 표시에서는, 확실히 보에서는 병렬로 보이지 않지만, 잘 보면 다중도 3 가 보이고 있습니다.



Jobs의 표시에서는, 확실히 병렬로 Job이 움직이고 있는 것을 알 수 있습니다.



artifacts에 대해서도 여러 Job을 정의한 것처럼 취급할 수 있습니다.
: job_b の出力
$ ls -l build/
total 0
-rw-r--r--    1 root     root             0 Dec 28 04:45 1_of_3.txt
-rw-r--r--    1 root     root             0 Dec 28 04:45 2_of_3.txt
-rw-r--r--    1 root     root             0 Dec 28 04:46 3_of_3.txt
Job succeeded

파일 단위로 병렬로 빌드 (parallel 응용)


parallel 에서는 병렬 다중도를 정적으로 지정할 수 밖에 없습니다.
예를 들면 「파일마다의 병렬 빌드」등, 다중도를 동적으로 결정하고 싶은 것은 있다고 생각합니다.

하지만 현시점(2018년 말, GitLab 11.6 릴리스 시점)에서 그것을 할 방법은 없습니다.

기능 제안이 되었기 때문에 향후 가능할 가능성이 있습니다.
htps : //기 tぁb. 코 m/기 tぁb-오 rg/기 tぁb-세/이스에 s/23455

조금 타협하여 적당한 다중도로 시작한 Job으로 대상 소스를 전환함으로써 빌드를 평준화할 수 있습니다.
다음은 그 예입니다.

리포지토리 구조


$ tree
.
├── 1.txt
├── 2.txt
├── 3.txt
├── 4.txt
└── 5.txt

0 directories, 5 files
$ head *.txt
==> 1.txt <==
11111

==> 2.txt <==
22222

==> 3.txt <==
33333

==> 4.txt <==
44444

==> 5.txt <==
55555

.gitlab-ci.yml


stages:
  - a
  - b

job_a:
  stage: a
  parallel: 3
  script:
    - mkdir build
    - NF=$(ls -1 *.txt | wc -l)
    - ls -1 *.txt
      | awk "(NR-1)%${CI_NODE_TOTAL}==${CI_NODE_INDEX}-1"
      | xargs -P$((NF/CI_NODE_TOTAL+1)) -I_ sh -c "cat _ | tee build/_"
  artifacts:
    paths:
      - build

job_b:
  stage: b
  script: head build/*.txt

도중에 조금 복잡한 awk 의 식이 있습니다만, 행수의 나머지를 취해, 순서대로 Job에 할당하고 있을 뿐입니다.
또, Job내에서도 프로세스를 병렬화하기 위해, 대상 소스의 수로부터 필요한 프로세스수를 계산해 xargs-P 옵션으로 건네주고 있습니다.

실행 결과



Pipeline의 외형은, 이전의 것과 같기 때문에 할애합니다.

각각의 Job의 출력을 보면, 제대로 처리가 평준화되고 있는 것을 알 수 있습니다.
: job_a 1/3 の出力
$ mkdir build
$ NF=$(ls -1 *.txt | wc -l)
$ ls -1 *.txt | awk "(NR-1)%${CI_NODE_TOTAL}==${CI_NODE_INDEX}-1" | xargs -P$((NF/CI_NODE_TOTAL+1)) -I_ sh -c "cat _ | tee build/_"
44444
11111
: job_a 2/3 の出力
$ mkdir build
$ NF=$(ls -1 *.txt | wc -l)
$ ls -1 *.txt | awk "(NR-1)%${CI_NODE_TOTAL}==${CI_NODE_INDEX}-1" | xargs -P$((NF/CI_NODE_TOTAL+1)) -I_ sh -c "cat _ | tee build/_"
22222
55555
:job_a 3/3 の出力
$ mkdir build
$ NF=$(ls -1 *.txt | wc -l)
$ ls -1 *.txt | awk "(NR-1)%${CI_NODE_TOTAL}==${CI_NODE_INDEX}-1" | xargs -P$((NF/CI_NODE_TOTAL+1)) -I_ sh -c "cat _ | tee build/_"
33333

job_b 에서도 build 이하에 파일이 남아 있으므로, 의도한 대로 동작한 것을 알 수 있습니다.
: job_b の出力
$ head build/*.txt
==> build/1.txt <==
11111

==> build/2.txt <==
22222

==> build/3.txt <==
33333

==> build/4.txt <==
44444

==> build/5.txt <==
55555
Job succeeded

이상입니다.

좋은 웹페이지 즐겨찾기