클러스터 보안 강화


Kubernetes의 개발 속도로 인해 종종 새로운 보안 기능을 사용하게 됩니다. 이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터를 강화하기 위한 최신 가이드를 구현하는 방법을 안내합니다.

이 가이드에서는 클러스터 생성 시 고객 조치가 필요한 고가치 보안 완화 방법을 우선합니다. 중요도가 낮은 기능, 기본 설정에 따른 보안, 생성 후 사용 설정 가능한 기능은 이 문서의 뒷부분에서 설명합니다. 보안 항목에 대한 일반적인 개요는 보안 개요를 읽어보세요.

Security Health Analytics을 사용하여 이러한 권장사항 및 기타 일반적인 구성 오류를 자동으로 확인할 수 있습니다.

아래의 권장사항이 CIS GKE 벤치마크 권장사항과 관련이 있는 경우에 지정됩니다.

지체 없는 GKE 인프라 업그레이드

CIS GKE 벤치마크 권장사항: 6.5.3. 노드 자동 업그레이드가 GKE 노드에 사용 설정되어 있는지 확인

보안을 향상시킬 수 있는 가장 간단한 방법 중 하나는 Kubernetes 버전을 최신 상태로 유지하는 것입니다. Kubernetes에는 새로운 보안 기능과 보안 패치가 자주 제공됩니다.

보안 패치에 대한 자세한 내용은 GKE 보안 게시판을 참조하세요.

Google Kubernetes Engine에서는 제어 영역이 자동으로 패치되고 업그레이드됩니다. 노드 자동 업그레이드도 클러스터의 노드를 자동으로 업그레이드합니다.

노드 자동 업그레이드를 사용 중지하는 경우 자체 일정에 따라 월 단위로 업그레이드하는 것이 좋습니다. 이전 클러스터는 노드 자동 업그레이드를 선택하고 중요한 패치와 관련된 GKE 보안 게시판을 따라야 합니다.

자세한 내용은 노드 자동 업그레이드를 참조하세요.

제어 영역 및 노드에 대한 네트워크 액세스 제한

CIS GKE 벤치마크 권장사항: 6.6.2. VPC 기반 클러스터 선호, 6.6.3. 마스터 승인 네트워크가 사용 설정되어 있는지 확인, 6.6.4. 비공개 엔드포인트는 사용 설정되고 공개 액세스는 중지된 상태로 클러스터가 생성되었는지 학인, 6.6.5. 클러스터가 비공개 노드로 생성되었는지 확인

클러스터 제어 영역과 노드의 인터넷 노출을 제한해야 합니다. 이는 클러스터 생성 시점에만 설정할 수 있습니다.

기본적으로 GKE 클러스터 제어 영역과 노드에는 모든 IP 주소에서 액세스할 수 있는 인터넷 라우팅 가능 주소가 있습니다.

GKE 클러스터 제어 영역의 경우 비공개 클러스터 만들기를 참조하세요. 네트워크 수준 보호를 제공할 수 있는 세 가지 유형의 비공개 클러스터가 있습니다.

  • 공개 엔드포인트 액세스 사용 안함: 제어 영역 및 노드에 대한 모든 인터넷 액세스를 차단하는 가장 안전한 옵션입니다. Cloud InterconnectCloud VPN을 사용하여 온프레미스 네트워크를 Google Cloud에 연결하도록 구성한 경우에 적합합니다. 이러한 기술은 회사 네트워크를 클라우드 VPC에 효과적으로 연결합니다.
  • 공개 엔드포인트 액세스 사용 설정, 승인된 네트워크 사용 설정(권장사항): 이 옵션은 정의된 소스 IP 주소에서 제어 영역에 대한 제한된 액세스를 제공합니다. 기존 VPN 인프라가 없거나 회사 VPN, Cloud Interconnect 또는 Cloud VPN 대신 공개 인터넷을 통해 연결된 원격 사용자나 지사가 있는 경우에 적합합니다.
  • 공개 엔드포인트 액세스 사용 설정, 승인된 네트워크 사용 안 함: 인터넷에 있는 모든 사용자가 제어 영역에 네트워크 연결을 할 수 있도록 허용하는 기본 옵션입니다.

노드에 직접 인터넷 액세스를 중지하려면 클러스터를 만들 때 gcloud CLIoption --enable-private-nodes를 지정합니다.

이는 GKE가 내부 IP 주소로 노드를 프로비저닝한다는 것을 의미합니다. 즉, 공개 인터넷을 통해 노드에 직접 연결할 수 없습니다.

클러스터는 최소한 승인된 네트워크 및 비공개 노드를 사용하는 것이 좋습니다. 이렇게 하면 다음 항목을 통해 제어 영역에 연결할 수 있습니다.

  • 승인된 네트워크에서 허용되는 CIDR
  • 클러스터 VPC 내의 노드
  • 제어 영역을 관리하는 Google의 내부 프로덕션 작업

클러스터 생성 시 다음 gcloud 플래그에 해당합니다.

  • --enable-ip-alias
  • --enable-private-nodes
  • --enable-master-authorized-networks

최소 권한 방화벽 규칙 사용

