Skip to content
Published on

CKS (Certified Kubernetes Security Specialist) 실전 모의고사 완전 정복

Authors

1. CKS 시험 개요

CKS(Certified Kubernetes Security Specialist)는 CNCF와 Linux Foundation이 제공하는 고급 Kubernetes 보안 자격증입니다.

항목내용
시험 시간120분
문제 유형15~20개 실기 문제 (퍼포먼스 기반)
합격 기준67% 이상
선행 조건현재 유효한 CKA 자격증
시험 환경원격 감독, 브라우저 기반 터미널
유효 기간2년

도메인별 비율

도메인비율
Cluster Setup10%
Cluster Hardening15%
System Hardening15%
Minimizing Microservice Vulnerabilities20%
Supply Chain Security20%
Monitoring, Logging and Runtime Security20%

2. Kubernetes 보안 핵심 개념 요약

2.1 RBAC (Role-Based Access Control)

RBAC는 Kubernetes API 접근을 제어하는 핵심 메커니즘입니다. Role/ClusterRole은 권한을 정의하고, RoleBinding/ClusterRoleBinding은 그 권한을 주체(user, group, serviceaccount)에 바인딩합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: ['']
    resources: ['pods']
    verbs: ['get', 'watch', 'list']

2.2 Pod Security Standards (PSS)

프로파일설명
Privileged제한 없음, 모든 권한 허용
Baseline최소한의 제한, 알려진 권한 상승 방지
Restricted강력한 보안 정책, 모범 사례 준수

2.3 Network Policy

NetworkPolicy는 Pod 간 트래픽을 L3/L4 수준에서 제어합니다. 기본적으로 모든 트래픽이 허용되며, NetworkPolicy를 적용하면 명시된 트래픽만 허용됩니다.

2.4 Falco 런타임 보안

Falco는 커널 시스템 콜을 모니터링하여 런타임 위협을 탐지합니다. 규칙 기반으로 의심스러운 활동을 감지하고 알림을 보냅니다.

2.5 Supply Chain Security

  • Image Scanning: Trivy, Snyk으로 CVE 취약점 탐지
  • Image Signing: Cosign으로 이미지 서명 및 검증
  • SBOM: 소프트웨어 구성 요소 목록 (Software Bill of Materials)
  • Admission Controllers: ImagePolicyWebhook으로 이미지 정책 강제

3. 개념 이해 문제 (Q1~Q55)

Cluster Setup (Q1~Q10)

Q1. kube-bench는 어떤 표준을 기반으로 Kubernetes 클러스터를 점검합니까?

A) NIST SP 800-190 B) CIS Kubernetes Benchmark C) PCI DSS D) ISO 27001

정답: B

설명: kube-bench는 CIS(Center for Internet Security) Kubernetes Benchmark를 기반으로 클러스터 구성 요소의 보안 설정을 자동으로 점검합니다. 마스터 노드, 워커 노드, etcd, API 서버 등을 검사합니다.

Q2. 다음 중 etcd 데이터를 저장 시(at rest) 암호화하기 위한 올바른 설정 위치는?

A) /etc/kubernetes/manifests/kube-apiserver.yaml--etcd-encryption-key 플래그 B) /etc/kubernetes/encryption-config.yaml을 kube-apiserver의 --encryption-provider-config로 지정 C) etcd의 --cipher-suites 플래그 D) kubelet의 --encrypt-data 플래그

정답: B

설명: etcd at-rest 암호화는 EncryptionConfiguration 리소스를 yaml 파일로 작성하고, kube-apiserver의 --encryption-provider-config 플래그로 해당 파일을 지정하여 활성화합니다. Secrets, ConfigMaps 등 특정 리소스 유형에 대해 암호화 프로바이더(aescbc, aesgcm, secretbox 등)를 설정합니다.

Q3. Kubernetes Ingress에 TLS를 구성할 때 인증서와 키는 어디에 저장해야 합니까?

A) ConfigMap B) Secret (type: kubernetes.io/tls) C) PersistentVolume D) ServiceAccount token

정답: B

설명: TLS 인증서와 개인키는 kubernetes.io/tls 타입의 Secret에 저장합니다. tls.crt 필드에 인증서, tls.key 필드에 개인키를 base64 인코딩하여 저장하며, Ingress 리소스의 spec.tls 섹션에서 이 Secret을 참조합니다.

Q4. 클라우드 환경에서 Node의 IMDS(Instance Metadata Service)에 Pod가 직접 접근하는 것을 방지하는 가장 적절한 방법은?

A) NetworkPolicy로 169.254.169.254 주소 차단 B) Pod의 hostNetwork: true 설정 C) ServiceAccount automount 비활성화 D) PSP에서 hostPID 금지

정답: A

설명: AWS IMDSv1은 인증 없이 169.254.169.254에 접근하여 IAM 자격증명을 탈취할 수 있습니다. NetworkPolicy로 해당 IP 주소로의 egress를 차단하거나, IMDSv2로 업그레이드하여 hop limit을 1로 설정하면 컨테이너에서의 직접 접근을 방지할 수 있습니다.

Q5. NetworkPolicy를 적용하여 특정 namespace의 Pod만 접근을 허용하려면 어떤 selector를 사용해야 합니까?

A) podSelector B) namespaceSelector C) ipBlock D) serviceSelector

정답: B

설명: namespaceSelector를 사용하면 특정 namespace 레이블을 가진 namespace의 Pod에서 오는 트래픽만 허용할 수 있습니다. podSelector와 함께 사용하면 특정 namespace 내 특정 Pod만 허용하는 세밀한 정책을 만들 수 있습니다.

