쿠버네티스 클러스터의 컨트롤 플레인노드는 버전이 일치해야만 최적의 성능과 안정성을 보장할 수 있습니다. 이는 단순히 기능적 호환성을 넘어, 클러스터의 보안을 유지하는 데 필수적인 요소입니다.


주요 원인

1. API 버전 호환성 문제

쿠버네티스 API는 지속적으로 발전하며 새로운 기능이 추가되거나 기존 기능이 변경됩니다. 만약 컨트롤 플레인의 API 서버와 각 노드의 Kubelet 버전이 서로 다르면, API 호출이 예상치 않게 실패할 수 있습니다. 예를 들어, 최신 API를 사용하는 컨트롤 플레인이 구형 API만 아는 Kubelet에 명령을 내리면, 명령이 제대로 수행되지 않아 클러스터의 기능적 오류와 더불어 보안 정책에 허점이 생길 수 있습니다.

2. 보안 기능 불일치

새로운 쿠버네티스 버전에는 항상 최신 보안 패치취약점 수정 사항이 포함됩니다. 만약 컨트롤 플레인만 최신 버전으로 업데이트되고 노드는 그대로 남아 있다면, 패치되지 않은 노드가 클러스터의 가장 약한 고리가 됩니다. 공격자는 이 취약한 노드를 통해 클러스터에 침투할 수 있으며, 이는 전체 시스템의 보안을 위협합니다.

3. 인증 및 권한 문제

버전이 다르면 Kubelet과 컨트롤 플레인 간의 통신에서 인증 및 권한 부여 방식에 차이가 발생할 수 있습니다. 이는 Kubelet이 API 서버로부터 필요한 권한을 얻지 못하거나, 반대로 과도한 권한으로 민감한 리소스에 접근하는 문제를 일으킬 수 있습니다. 이러한 문제는 클러스터의 보안 모델을 무너뜨릴 수 있는 심각한 위험을 내포합니다.

4. 기능적 비정상 작동

버전 불일치는 파드 스케줄링, 볼륨 마운트 등 기본적인 클러스터 운영에도 영향을 미칩니다. 컨트롤 플레인에는 존재하는 새로운 기능이 노드에는 없어 정상적으로 작동하지 않거나, 예측 불가능한 오류가 발생할 수 있습니다. 이러한 기능적 불안정성은 클러스터를 취약하게 만들고, 결국 보안 문제로 이어질 수 있습니다.

결론적으로, 컨트롤 플레인과 노드의 버전을 일관되게 유지하는 것은 클러스터의 안정성을 넘어, 최신 보안 기능을 모두에게 적용하고, 불필요한 보안 취약점을 예방하는 가장 핵심적인 보안 관리 방법입니다.

 

적용 방법

https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/upgrading-linux-nodes/

 

Upgrading Linux nodes

This page explains how to upgrade a Linux Worker Nodes created with kubeadm. Before you begin You need to have shell access to all the nodes, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run th

kubernetes.io

 

예시 사진

controlplain 1.33.3

node01 1.33.2

 

1. 노드에서 kubeadm 설치

# replace x in 1.3x.x-* with the latest patch version
sudo apt-mark unhold kubeadm && \
sudo apt-get update && sudo apt-get install -y kubeadm='1.33.3-*' && \
sudo apt-mark hold kubeadm

 

2. 노드에서 kubeadm 을 통한 업그레이드

sudo kubeadm upgrade node

 

3. 컨트롤플레인에서 node drain 적용

kubectl drain node01 --ignore-daemonsets

 

 

4. 노드에서 kubelet 과 kubectl 적용

# replace x in 1.34.x-* with the latest patch version
sudo apt-mark unhold kubelet kubectl && \
sudo apt-get update && sudo apt-get install -y kubelet='1.33.3-*' kubectl='1.33.3-*' && \
sudo apt-mark hold kubelet kubectl

 

5. 노드에서 설정 적용을 위해 재기동

sudo systemctl daemon-reload
sudo systemctl restart kubelet

 

6. 컨트롤플레인에서 버전 확인 후 uncordon 수행

# execute this command on a control plane node
# replace <node-to-uncordon> with the name of your node
kubectl uncordon node01

 