방화벽 규칙에 최소 권한의 원칙을 사용하여 의도하지 않은 액세스 위험 최소화

GKE는 시스템 기능을 사용 설정하고 올바른 보안 방침을 적용하기 위해 기본 VPC 방화벽 규칙을 만듭니다. 자동으로 생성되는 방화벽 규칙의 전체 목록은 자동으로 생성된 방화벽 규칙을 참조하세요.

GKE는 우선순위가 1,000인 기본 방화벽 규칙을 만듭니다. 디버깅용 allow-all 방화벽 규칙과 같이 우선순위가 더 높은 허용 방화벽 규칙을 만들면 클러스터가 의도치 않은 액세스 위험에 노출될 수 있습니다.

그룹 인증

CIS GKE 벤치마크 권장사항: 6.8.3. RBAC용 Google 그룹스로 Kubernetes RBAC 사용자 관리

그룹을 사용하여 사용자를 관리해야 합니다. 그룹을 사용하면 ID 관리 시스템과 ID 관리자를 사용하여 ID를 제어할 수 있습니다. 그룹 구성원을 조정하면 그룹에 사용자를 추가하거나 제거할 때마다 RBAC 구성을 업데이트할 필요가 없습니다.

Google 그룹스를 사용하여 사용자 권한을 관리하려면 클러스터에서 RBAC용 Google 그룹스를 사용 설정해야 합니다. 이를 통해 동일한 권한을 가진 사용자를 손쉽게 관리하고 ID 관리자가 사용자를 중앙에서 일관성 있게 관리하도록 허용할 수 있습니다.

RBAC용 Google 그룹스를 사용 설정하는 방법은 RBAC용 Google 그룹스를 참조하세요.

컨테이너 노드 선택사항

다음 섹션에서는 보안 노드 구성 선택사항을 설명합니다.

보안 GKE 노드 사용 설정

CIS GKE 벤치마크 권장사항: 6.5.5. 보안 GKE 노드가 사용 설정되어 있는지 확인

보안 GKE 노드는 강력하고 검증 가능한 노드 ID와 무결성을 제공하여 GKE 노드 보안을 강화하고 모든 GKE 클러스터에서 사용 설정되어야 합니다.

클러스터 생성 또는 업데이트 시 보안 GKE 노드를 사용 설정할 수 있습니다. 보안 GKE 노드를 보안 부팅과 함께 사용해야 합니다. 타사의 서명되지 않은 커널 모듈이 필요한 경우 보안 부팅을 사용하면 안 됩니다. 보안 GKE 노드를 사용 설정하는 방법 및 보안 GKE 노드를 사용하여 보안 부팅을 사용 설정하는 방법에 대한 안내는 보안 GKE 노드 사용을 참조하세요.

containerd 런타임에서 강화 노드 이미지 선택

Containerd(cos_containerd)를 포함한 Container-Optimized OS 이미지는 Kubernetes와 직접 통합된 containerd를 메인 컨테이너 런타임으로 하는 Container-Optimized OS 이미지의 한 변형입니다.

containerd는 Docker의 핵심 런타임 구성요소이며 Kubernetes Container 런타임 인터페이스(CRI)의 핵심 컨테이너 기능을 제공하도록 설계되었습니다. 전체 Docker 데몬보다 훨씬 덜 복잡하므로 공격 표면이 적습니다.

클러스터에서 cos_containerd 이미지를 사용하려면 컨테이너화된 이미지를 참조하세요.

cos_containerd 이미지는 컨테이너를 실행하기 위해 특별히 커스텀으로 빌드, 최적화, 강화된 GKE의 선호 이미지입니다.

GKE용 워크로드 아이덴티티 제휴 사용 설정

CIS GKE 벤치마크 권장사항: 6.2.2. 전용 Google Cloud 서비스 계정 및 워크로드 아이덴티티 사용 선호

GKE용 워크로드 아이덴티티 제휴는 Google Cloud API에 인증하는 데 권장되는 방법입니다.

GKE용 워크로드 아이덴티티 제휴는 메타데이터 숨김을 사용해야 할 필요성을 대체하며, 따라서 두 접근 방법은 상호 호환되지 않습니다. 메타데이터 숨김으로 보호되는 민감한 메타데이터는 GKE용 워크로드 아이덴티티 제휴로도 보호됩니다.

GKE Sandbox로 워크로드 격리 강화

CIS GKE 벤치마크 권장사항: 6.10.4. 특히 신뢰할 수 없는 워크로드의 격리 강화를 위해 GKE Sandbox 고려

GKE Sandbox는 악성 코드가 클러스터 노드의 호스트 커널에 영향을 미치지 않도록 차단하는 보안 레이어를 추가합니다.

샌드박스 환경에서 컨테이너를 실행하면 대부분의 컨테이너 이스케이프 공격(로컬 권한 에스컬레이션 공격이라고도 함)을 완화할 수 있습니다. 이전의 컨테이너 이스케이프 취약점에 대해서는 보안 게시판을 참조하세요. 이 유형의 공격은 공격자가 컨테이너의 호스트 VM에 액세스하여 동일한 VM의 다른 컨테이너에 액세스할 수 있도록 허용합니다. GKE Sandbox와 같은 샌드박스는 이러한 공격의 영향을 제한하는 데 도움이 될 수 있습니다.