Q6. kube-bench 실행 결과에서 [FAIL] 항목을 수정할 때 가장 먼저 해야 할 일은?

A) 클러스터를 즉시 재시작 B) 해당 권고사항의 remediation 섹션 확인 C) 새 클러스터 생성 D) etcd 백업 삭제

정답: B

설명: kube-bench 결과의 각 [FAIL] 항목에는 remediation(수정 방법) 섹션이 포함되어 있습니다. 이 섹션에는 구체적인 수정 명령어나 설정 변경 방법이 기술되어 있으므로, 이를 먼저 확인하고 신중하게 적용해야 합니다.

Q7. 다음 중 Kubernetes API 서버에 대한 익명(anonymous) 인증을 비활성화하는 올바른 설정은?

A) --anonymous-auth=false B) --disable-anonymous=true C) --allow-anonymous=false D) --auth-anonymous=disabled

정답: A

설명: kube-apiserver의 --anonymous-auth=false 플래그로 익명 인증을 비활성화할 수 있습니다. 이를 설정하면 인증되지 않은 요청이 system:anonymous 사용자로 처리되지 않고 거부됩니다.

Q8. etcd 클러스터의 피어(peer) 통신을 TLS로 보호하기 위해 필요한 etcd 플래그 조합은?

A) --peer-cert-file, --peer-key-file, --peer-trusted-ca-file B) --tls-cert-file, --tls-key-file C) --client-cert-auth, --trusted-ca-file D) --peer-auth=tls

정답: A

설명: etcd 피어 통신 TLS는 --peer-cert-file(피어 인증서), --peer-key-file(피어 개인키), --peer-trusted-ca-file(피어 CA 인증서) 세 가지 플래그로 설정합니다. --peer-client-cert-auth=true도 함께 설정하면 피어 클라이언트 인증도 강제할 수 있습니다.

Q9. Kubernetes 감사 로그(Audit Log)에서 RequestResponse 레벨로 기록하면 어떤 정보가 포함됩니까?

A) 이벤트 메타데이터만 B) 요청 메타데이터와 요청 본문 C) 메타데이터, 요청 본문, 응답 본문 모두 D) 응답 본문만

정답: C

설명: 감사 로그 레벨은 None, Metadata, Request, RequestResponse 4단계입니다. RequestResponse는 가장 상세한 레벨로 이벤트 메타데이터, 요청 본문(request body), 응답 본문(response body)을 모두 기록합니다. 다만 데이터 양이 많아 스토리지 비용이 높습니다.

Q10. 다음 중 CIS Benchmark에서 권장하는 kube-apiserver의 admission controller 설정은?

A) AlwaysAllow B) NodeRestriction, PodSecurityAdmission 포함 C) AlwaysDeny D) LimitRanger만 활성화

정답: B

설명: CIS Benchmark는 NodeRestriction(노드가 자신의 리소스만 수정 가능), PodSecurityAdmission(PSS 정책 적용), ResourceQuota, LimitRanger 등 보안 강화 admission controller를 활성화할 것을 권장합니다.

Cluster Hardening (Q11~Q22)

Q11. ServiceAccount의 토큰이 자동으로 Pod에 마운트되지 않도록 하려면 어떻게 설정합니까?

A) ServiceAccount에 automountServiceAccountToken: false 설정 B) Pod spec에 serviceAccountName: none 설정 C) RBAC에서 serviceaccount 리소스를 삭제 D) Secret 삭제

정답: A

설명: ServiceAccount 리소스에 automountServiceAccountToken: false를 설정하거나, Pod spec에 automountServiceAccountToken: false를 설정하면 ServiceAccount 토큰이 자동으로 마운트되지 않습니다. Pod 레벨 설정이 ServiceAccount 레벨 설정을 오버라이드합니다.

Q12. 최소 권한 원칙(Principle of Least Privilege)에 따라 RBAC를 구성할 때 올바른 접근 방식은?

A) cluster-admin ClusterRole을 모든 ServiceAccount에 바인딩 B) 필요한 리소스와 동사(verbs)만 포함하는 맞춤형 Role 생성 C) RBAC를 비활성화하고 ABAC 사용 D) 모든 리소스에 wildcard(*) 사용

정답: B

설명: 최소 권한 원칙은 필요한 작업에 최소한의 권한만 부여하는 것입니다. 특정 namespace의 특정 리소스에 대한 특정 동사만 허용하는 맞춤형 Role을 만들고, 필요한 주체에만 RoleBinding을 통해 부여해야 합니다.

Q13. kubelet 인증을 강화하기 위해 설정해야 하는 kubelet 플래그는?

A) --authentication-token-webhook=true, --authorization-mode=Webhook B) --anonymous-auth=true C) --read-only-port=10255 D) --allow-all-requests=true

정답: A

설명: kubelet 보안 강화를 위해 --anonymous-auth=false로 익명 접근을 차단하고, --authentication-token-webhook=true로 토큰 웹훅 인증을 활성화하며, --authorization-mode=Webhook으로 API 서버를 통한 권한 부여를 설정합니다.

Q14. Kubernetes 버전 업그레이드 주기가 보안에 중요한 이유는?

A) 새 기능 추가를 위해 B) CVE 취약점 패치 및 보안 픽스 적용 C) 성능 향상을 위해 D) kubectl 버전 호환성

정답: B

