Skip to main content

AI 클러스터에서 보안의 기준선이 달라진다

웹 서비스 시대의 쿠버네티스 보안은 비교적 선명했다. 컨테이너 이미지에 취약점이 없는지 확인하고, Secret을 잘 숨기고, RBAC를 최소 권한으로 나누고, Pod가 루트 권한으로 뜨지 않게 하면 기본 골격은 잡혔다. 물론 그것만으로도 쉬운 일은 아니었다. 그러나 AI 워크로드가 들어오면 보안의 무게가 한 단계 더 무거워진다.

이제 클러스터에는 단순한 API 서버만 올라가지 않는다. 수십 GB에서 수백 GB에 이르는 모델 가중치가 있고, 사용자의 프롬프트와 응답 로그가 있고, RAG를 위한 문서 조각과 임베딩 벡터가 있으며, 외부 LLM API 키와 벡터 DB 접속 토큰이 있다. 에이전트는 사용자를 대신해 외부 도구를 호출하고, 어떤 경우에는 코드를 실행하거나 데이터베이스에 접근한다. 쿠버네티스 입장에서 보면 모두 Pod이고 Service이고 Secret이지만, 운영자 입장에서 보면 이것은 훨씬 더 민감한 시스템이다.

AI 클러스터 보안은 네 가지 질문에서 출발해야 한다.

첫째, 무엇을 실행하고 있는가? 컨테이너 이미지뿐 아니라 모델 파일, 추론 런타임, CUDA 베이스 이미지, Python 패키지, Helm 차트까지 포함해 출처와 무결성을 확인해야 한다.

둘째, 누가 무엇에 접근할 수 있는가? 데이터 사이언티스트, ML 엔지니어, 플랫폼 팀, CI/CD 파이프라인, 추론 Pod, 에이전트 Pod가 서로 다른 권한을 가져야 한다.

셋째, 어떤 데이터가 어디에 남는가? 프롬프트, 응답, 임베딩, 모델 출력, 업로드 파일, 벡터 인덱스는 모두 민감 데이터가 될 수 있다.

넷째, 정책을 사람이 기억하는가, 플랫폼이 강제하는가? 보안 문서를 잘 써두는 것만으로는 부족하다. 승인된 이미지, 시크릿 방식, 네트워크 정책, 리소스 제한이 기본값으로 포함된 배포 경로를 제공해야 한다.

이 장의 목표는 보안 도구 목록을 나열하는 것이 아니다. 프로덕션 AI 서비스를 운영할 때 "이 정도는 기본으로 지켜야 한다"라고 말할 수 있는 기준선을 세우는 것이다.

보안과 규정 준수

AI 컨테이너 공급망: 이미지 하나를 믿기 위해 필요한 것들

AI 서비스의 컨테이너 이미지는 보통 무겁다. CUDA 런타임, cuDNN, NCCL, Python, PyTorch, Transformers, vLLM, SGLang, 토크나이저 라이브러리, 커스텀 전처리 코드가 한 이미지 안에 들어간다. 여기에 사내 패치가 들어간 추론 서버나 모델 어댑터까지 포함되면, 이미지 하나가 사실상 작은 운영체제처럼 변한다.

문제는 이미지가 크고 복잡할수록 "무엇이 들어 있는지" 알기 어렵다는 점이다. 어느 날 OpenSSL이나 glibc, Python 패키지에서 치명적인 CVE가 발표되었을 때, 우리는 즉시 대답할 수 있어야 한다.

"우리 프로덕션 추론 이미지 중 이 취약한 라이브러리를 포함한 것이 있는가?"

이 질문에 답하려면 공급망 보안을 단일 단계가 아니라 파이프라인으로 봐야 한다. 핵심 흐름은 다음과 같다.

  1. 이미지를 빌드한다.

  2. 취약점을 스캔한다.

  3. SBOM을 생성한다.

  4. 이미지와 SBOM에 서명한다.

  5. provenance, 즉 빌드 출처를 기록한다.

  6. 쿠버네티스 admission 단계에서 검증된 것만 배포한다.

SBOM은 Software Bill of Materials의 약자로, 소프트웨어 구성 명세서라고 부른다. 식품 포장지의 원재료 목록처럼 이미지 안에 어떤 패키지와 라이브러리가 들어 있는지 기계가 읽을 수 있는 형식으로 기록한 문서다. Kubernetes 프로젝트도 릴리스 아티팩트와 SBOM을 서명하고 검증하는 절차를 문서화하고 있으며, cosign 기반의 keyless 서명과 SBOM 검증 흐름을 사용한다1.

AI 이미지에서는 SBOM의 가치가 더 크다. 같은 vllm-openai 이미지라도 베이스 CUDA 버전, PyTorch 빌드 옵션, FlashAttention 버전, 토크나이저 라이브러리 버전에 따라 성능과 안정성, 취약점이 달라진다. 운영팀은 "vLLM을 쓴다"가 아니라 "어떤 digest의 어떤 이미지가 어떤 라이브러리 조합으로 빌드되었는가"를 추적해야 한다.

# 예: Trivy로 이미지 취약점 스캔
trivy image \
  --severity HIGH,CRITICAL \
  --ignore-unfixed \
  ghcr.io/acme/llm-server@sha256:...

# 예: Syft로 CycloneDX 형식 SBOM 생성
syft packages \
  ghcr.io/acme/llm-server@sha256:... \
  -o cyclonedx-json=sbom.cyclonedx.json

# 예: SPDX 형식 SBOM 생성
syft packages \
  ghcr.io/acme/llm-server@sha256:... \
  -o spdx-json=sbom.spdx.json

여기서 중요한 습관은 태그가 아니라 digest를 기준으로 다루는 것이다. :latest, :prod, :v1 같은 태그는 덮어쓸 수 있다. 반면 @sha256:... digest는 이미지 내용 자체를 가리킨다. 서명, SBOM, 배포 매니페스트는 가능하면 digest를 기준으로 연결해야 한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-server
  namespace: ai-prod
