[GCP] GKE 의 Kubernetes 보안 강화 기능

Kiwon Lee
google-cloud-apac
Published in
16 min readApr 9, 2020

안녕하세요, 이기원 입니다.

Google Cloud 의 관리형 Kubernetes 서비스인 Google Kubernetes Engine (이하, GKE) 에서는 Kubernetes 클러스터의 보안 강화를 위해 다양한 기능들을 제공하고 있습니다. 이번 가이드 에서는 관련 내용들을 정리해 보겠습니다.

1. Kubernetes 를 최신 버전으로 유지 하라.

Kubernetes 는 보안 업데이트 및 이슈 해결등을 위해 자주 업데이트 되고 있습니다. 운영하고 있는 GKE 클러스터의 안정성을 유지하기 위해서는 마스터(Control Plane) 와 노드들을 최신 버전의 Kubernetes 로 유지하는 것이 좋습니다.

GKE 에서 클러스터 생성 시 출시채널(Release Channel) 기능을 통해 최신의 Kubernetes 버전으로 자동 업그레이드 (마스터, 노드) 를 지원하고 있습니다.

  1. 자동 업그레이드 - 출시 채널

클러스터 생성 시, 목적에 맞게 다음 채널 중 하나를 선택하면, 그 채널에 출시되는 신규 버전으로 마스터와 노드가 자동 업그레이드 됩니다.

https://cloud.google.com/kubernetes-engine/docs/concepts/release-channels

클러스터 생성 시, 출시 채널의 버전이 아닌 특정 버전(정적 버전) 으로 생성하고, 마스터의 수동 업그레이드를 진행 하는 경우, 노드 들은 “자동 업그레이드” 기능을 통해 마스터에 설치된 버전에 맞게 최신 상태로 유지할 수 있습니다.

2. 수동 업그레이드 - 정적 버전

Kubernetes 의 특정 버전으로 설치가 필요한 경우, 클러스터 생성 시 정적버전에서 특정 버전을 선택해서 설치 가능합니다. 이후 업그레이드를 위해서 클러스터 상세 보기에서 원하는 버전으로 마스터의 수동 업그레이드가 가능합니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/upgrading-a-cluster#upgrade_nodes

마스터의 수동 업그레이드를 진행 하는 경우, 노드 들은 “자동 업그레이드” 설정을 통해 마스터에 설치된 버전에 맞게 최신 상태로 유지할 수 있습니다. 노드 자동 업그레이드는 “정적 버전” 으로 클러스터 생성시에만 설정 가능 합니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades

2. 마스터 (Control Plane)와 노드들의 외부 노출을 제한하라.

Kubernetes 의 클러스터 보안 강화를 위해서 꼭 필요한 경우를 제외하고는 마스터와 노드의 In/Out 바운드 연결을 제한해야 합니다. 특히 마스터는 클러스터의 많은 부분들에 대한 설정이 가능하기 때문에 허용된 클라이언트만 접근 할 수 있도록 접근 제어가 필요합니다. GKE 에서는 다음 기능들로 마스터와 노드들의 외부 노출을 제한할 수 있습니다.

  1. 비공개 클러스터 (Private Cluster)

클러스터를 비공개 클러스터로 생성 시, 노드들은 내부 IP 주소만 가지게 되어 외부 인터넷으로 부터 격리되어 보안이 강화됩니다. 이때, 외부 인터넷에 접근이 필요한 노드 들의 경우 Cloud NAT 를 통해 외부 접속이 가능 하고, 외부에서 비공개 클러스터 내부의 호출이 필요한 경우에는 LoadBalancer 타입의 서비스를 통해 호출이 가능합니다.

기본적으로 마스터는 공개 IP 주소를 사용하고, 이를 통해 노드와 통신합니다. 비공개 클러스터 생성 시, 마스터는 각 노드들이 독립적인 VPC 로 구축 되어 VPC Peering 을 사용합니다. VPC Peering 을 통해 비공개 네트워크 통신을 제공하여 네트워크 보안이 강화됩니다.

https://cloud.google.com/kubernetes-engine/docs/concepts/private-cluster-concept

https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters

2. 마스터 (Control Plane) 내/외부 접근 제어

다음과 같은 클러스터 설정을 통해 허용된 IP 만 마스터에 접근 할 수 있도록 설정 합니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks

https://cloud.google.com/kubernetes-engine/docs/concepts/private-cluster-concept#overview

3. 필요한 권한만 가진 노드의 서비스 계정을 생성하고 사용하라.

GKE 의 각 노드는 Google cloud 의 VM 서비스인 Google Compute Engine(이하, GCE) 위에서 동작하기 때문에, GCE 의 기본 설정값을 그대로 상속받습니다. 클러스터 생성 시, 노드의 기본 서비스 계정이 “Compute Engine default service account” (프로젝트 내의 모든 Editor 권한 소유) 로 되어 있어 다양한 서비스 사용에는 유용하지만, GKE 클러스터를 실행하는데 필요한 것 보다 많은 권한이 포함됩니다. “최소 권한 법칙” 에 따라, GKE 클러스터 실행에 필요한 최소 권한만 있는 서비스 계정을 만들어서 사용하는 것이 좋습니다.