설명: Kubernetes는 마이너 버전을 약 4개월 주기로 릴리스하며, 각 버전은 약 14개월간 지원됩니다. 업그레이드하지 않으면 CVE(Common Vulnerabilities and Exposures) 취약점이 패치되지 않아 보안 위험이 증가합니다. CKS 시험에서는 최신 지원 버전 유지를 권장합니다.

Q15. 다음 ClusterRoleBinding이 위험한 이유는?
subjects:
  - kind: Group
    name: system:authenticated
roleRef:
  kind: ClusterRole
  name: cluster-admin

A) subjects 필드가 잘못됨 B) 인증된 모든 사용자에게 cluster-admin 권한 부여 C) ClusterRoleBinding 이름이 없음 D) apiGroup이 누락됨

정답: B

설명: system:authenticated 그룹은 인증된 모든 사용자를 포함합니다. 이 그룹에 cluster-admin을 바인딩하면 클러스터에 접근 가능한 모든 사용자가 최고 권한을 갖게 됩니다. 마찬가지로 system:unauthenticated에 권한을 부여하는 것도 매우 위험합니다.

Q16. Audit Policy에서 특정 리소스의 변경(create/update/delete)만 기록하고 get/list는 제외하려면?

A) rules의 verbs 필드에 원하는 동사만 지정 B) resourceNames 필드 사용 C) namespace 필드로 필터링 D) level을 None으로 설정

정답: A

설명: Audit Policy의 rules에서 verbs 필드를 사용하여 특정 HTTP 동사에 대해서만 로깅할 수 있습니다. 예를 들어 verbs: ["create", "update", "delete", "patch"]로 설정하면 변경 작업만 감사 로그에 기록됩니다.

Q17. kubelet의 read-only 포트(기본 10255)를 비활성화하려면?

A) --read-only-port=0 B) --disable-readonly=true C) --secure-port=0 D) --port=0

정답: A

설명: --read-only-port=0으로 설정하면 kubelet의 읽기 전용 HTTP 포트(기본 10255)가 비활성화됩니다. 이 포트는 인증 없이 Pod 정보와 메트릭을 노출하므로 비활성화하는 것이 보안상 권장됩니다.

Q18. 다음 중 ServiceAccount에 최소 권한을 적용하는 모범 사례로 올바른 것은?

A) 모든 Pod가 default ServiceAccount 사용 B) 각 애플리케이션 전용 ServiceAccount 생성, 필요 최소 권한만 부여 C) cluster-admin을 모든 ServiceAccount에 부여 D) RBAC 대신 파일 기반 접근 제어 사용

정답: B

설명: 각 워크로드에 맞는 전용 ServiceAccount를 생성하고, 해당 애플리케이션이 실제로 필요한 리소스와 동사만 허용하는 Role을 만들어 바인딩하는 것이 모범 사례입니다. default ServiceAccount를 공유하면 불필요한 권한이 과다 부여될 수 있습니다.

Q19. kube-apiserver에서 --insecure-port 플래그의 보안상 올바른 설정은?

A) 8080으로 설정 B) 0으로 설정하여 비활성화 C) 443으로 변경 D) TLS 인증서 추가

정답: B

설명: --insecure-port=0으로 설정하면 TLS 없이 인증도 거치지 않는 HTTP 포트를 비활성화합니다. Kubernetes 1.20부터 이 플래그는 deprecated되었고 기본값이 0이지만, 명시적으로 0으로 설정하는 것이 CIS Benchmark 권장사항입니다.

Q20. Node Authorization 모드가 하는 역할은?

A) 모든 사용자에게 노드 접근 허용 B) kubelet이 자신이 실행하는 Pod와 관련된 리소스에만 접근하도록 제한 C) 노드 간 네트워크 통신 암호화 D) 노드의 OS 레벨 접근 제어

정답: B

설명: Node Authorization 모드는 kubelet이 API 서버에 접근할 때 자신의 노드에서 실행 중인 Pod에 필요한 리소스(Secrets, ConfigMaps, PersistentVolumes 등)에만 접근하도록 제한합니다. --authorization-mode=Node,RBAC로 함께 사용하는 것이 권장됩니다.

Q21. Kubernetes CertificateSigningRequest(CSR)를 통해 사용자 인증서를 발급하는 올바른 순서는?

A) CSR 생성 → approve → CSR 오브젝트 생성 → 인증서 추출 B) 개인키 생성 → CSR 파일 생성 → CSR 오브젝트 생성 → approve → 인증서 추출 C) CA 직접 서명 → kubeconfig 설정 D) ServiceAccount 토큰 사용

정답: B

설명: 올바른 순서는 1) openssl로 개인키 생성, 2) CSR 파일 생성, 3) base64 인코딩하여 CertificateSigningRequest 오브젝트 생성, 4) kubectl certificate approve로 승인, 5) kubectl get csr -o jsonpath='{.status.certificate}'로 인증서 추출입니다.

Q22. kubectl auth can-i 명령어는 어떤 용도로 사용합니까?

A) 클러스터 인증서 갱신 B) 특정 사용자/ServiceAccount가 특정 작업을 수행할 수 있는지 확인 C) RBAC 규칙 적용 D) 감사 로그 확인

정답: B

설명: kubectl auth can-i get pods --namespace default처럼 사용하여 현재 사용자가 특정 작업을 할 수 있는지 확인합니다. --as 플래그로 다른 사용자를 가장하여 확인할 수도 있습니다. RBAC 설정 검증에 매우 유용합니다.

System Hardening (Q23~Q32)

Q23. AppArmor 프로파일을 Pod에 적용하기 위한 annotation 형식은?