spec:
  replicas: 2
  selector:
    matchLabels:
      app: llm-server
  template:
    metadata:
      labels:
        app: llm-server
    spec:
      containers:
        - name: vllm
          image: ghcr.io/acme/llm-server@sha256:abc123...
          args:
            - "--model=/models/llama"

이렇게 해야 "어제 배포한 이미지와 오늘 실행 중인 이미지가 같은가?"라는 질문에 명확히 답할 수 있다.

서명과 provenance: 누가, 어디서, 어떻게 만들었는가

취약점 스캔은 "알려진 문제가 있는가?"를 확인한다. 그러나 공급망 공격은 꼭 알려진 CVE만 이용하지 않는다. 빌드 파이프라인 자체가 침해되거나, 레지스트리의 이미지가 바뀌거나, 누군가 비슷한 이름의 이미지를 올리는 방식으로도 발생한다.

이미지 서명은 이 문제에 대한 기본 방어선이다. 서명은 단순히 "이 이미지는 안전하다"라는 도장이 아니다. 더 정확히 말하면 "이 digest의 이미지는 우리가 신뢰하는 빌드 주체가 만들었다"라는 암호학적 증거다.

# GitHub Actions 같은 OIDC 환경에서 keyless 서명
cosign sign --yes ghcr.io/acme/llm-server@sha256:abc123...

# 신뢰하는 워크플로에서 서명되었는지 검증
cosign verify \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  --certificate-identity \
  "https://github.com/acme/llm-platform/.github/workflows/release.yml@refs/heads/main" \
  ghcr.io/acme/llm-server@sha256:abc123...

여기서 --certificate-identity와 --certificate-oidc-issuer를 지정하는 것이 중요하다. 단순히 "서명이 있다"만 확인하면 공격자가 자기 계정으로 서명한 이미지도 통과할 수 있다. 우리가 확인하려는 것은 서명의 존재가 아니라 신뢰하는 주체가 서명했는가이다.

provenance는 한 단계 더 나아간다. provenance는 빌드 출처 증명이다. 어떤 Git 커밋에서, 어떤 워크플로로, 어떤 빌드 환경에서, 어떤 입력을 사용해 이미지가 만들어졌는지 기록한다. SLSA는 이런 공급망 보안 성숙도를 단계적으로 정리한 프레임워크다. 처음부터 높은 수준을 달성하려고 하면 부담스럽다. 현실적인 시작점은 다음 정도다.

name: llm-image-release

on:
  push:
    tags:
      - "llm-server-v*"

permissions:
  contents: read
  packages: write
  id-token: write

jobs:
  build-scan-sign:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/acme/llm-server:${{ github.sha }}

      - name: Scan image
        run: |
          trivy image \
            --severity HIGH,CRITICAL \
            --exit-code 1 \
            ghcr.io/acme/llm-server:${{ github.sha }}

      - name: Generate SBOM
        run: |
          syft packages \
            ghcr.io/acme/llm-server:${{ github.sha }} \
            -o cyclonedx-json=sbom.cyclonedx.json

      - name: Sign image
        run: |
          cosign sign --yes ghcr.io/acme/llm-server@${{ steps.build.outputs.digest }}

      - name: Attach SBOM
        run: |
          cosign attach sbom \
            --sbom sbom.cyclonedx.json \
            ghcr.io/acme/llm-server@${{ steps.build.outputs.digest }}

이 파이프라인은 완벽한 보안의 끝이 아니라 출발점이다. 하지만 이 정도만 해도 "누가 만든 이미지인지 모른다", "이미지 안에 뭐가 들어 있는지 모른다", "취약한 이미지를 실수로 배포했다"라는 세 가지 흔한 사고를 크게 줄일 수 있다.

Admission policy: 클러스터 입구에서 막아야 한다

보안 검사는 CI/CD에서 끝나면 안 된다. 누군가 직접 kubectl apply를 하거나, 잘못된 Helm values를 넣거나, 테스트용 이미지를 프로덕션 네임스페이스에 배포할 수도 있다. 그래서 쿠버네티스 API 서버 앞단에서 정책을 강제해야 한다. 이 역할을 admission controller가 맡는다.

대표적인 선택지는 Kyverno, OPA Gatekeeper, Sigstore policy-controller 같은 도구다. 정책의 형태는 조직마다 다르지만, AI 프로덕션 네임스페이스에는 최소한 다음 조건을 권장한다.

  • 승인된 레지스트리의 이미지만 허용한다.

  • digest로 고정된 이미지만 허용한다.

  • 신뢰하는 CI/CD 주체가 서명한 이미지만 허용한다.

  • 필수 라벨과 owner 정보를 요구한다.

  • privileged Pod, hostPath, hostNetwork를 기본 차단한다.

  • GPU Operator 같은 시스템 컴포넌트 예외는 별도 네임스페이스에만 허용한다.

Kyverno를 사용한다면 이미지 서명 검증 정책을 다음처럼 작성할 수 있다.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-ai-images
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: require-signed-ai-images
      match:
        any:
          - resources:
              kinds:
                - Pod
              namespaces:
                - ai-prod
      verifyImages:
        - imageReferences:
            - "ghcr.io/acme/*"
          required: true
          verifyDigest: true
          attestors:
            - entries:
                - keyless:
                    issuer: "https://token.actions.githubusercontent.com"
                    subject: "https://github.com/acme/llm-platform/.github/workflows/release.yml@refs/heads/main"

처음부터 모든 정책을 Enforce로 걸면 개발팀이 하루 종일 막힐 수 있다. 좋은 도입 방식은 먼저 Audit 모드로 2~4주 정도 운영하면서 실제 위반 패턴을 보는 것이다. 어떤 팀이 latest를 쓰는지, 어떤 이미지가 개인 Docker Hub에서 오는지, 어떤 실험 Pod가 루트 권한으로 뜨는지 확인한다. 그다음 경고를 공유하고, 템플릿을 제공하고, 마지막에 차단으로 전환한다.

보안 정책은 사람을 혼내는 장치가 아니라 사고를 줄이는 안전벨트다. 안전벨트가 불편하다고 차에서 제거하지 않듯이, admission policy도 결국 모두를 보호하는 기본 장치가 되어야 한다.

