PodSecurity를 사용하여 사전 정의된 포드 수준 보안 정책 적용


이 페이지에서는 PodSecurity 허용 컨트롤러를 사용하여 Google Kubernetes Engine(GKE) 클러스터에 사전 정의된 포드 수준 보안 제어를 적용하는 방법을 보여줍니다.

PodSecurity 작동 방식에 대한 자세한 내용은 포드 보안 허용을 참조하세요.

개요

PodSecurity포드 보안 표준을 GKE 클러스터에서 실행되는 포드에 적용할 수 있게 해주는 Kubernetes 허용 컨트롤러입니다. 포드 보안 표준은 Kubernetes에서 포드 보안의 고급 요구사항을 다루는 사전 정의된 보안 정책입니다. 이러한 정책은 매우 허용적인 정책부터 매우 제한적인 정책까지 다양합니다.

다음 포드 보안 표준을 GKE 클러스터에 적용할 수 있습니다.

  • 권한: 가장 광범위한 수준의 권한을 제공하는 제한되지 않은 정책입니다. 알려진 권한 에스컬레이션을 허용합니다.
  • 기본: 최소한으로 지정된 기본 포드 구성을 허용하는 최소 제한 정책입니다. 알려진 권한 에스컬레이션을 허용하지 않습니다.
  • 제한됨: 포드 강화 권장사항을 따르는 매우 제한적인 정책입니다.

PodSecurity 허용 컨트롤러를 사용하여 다음 모드로 포드 보안 표준을 적용할 수 있습니다.

  • 적용: 정책 위반은 포드 생성을 거부합니다. 감사 이벤트가 감사 로그에 추가됩니다.
  • 감사: 정책 위반은 감사 로그에 감사 이벤트를 추가하는 것을 트리거합니다. 포드 만들기가 허용됩니다.
  • 경고: 정책 위반은 사용자에게 표시되는 경고를 트리거합니다. 포드 만들기가 허용됩니다.

PodSecurity 허용 컨트롤러는 이러한 정책을 Kubernetes API에 삽입합니다.

포드 수준에서 커스텀 보안 정책을 만들고 적용하려면 Gatekeeper 허용 컨트롤러를 대신 사용하는 것이 좋습니다.

시작하기 전에

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

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

요구사항

PodSecurity 허용 컨트롤러를 사용할 수 있고 기본적으로 다음 GKE 버전을 실행하는 클러스터에서 사용 설정됩니다.

  • 버전 1.25 이상: 정식
  • 버전 1.23 및 버전 1.24: 베타

GKE 버전을 사용할 수 있고 출시 채널의 기본 버전인지 확인하려면 출시 일정을 참조하세요.

PodSecurity를 사용하여 포드 보안 표준 적용

PodSecurity 허용 컨트롤러를 사용하려면 특정 모드의 특정 포드 보안 표준을 특정 네임스페이스에 적용해야 합니다. 네임스페이스 라벨을 사용하여 이를 수행할 수 있습니다. 이 연습에서는 다음을 수행합니다.

  • 새 네임스페이스 2개 만들기
  • 각 네임스페이스에 보안 정책 적용
  • 구성된 정책 테스트

다음 GKE 버전에서 GKE는 kube-system 네임스페이스에 적용되는 정책을 무시합니다.

  • 1.23.6-gke.1900 이상
  • 1.24.0-gke.1200 이상

이전 GKE 버전에서는 kube-system에 정책을 적용하지 않습니다.

새 네임스페이스 만들기

클러스터에 네임스페이스를 만듭니다.

kubectl create ns baseline-ns
kubectl create ns restricted-ns

이 명령어는 다음 네임스페이스를 만듭니다.

  • baseline-ns: 허용적인 워크로드용
  • restricted-ns: 매우 제한적인 워크로드용

라벨을 사용하여 보안 정책 적용

다음 포드 보안 표준을 적용합니다.

  • baseline: warn 모드의 baseline-ns에 적용
  • restricted: enforce 모드의 restricted-ns에 적용
kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline
kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted

이러한 명령어는 다음과 같은 결과를 생성합니다.

  • baseline 정책을 위반하는 baseline-ns 네임스페이스의 워크로드가 허용되며 클라이언트에 경고 메시지가 표시됩니다.
  • restricted 정책을 위반하는 restricted-ns 네임스페이스의 워크로드가 거부되고 GKE는 감사 로그에 항목을 추가합니다.

라벨이 추가되었는지 확인합니다.

kubectl get ns --show-labels

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

baseline-ns       Active   74s   kubernetes.io/metadata.name=baseline-ns,pod-security.kubernetes.io/warn=baseline
restricted-ns     Active   18s   kubernetes.io/metadata.name=restricted-ns,pod-security.kubernetes.io/enforce=restricted
default           Active   57m   kubernetes.io/metadata.name=default
kube-public       Active   57m   kubernetes.io/metadata.name=kube-public
kube-system       Active   57m   kubernetes.io/metadata.name=kube-system