A) security.alpha.kubernetes.io/apparmor: runtime/default B) container.apparmor.security.beta.kubernetes.io/CONTAINER_NAME: localhost/PROFILE_NAME C) apparmor.kubernetes.io/profile: enforced D) securityContext.appArmorProfile: localhost/custom

정답: B

설명: Kubernetes 1.30 이전에는 container.apparmor.security.beta.kubernetes.io/컨테이너이름: localhost/프로파일이름 annotation으로 AppArmor를 적용했습니다. 1.30부터는 securityContext.appArmorProfile 필드를 사용합니다. 프로파일은 노드에 미리 로드되어 있어야 합니다.

Q24. Seccomp 프로파일 RuntimeDefault를 Pod에 적용하는 올바른 방법은?

A) Pod annotation으로만 설정 B) securityContext.seccompProfile.type: RuntimeDefault C) 별도 CRD 생성 필요 D) Node 레벨에서만 설정 가능

정답: B

설명: Kubernetes 1.19부터 securityContext.seccompProfile 필드로 Seccomp를 설정할 수 있습니다. type: RuntimeDefault는 컨테이너 런타임의 기본 Seccomp 프로파일을 사용하며, type: Localhost로 사용자 정의 프로파일을 지정할 수도 있습니다.

Q25. 다음 중 컨테이너 내부에서 실행되는 프로세스의 OS 레벨 보안을 강화하는 도구는?

A) NetworkPolicy B) RBAC C) AppArmor, Seccomp D) PodDisruptionBudget

정답: C

설명: AppArmor는 MAC(Mandatory Access Control)으로 프로세스가 접근할 수 있는 파일, 네트워크, 기능을 제한합니다. Seccomp는 프로세스가 호출할 수 있는 시스템 콜을 제한합니다. 두 도구 모두 컨테이너 내 프로세스의 OS 레벨 행동을 제한합니다.

Q26. 노드에서 불필요한 서비스와 포트를 확인하는 명령어로 적절한 것은?

A) kubectl describe node B) ss -tlnp 또는 netstat -tlnp C) docker ps D) journalctl -u kubelet

정답: B

설명: ss -tlnp(소켓 통계) 또는 netstat -tlnp 명령어로 현재 노드에서 리스닝 중인 TCP 포트와 해당 프로세스를 확인할 수 있습니다. 불필요한 서비스가 포트를 열고 있다면 비활성화하거나 제거해야 합니다.

Q27. Linux capability를 제거하여 컨테이너의 권한을 제한하는 securityContext 설정은?

A) securityContext.privileged: false B) securityContext.capabilities.drop: ["ALL"] C) securityContext.runAsRoot: false D) securityContext.allowPrivilegeEscalation: false

정답: B

설명: securityContext.capabilities.drop: ["ALL"]로 모든 Linux capability를 제거하고, capabilities.add로 필요한 capability만 선택적으로 추가하는 것이 모범 사례입니다. allowPrivilegeEscalation: false와 함께 사용하면 더욱 강화됩니다.

Q28. gVisor(runsc)를 사용하는 RuntimeClass를 Pod에 적용하는 방법은?

A) spec.runtimeClassName: gvisor B) spec.securityContext.runtime: gvisor C) annotation으로 설정 D) Node label로 자동 선택

정답: A

설명: RuntimeClass 오브젝트를 먼저 생성(handler: runsc)한 후, Pod spec의 runtimeClassName 필드로 해당 RuntimeClass를 지정합니다. gVisor는 사용자 공간 커널을 구현하여 컨테이너를 샌드박싱하므로 호스트 커널과 격리됩니다.

Q29. AWS에서 Pod에 IAM 권한을 부여하는 권장 방법(IRSA)은?

A) 노드 IAM 역할에 모든 권한 부여 B) Access Key/Secret Key를 Secret에 저장 C) OIDC Provider와 ServiceAccount annotation으로 IAM Role 연결 D) EC2 인스턴스 프로파일만 사용

정답: C

설명: IRSA(IAM Roles for Service Accounts)는 EKS OIDC Provider를 사용하여 Kubernetes ServiceAccount를 IAM Role과 연결합니다. eks.amazonaws.com/role-arn annotation을 ServiceAccount에 추가하면 해당 SA를 사용하는 Pod에만 특정 IAM 권한이 부여됩니다.

Q30. 컨테이너의 파일시스템을 읽기 전용으로 설정하는 securityContext 필드는?

A) securityContext.immutable: true B) securityContext.readOnlyRootFilesystem: true C) securityContext.noWrite: true D) volumeMounts.readOnly: true

정답: B

설명: securityContext.readOnlyRootFilesystem: true를 설정하면 컨테이너의 루트 파일시스템이 읽기 전용이 됩니다. 공격자가 컨테이너 내부에 악성 파일을 생성하거나 바이너리를 변조하는 것을 방지합니다. 쓰기가 필요한 경로는 emptyDir 볼륨으로 마운트합니다.

Q31. 다음 중 컨테이너가 root로 실행되지 않도록 강제하는 설정은?

A) securityContext.runAsUser: 0 B) securityContext.runAsNonRoot: true C) securityContext.privileged: false D) RBAC로 제어

정답: B

설명: securityContext.runAsNonRoot: true를 설정하면 컨테이너가 root(UID 0)로 실행되려 할 때 Kubernetes가 이를 차단합니다. runAsUser: 1000처럼 특정 UID를 지정하는 것도 좋은 방법입니다.

Q32. 다음 중 Kata Containers의 특징으로 올바른 것은?

