GKE Sandbox로 워크로드 격리 강화


이 페이지에서는 Pod의 컨테이너가 알 수 없는 또는 신뢰할 수 없는 코드를 실행하거나 노드에서 추가 격리가 필요한 경우 GKE Sandbox를 사용하여 노드의 호스트 커널을 보호하는 방법을 설명합니다.

GKE Sandbox 가용성

GKE 버전 1.27.4-gke.800 이상을 실행하는 Autopilot 클러스터에서 GKE Sandbox를 사용할 수 있습니다. 샌드박스에서 Autopilot 워크로드 배포를 시작하려면 GKE Sandbox 작업으로 건너뛰세요.

신규 또는 기존 GKE Standard 클러스터에서 GKE Sandbox를 사용하려면 클러스터에서 GKE Sandbox를 수동으로 사용 설정해야 합니다.

GPU 워크로드는 GKE Sandbox 버전 1.29.2-gke.11080000 이상에서 프리뷰 버전으로 제공됩니다.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.

새 Standard 클러스터에서 GKE Sandbox 사용 설정

GKE 관리형 시스템 워크로드가 신뢰할 수 없는 샌드박스 워크로드와 별도로 실행되어야 하므로 새 클러스터를 만들 때 생성되는 기본 노드 풀은 GKE Sandbox가 클러스터의 유일한 노드 풀인 경우 이를 사용할 수 없습니다. 클러스터를 만드는 중에 GKE Sandbox를 사용 설정하려면 클러스터에 노드 풀을 최소 하나 이상 추가해야 합니다.

콘솔

클러스터를 보려면 Google Cloud 콘솔에서 Google Kubernetes Engine 메뉴로 이동합니다.

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 만들기를 클릭합니다.

  3. 선택사항이지만 권장됨: 탐색 메뉴의 클러스터에서 기능을 클릭하고 gVisor 메시지가 로깅되도록 다음 체크박스를 선택합니다.

    • Cloud Logging
    • Cloud Monitoring
    • Prometheus용 관리형 서비스
  4. 노드 풀 추가를 클릭합니다.

  5. 탐색 메뉴의 노드 풀에서 새 노드 풀을 펼치고 노드를 클릭합니다.

  6. 노드 풀에 다음 설정을 구성합니다.

    1. 이미지 유형 드롭다운 목록에서 Containerd를 포함한 Container-Optimized OS(cos_containerd)를 선택합니다. GKE Sandbox에 지원되는 유일한 이미지 유형입니다.
    2. 머신 구성에서 시리즈머신 유형을 선택합니다.
    3. 원하는 경우 지원되는 GKE 버전이 실행되면 GPU 유형을 선택합니다. 다음 유형 중 하나여야 합니다.

      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb

      GKE Sandbox의 GPU가 프리뷰 버전으로 제공됩니다.

    4. GKE Sandbox(프리뷰)에서 GPU를 사용하는 경우 latest 드라이버 변형을 선택하거나 설치합니다.

  7. 탐색 메뉴에서 구성하려는 노드 풀 이름 아래에서 보안을 클릭하고 gVisor가 포함된 샌드박스 사용 설정 체크박스를 선택합니다.

  8. 계속해서 필요에 따라 클러스터 및 노드 풀을 구성합니다.

  9. 만들기를 클릭합니다.

gcloud

GKE Sandbox는 기본 노드 풀에 대해 사용 설정할 수 없습니다. 또한 gcloud 명령어를 실행하여 새 클러스터를 만드는 것과 동시에 추가 노드 풀을 만들 수는 없습니다. 대신 평소와 같이 클러스터를 만듭니다. 선택사항이지만 gVisor 메시지가 로깅되도록 Logging 및 Monitoring을 사용 설정하는 것이 좋습니다.

그 다음 gcloud container node-pools create 명령어를 사용하고 -- sandbox 플래그를 type=gvisor로 설정합니다. GKE Sandbox의 노드 이미지 유형은 cos_containerd여야 합니다.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

다음 변수를 바꿉니다.

  • NODE_POOL_NAME: 새 노드 풀의 이름입니다.
  • CLUSTER_NAME: 클러스터 이름입니다.
  • NODE_VERSION: 노드 풀에 사용할 버전입니다.
  • MACHINE_TYPE: 노드에 사용할 머신 유형입니다.