다음과 같은 상황에서 워크로드 샌드박스 사용을 고려해야 합니다.

  • 워크로드가 신뢰할 수 없는 코드를 실행합니다.
  • 공격자가 워크로드의 컨테이너에 침투하여 발생하는 영향을 제한해야 합니다.

GKE Sandbox로 워크로드 격리 강화에서 GKE Sandbox를 사용하는 방법을 알아보세요.

보안 게시판 알림 사용 설정

클러스터와 관련된 보안 게시판을 사용할 수 있으면 GKE가 해당 이벤트에 대한 알림을 사용자가 구성하는 Pub/Sub 주제에 대한 메시지로 게시합니다. Pub/Sub 구독에서 이러한 알림을 수신하고 타사 서비스와 통합하고 수신하려는 알림 유형을 필터링할 수 있습니다.

GKE 클러스터 알림을 사용한 보안 게시판 수신에 대한 자세한 내용은 클러스터 알림을 참조하세요.

권한

IAM 서비스 계정 최소 권한 사용

CIS GKE 벤치마크 권장사항: 6.2.1. Compute Engine 기본 서비스 계정을 사용하여 GKE 클러스터 실행하지 않는 것을 선호

각 GKE 노드에는 Identity and Access Management(IAM) 서비스 계정이 연결되어 있습니다. 기본적으로 노드에는 Compute Engine 기본 서비스 계정이 제공됩니다. Google Cloud 콘솔의 IAM 섹션으로 이동하면 이 계정을 찾을 수 있습니다. 이 계정은 기본적으로 넓은 액세스 범위를 포함하기 때문에, 다양한 애플리케이션에 유용하지만, Kubernetes Engine 클러스터를 실행하는 데 필요한 것보다 많은 권한을 포함합니다. Compute Engine 기본 서비스 계정 대신 사용할 노드에 대해 최소 권한이 부여된 서비스 계정을 만들고 사용해야 합니다.

GKE용 워크로드 아이덴티티 제휴를 출시하면서 노드 서비스 계정에 더 제한된 사용 사례를 제안하고 있습니다. 로깅, 모니터링, 유사한 작업을 담당하는 시스템 데몬이 노드 서비스 계정을 사용할 것으로 예상됩니다. 대신 포드 내 워크로드는 GKE용 워크로드 아이덴티티 제휴로 ID를 프로비저닝해야 합니다.

GKE에는 최소한 monitoring.viewer, monitoring.metricWriter, logging.logWriter, stackdriver.resourceMetadata.writer, autoscaling.metricsWriter 역할이 포함된 서비스 계정이 필요합니다. 모니터링 역할로깅 역할을 자세히 알아보세요.

다음 명령어는 GKE를 작동하는 데 필요한 최소 권한으로 IAM 서비스 계정을 만듭니다. 서비스 계정을 다른 프로젝트의 리소스에도 사용할 수 있습니다. 안내는 프로젝트 간 서비스 계정 가장 사용 설정을 참조하세요.

gcloud

gcloud iam service-accounts create SA_NAME \
    --display-name=DISPLAY_NAME

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role roles/logging.logWriter

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role roles/monitoring.metricWriter

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role roles/monitoring.viewer

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role roles/stackdriver.resourceMetadata.writer

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
    --role roles/autoscaling.metricsWriter

다음을 바꿉니다.

  • SA_NAME: 새 서비스 계정의 이름으로 바꿉니다.
  • DISPLAY_NAME: 계정을 쉽게 식별할 수 있도록 새 서비스 계정의 표시 이름으로 바꿉니다.
  • PROJECT_ID: 새 서비스 계정을 만들 프로젝트의 프로젝트 ID로 바꿉니다.

구성 커넥터

참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치하세요.

  1. 서비스 계정을 만들려면 다음 리소스를 service-account.yaml로 다운로드합니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMServiceAccount
    metadata:
      name: [SA_NAME]
    spec:
      displayName: [DISPLAY_NAME]

    다음을 바꿉니다.

    • SA_NAME: 새 서비스 계정의 이름으로 바꿉니다.
    • DISPLAY_NAME: 계정을 쉽게 식별할 수 있도록 새 서비스 계정의 표시 이름으로 바꿉니다.

    그런 후 다음을 실행합니다.

    kubectl apply -f service-account.yaml

  2. logging.logWriter 역할을 서비스 계정에 적용합니다. 다음 리소스를 policy-logging.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-logging
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/logging.logWriter
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-logging.yaml

  3. monitoring.metricWriter 역할을 적용합니다. 다음 리소스를 policy-metrics-writer.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-metrics-writer
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/monitoring.metricWriter
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-metrics-writer.yaml

  4. monitoring.viewer 역할을 적용합니다. 다음 리소스를 policy-monitoring.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-monitoring
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/monitoring.viewer
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-monitoring.yaml

  5. autoscaling.metricsWriter 역할을 적용합니다. 다음 리소스를 policy-autoscaling-metrics-writer.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-autoscaling-metrics-writer
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/autoscaling.metricsWriter
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-autoscaling-metrics-writer.yaml