시크릿 관리: Kubernetes Secret을 그대로 믿지 말자

AI 서비스에서 시크릿은 특히 많다. OpenAI API 키, Azure OpenAI 키, Hugging Face 토큰, 모델 레지스트리 토큰, Pinecone이나 Weaviate 접속 정보, MongoDB 연결 문자열, S3 버킷 접근 권한, Slack Webhook, 결제 API 키가 모두 시크릿이다.

쿠버네티스의 Secret 오브젝트는 ConfigMap보다 나은 선택이지만, 그 자체로 만능 금고는 아니다. Kubernetes 공식 문서는 Secret 값이 기본적으로 base64로 인코딩되며, etcd에는 기본적으로 암호화되지 않은 상태로 저장될 수 있으므로 저장 시 암호화와 최소 권한 접근을 구성해야 한다고 설명한다2. base64는 암호화가 아니다. 누구나 디코딩할 수 있는 표현 방식일 뿐이다.

kubectl get secret openai-key -n ai-prod -o jsonpath='{.data.API_KEY}' | base64 -d

이 명령 한 줄로 값이 보인다면, get secrets 권한은 사실상 비밀번호를 읽는 권한이다. 따라서 Secret 보안은 다음 세 가지 원칙으로 잡아야 한다.

첫째, 평문 시크릿을 Git에 넣지 않는다. Kubernetes Secret YAML도 base64일 뿐이므로 Git에 커밋하면 평문 유출과 다르지 않다.

둘째, 프로덕션 시크릿의 원본은 외부 시크릿 저장소에 둔다. HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault 같은 시스템을 사용하고, 쿠버네티스에는 필요한 시점에 필요한 형태로만 동기화한다.

셋째, 접근 권한과 감사 로그를 외부 저장소와 쿠버네티스 양쪽에서 모두 남긴다. 누가 시크릿을 읽었는지, 어떤 Pod가 어떤 시크릿을 사용했는지 추적할 수 있어야 한다.

External Secrets Operator를 사용하면 외부 시크릿 저장소의 값을 Kubernetes Secret으로 동기화할 수 있다. 다음은 Azure OpenAI 키를 외부 저장소에서 가져오는 예시다.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: azure-keyvault
  namespace: ai-prod
spec:
  provider:
    azurekv:
      tenantId: "00000000-0000-0000-0000-000000000000"
      vaultUrl: "https://acme-prod-kv.vault.azure.net"
      authType: WorkloadIdentity
      serviceAccountRef:
        name: external-secrets-sa
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: azure-openai-credentials
  namespace: ai-prod
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: azure-keyvault
    kind: SecretStore
  target:
    name: azure-openai-credentials
    creationPolicy: Owner
  data:
    - secretKey: AZURE_OPENAI_API_KEY
      remoteRef:
        key: prod-azure-openai-api-key
    - secretKey: AZURE_OPENAI_ENDPOINT
      remoteRef:
        key: prod-azure-openai-endpoint

애플리케이션 Pod에서는 이 Secret을 환경 변수로 넣을 수도 있고 파일로 마운트할 수도 있다. 일반적으로는 파일 마운트가 더 낫다. 환경 변수는 디버깅 도구, 프로세스 목록, 오류 로그에 노출될 가능성이 있기 때문이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rag-api
  namespace: ai-prod
spec:
  template:
    spec:
      containers:
        - name: api
          image: ghcr.io/acme/rag-api@sha256:...
          volumeMounts:
            - name: openai-secret
              mountPath: /var/run/secrets/openai
              readOnly: true
      volumes:
        - name: openai-secret
          secret:
            secretName: azure-openai-credentials

애플리케이션은 /var/run/secrets/openai/AZURE_OPENAI_API_KEY 파일을 읽어 사용한다. 이때 주의할 점은 Secret을 읽은 뒤 로그에 남기지 않는 것이다. 생각보다 많은 사고가 "디버깅을 위해 config 전체를 출력했다"에서 시작된다.

RBAC와 서비스 계정: 사람보다 Pod가 더 위험할 수 있다

쿠버네티스 보안에서 흔히 사람 계정만 신경 쓰는 실수를 한다. 하지만 클러스터 안에서 실제로 많은 요청을 보내는 주체는 Pod다. Pod는 ServiceAccount를 통해 쿠버네티스 API에 접근할 수 있고, 클라우드 IAM과 연결되어 외부 리소스에도 접근할 수 있다.

AI 클러스터에서는 워크로드별 권한 분리가 특히 중요하다. 학습 Job은 데이터셋 버킷과 체크포인트 저장소에 접근할 수 있어야 하지만, 프로덕션 추론 Secret을 읽을 필요는 없다. 추론 서버는 모델 가중치와 일부 캐시 저장소에 접근하면 되지만, 학습 데이터 전체를 읽을 필요는 없다. 에이전트 Pod는 외부 도구 호출 권한을 가질 수 있지만, 그 권한은 사용자와 테넌트에 따라 제한되어야 한다.

좋은 기본 규칙은 "하나의 워크로드, 하나의 서비스 계정"이다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: vllm-inference-sa
  namespace: ai-prod
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: vllm-inference-reader
  namespace: ai-prod
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: vllm-inference-reader-binding
  namespace: ai-prod
subjects:
  - kind: ServiceAccount
    name: vllm-inference-sa
    namespace: ai-prod
roleRef:
  kind: Role
  name: vllm-inference-reader
  apiGroup: rbac.authorization.k8s.io

여기서 automountServiceAccountToken: false에 주목하자. 애플리케이션이 쿠버네티스 API를 호출할 필요가 없다면 토큰을 자동 마운트하지 않는 것이 안전하다. 많은 웹 API, 추론 서버, 워커는 클러스터 API에 접근할 필요가 없다. "혹시 필요할지도 모르니 열어둔다"는 습관이 나중에 침해 사고의 이동 경로가 된다.

권한을 설계할 때는 kubectl auth can-i를 자주 사용하자.

kubectl auth can-i get secrets \
  --as=system:serviceaccount:ai-prod:vllm-inference-sa \
  -n ai-prod