'k8s > CKS' 카테고리의 다른 글

[CKS] Pod Security Standards - restricted  (0) 2025.09.08
[CKS] cilium  (0) 2025.09.08
[CKS] Pod Security Standards  (1) 2025.09.07
[CKS] falco 사용방법 및 샘플 - 2  (0) 2025.09.07
[CKS] falco 사용방법 및 샘플 - 1  (0) 2025.09.07

Pod Security Standards (PSS)는 쿠버네티스에서 파드(Pod)의 보안 수준을 정의하는 일련의 표준입니다. 이는 쿠버네티스 클러스터에서 파드를 실행할 때 따라야 할 권장 보안 정책을 세 가지 프로파일로 구분하여 제공합니다.

이는 과거에 사용되었던 PodSecurityPolicy(PSP)를 대체하며, 쿠버네티스 버전 1.25부터 PodSecurityPolicy가 완전히 제거되면서 PSS가 표준 보안 정책 강제(enforcement) 수단으로 자리 잡았습니다.

PSS는 세 가지 보안 프로파일을 정의합니다.

1. privileged (특권)

  • 정책: 이 프로파일은 제한이 없습니다. 모든 유형의 파드를 허용합니다.
  • 용도: privileged 파드는 호스트의 모든 권한에 접근할 수 있으며, 시스템 유틸리티 파드나 클러스터 관리 에이전트(kube-proxy, calico-node)와 같이 시스템 수준의 작업을 수행해야 하는 워크로드에 사용됩니다.
  • 보안 위험: privileged 파드는 호스트의 루트 권한을 가질 수 있어, 컨테이너 탈출(Container Breakout)과 같은 심각한 보안 취약점을 야기할 수 있습니다. 일반적인 애플리케이션에는 절대 사용해서는 안 됩니다.

2. baseline (기본)

  • 정책: 이 프로파일은 알려진 권한 상승(privilege escalation)을 방지하기 위한 최소한의 제한을 적용합니다.
  • 용도: 일반적인 애플리케이션 개발자에게 충분한 유연성을 제공하면서도, 주요 보안 위협을 방지하는 기본 보안 수준을 제공합니다.
  • 주요 제한 사항:
    • hostPath 볼륨 사용 금지
    • privileged 컨테이너 실행 금지
    • HostPID, HostIPC, HostNetwork 사용 금지
    • allowPrivilegeEscalation 필드 false 강제

3. restricted (제한됨)

  • 정책: 이 프로파일은 baseline보다 더 엄격한 제한을 적용하여 최고 수준의 파드 강화(hardening)를 목표로 합니다.
  • 용도: 보안에 매우 민감한 애플리케이션이나, 권한이 최소화된(least-privilege) 환경에 사용됩니다.
  • 주요 제한 사항:
    • baseline의 모든 제한 사항 포함
    • 컨테이너가 루트(root) 사용자로 실행되는 것을 금지 (runAsNonRoot: true 강제)
    • CAPABILITIES를 기본값으로 제한 (불필요한 기능 제거)
    • hostPath와 유사한 volume 타입 제한 (defaultMode, projected 등)

Pod Security Admission과의 관계

Pod Security Standards(PSS)는 Pod Security Admission(PSA) 컨트롤러를 통해 쿠버네티스 클러스터에 적용됩니다.

  • PSA 컨트롤러는 네임스페이스에 적용된 PSS 레이블(pod-security.kubernetes.io/enforce=baseline)을 읽어, 해당 네임스페이스에 배포되는 파드가 레이블에 정의된 보안 표준을 준수하는지 검사합니다.
  • 정책 위반 시, PSA는 enforce, audit, warn 세 가지 모드에 따라 파드 생성을 거부하거나 경고만 발생시킵니다.

 

적용 테스트

Pod Security Standards 적용을 위해 kube-apiserver.yaml 수정

spec:
  containers:
  - command:
    - kube-apiserver
    - --enable-admission-plugins=NodeRestriction,PodSecurity ####PodSecurity#### 적용

 

Pod Security Standards 적용한 namespace 와 label 추가

kubectl create namespace my-secure-ns

# `enforce=baseline` 레이블 적용
kubectl label namespace my-secure-ns pod-security.kubernetes.io/enforce=baseline

 

