Pod Security 는 Pod 내의 컨테이너의 리소스 접근에 제한을 가해서 쿠버네티스의 보안 수준을 올리기 위해서 필요하다.

만약 컨테이너가 많은 권한을 가지도록 하면 쿠버네티스 Pod 가 실행되는 호스트 노드에 다양한 리소스들 (e.g 파일 시스템, 네트워크, 프로세스, CPU/Memory 등) 을 조작할 수 있게 되면서 다른 Pod 나 Service 에 문제를 줄 수 있다.

컨테이너는 격리된 환경이라서 호스트 노드에 어떻게 영향을 줄 수 있는지 궁금할 수 있다. 컨테이너 환경이라도 특권 모드(Privileged Mode) 로 실행된다면 호스트 노드에 접근이 가능하고, 특권 모드가 아니더라도 호스트 노드의 네트워크 네임스페이스를 사용하거나, 호스트 시스템을 마운트하게 되면 접근할 수 있게 된다.

  • 쿠버네티스에서 Pod 를 배포할 때 privilege elevation 을 허용시킬 수 있기 때문에 조심해야한다.

예시를 들면 다음과 같은 문제가 발생할 수 있다:

  • 특권 모드 실행(Privileged Mode Execution):
    • 특권 모드로 실행되는 컨테이너는 호스트 머신의 많은 부분에 대한 거의 무제한 접근 권한을 가직 될 수 있다.
  • 호스트 파일 시스템 접근(Host Filesystem Access):
    • 컨테이너가 호스트 시스템의 파일 시스템에 접근할 수 있다면, 중요한 시스템 파일을 읽거나 수정할 수 있게 된다.
  • 호스트 네트워크 사용(Host Network Usage):
    • 컨테이너가 호스트의 네트워크 네임스페이스를 사용할 수 있게 되면, 네트워크 트래픽을 가로채거나 네트워크 설정을 변경할 수 있게 된다.
  • 프로세스 권한 상승(Process Privilege Escalation):
    • 컨테이너 내부에서 실행되는 프로세스가 더 높은 권한으로 전환할 수 있게 되면, 시스템 전체에 대한 제어를 얻을 수 있게 된다.
  • 리소스 사용 제한(Resource Usage Limits):
    • 컨테이너가 사용할 수 있는 CPU, 메모리 및 기타 리소스를 제한하지 않으면, 한 컨테이너가 과도한 리소스를 소비하여 시스템의 안정성을 해칠 수 있게 된다.

Pod Security 를 달성하는 방법으로 개별 Pod 내에 적용할 수 있는 Security Context 가 있고, 클러스터 내 모든 Pod 에 간편하게 적용할 수 있는 파드 보안 정책 (Pod Security Policy, PSP) 이라는 것도 있다.

하나씩 살펴보자.

Security Context

Security Context 를 통해서 Pod Security 를 달성할 수 있다.

  • 이를 통해 컨테이너가 루트 권한으로 실행되는 것을 막을 수 있다. (루트 권한이 아니기 때문에 시스템 파일에 접근하고 수정할 수 없다.)
    • 시스템 파일이란 운영체제의 작동과 관련된 파일을 말한다.
  • 그리고 컨테이너가 권한 상승을 하지 못하게 막을 수 있고, 루트 파일 시스템을 읽기만 가능하게 만들 수 있다.
  • (루트 권한과 특권 모드는 관련이 있지만 다르다. 루트 권한이 있다고 특권 권한을 얻을 수 있는 건 아니다.)

다음은 Security Context 의 예시이다:

  • 모든 Pod 내 컨테이너는 사용자 Id 1000, 그룹 Id 3000, 파일 시스템 그룹 Id 2000 으로 실행된다.
  • allowPrivilegeEscalation=false 를 통해서 실행되는 example-container 는 권한 상승을 하지 못하게 막았다.
  • readOnlyRootFilesystem=true 를 통해서 루트 파일 시스템을 읽기만 가능하도록 했다.
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: example-container
    image: example-image
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true

Pod Security Policy

파드 보안 정책 (Pod Security Policy, PSP) 는 Security Context 를 매번 Pod 에 적용하기 귀찮으니까 이를 한번에 모든 Pod 에 적용하기 위해서 사용한다.

PSP 는 보안 정책이 담긴 object 와 Pod 가 생성되거나 업데이트 될 때 보안 정책을 검사해주는 admission controller 로 구성된다.

PSP 를 사용하는 예시는 다음과 같다:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: example-psp
spec:
  privileged: false  # 특권 모드 실행을 금지
  # 파드가 실행할 수 있는 Volume
  volumes:
  - 'configMap'
  - 'emptyDir'
  - 'projected'
  - 'secret'
  - 'downwardAPI'
  - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'  # 루트가 아닌 사용자로 실행
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'

PSP 를 작성하더라도 PSP 를 사용할 수 있는 권한이 없다면 이건 제대로 작동하지 않고, Pod 의 생성들에 대해서도 정지시키는 문제가 발생한다.

PSP 에 대한 권한을 주기 위해서 Kubernetes 의 RBAC 를 이용하는 방법이 있다.

다음과 같이 PSP 를 사용할 수 있는 ClusterRole 를 만든다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: psp-example
rules:
- apiGroups: ["policy"]
  resources: ["podsecuritypolicies"]
  resourceNames: ["example-psp"]
  verbs: ["use"]

그리고 다음과 같이 RoleBinding 을 통해서 특정 User, Group, ServiceAccount 에 PSP Role 을 연결시킨다:

  • ServiceAccount 에게 줄 땐 Pod 를 생성할 수 있는 Deployment 나 Replicaset 에게 줘야겠다.
# User 또는 Group 에 RoleBinding 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: psp-example-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: psp-example
subjects:
- kind: User
  name: "example-user"
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: "example-group"
  apiGroup: rbac.authorization.k8s.io
# 특정 네임스페이스의 ServiceAccount 에 연결 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: psp-example-binding
  namespace: example-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: psp-example
subjects:
- kind: ServiceAccount
  name: example-serviceaccount
  namespace: example-namespace

(PSP 는 Kubernetes 1.21 에서 제거되었다. PSP 대신에 유연하게 사용할 수 있는 기술인 Open Policy Agent (OPA) 가 등장했기 때문.)

+ Recent posts