kubectl auth can-i create jobs \
  --as=system:serviceaccount:ai-prod:vllm-inference-sa \
  -n ai-prod

두 명령 모두 no가 나와야 정상일 가능성이 높다. 추론 서버가 Secret을 직접 열람하거나 Job을 생성할 필요가 없다면 말이다.

사람 계정도 네임스페이스와 역할 기준으로 나눠야 한다. 데이터 사이언티스트에게 클러스터 전체 cluster-admin을 주는 것은 편하지만 위험하다. 대신 팀별 네임스페이스와 Role을 만들고, Job 생성과 로그 조회 정도만 허용한다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: data-scientist
  namespace: team-a-train
rules:
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["create", "get", "list", "watch", "delete"]
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: []

마지막 secrets 규칙은 실제로는 생략해도 된다. 쿠버네티스 RBAC는 허용 목록 방식이므로 명시하지 않으면 거부된다. 예시에서는 의도를 보여주기 위해 넣었지만, 실제 YAML에서는 빈 verbs 규칙보다 아예 권한을 정의하지 않는 방식이 더 깔끔하다.

Pod Security Standards: AI Pod도 루트일 필요는 없다

GPU를 사용하는 Pod는 왠지 특별한 권한이 필요할 것처럼 보인다. 하지만 대부분의 vLLM, SGLang, KServe 추론 Pod는 privileged 권한이 필요 없다. GPU 디바이스 접근은 NVIDIA Device Plugin, GPU Operator, CDI, DRA 같은 계층이 처리해야 한다. 애플리케이션 컨테이너가 호스트 네임스페이스를 열거나, 루트 파일시스템을 마음대로 쓰거나, Linux capability를 많이 들고 있을 이유는 없다.

네임스페이스에는 Pod Security Standards를 적용해 기본 기준선을 잡는다.

kubectl label namespace ai-prod \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

단, GPU Operator나 CNI, 스토리지 CSI 드라이버처럼 노드 수준 권한이 필요한 시스템 컴포넌트는 별도 네임스페이스에 두고 예외를 명확히 관리한다. 예외는 필요하다. 문제는 예외가 문서화되지 않고 일반 애플리케이션 네임스페이스에 섞이는 것이다.

추론 Pod의 보안 컨텍스트는 다음처럼 시작할 수 있다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-vllm
  namespace: ai-prod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: secure-vllm
  template:
    metadata:
      labels:
        app: secure-vllm
    spec:
      serviceAccountName: vllm-inference-sa
      automountServiceAccountToken: false
      securityContext:
        runAsNonRoot: true
        runAsUser: 10001
        runAsGroup: 10001
        fsGroup: 10001
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: vllm
          image: ghcr.io/acme/vllm-runtime@sha256:...
          ports:
            - containerPort: 8000
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: model-cache
              mountPath: /models
              readOnly: true
          resources:
            limits:
              nvidia.com/gpu: "1"
              memory: "64Gi"
            requests:
              nvidia.com/gpu: "1"
              memory: "64Gi"
      volumes:
        - name: tmp
          emptyDir: {}
        - name: model-cache
          persistentVolumeClaim:
            claimName: llama-model-cache

readOnlyRootFilesystem: true를 켜면 일부 Python 라이브러리나 모델 런타임이 임시 파일을 쓰지 못해 실패할 수 있다. 이때 루트 파일시스템을 쓰게 풀어주는 대신 /tmp, /var/tmp, 캐시 경로만 emptyDir나 PVC로 명시적으로 열어주는 편이 낫다. 보안은 "안 된다"가 아니라 "필요한 곳만 된다"로 설계해야 지속된다.

User Namespaces가 안정화된 환경에서는 컨테이너 내부의 root와 호스트의 root를 분리할 수 있다. 이것은 컨테이너 탈출 위험을 줄이는 중요한 계층이다. 다만 모든 런타임, CNI, 스토리지 조합에서 동일하게 동작하는 것은 아니므로, 프로덕션 적용 전 GPU 워크로드와 함께 충분히 테스트해야 한다.

네트워크 정책: LLM 서버가 모든 곳에 말하게 두지 않는다

기본 쿠버네티스 네트워크는 많은 환경에서 "Pod끼리 서로 통신 가능"에 가깝다. 작은 개발 클러스터에서는 편하지만, AI 프로덕션에서는 위험하다. 추론 서버가 벡터 DB에는 접근해야 할 수 있다. 그러나 학습 네임스페이스의 데이터셋 전처리 Pod나 운영 DB, 내부 관리자 API까지 접근할 필요는 없다.

먼저 네임스페이스 전체에 기본 차단 정책을 적용한다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: ai-prod
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

그다음 필요한 통신만 열어준다. 예를 들어 Gateway에서 RAG API로 들어오는 트래픽, RAG API에서 벡터 DB와 Azure OpenAI 엔드포인트로 나가는 트래픽만 허용한다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-gateway-to-rag-api
  namespace: ai-prod
spec:
  podSelector:
    matchLabels:
      app: rag-api
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: gateway
          podSelector:
            matchLabels:
              app: ai-gateway
      ports:
        - protocol: TCP
          port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-rag-api-egress
  namespace: ai-prod
spec:
  podSelector:
    matchLabels:
      app: rag-api
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: vector-db
      ports:
        - protocol: TCP
          port: 5432
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: observability
      ports:
        - protocol: TCP
          port: 4317

외부 SaaS로 나가는 트래픽은 CNI에 따라 FQDN 기반 정책이나 egress gateway를 사용해야 한다. 특히 OpenAI, Anthropic, Vertex AI, Bedrock, Azure OpenAI 같은 외부 AI 서비스로 나가는 트래픽은 API 키 주입, 지역 제한, 감사 로그, 장애 시 failover 정책과 연결된다.

