클러스터 레벨에서 Pod Security Standards 적용하기
클러스터 레벨에서 Pod Security Standards 적용하기
이 튜토리얼에서는 클러스터의 모든 네임스페이스에 표준 구성이 적용되도록, 클러스터 레벨에서 baseline Pod Security Standard를 적용하는 방법을 함께 살펴봐요.
출처: 문서
본문
[NOTE] Note
이 튜토리얼은 새 클러스터에만 적용돼요.
Pod Security는 새 파드가 생성될 때 쿠버네티스의 Pod Security Standards에 맞춰 검사를 수행하는 어드미션 컨트롤러예요. v1.25에서 GA가 된 기능입니다. 이 튜토리얼은 클러스터의 모든 네임스페이스에 표준 구성을 적용하는 baseline Pod Security Standard를 클러스터 레벨에서 시행하는 방법을 보여줘요.
특정 네임스페이스에만 Pod Security Standards를 적용하려면 네임스페이스 레벨에서 Pod Security Standards 적용하기 문서를 참고하세요.
v1.37이 아닌 다른 버전의 쿠버네티스를 사용 중이라면, 해당 버전의 문서를 확인해주세요.
시작하기 전에
워크스테이션에 다음을 설치해요:
이 튜토리얼은 여러분이 완전히 제어할 수 있는 쿠버네티스 클러스터에서 구성할 수 있는 것을 보여줘요. 컨트롤 플레인을 구성할 수 없는 관리형 클러스터에서 Pod Security Admission을 설정하는 방법을 배우고 싶다면 네임스페이스 레벨에서 Pod Security Standards 적용하기 문서를 읽어보세요.
적용할 올바른 Pod Security Standard 고르기
Pod Security Admission은 내장 Pod Security Standards를 enforce, audit, warn 모드로 적용할 수 있게 해줘요.
여러분의 구성에 가장 적합한 Pod Security Standards를 고르는 데 도움이 되는 정보를 모으려면 다음을 수행해요:
-
Pod Security Standards가 적용되지 않은 클러스터를 만든다:
kind create cluster --name psa-wo-cluster-pss출력은 다음과 비슷합니다:
Creating cluster "psa-wo-cluster-pss" ... ✓ Ensuring node image (kindest/node:v) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 Set kubectl context to "kind-psa-wo-cluster-pss" You can now use your cluster with: kubectl cluster-info --context kind-psa-wo-cluster-pss Thanks for using kind! 😊 -
kubectl 컨텍스트를 새 클러스터로 설정한다:
kubectl cluster-info --context kind-psa-wo-cluster-pss출력은 다음과 비슷합니다:
Kubernetes control plane is running at https://127.0.0.1:61350 CoreDNS is running at https://127.0.0.1:61350/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. -
클러스터의 네임스페이스 목록을 가져온다:
kubectl get ns출력은 다음과 비슷합니다:
NAME STATUS AGE default Active 9m30s kube-node-lease Active 9m32s kube-public Active 9m32s kube-system Active 9m32s local-path-storage Active 9m26s -
--dry-run=server를 사용해 서로 다른 Pod Security Standards를 적용하면 어떤 일이 일어나는지 확인한다:-
Privileged
kubectl label --dry-run=server --overwrite ns --all \ pod-security.kubernetes.io/enforce=privileged출력은 다음과 비슷합니다:
namespace/default labeled namespace/kube-node-lease labeled namespace/kube-public labeled namespace/kube-system labeled namespace/local-path-storage labeled -
Baseline
kubectl label --dry-run=server --overwrite ns --all \ pod-security.kubernetes.io/enforce=baseline출력은 다음과 비슷합니다:
namespace/default labeled namespace/kube-node-lease labeled namespace/kube-public labeled Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "baseline:latest" Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged namespace/kube-system labeled namespace/local-path-storage labeled -
Restricted
kubectl label --dry-run=server --overwrite ns --all \ pod-security.kubernetes.io/enforce=restricted출력은 다음과 비슷합니다:
namespace/default labeled namespace/kube-node-lease labeled namespace/kube-public labeled Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "restricted:latest" Warning: coredns-7bb9c7b568-hsptc (and 1 other pod): unrestricted capabilities, runAsNonRoot != true, seccompProfile Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile namespace/kube-system labeled Warning: existing pods in namespace "local-path-storage" violate the new PodSecurity enforce level "restricted:latest" Warning: local-path-provisioner-d6d9f7ffc-lw9lh: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile namespace/local-path-storage labeled
-
앞선 출력에서 privileged Pod Security Standard를 적용하면 어떤 네임스페이스에서도 경고가 나타나지 않는 걸 확인할 수 있어요. 반면 baseline과 restricted 표준은 모두 경고가 있고, 특히 kube-system 네임스페이스에서 나타납니다.
모드·버전·표준 설정하기
이 절에서는 latest 버전에 다음 Pod Security Standards를 적용해요:
baseline표준을enforce모드로.restricted표준을warn과audit모드로.
baseline Pod Security Standard는 예외 목록을 짧게 유지하면서 알려진 권한 상승을 막아주는 편리한 중간 지점을 제공해요.
추가로 kube-system에서 파드가 실패하지 않도록, 이 네임스페이스는 Pod Security Standards 적용에서 제외합니다.
여러분의 환경에 Pod Security Admission을 구현할 때는 다음을 고려해보세요:
-
클러스터에 적용된 위험 수준에 따라
restricted같은 더 엄격한 Pod Security Standard가 더 나은 선택일 수 있어요. -
kube-system네임스페이스를 제외하면 이 네임스페이스에서 파드가privileged로 실행될 수 있어요. 실제 운영에서는 쿠버네티스 프로젝트가 최소 권한 원칙에 따라kube-system에 대한 접근을 제한하는 엄격한 RBAC 정책을 적용할 것을 강력히 권장합니다. 앞선 표준을 구현하려면 다음을 수행해요: -
Pod Security Admission Controller가 소비할 수 있는 구성 파일을 만들어 이 Pod Security Standards를 구현한다:
mkdir -p /tmp/pss cat <<EOF > /tmp/pss/cluster-level-pss.yaml apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: PodSecurity configuration: apiVersion: pod-security.admission.config.k8s.io/v1 kind: PodSecurityConfiguration defaults: enforce: "baseline" enforce-version: "latest" audit: "restricted" audit-version: "latest" warn: "restricted" warn-version: "latest" exemptions: usernames: [] runtimeClasses: [] namespaces: [kube-system] EOFpod-security.admission.config.k8s.io/v1구성은 v1.25 이상이 필요해요. v1.23과 v1.24는 v1beta1을, v1.22는 v1alpha1을 사용해요. -
클러스터를 만들 때 API 서버가 이 파일을 소비하도록 구성한다:
cat <<EOF > /tmp/pss/cluster-config.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane kubeadmConfigPatches: - | kind: ClusterConfiguration apiServer: extraArgs: admission-control-config-file: /etc/config/cluster-level-pss.yaml extraVolumes: - name: accf hostPath: /etc/config mountPath: /etc/config readOnly: false pathType: "DirectoryOrCreate" extraMounts: - hostPath: /tmp/pss containerPath: /etc/config # optional: if set, the mount is read-only. # default false readOnly: false # optional: if set, the mount needs SELinux relabeling. # default false selinuxRelabel: false # optional: set propagation mode (None, HostToContainer or Bidirectional) # see https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation # default None propagation: None EOFmacOS에서 kind와 함께 Docker Desktop을 사용한다면 Preferences > Resources > File Sharing 메뉴 아래에서
/tmp를 Shared Directory로 추가할 수 있어요. -
Pod Security Admission이 이 Pod Security Standards를 적용하도록 클러스터를 만든다:
kind create cluster --name psa-with-cluster-pss --config /tmp/pss/cluster-config.yaml출력은 다음과 비슷합니다:
Creating cluster "psa-with-cluster-pss" ... ✓ Ensuring node image (kindest/node:v) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 Set kubectl context to "kind-psa-with-cluster-pss" You can now use your cluster with: kubectl cluster-info --context kind-psa-with-cluster-pss Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂 -
kubectl을 클러스터로 지정한다:
kubectl cluster-info --context kind-psa-with-cluster-pss출력은 다음과 비슷합니다:
Kubernetes control plane is running at https://127.0.0.1:63855 CoreDNS is running at https://127.0.0.1:63855/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. -
default 네임스페이스에 Pod를 만든다:
kubectl apply -f https://k8s.io/examples/security/example-baseline-pod.yaml파드는 정상적으로 시작되지만, 출력에 경고가 포함됩니다:
Warning: would violate 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") pod/nginx created
정리하기
위에서 만든 클러스터를 다음 명령으로 삭제해요:
kind delete cluster --name psa-with-cluster-pss
kind delete cluster --name psa-wo-cluster-pss
더 알아보기 (Learn more)
- 앞선 모든 절차를 한 번에 수행하는 셸 스크립트 실행:
- Pod Security Standards 기반 클러스터 레벨 구성을 만든다.
- API 서버가 이 구성을 소비하도록 파일을 만든다.
- 이 구성으로 API 서버를 가진 클러스터를 만든다.
- kubectl 컨텍스트를 이 새 클러스터로 설정한다.
- 최소 pod yaml 파일을 만든다.
- 이 파일을 적용해 새 클러스터에 Pod를 만든다.
- Pod Security Admission
- Pod Security Standards
- 네임스페이스 레벨에서 Pod Security Standards 적용하기