
Agent Substrate: K8s 상의 에이전트형 AI 격리 계층
요약
Kubernetes 환경에서 에이전트형 워크플로우를 안전하게 실행하기 위한 격리 계층인 Agent Substrate를 소개합니다. gVisor를 활용하여 보안과 효율성을 동시에 확보하며, GKE 배포를 위한 아키텍처와 구성 요소를 다룹니다.
핵심 포인트
- 에이전트의 무분별한 권한 접근을 방지하기 위한 샌드박싱 기술의 중요성
- gVisor를 활용한 보안 및 리소스 효율적인 컨테이너 격리 구현
- Kubernetes 기반의 컨트롤 플레인 및 상태 저장소 등 시스템 구성 요소 설명
- atelet을 통한 워커 포드 관리 및 스냅샷 체크포인트/복구 기능
격리/샌드박싱 (Isolation/sandboxing)은 에이전트형 워크플로우 (agentic workflows)를 안전하고 보안이 유지되며 통제된 방식으로 실행할 수 있는 능력을 제공합니다. 이것이 없다면, 여러분의 에이전트 (Agents)는 여러분이 할 수 있는 거의 모든 것에 접근할 수 있으며, 모든 유형의 웹 조사 및 API 호출을 수행할 수 있습니다.
샌드박싱 (sandboxing)이 이러한 에이전트 문제를 해결함에 따라, 다음 질문은 "샌드박스가 어디서 어떻게 실행될 것인가?"이며, 바로 이 지점에서 Substrate가 등장합니다.
이 블로그에서는 Substrate가 무엇인지, 그리고 GKE에 어떻게 배포하는지에 대해 배우게 될 것입니다.
사전 요구 사항 (Prerequistes)
이 블로그 포스트를 실습 관점에서 따라오기 위해서는 다음이 필요합니다:
- GCP 계정
- GKE 클러스터 (cluster)
Agent Substrate란 무엇인가
Kubernetes는 기본적으로 두 가지를 매우 잘 수행합니다:
- 오케스트레이션 (Orchestration)
- 사용자가 GPU, CPU 및 메모리 풀을 확보할 수 있도록 워커 노드 (worker nodes)를 클러스터링 (Clustering) 하는 것
Kubernetes 상에 구축할 수 있지만 기본 기능은 아닌 것은 하드웨어 리소스 관리의 더 높은 효율성, 더 낮은 지연 시간 (latency), 그리고 에이전트형 워크플로우 (Agentic workflows)의 구현 (예: 에이전트 실행 및 에이전트 격리)입니다. 하지만 Kubernetes의 기본 요소 (Pods, 오토스케일링 (autoscaling), 워커 노드 클러스터링)는 여전히 매우 필요하므로, 오늘날 우리가 알고 있는 Kubernetes를 기반으로 구축된 에이전트 시대 (Agentic era)를 위한 도구/플랫폼이 필요합니다. 자체적인 컨트롤 플레인 (Control Plane)/관리 계층을 가지면서도, 여전히 Kubernetes가 제공하는 기능을 사용하는 무언가가 필요합니다.
그것이 바로 Agent Substrate가 등장하는 이유입니다.
내부적으로 Substrate는 gvisor (CNCF SIG의 Agent Sandbox 프로젝트와 동일한 것)를 사용합니다. 이는 보안, 격리, 그리고 효율적인 방식(예: 막대한 하드웨어 리소스를 차지하지 않음)으로 사용할 수 있는 능력에 초점을 맞춘 Google에서 개발한 컨테이너 샌드박스 (container sandbox)입니다.
Substrate 내부 구조 (Substrate Internals)
Substrate에는 네 가지 주요 구성 요소가 있습니다:
- ate-api-server (컨트롤 플레인 (control plane))
- atenet-router (Envoy/DNS 라우터)
- valkey (상태 저장소 (state store))
- pod-certificate-controller 자체
그리고 워커 (Workers)와 함께 "에이전트와 유사한 액터 (agent-like Actors)"가 있습니다.
또한 모든 워커 노드에서 실행되는 노드별 에이전트 (Per-node Agent, DaemonSet)인 atelet을 볼 수 있습니다. atelet은 워커 포드 (Worker Pods)를 관리하고, runsc 체크포인트/복구 (checkpoint/restore)를 구동하며, 이어지는 섹션에서 생성할 GCS 버킷으로 스냅샷을 스트리밍하거나 버킷으로부터 스냅샷을 가져옵니다.
시스템 구성 요소 (System Components)
그리고 이 네 가지 워크로드 (workloads)는 앞서 언급한 모든 시스템 구성 요소를 위해 podCertificate 볼륨을 마운트합니다. 포드 인증서 (pod certs)가 필요한 이유는 이러한 구성 요소들(정확히는 구성 요소를 실행하는 포드들)이 서로 간의 mTLS (mutual TLS)를 수행할 수 있도록 TLS 인증서를 자동으로 발급 및 자동 갱신 (auto-rotated) 받기 위함입니다.
💡
Google에 따르면: 포드 인증서 (Pod Certificates)는 실행 중인 포드에 직접 수명이 짧은 X.509 TLS 인증서를 자동으로 발급하는 Kubernetes 네이티브 기능입니다. Kubernetes v1.34에서 알파 (alpha) 기능으로 도입되어 v1.35에서 베타 (Beta)로 격상된 이 기능은 워크로드가 kube-apiserver에 인증하고 다른 워크로드와 네이티브하게 상호 TLS (mTLS)를 설정할 수 있도록 합니다.
포드 인증서는 Agent Substrate의 필수 요구 사항입니다. Substrate가 각 구성 요소에 포드별로 자동 갱신되는 mTLS 신원 (identity)을 부여하는 방식이 바로 이것이기 때문입니다. 포드는 podCertificate가 투영된 볼륨 소스 (projected volume source)를 선언하며, 이는 PodCertificateRequest를 트리거하고 서명자 (signer)가 이를 이행합니다. kubelet은 자격 증명 번들 (credential bundle)을 포드에 투영(및 자동 갱신)하며, 포드가 실행되려면 해당 볼륨이 반드시 마운트되어야 합니다.
두 가지 별개의 차이점을 명확히 하자면 다음과 같습니다:
- 포드 인증서 (Pod certs) == Substrate 자체 인프라(위의 네 가지 포드)를 위한 신원 (identity). 이것이 포드 인증서를 필요로 하는 부분입니다.
- 액터 신원 (Actor identity) == 세션 ID JWT/CA 풀 비밀값 (session-id JWT/CA pool secrets)에 의해 뒷받침되는
SessionIdentitygRPC 서비스 (MintJWT/MintCert). Actor/worker/ateom 포드는podCertificate볼륨을 마운트하지 않습니다.
따라서 이 기능은 에이전트에게 인증서를 주는 것이 아니라
- 액터 (Actor)의 생명주기 관리 기능 (예: 액터 생성, 파괴, 일시 중단, 재개)
- 실시간으로 액터를 워커 (Worker)에 할당하는 능력
- 유입되는 트래픽을 액터로 라우팅 (Route)
Substrate가 액터를 실행하는 방식의 효율성 덕분에, 단일 워커 (Single Worker) 상에서 수많은 액터를 실행할 수 있습니다. Google은 단 8개의 포드 (Pods, 즉 워커)에 걸쳐 250개의 상태 저장 액터 (Stateful Actors)를 실행하며 이를 테스트했습니다.
Substrate와의 상호작용
Substrate는 자체적인 관리 평면 (Management Plane)과 리소스를 가지고 있기 때문에, 자체 명령줄 도구(CLI)인 ate를 통해 상호작용할 수 있습니다.
예: kubectl ate (이와 관련된 자세한 내용은 이어지는 설정 섹션에서 다룰 예정입니다).
환경 설정 요구사항/전제 조건
Google Kubernetes Engine (GKE) 클러스터, GCP 환경 및 CLI 도구에 대해 설정해야 할 몇 가지 사항이 있습니다.
- 터미널에서 GCP 및 GKE 환경을 관리하기 위한
gcloud및 관련 모든 인증 (Auth) 도구.
export PROJECT_ID=<your-project-id>
gcloud auth login
...
- Substrate에 필요한 API들.
gcloud services enable \
cloudresourcemanager.googleapis.com \
container.googleapis.com \
...
- 로컬 환경에 클론(Clone)된 Agent Substrate 저장소. 여기에서 클론할 수 있습니다.
- 터미널의 로컬 도구들:
- Go (v1.26.3 이상)
kubectlgit- Valkey CA 인증서를 통합하기 위한
openssl(자세한 내용은 나중에 설명)
왜 GKE 또는 Kind를 사용하는가?
podCertificate 프로젝션 볼륨 소스 (Projected Volume Source)는 kubelet/apiserver 내의 코드이지만, k8s 1.36 버전 기준으로 기본값이 꺼져 있는 기능 게이트 (Feature Gates) 뒤에 있습니다. 이를 사용하려면 k8s API Server를 통해 해당 게이트를 활성화해야 합니다. 다음과 같은 방식입니다:
--feature-gates=PodCertificateRequest=true,ClusterTrustBundle=true,ClusterTrustBundleProjection=true
--runtime-config=certificates.k8s.io/v1beta1=true
문제는 모든 관리형 Kubernetes (k8s) 서비스(예: AKS)가 이 기능을 활성화하는 것을 허용하지 않는다는 점입니다. GKE는 기본적으로 이를 조절할 수 있는 "노브(knob)"를 제공하므로 가능하며, 관리되지 않는/순수 Kubernetes 클러스터(Kind, Kubeadm 등)는 사용자가 구성을 직접 관리하기 때문에 가능합니다.
ko
ko는 Google에서 만든 Go 컨테이너 이미지용 빌드 도구입니다. Dockerfile과 Docker 데몬 없이 Go 소스 코드에서 직접 이미지를 빌드합니다. 이미지는 ko에 의해 빌드되어 사용자의 KO_DOCKER_REPO로 푸시됩니다. valkey(상태 저장소)는 설치 스크립트를 통해 자동으로 배포될 수 있으므로 수동으로 설치할 필요가 없습니다.
환경 설정 (Configure Your Environment)
선행 요구 사항, 환경 설정, 그리고 Agent Substrate 및 그 구성 요소에 대한 설명을 마쳤으니, 이제 직접 Substrate 환경을 배포해 보겠습니다.
- 클론(clone)한
substrate디렉토리 내에서 다음을 실행합니다:
cp hack/ate-dev-env.sh.example .ate-dev-env.sh
.ate-dev-env.sh파일을 환경 설정에 맞게 수정합니다. 선행 요구 사항(Prerequisites) 섹션에 따라 이미 GKE 클러스터를 보유하고 있으므로, 파일에는 다음 내용만 필요합니다:
# --- 프로젝트 / ID (Project / identity) ---
export PROJECT_ID=my-substrate-proj
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
...
- 2단계에서 도출한 두 개의 ID를 생성합니다.
export ATELET_PRINCIPAL="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/ate-system/sa/atelet"
export NODE_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
- GKE 클러스터에 Pod Certificate 베타 API와 Workload Identity가 활성화되어 있는지 확인합니다.
source .ate-dev-env.sh
gcloud container clusters update "$CLUSTER_NAME" \
...
- Actor를 위한 스냅샷 버킷(snapshot bucket)을 생성합니다.
gcloud storage buckets create "gs://${BUCKET_NAME}" \
--project="$PROJECT_ID" --location="$GCE_REGION" --uniform-bucket-level-access
atelet이 버킷과 상호 작용할 때 사용할 IAM 권한을 생성합니다.
gcloud storage buckets add-iam-policy-binding "gs://${BUCKET_NAME}" \
--member="$ATELET_PRINCIPAL" --role=roles/storage.objectAdmin
gcloud storage buckets add-iam-policy-binding "gs://${BUCKET_NAME}" \
...
- GKE 노드와
atelet에 대한 프로젝트 수준 IAM 권한을 부여합니다.
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${NODE_SA}" --role=roles/storage.objectViewer
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
...
새 노드 풀 (New Node Pools)
Pod Certificate 볼륨을 마운트하는 것은 kubelet(노드 수준) 기능이며, 노드의 kubelet 설정은 노드가 생성될 때 고정됩니다. 컨트롤 플레인에서 베타 API를 활성화한다고 해서 이미 존재하는 노드에 소급 적용되는 것은 아닙니다. 이 경우 기존 클러스터였기 때문에 노드들이 기능을 활성화하기 이전의 시점을 거치므로, 해당 기능을 사용하려면 노드를 다시 생성해야 합니다. 가장 간단한 방법은 새로운 노드 풀을 만드는 것입니다 (같은 버전으로 업그레이드하는 것만으로는 노드가 이미 컨트롤 플레인 버전에 맞기 때문에 재설정되지 않습니다).
- c3 유형의 노드 풀을 생성합니다.
gcloud container node-pools create substrate-pool \
--cluster="$CLUSTER_NAME" --location="$CLUSTER_LOCATION" --project="$PROJECT_ID" \
--machine-type=c3-standard-4 --num-nodes=1 \
...
- 노드 풀이 준비될 때까지 기다립니다.
kubectl get nodes -l cloud.google.com/gke-nodepool=substrate-poo
- 이전 노드 풀을 삭제합니다.
gcloud container node-pools delete default-pool \
--cluster="$CLUSTER_NAME" --location="$CLUSTER_LOCATION" --project="$PROJECT_ID"
클러스터 환경 설정 및 설치가 완료되었으므로, Agent Substrate를 설치해 보겠습니다.
Substrate 설치 (Installing Substrate)
substrate 디렉토리 내의 hack 디렉토리에서 install-ate.sh 파일을 찾을 수 있습니다. 이 파일은 핵심 이미지(ko를 통해 빌드되어 KO_DOCKER_REPO에 푸시됨)를 구축하고, Agent Substrate 컨트롤 플레인/관리 플레인 및 노드 구성 요소를 배포합니다:
- CRD (Custom Resource Definitions)
ate-api-server(컨트롤 플레인 (control plane))pod-certificate-controller(PodCertificateRequest를 처리하는 클러스터 내부 mTLS 서명자 (in-cluster mTLS signer))atelet(노드 데몬셋 (node DaemonSet))atenet(DNS + Envoy 라우터 (router))valkey(동적 상태 저장소 (dynamic state store))- 다음 명령어를 실행합니다:
./hack/install-ate.sh --deploy-ate-system
설치가 진행되는 것을 확인할 수 있습니다.
- 시스템 Pod가 올라올 때까지 기다립니다.
kubectl get pods -n ate-system --watch
Pod가 모두 올라오면, Substrate 설치가 완료되었습니다.
Substrate CLI 설치
Substrate 시스템이 가동 중인 상태에서, 컨트롤/관리 플레인 (control/management plane)과 상호작용할 방법이 필요합니다. 이를 위해 ate 서브 명령어 (sub-command)를 사용하게 됩니다.
- 명령어를 설치합니다.
go install ./cmd/kubectl-ate
- 바이너리 (binary)를 PATH에 추가합니다.
echo 'export PATH="$PATH:$(go env GOPATH)/bin"' >> ~/.zshrc
source ~/.zshrc
- 서브 명령어를 테스트합니다.
kubectl ate --help
이제 ate가 설치되었으며 Agent Substrate와 상호작용할 준비가 되었습니다.
마무리
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