2026년 Kubernetes 커뮤니티에서 AI Gateway Working Group이 만들어진 것도 이 흐름과 맞닿아 있다. 이 워킹그룹은 Gateway API 기반 인프라 위에 AI API를 위한 토큰 기반 rate limit, 세밀한 접근 제어, payload inspection, 라우팅, 캐싱, guardrail 같은 기능을 표준화하려고 한다3. AI 트래픽은 단순 HTTP가 아니다. 요청 본문 안의 프롬프트, 도구 호출, 모델 이름, 테넌트 정보가 모두 정책 판단의 입력이 된다.

에이전트와 샌드박스: 신뢰할 수 없는 실행을 격리한다

에이전트 워크로드는 전통적인 API 서버보다 위험하다. 사용자의 요청을 해석하고, 도구를 선택하고, 외부 API를 호출하고, 때로는 코드를 생성해 실행한다. 이때 "Pod 안에서 실행되니까 안전하다"라고 생각하면 안 된다. 쿠버네티스의 기본 격리는 프로세스와 네임스페이스 수준의 격리이지, 악성 코드를 마음 놓고 실행해도 되는 보안 경계가 아니다.

특히 다음 상황에서는 샌드박스 런타임을 고려해야 한다.

  • 사용자가 업로드한 코드를 실행한다.

  • LLM이 생성한 Python, JavaScript, Bash 코드를 실행한다.

  • 외부 플러그인이나 MCP 서버를 동적으로 연결한다.

  • 테넌트별로 신뢰 수준이 다른 작업을 같은 클러스터에서 처리한다.

  • 에이전트가 사내 시스템에 대한 도구 호출 권한을 가진다.

gVisor는 사용자 공간 커널 계층을 통해 시스템 호출을 중간에서 처리하고, Kata Containers는 경량 VM 기반 격리를 제공한다. 둘 다 일반 runc 컨테이너보다 강한 격리를 제공하지만 비용이 있다. 시작 시간이 늘거나, 일부 시스템 호출이 호환되지 않거나, GPU 접근이 제한될 수 있다. 따라서 모든 Pod에 무조건 적용하기보다 "신뢰할 수 없는 코드 실행" 네임스페이스를 별도로 만들고, 그곳에 RuntimeClass를 강제하는 방식이 현실적이다.

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
---
apiVersion: batch/v1
kind: Job
metadata:
  name: agent-code-runner
  namespace: ai-sandbox
spec:
  template:
    spec:
      runtimeClassName: gvisor
      restartPolicy: Never
      automountServiceAccountToken: false
      containers:
        - name: runner
          image: ghcr.io/acme/agent-runner@sha256:...
          securityContext:
            runAsNonRoot: true
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          resources:
            limits:
              cpu: "1"
              memory: "1Gi"

이 Job은 쿠버네티스 API 토큰도 없고, 루트 파일시스템도 읽기 전용이며, capability도 모두 제거했다. 여기에 네트워크 정책으로 egress를 차단하면, 코드 실행 환경의 폭발 반경을 크게 줄일 수 있다.

에이전트 보안의 핵심은 "모델을 믿지 않는다"가 아니라 "모델이 선택한 행동을 검증한다"이다. 사람도 실수하고 모델도 실수한다. 따라서 도구 호출은 항상 정책 엔진을 거쳐야 한다. 예를 들어 send_email, delete_file, query_customer_db, execute_sql 같은 도구는 사용자 권한, 테넌트, 요청 목적, 승인 상태에 따라 허용 여부가 달라져야 한다.

모델과 데이터도 공급망이다

컨테이너 이미지만 서명하고 모델 파일은 아무 곳에서나 내려받는다면 공급망 보안은 절반만 한 것이다. LLM 운영에서 모델 가중치는 실행 코드만큼 중요하다. 모델이 바뀌면 애플리케이션의 행동이 바뀐다. 같은 API 서버라도 어떤 모델을 로드하느냐에 따라 개인정보를 더 잘 누출할 수도 있고, 특정 프롬프트에 취약할 수도 있고, 성능과 비용이 크게 달라질 수도 있다.

따라서 모델도 아티팩트로 관리해야 한다.

모델 레지스트리에는 모델 이름, 버전, digest, 학습 데이터 범위, 라이선스, 평가 결과, 승인자, 배포 가능 환경을 기록한다. 프로덕션 추론 서버는 llama-70b:latest 같은 이름이 아니라 승인된 모델 버전과 digest를 사용해야 한다. 가능하다면 모델 파일에도 서명하거나, 최소한 해시를 검증해야 한다.

# 모델 파일 해시 기록 예시
sha256sum model.safetensors > model.safetensors.sha256

# 로딩 전 검증 예시
sha256sum -c model.safetensors.sha256

모델 아티팩트와 컨테이너 이미지의 관계도 추적해야 한다. 어떤 이미지가 어떤 모델을 로드했는지, 어떤 배포가 어떤 프롬프트 템플릿과 어떤 RAG 인덱스를 사용했는지 알아야 장애와 보안 사고를 추적할 수 있다.

metadata:
  labels:
    app: llm-server
    model.acme.io/name: llama-3-70b-instruct
    model.acme.io/version: "2026-05-01"
    model.acme.io/risk-tier: high
  annotations:
    model.acme.io/digest: "sha256:9f1c..."
    model.acme.io/approved-by: "ai-review-board"
    model.acme.io/eval-report: "https://internal.example.com/evals/llama-3-70b-2026-05-01"

이런 라벨과 어노테이션은 단순 장식이 아니다. 비용 귀속, 감사, 장애 대응, 배포 승인, 네트워크 정책, 모니터링 대시보드의 기준이 된다.

프롬프트, 응답, 임베딩은 모두 민감 데이터다

AI 시스템에서 가장 자주 과소평가되는 데이터가 로그다. 웹 서비스에서는 요청 URL, 상태 코드, 지연 시간 정도를 남기는 것이 일반적이었다. 하지만 LLM 서비스에서는 디버깅을 위해 프롬프트와 응답 전체를 남기고 싶은 유혹이 크다. 모델이 왜 이상한 답을 했는지 보려면 원문이 필요하기 때문이다.

