파이프라인 아키텍처

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

파이프라인은 GitLab에서 CI/CD의 기본적인 구성 요소입니다. 이 페이지에서는 그와 관련된 중요한 개념들을 문서화했습니다.

여러 다양한 방법으로 파이프라인을 구성할 수 있으며 각각에는 각자의 장점이 있습니다. 필요에 따라 이러한 방법들을 혼합하여 사용할 수 있습니다.

  • Basic: 모든 구성이 한 곳에 있는 간단한 프로젝트에 적합합니다.
  • Directed Acyclic Graph: 효율적인 실행이 필요한 대규모 복잡한 프로젝트에 적합합니다.
  • Parent-child pipelines: 모노 리포지토리 및 독립적으로 정의된 구성 요소가 많은 프로젝트에 적합합니다.

    자세한 내용은 Parent-Child Pipelines 기능 데모를 참조하세요.

  • Multi-project pipelines: 상호 의존성이 있는 큰 제품에 필요한 프로젝트 간 상호 의존성을 요구하는 경우에 적합하며 마이크로서비스 아키텍처와 같은 제품에도 적합합니다.

    예를 들어 웹 애플리케이션을 세 개의 다른 GitLab 프로젝트에서 배포할 수 있습니다. Multi-project 파이프라인을 사용하면 각 프로젝트에서 파이프라인을 트리거할 수 있으며 각각이 고유한 빌드, 테스트 및 배포 프로세스를 갖습니다. 모든 프로젝트 간 상호 의존성을 포함하여 연결된 파이프라인을 한 곳에서 시각화할 수 있습니다.

    자세한 내용은 Multi-project 파이프라인 데모를 참조하세요.

기본 파이프라인

기본 파이프라인은 GitLab에서 가장 간단한 파이프라인입니다. 모든 것을 빌드 단계에서 동시에 실행하고, 그 모든 작업이 완료되면 테스트 및 다음 단계를 동일하게 실행합니다. 가장 효율적인 방법은 아니지만 단계가 많으면 다소 복잡해질 수 있지만 유지 보수가 쉽습니다.

graph LR subgraph deploy stage deploy --> deploy_a deploy --> deploy_b end subgraph test stage test --> test_a test --> test_b end subgraph build stage build --> build_a build --> build_b end build_a -.-> test build_b -.-> test test_a -.-> deploy test_b -.-> deploy

그림과 일치하는 /.gitlab-ci.yml 파이프라인 구성 예시:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "이 작업은 무언가를 빌드합니다."

build_b:
  stage: build
  script:
    - echo "다른 무언가를 빌드하는 이 작업은 더디게 실행됩니다."

test_a:
  stage: test
  script:
    - echo "이 작업은 무언가를 테스트합니다. (빌드 단계의 모든 작업이 완료되어야만 실행됩니다.)"

test_b:
  stage: test
  script:
    - echo "다른 무언가를 테스트하는 이 작업은 (빌드 단계의 모든 작업이 완료되어야만 실행됩니다.) 그 또한 같은 시간에 test_a와 시작합니다."

deploy_a:
  stage: deploy
  script:
    - echo "이 작업은 무언가를 배포합니다. (테스트 단계의 모든 작업이 완료되어야만 실행됩니다.)"
  environment: production

deploy_b:
  stage: deploy
  script:
    - echo "다른 무언가를 배포하는 이 작업은 (테스트 단계의 모든 작업이 완료되어야만 실행됩니다.) deploy_a와 같은 시간에 시작합니다."
  environment: production

Directed Acyclic Graph 파이프라인

효율성이 중요하고 가능한 한 빨리 모든 것을 실행하려면 Directed Acyclic Graphs (DAG)을 사용할 수 있습니다. 작업 간의 의존 관계를 정의하기 위해 needs 키워드를 사용합니다. GitLab이 작업 간의 관계를 파악하면 가능한 한 빨리 모든 것을 실행하며 가능한 경우 후속 단계로 건너뛸 수 있습니다.

아래 예시에서는 build_atest_abuild_btest_b보다 훨씬 빠른 경우, GitLab은 build_b가 아직 실행 중이어도 deploy_a를 시작합니다.

graph LR subgraph DAG를 사용한 파이프라인 build_a --> test_a --> deploy_a build_b --> test_b --> deploy_b end

그림과 일치하는 /.gitlab-ci.yml 설정 예시:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "이 작업은 빠르게 무언가를 빌드합니다."