GKE Sandbox로 GPU 노드 풀을 만들려면 다음 명령어를 실행합니다.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --accelerator=type=GPU_TYPE,gpu-driver-version=latest \
  --image-type=cos_containerd \
  --sandbox type=gvisor

다음을 바꿉니다.

기존 Standard 클러스터에서 GKE Sandbox 사용 설정

새 노드 풀을 추가하고 해당 노드 풀에 대해 기능을 사용 설정하여 기존 Standard 클러스터에서 GKE Sandbox를 사용 설정할 수 있습니다.

콘솔

GKE Sandbox가 사용 설정된 새 노드 풀을 만들려면 다음 안내를 따르세요.

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 수정할 클러스터의 이름을 클릭합니다.

  3. 노드 풀 추가를 클릭합니다.

  4. 선택한 대로 노드 풀 세부정보 페이지를 구성합니다.

  5. 탐색 메뉴에서 노드를 클릭하고 다음 설정을 구성합니다.

    1. 이미지 유형 드롭다운 목록에서 Containerd를 포함한 Container-Optimized OS(cos_containerd)를 선택합니다. GKE Sandbox에 지원되는 유일한 이미지 유형입니다.
    2. 머신 구성에서 시리즈머신 유형을 선택합니다.
    3. 원하는 경우 지원되는 GKE 버전이 실행되면 GPU 유형을 선택합니다. 다음 유형 중 하나여야 합니다.

      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb

      GKE Sandbox의 GPU가 프리뷰 버전으로 제공됩니다.

    4. GKE Sandbox(프리뷰)에서 GPU를 사용하는 경우 latest 드라이버 변형을 선택하거나 설치합니다.

  6. 탐색 메뉴에서 보안을 클릭하고 gVisor가 포함된 샌드박스 사용 설정 체크박스를 선택합니다.

  7. 만들기를 클릭합니다.

gcloud

GKE Sandbox가 사용 설정된 새 노드 풀을 만들려면 다음과 같은 명령어를 사용합니다.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

GKE Sandbox의 노드 이미지 유형은 cos_containerd여야 합니다.

GKE Sandbox로 GPU 노드 풀을 만들려면 다음 명령어를 실행합니다.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --accelerator=type=GPU_TYPE,gpu-driver-version=latest \
  --image-type=cos_containerd \
  --sandbox type=gvisor

다음을 바꿉니다.

선택사항: Monitoring 및 Logging 사용 설정

선택사항이지만 클러스터에서 Cloud Logging 및 Cloud Monitoring을 사용 설정하여 gVisor 메시지가 로깅되도록 하는 것이 좋습니다. 이러한 서비스는 기본적으로 새 클러스터에 사용 설정됩니다.

Google Cloud 콘솔을 사용하여 기존 클러스터에서 이러한 기능을 사용 설정할 수 있습니다.

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 수정할 클러스터의 이름을 클릭합니다.

  3. 기능Cloud Logging 필드에서 Cloud Logging 수정을 클릭합니다.

  4. Cloud Logging 사용 설정 체크박스를 선택합니다.

  5. 변경사항 저장을 클릭합니다.

  6. Cloud MonitoringManaged Service for Prometheus 필드에 동일한 단계를 반복하여 이러한 기능을 사용 설정합니다.

Autopilot 및 Standard에서 GKE Sandbox 사용

Autopilot 클러스터와 GKE Sandbox가 사용 설정된 Standard 클러스터에서는 포드 사양에 gvisor RuntimeClass를 지정하여 포드에 대한 샌드박스 환경을 요청합니다.

Autopilot 클러스터의 경우 GKE 버전 1.27.4-gke.800 이상이 실행 중인지 확인합니다.

샌드박스에서 애플리케이션 실행

GKE Sandbox가 사용 설정된 노드에서 배포를 실행하려면 다음 예시와 같이 spec.template.spec.runtimeClassNamegvisor로 설정합니다.

# httpd.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      runtimeClassName: gvisor
      containers:
      - name: httpd
        image: httpd

배포를 만듭니다.

kubectl apply -f httpd.yaml

포드는 GKE Sandbox가 사용 설정된 노드에 배포됩니다. 배포를 확인하려면 포드가 배포된 노드를 찾습니다.

kubectl get pods

출력은 다음과 비슷합니다.

NAME                    READY   STATUS    RESTARTS   AGE
httpd-db5899bc9-dk7lk   1/1     Running   0          24s

출력에서 포드 이름을 찾은 후 RuntimeClass 값을 확인합니다.