비공개 이미지 저장소에 대한 액세스 권한 부여

Artifact Registry에서 비공개 이미지를 사용하려면 서비스 계정에 Artifact Registry 리더 역할(roles/artifactregistry.reader)을 부여합니다.

gcloud

gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
    --member=serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --role=roles/artifactregistry.reader

REPOSITORY_NAME을 Artifact Registry 저장소의 이름으로 바꿉니다.

구성 커넥터

참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치하세요.

  1. 다음 매니페스트를 policy-artifact-registry-reader.yaml로 저장합니다.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-artifact-registry-reader
    spec:
      member: serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com
      role: roles/artifactregistry.reader
      resourceRef:
        apiVersion: artifactregistry.cnrm.cloud.google.com/v1beta1
        kind: ArtifactRegistryRepository
        name: REPOSITORY_NAME

    다음을 바꿉니다.

    • SA_NAME: IAM 서비스 계정의 이름입니다.
    • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
    • REPOSITORY_NAME: Artifact Registry 저장소의 이름입니다.
  2. Artifact Registry 리더 역할을 서비스 계정에 부여합니다.

    kubectl apply -f policy-artifact-registry-reader.yaml
    

또한 Container Registry에서 비공개 이미지를 사용할 때는 이에 대한 액세스 권한을 부여해야 합니다.

gsutil

gsutil iam ch \
  serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com:objectViewer \
  gs://BUCKET_NAME

이미지를 저장하는 버킷 이름 BUCKET_NAME은 다음과 같은 형식입니다.

  • artifacts.PROJECT_ID.appspot.com - 호스트 gcr.io의 레지스트리로 내보낸 이미지의 경우
  • STORAGE_REGION.artifacts.PROJECT_ID.appspot.com

다음을 바꿉니다.

  • PROJECT_ID는 Google Cloud 콘솔 프로젝트 ID입니다.
  • STORAGE_REGION은 스토리지 버킷의 위치입니다.
    • us - us.gcr.io 호스트의 레지스트리
    • eu - eu.gcr.io 호스트의 레지스트리
    • asia - asia.gcr.io 호스트의 레지스트리

명령어에 대한 자세한 내용은 gsutil iam 문서를 참조하세요.

구성 커넥터

참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치하세요.

서비스 계정에 storage.objectViewer 역할을 적용합니다. 다음 리소스를 policy-object-viewer.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-object-viewer
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/storage.objectViewer
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-object-viewer.yaml

다른 사용자가 이 서비스 계정으로 새 클러스터 또는 노드 풀을 만들 수 있게 하려면 해당 사용자에게 이 서비스 계정의 서비스 계정 사용자 역할을 부여해야 합니다.

gcloud

gcloud iam service-accounts add-iam-policy-binding \
    SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --member=user:USER \
    --role=roles/iam.serviceAccountUser

구성 커넥터

참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치하세요.

서비스 계정에 iam.serviceAccountUser 역할을 적용합니다. 다음 리소스를 policy-service-account-user.yaml로 다운로드합니다. [SA_NAME][PROJECT_ID]를 자체 정보로 바꿉니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-service-account-user
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-service-account-user.yaml

기존 표준 클러스터의 경우 이제 이 새로운 서비스 계정으로 새 노드 풀을 만들 수 있습니다. Autopilot 클러스터의 경우 서비스 계정으로 새 클러스터를 만들어야 합니다. 자세한 내용은 Autopilot 클러스터 만들기를 참조하세요.

  • 새 서비스 계정을 사용하는 노드 풀을 만듭니다.

    gcloud container node-pools create NODE_POOL_NAME \
    --service-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
    --cluster=CLUSTER_NAME

GKE 클러스터에 다른 Google Cloud 서비스에 대한 액세스 권한이 필요하면 GKE용 워크로드 아이덴티티 제휴를 사용해야 합니다.

클러스터 API 검색에 대한 액세스 제한

기본적으로 Kubernetes는 CustomResourceDefinitions의 항목을 포함한 클러스터의 API 정보에 대한 광범위한 액세스 권한을 부여하는 방임적인 discovery ClusterRoleBindings 집합으로 클러스터를 부트스트랩합니다.

사용자는 system:discoverysystem:basic-user ClusterRoleBindings의 대상에 포함된 system:authenticated 그룹이 인증된 사용자(Google 계정이 있는 사용자 포함)를 포함할 수 있으며 GKE의 클러스터에 대한 유의미한 수준의 보안을 나타내지 않는다는 점을 알아야 합니다. 자세한 내용은 기본 역할 및 그룹 사용 안함을 참조하세요.

클러스터의 탐색 API를 강화하고자 하는 경우 다음 중 하나 이상을 고려해야 합니다.

이러한 옵션 중 하나라도 GKE 사용 사례에 적합하지 않으면 모든 API 검색 정보(CustomResources의 스키마, APIService 정의, 확장 API 서버에서 호스팅하는 검색 정보)를 공개로 취급해야 합니다.

이러한 옵션은 모두 Cloud Run 및 Cloud Functions에서 API 서버 IP 주소에 대한 액세스를 허용합니다. 이 액세스는 삭제되므로 이러한 서비스를 사용하여 API 서버와 통신하지 마세요. 자세한 내용은 Google Cloud 블로그 게시물을 참조하세요.