A) 커널 공유하는 일반 컨테이너 격리 B) 각 컨테이너/Pod가 경량 VM과 독립 커널로 실행 C) 네트워크 격리만 제공 D) Seccomp 프로파일 기반 격리

정답: B

설명: Kata Containers는 각 컨테이너(또는 Pod)를 경량 VM 위에서 실행합니다. 각 워크로드가 독립적인 커널을 가지므로 커널 취약점을 통한 컨테이너 탈출이 극도로 어렵습니다. gVisor와 달리 실제 Linux 커널을 사용합니다.

Minimizing Microservice Vulnerabilities (Q33~42)

Q33. Pod Security Admission(PSA)에서 enforce 모드와 warn 모드의 차이점은?

A) 차이 없음 B) enforce는 정책 위반 Pod를 거부, warn은 경고만 표시하고 허용 C) warn이 더 엄격 D) enforce는 기존 Pod에도 소급 적용

정답: B

설명: PSA의 세 가지 모드 중 enforce는 정책을 위반하는 Pod 생성을 거부합니다. warn은 위반 시 경고 메시지를 반환하지만 Pod는 생성됩니다. audit는 감사 로그에 기록하지만 역시 Pod는 허용됩니다.

Q34. OPA Gatekeeper와 Kyverno의 공통점은?

A) 동일한 정책 언어 사용 B) Kubernetes admission webhook으로 동작하여 정책을 강제 C) 런타임 모니터링 도구 D) 네트워크 정책 관리

정답: B

설명: OPA Gatekeeper와 Kyverno 모두 Kubernetes ValidatingAdmissionWebhook으로 동작하여 리소스 생성/수정 시 정책을 검사하고 위반 시 거부합니다. Gatekeeper는 Rego 언어를, Kyverno는 YAML 기반 정책을 사용한다는 차이가 있습니다.

Q35. mTLS(mutual TLS)를 서비스 메시(Istio)에서 활성화할 때의 이점은?

A) 성능 향상 B) 서비스 간 통신의 양방향 인증 및 암호화 C) 외부 트래픽 차단 D) 데이터베이스 암호화

정답: B

설명: mTLS는 클라이언트와 서버 모두 인증서로 서로를 인증합니다. Istio에서 PeerAuthentication 리소스로 STRICT mTLS를 설정하면 서비스 간 모든 통신이 암호화되고, 인증된 서비스만 통신할 수 있어 측면 이동(lateral movement) 공격을 방지합니다.

Q36. Kubernetes Secrets를 더 안전하게 관리하는 방법으로 올바르지 않은 것은?

A) etcd at-rest 암호화 활성화 B) Vault나 Sealed Secrets 사용 C) Secrets를 Git 저장소에 평문으로 저장 D) RBAC로 Secrets 접근 제한

정답: C

설명: Secrets를 Git에 평문으로 저장하는 것은 매우 위험합니다. 올바른 방법은 etcd 암호화, Bitnami Sealed Secrets(암호화된 SealedSecret을 Git에 저장), HashiCorp Vault(동적 시크릿 관리), AWS Secrets Manager 연동 등입니다.

Q37. Restricted Pod Security Standard를 위반하는 설정은?

A) runAsNonRoot: true B) seccompProfile.type: RuntimeDefault C) privileged: true D) capabilities.drop: ["ALL"]

정답: C

설명: Restricted PSS는 가장 엄격한 프로파일로 privileged: true, hostNetwork, hostPID, hostIPC 사용 금지, 특정 capability 추가 금지, runAsNonRoot 필수 등을 요구합니다. privileged: true는 Privileged PSS에서만 허용됩니다.

Q38. PodSecurityPolicy(PSP)가 deprecated된 이유와 대체재는?

A) 성능 문제로 인해, RuntimeClass로 대체 B) 복잡성과 권한 상승 위험으로 인해, Pod Security Admission으로 대체 C) 기능 부족으로 인해, OPA로 대체 D) etcd 호환성 문제

정답: B

설명: PSP는 Kubernetes 1.21에서 deprecated, 1.25에서 제거되었습니다. PSP를 사용하려면 서비스에 ClusterRole을 통한 PSP use 권한이 필요했는데, 이 과정에서 권한 상승이 발생할 수 있었고 설정이 복잡했습니다. 대체재는 Pod Security Admission(PSA)이며, OPA Gatekeeper나 Kyverno도 사용됩니다.

Q39. 다음 중 컨테이너 샌드박싱(sandboxing) 기술이 아닌 것은?

A) gVisor B) Kata Containers C) Firecracker D) Calico

정답: D

설명: gVisor, Kata Containers, Firecracker는 컨테이너 격리를 강화하는 샌드박싱 기술입니다. Calico는 CNI 네트워크 플러그인으로 네트워크 정책을 구현하는 도구이며 샌드박싱 기술이 아닙니다.

Q40. Istio의 AuthorizationPolicy를 사용하는 목적은?

A) 인증서 자동 갱신 B) 서비스 간 접근 제어(누가 누구에게 요청 가능한지 정의) C) 트래픽 로드 밸런싱 D) 컨테이너 이미지 스캔

정답: B

설명: Istio AuthorizationPolicy는 서비스 메시 내에서 L7 수준의 접근 제어를 구현합니다. 특정 서비스, 경로, 메서드에 대해 어떤 서비스/사용자가 접근할 수 있는지 정의합니다. mTLS와 함께 사용하면 Zero Trust 네트워킹을 구현할 수 있습니다.

Q41. Kubernetes에서 Secret을 환경 변수로 사용할 때의 보안 위험은?