- “IAM 및 관리자 — 서비스 계정”에서 필요한 권한만 추가한 서비스 계정 생성 (GKE 관련 권한만 부여 시 다음 참조)

https://cloud.google.com/iam/docs/understanding-roles#kubernetes-engine-roles

전체 권한에 대한 내용은 다음에서 확인 가능합니다.
https://cloud.google.com/iam/docs/understanding-roles#predefined_roles

서비스 계정 생성 이후, 클러스터 생성 시 아래에서 생성한 서비스 계정을 선택합니다.

4. 노드에 대한 보안을 고려하라.

앞서 설명한 것과 같이, GKE 의 노드들은 GCE 위에서 동작되기 때문에, 인스턴스 자체, 즉 노드들에 대한 보안을 고려해야 합니다. 일반적으로 GCE 는 방화벽 규칙을 통해 인바운드/아웃바운드에 대한 트래픽을 제한 합니다. 이와 유사하게 Kubernetes 는 실제 트래픽이 발생되는 Pod 에 대한 방화벽 제한이 필요한데, Network Policy 를 통해 지원합니다.

  1. 보안 GKE 노드

보안 GKE 는 인스턴스의 무결성을 보장하는 GCE 의 Shielded VM 을 기반으로 실행됩니다, 이를 통해, 부팅 또는 커널 수준의 멀웨어 침해로 부터 인스턴스의 안전을 보장하여 GKE 노드 보안을 강화 합니다. Shield VM의 무결성은 보안 부팅, 무결성 모니터링 등을 통해 지원되기 때문에, 설정합니다. 보안 GKE 노드는 1.18 버전부터 기본적으로 적용됩니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/shielded-gke-nodes

  • 무결성 모니터링

최신 부팅 데이터를 무결성 정책 기준과 비교하여 일치 여부를 검사합니다.

https://cloud.google.com/security/shielded-cloud/shielded-vm#integrity-monitoring

  • 보안 부팅

부팅 시 모든 부팅 구성 요소들의 디지털 서명을 확인하고, 서명 확인에 실패 시 부팅 프로세스를 중단하여, 시스템에서 인증된 소프트웨어만 실행하도록 보장 하는 기능 입니다.

https://cloud.google.com/security/shielded-cloud/shielded-vm#secure-boot

2. 노드 풀 생성 시, cos_containerd 이미지를 사용

Container-Optimized OS(cos) 는 GCP 에서 컨테이너를 실행할 때 권장되는 OS 로, 크기가 작아 보안 노출이 최소화 되고, 여러 보안 이슈들에 대해서 백그라운드에서 자동 업데이트가 진행 될 뿐만 아니라, 기타 보안 설정(파일 시스템 무결성 확인, 감사 데이터 등) 이 기본적으로 포함되어 더욱 강화된 노드에 대한 보안을 지원합니다.

특히, cos_containerd 이미지는 컨테이너 런타임으로 containerd 를 포함한 cos 이미지로 기본 Docker 데몬보다 덜 복잡하여 공격에 취약한 부분이 적습니다. 그렇기 때문에, 보안 향상을 위해서는 노드 풀 생성 시, cos_containerd 이미지를 사용하는 것을 권장 합니다.

5. 신뢰 할 수 있는 애플리케이션을 사용하라.

컨테이너에서 신뢰할 수 없는 애플리케이션이 실행되는 경우, 프로세스가 컨테이너를 벗어나 커널에 영향을 주거나, 동일 노드 내 다른 컨테이너, 다른 클러스터에도 영향을 줄 수 있습니다. 그렇기 때문에 다음의 기능들을 통해 컨테이너에서 신뢰할 수 있는 애플리케이션을 실행하도록 합니다.

  1. gVisor 가 포함된 샌드박스

샌드박스 기능은 호스트 커널을 재 구현한 gVisor 을 통해, 각 Pod 마다 샌드박스를 생성하고, 샌드 박스 내에서 호스트 커널을 대신하여 서비스를 제공합니다. 이를 통해 신뢰할 수 없는 소스 코드가 컨테이너에서 동작 되더라도 샌드박스 내에서만 실행되기 때문에, 다른 곳에 영향을 주지 않습니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods

2. Binary Authorization

개발 프로세스 중에 이미지에 서명을 받도록 요구하고, 이후 배포 시 서명에 대한 검증을 실시합니다. 이렇게 배포 시점의 보안 제어를 통해 GKE 에 신뢰할 수 있는 컨테이너 이미지만 배포되도록 기능을 제공하여 실제 운영 환경에서 의도하지 않은 코드 또는 악의적인 코드가 실행될 가능성을 줄입니다.

