워크로드를 전용 노드 풀에서 격리


이 페이지에서는 Google Kubernetes Engine(GKE)에 권한이 있는 GKE 관리형이 아닌 별도의 전용 노드 풀에 워크로드를 예약하도록 하여 클러스터에서 권한 에스컬레이션 공격의 위험을 줄이는 방법을 보여줍니다. 이 페이지는 노드 자동 프로비저닝이 없는 표준 클러스터에 적용됩니다. Autopilot 클러스터와 노드 자동 프로비저닝이 사용 설정된 표준 클러스터의 워크로드를 구분하려면 GKE에서 워크로드 분리 구성을 참조하세요.

개요

GKE 클러스터는 권한이 있는 GKE 관리 워크로드를 사용하여 측정항목 수집과 같은 특정 클러스터 기능을 사용 설정합니다. 이러한 워크로드에는 클러스터에서 올바르게 실행될 수 있는 특수한 권한이 부여됩니다.

노드에 배포하는 워크로드는 악의적인 항목에 의해 손상될 가능성이 있습니다. 권한이 있는 GKE 관리 워크로드와 함께 이러한 워크로드를 실행하면 손상된 컨테이너를 침입한 공격자가 노드에서 권한이 있는 워크로드의 사용자 인증 정보를 사용하여 클러스터의 권한을 에스컬레이션할 수 있습니다.

컨테이너 소그룹 방지

기본 방어는 애플리케이션이어야 합니다. GKE에는 클러스터 및 포드를 강화하는 데 사용할 수 있는 여러 기능이 있습니다. 대부분의 경우 GKE Sandbox를 사용하여 워크로드를 격리하는 것이 가장 좋습니다. GKE Sandbox는 gVisor 오픈소스 프로젝트를 기반으로 하며 사용자 공간에 Linux 커널 API를 구현합니다. 각 포드는 호스트 커널의 권한이 있는 시스템 호출에 대한 액세스를 방지하기 위해 애플리케이션을 샌드박스 처리하는 전용 커널에서 실행됩니다. GKE Sandbox에서 실행되는 워크로드는 다른 워크로드와 격리된 별도의 노드에서 자동으로 예약됩니다.

클러스터 보안 강화의 추천도 따라야 합니다.

권한 에스컬레이션 공격 방지

GKE Sandbox를 사용할 수 없고 다른 강화 조치 외에 추가 격리 레이어가 필요한 경우 노드 taint노드 어피니티를 사용하여 전용 노드 풀에서 워크로드를 예약할 수 있습니다. 노드 taint는 GKE에 해당 노드에서 해당 톨러레이션(toleration)(예: GKE 관리 워크로드) 없이 워크로드를 예약하지 않도록 지시합니다. 자체 워크로드의 노드 어피니티는 전용 노드에서 포드를 예약하도록 GKE에 지시합니다.

노드 격리 제한사항

  • 공격자는 여전히 손상된 노드에서 서비스 거부 (DoS) 공격을 시작할 수 있습니다.
  • 손상된 노드는 클러스터의 모든 포드 및 네임스페이스를 포함하여 여러 리소스를 계속 읽을 수 있습니다.
  • 손상된 노드는 해당 노드에서 실행되는 모든 포드에서 사용되는 보안 비밀과 사용자 인증 정보에 액세스할 수 있습니다.
  • 별도의 노드 풀을 사용하여 워크로드를 격리하면 비용 효율성, 자동 확장, 리소스 사용률에 영향을 미칠 수 있습니다.
  • 손상된 노드는 계속해서 이그레스 네트워크 정책을 우회할 수 있습니다.
  • 일부 GKE 관리 워크로드는 클러스터의 모든 노드에서 실행되어야 하며 모든 taint를 허용하도록 구성됩니다.
  • 권한이 승격되고 taint를 허용할 수 있는 DaemonSet을 배포하는 경우, 해당 포드는 손상된 노드에서 권한 에스컬레이션을 위한 경로가 될 수 있습니다.

노드 격리 작동 방식

워크로드의 노드 격리를 구현하려면 다음을 수행해야 합니다.

  1. 워크로드의 노드 풀을 taint하고 라벨을 지정합니다.
  2. 해당 톨러레이션(toleration) 및 노드 어피니티 규칙으로 워크로드를 업데이트합니다.

이 가이드는 클러스터에서 노드 풀 한 개로 시작한다고 가정합니다. 노드 taint 외에 노드 어피니티를 반드시 사용할 필요는 없지만 예약을 보다 효율적으로 제어할 수 있으므로 이를 사용하는 것이 좋습니다.