A) 성능 저하 B) 프로세스 환경에 노출되어 proc/PID/environ으로 읽히거나 로그에 출력될 위험 C) 크기 제한 D) 타입 제한

정답: B

설명: 환경 변수는 프로세스의 /proc/PID/environ을 통해 읽을 수 있고, 애플리케이션이 실수로 환경 변수를 로그에 출력할 수 있습니다. 볼륨 마운트 방식이 더 안전하며, 특히 Vault Agent Injector나 CSI Secret Store 방식을 권장합니다.

Q42. 다음 중 Zero Trust 보안 모델을 Kubernetes에서 구현하는 방법은?

A) 방화벽만 사용 B) mTLS + RBAC + NetworkPolicy + PSA 조합 C) VPN만 사용 D) 물리적 네트워크 분리

정답: B

설명: Zero Trust는 "신뢰하지 말고 항상 검증하라"는 원칙입니다. Kubernetes에서는 mTLS(서비스 간 인증), RBAC(최소 권한), NetworkPolicy(네트워크 마이크로세그멘테이션), PSA(워크로드 보안 표준)를 조합하여 구현합니다.

Supply Chain Security (Q43~52)

Q43. Trivy로 컨테이너 이미지를 스캔하는 명령어는?

A) trivy scan IMAGE_NAME B) trivy image IMAGE_NAME C) trivy check IMAGE_NAME D) trivy docker IMAGE_NAME

정답: B

설명: trivy image nginx:latest처럼 trivy image 서브커맨드를 사용합니다. CVE 데이터베이스를 기반으로 이미지의 OS 패키지, 언어별 의존성 등의 취약점을 스캔합니다. --severity HIGH,CRITICAL로 심각도 필터링도 가능합니다.

Q44. ImagePolicyWebhook admission controller의 역할은?

A) 이미지를 자동으로 최신 버전으로 업데이트 B) 외부 웹훅 서비스에 이미지 허용 여부를 질의 C) 이미지 취약점 자동 수정 D) 이미지 크기 제한

정답: B

설명: ImagePolicyWebhook은 Pod 생성 시 외부 웹훅 서비스에 이미지 사용 허용 여부를 질의합니다. 웹훅 서비스는 이미지 스캔 결과, 서명 검증, 레지스트리 정책 등을 기반으로 허용/거부를 응답합니다.

Q45. Cosign으로 컨테이너 이미지에 서명하는 명령어는?

A) cosign sign --key cosign.key IMAGE_DIGEST B) cosign create-signature IMAGE C) docker sign IMAGE D) kubectl sign image IMAGE

정답: A

설명: cosign sign --key cosign.key IMAGE@sha256:DIGEST로 이미지에 서명합니다. 서명은 OCI 레지스트리에 별도 태그로 저장됩니다. cosign verify --key cosign.pub IMAGE로 검증하며, Kyverno 정책으로 서명된 이미지만 허용하도록 강제할 수 있습니다.

Q46. SBOM(Software Bill of Materials)이란?

A) 소프트웨어 라이선스 목록 B) 소프트웨어를 구성하는 모든 컴포넌트, 라이브러리, 의존성 목록 C) 소프트웨어 비용 명세서 D) 소프트웨어 배포 계획서

정답: B

설명: SBOM은 소프트웨어에 포함된 모든 오픈소스 및 독점 컴포넌트, 버전, 라이선스, 취약점 정보를 담은 목록입니다. CycloneDX, SPDX 형식이 표준으로 사용됩니다. 공급망 공격 방지와 취약점 추적에 필수적입니다.

Q47. Distroless 이미지를 사용하는 보안상 이점은?

A) 이미지 크기가 작아 빌드 속도 향상 B) 쉘, 패키지 관리자 등 불필요한 도구 제거로 공격 표면 최소화 C) 무료로 사용 가능 D) CI/CD 파이프라인 통합 용이

정답: B

설명: Distroless 이미지는 애플리케이션 실행에 필요한 런타임만 포함하고 쉘(/bin/sh), 패키지 관리자, 불필요한 유틸리티가 없습니다. 공격자가 컨테이너에 침입해도 활용할 수 있는 도구가 없어 피해를 최소화할 수 있습니다.

Q48. ValidatingWebhookConfiguration을 사용하여 특정 레이블이 없는 Pod를 차단하려면?

A) RBAC 규칙 추가 B) webhook 서비스가 admission review 요청을 검사하고 거부 응답 C) NetworkPolicy 설정 D) Pod 삭제 컨트롤러 배포

정답: B

설명: ValidatingWebhookConfiguration은 리소스 생성/수정 시 외부 webhook 서비스에 AdmissionReview 요청을 보냅니다. webhook 서비스는 요청을 검사하여 allowed: false와 메시지를 반환하면 Kubernetes API 서버가 리소스 생성을 거부합니다.

Q49. 컨테이너 이미지에 latest 태그를 사용하지 않아야 하는 이유는?

A) latest 태그가 deprecated됨 B) 재현성 부재, 어떤 이미지 버전이 실행 중인지 알 수 없음 C) 레지스트리 용량 낭비 D) 빌드 속도 저하

정답: B

설명: latest 태그는 변경 가능(mutable)하여 동일한 태그로 다른 이미지가 푸시될 수 있습니다. 이로 인해 배포 재현성이 없고, 보안 취약점이 있는 이미지가 latest로 배포될 수 있습니다. 항상 SHA256 다이제스트나 고정된 버전 태그를 사용해야 합니다.

Q50. Kyverno 정책으로 latest 태그 사용을 금지하는 정책 유형은?

A) MutatePolicy B) ClusterPolicy with validate rule C) GeneratePolicy D) SyncPolicy