3. 컨테이너 이미지 취약점 분석

Container Registry 에 이미지를 저장하는 시점에, Ubuntu, Debian, Alpine 의 이미지 취약점을 검사하고 조치 합니다. Container Registry 의 설정에서 취약점 스캔 사용 설정을 하고, 이미지를 등록 하는 시점에 검사를 합니다.

6. Pod에 대한 네트워크 방화벽을 적용 하라.

일반적으로 GCE 는 방화벽 규칙을 통해 In/Out 바운드에 대한 트래픽을 제한 합니다. 이와 유사하게 Kubernetes 는 실제 트래픽이 발생되는 Pod 에 대한 방화벽 제한이 필요한데, Network Policy 를 통해 지원합니다.

클러스터 생성 시, Kubernetes 의 Network Policy 는 네트워크 플러그인들을 통해 지원되는데, GKE 는 Calico 를 통해 지원 합니다. 클러스터 생성 시 “네트워크 정책 사용” 을 체크하면 Calico 관련 플러그인들이 설치되어 네트워크 정책 설정을 사용 가능합니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy

NetworkPolicy 는 아래와 같은 리소스를 생성하여 적용 가능합니다. 해당 리소스에 대한 자세한 내용은 다음에서 확인가능합니다.

https://kubernetes.io/ko/docs/concepts/services-networking/network-policies/

7. Pod와 컨테이너의 보안 정책을 고려하라.

컨테이너의 securityContext 설정을 통해 컨테이너에 대한 여러 권한 및 보안 관련 기능에 대한 제어를 제공합니다.

  • 특정 사용자 ID 로 컨테이너의 실행 정의 (runAsUser)
  • Root 사용자로 컨테이너 실행 금지를 정의 (runAsNonRoot)
  • 컨테이너에서 사용할 개별 커널 기능을 정의, 정의한 기능만 사용하도록 제한 (capabilities)
  • 컨테이너 파일 시스템에 ReadOnly 권한 정의 (readOnlyRootFilesystem)

이 외에도 아래에서 더 많은 설정들을 확인할 수 있습니다.

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#securitycontext-v1-core

PodSecurityPolicy 는 클러스터 내에서 Pod의 생성 및 업데이트 요청에 대한 유효성을 검사하는 리소스로, Pod에 정의되는 여러 권한 및 보안 관련 기능에 대한 제어를 제공합니다. PodSecurityPolicy 값에 따라, Pod 생성 시 기본값 목록을 설정하거나, 조건을 검사해서 조건에 맞지 않으면 생성 요청이 거부됩니다.

https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies#define_policies

  • 클러스터 내의 컨테이너들이 실행 할 수 있는 사용자 ID 목록 (runAsUser, fsGroup, supplementalGroups)
  • 컨테이너 파일 시스템에 ReadOnly 권한만 부여 여부하기 (readOnlyRootFilesystem)
  • Pod가 사용할 수 있는 파일 시스템의 볼륨 유형 리스트를 정의 (volumes)

이 외에도 아래에서 더 많은 설정들을 확인할 수 있습니다.

https://kubernetes.io/docs/concepts/policy/pod-security-policy/#what-is-a-pod-security-policy

현재 PodSecurityPolicy 는 BETA 로 클러스터 생성 이후 아래의 명령어를 통해 클러스터를 업데이트 해야 실제로 동작됩니다. (현재, 웹 화면에서는 별도 설정 체크 지원 안 함)

kiwonlee@cloudshell:~ (kwlee-default-project)$ gcloud beta container clusters update cluster-1 --enable-pod-security-policy

PodSecurityPolicy 는 기본적으로 클러스터에 적용되는 규칙입니다. 모든 클러스터 내에 동일한 규칙이 아닌 예외적으로 적용해야 할 경우가 있습니다. (시스템 관련 파드 등) 이럴때, RBAC (Role Based Access Control) 을 활용하여, 사용자 또는 그룹에 별도 정책을 할당 할 수 있습니다.

  • Role : 사용자가 어떤 리소스에 어떤 액션을 할수 있는지를 정의하는 리소스, 리소스에 PodSecurityPolicy 를 정의합니다.
  • RoleBinding : Role 에 사용자/그룹 등을 매핑하는 하는 리소스

지금까지 Kubernetes 클러스터의 보안 강화를 위해 GKE 에서 지원하는 여러 내용들을 살펴 봤습니다. 이러한 기능들을 Kubernetes 클러스터에 적용하여 보안을 강화 할 수 있습니다.

Disclaimer: 본 글의 작성자는 Google 직원이지만 Google Cloud 를 공부하는 한 개인으로서 작성된 글입니다. 본 글의 내용, 입장은 Google 을 대변하지 않으며 Google 이 해당 콘텐츠를 보장하지 않습니다.

[참고 자료]

--

--