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

NetworkPolicy 기본 설정

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 80

정책의 주요 내용

  • podSelector: 이 네트워크 정책이 적용될 파드를 지정합니다. 이 설정에서는 role: db라는 라벨이 붙은 모든 파드에 정책을 적용합니다. 즉, 이 정책은 데이터베이스 역할을 하는 파드를 보호하는 역할을 합니다.
  • policyTypes: 정책이 적용될 트래픽의 방향을 지정합니다.
    • Ingress: 외부에서 파드로 들어오는 트래픽에 대한 규칙을 정의합니다.
    • Egress: 파드에서 외부로 나가는 트래픽에 대한 규칙을 정의합니다. 이 설정에서는 인그레스(Ingress)와 이그레스(Egress) 규칙을 모두 정의하고 있습니다. 하지만 YAML 파일에 이그레스(Egress) 규칙이 명시되어 있지 않으므로, 이 정책이 적용되는 파드에서는 외부로의 모든 트래픽이 차단됩니다.
  • ingress: role: db 파드로 들어오는 트래픽에 대한 허용 규칙을 정의합니다.
    • from: 어떤 소스로부터의 트래픽을 허용할지 지정합니다. 여기서는 두 가지 소스를 허용하고 있습니다.
      • namespaceSelector: project: myproject 라벨이 붙은 모든 네임스페이스의 파드로부터의 접근을 허용합니다.
      • podSelector: 현재 네임스페이스(default) 내에서 role: frontend 라벨이 붙은 모든 파드로부터의 접근을 허용합니다. 즉, 이 데이터베이스 파드에는 myproject라는 프로젝트 라벨이 붙은 네임스페이스의 파드와, default 네임스페이스에 있는 frontend 파드만 접근할 수 있습니다.
    • ports: 허용되는 포트와 프로토콜을 지정합니다. 여기서는 TCP 프로토콜을 사용하는 80번 포트로 들어오는 트래픽만 허용하고 있습니다.
      • 참고: 보통 데이터베이스는 3306(MySQL), 5432(PostgreSQL) 등 다른 포트를 사용

 

 

[샘플1] 모든 인그레스 트래픽 차단 정책

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

정책의 주요 내용

    • podSelector: {}: 이 부분이 가장 중요합니다. 비어 있는 {}는 '모든 파드'를 의미합니다. 즉, 이 정책이 적용되는 네임스페이스의 모든 파드에 대해 규칙을 적용하겠다는 뜻입니다. 만약 네임스페이스가 명시되지 않았다면, 이 정책을 배포하는 네임스페이스의 모든 파드에 적용됩니다.
    • policyTypes: 정책이 적용될 트래픽의 방향을 지정합니다.
      • Ingress: 외부에서 파드로 들어오는 트래픽에 대한 규칙을 정의합니다.
      • 이 설정은 Ingress만 명시하고 있으며, 인그레스 규칙을 구체적으로 정의하는 ingress: 섹션이 없습니다.

요약

 

  • 들어오는 트래픽(Ingress):
    • ingress 규칙이 명시되어 있지 않습니다.
    • policyTypes에 Ingress가 포함되어 있고 ingress 규칙이 없으면, 이는 **'모든 인그레스 트래픽을 거부한다'**는 의미로 해석됩니다.
    • 따라서 이 정책이 적용되는 네임스페이스의 모든 파드는 외부로부터의 모든 네트워크 접근이 차단됩니다.
  • 나가는 트래픽(Egress):
    • Egress 정책 타입이 명시되지 않았으므로, 나가는 트래픽에는 아무런 제약이 없습니다. 모든 파드는 외부로 자유롭게 통신할 수 있습니다.

 

 

[샘플2] 모든 인그레스 트래픽 허용 정책

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

정책의 주요 내용

  • podSelector: {}: 이 정책이 적용될 파드를 지정합니다. 비어 있는 {}는 '모든 파드'를 의미합니다. 이 정책이 배포되는 네임스페이스에 있는 모든 파드에 규칙이 적용됩니다.
  • ingress: - {}: 이 부분이 핵심입니다. 비어 있는 ingress 규칙은 **모든 소스(from)**와 **모든 포트(ports)**에 대해 인그레스 트래픽을 허용하겠다는 의미입니다.
  • policyTypes: - Ingress: 이 정책이 **들어오는 트래픽(Ingress)**에 대한 규칙만 정의하고 있음을 나타냅니다.

 

요약

  1. 들어오는 트래픽(Ingress):
    • ingress: - {}는 모든 외부 소스로부터 모든 포트로 들어오는 트래픽을 허용합니다.
    • 이 정책은 마치 방화벽의 모든 문을 활짝 열어주는 것과 같습니다.
  2. 나가는 트래픽(Egress):
    • Egress 정책 타입이 명시되지 않았습니다.
    • 따라서 파드에서 외부로 나가는 트래픽에는 아무런 제약이 없습니다. 모든 파드는 외부로 자유롭게 통신할 수 있습니다.

 

 

https://kubernetes.io/docs/concepts/services-networking/network-policies/

 

Network Policies

If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), NetworkPolicies allow you to specify rules for traffic flow within your cluster, and also between Pods and the outside world. Your cluster must use a network plugin tha

kubernetes.io

 

문제 개요

ServiceAccount 를 파드용으로 생성 후 파드에 적용

 

- ServiceAccount 생성(https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/  참고)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-sa
automountServiceAccountToken: false

 

- Pod 생성 후 ServiceAccount 적용

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: my-pod
  name: my-pod
spec:
  serviceAccountName: my-sa
  automountServiceAccountToken: false
  containers:
  - image: nginx
    name: my-pod

ingrss 란 여러가지 조건에 따라 트래픽 라우팅을 설정해 주는 서비스이다.

AWS 로 예를들면 ALB 와 동일하다고 생각하면 된다. 

설정할 수 있는 조건으로는 host 와 path 등이 있고, ingress 를 사용하기 위해서는 ingress-controller 가 설치 되어 있어야 한다.


예제

  • Nginx Deployment 와 Service 가 Cluster 내부에서 기동 중
  • ingress controller 를 사용하여 외부에서 내부의 Nginx 서비스로 접근
  • Nginx ingress controller 는 아래의 경로를 통해 설치 

nginx ingress controller

https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

 

Installation Guide - Ingress-Nginx Controller

Installation Guide There are multiple ways to install the Ingress-Nginx Controller: with Helm, using the project repository chart; with kubectl apply, using YAML manifests; with specific addons (e.g. for minikube or MicroK8s). On most Kubernetes clusters,

kubernetes.github.io

 


  • Deploy, Service, Ingress 배포
  • 배포 후 Nginx-ingress-controller 의 서비스 인 ingress-nginx-controller 의 ip:port 형식으로 호출하여야 한다
  • ingress 에서 path 를 /test 로 설정하였으므로, 호출시 ip:port/test 를 하면 클러스터 내부의 nignx 응답을 받을 수 있다
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - port: 31100
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
---
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /test
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 31100
  • 제 횐경에서의 ingress-nginx-controller 는 30303 포트이므로 NodeIP:30303/test 를 하게되면 ingress 를 통해서 nignx 가 호출 된다

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

NetworkPolicy 개념 정리  (0) 2024.01.20
[CKAD] Secret 생성 후 Pod 에 env 로 사용  (0) 2023.12.01
[CKAD]k8s Job / CronJob  (0) 2023.09.10
[CKAD]Docker image build  (0) 2023.09.09

+ Recent posts