kubectl get pods POD_NAME -o jsonpath='{.spec.runtimeClassName}'

출력은 gvisor입니다.

또는 각 포드의 RuntimeClass를 나열하고 gvisor로 설정된 RuntimeClass를 찾을 수 있습니다.

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

출력은 다음과 같습니다.

POD_NAME: gvisor

pod가 샌드박스에서 실행 중인지 확인하는 이 방법은 샌드박스 자체의 데이터에 의존하지 않으므로 신뢰할 수 있습니다. 샌드박스 내에서 보고되는 내용은 결함이 있거나 악성일 수 있으므로 신뢰할 수 없습니다.

GKE Sandbox에서 GPU로 포드 실행

GKE Sandbox에서 GPU 워크로드를 실행하려면 다음 예시와 같이 runtimeClassName: gvisor 필드를 매니페스트에 추가합니다.

  • Standard 모드 GPU 포드의 매니페스트 예시:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-gpu-pod
    spec:
      runtimeClassName: gvisor
      containers:
      - name: my-gpu-container
        image: nvidia/samples:vectoradd-cuda10.2
        resources:
          limits:
          nvidia.com/gpu: 1
    
  • Autopilot 모드 GPU 포드의 매니페스트 예시:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-gpu-pod
    spec:
      runtimeClassName: gvisor
      nodeSelector:
        cloud.google.com/gke-gpu-driver-version: "latest"
        cloud.google.com/compute-class: "Accelerator"
        cloud.google.com/gke-accelerator: nvidia-tesla-t4
      containers:
      - name: my-gpu-container
        image: nvidia/samples:vectoradd-cuda10.2
        resources:
          limits:
            nvidia.com/gpu: 1
    

runtimeClassName: gvisor 필드를 매니페스트에 추가하여 GKE Sandbox에서 버전 및 GPU 유형 요구사항을 충족하는 Autopilot 또는 Standard 모드 GPU 포드를 실행할 수 있습니다. GKE에서 GPU 포드를 실행하는 방법은 다음 리소스를 참조하세요.

샌드박스 처리된 pod와 일반 pod 함께 실행

이 섹션의 단계는 Standard 모드 워크로드에 적용됩니다. Autopilot 가격 책정 모델을 사용하면 노드에 예약된 포드 수를 수동으로 최적화할 필요가 없으므로 Autopilot 모드에서 샌드박스 포드와 함께 일반 포드를 실행할 필요가 없습니다.

노드 풀에서 GKE Sandbox를 사용 설정한 후에는 노드 taint 및 내결함성을 사용하여 샌드박스를 사용하지 않고도 이러한 노드에서 신뢰할 수 있는 애플리케이션을 실행할 수 있습니다. 샌드박스 처리된 pod와 구분하기 위해 이러한 pod를 '일반 pod'라고 합니다.

일반 pod는 샌드박스 처리된 pod와 마찬가지로 다른 Google Cloud 서비스나 클러스터 메타데이터에 액세스할 수 없습니다. 이러한 액세스 차단은 노드 구성의 일부입니다. 일반 포드 또는 샌드박스 처리된 포드에서 Google Cloud 서비스에 액세스해야 하는 경우 GKE용 워크로드 아이덴티티 제휴를 사용합니다.

GKE Sandbox는 샌드박스 처리된 pod를 실행할 수 있는 노드에 다음 라벨과 taint를 추가합니다.

labels:
  sandbox.gke.io/runtime: gvisor
taints:
- effect: NoSchedule
  key: sandbox.gke.io/runtime
  value: gvisor

포드 매니페스트의 노드 어피니티 및 내결함성 설정 외에, GKE Sandbox는 다음 노드 어피니티 및 내결함성을 RuntimeClassgvisor로 설정된 모든 포드에 적용합니다.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: sandbox.gke.io/runtime
          operator: In
          values:
          - gvisor
tolerations:
  - effect: NoSchedule
    key: sandbox.gke.io/runtime
    operator: Equal
    value: gvisor

GKE Sandbox가 사용 설정된 노드에서 일반 포드를 예약하려면 앞에서 설명한 노드 어피니티 및 톨러레이션(toleration)을 포드 매니페스트에 수동으로 적용합니다.

  • GKE Sandbox가 사용 설정된 노드에서 포드를 실행할 수 있는 경우 내결함성을 추가합니다.
  • GKE Sandbox가 사용 설정된 노드에서 포드를 실행해야 하는 경우 노드 어피니티와 내결함성을 모두 추가합니다.