테스트 파드 수행

# pod-with-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-test-pod
  namespace: my-secure-ns
spec:
  containers:
  - name: my-container
    image: busybox
    command: ["/bin/sh", "-c", "sleep 3600"]
  volumes:
  - name: hostpath-vol
    hostPath:
      path: /

수행 결과

  • baseline 정책에 위반하면 위반된 사유를 기재해주고 아래와 같은 오류 발생

Falco에서 경고(Alert)를 파일로 저장하도록 설정하는 방법은 falco.yaml 파일을 수정하는 것입니다.

1단계: falco.yaml 파일 찾기

Falco 설정 파일은 일반적으로 다음 위치 중 하나에 있습니다.

  • /etc/falco/falco.yaml
  • /usr/local/etc/falco/falco.yaml

 

2단계: file_output 설정 활성화하기

텍스트 편집기를 사용하여 falco.yaml 파일을 열고, file_output 섹션을 찾으세요. 기본적으로 아래와 같이 enabled 값이 false로 되어 있습니다.

# [Stable] `file_output`
#
# When appending Falco alerts to a file, each new alert will be added to a new
# line. It's important to note that Falco does not perform log rotation for this
# file. If the `keep_alive` option is set to `true`, the file will be opened once
# and continuously written to, else the file will be reopened for each output
# message. Furthermore, the file will be closed and reopened if Falco receives
# the SIGUSR1 signal.
file_output:
  enabled: false
  keep_alive: false
  filename: ./events.txt

이 설정을 다음과 같이 수정하여 활성화합니다.

file_output:
  enabled: true
  keep_alive: false
  filename: /var/log/falco/events.json

수정된 부분의 의미:

  • enabled: true: 파일 출력을 활성화합니다.
  • keep_alive: true: Falco가 파일을 한 번 열고 계속 쓰도록 설정합니다. 이는 성능을 향상시키며, 많은 경고가 발생하는 환경에서 오버헤드를 줄여줍니다.(본문에서는 false 로 테스트 하였습니다)
  • filename: /var/log/falco/events.json: 경고를 저장할 파일의 경로와 이름을 지정합니다. .json 확장자를 사용하면 경고 메시지가 JSON 형식으로 저장되어 로그 분석 도구와 연동하기 쉽습니다.

3단계: Falco 재시작 또는 설정 적용하기

변경사항을 적용하려면 Falco 서비스를 재시작해야 합니다.

  • Systemd를 사용하는 경우 (대부분의 리눅스 배포판)
    sudo systemctl restart falco

 
 

Falco는 클라우드 네이티브 컴퓨팅 재단(CNCF)의 인큐베이팅 프로젝트로, 시스템 동작을 감시하고 비정상적인 행위를 탐지하는 강력한 런타임 보안 도구입니다. 특히 컨테이너와 쿠버네티스 환경의 보안을 강화하는 데 최적화되어 있습니다.

CKS 시험에서 Falco는 런타임 보안(Runtime Security) 분야의 핵심 도구입니다. 시험에서는 주로 컨테이너 환경에서 발생할 수 있는 비정상적인 행위를 탐지하는 룰을 만들거나 수정하는 문제가 출제됩니다.

https://falco.org/docs/concepts/rules/basic-elements/ 

 

Basic Elements of Falco Rules

Understand Falco Rules, Lists and Macros

falco.org

 

대표적인 룰 설정

1. 쉘(Shell)이 컨테이너 내에서 실행될 때 탐지하는 룰

이 룰은 CKS에서 가장 기본적인 유형입니다. 운영 중인 컨테이너에서 쉘이 실행되는 것은 일반적으로 디버깅 목적이거나, 공격자가 컨테이너에 침투한 후 명령을 내리기 위한 행위일 수 있어 중요한 보안 위협입니다.