정답: B

설명: Kyverno ClusterPolicyvalidate 규칙으로 이미지 태그가 latest인 경우를 거부할 수 있습니다. deny 조건에서 이미지 태그를 검사하고 위반 시 message와 함께 거부합니다. mutate 규칙으로 이미지를 자동 변환할 수도 있습니다.

Q51. 다음 중 소프트웨어 공급망 공격(Supply Chain Attack)의 예시가 아닌 것은?

A) SolarWinds 해킹 B) 악성 npm 패키지 배포 C) DDoS 공격 D) 의존성 혼동 공격(Dependency Confusion)

정답: C

설명: 공급망 공격은 소프트웨어 개발/배포 파이프라인의 취약점을 이용합니다. SolarWinds 빌드 서버 침해, 악성 npm/PyPI 패키지, Dependency Confusion(사설 패키지명으로 공개 패키지 배포)이 대표적 예시입니다. DDoS는 가용성 공격으로 공급망 공격이 아닙니다.

Q52. 컨테이너 레지스트리에서 이미지를 pull할 때 인증하는 Kubernetes 리소스는?

A) ServiceAccount B) imagePullSecret C) ConfigMap D) PersistentVolumeClaim

정답: B

설명: 프라이빗 레지스트리 인증을 위해 docker-registry 타입의 Secret을 생성하고, Pod spec의 imagePullSecrets에 참조하거나 ServiceAccount의 imagePullSecrets에 추가합니다. 이렇게 하면 해당 SA를 사용하는 모든 Pod가 자동으로 인증됩니다.

Monitoring, Logging and Runtime Security (Q53~55)

Q53. Falco 규칙에서 컨테이너 내에서 쉘이 실행될 때 알림을 생성하는 조건은?

A) evt.type=connect and fd.type=ipv4 B) evt.type=execve and container.id!=host and proc.name in (sh, bash, zsh) C) evt.type=open and fd.name contains /etc/passwd D) evt.type=write and fd.name startswith /tmp

정답: B

설명: Falco에서 execve 이벤트 타입은 새 프로세스 실행을 의미합니다. container.id!=host는 컨테이너 내부를 의미하고, proc.name in (sh, bash, zsh)는 쉘 프로세스를 필터링합니다. 기본 제공 규칙 Terminal shell in container가 이 패턴을 사용합니다.

Q54. Kubernetes Audit Policy에서 kube-system namespace의 Secrets에 대한 get 요청을 기록하지 않으려면?

A) audit policy에서 해당 규칙을 제거 B) 해당 리소스/namespace/동사에 level: None 규칙을 먼저 작성 C) kube-system namespace 삭제 D) Secrets 타입 변경

정답: B

설명: Audit Policy는 규칙을 순서대로 평가하여 첫 번째 매칭 규칙을 적용합니다. level: None으로 특정 조건을 건너뛰려면 해당 규칙을 다른 규칙보다 먼저(상위에) 작성해야 합니다. 예를 들어 kube-system secrets의 get 요청을 제외할 때는 level: None, resources: secrets, namespaces: kube-system, verbs: get 규칙을 파일 상단에 작성합니다.

Q55. 침해된 Pod를 발견했을 때 올바른 대응 순서는?

A) 즉시 삭제 후 재배포 B) 증거 수집(로그, 포렌식) → Pod 격리(NetworkPolicy) → 침해 범위 파악 → 수정 및 재배포 C) 노드 재시작 D) 클러스터 전체 재배포

정답: B

설명: 침해 대응의 올바른 순서는 1) 증거 보존(로그 수집, 메모리 덤프), 2) 추가 피해 방지를 위해 NetworkPolicy로 해당 Pod의 네트워크 격리, 3) 침해 경로와 범위 파악, 4) 취약점 수정 후 새 이미지 빌드 및 배포입니다. 즉시 삭제하면 포렌식 증거를 잃게 됩니다.


4. 실기 시나리오 (P1~P10)

P1. NetworkPolicy로 Pod 격리 설정

# 특정 namespace의 Pod만 DB에 접근 허용하는 NetworkPolicy 작성
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-app-only
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
      podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 5432
EOF

P2. ServiceAccount 보안 강화

# 1. 전용 ServiceAccount 생성 (automount 비활성화)
kubectl create serviceaccount app-sa -n default

kubectl patch serviceaccount app-sa -n default -p '{"automountServiceAccountToken": false}'

# 2. 필요한 권한만 부여하는 Role 생성
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]
EOF

# 3. RoleBinding
kubectl create rolebinding app-binding \
  --role=app-role \
  --serviceaccount=default:app-sa \
  -n default

# 4. 권한 확인
kubectl auth can-i get configmaps \
  --as=system:serviceaccount:default:app-sa \
  -n default

P3. etcd 암호화 설정

# 1. 암호화 키 생성
head -c 32 /dev/urandom | base64

# 2. EncryptionConfiguration 작성
cat <<EOF > /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <BASE64_32BYTE_KEY>
  - identity: {}
EOF

# 3. kube-apiserver manifest 수정 (/etc/kubernetes/manifests/kube-apiserver.yaml)
# --encryption-provider-config=/etc/kubernetes/encryption-config.yaml 추가

# 4. 기존 Secrets를 새로 암호화 (re-encrypt)
kubectl get secrets --all-namespaces -o json | kubectl replace -f -

# 5. etcd에서 직접 확인 (암호화되어 읽을 수 없어야 함)
ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  get /registry/secrets/default/my-secret

P4. AppArmor 프로파일 적용