네임스페이스와 RBAC를 사용하여 클러스터 리소스에 대한 액세스 제한

CIS GKE 벤치마크 권장사항: 5.6.1. 네임스페이스를 사용하여 리소스 간 관리 경계 만들기

각 팀과 환경별로 별도의 네임스페이스 또는 클러스터를 생성하여 팀에 Kubernetes에 대한 최소 권한을 부여합니다. 책임성 및 지불 거절과 관련하여 각 네임스페이스에 비용 센터 및 적절한 라벨을 지정합니다. 특히 프로덕션 환경에서 개발자에게만 애플리케이션을 배포하고 관리하는 데 필요한 네임스페이스의 액세스 수준을 제공합니다. 사용자가 클러스터에 수행해야 하는 작업을 매핑하고 각 작업을 수행하는 데 필요한 권한을 정의합니다.

네임스페이스 만들기에 대한 자세한 내용은 Kubernetes 문서를 참조하세요. RBAC 구성 계획 시 권장사항은 GKE RBAC 권장사항을 참조하세요.

IAM역할 기반 액세스 제어(RBAC)는 함께 작동하며 항목이 클러스터의 리소스를 사용하려면 수준과 관계없이 충분한 권한을 보유해야 합니다.

그룹과 사용자에게 적절한 GKE용 IAM 역할을 할당하여 프로젝트 수준의 권한을 제공하고 RBAC를 사용하여 클러스터와 네임스페이스 수준의 권한을 부여합니다. 자세한 내용은 액세스 제어를 참조하세요.

네임스페이스와 함께 IAM 및 RBAC 권한을 사용하여 Google Cloud 콘솔에서 클러스터 리소스와의 사용자 상호작용을 제한할 수 있습니다. 자세한 내용은 액세스 권한을 사용 설정하고 네임스페이스별 클러스터 리소스 보기를 참조하세요.

네트워크 정책으로 포드 간 트래픽 제한

CIS GKE 벤치마크 권장사항: 6.6.7. 네트워크 정책이 사용 설정되어 있고 적절하게 설정되어 있는지 확인

기본적으로 클러스터에 있는 모든 포드는 서로 통신할 수 있습니다. 워크로드의 필요에 따라 포드 간 통신을 제어해야 합니다.

서비스에 대한 네트워크 액세스를 제한하면 클러스터 내에서 공격자의 측면 이동이 더 어려워지고 실수로 인한 서비스 거부나 고의적인 서비스 거부로부터 서비스를 보호할 수 있습니다. 트래픽을 제어하는 두 가지 권장 방법은 다음과 같습니다.

  1. Istio를 사용합니다. 부하 분산, 서비스 승인, 제한, 할당량, 측정항목 등에 관심이 있는 경우 Google Kubernetes Engine에 Istio 설치를 참조하세요.
  2. Kubernetes 네트워크 정책을 사용합니다. 클러스터 네트워크 정책 만들기를 참조하세요. Kubernetes에서 제공하는 기본 액세스 제어 기능을 찾고 있는 경우 이 옵션을 선택합니다. 네트워크 정책을 사용하여 트래픽을 제한하는 일반적인 방식을 구현하려면 GKE Enterprise 보안 청사진 구현 가이드를 따르세요. 또한 Kubernetes 문서에 간단한 nginx 배포를 위한 훌륭한 둘러보기가 포함되어 있습니다. 네트워크 정책 로깅을 사용하여 네트워크 정책이 예상대로 작동하는지 확인하는 것이 좋습니다.

Istio와 네트워크 정책은 필요할 경우 함께 사용할 수 있습니다.

보안 비밀 관리

CIS GKE 벤치마크 권장사항: 6.3.1. Cloud KMS에서 관리되는 키를 사용하여 Kubernetes 보안 비밀 암호화

etcd에 저장되는 보안 비밀과 같이 민감한 정보를 위한 추가 보안 레이어를 제공해야 합니다. 이렇게 하려면 GKE 클러스터와 통합된 보안 비밀 관리자를 구성해야 합니다. 일부 솔루션은 GKE와 VMware용 GKE 모두에서 작동하므로 여러 환경에서 워크로드를 실행하는 경우에 더 적합할 수 있습니다. HashiCorp Vault와 같은 외부 보안 비밀 관리자를 사용하는 경우 클러스터를 만들기 전에 사용 준비를 완료해야 합니다.

보안 비밀 관리에는 여러 가지 옵션이 있습니다.

  • Kubernetes 보안 비밀은 기본적으로 GKE에서 사용할 수 있습니다. 선택적으로 애플리케이션 레이어 보안 비밀 암호화를 사용하여 관리하는 키로 애플리케이션 레이어에서 암호화할 수 있습니다.
  • HashiCorp Vault와 같은 보안 비밀 관리자를 사용할 수 있습니다. 이는 강화 HA 모드에서 실행될 때 일관성 있는 프로덕션 수준의 보안 비밀 관리 방법을 제공합니다. Kubernetes 서비스 계정 또는 Google Cloud 서비스 계정을 사용하여 HashiCorp Vault에 인증할 수 있습니다. GKE에서 Vault를 사용하는 방법에 대한 자세한 내용은 Kubernetes에서 HashiCorp Vault 실행 및 연결을 참조하세요.