구성된 정책 테스트

PodSecurity 허용 컨트롤러가 의도한 대로 작동하는지 확인하려면 baselinerestricted 정책을 위반하는 워크로드를 두 네임스페이스 모두에 배포합니다. 다음 매니페스트 예시에서는 권한 에스컬레이션을 허용하는 nginx 컨테이너를 배포합니다.

  1. 다음 매니페스트를 psa-workload.yaml로 저장합니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    
  2. baseline-ns 네임스페이스에 매니페스트를 적용합니다.

    kubectl apply -f psa-workload.yaml --namespace=baseline-ns
    

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

    Warning: would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
    

    baseline 정책은 포드가 네임스페이스에 배포되도록 허용합니다.

  3. 포드가 성공적으로 배포되었는지 확인합니다.

    kubectl get pods --namespace=baseline-ns -l=app=nginx
    
  4. restricted-ns 네임스페이스에 매니페스트를 적용합니다.

    kubectl apply -f psa-workload.yaml --namespace=restricted-ns
    

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

    Error from server (Forbidden): error when creating "workload.yaml": pods "nginx"
    is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation
    != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false),
    unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]),
    runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
    seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
    to "RuntimeDefault" or "Localhost")
    

    포드가 네임스페이스에 배포되지 않습니다. 감사 항목이 로그에 추가됩니다.

감사 로그에서 정책 위반 보기

auditenforce 모드에서의 정책 위반은 클러스터의 감사 로그에 기록됩니다. Google Cloud 콘솔의 로그 탐색기를 사용하여 이러한 로그를 볼 수 있습니다.

  1. Google Cloud 콘솔의 로그 탐색기 페이지로 이동합니다.

    로그 탐색기로 이동

  2. 쿼리 필드에 다음을 지정하여 auditenforce 모드 감사 로그를 검색합니다.

    resource.type="k8s_cluster"
    protoPayload.resourceName:"/pods/nginx"
    protoPayload.methodName="io.k8s.core.v1.pods.create"
    (labels."pod-security.kubernetes.io/audit-violations":"PodSecurity" OR protoPayload.response.reason="Forbidden")
    
  3. 쿼리 실행을 클릭합니다.

  4. 쿼리 결과 섹션에서 Forbidden 로그 항목을 펼쳐 enforce 모드 거부 로그를 살펴봅니다. 세부정보는 다음과 비슷합니다.

    {
      ...
      protoPayload: {
        @type: "type.googleapis.com/google.cloud.audit.AuditLog"
        authenticationInfo: {1}
        authorizationInfo: [1]
        methodName: "io.k8s.core.v1.pods.create"
        request: {6}
        requestMetadata: {2}
        resourceName: "core/v1/namespaces/restricted-ns/pods/nginx"
        response: {
          @type: "core.k8s.io/v1.Status"
          apiVersion: "v1"
          code: 403
          details: {2}
          kind: "Status"
          message: "pods "nginx" is forbidden: violates PodSecurity "restricted:latest": privileged
                  (container "nginx" must not set securityContext.privileged=true),
                  allowPrivilegeEscalation != false (container "nginx" must set
                  securityContext.allowPrivilegeEscalation=false), unrestricted capabilities
                  (container "nginx" must set securityContext.capabilities.drop=["ALL"]),
                  runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
                  seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
                  to "RuntimeDefault" or "Localhost")"
          metadata: {0}
          reason: "Forbidden"
          status: "Failure"
          }
          serviceName: "k8s.io"
          status: {2}
        }
      receiveTimestamp: "2022-02-01T19:19:25.353235326Z"
      resource: {2}
      timestamp: "2022-02-01T19:19:21.469360Z"
    }
    
  5. audit 모드 로그를 살펴보려면 audit-violations 로그 항목을 펼칩니다. 세부정보는 다음과 비슷합니다.

    {
      ...
      labels: {
        ...
        pod-security.kubernetes.io/audit-violations: "would violate PodSecurity "baseline:latest": privileged
                                                    (container "nginx" must not set securityContext.privileged=true)"
        pod-security.kubernetes.io/enforce-policy: "privileged:latest"
      }
      operation: {4}
      protoPayload: {10}
      receiveTimestamp: "2023-12-26T05:18:04.533631468Z"
      resource: {2}
      timestamp: "2023-12-26T05:17:36.102387Z"
    }
    

삭제

Google Cloud 계정에 비용이 청구되지 않도록 하려면 네임스페이스를 삭제하세요.

kubectl delete ns baseline-ns
kubectl delete ns restricted-ns

PodSecurity의 대안

포드 보안 표준을 적용하기 위해 기본 제공되는 Kubernetes PodSecurity 허용 컨트롤러를 사용하는 것 외에도 Open Policy Agent(OPA)를 기반으로 하는 허용 컨트롤러인 Gatekeeper를 사용하여 커스텀 포드 수준 보안 제어를 만들고 적용할 수 있습니다.

다음 단계