# 1. 노드에 AppArmor 프로파일 확인
ssh worker-node-1 "aa-status"

# 2. 커스텀 프로파일 파일 생성 (노드에서)
cat <<EOF > /etc/apparmor.d/k8s-custom-profile
#include <tunables/global>

profile k8s-custom-profile flags=(attach_disconnected) {
  #include <abstractions/base>
  file,
  deny /etc/shadow r,
  deny /proc/** w,
}
EOF

# 3. 프로파일 로드
apparmor_parser -r /etc/apparmor.d/k8s-custom-profile

# 4. Pod에 AppArmor 적용 (Kubernetes 1.30 이전)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: secured-pod
  annotations:
    container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-custom-profile
spec:
  containers:
  - name: app
    image: nginx:alpine
EOF

P5. Falco 규칙 커스터마이징

# /etc/falco/rules.d/custom-rules.yaml
- rule: Detect Shell in Container
  desc: Alert when a shell is spawned in a container
  condition: >
    spawned_process and
    container and
    proc.name in (shell_binaries)
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
    image=%container.image.repository proc=%proc.name
    parent=%proc.pname cmdline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, cks]

- rule: Sensitive File Access
  desc: Detect access to sensitive files
  condition: >
    open_read and
    (fd.name in (/etc/shadow, /etc/sudoers) or
     fd.name startswith /root/.ssh)
  output: >
    Sensitive file accessed
    (user=%user.name file=%fd.name
    container=%container.name proc=%proc.name)
  priority: CRITICAL
  tags: [filesystem, sensitive, cks]
# Falco 재시작 후 규칙 확인
systemctl restart falco
falco --list | grep "Detect Shell"

P6. Pod Security Admission 설정

# namespace에 PSA 레이블 설정
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

# Restricted PSS 준수 Pod 예시
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    volumeMounts:
    - name: tmp
      mountPath: /tmp
    - name: var-cache
      mountPath: /var/cache/nginx
    - name: var-run
      mountPath: /var/run
  volumes:
  - name: tmp
    emptyDir: {}
  - name: var-cache
    emptyDir: {}
  - name: var-run
    emptyDir: {}
EOF

P7. Trivy를 사용한 이미지 스캔

# 이미지 스캔 (HIGH, CRITICAL만)
trivy image --severity HIGH,CRITICAL nginx:latest

# JSON 형식으로 출력
trivy image -f json -o scan-result.json nginx:latest

# 파일시스템 스캔
trivy fs --security-checks vuln,secret /path/to/project

# Kubernetes cluster 스캔
trivy k8s --report summary cluster

# CI/CD 파이프라인에서 취약점 발견 시 실패처리
trivy image --exit-code 1 --severity CRITICAL myapp:latest

P8. Audit Policy 설정

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # kube-system의 ServiceAccount token 요청은 기록 안 함
  - level: None
    resources:
      - group: ''
        resources: ['secrets']
    namespaces: ['kube-system']
    verbs: ['get']

  # Secrets에 대한 모든 접근 상세 기록
  - level: RequestResponse
    resources:
      - group: ''
        resources: ['secrets']

  # Pod 변경사항 기록
  - level: Request
    resources:
      - group: ''
        resources: ['pods']
    verbs: ['create', 'update', 'patch', 'delete']

  # 그 외 모든 요청 메타데이터만 기록
  - level: Metadata
    omitStages:
      - RequestReceived
# kube-apiserver에 audit policy 적용 (manifest 수정)
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# --audit-log-maxage=30
# --audit-log-maxbackup=10
# --audit-log-maxsize=100

P9. gVisor RuntimeClass 설정

# 1. containerd에 gVisor 설정 확인 (/etc/containerd/config.toml)
# [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
#   runtime_type = "io.containerd.runsc.v1"

# 2. RuntimeClass 생성
cat <<EOF | kubectl apply -f -
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
EOF

# 3. gVisor를 사용하는 Pod 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: sandboxed-pod
spec:
  runtimeClassName: gvisor
  containers:
  - name: app
    image: nginx:alpine
EOF

# 4. 샌드박싱 확인
kubectl exec sandboxed-pod -- uname -r
# gVisor 커널 버전이 표시됨

P10. Cosign을 사용한 이미지 서명 및 검증

# 1. 키 쌍 생성
cosign generate-key-pair

# 2. 이미지 빌드 및 push
docker build -t registry.example.com/myapp:v1.0 .
docker push registry.example.com/myapp:v1.0

# 3. 이미지 서명
cosign sign --key cosign.key registry.example.com/myapp:v1.0

# 4. 서명 검증
cosign verify --key cosign.pub registry.example.com/myapp:v1.0

# 5. Kyverno 정책으로 서명된 이미지만 허용
cat <<EOF | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: verify-cosign
    match:
      any:
      - resources:
          kinds: ["Pod"]
    verifyImages:
    - imageReferences: ["registry.example.com/*"]
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              <COSIGN_PUBLIC_KEY>
              -----END PUBLIC KEY-----
EOF

5. 시험 팁

  • 시험 환경: 브라우저 터미널에서 kubectl, crictl, kubeadm, openssl, falco, trivy, cosign 등 사용 가능
  • 빠른 명령어: kubectl config use-context 로 문제별 컨텍스트 전환 필수
  • 북마크: killer.sh, Kubernetes 공식 문서 등 허용된 리소스 적극 활용
  • 우선순위: 배점이 높은 문제부터 풀고 어려운 문제는 나중에
  • 검증: 설정 변경 후 항상 kubectl get, kubectl describe로 검증