GKE VM은 기본적으로 etcd를 포함하는 스토리지 레이어에서 암호화됩니다.

허용 컨트롤러를 사용하여 정책 적용

허용 컨트롤러는 클러스터가 사용되는 방식을 제어하고 적용하는 플러그인입니다. Kubernetes의 고급 보안 기능 중 일부를 사용하도록 설정해야 하며, 클러스터 보안 강화를 위한 심층 방어 방식의 중요한 요소입니다.

기본적으로 Kubernetes에서 포드는 필요한 것 이상의 기능으로 작동될 수 있습니다. 해당 워크로드에 필요한 정도로만 포드 기능을 제한해야 합니다.

Kubernetes는 명시적으로 부여된 기능만으로 포드 실행을 제한하기 위한 여러 가지 컨트롤을 지원합니다. 예를 들어 정책 컨트롤러를 Fleet의 클러스터에 사용할 수 있습니다. Kubernetes에는 또한 개별 클러스터에서 포드 보안 표준을 적용할 수 있게 해주는 기본 제공되는 PodSecurity 허용 컨트롤러가 있습니다.

정책 컨트롤러는 선언적 정책을 사용하여 GKE 클러스터에서 대규모로 보안을 시행하고 유효성을 검사할 수 있는 GKE Enterprise 기능입니다. 정책 컨트롤러를 사용해서 GKE 클러스터에서 선언적 제어를 적용하는 방법은 정책 컨트롤러 설치를 참조하세요.

PodSecurity 허용 컨트롤러를 사용하면 특정 네임스페이스나 전체 클러스터에 사전 정의된 정책을 적용할 수 있습니다. 이러한 정책은 서로 다른 포드 보안 표준에 해당합니다.

워크로드가 자체 수정하는 기능을 제한

특정 Kubernetes 워크로드, 특히 시스템 워크로드에는 자체 수정 권한이 있습니다. 예를 들어 일부 워크로드는 수직적으로 자동 확장됩니다. 이렇게 하면 노드를 이미 손상시킨 공격자가 클러스터에서 추가로 에스컬레이션할 수 있습니다. 예를 들어 공격자는 노드에 있는 워크로드가 동일 네임스페이스에 존재하는 권한이 높은 서비스 계정으로 실행되도록 변경할 수 있습니다.

워크로드에 자체 수정 권한이 애초에 부여되지 않는 것이 좋습니다. 자체 수정이 필요한 경우 몇 가지 유용한 보안 정책을 제공하는 오픈소스 Gatekeeper 라이브러리에서 NoUpdateServiceAccount와 같은 Gatekeeper 또는 Policy Controller 제약조건을 적용하여 권한을 제한할 수 있습니다.

정책을 배포할 때는 일반적으로 클러스터 수명 주기를 관리하는 컨트롤러가 정책을 우회할 수 있도록 해야 합니다. 이는 컨트롤러가 클러스터 업그레이드 적용과 같이 클러스터를 변경할 수 있도록 하기 위해 필요합니다. 예를 들어 GKE에 NoUpdateServiceAccount 정책을 배포하는 경우 Constraint에 다음 매개변수를 설정해야 합니다.

parameters:
  allowedGroups:
  - system:masters
  allowedUsers:
  - system:addon-manager

지원 중단된 gcePersistentDisk 볼륨 유형 사용 제한

지원 중단된 gcePersistentDisk 볼륨 유형을 사용하면 Compute Engine 영구 디스크를 포드에 마운트할 수 있습니다. 워크로드에서 gcePersistentDisk 볼륨 유형 사용을 제한하는 것이 좋습니다. Google Cloud는 기본 VM에 디스크를 연결할 때 승인 검사를 수행하지만 GKE는 디스크를 이 볼륨 유형을 마운트할 때 포드에서 IAM 승인 검사를 수행하지 않습니다. 따라서 이미 네임스페이스에 포드를 만들 수 있는 공격자는 Google Cloud 프로젝트의 Compute Engine 영구 디스크 콘텐츠에 액세스할 수 있습니다.

Compute Engine 영구 디스크에 액세스하고 사용하려면 PersistentVolumes 및 PersistentVolumeClaims를 대신 사용합니다. gcePersistentDisk 볼륨 유형의 사용을 방지하는 보안 정책을 클러스터에 적용합니다.

gcePersistentDisk 볼륨 유형의 사용을 방지하려면 PodSecurity 허용 컨트롤러로 기준 또는 제한 정책을 적용하거나 정책 컨트롤러 또는 게이트키퍼 허용 컨트롤러에서 커스텀 제약조건을 정의할 수 있습니다.

