
관리② 리소스 그룹·각종 시크릿 관리
요약
SAP AI Core의 리소스 그룹 및 세 가지 유형의 시크릿(Object Store, Docker Registry, General Secret) 관리 방법을 다룹니다. API를 통한 리소스 그룹 조작 절차와 학습 파이프라인 운영을 위한 필수 시크릿 설정 규칙을 설명합니다.
핵심 포인트
- 리소스 그룹 생성 및 API를 통한 관리 절차 안내
- 시스템 시크릿(Object Store, Docker Registry)과 범용 시크릿의 차이점
- 학습 파이프라인 성공을 위한 'default' 오브젝트 스토어 시크릿 필수 등록
- 리소스 그룹 ID 명명 규칙 및 관리자 주의사항
「SAP AI Core 기술 연재」 제5회.
SAP AI Core의 관리 작업 중, 리소스 그룹 관리(6.3절)와 3종류의 시크릿 관리(6.4-6.6절)를 다룬다. 지난 회차(#4)는 Git 리포지토리·애플리케이션 관리를 다루었다. 다음 회차(#6)는 고도화된 기능(AI Content as a Service)을 다룬다.
리소스 그룹의 개념(정의·분리의 목적·리소스의 범위)은 #2에서, 쿼터(Quota)(리소스 그룹 최대 50개·테넌트 전체 시크릿 최대 5개)는 #3에서 해설 완료했다. 본 기사에서는 그것들을 실제로 조작하는 API 절차에 집중한다.
curl 예시에서 사용하는 $AI_API_URL 및 $TOKEN 환경 변수 설정은 #3을 참조.
SAP AI Core에서 다루는 시크릿은 크게 3종류로 나뉜다.
오브젝트 스토어 시크릿 (Object Store Secret) (6.4절): 데이터셋·모델의 저장소가 되는 클라우드 스토리지로의 접속 정보 -
Docker 레지스트리 시크릿 (Docker Registry Secret) (6.5절): 프라이빗 Docker 이미지를 pull 하기 위한 인증 정보 -
범용 시크릿 (General Secret) (6.6절): 위의 시스템 시크릿에 해당하지 않는 임의의 기밀 정보
앞의 두 가지는 「시스템 시크릿 (System Secret)」이라 불리며, 템플릿 내에서 컨테이너에 직접 전달할 수 없다. 컨테이너에 환경 변수나 볼륨으로 전달할 수 있는 것은 범용 시크릿뿐이다.
Remember: BTP 내의 SAP AI Core 액세스 인증 정보·인증서의 로테이션(Rotation)은 리전 정책에 따라 사용자 자신의 책임하에 수행한다.
관리자는 서비스 컨슈머나 이용 시나리오에 따라 리소스 그룹을 생성·편집·삭제한다.
리소스 그룹 ID 명명 규칙
- 최소 3자, 최대 253자
- 시작과 끝 문자는 소문자·대문자·숫자 중 하나
- 2번째 문자부터 마지막 바로 전까지는 소문자·대문자·숫자·마침표(
.)·하이픈(-)을 사용할 수 있다. 위의 이외의 특수 문자는 사용 불가
curl --location --request POST "$AI_API_URL/v2/admin/resourceGroups" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
요청이 수락되면 202 응답이 반환된다.
중요: 새로운 리소스 그룹을 생성한 경우, 해당 리소스 그룹에서 학습을 실행하기 전에 default라는 이름의 오브젝트 스토어 시크릿을 등록해야 한다(6.4절 참조). 이것이 없으면 학습 파이프라인은 실패한다.
curl --location --request PATCH "$AI_API_URL/v2/admin/resourceGroups/{{resource_group_name}}" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
{{apiurl}}/v2/admin/resourceGroups/{{resource_group_name}} 엔드포인트에 DELETE 요청을 전송한다.
또한, 기본(Default) 리소스 그룹은 삭제할 수 없다(#2 참조).
SAP AI Core를 클라우드 오브젝트 스토어에 접속하고, 오브젝트 스토어 시크릿으로 액세스를 관리한다. 접속한 스토리지에는 데이터셋·모델, 그리고 Metaflow Library for SAP AI Core의 캐시 파일이 저장된다.
Restriction: 학습 출력 아티팩트(모델 등)를 저장하기 위해서는, 입력 학습 아티팩트용으로는 필요에 따라 다른 이름으로 여러 개의 오브젝트 스토어 시크릿을 생성할 수 있지만, default라는 이름의 오브젝트 스토어 시크릿을 생성해야 한다. 이 default 시크릿이 존재하지 않으면 학습 파이프라인은 실패한다.
대응하는 하이퍼스케일러(Hyperscaler) 오브젝트 스토어
- Amazon S3
- Azure Blob Storage
- Google Cloud Storage (GCS)
- OSS (Alibaba Cloud Object Storage Service)
- SAP HANA Cloud, Data Lake
/v2/admin/objectStoreSecrets 엔드포인트에 등록합니다.
Note: Azure Blob Storage 이외의 스토리지 타입에서는 data 필드는 모두 필수입니다. Azure의 경우에만 필수 항목이 개별적으로 지정되어 있습니다.
Amazon S3의 경우
curl --location --request POST "$AI_API_URL/v2/admin/objectStoreSecrets" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
OSS(Alibaba Cloud)의 경우
{
"name": "default",
"type": "oss",
...
SAP HANA Cloud, Data Lake의 경우
{
"name": "default",
"type": "webhdfs",
...
Restriction: SAP HANA Data Lake의 오브젝트 스토어(Object Store)에서 출력 아티팩트(Artifact)가 디렉터리를 가리키는 경우, 워크플로 템플릿에서 archive: none: {}를 사용하여 아티팩트의 아카이브(Archive)를 비활성화할 수 없습니다.
Azure Blob Storage의 경우
{
"name": "default",
"type": "azure",
...
Azure에서 필수인 것은 CONTAINER_URI와 STORAGE_ACCESS_KEY 두 가지입니다. REGION, CLIENT_ID, CLIENT_SECRET, TENANT_ID, SUBSCRIPTION_ID는 선택 사항입니다.
Google Cloud Storage(GCS)의 경우
{
"name": "default",
"type": "gcs",
...
GCS는 BUCKET과 PRIVATE_KEY가 모두 필수입니다.
Tip: pathPrefix는 동일한 버킷을 서로 다른 프로젝트에서 공유할 때 유용합니다. 프로젝트 폴더 이름을 my-ml-project1과 같이 설정하면 모든 데이터가 해당 폴더에 저장됩니다.
Note: AI-Resource-Group 헤더를 지정하지 않으면 리소스 그룹에 자동으로 default가 할당됩니다.
이 헤더를 생략했을 때의 자동 적용은 여러 리소스 그룹을 운영하는 환경에서는 사고로 이어질 수 있습니다. 지정을 잊으면 의도한 리소스 그룹이 아닌 default에 시크릿(Secret)이 등록되며, 심지어 에러가 발생하지 않기 때문에 알아차리기 어렵습니다. 시크릿 조작 시에는 항상 AI-Resource-Group 헤더를 명시할 것을 권장합니다.
등록에 성공하면 202 응답과 성공 메시지가 반환됩니다.
$AI_API_URL/v2/admin/objectStoreSecrets/{{objectStoreName}} 엔드포인트에 PATCH 요청을 전송합니다. 요청 본문(Request Body)의 구조는 등록 시와 동일합니다.
curl --location --request PATCH "$AI_API_URL/v2/admin/objectStoreSecrets/{{objectStoreName}}" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
$AI_API_URL/v2/admin/objectStoreSecrets/{{objectStoreName}} 엔드포인트에 DELETE 요청을 전송합니다.
오브젝트 스토어 시크릿을 삭제하면 해당 오브젝트 스토어에 대한 액세스가 중단됩니다.
Docker는 애플리케이션을 원격 컨테이너에 패키징하여 실행합니다. SAP AI Core를 Docker 리포지토리(Repository)에 연결하고, Docker 레지스트리 시크릿(Registry Secret)으로 액세스를 관리합니다.
Docker 레지스트리 시크릿을 통해 SAP AI Core가 프라이빗 Docker 이미지를 리포지토리에서 pull 할 수 있도록 허가합니다. 워크플로 내에서 시크릿 이름을 지정하여 Docker 이미지 pull을 인증합니다.
전제 조건
- 초기 설정이 완료되어 있을 것 (#3 참조)
인터넷에 공개된 Docker 레지스트리에 접근할 수 있어야 함. VPN이나 사내 네트워크 뒤에 있는 Docker 레지스트리는 사용할 수 없음
{{apiurl}}/v2/admin/dockerRegistrySecrets
엔드포인트로 POST 요청을 보낸다.
curl --location --request POST "$AI_API_URL/v2/admin/dockerRegistrySecrets" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
파라미터는 다음과 같다.
name
: Docker 레지스트리 시크릿(Secret)의 이름. 임의의 식별자를 지정한다.
data
: Docker 레지스트리 시크릿을 나타내는 JSON 문자열
Note: Docker Hub(hub.docker.com)의 퍼블릭 Docker 레지스트리를 사용하는 경우, auths 변수 입력 시 Docker URL을 https://index.docker.io 형식으로 지정해야 한다.
성공하면 {"message": "secret has been created"}가 반환된다.
생성 후에는 템플릿 내에서 이미지 pull 시크릿으로 참조한다.
spec:
imagePullSecrets:
- name: <Name of your Docker registry secret>
$AI_API_URL/v2/admin/dockerRegistrySecrets/{{dockerRegistryName}}
엔드포인트로 PATCH 요청을 보낸다. 바디(Body) 구조는 등록 시와 동일하다 (name, data).
$AI_API_URL/v2/admin/dockerRegistrySecrets/{{dockerRegistryName}}
엔드포인트로 DELETE 요청을 보낸다.
삭제하면 Docker 레지스트리에 대한 접근 권한을 잃게 된다.
범용 시크릿(General Secret)은 시스템 시크릿(System Secret)에 해당하지 않는 기밀 정보를 저장한다. SAP AI Core가 오케스트레이션(Orchestration) 계층으로 기능하는 통합 시나리오에서 유용하다.
3가지 스코프 (Scopes)
범용 시크릿은 요청 헤더(Request Header)의 조합으로 스코프를 지정한다.
- 메인 테넌트 레벨 (Main Tenant Level):
AI-Tenant-Scope: true - 리소스 그룹 레벨 (Resource Group Level):
AI-Resource-Group: <resource-group-name> - 테넌트 전체 레벨 (Tenant-wide Level):
AI-Tenant-Scope: true이면서AI-Resource-Group: *
범용 시크릿은 execution이나 deployment 내의 컨테이너에 환경 변수 또는 볼륨 마운트(Volume Mount)로 연결할 수 있다.
장시간 가동되는 deployment에서 테넌트 전체 시크릿을 재시작 없이 로테이션(Rotation)하려면, deployment 측에서 테넌트 전체 시크릿을 마운트하고 메모리상의 복사본에 의존하지 않고 마운트된 시크릿의 변경 사항을 감시해야 한다. 테넌트 전체 시크릿이 업데이트되었을 때는 Get Secret 엔드포인트의 resourceGroupSecretReplicationStatus 필드를 관찰하여, 필요한 리소스 그룹 전체에 시크릿이 올바르게 복제되었는지 확인한다.
테넌트 전체 시크릿은 테넌트당 최대 5개까지 가능하다 (#3 참조).
Tip: 테넌트 레벨에서 생성한 범용 시크릿은 모든 리소스 그룹으로 자동 전파된다. 단, 동일한 이름의 범용 시크릿이 리소스 그룹 레벨에서 생성되면 생성 시점에 테넌트 레벨의 시크릿을 대체한다. 시스템은 정기적으로 리소스 그룹 레벨의 시크릿을 테넌트 레벨의 것으로 덮어쓰지만, 이 처리에는 시간이 걸릴 수 있다.
리소스 그룹의 사용자가 기존 테넌트 전체 시크릿과 동일한 이름의 시크릿을 생성하면, 리소스 그룹 레벨에서 일시적으로 테넌트 전체 시크릿을 덮어쓰게 된다. 이 동작은 미터링(Metering)과 같은 중요한 처리에서 문제를 일으킬 가능성이 있다.
의도하지 않은 덮어쓰기를 방지하려면, 리소스 그룹 (Resource Group) 사용자가 임의의 시크릿 (Secret)을 생성할 수 없도록 해야 한다. 방법은 두 가지가 있다.
- JWT 토큰을 전달하지 않음으로써, 리소스 그룹 레벨의 사용자가 시크릿 엔드포인트 (Secret Endpoint)에 접근하는 것을 제한한다.
- 리소스 그룹 레벨의 사용자에게는 별도의 인증 메커니즘 (Authentication Mechanism)으로 요청하게 하여 범용 시크릿 (Generic Secret) 생성을 허용한다. 메인 테넌트 (Main Tenant)가 해당 요청을 검증 및 변환한 후 런타임 어댑터 (Runtime Adapter)로 전파함으로써, 시크릿 이름의 일관성을 유지하고 중요한 시크릿이 의도치 않게 변경되지 않도록 한다.
이 두 가지 안에는 트레이드오프 (Trade-off)가 존재한다. 전자는 단순하지만, 리소스 그룹 사용자에 의한 정당한 시크릿 조작까지 일괄적으로 차단한다. 후자는 정당한 조작을 허용할 수 있지만, 메인 테넌트 측에 검증 및 변환 구현이 필요하다. 운영 체제와 리소스 그룹 사용자의 역할에 따라 선택한다.
curl --location --request POST "$AI_API_URL/v2/admin/secrets" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
Note: 관례상, 나중에 Unix 환경 변수 (Environment Variable)로 사용하기 쉽도록 시크릿 이름은 하이픈 (Hyphen) 없이 기술해도 좋다.
성공하면 {"message": "secret has been created", "name": "my-generic-secret"}
가 반환된다.
단일 시크릿 조회와 전체 시크릿 목록 조회가 가능하다.
단일 조회
curl --location --request GET "$AI_API_URL/v2/admin/secrets/$SECRET_NAME" \
--header "Authorization: Bearer $TOKEN" \
--header 'AI-Resource-Group: default'
목록 조회
curl --location --request GET "$AI_API_URL/v2/admin/secrets" \
--header "Authorization: Bearer $TOKEN" \
--header 'AI-Resource-Group: default'
응답에는 시크릿의 이름, 라벨 (Label), 생성 타임스탬프 (Timestamp)가 포함된다. 기밀 정보 그 자체는 응답에 일절 나타나지 않는다.
테넌트 전체 시크릿 (Tenant-wide Secret)의 경우, 응답에는 추가로 테넌트에 연결된 모든 리소스 그룹 목록과 해당 리소스 그룹들로의 복제 상황이 포함된다.
{
"name": "secret-1",
"createdAt": "<timestamp>",
...
resourceGroupSecretReplicationStatus
값은 true가 해당 네임스페이스 (Namespace)에 올바르게 복제되었음을, false가 미복제되었거나 아직 존재하지 않음을 나타낸다.
PATCH 엔드포인트 (Endpoint)를 통해 data와 라벨을 업데이트한다. 시크릿 인증 정보의 로테이션 (Rotation)에도 사용할 수 있다.
curl --location --request PATCH "$AI_API_URL/v2/admin/secrets/$SECRET_NAME" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
...
라벨은 시크릿 데이터와 동시에, 또는 데이터 대신 업데이트할 수 있다. 변경할 수 있는 것은 ext.ai.sap.com/ 접두사 (Prefix)를 가진 라벨뿐이다.
Restriction: 다음 라벨은 PATCH로 업데이트할 수 없다.
ext.ai.sap.com/document-grounding
ext.ai.sap.com/documentRepositoryType
라벨을 삭제하려면 값을 빈 문자열("")로 설정한다.
라벨 업데이트는 시크릿의 재생성을 필요로 하지 않으며 즉시 적용된다. 업데이트 내용은 GET 엔드포인트에서 확인할 수 있다.
curl --location --request DELETE "$AI_API_URL/v2/admin/secrets/$SECRET_NAME" \
--header "Authorization: Bearer $TOKEN" \
--header 'AI-Resource-Group: default'
성공하면 200이 반환된다.
리소스 그룹 (Resource Group) 레벨의 범용 시크릿 (General Secret)은 execution이나 deployment 내의 컨테이너에 연결할 수 있다. 볼륨 (Volume)으로 마운트할지, 환경 변수 (Environment Variable)로 전달할지 선택할 수 있다.
Note: 이 방법으로 컨테이너에 연결할 수 있는 것은 범용 시크릿뿐이다. 시스템 시크릿 (System Secret) (오브젝트 스토어 (Object Store) · Docker 레지스트리 (Docker Registry))은 템플릿에서 사용할 수 없다.
환경 변수로 전달하기 (envFrom.secretRef)
spec:
containers:
- name: my-kserve-container
...
시크릿에 하이픈(-) 등의 유효하지 않은 문자가 포함된 경우, 이 방법으로는 에러가 발생한다. 그 경우에는 env.valueFrom.secretKeyRef를 사용하여 유효한 변수명으로 매핑한다.
환경 변수로 전달하기 (env.valueFrom.secretKeyRef)
spec:
containers:
- name: kserve-container
...
볼륨 마운트 (Volume Mount)로 전달하기
spec:
containers:
- name: kserve-container
...
템플릿 파라미터 (Template Parameter)로 전달하기
시크릿 이름을 템플릿의 파라미터로 포함하여 AI API configuration으로부터 공급할 수도 있다.
envFrom:
- secretRef:
name: "{{inputs.parameters.secretName}}"
리소스 그룹 (Resource Group)
-
생성:
POST /v2/admin/resourceGroups -
편집:
PATCH /v2/admin/resourceGroups/{{resource_group_name}} -
삭제:
DELETE /v2/admin/resourceGroups/{{resource_group_name}}
오브젝트 스토어 시크릿 (Object Store Secret)
-
등록:
POST /v2/admin/objectStoreSecrets -
편집:
PATCH /v2/admin/objectStoreSecrets/{{objectStoreName}} -
삭제:
DELETE /v2/admin/objectStoreSecrets/{{objectStoreName}}
Docker 레지스트리 시크릿 (Docker Registry Secret)
-
등록:
POST /v2/admin/dockerRegistrySecrets -
편집:
PATCH /v2/admin/dockerRegistrySecrets/{{dockerRegistryName}} -
삭제:
DELETE /v2/admin/dockerRegistrySecrets/{{dockerRegistryName}}
범용 시크릿 (General Secret)
-
생성:
POST /v2/admin/secrets -
조회 (단일):
GET /v2/admin/secrets/{{secretName}} -
조회 (목록):
GET /v2/admin/secrets -
업데이트:
PATCH /v2/admin/secrets/{{secretName}} -
삭제:
DELETE /v2/admin/secrets/{{secretName}}
본 기사의 대상 범위 내에서, 공식 문서에 다음과 같은 기재 불일치가 확인되었다. 구현 시에는 최신 공식 API 레퍼런스 (API Reference)를 확인하는 것을 권장한다.
6.3.3 리소스 그룹 삭제: curl 예시의 HTTP 메서드가 POST로 되어 있다 (서드파티 API 플랫폼 설명에서는 DELETE이다).
6.4.1 GCS 등록 예시: GCS에 대해서만 엔드포인트가 /objectStoreSecrets/{{objectStoreName}}라고 기재되어 있다 (다른 스토리지 타입은 /objectStoreSecrets이다).
) -
6.5.2 Docker 레지스트리 시크릿 편집: 「서드파티 API 플랫폼」 절의 내용이 Docker가 아닌 Git 리포지토리 편집 설명으로 되어 있음 (#4의 6.1.2와 동일한 문구) -
6.6.2/6.6.3의 JSON 예시: {{secret_name]]와 같은 괄호 오류, data 객체 뒤의 콤마 누락, 인용부호 불일치 등이 포함되어 있음 (본 기사에서는 이를 수정하여 게재함)
본 기사에서 다룬 설정 중에는 실수를 하더라도 즉시 에러가 발생하지 않고, 나중에 원인을 알기 어려운 형태로 문제가 나타나는 것들이 여러 개 있다. 운영을 시작하기 전에 다음 사항을 점검해 두는 것이 좋다.
각 리소스 그룹(Resource Group)에 default라는 이름의 오브젝트 스토어 시크릿(Object Store Secret)이 등록되어 있는지 (없으면 학습 파이프라인이 실패함) -
시크릿 조작 시 AI-Resource-Group 헤더를 명시하고 있는지 (생략하면 default에 등록되어 에러가 발생하지 않음) -
테넌트 전체 시크릿(Tenant-wide Secret)과 동일한 이름의 시크릿이 리소스 그룹 레벨에서 생성되어 있지 않은지 (일시적인 덮어쓰기가 발생함)
-
리소스 그룹 사용자의 시크릿 생성 권한이 운영 방침에 따라 제한되어 있는지
-
Docker 레지스트리가 인터넷에 공개되어 있는지 (VPN·사내 네트워크 하위는 사용 불가)
-
테넌트 전체 시크릿이 상한선인 5개에 도달하지 않았는지
-
리소스 그룹이 상한선인 50개에 도달하지 않았는지
-
SAP HANA Data Lake를 사용하는 경우, 워크플로 템플릿에서
archive: none: {}를 사용하고 있지 않은지 -
리소스 그룹 ID는 3~253자이다. 시작과 끝은 영숫자여야 하며, 중간에는 마침표(.)와 하이픈(-)만 허용된다.
-
학습 출력을 저장하려면
default라는 이름의 오브젝트 스토어 시크릿이 필수이다. 없으면 학습 파이프라인이 실패한다. -
대응하는 오브젝트 스토어는 S3, Azure Blob, GCS, OSS, HANA Cloud Data Lake의 5종류이다. Azure를 제외한 나머지는
data필드가 모두 필수이다. -
Docker 레지스트리는 인터넷에 공개되어 있어야 한다. VPN·사내 네트워크 하위는 사용 불가하다.
-
범용 시크릿(Generic Secret)은 메인 테넌트, 테넌트 전체, 리소스 그룹의 3가지 스코프(Scope)를 가지며, 헤더의 조합으로 지정한다.
-
동일한 이름의 시크릿이 스코프가 중복될 경우 일시적인 덮어쓰기가 발생하여 미터링(Metering) 등에 영향을 줄 수 있다. 리소스 그룹 사용자의 시크릿 생성 권한을 제한하여 이를 방지한다.
-
컨테이너에 연결할 수 있는 것은 범용 시크릿뿐이다. 시스템 시크릿(System Secret)은 템플릿에서 소비할 수 없다.
-
다음 편(#6)에서는 고급 기능(AI Content as a Service)을 다룬다.
시스템 시크릿 (System Secret): 오브젝트 스토어 및 Docker 레지스트리용 시크릿. 템플릿을 통해 컨테이너로 전달할 수 없다.
범용 시크릿 (Generic Secret): 시스템 시크릿에 해당하지 않는 기밀 정보를 저장하는 시크릿. 컨테이너에 환경 변수 또는 볼륨으로 전달할 수 있다.
pathPrefix: 오브젝트 스토어의 버킷 이름 뒤에 붙는 경로 접두사(Path Prefix). 동일한 버킷을 여러 프로젝트에서 공유할 때 폴더를 구분하기 위해 사용한다.
imagePullSecrets: Kubernetes 템플릿에서 프라이빗 Docker 이미지의 pull 인증에 사용할 시크릿을 지정하는 필드.
resourceGroupSecretReplicationStatus: 테넌트 전체 시크릿이 각 리소스 그룹으로 복제되었는지를 나타내는 상태(Status) 필드.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기