- rule: Shell in a Container
  desc: A shell was used as the entrypoint/exec point into a container with an attached terminal.
  condition: >
    spawned_process and container and proc.name in (shell_binaries)
  output: >
    A shell was spawned in a container (user=%user.name container_id=%container.id container_name=%container.name shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
  priority: WARNING
  • condition:
    • spawned_process: 새로운 프로세스가 생성되는 이벤트를 탐지하는 매크로입니다.
    • container: 이벤트가 호스트가 아닌 컨테이너에서 발생했음을 확인하는 매크로입니다.
    • proc.name in (shell_binaries): 실행된 프로세스의 이름이 sh, bash, zsh 등 쉘 바이너리 목록에 포함되는지를 확인합니다.
  • output: 룰이 트리거되면 output에 정의된 상세한 정보(사용자, 컨테이너 ID, 쉘 이름 등)를 로그에 남깁니다.
  • priority: 경고의 심각도를 WARNING으로 설정합니다.

 

2. 민감한 파일에 접근할 때 탐지하는 룰

/etc/shadow나 /dev/mem과 같이 중요한 시스템 파일에 접근하는 것은 악의적인 의도일 가능성이 높습니다. CKS 시험에서는 이러한 파일에 대한 접근을 탐지하도록 룰을 수정하거나 새로 만들도록 요구할 수 있습니다.

/etc/shadow 파일 접근 탐지:

- rule: Read sensitive file trusted by host
  desc: Detect attempts to read host sensitive files from a container.
  condition: >
    open_read and container and fd.name in (/etc/shadow, /etc/gshadow)
  output: >
    Sensitive file accessed (user=%user.name process=%proc.name container_id=%container.id file=%fd.name)
  priority: CRITICAL
  • condition:
    • open_read: 파일을 읽기 모드로 여는 이벤트를 탐지하는 매크로입니다.
    • fd.name in (...): 열린 파일의 경로가 /etc/shadow 또는 /etc/gshadow일 때를 조건으로 합니다.

/dev/mem 파일 접근 탐지:

- rule: devmem
  desc: Access to /dev/mem
  condition: >
    fd.name = /dev/mem
  output: >
    Access to /dev/mem (user=%user.name process=%proc.name container_id=%container.id)
  priority: WARNING
  • condition: fd.name = /dev/mem이라는 매우 직관적인 조건으로 /dev/mem 파일에 대한 접근을 탐지합니다.

 

3. 컨테이너에서 네트워크 연결이 생성될 때 탐지하는 룰

컨테이너가 예상치 않은 외부 네트워크에 연결을 시도하는 경우를 탐지하는 룰입니다. 특히 외부로의 데이터 유출(egress)을 막는 데 유용합니다.

- rule: Outbound Connection
  desc: Detects when a container makes an outbound network connection.
  condition: >
    evt.type = connect and container and evt.dir=<
  output: >
    Outbound connection from container (user=%user.name container_id=%container.id proc_name=%proc.name dest_ip=%fd.cip dest_port=%fd.cport)
  priority: NOTICE
  • condition:
    • evt.type = connect: 네트워크 연결(socket connect) 이벤트가 발생했음을 탐지합니다.
    • evt.dir=<: 이벤트가 시스템 호출(syscall)로 들어오고 있음을 의미합니다

 

4. 컨테이너에서 새로운 프로세스를 실행할 때 사용되는 시스템 호출

컨테이너 에서 새로은 프로세스가 사용될때 탐지하는 룰 입니다.

- rule: Any process in a specific container
  desc: Detects any process execution inside the 'my-web-app' container.
  condition: >
    evt.type = execve and container.name = "my-web-app"
  output: >
    Process '%proc.name' started in container '%container.name' (user=%user.name cmdline=%proc.cmdline)
  priority: INFO
  • condition:
    • evt.type = execve: 새로운 프로세스 실행을 탐지합니다.
    • container.name: 컨테이너 이름을 지정해서 탐지합니다.

 

 

 

어드미션 컨트롤러란?

어드미션 컨트롤러는 쿠버네티스 API 서버의 요청을 가로채는 코드 조각입니다. 요청이 인증 및 권한 부여를 통과한 후, 하지만 리소스가 영구적으로 저장되기 전에 작동합니다.

이 컨트롤러는 오브젝트를 생성, 삭제, 또는 수정하는 요청에 적용됩니다. 또한 API 서버 프록시를 통해 파드에 연결하는 것과 같은 사용자 정의 동사(custom verbs) 요청도 차단할 수 있습니다. 하지만 오브젝트를 읽는(get, watch, list) 요청은 어드미션 컨트롤 계층을 통과하므로 차단하지 못합니다.


어드미션 컨트롤러의 역할

  • 쿠버네티스 기능 지원: 쿠버네티스의 여러 중요한 기능은 제대로 작동하기 위해 특정 어드미션 컨트롤러가 활성화되어야 합니다.
  • 보안 및 정책 적용: 클러스터 전체에 걸쳐 보안 정책, 거버넌스 규칙, 또는 사용자 지정 유효성 검사 규칙을 적용하는 핵심 메커니즘 역할을 합니다.

어드미션 컨트롤러의 종류

어드미션 컨트롤 메커니즘은 두 가지 유형으로 나눌 수 있습니다.

  • 변형(Mutating) 컨트롤러: 요청을 수정할 수 있습니다. 예를 들어, 파드에 특정 사이드카 컨테이너를 자동으로 추가하거나 기본값을 설정할 수 있습니다.
  • 유효성 검증(Validating) 컨트롤러: 요청을 수정할 수 없으며, 요청이 특정 규칙을 충족하는지 여부만 확인합니다. 규칙을 위반할 경우 요청을 거부합니다.

작동 방식

어드미션 컨트롤러는 kube-apiserver 바이너리에 내장되어 있으며, 요청이 API 서버로 들어오면 정의된 규칙에 따라 순차적으로 작동합니다. 첫 번째로 일치하는 규칙이 적용되며, 이 과정은 클러스터의 전반적인 보안과 안정성을 보장하는 데 매우 중요합니다.

따라서 올바른 어드미션 컨트롤러가 구성되지 않은 API 서버는 기능적으로 불완전하며, 기대하는 모든 기능을 지원하지 못할 수 있습니다.

 

설정 방법

AdmmisionConfiguration 파일 생성

{
   "apiVersion": "apiserver.config.k8s.io/v1",
   "kind": "AdmissionConfiguration",
   "plugins": [
      {
         "name": "ImagePolicyWebhook",
         "configuration": {
            "imagePolicy": {
               "kubeConfigFile": "/etc/kubernetes/policywebhook/kubeconf", ###kubeconf 위치####
               "allowTTL": 100,
               "denyTTL": 50,
               "retryBackoff": 500,
               "defaultAllow": false   ####필수####
            }
         }
      }
   ]
}

구문 설명

plugins: API 서버에서 활성화하고 구성할 어드미션 컨트롤러 목록입니다.

  • name: "ImagePolicyWebhook": 이미지 정책 웹훅 어드미션 컨트롤러를 활성화합니다. 이 컨트롤러는 파드(Pod)가 생성될 때 이미지의 유효성을 검사하기 위해 외부 웹훅 서비스에 요청을 보냅니다.
  • configuration: ImagePolicyWebhook 플러그인의 상세 설정입니다.
    • imagePolicy: 이미지 정책 웹훅의 핵심 설정입니다.
      • kubeConfigFile: "/etc/kubernetes/policywebhook/kubeconf": 웹훅 서비스와 통신하는 데 사용되는 kubeconfig 파일의 경로를 지정합니다. 이 파일에는 웹훅 서버의 주소, 인증서 등의 정보가 포함됩니다.
      • allowTTL: 100: 웹훅 서버가 이미지를 허용(Allow)한다고 응답하면, 해당 결과를 100초 동안 캐시합니다. 이 시간 동안 동일한 이미지에 대한 요청은 웹훅 서버로 보내지지 않고 캐시된 결과를 사용합니다. 이는 API 서버의 성능을 최적화하는 데 도움이 됩니다.
      • denyTTL: 50: 웹훅 서버가 이미지를 거부(Deny)한다고 응답하면, 해당 결과를 50초 동안 캐시합니다. 이 시간 동안 동일한 이미지는 무조건 거부됩니다.
      • retryBackoff: 500: 웹훅 서버에 연결할 수 없을 때 재시도 대기 시간을 500밀리초로 설정합니다.
      • defaultAllow: false: 이 설정이 가장 중요합니다. 웹훅 서비스에 연결할 수 없거나 웹훅에서 응답을 받지 못할 경우, 기본적으로 모든 이미지에 대한 요청을 거부합니다. 이는 "암묵적 거부(implicit deny)" 정책으로, 클러스터의 보안을 강화하는 데 매우 중요합니다. 만약 이 값이 true였다면, 외부 서비스가 다운될 경우 모든 이미지가 허용되어 보안 취약점이 발생할 수 있습니다.

 

 

kubeconf 파일 생성

apiVersion: v1
kind: Config

# clusters refers to the remote service.
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/policywebhook/external-cert.pem  # CA for verifying the remote service.
    server: https://localhost:1234                   # URL of remote service to query. Must use 'https'.
  name: image-checker

contexts:
- context:
    cluster: image-checker
    user: api-server
  name: image-checker
current-context: image-checker
preferences: {}

# users refers to the API server's webhook configuration.
users:
- name: api-server
  user:
    client-certificate: /etc/kubernetes/policywebhook/apiserver-client-cert.pem     # cert for the webhook admission controller to use
    client-key:  /etc/kubernetes/policywebhook/apiserver-client-key.pem             # key matching the cert

 

구문 설명

 

  • apiVersion: v1kind: Config: 이 파일이 kubeconfig 형식임을 나타냅니다.
  • clusters: API 서버가 연결할 외부 웹훅 서비스에 대한 정보를 정의합니다.
    • name: image-checker: 이 외부 클러스터의 이름입니다.
    • certificate-authority: /etc/kubernetes/policywebhook/external-cert.pem: 웹훅 서버의 TLS(Transport Layer Security) 인증서를 검증하는 데 사용되는 CA(Certificate Authority) 인증서 파일의 경로입니다. 이를 통해 API 서버는 자신이 연결하는 웹훅 서버가 신뢰할 수 있는 서버인지 확인합니다.
    • server: https://localhost:1234: 웹훅 서비스의 URL입니다. 이 주소로 API 서버가 이미지를 검증하기 위한 요청을 보냅니다. 반드시 https를 사용해야 합니다.
  • users: API 서버가 웹훅 서비스에 자신을 인증하기 위해 사용하는 클라이언트 정보를 정의합니다.
    • name: api-server: API 서버 사용자의 이름입니다.
    • client-certificate: /etc/kubernetes/policywebhook/apiserver-client-cert.pem: API 서버가 웹훅 서비스에 자신을 인증하기 위해 제시할 클라이언트 인증서 파일의 경로입니다.
    • client-key: /etc/kubernetes/policywebhook/apiserver-client-key.pem: 클라이언트 인증서와 쌍을 이루는 프라이빗 키 파일의 경로입니다.
  • contexts: 클러스터와 사용자를 결합하여 컨텍스트를 정의합니다.
    • name: image-checker: 이 컨텍스트의 이름입니다.
    • cluster: image-checker: 위에서 정의한 image-checker 클러스터를 사용합니다.
    • user: api-server: 위에서 정의한 api-server 사용자를 사용합니다.
  • current-context: image-checker: 현재 사용 중인 컨텍스트를 지정합니다. 이 설정 덕분에 kubectl과 같은 클라이언트가 특정 클러스터에 연결할 때 별도의 --context 플래그를 지정할 필요가 없습니다. 하지만 이 파일은 kubeconfig이므로 API 서버에서만 사용됩니다.

 

kube-apiserver 수정

    - --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook  ###ImagePolicyWebhook 추가###
    - --admission-control-config-file=/etc/kubernetes/policywebhook/admission_config.json  ##경로 추가##
    
    ...
    volumeMounts:
    - mountPath: /etc/kubernetes/policywebhook
      name: policywebhook
      readyOnly: true
      
    ...
  volumes:
  - hostPath:
      path: /etc/kubernetes/policywebhook
      type: DirectoryOrCreate
    name: policywebhook

 

'k8s > CKS' 카테고리의 다른 글

[CKS] Pod Security Standards  (1) 2025.09.07
[CKS] falco 사용방법 및 샘플 - 2  (0) 2025.09.07
[CKS] falco 사용방법 및 샘플 - 1  (0) 2025.09.07
[CKS] NetworkPolicy 설명  (0) 2025.09.07
[CKS] ServiceAccount 생성 및 Pod 적용  (0) 2025.09.07

+ Recent posts