이 볼륨 유형을 제한하는 커스텀 제약조건을 정의하려면 다음 안내를 따르세요.

  1. 정책 컨트롤러 또는 게이트키퍼 OPA와 같은 정책 기반 허용 컨트롤러를 설치합니다.

    Policy Controller

    클러스터에 정책 컨트롤러를 설치합니다.

    참고: 정책 컨트롤러는 GKE 사용자를 위한 유료 기능입니다. 정책 컨트롤러는 오픈소스 Gatekeeper를 기반으로 하지만 전체 제약조건 템플릿 라이브러리, 정책 번들, Google Cloud 콘솔 대시보드와의 통합을 이용할 수 있으므로 클러스터 관찰 및 유지보수에 도움이 됩니다. 정책 번들은 CIS Kubernetes 벤치마크와 같은 권장사항을 기반으로 하는 번들을 포함하여 클러스터에 적용할 수 있는 독자적인 권장사항입니다.

    게이트키퍼

    클러스터에 게이트키퍼를 설치합니다.

    Autopilot 클러스터의 경우 텍스트 편집기에서 게이트키퍼 gatekeeper.yaml 매니페스트를 엽니다. MutatingWebhookConfiguration 사양의 rules 필드를 수정하여 와일드 카드(*) 문자를 다음 예시와 같이 특정 API 그룹 및 리소스 이름으로 바꿉니다.

    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    ...
    webhooks:
    - admissionReviewVersions:
      - v1
      - v1beta1
      ...
      rules:
      - apiGroups:
        - core
        - batch
        - apps
        apiVersions:
        - '*'
        operations:
        - CREATE
        - UPDATE
        resources:
        - Pod
        - Deployment
        - Job
        - Volume
        - Container
        - StatefulSet
        - StorageClass
        - Secret
        - ConfigMap
      sideEffects: None
      timeoutSeconds: 1
    

    Autopilot 클러스터에 업데이트된 gatekeeper.yaml 매니페스트를 적용하여 게이트키퍼를 설치합니다. 이는 Autopilot이 기본 제공 보안 조치로서 허용 웹훅을 변형할 때 와일드 카드 문자를 허용하지 않기 때문에 필요합니다.

  2. 기본 제공 포드 보안 정책 볼륨 유형 ConstraintTemplate을 배포합니다.

    kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/volumes/template.yaml
    
  3. constraint.yaml 등 허용되는 볼륨 유형 목록과 함께 다음 제약조건을 저장합니다.

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: k8sPSPVolumeTypes
    metadata:
      name: nogcepersistentdisk
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pods"]
      parameters:
        volumes: ["configMap", "csi", "projected", "secret", "downwardAPI", "persistentVolumeClaim", "emptyDir", "nfs", "hostPath"]
    

    이 제약조건은 spec.parameters.volumes 필드의 목록으로 볼륨을 제한합니다.

  4. 제약조건을 배포합니다.

    kubectl apply -f constraint.yaml
    

클러스터 구성 모니터링

클러스터 구성을 감사하여 정의된 설정과의 편차를 확인해야 합니다.

Security Health Analytics을 사용하여 이 강화 가이드에서 다룬 많은 권장사항 및 기타 일반적인 구성 오류를 자동으로 확인할 수 있습니다.

보안 기본 사항

다음 섹션에서는 새 클러스터에서 기본적으로 안전하게 구성되는 옵션을 설명합니다. 기존 클러스터가 안전하게 구성되어 있는지 확인해야 합니다.

노드 메타데이터 보호

CIS GKE 벤치마크 권장사항: 6.4.1. 기존 Compute Engine 인스턴스 메타데이터 API가 사용 중지되어 있는지 확인, 6.4.2. GKE 메타데이터 서버가 사용 설정되어 있는지 확인

v0.1v1beta1 Compute Engine 메타데이터 서버 엔드포인트는 지원 중단되었고 2020년 9월 30일 종료되었습니다. 이러한 엔드포인트에는 메타데이터 쿼리 헤더가 적용되지 않았습니다. 종료 일정은 v0.1v1beta1 메타데이터 서버 엔드포인트 지원 중단을 참조하세요.

Kubernetes에 대한 일부 실제 공격은 사용자 인증 정보를 추출하기 위해 VM 메타데이터 서버에 액세스합니다. GKE용 워크로드 아이덴티티 제휴 또는 메타데이터 숨김을 사용하는 경우 이러한 공격이 차단됩니다.

기존 클라이언트 인증 방법 사용 안 함

CIS GKE 벤치마크 권장사항: 6.8.1. 정적 비밀번호를 사용하는 기본 인증이 중지되어 있는지 확인, 6.8.2. 클라이언트 인증서를 사용한 인증이 중지되어 있는지 확인

Kubernetes API 서버에 인증하는 방법에는 몇 가지가 있습니다. GKE에서 지원되는 방법은 서비스 계정 Bearer 토큰, OAuth 토큰, x509 클라이언트 인증서입니다. OAuth 토큰 방법의 경우 GKE는 Kubernetes 구성을 설정하고, 액세스 토큰을 가져오고, 이를 최신 상태로 유지하는 방식으로 gcloud를 통해 인증을 관리합니다.