문제는 그 원문 안에 민감 정보가 들어간다는 점이다. 사용자는 주민등록번호, 계좌번호, 계약서, 의료 정보, 사내 전략 문서, 소스 코드, API 키를 프롬프트에 붙여넣을 수 있다. 모델 응답도 안전하지 않다. RAG 시스템이 검색한 내부 문서 일부를 응답에 포함할 수 있고, 에이전트가 도구 호출 결과를 그대로 출력할 수도 있다.

임베딩도 안전하다고 단정하면 안 된다. 임베딩은 원문을 그대로 저장하지 않지만, 특정 공격이나 유사도 검색을 통해 원문의 특성을 유추할 수 있다. 벡터 인덱스는 "암호화된 무의미한 숫자 뭉치"가 아니라 검색 가능한 민감 데이터 저장소로 취급해야 한다.

AI 데이터 보호 정책에는 다음 항목이 포함되어야 한다.

  • 프롬프트와 응답 원문을 저장할지 여부

  • 저장한다면 마스킹 범위와 보존 기간

  • 사용자별, 테넌트별 삭제 요청 처리 방식

  • RAG 문서와 임베딩의 접근 권한

  • 벡터 DB 백업의 암호화와 보존 기간

  • 모델 개선용 데이터 재사용 동의 여부

  • 운영자와 개발자의 로그 접근 승인 절차

예를 들어 프로덕션 로그 정책을 다음처럼 잡을 수 있다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: ai-logging-policy
  namespace: ai-prod
data:
  LOG_PROMPT_BODY: "false"
  LOG_RESPONSE_BODY: "false"
  LOG_REDACT_PII: "true"
  LOG_TOKEN_COUNT: "true"
  LOG_MODEL_NAME: "true"
  LOG_TENANT_ID: "true"
  RAW_TRACE_RETENTION_DAYS: "7"
  AGGREGATED_METRIC_RETENTION_DAYS: "180"

실무에서는 원문을 완전히 저장하지 않으면 디버깅이 어려운 경우가 있다. 그럴 때는 샘플링, 테넌트별 옵트인, 짧은 보존 기간, 강한 접근 감사, 필드 단위 마스킹을 조합한다. 예를 들어 장애 조사용으로 7일만 원문을 보관하고, 운영자 접근 시 티켓 번호와 사유를 남기며, 이메일·전화번호·카드번호·API 키 패턴은 저장 전에 제거한다.

테넌트 분리: 검색되면 안 되는 기억을 막아야 한다

RAG와 에이전트 시스템에서 가장 무서운 사고 중 하나는 "다른 고객의 문서가 검색되는 것"이다. 벡터 검색은 편리하지만, 테넌트 필터가 빠지면 순식간에 데이터 유출이 된다. SQL에서 WHERE tenant_id = ?를 빠뜨리는 것과 비슷하지만, 벡터 검색에서는 더 알아차리기 어렵다. 응답이 그럴듯하게 자연어로 나오기 때문이다.

테넌트 분리는 여러 계층에서 반복해야 한다. 애플리케이션 코드에서만 필터링하지 말고, 벡터 DB 인덱스 설계, 네임스페이스, API Gateway, 인증 토큰, 감사 로그에서 모두 테넌트 경계를 유지한다.

# 나쁜 예: tenant 필터 없이 검색
results = vector_store.search(query_embedding, top_k=5)

# 좋은 예: tenant_id와 collection 권한을 함께 확인
results = vector_store.search(
    query_embedding,
    top_k=5,
    filter={
        "tenant_id": current_user.tenant_id,
        "visibility": {"$in": current_user.allowed_scopes},
    },
)

운영 정책으로는 테넌트 필터 없는 검색 API를 아예 만들지 않는 것이 좋다. 내부 라이브러리에서 tenant_id를 필수 인자로 강제하고, 누락되면 컴파일 또는 테스트 단계에서 실패하게 만든다. 또한 검색 결과에는 어떤 문서 ID와 테넌트 ID가 사용되었는지 trace에 남겨야 한다. 나중에 "왜 이 답변이 나왔는가?"를 설명하려면 모델 출력뿐 아니라 검색 경로도 추적해야 한다.

감사 로그와 런타임 탐지: 사고가 났을 때 되감기

보안은 예방만으로 끝나지 않는다. 사고는 언젠가 난다. 중요한 것은 얼마나 빨리 발견하고, 얼마나 정확히 범위를 파악하고, 얼마나 깨끗하게 복구하느냐이다.

쿠버네티스 감사 로그에서는 최소한 다음 이벤트를 추적해야 한다.

  • Secret get/list/watch

  • RoleBinding과 ClusterRoleBinding 변경

  • ServiceAccount 토큰 관련 변경

  • Pod exec, port-forward

  • admission policy 위반

  • 프로덕션 네임스페이스의 Deployment, Job, CronJob 생성·수정·삭제

  • GPU 노드와 RuntimeClass 관련 변경

감사 정책 예시는 다음과 같다.

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets"]

  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: "rbac.authorization.k8s.io"
        resources:
          - "rolebindings"
          - "clusterrolebindings"
          - "roles"
          - "clusterroles"

  - level: Metadata
    verbs: ["create"]
    resources:
      - group: ""
        resources: ["pods/exec", "pods/portforward"]

  - level: Metadata
    namespaces: ["ai-prod"]
    resources:
      - group: "apps"
        resources: ["deployments", "statefulsets"]
      - group: "batch"
        resources: ["jobs", "cronjobs"]

런타임 탐지도 필요하다. 예를 들어 추론 서버 컨테이너에서 갑자기 셸이 실행되거나, 패키지 매니저가 실행되거나, 예상하지 못한 외부 IP로 연결을 시도하면 알림이 떠야 한다. Falco 같은 런타임 탐지 도구는 시스템 호출과 쿠버네티스 메타데이터를 연결해 이런 이상 행동을 감지하는 데 유용하다.

AI 워크로드에 맞춘 탐지 규칙도 생각해 볼 수 있다.

  • vLLM 컨테이너 안에서 /bin/sh 또는 bash 실행

  • 모델 디렉터리에서 대량 파일 읽기 후 외부 네트워크 전송

  • 평소 사용하지 않는 Secret에 대한 접근

  • 에이전트 샌드박스 Pod의 외부 egress 시도

  • 특정 사용자의 비정상적으로 높은 토큰 사용량

  • 짧은 시간 안에 많은 테넌트의 벡터 검색 수행

