모듈 정의, 수정과 삭제
모듈은 제품과 배포 개체 구성, 설치 변수를 하나의 정의로 묶습니다. 정의를 바꾸어 게시하면 새 버전이 만들어지며, 기존 환경에 적용하려면 설치본 업데이트가 필요합니다. 이미 게시한 버전을 직접 수정하는 방식은 아닙니다.
먼저 Apollo CLI를 설치하고 연결합니다. 필요한 모듈 기능이 없는 오래된 CLI라면 새 배포본을 받아 사용해야 할 수 있습니다.
이름과 파일
YAML 파일의 기본 이름은 name 값과 맞춥니다. 다음 모듈의 파일 이름은 control-plane-module.yml 또는 control-plane-module.yaml로 정합니다.
name: control-plane-module
displayName: Control Plane Module
description: 애플리케이션 제어 계층의 제품과 구성을 묶습니다.
name은 내부 이름이며 displayName과 설명은 사람이 구분하기 위한 정보입니다.
변수의 종류
변수는 variables 아래에 이름별로 정의합니다. 정의한 변수만 {{ moduleVariable.myNamespace }}처럼 참조할 수 있습니다. 다른 곳에서 여전히 참조하는 변수는 삭제할 수 없습니다.
| 종류 | 역할 |
|---|---|
string | 설치 시 직접 입력할 문자열 |
options | 미리 정한 선택지 중 하나를 고르는 변수 |
stringPreset | 선택한 options 값에 따라 문자열 값을 계산하는 변수 |
문자열 변수
| 필드 | 의미 |
|---|---|
description | 설치자가 값을 정할 때 참고할 설명 |
defaultValue | 선택적 기본값. 없으면 설치 시 값을 제공해야 함 |
constraint | 선택적 값 제한. 기본값이 있으면 기본값도 제한을 충족해야 함 |
제약은 oneOf와 regex를 지원합니다. 정규식은 문자열 양끝에 경계가 있는 것으로 검사하므로 일부만 맞는 값은 통과하지 않습니다.
variables:
myNamespace:
type: string
string:
defaultValue: default
description: 배포 개체를 설치할 네임스페이스
constraint:
type: oneOf
oneOf: [default, namespace1, namespace2]
heapSize:
type: string
string:
defaultValue: 3g
description: 숫자 뒤에 k, m 또는 g를 붙인 힙 크기
constraint:
type: regex
regex: '\d+[kmg]'
myNamespace는 열거한 값 중 하나여야 합니다. heapSize의 3g는 정규식에 맞지만 heap-3g처럼 앞에 다른 문자가 붙은 값은 맞지 않습니다.
프리셋 변수
여러 구성값을 함께 선택하게 하려면 options와 stringPreset을 조합합니다. 예를 들어 small, medium, large 중 하나를 선택하면 CPU와 메모리를 함께 정할 수 있습니다.
variables:
resourceProfile:
type: options
options:
values: [small, medium, large]
defaultValue: medium
description: 배포 규모
serviceMemory:
type: stringPreset
stringPreset:
description: 서비스 메모리
options: resourceProfile
mapping:
small: 1Gi
medium: 2Gi
large: 4Gi
serviceCpu:
type: stringPreset
stringPreset:
description: 서비스 CPU
options: resourceProfile
mapping:
small: 500m
medium: 1000m
large: 2000m
- 각
stringPreset은options필드로 options 변수를 참조해야 합니다. mapping에는 그 options 변수의 모든 선택지가 있어야 합니다.- 설치자는 options 값을 선택하며 개별 stringPreset 값을 직접 재정의하지 않습니다.
- 새 모듈 버전에서 매핑을 바꾸면 설치본을 그 버전으로 업데이트할 때 새 값이 적용됩니다. 예를 들어 small의 메모리를
1Gi에서1.5Gi로 바꾸면 small을 선택한 설치본의 값도 업데이트됩니다.
배포 개체 정의
entities는 배포 개체 정의의 목록입니다. 여기의 helmChart, terraformModule은 모듈 안에서 사용하는 배포 개체 종류이며 제품 명세의 제품 유형 필드와 구분합니다.
공통 필드
다음 필드는 각 종류의 구성 블록 안에 둡니다.
| 필드 | 필수 여부 | 의미 |
|---|---|---|
productId | 필수 | 제품의 groupId:artifactId |
entityName | 선택 | 배포 개체 식별 이름. 기본값은 제품의 artifactId |
ignoredDependencies | 선택 | 검사에서 제외할 제품 의존 관계. 없으면 빈 목록 사용 가능 |
configOverrides | 선택 | 버전별 설정 재정의를 담은 YAML 문자열 |
installConfigOverrides | 선택 | 처음 설치할 때만 적용할 재정의. syncConfigOverrides: MERGE 필요 |
syncConfigOverrides | 선택 | 기존 개체 구성의 동기화 방식. 기본값은 ENABLED |
markedForUninstallation | 선택 | 존재하면 설치 제거 대상으로 표시. 환경에 대상이 없으면 그 항목은 설치 시 무시 |
markedForUninstallation.minVersion | 선택 | 설치 제거가 가능한 최소 버전. 없으면 버전에 관계없이 제거 대상 |
markedForUninstallation.unmanageAfterUninstall | 선택 | 제거 후 관리 해제 방식. 기본값 AUTOMATIC, 관리를 남기려면 MANUAL |
secretRequirements | 선택 | 설치·업데이트 전에 있어야 하는 비밀정보 이름과 키 |
dependencyGroups | 선택 | 의존 관계를 평가할 그룹. 없으면 default 그룹 |
dependencyGroupOverrides | 선택 | 특정 의존 제품을 찾을 그룹의 재정의. "*"는 어느 그룹에서든 충족 가능하게 함 |
의존 관계를 충족하는 개체는 기본적으로 관련 개체와 그룹을 하나 이상 공유해야 합니다. 스택이나 네임스페이스 이름과 의존 그룹을 같은 설정으로 취급하지 않습니다.
Helm 차트
type: helmChart와 helmChart 블록을 사용하며, k8sNamespace가 필수입니다.
네임스페이스를 변수로 제공하더라도 기존 배포 개체의 설치 위치를 자동으로 옮기는 기능은 아닙니다. 개체를 만든 뒤의 네임스페이스 변경 제약을 확인해야 합니다.
entities:
- type: helmChart
helmChart:
productId: com.example:backend-service
k8sNamespace: "{{ moduleVariable.myNamespace }}"
syncConfigOverrides: MERGE
configOverrides: |
"2.0.0":
overrides:
num-threads: 100
이 블록은 myNamespace 변수가 정의된 모듈에 포함하는 예입니다. configOverrides는 중첩 YAML을 문자열로 담으므로 |를 사용합니다.
Terraform 모듈
type: terraformModule과 terraformModule 블록을 사용합니다. accountId는 선택적 설치 계정 식별자입니다.
다음은 변수 정의까지 포함한 가상의 인프라 모듈 예시입니다.
name: infrastructure-module
displayName: Infrastructure Module
variables:
targetAccountId:
type: string
string:
description: 설치 대상 계정 식별자
moduleInstanceName:
type: string
string:
defaultValue: application-infrastructure
description: 배포 개체 이름
dependencyGroupId:
type: string
string:
defaultValue: application
description: 이 개체의 의존 그룹
networkDependencyGroupId:
type: string
string:
defaultValue: networking
description: 네트워크 의존 제품을 찾을 그룹
exampleValue:
type: string
string:
description: Terraform에 전달할 값
entities:
- type: terraformModule
terraformModule:
productId: com.example:infrastructure-module
accountId: "{{ moduleVariable.targetAccountId }}"
entityName: "{{ moduleVariable.moduleInstanceName }}"
dependencyGroups:
- "{{ moduleVariable.dependencyGroupId }}"
dependencyGroupOverrides:
"com.example:networking-module":
- "{{ moduleVariable.networkDependencyGroupId }}"
syncConfigOverrides: MERGE
configOverrides: |
"1.0.0":
overrides:
subpath: infrastructure
variables:
exampleVariable: "{{ moduleVariable.exampleValue }}"
기존 대상과 설치 순서
모듈의 정의와 같은 배포 개체가 이미 있으면 그 설정을 모듈에 맞추어 변경할 수 있습니다. 기존 값의 유지 여부는 아래의 동기화 방식에 따라 다릅니다. 설치 시 편입에서는 Entity ID도 확인해야 합니다.
배포 개체 목록의 작성 순서만으로 설치 순서를 지정하는 것은 아닙니다. 제품 릴리스 명세의 의존 관계를 선언하면 Apollo가 제약 평가 과정에서 설치 순서를 계산합니다.
가상의 애플리케이션 제품이 데이터베이스 제품 뒤에 설치되어야 한다면 애플리케이션 릴리스의 명세에 다음 관계를 넣을 수 있습니다.
extensions:
product-dependencies:
- product-group: com.example
product-name: database-service
minimum-version: 1.0.0
maximum-version: 1.x.x
하위 모듈
submodules에 이미 존재하는 모듈을 이름과 정확한 버전으로 포함할 수 있습니다.
submodules:
- name: backend-module
version: 0.3.0
| 필드 | 의미 |
|---|---|
name | 이미 Apollo에 있는 모듈 이름 |
version | 포함할 정확한 버전. 상위 모듈의 한 버전 안에서는 불변 |
key | 같은 하위 모듈을 여러 번 포함할 때 구별하는 고유 키 |
variableOverrides | 하위 모듈 변수를 고정값 또는 상위 변수로 연결 |
entityOverrides | 하위 모듈의 배포 개체 구성과 비밀정보 요구 사항 등을 재정의 |
하위 모듈 버전을 바꾸려면 상위 모듈의 새 버전을 만들어야 합니다. 변수와 개체 재정의의 적용 범위는 복합 모듈에서 설명합니다.
사용 제한
새 직접 설치 제한
restrictions:
newInstallations:
allowed: false
이 설정으로 새 설치를 허용하지 않을 수 있습니다. 다른 복합 모듈의 하위 구성으로만 쓰려는 모듈에서 고려할 수 있습니다.
상위 모듈의 개체 재정의 제한
restrictions:
submoduleUsage:
allowEntityOverrides: false
이 제한이 있으면 상위 모듈의 entityOverrides로 구성, 비밀정보 요구 사항이나 무시할 의존 관계 등을 바꿀 수 없습니다. 그런 복합 모듈을 만들면 검증에 실패합니다. variableOverrides는 여전히 사용할 수 있습니다.
예를 들어 데이터베이스 모듈에서 버전과 고정 설정을 보호하면서 선택한 변수만 조정하도록 만들 수 있습니다. 다음은 가상의 사용자 지정 데이터베이스 차트 예시이며 특정 범용 PostgreSQL 차트의 공통 인터페이스를 뜻하지 않습니다.
name: database-module
displayName: Database Module
restrictions:
submoduleUsage:
allowEntityOverrides: false
variables:
postgresReplicated:
type: string
string:
defaultValue: 'false'
description: 복제 구성 선택
backupTuningParameter:
type: string
string:
defaultValue: '3'
description: 백업 조정 값
postgresMaxConnections:
type: string
string:
description: 최대 연결 수
entities:
- type: helmChart
helmChart:
productId: com.example:database
k8sNamespace: databases
configOverrides: |
"1.0.0":
overrides:
postgresql:
name: postgres-shared-cluster
feature-flag-1: true
feature-flag-2: true
postgresql-version: '17'
data-storage: 400Gi
replicated: "{{ moduleVariable.postgresReplicated }}"
env:
BACKUP_TUNING_PARAMETER: "{{ moduleVariable.backupTuningParameter }}"
postgresql-conf:
max_connections: {{ moduleVariable.postgresMaxConnections }}
wal_keep_size: 800
max_connections는 변수 치환 뒤 유효한 숫자형 YAML 값이 되도록 설치 값을 제공합니다. 기본값이 없으므로 설치자가 값을 지정해야 합니다.
이 모듈을 사용하는 상위 정의는 노출된 변수만 바꿀 수 있습니다.
name: application-composite-module
submodules:
- name: application-module
version: 0.1.0
- name: database-module
version: 0.1.0
variableOverrides:
postgresReplicated: 'true'
backupTuningParameter: '10'
entityOverrides로 데이터베이스 버전을 17에서 16으로 바꾸는 식의 수정은 허용되지 않습니다. 위에서 지정하지 않은 최대 연결 수는 설치 시 제공해야 합니다.
전체 모듈 예시
다음은 백엔드와 데이터베이스를 함께 구성하고, 사용을 종료할 제품 하나를 제거 대상으로 두는 가상의 control-plane-module.yml입니다. variables는 이름별 매핑이며 entities는 목록입니다.
name: control-plane-module
displayName: Control Plane Module
description: 애플리케이션 제어 계층 구성
variables:
myNamespace:
type: string
string:
defaultValue: default
description: 배포 개체의 기본 네임스페이스
resourceProfile:
type: options
options:
values: [small, medium, large]
defaultValue: medium
description: 배포 규모
backendCpu:
type: stringPreset
stringPreset:
description: 백엔드 CPU
options: resourceProfile
mapping:
small: 500m
medium: 1000m
large: 2000m
databaseCpu:
type: stringPreset
stringPreset:
description: 데이터베이스 CPU
options: resourceProfile
mapping:
small: 250m
medium: 500m
large: 1000m
backendMemory:
type: stringPreset
stringPreset:
description: 백엔드 메모리
options: resourceProfile
mapping:
small: 1Gi
medium: 2Gi
large: 4Gi
databaseMemory:
type: stringPreset
stringPreset:
description: 데이터베이스 메모리
options: resourceProfile
mapping:
small: 512Mi
medium: 1Gi
large: 2Gi
entities:
- type: helmChart
helmChart:
productId: com.example:backend-service
k8sNamespace: "{{ moduleVariable.myNamespace }}"
configOverrides: |
"2.0.0":
overrides:
resources:
requests:
cpu: "{{ moduleVariable.backendCpu }}"
memory: "{{ moduleVariable.backendMemory }}"
limits:
memory: "{{ moduleVariable.backendMemory }}"
num-threads: 100
- type: helmChart
helmChart:
productId: com.example:database-service
k8sNamespace: "{{ moduleVariable.myNamespace }}"
configOverrides: |
"2.0.0":
overrides:
resources:
requests:
cpu: "{{ moduleVariable.databaseCpu }}"
memory: "{{ moduleVariable.databaseMemory }}"
limits:
memory: "{{ moduleVariable.databaseMemory }}"
secretRequirements:
service-secret:
type: multikey
multikey:
description: 서비스 간 통신용 API 키
keys: [api-key]
- type: helmChart
helmChart:
productId: com.example:retired-application
k8sNamespace: app-namespace
markedForUninstallation:
minVersion: 1.0.0
unmanageAfterUninstall: MANUAL
게시와 버전
CLI로 정의를 게시합니다.
./apollo-cli module create --module-definition-file ./control-plane-module.yml
모듈 버전은 처음 0.1.0으로 배정되고 정의를 업데이트할 때 부 버전이 증가합니다. 개별 게시 버전은 불변이며 직접 편집하거나 삭제할 수 없습니다.
Software Catalog → Modules에서 게시 결과를 확인합니다.
정의 수정
모듈의 Actions → Edit module에서 정의를 내려받을 수 있습니다.
Download module definition으로 파일을 받아 수정하고 CLI의 module create로 새 버전을 게시합니다.
모듈 이름 옆 버전 선택기와 설치본 표에서 버전을 확인합니다.
실제 설치본 업데이트는 추적하는 릴리스 채널과 변경 요청을 따릅니다. 업데이트 및 승인 정책을 함께 확인합니다.
변수를 바꿀 때의 영향
추가
새 변수에는 가능한 경우 기본값을 제공합니다. 기본값이 없으면 기존 설치본의 업데이트는 사용자가 값을 넣기 전까지 차단됩니다.
삭제
모든 참조를 먼저 제거해야 변수를 삭제할 수 있습니다. 예를 들어 enableFeatureFlag를 구성에서 참조하고 있다면 다음 중 하나로 바꿉니다.
| 변경 | 기존 설치본에 대한 의미 |
|---|---|
참조를 고정값 true로 대체 | 해당 키가 동기화되는 모드에서는 이전 선택값 대신 고정값 사용 |
| 해당 구성 항목 제거 | 이후의 처리 방식은 설정 동기화 모드에 따름 |
| 정의된 다른 변수로 참조 변경 | 해당 키가 동기화되면 새 변수가 제공하는 값 사용 |
이름 변경
기존 설치본이 선택한 값을 보존하면서 변수 이름만 바꾸는 기능은 없습니다. Apollo는 이름 변경을 기존 변수 삭제와 새 변수 생성으로 구분할 수 없으므로 값의 이전을 별도로 고려해야 합니다.
배포 개체 제거와 모듈 간 이동
설치 제거를 지시하는 경우
대상을 실제로 제거하려면 모듈 정의에서 markedForUninstallation을 명시합니다. 빈 객체도 제거 의사를 나타냅니다.
entities:
- type: helmChart
helmChart:
productId: com.example:retired-application
k8sNamespace: app-namespace
markedForUninstallation: {}
특정 이전 작업이 끝난 버전부터 제거해야 한다면 최소 버전을 지정합니다.
markedForUninstallation:
minVersion: 1.45.0
설치본을 이 모듈 버전으로 업데이트하면 해당 조건과 제품 의존 관계 제약에 따라 제거가 진행됩니다.
정의에서 항목만 없애는 경우
배포 개체 항목을 모듈 정의에서 삭제하는 것만으로 설치가 제거되지는 않습니다. 대상은 남고 그 모듈의 관리만 끝납니다. Apollo의 개체 자체를 관리 해제하는 작업과도 다릅니다.
하나의 배포 개체를 동시에 관리할 수 있는 모듈은 하나뿐입니다. 모듈 사이에서 개체를 옮기려면 다음 순서로 진행합니다.
- 기존 모듈 정의에서 항목만 제거합니다. 설치 제거 표시는 하지 않습니다.
- 새 모듈 정의에 같은 ID와 구성을 추가하고 필요한 변수도 옮깁니다.
- 기존 모듈 설치본을 먼저 업데이트하여 소유 관계를 해제합니다.
- 이후 새 모듈 설치본을 업데이트하여 관리를 넘겨받습니다.
예를 들어 core-services의 모니터링 제품을 observability로 옮길 수 있습니다. 실제 ID와 적용값을 그대로 유지하여 최종 차이가 없으면 새 변경 계획 없이 설치를 유지한 채 소유 관계를 바꿀 수 있습니다. 변수 값이 달라졌다면 적용될 변경 내용을 확인해야 합니다.
기존 구성의 동기화 방식
syncConfigOverrides는 기존 개체를 편입하거나 모듈 설치본을 갱신할 때의 동작을 정합니다. 새 개체를 처음 추가할 때는 어느 모드든 모듈의 configOverrides를 적용합니다.
| 값 | 기존 개체의 구성 처리 |
|---|---|
ENABLED | 기본값. 모듈의 재정의로 기존 재정의 전체를 대체 |
MERGE | 모듈에 있는 키는 모듈 값으로 덮어쓰고, 나머지 기존 키는 유지 |
DISABLED | 기존 개체의 재정의를 유지. 기존 대상을 새로 편입할 때도 유지 |
MERGE에서 모듈이 제어하는 키는 사용자가 개체에서 직접 덮어쓸 수 없습니다. {{ unset }}은 키를 제거하고 사용자가 다시 설정하지 못하게 하는 특별한 값입니다.
모듈 정의에서 키 자체를 빼는 것과 {{ unset }}으로 지정하는 것은 다릅니다. MERGE에서 키를 정의에서 빼면 기존 환경의 값은 남고, 이후 사용자가 자유롭게 수정할 수 있습니다.
모드별 결과 예시
가상의 기존 구성과 새 모듈 구성이 다음과 같다고 가정합니다.
"3.0.0":
overrides:
conf:
key1: a
key2: b
key3: c
"3.0.0":
overrides:
conf:
key1: x
key3: "{{ unset }}"
key4: d
| 적용 방식 | key1 | key2 | key3 | key4 |
|---|---|---|---|---|
MERGE | x | b 유지 | 제거 | d 추가 |
ENABLED | x | 제거 | 제거 | d |
DISABLED | a 유지 | b 유지 | c 유지 | 없음 |
그다음 모듈 정의에서 key1도 제거하고 key3: "{{ unset }}", key4: d만 남기면 결과는 다음과 같습니다.
| 적용 방식 | 결과 |
|---|---|
MERGE | key1: x, key2: b, key4: d 유지. key1은 이제 사용자가 수정 가능 |
DISABLED | 처음의 key1: a, key2: b, key3: c 유지 |
ENABLED | key4: d만 남음 |
처음 설치할 때만 적용할 값
installConfigOverrides는 MERGE에서만 사용할 수 있습니다. 개체를 처음 만들 때 configOverrides와 함께 적용하고, 이후 해당 키는 개체 소유가 되어 모듈이 갱신하지 않습니다.
entities:
- type: helmChart
helmChart:
productId: com.example:database-service
k8sNamespace: "{{ moduleVariable.myNamespace }}"
syncConfigOverrides: MERGE
configOverrides: |
"2.0.0":
overrides:
feature-flag: enabled
installConfigOverrides: |
"2.0.0":
overrides:
resources:
requests:
cpu: 8
memory: 4Gi
이 예시는 myNamespace가 정의된 모듈에 포함합니다. feature-flag는 계속 동기화하지만 CPU와 메모리는 첫 설치 뒤 환경별로 바꿀 수 있습니다. 이후 모듈 버전의 installConfigOverrides에 새 키를 추가해도 기존 설치에 소급 적용되지 않으며 앞으로 처음 설치하는 대상에만 적용됩니다.
모듈 업데이트 일시 정지
긴급하게 모듈 소유의 개체 설정을 바꿔야 한다면 설치본의 모듈 업데이트를 일시 정지할 수 있습니다.
일시 정지하면 다음과 같이 동작합니다.
- 열려 있는 모듈 업데이트 변경 요청을 취소합니다.
- 새 모듈 업데이트 변경 요청을 만들지 않습니다.
- 평소 모듈이 제어하는 개체 구성 키를 수정할 수 있습니다.
모듈의 Installations 또는 환경의 Modules에서 설치본의 점 세 개 메뉴를 열고 Pause Module updates를 선택합니다.
업데이트를 다시 활성화하면 최신 적용 대상 모듈 버전으로 맞추는 변경 요청이 만들어지고, 일시 정지 중 생긴 구성 차이를 조정합니다. 이 요청이 병합될 때까지 Resuming Updates로 표시됩니다.
모듈 업데이트 일시 정지는 모듈 정의 업데이트를 멈춥니다. 배포 개체에 새 변경 계획이 발행되는 것을 막으려면 변경 억제 시간대를 사용합니다.
모듈 삭제
남아 있는 설치본이 없을 때만 모듈을 삭제할 수 있습니다. 먼저 모든 설치본에서 모듈 연결을 해제해야 합니다.
Actions → Delete module을 선택하면 Software Catalog에서 모듈이 제거됩니다.
모듈 연결 해제와 카탈로그의 모듈 삭제는 실제 제품 설치를 제거하는 동작이 아닙니다. 개별 버전의 불변성과 모듈 전체 삭제의 조건도 구분해야 합니다.