GKE가 Google OAuth와 통합되기 전에는 1회 생성된 x509 인증서나 정적 비밀번호가 유일하게 사용 가능한 인증 방법이었지만 이제는 권장되지 않으며 사용 중지해야 합니다. 이러한 방법은 클러스터를 손상시킬 수 있는 공격 범위가 넓으며 GKE 버전 1.12 이후부터는 기본적으로 사용 중지되었습니다. 기존 인증 방법을 사용하는 경우 중지하는 것이 좋습니다. 정적 비밀번호를 사용하는 인증은 지원 중단되었으며 GKE 버전 1.19 이후부터는 삭제되었습니다.

기존 클러스터는 OAuth로 이동해야 합니다. 클러스터 외부의 시스템에서 장기적인 사용자 인증 정보가 필요한 경우 필요한 권한을 보유한 Google 서비스 계정 또는 Kubernetes 서비스 계정을 생성하고 키를 내보내는 것이 좋습니다.

기존 클러스터를 업데이트하고 정적 비밀번호를 삭제하려면 정적 비밀번호를 사용한 인증 사용 중지를 참조하세요.

현재 기존 클러스터에서 사전 발급된 클라이언트 인증서를 삭제할 수 있는 방법이 없지만 RBAC가 사용 설정되어 있고 ABAC가 사용 중지되어 있는 경우 권한이 없습니다.

Cloud Logging 사용

CIS GKE 벤치마크 권장사항: 6.7.1. Stackdriver Kubernetes Logging 및 Monitoring이 사용 설정되어 있는지 확인

작업 오버헤드를 줄이고 로그의 통합 보기를 유지하려면 클러스터 배포 위치와 상관없이 일관성 있는 로깅 전략을 구현합니다. GKE Enterprise 클러스터는 기본적으로 Cloud Logging과 통합되어 있으며 이렇게 구성된 상태를 유지해야 합니다.

모든 GKE 클러스터에는 Kubernetes API 서버로 전송된 호출을 시간순으로 기록하는 Kubernetes 감사 로깅이 기본적으로 사용 설정되어 있습니다. Kubernetes 감사 로그 항목은 의심스러운 API 요청을 조사하거나, 통계를 수집하거나, 원치 않는 API 호출에 대한 모니터링 알림을 생성하는 데 유용합니다.

GKE 클러스터는 Cloud 감사 로그에 의한 Kubernetes 감사 로깅Cloud Logging을 통합합니다. 로그를 Cloud Logging에서 사용자 고유 로깅 시스템으로 라우팅할 수 있습니다.

Kubernetes 웹 UI(대시보드) 사용 안 함

CIS GKE 벤치마크 권장사항: 6.10.1. Kubernetes 웹 UI가 중지되어 있는지 확인

GKE에서 실행할 때 Kubernetes 웹 UI(대시보드)를 사용할 수 없습니다.

Kubernetes 웹 UI(대시보드)는 상위 권한의 Kubernetes 서비스 계정으로 지원됩니다. Google Cloud 콘솔에서 대부분의 동일 기능을 제공하므로 이러한 권한이 필요하지 않습니다.

Kubernetes 웹 UI를 사용 중지하려면 다음을 수행하세요.

gcloud container clusters update CLUSTER_NAME \
    --update-addons=KubernetesDashboard=DISABLED

ABAC 사용 안 함

CIS GKE 벤치마크 권장사항: 6.8.4. 기존 승인(ABAC)이 중지되어 있는지 확인

ABAC(속성 기반 액세스 제어)를 중지하고 대신 GKE에서 RBAC(역할 기반 액세스 제어)를 사용해야 합니다.

기본적으로 ABAC는 GKE 버전 1.8 이상을 사용하여 생성된 클러스터에서 사용 중지됩니다. Kubernetes에서 RBAC는 클러스터 및 네임스페이스 수준에서 리소스에 대한 권한을 부여하기 위해 사용됩니다. RBAC를 사용하면 권한 집합이 포함된 규칙을 사용하여 역할을 정의할 수 있습니다. RBAC는 ABAC에 비해 상당한 보안 이점이 있습니다.

아직 ABAC를 사용하는 경우에는 먼저 RBAC 사용을 위한 기본 요건을 참조하세요. 클러스터를 이전 버전에서 업그레이드했고, ABAC를 사용하는 경우에는 액세스 제어 구성을 업데이트해야 합니다.

gcloud container clusters update CLUSTER_NAME \
    --no-enable-legacy-authorization

위의 권장사항에 따라 새 클러스터를 만들려면 다음을 사용하세요.

gcloud container clusters create CLUSTER_NAME \
    --no-enable-legacy-authorization

DenyServiceExternalIPs 허용 컨트롤러를 사용 설정된 상태로 둡니다.

DenyServiceExternalIPs 허용 컨트롤러를 사용 중지하지 마세요.

DenyServiceExternalIPs 허용 컨트롤러는 서비스에 ExternalIP가 사용되지 않도록 차단하고 알려진 보안 취약점을 완화합니다.

DenyServiceExternalIPs 허용 컨트롤러는 GKE 버전 1.21 이상에서 생성된 새 클러스터에서 기본적으로 사용 설정됩니다. GKE 버전 1.21 이상으로 업그레이드하는 클러스터의 경우 다음 명령어를 사용해서 허용 컨트롤러를 사용 설정할 수 있습니다.

gcloud beta container clusters update CLUSTER_NAME \
    --no-enable-service-externalips

다음 단계