마지막 두 항목은 쿠버네티스만으로 알 수 없다. 애플리케이션 로그와 AI Gateway, 벡터 DB 감사 로그가 함께 있어야 한다. AI 보안은 클러스터 보안과 애플리케이션 보안의 경계에 있다.

규정 준수: 체크박스가 아니라 설명 가능성

규정 준수는 귀찮은 문서 작업처럼 보이지만, 본질은 단순하다. 문제가 생겼을 때 설명할 수 있어야 한다.

"어떤 데이터가 들어왔는가?"

"어디에 저장되었는가?"

"누가 접근했는가?"

"언제 삭제되는가?"

"어떤 모델이 그 데이터를 처리했는가?"

"모델과 컨테이너는 검증된 것인가?"

금융, 의료, 공공, 교육, B2B SaaS에서는 이 질문들이 계약과 감사의 핵심이 된다. AI 시스템에서는 여기에 "모델 출력이 어떻게 생성되었는가?"라는 질문까지 더해진다. 완벽한 설명은 어려워도, 최소한 어떤 모델 버전, 어떤 프롬프트 템플릿, 어떤 검색 문서, 어떤 도구 호출이 사용되었는지는 추적해야 한다.

운영 정책은 문서와 시스템이 일치해야 한다. 개인정보 보존 기간을 30일이라고 문서에 써놓고 실제 S3 버킷에는 2년치 로그가 남아 있으면 규정 준수가 아니다. "모델 개선에 사용하지 않는다"고 약속했는데 학습 데이터 파이프라인이 프로덕션 로그 버킷을 읽고 있으면 더 큰 문제다.

AI 데이터 분류를 다음처럼 단순하게 시작할 수 있다.

데이터 유형예시기본 정책
모델 아티팩트가중치, LoRA 어댑터, 토크나이저서명 또는 해시 검증, 접근 감사, 버전 고정
사용자 입력프롬프트, 업로드 파일암호화, 짧은 보존 기간, 테넌트 분리
모델 출력응답, 요약, 생성 코드PII 마스킹, 원문 저장 제한
검색 데이터문서 청크, 임베딩, 벡터 인덱스테넌트 필터 강제, 삭제 요청 반영
운영 메타데이터토큰 수, latency, 모델명장기 보관 가능하나 tenant 식별자 보호
시크릿API 키, DB 비밀번호, 토큰외부 시크릿 저장소, 자동 회전, Git 저장 금지

규정 준수의 출발은 거창한 GRC 도구가 아니라 이런 표를 실제 시스템과 맞추는 일이다.

IDP의 골든 패스: 보안을 기본값으로 만든다

보안팀이 "이 YAML은 안 됩니다"라고 계속 말하는 구조는 오래가지 못한다. 데이터 사이언티스트와 ML 엔지니어는 모델을 배포하고 싶고, 플랫폼 팀은 클러스터를 안전하게 유지하고 싶다. 둘의 요구를 동시에 만족시키려면 IDP, 즉 Internal Developer Platform의 골든 패스가 필요하다.

골든 패스는 승인된 방식으로 가장 쉽게 가는 길이다. 사용자가 아무 YAML이나 작성하지 않아도, 포털이나 템플릿을 통해 안전한 기본값이 들어간 배포를 만들 수 있어야 한다.

예를 들어 "LLM 추론 서비스 생성" 템플릿은 다음 정보를 입력받는다.

  • 서비스 이름

  • 모델 이름과 버전

  • GPU 타입과 개수

  • 예상 QPS와 최대 토큰 수

  • 접근 가능한 시크릿 목록

  • 접근 가능한 벡터 인덱스

  • 외부 API egress 필요 여부

  • 로그 원문 저장 여부

  • 테넌트 범위

그리고 플랫폼은 다음 리소스를 자동으로 생성한다.

  • Deployment 또는 KServe InferenceService

  • 전용 ServiceAccount

  • 최소 권한 RoleBinding

  • ExternalSecret 참조

  • ResourceQuota와 LimitRange

  • NetworkPolicy

  • Pod Security 기본값

  • 서명된 이미지만 허용하는 admission label

  • Prometheus ServiceMonitor

  • 비용 귀속 라벨

  • 감사용 어노테이션

간단한 Helm values는 다음처럼 보일 수 있다.

service:
  name: customer-support-llm
  namespace: ai-prod

image:
  repository: ghcr.io/acme/vllm-runtime
  digest: sha256:abc123...
  requireSignature: true

model:
  name: llama-3-70b-instruct
  version: "2026-05-01"
  digest: sha256:9f1c...

security:
  runAsNonRoot: true
  readOnlyRootFilesystem: true
  automountServiceAccountToken: false
  networkPolicy: restricted
  secretStore: azure-keyvault
  allowedEgress:
    - azure-openai
    - pinecone

logging:
  storePromptBody: false
  storeResponseBody: false
  redactPII: true
  retentionDays: 30

cost:
  owner: ai-platform
  product: customer-support
  environment: production

이 values를 기반으로 생성되는 실제 YAML은 복잡할 수 있다. 하지만 사용자는 안전한 선택지 안에서 필요한 값만 입력하면 된다. 이것이 보안과 생산성을 동시에 잡는 방식이다.

좋은 플랫폼은 개발자를 의심하지 않는다. 대신 실수하기 어려운 길을 제공한다.

AI Conformance와 표준화 흐름

2026년의 중요한 변화 중 하나는 AI 워크로드를 위한 쿠버네티스 표준화가 본격화되고 있다는 점이다. Certified Kubernetes AI Conformance 프로그램은 Kubernetes 기반 플랫폼이 AI/ML 워크로드를 안정적으로 실행하기 위해 필요한 역량을 정의하려는 시도다. 이 프로그램은 기본 Kubernetes conformance 위에 AI 워크로드에 필요한 가속기, 네트워킹, 스케줄링, 관찰 가능성, 보안, 운영 지원 역량을 추가로 다룬다4.