시작하기 전에

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

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.
  • 전용 노드 풀에 사용할 노드 taint와 노드 라벨의 특정 이름을 선택하세요. 이 예시에서는 workloadType=untrusted를 사용합니다.

워크로드의 노드 풀 taint 및 라벨 지정

워크로드의 새 노드 풀을 만들고 노드 taint 및 노드 라벨을 적용합니다. 노드 풀 수준에서 taint 또는 라벨을 적용하면 자동 확장으로 생성된 노드와 같이 모든 새 노드는 지정된 taint 및 라벨을 자동으로 가져옵니다.

또한 기존 노드 풀에 노드 taint와 노드 라벨을 추가할 수 있습니다. NoExecute 효과를 사용하면 GKE는 새 taint에 대한 내결함성이 없는 노드에서 실행 중인 모든 포드를 삭제합니다.

새 노드 풀에 taint와 라벨을 추가하려면 다음 명령어를 실행합니다.

gcloud container node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

다음을 바꿉니다.

  • POOL_NAME: 워크로드의 새 노드 풀 이름입니다.
  • CLUSTER_NAME: GKE 클러스터의 이름입니다.
  • TAINT_KEY=TAINT_VALUE: TAINT_EFFECT 예약과 연결된 키 값 쌍입니다. 예를 들면 workloadType=untrusted입니다.
  • TAINT_EFFECT: 효과 값 중 하나입니다(NoSchedule, PreferNoSchedule, NoExecute). NoExecuteNoSchedule보다 더 나은 제거를 보장합니다.
  • LABEL_KEY=LABEL_VALUE: 워크로드 매니페스트에 지정한 선택기에 해당하는 노드 라벨의 키-값 쌍입니다.

워크로드에 톨러레이션(toleration) 및 노드 어피니티 규칙 추가

전용 노드 풀을 taint한 후에는 추가한 taint에 대한 톨러레이션(toleration)이 없으면 워크로드가 이를 예약할 수 없습니다. 워크로드 사양에 톨러레이션(toleration)을 추가하여 해당 포드가 taint된 노드 풀에서 예약할 수 있도록 합니다.

전용 노드 풀에 라벨을 지정한 경우, 노드 어피니티 규칙을 추가하여 해당 노드 풀에서만 워크로드를 예약하도록 GKE에 지시할 수도 있습니다.

다음 예시에서는 workloadType=untrusted:NoExecute taint에 대한 톨러레이션(toleration)과 workloadType=untrusted 노드 라벨에 대한 노드 어피니티 규칙을 추가합니다.

kind: Deployment
apiVersion: apps/v1
metadata:
  name: my-app
  namespace: default
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      tolerations:
      - key: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

다음을 바꿉니다.

  • TAINT_KEY: 전용 노드 풀에 적용한 taint 키입니다.
  • TAINT_VALUE: 전용 노드 풀에 적용한 taint 값입니다.
  • LABEL_KEY: 전용 노드 풀에 적용한 노드 라벨 키입니다.
  • LABEL_VALUE: 전용 노드 풀에 적용한 노드 라벨 값입니다.

kubectl apply로 배포를 업데이트하면 GKE가 영향을 받는 포드를 다시 만듭니다. 노드 어피니티 규칙은 생성된 전용 노드 풀로 포드를 강제 적용합니다. 톨러레이션(toleration)을 통해 이러한 포드만 노드에 배치될 수 있습니다.

분리 작동 확인

예약이 올바르게 작동하는지 확인하려면 다음 명령어를 실행하고 워크로드가 전용 노드 풀에 있는지 확인합니다.

kubectl get pods -o=wide

추천 및 권장사항

노드 격리를 설정한 후에는 다음을 수행하는 것이 좋습니다.

  • components.gke.io/gke-managed-components taint를 추가하여 특정 노드 풀을 GKE 관리 워크로드로 제한합니다. 이 taint를 추가하면 자체 Pod가 이러한 노드에서 예약되지 않도록 하여 격리가 향상됩니다.
  • 새 노드 풀을 만들 때 노드 풀에 자체 taint를 추가하여 대부분의 GKE 관리 워크로드가 이러한 노드에서 실행되지 않도록 합니다.
  • 타사 도구를 설치할 때와 같이 새 워크로드를 클러스터에 배포할 때마다 포드에 필요한 권한을 감사합니다. 가능하면 공유 노드에 승격된 권한을 사용하는 워크로드를 배포하지 마세요.

다음 단계