리소스 그룹
- GitLab 12.7에서 소개되었습니다.
기본적으로 GitLab CI/CD에서는 파이프라인이 동시에 실행됩니다. 동시성은 Merge Request에서 피드백 루프를 향상시키는 중요한 요소이지만, 배포 작업의 동시성을 제한하여 하나씩 실행하도록 하는 상황도 있습니다. 연속적인 배포 워크플로우를 최적화하기 위해 작업의 동시성을 전략적으로 제어하기 위해 리소스 그룹을 사용합니다.
리소스 그룹 추가
리포지터리의 .gitlab-ci.yml
파일에 다음 파이프라인 구성이 있는 경우를 가정합니다:
build:
stage: build
script: echo "빌드 스크립트"
deploy:
stage: deploy
script: echo "배포 스크립트"
environment: production
브랜치에 새로운 커밋을 푸시할 때마다 build
와 deploy
두 작업이 있는 새 파이프라인이 실행됩니다. 그러나 짧은 간격으로 여러 커밋을 푸시하면 여러 파이프라인이 동시에 실행됩니다. 예를 들면:
- 첫 번째 파이프라인은 작업
build
->deploy
를 실행합니다. - 두 번째 파이프라인은 작업
build
->deploy
를 실행합니다.
이 경우 다른 파이프라인에서 production
환경으로 배포 작업이 동시에 실행될 수 있습니다. 동일한 인프라에 대해 여러 배포 스크립트를 실행하는 것은 최악의 경우 인스턴스를 손상시키고 오류 상태로 남길 수 있습니다.
deploy
작업이 한 번에 한 번씩 실행되도록 보장하려면 리소스 그룹 키워드를 동시성 민감한 작업에 명시할 수 있습니다:
deploy:
...
resource_group: production
이 구성을 통해 배포의 안전성을 보장할 수 있으면서 파이프라인 효율을 극대화할 수 있습니다.
사전 요구 사항
- GitLab CI/CD 파이프라인에 대한 기본 지식
- GitLab 환경 및 배포에 대한 기본 지식
- 프로젝트에서 CI/CD 파이프라인을 구성하려면 적어도 Developer 역할이 필요합니다.
제한 사항
하나의 리소스만 리소스 그룹에 연결할 수 있습니다.
프로세스 모드
- GitLab 14.3에서 소개되었습니다.
- 피처 플래그
ci_resource_group_process_modes
는 GitLab 14.4에서 제거되었습니다.- GitLab 14.4에서 일반적으로 사용할 수 있습니다.
작업 동시성을 전략적으로 제어하기 위해 프로세스 모드를 선택할 수 있습니다. 다음 모드가 지원됩니다:
- 정렬되지 않음(Unordered): 이는 실행 작업의 동시성을 제한하는 기본 프로세스 모드입니다. 작업의 실행 순서에 신경쓰지 않을 때 가장 쉬운 옵션입니다. 작업이 실행 준비가 되면 즉시 처리를 시작합니다.
-
가장 오래된 것 먼저(Oldest first): 이 프로세스 모드는 작업의 동시성을 제한합니다. 자원이 여유로울 때, 파이프라인 ID로 정렬된 다가오는 작업 디렉터리(
created
,scheduled
, 또는waiting_for_resource
상태)에서 첫 번째 작업을 선택합니다.이 모드는 작업이 가장 오래된 파이프라인에서 실행되도록 보장하고, 파이프라인 효율에 있어
unordered
모드보다는 덜 효율적이지만 연속적 배포에는 더 안전합니다. -
가장 최신 것 먼저(Newest first): 이 프로세스 모드는 작업의 동시성을 제한합니다. 자원이 여유로울 때, 파이프라인 ID로 정렬된 다가오는 작업 디렉터리(
created
,scheduled
, 또는waiting_for_resource
상태)에서 첫 번째 작업을 선택합니다.이 모드는 작업이 가장 최신 파이프라인에서 실행되도록 보장하고, 오래된 배포 작업 방지 기능을 사용하여 이전 배포 작업을 모두 방지합니다. 파이프라인 효율에 있어 가장 효율적이지만 각 배포 작업이 멱득성(idempotent)임을 보장해야 합니다.
프로세스 모드 변경
리소스 그룹의 프로세스 모드를 변경하려면 API를 사용하고 process_mode
를 지정하여 기존 리소스 그룹 편집에 대한 요청을 보내어야 합니다:
unordered
oldest_first
newest_first
프로세스 모드의 차이 예시
다음과 같은 .gitlab-ci.yml
을 고려해보겠습니다. 이곳에는 build
와 deploy
라는 두 작업이 각자의 스테이지에서 실행되며, deploy
작업에는 production
으로 설정된 리소스 그룹이 있습니다:
build:
stage: build
script: echo "빌드 스크립트"
deploy:
stage: deploy
script: echo "배포 스크립트"
environment: production
resource_group: production
프로젝트에 세 번의 커밋이 짧은 간격으로 푸시된다면, 거의 동시에 세 개의 파이프라인이 실행됩니다:
- 첫 번째 파이프라인은 작업
build
->deploy
를 실행합니다. 이 배포 작업을deploy-1
이라고 합시다. - 두 번째 파이프라인은 작업
build
->deploy
를 실행합니다. 이 배포 작업을deploy-2
이라고 합시다. - 세 번째 파이프라인은 작업
build
->deploy
를 실행합니다. 이 배포 작업을deploy-3
이라고 합시다.
리소스 그룹의 프로세스 모드에 따라:
- 프로세스 모드가
unordered
로 설정된 경우:-
deploy-1
,deploy-2
,deploy-3
이 동시에 실행되지 않습니다. - 작업 실행 순서에 대한 보장이 없으며, 예를 들어
deploy-1
이deploy-3
보다 먼저 실행될 수도 있고 그 반대가 될 수도 있습니다.
-
- 프로세스 모드가
oldest_first
로 설정된 경우:-
deploy-1
,deploy-2
,deploy-3
이 동시에 실행되지 않습니다. -
deploy-1
이 먼저 실행되고,deploy-2
가 두 번째로,deploy-3
이 마지막으로 실행됩니다.
-
- 프로세스 모드가
newest_first
로 설정된 경우:-
deploy-1
,deploy-2
,deploy-3
이 동시에 실행되지 않습니다. -
deploy-3
이 먼저 실행되고,deploy-2
가 두 번째로,deploy-1
이 마지막으로 실행됩니다.
-
파이프라인 수준의 교차 프로젝트/상위-하위 파이프라인 동시성 제어
- GitLab 13.9에서 소개되었습니다.
동시 실행에 민감한 하위 파이프라인에 대해 resource_group
를 정의할 수 있습니다. trigger
키워드는 하위 파이프라인을 트리거하고 resource_group
키워드는 이와 함께 사용할 수 있습니다. resource_group
는 배포 파이프라인의 동시성을 제어하는 데 효과적이며, 다른 작업은 계속해서 동시에 실행될 수 있습니다.
다음 예시는 프로젝트에서 두 개의 파이프라인 구성을 보여줍니다. 파이프라인이 실행되면 민감하지 않은 작업이 먼저 실행되며, 다른 파이프라인의 동시 실행에 영향을 받지 않습니다. 그러나 GitLab은 배포(하위) 파이프라인을 트리거하기 전에 다른 배포 파이프라인이 실행 중인지 확인합니다. 다른 배포 파이프라인이 실행 중이면 GitLab은 해당 파이프라인이 완료될 때까지 기다립니다.
# .gitlab-ci.yml (상위 파이프라인)
build:
stage: build
script: echo "빌드 중..."
test:
stage: test
script: echo "테스트 중..."
deploy:
stage: deploy
trigger:
include: deploy.gitlab-ci.yml
strategy: depend
resource_group: AWS-production
# deploy.gitlab-ci.yml (하위 파이프라인)
stages:
- provision
- deploy
provision:
stage: provision
script: echo "준비 중..."
deployment:
stage: deploy
script: echo "배포 중..."
environment: production
trigger
키워드와 함께 strategy: depend
를 정의해야 합니다. 이를 통해 하위 파이프라인이 완료될 때까지 잠금이 해제되지 않도록 보장합니다.
관련 주제
문제 해결
파이프라인 구성에서 교차 프로젝트 방지
oldest_first
프로세스 모드는 작업이 파이프라인 순서대로 실행되도록 강제하기 때문에, 다른 CI 기능과 잘 작동하지 않는 경우가 있습니다.
예를 들어, 상위-하위 파이프라인을 실행하는 경우에 상위 파이프라인과 동일한 리소스 그룹을 필요로 하는 하위 파이프라인이 있다면 데드락이 발생할 수 있습니다. 다음은 잘못된 설정의 예시입니다:
# 잘못된 설정
test:
stage: test
trigger:
include: child-pipeline-requires-production-resource-group.yml
strategy: depend
deploy:
stage: deploy
script: echo
resource_group: production
environment: production
상위 파이프라인에서 test
작업을 실행하고 그 후 하위 파이프라인을 실행하는데, strategy: depend
옵션으로 인해 test
작업이 하위 파이프라인이 완료될 때까지 기다립니다. 그 다음 상위 파이프라인은 다음 단계에서 production
리소스 그룹의 리소스가 필요한 deploy
작업을 실행합니다. oldest_first
프로세스 모드인 경우, 가장 이전 파이프라인부터 작업을 실행하므로 deploy
작업이 다음에 실행됩니다.
그러나 하위 파이프라인 역시 production
리소스 그룹에서 리소스를 필요로 합니다. 하위 파이프라인은 상위 파이프라인보다 새로운 상태이므로, deploy
작업이 완료될 때까지 기다리게 됩니다.
이 경우, 상위 파이프라인 설정에서 resource_group
키워드를 명시해야 합니다:
# 올바른 설정
test:
stage: test
trigger:
include: child-pipeline.yml
strategy: depend
resource_group: production # 상위 파이프라인에서 리소스 그룹을 명시
deploy:
stage: deploy
script: echo
resource_group: production
environment: production
“리소스 대기 중”에서 작업이 멈추는 경우
가끔 작업이 “리소스 대기 중:
- 작업 세부 정보 페이지로 이동합니다.
-
리소스가 작업에 할당되어 있는지 확인하고, 현재 리소스를 사용하는 작업 보기를 선택하여 작업 상태를 확인합니다.
- 상태가
running
또는pending
인 경우, 기능이 올바르게 작동합니다. 작업이 완료되고 리소스가 해제될 때까지 기다립니다. - 상태가
created
이고 프로세스 모드가 가장 오래된 것 먼저 또는 가장 최신 것 먼저인 경우, 기능이 올바르게 작동합니다. 작업이 차단된 상위 단계나 작업을 확인하기 위해 해당 작업의 파이프라인 페이지를 방문합니다. - 위의 조건 중 어느 것에도 해당하지 않는 경우, 기능이 올바르게 작동하지 않을 수 있습니다. GitLab에 문제를 보고합니다.
- 상태가
-
현재 리소스를 사용하는 작업 보기가 사용 불가능한 경우, 리소스가 작업에 할당되지 않았습니다. 대신, 해당 리소스의 다가오는 작업을 확인해야 합니다.
- REST API를 사용하여 리소스의 다가오는 작업을 가져옵니다.
- 작업의 프로세스 모드가 가장 오래된 것 먼저인지 확인합니다.
- 다가오는 작업 디렉터리에서 첫 번째 작업을 찾고, GraphQL을 사용하여 해당 작업의 상세 정보를 가져옵니다.
- 첫 번째 작업의 파이프라인이 더 이전의 파이프라인인 경우, 해당 파이프라인 또는 작업 자체를 취소하려고 시도합니다.
- 선택 사항. 다음 다가오는 작업을 실행할 필요가 없는 더 오래된 파이프라인인 경우, 이 작업을 취소합니다.
- 문제가 지속되는 경우, GitLab에 문제를 보고합니다.
GraphQL을 통한 작업 상세 정보 가져오기
GraphQL API를 사용하여 작업 정보를 가져올 수 있습니다. 파이프라인 수준의 교차 프로젝트/상위-하위 파이프라인을 사용하는 경우에는 트리거 작업을 UI에서 접근할 수 없으므로, GraphQL API를 사용해야 합니다.
인터랙티브 GraphQL 탐색기를 사용하려면:
- 파이프라인 세부 정보 페이지로 이동합니다.
- 작업 탭을 선택하고 멈춘 작업의 ID를 찾습니다.
-
다음 쿼리를 실행합니다:
{ project(fullPath: "<프로젝트의 전체 경로>") { name job(id: "gid://gitlab/Ci::Build/<작업-id>") { name status detailedStatus { action { path buttonTitle } } } } }
job.detailedStatus.action.path
필드는 리소스를 사용하는 작업 ID를 포함합니다. -
다음 쿼리를 실행하고, 위의 기준에 따라
job.status
필드를 확인합니다. 또한pipeline.path
필드에서 파이프라인 페이지로 이동할 수 있습니다.{ project(fullPath: "<프로젝트의 전체 경로>") { name job(id: "gid://gitlab/Ci::Build/<현재 리소스를 사용하는 작업-id>") { name status pipeline { path } } } }
문제 신고
다음 정보를 포함하여 새로운 이슈를 엽니다:
- 영향을 받는 작업의 ID
- 작업 상태
- 문제가 발생하는 빈도
-
문제를 재현하는 단계
더 많은 지원이 필요하거나 개발 팀과 연락하려면 지원팀에 연락할 수도 있습니다.