이 흐름이 중요한 이유는 단순하다. AI 인프라는 멀티클라우드와 온프레미스 사이를 오갈 가능성이 크다. 오늘은 EKS에서 돌리던 추론 워크로드를 내일은 온프레미스 H100 클러스터로 옮겨야 할 수 있다. 특정 클라우드의 독자 기능에 모든 보안과 네트워킹, 감사 체계를 묶어두면 이동성이 떨어진다.

AI Conformance가 다루는 방향은 이 책에서 계속 강조한 주제와 맞닿아 있다. GPU 같은 가속기 자원을 표준 방식으로 요청하고, 분산 학습이 all-or-nothing 방식으로 스케줄링되며, AI 메트릭 기반 오토스케일링이 가능하고, 가속기 성능과 상태를 표준적으로 관찰할 수 있어야 한다. 앞으로는 여기에 더 강한 보안 요구사항도 붙을 가능성이 높다.

AI Gateway Working Group 역시 같은 맥락이다. 추론 API, RAG, 에이전트 트래픽은 단순한 HTTP 라우팅으로 끝나지 않는다. 토큰 기반 rate limit, 프롬프트와 응답 payload 처리, 외부 AI 서비스 egress 제어, 멀티클러스터 라우팅, 지역 규정 준수 같은 기능이 필요하다. 이런 기능이 표준 API와 커뮤니티 합의를 통해 정리되면, 운영자는 특정 제품에 덜 묶이고 더 일관된 보안 기준을 적용할 수 있다.

표준은 화려하지 않다. 그러나 표준이 생기면 운영은 쉬워진다. "우리 클러스터에서는 되는데 저 클러스터에서는 안 된다"는 말이 줄어든다. AI 인프라가 실험실을 지나 프로덕션으로 가려면, 이런 지루한 표준화가 반드시 필요하다.

운영 체크리스트: 프로덕션 AI 클러스터의 최소 보안 기준

이 장의 내용을 실제 운영 기준으로 압축하면 다음과 같다.

영역최소 기준
이미지취약점 스캔, digest 고정, 서명 검증, 승인 레지스트리 제한
SBOM모든 릴리스 이미지에 SBOM 생성 및 보관, 가능하면 이미지에 첨부
ProvenanceCI/CD 주체, Git 커밋, 빌드 워크플로 추적
Admission서명 없는 이미지, privileged Pod, hostPath, 기본 SA 사용 차단
시크릿외부 시크릿 저장소 사용, Git 평문 금지, etcd 암호화, 접근 감사
RBAC네임스페이스별 최소 권한, 워크로드별 ServiceAccount, cluster-admin 제한
Pod 보안non-root, capability drop, seccomp RuntimeDefault, read-only root filesystem
네트워크default deny, 필요한 ingress/egress만 허용, 외부 AI API 통제
에이전트도구 권한 분리, 코드 실행 샌드박스, egress 제한, 모든 호출 감사
데이터프롬프트·응답·임베딩 민감 데이터 취급, 보존 기간과 삭제 절차 정의
관찰과 감사Secret 접근, RBAC 변경, exec, 배포 변경, AI 요청 메타데이터 추적
IDP승인된 템플릿과 골든 패스로 안전한 기본값 제공

소규모 팀이라면 이 모든 것을 한 번에 구현하기 어렵다. 그렇다면 우선순위를 정하자. 첫 단계는 시크릿을 Git에서 제거하고, 이미지 스캔을 CI에 넣고, 프로덕션 네임스페이스에 기본 Pod Security와 NetworkPolicy를 적용하는 것이다. 두 번째 단계는 이미지 서명과 admission 검증, 외부 시크릿 저장소, 워크로드별 ServiceAccount다. 세 번째 단계는 SBOM 자동화, provenance, AI Gateway, 샌드박스 런타임, 세밀한 감사와 규정 준수 체계다.

중요한 것은 "언젠가 해야지"가 아니라, 오늘 하나씩 플랫폼의 기본값으로 만드는 것이다.

보안은 속도를 늦추는 장치가 아니다

보안이 개발 속도를 늦춘다고 느껴질 때가 있다. 서명 때문에 배포가 막히고, NetworkPolicy 때문에 API 호출이 실패하고, Secret 접근 권한 때문에 Job이 Pending 상태에 빠진다. 하지만 이것은 보안이 나쁜 것이 아니라, 보안이 뒤늦게 붙었기 때문에 생기는 마찰이다.

잘 설계된 보안은 오히려 속도를 높인다. 개발자는 어떤 이미지를 써야 하는지 고민하지 않아도 된다. 승인된 베이스 이미지가 있다. 시크릿을 어디에 넣어야 하는지 묻지 않아도 된다. ExternalSecret 템플릿이 있다. 네트워크 정책을 처음부터 작성하지 않아도 된다. 서비스 유형별 기본 정책이 있다. 감사와 비용 라벨도 자동으로 붙는다.

AI 시대의 쿠버네티스 보안은 "하지 마세요"의 목록이 아니라 "이 길로 가면 안전합니다"라는 플랫폼 경험이어야 한다. 모델과 데이터, 컨테이너 공급망을 함께 보호하는 기준선을 만들고, 그 기준선을 IDP의 골든 패스로 녹여내는 것. 그것이 2026년 프로덕션 AI 클러스터를 운영하는 팀의 중요한 역량이다.

다음 장에서는 이 안전한 기준선 위에서 모델을 어떻게 배포하고 승격할지 살펴본다. CI/CD와 GitOps는 단순히 코드를 배포하는 도구가 아니다. AI 시대에는 모델 버전, 프롬프트 템플릿, 평가 결과, 서명, 정책을 함께 움직이는 운영 시스템이 된다.

참고

1Verify Signed Kubernetes Artifacts

2Good practices for Kubernetes Secrets

3Announcing the AI Gateway Working Group

4Kubernetes AI Conformance

책 목록

AI 시대의 쿠버네티스: LLM 추론과 에이전트를 운영하는 인프라 전략

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기