예를 들어 다음 매니페스트는 runtimeClass를 제거하고 앞에서 설명한 taint와 톨러레이션(toleration)을 모두 추가하여 샌드박스에서 애플리케이션 실행에 사용된 매니페스트를 수정하여 샌드박스 처리된 포드가 있는 노드에서 일반 포드로 실행됩니다.

# httpd-no-sandbox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-no-sandbox
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: sandbox.gke.io/runtime
                operator: In
                values:
                - gvisor
      tolerations:
        - effect: NoSchedule
          key: sandbox.gke.io/runtime
          operator: Equal
          value: gvisor

먼저 샌드박스에서 배포가 실행되고 있지 않은지 확인합니다.

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

출력은 다음과 비슷합니다.

httpd-db5899bc9-dk7lk: gvisor
httpd-no-sandbox-5bf87996c6-cfmmd:

runtimeClass가 gvisor이므로 이전에 생성된 httpd 배포는 샌드박스에서 실행 중입니다. httpd-no-sandbox 배포에는 runtimeClass의 값이 없으므로 샌드박스에서 실행 중이 아닙니다.

다음 명령어를 실행하여 GKE Sandbox가 있는 노드에서 샌드박스 처리되지 않은 배포가 실행 중인지 확인합니다.

kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'

노드 풀의 이름은 nodeName 값에 삽입됩니다. 포드가 GKE Sandbox가 사용 설정된 노드 풀의 노드에서 실행 중인지 확인합니다.

메타데이터 보호 확인

샌드박스 처리된 pod를 실행할 수 있는 노드에서 메타데이터가 보호된다는 어설션을 검증하려면 테스트를 실행합니다.

  1. kubectl apply -f를 사용하여 다음 매니페스트에서 샌드박스 처리된 배포를 만듭니다. 여기서는 curl 명령어가 포함된 fedora 이미지를 사용합니다. pod는 /bin/sleep 명령어를 실행하여 배포가 10000초 동안 실행되는지 확인합니다.

    # sandbox-metadata-test.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: fedora
      labels:
        app: fedora
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: fedora
      template:
        metadata:
          labels:
            app: fedora
        spec:
          runtimeClassName: gvisor
          containers:
          - name: fedora
            image: fedora
            command: ["/bin/sleep","10000"]
    
  2. kubectl get pods를 사용하여 pod 이름을 가져온 다음 kubectl exec를 사용하여 대화형으로 pod에 연결합니다.

    kubectl exec -it POD_NAME /bin/sh
    

    /bin/sh 세션에서 pod에서 실행 중인 컨테이너에 연결됩니다.

  3. 대화형 세션 내에서 다음과 같이 클러스터 메타데이터를 반환하는 URL에 액세스를 시도합니다.

    curl -s "http://169.254.169.254/computeMetadata/v1/instance/attributes/kube-env" -H "Metadata-Flavor: Google"
    

    아무런 표시 없이 패킷이 누락되므로 명령어 실행이 멈추고 결국 타임아웃됩니다.

  4. Ctrl+C를 눌러 curl 명령어를 종료하고 exit를 입력하여 pod 연결을 해제합니다.

  5. YAML 매니페스트에서 RuntimeClass 줄을 삭제하고 kubectl apply -f FILENAME을 사용하여 pod를 다시 배포합니다. 샌드박스 처리된 pod가 종료되고 GKE Sandbox가 없는 노드에서 다시 생성됩니다.

  6. 새 pod 이름을 가져오고 kubectl exec를 사용하여 연결하고 curl 명령어를 다시 실행합니다. 이번에는 결과가 반환됩니다. 이 예시 출력은 잘립니다.

    ALLOCATE_NODE_CIDRS: "true"
    API_SERVER_TEST_LOG_LEVEL: --v=3
    AUTOSCALER_ENV_VARS: kube_reserved=cpu=60m,memory=960Mi,ephemeral-storage=41Gi;...
    ...
    

    exit를 입력하여 pod 연결을 해제합니다.

  7. 배포를 삭제합니다.

    kubectl delete deployment fedora
    

GKE Sandbox 사용 중지

GKE Autopilot 클러스터 또는 GKE Standard 노드 풀에서는 GKE Sandbox를 중지할 수 없습니다. GKE Sandbox 사용을 중지하려면 노드 풀을 삭제합니다.

다음 단계