build_b:
  stage: build
  script:
    - echo "다른 무언가를 느리게 빌드하는 이 작업은 더디게 실행됩니다."

test_a:
  stage: test
  needs: [build_a]
  script:
    - echo "이 테스트 작업은 build_a가 완료되는 즉시 시작됩니다."
    - echo "build_b나 빌드 단계의 다른 작업을 기다리지 않습니다."

test_b:
  stage: test
  needs: [build_b]
  script:
    - echo "이 테스트 작업은 build_b가 완료되는 즉시 시작됩니다."
    - echo "빌드 단계의 다른 작업을 기다리지 않습니다."

deploy_a:
  stage: deploy
  needs: [test_a]
  script:
    - echo "build_a와 test_a가 빠르게 실행되므로 이 배포 작업은 훨씬 이른 시간에 실행될 수 있습니다."
    - echo "build_b나 test_b를 기다릴 필요가 없습니다."
  environment: production

deploy_b:
  stage: deploy
  needs: [test_b]
  script:
    - echo "build_b와 test_b가 느리게 실행되므로 이 배포 작업은 훨씬 나중에 실행됩니다."
  environment: production

부모-자식 파이프라인

파이프라인이 더 복잡해지면 몇 가지 관련 문제가 발생합니다:

  • 모든 단계의 작업이 완료되어야 다음 단계의 첫 번째 작업이 시작되는 단계 구조는 속도를 늦추는 대기를 유발합니다.
  • 단일 전역 파이프라인의 구성 관리가 어려워집니다.
  • include을 이용한 가져오기는 구성의 복잡성을 증가시키고, 작업이 의도치 않게 중복되는 경우가 발생할 수 있습니다.
  • 파이프라인 UX에 너무 많은 작업과 단계가 있는 데 작업하기가 어렵습니다.

또한 때로는 파이프라인의 동작을 더 동적으로 조정해야 하는 경우가 있습니다. 특히 YAML이 동적으로 생성될 때 하위 파이프라인을 시작하거나 시작하지 않을 수 있는 능력은 강력합니다.

부모 파이프라인 그래프 확장

# 기본 파이프라인# 유향 비순환 그래프의 예에서 독립적으로 빌드할 수 있는 두 개의 패키지가 있습니다. 이러한 경우 부모-자식 파이프라인을 사용하는 것이 이상적입니다. 이를 통해 구성을 여러 파일로 분리하여 더 간단하게 유지할 수 있습니다. 부모-자식 파이프라인을 다음과 결합할 수 있습니다:

graph LR subgraph 부모 파이프라인 trigger_a -.-> build_a trigger_b -.-> build_b subgraph 자식 파이프라인 B build_b --> test_b --> deploy_b end subgraph 자식 파이프라인 A build_a --> test_a --> deploy_a end end

위 다이어그램과 일치하는 부모 파이프라인의 예시 /.gitlab-ci.yml 구성:

stages:
  - triggers

trigger_a:
  stage: triggers
  trigger:
    include: a/.gitlab-ci.yml
  rules:
    - changes:
        - a/*

trigger_b:
  stage: triggers
  trigger:
    include: b/.gitlab-ci.yml
  rules:
    - changes:
        - b/*

DAG needs 키워드를 활용한 /a/.gitlab-ci.yml에 위치한 자식 a 파이프라인의 예시 구성:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "이 작업은 무언가를 빌드합니다."

test_a:
  stage: test
  needs: [build_a]
  script:
    - echo "이 작업은 무언가를 테스트합니다."

deploy_a:
  stage: deploy
  needs: [test_a]
  script:
    - echo "이 작업은 무언가를 배포합니다."
  environment: production

DAG needs 키워드를 활용한 /b/.gitlab-ci.yml에 위치한 자식 b 파이프라인의 예시 구성:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_b:
  stage: build
  script:
    - echo "이 작업은 다른 무언가를 빌드합니다."

test_b:
  stage: test
  needs: [build_b]
  script:
    - echo "이 작업은 다른 무언가를 테스트합니다."

deploy_b:
  stage: deploy
  needs: [test_b]
  script:
    - echo "이 작업은 다른 무언가를 배포합니다."
  environment: production

GitLab에서 자식 파이프라인을 트리거하기 전이나 후에 작업을 실행할 수 있어 공통 설정 단계나 통합 배포를 가능하게 합니다.