GitLab Deploy Policy (운영 기준)¶
0. 전제¶
다음 환경 기준으로 작성:
- 규모: 프로젝트 5~20개 / 서버 소수
- 인력: 1~2명 (소수 정예)
- 멀티 스택 환경: Node.js, Express, Next.js, Nuxt.js, PHP, Laravel, C++ 등
- 운영 서버: Linux / Windows 혼합 가능
- Docker 사용 범위: Runner 빌드 환경 및 Release Storage 서버의 AIStor 실행 용도
- 배포 방식: 운영 서버가 Release Storage에서 빌드 결과물을 직접 가져가는 pull 배포
인프라 전제:
- GitLab 서버, Runner 서버, Release Storage 서버, 운영 서버는 논리적, 물리적으로 분리 가능한 구성으로 보며, 분리 운영을 전제로 작성함.
- GitLab 서버는 외부 비공개로 유지하며, 운영 서버는 GitLab 서버에 직접 접근하지 않음.
- Release Storage 서버는 운영 서버가 접근 가능한 별도 서버로 구성함.
운영 원칙:
- build -> publish -> operation server pull deploy 구조 유지
{YYYYMMDD-HHMMSS}-{declared_version}-{CI_COMMIT_SHORT_SHA}기반 immutable package version 운영- 인증은 목적별 계정 및 Access Key로 분리
- 빌드: Runner 서버
- CI 내부 산출물 보관: GitLab Generic Package Registry
- 운영 배포 기준 저장소: Release Storage (S3-compatible Object Storage)
- 운영: download, verify, extract, activate, report 수행
금지 사항:
- 운영 서버에 write 권한 Access Key 배치 금지
.env및 서버 고유 설정 파일을 패키지에 포함 금지- 운영 서버에서 배포 파일을 수동 수정한 뒤 재사용 금지
- Generic Package Registry에 업로드된 package version/file overwrite 금지
- Release Storage 의 releases 경로 Release Object overwrite 금지
- Release Storage 의
current/{RELEASE_ENV}.json외 object overwrite 금지 - 운영 서버가 GitLab 서버에 직접 접근하도록 구성 금지
1. 배포 방식 선택 배경¶
본 시스템은 운영 서버에 직접 명령을 전달하는 push 방식이 아니라,
운영 서버가 스스로 상태를 수렴하는 pull 기반 상태 수렴(State-based Reconciliation) 배포 구조를 사용함.
해당 구조는 다음 개념을 기반으로 설계됨:
- GitOps pull 방식의 단순화 버전 (Netflix, Airbnb 등 대규모 서비스 구조)
- Kubernetes 환경의 ArgoCD, FluxCD와 동일한 배포 모델
- "중앙이 상태를 선언하면, 각 서버가 해당 상태로 수렴"하는 구조
- 선언적 배포(Declarative Deployment) 및 상태 기반 배포(State-based Deployment)
2. 핵심 운영 개념¶
-
선언적 배포
- GitLab CI/CD 는 운영 서버에 직접 배포 명령을 전달하지 않음
- GitLab CI/CD 는 Release Storage 에 desired release state 를 publish 하여 운영 서버가 수렴해야 할 상태를 선언함
-
자율적 수렴
- 운영 서버는 주기적으로 Release Storage 의
current/{RELEASE_ENV}.json을 polling 함 - 운영 서버는 현재 적용된
package_version과 desired state 의package_version을 비교함 - 값이 다르면 직접 download / verify / extract / activate 과정을 수행하여 상태를 일치시킴
- 운영 서버는 주기적으로 Release Storage 의
-
GitLab CI/CD 역할 재정의
- GitLab CI/CD 는 build, package, release state publish 까지만 수행함
- GitLab CI/CD 는 운영 서버에 직접 접근하지 않음
- GitLab CI/CD 는 운영 서버의 deploy executor 가 아님
운영 기준:
- GitLab CI/CD 는 Release Storage 를 상태 선언 저장소로 사용함
- 운영 서버는 Release Storage metadata 기준으로 상태 수렴(reconciliation)을 수행함
- GitLab Runner 는 운영 서버 접근 권한을 가지지 않음
- GitLab Runner 는 release package 와 release state publish 만 수행함
3. CI/CD 실행 정책¶
- release target branch 는 GitLab CI rules 에 하드코딩하지 않음.
- release 대상 여부는 Release Yaml 파일 존재 여부로 판단함.
경로:
.ops/ci/release-branch-versions/{CI_COMMIT_BRANCH}.yaml
운영 기준:
- Release Yaml 파일 이 존재하는 branch 만 release target 으로 간주함
- 해당 yaml 파일이 없으면 release package 와 release state publish 를 수행하지 않음
- release target branch 를 추가하려면 동일한 이름의 yaml 파일을 추가함
- Protected Variable 을 사용하는 경우 release target branch 도 Protected Branch 로 등록해야 함
Pipeline source 별 동작:
| Pipeline source | 동작 |
|---|---|
merge_request_event |
branch 승격 경로 검증만 수행함 |
push |
release target branch 이면 package/release state publish 를 수행함 |
web |
New Pipeline 수동 실행이며, release target branch 이면 강제 package/release state publish 를 수행함 |
New Pipeline 운영 기준:
- GitLab UI 에서 New Pipeline 실행 시 별도 variable 입력은 필요하지 않음
production,jp-dev-test등 Release Yaml 파일 이 있는 branch 를 선택하면 수동 release 실행 요청으로 처리함- New Pipeline 실행 결과는 새
package_version생성과 Release Storage current metadata 갱신으로 이어짐 - 동일 commit / 동일 declared version 이라도 New Pipeline 실행 시 새 datetime 기반 package version 이 생성될 수 있음
4. 구조적 장점¶
-
확장성
- 서버 수 증가 시 CI/CD 작업량 증가 없음 (O(1))
-
관리 효율
- CI에서 운영 서버 목록(IP 등)을 관리할 필요 없음
-
장애 격리
- 특정 서버 장애가 전체 배포 흐름을 차단하지 않음
-
역할 단순화
- GitLab Runner 는 배포 실행자가 아니라 release package 와 release state 를 publish 하는 역할로 단순화됨
5. 운영 고려사항 및 대응¶
-
배포 즉시성
- Polling 주기 기반 지연 발생
- 현재 구조에서는 systemd timer 주기 기준으로 수렴함
- 필요 시 향후 signal / webhook / queue 기반 보조 구조를 추가할 수 있음
-
배포 완료 가시성
- 운영 서버의
poll-release.log, systemd journal, PM2 상태를 기준으로 확인함 - 필요 시 향후 Slack, API report, central status store 로 확장할 수 있음
- 운영 서버의
-
스크립트 관리
- release 판단과 publish 는 GitLab CI/CD script 기준으로 관리함
- 실제 운영 서버 deploy 절차는
poll-release.sh기준으로 관리함 - 서비스별 검증/후처리는
01-after-prepare-release.shhook 으로 분리함
-
실패 감지
- GitLab CI/CD 실패는 pipeline log 기준으로 확인함
- 운영 서버 deploy 실패는
poll-release.log, systemd journal, PM2 상태 기준으로 확인함 - 현재 구조에서는 운영 서버별 deploy 결과를 중앙에서 강제 수집하지 않음
-
멱등성 보장
- 같은 desired state 를 반복 polling 하더라도 이미 적용된
package_version이면 skip 함 - New Pipeline 수동 실행은 새 package version publish 를 통해 의도적 재패치를 수행함
- 같은 desired state 를 반복 polling 하더라도 이미 적용된
6. 보안 관점 핵심 특징 (Zero-Inbound)¶
본 구조는 배포를 위해 운영 서버에 대한 외부 접근을 허용하지 않음.
운영 기준:
- 운영 서버는 inbound 접근 없이 outbound 통신만 수행함
- GitLab CI/CD 및 Runner 가 운영 서버에 직접 접근하지 않음
- SSH 포트 및 SSH Key 기반 배포 권한 관리가 필요 없음
- 운영 서버는 Release Storage 에 대해 read-only 권한만 사용함
- 운영 서버는 GitLab 서버에 직접 접근하지 않음
효과:
- 운영 서버 공격 표면 최소화
- SSH Key 유출에 따른 전체 서버 침해 리스크 제거
- CI/CD 침해 시 운영 서버로의 횡적 이동(Lateral Movement) 차단
- 배포 권한과 운영 서버 접근 권한 분리
- 네트워크 정책 단순화
본 구조는 운영 서버에 대한 inbound 접근을 제거하여 배포 관련 주요 보안 리스크를 근본적으로 차단함.
7. 결론¶
본 Pull 기반 배포 구조는 다음을 동시에 확보하기 위한 운영 전략임.
-
확장성
- 서버 수 증가 시 GitLab CI/CD 작업량이 서버 수에 비례하여 증가하지 않음
-
운영 단순성
- GitLab CI/CD 는 build, package, release state publish 까지만 담당함
- 운영 서버는 Release Storage current metadata 기준으로 스스로 상태를 수렴함
-
보안성
- 운영 서버는 GitLab 및 Runner 로부터 inbound 접근을 받지 않음
- 운영 서버는 Release Storage read-only 권한만 사용함
-
유연성
- release target branch 는 Release Yaml 파일 (
.ops/ci/release-branch-versions/{CI_COMMIT_BRANCH}.yaml) 로 확장 가능함 - New Pipeline 을 통해 별도 variable 없이 수동 패치를 실행할 수 있음
- release target branch 는 Release Yaml 파일 (
특히 소수 인력 환경에서 다수의 서비스와 여러 runtime stack 을 안정적으로 운영하기 위한 배포 모델로 사용함.