Cilium 은 네트워크의 다양한 계층에서 보안 기능을 제공합니다. Layer 3에서는 Identity-Based 보안을 제공하고, Layer 4에서는 Port Level 보안을, Layer 7에서는 Application protocol Level 보안을 지원합니다.
Layer 3 Identity-Based

Security-ID
저번 시간에 공유드렸듯이, 쿠버네티스 환경에서 파드들의 IP 가 수시로 변하기 때문에 ip 기반 접근 통제 보다는 id 기반 접근 정책을 통해 파드들의 통신을 제어합니다. Cilium 에서는 모든 엔드포인트에 대해 고유한 ID 가 할당됩니다. 이 ID 는 클러스터 내에서 유일한 ID 로 구성되며, 동일한 Security 정책을 사용하는 엔드포인트들은 동일한 ID 를 공유하게 됩니다.

위와 같이 ciliumendpoint 들을 조회했을 때, 동일한 보안 정책을 부여받는 엔드포인트끼리 동일한 security ID 값을 부여받는 것을 알 수 있습니다.
파드 또는 컨테이너가 시작되면 Cilium 은 컨테이너 런타임에서 수신한 이벤트를 기반으로 엔드포인트를 생성합니다. 다음 단계로 Cilium 은 생성된 엔드포인트의 ID 를 확인하며, 포드나 컨테이너의 Labels가 변경될 때마다 ID 가 재확인되고 필요에 따라 자동으로 수정됩니다.
Labels 변경 시 endpoint가 waiting-for-identity 상태로 전환되어 새로운 identity 를 할당받게 됩니다. 이로 인해 security labels 와 관련된 네트워크 정책도 자동으로 재적용됩니다. 예를 들어 간단한 pod을 생성하면 초기 security identity 가 할당되고, kubectl label 명령으로 labels 를 변경하면 새로운 identity 값으로 업데이트되는 것을 확인할 수 있습니다.

참고로 security label 중 reserved 문자열 접두사가 붙은 라벨들은 Cilium 에서 관리하지 않는 네트워크 엔드포인트와의 통신을 허용하기 위해 예약된 라벨들입니다.
엔드포인트 기반 정책
두 엔드포인트가 Cilium에 의해 관리되고 레이블이 할당되어 있는 경우 유용합니다. 이 방법의 장점은 IP 주소가 정책에 하드코딩되지 않고 유연하게 대처가 가능하다는 점입니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
spec:
endpointSelector:
matchLabels:
role: backend
ingress:
- fromEndpoints:
- matchLabels:
role: frontend
서비스 기반 정책
kubernetes 의 서비스 엔드포인트로 정책을 구성합니다. 이 엔드포인트는 서비스의 모든 백엔드 IP 주소를 포함하도록 자동으로 유지됩니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "service-rule"
spec:
endpointSelector:
matchLabels:
id: app2
egress:
- toServices:
# Services may be referenced by namespace + name
- k8sService:
serviceName: myservice
namespace: default
# Services may be referenced by namespace + label selector
- k8sServiceSelector:
selector:
matchLabels:
env: staging
namespace: another-namespace
엔티티 기반 정책
혹은 앞서 살펴본 reserved 된 cilium identity 로도 네트워크 정책을 구성할 수 있습니다. IP 주소로 설명이 되지 않지만 원격 피어를 구성 정책에 활용할 수 있습니다. 로컬 호스트에 대한 연결이나 클러스터 외부에 대한 모든 연결이 포함됩니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "dev-to-kube-apiserver"
spec:
endpointSelector:
matchLabels:
env: dev
egress:
- toEntities:
- kube-apiserver
노드 기반 정책
특정 노드를 기반으로도 네트워크 정책을 구성할 수 있습니다. 특정 노드의 접근만 허용하거나 차단할 수 있습니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "to-prod-from-control-plane-nodes"
spec:
endpointSelector:
matchLabels:
env: prod
ingress:
- fromNodes:
- matchLabels:
node-role.kubernetes.io/control-plane: ""
IP/CIDR 기반 정책
원격 피어가 엔드포인트가 아닌 경우 외부 서비스와 네트워크 정책을 구성할 때 유용합니다. IP 주소 또는 서브넷을 정책에 직접 지정해야 합니다. 이 구성은 안정적인 IP 또는 서브넷 할당이 필요하므로 최후의 수단으로 사용해야 합니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "cidr-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toCIDR:
- 20.1.1.1/32
- toCIDRSet:
- cidr: 10.0.0.0/8
except:
- 10.96.0.0/12
DNS 기반 정책
DNS 조회를 통해 IP 로 변환된 DNS 이름을 사용하여 원격의 비클러스터 피어를 선택하여 정책을 구성할 수도 있습니다.
보통 DNS 는 L7 기반 정책이므로 Envoy Proxy 가 대신 수행할 것으로 보이지만, L3 에서도 경량의 DNS Proxy 가 트래픽을 처리하여 가능하다고 하네요. DNS TTL 은 준수됩니다.
DNS 요청을 허용하는 L7 정책이 구성되어 있어야 하기 때문에 --enable-l7-proxy=true 옵션이 활성화 되어 있어야 합니다. 두 가지 패턴을 사용합니다.
- toFQDNs.matchName: 정확히 일치하는 도메인 입력
- toFQDNs.matchPattern: 와일드카드 패턴 입력
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "to-fqdn"
spec:
endpointSelector:
matchLabels:
app: test-app
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"
- toFQDNs:
- matchName: "my-remote-service.com"
Layer 4 Port Level
cilium 에서 프로토콜 기반 제어를 제공합니다. 해당 계층 정책은 3계층 정책과 함께 또는 독립적으로 사용할 수 있습니다.
포트를 지정해서 사용할 수도 있고,
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l4-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toPorts:
- ports:
- port: "80"
protocol: TCP
포트 범위를 지정할 수도 있고,
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l4-port-range-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toPorts:
- ports:
- port: "80"
endPort: 444
protocol: TCP
CIDR 대역의 IP 와 함께 사용할 수도 있습니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "cidr-l4-rule"
spec:
endpointSelector:
matchLabels:
role: crawler
egress:
- toCIDR:
- 192.0.2.0/24
toPorts:
- ports:
- port: "80"
protocol: TCP
TLS 의 SNI (서버 이름 표시) 기능을 활용하여 제한할 수도 있습니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l4-sni-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toPorts:
- ports:
- port: "443"
protocol: TCP
serverNames: # SNI
- one.one.one.one
Application protocol Level
cilium 에서 아래에 해당하는 프로토콜 중 L7 정책을 통해 L7 어플리케이션 트래픽들을 제어할 수 있습니다.
// L7Rules is a union of port level rule types. Mixing of different port
// level rule types is disallowed, so exactly one of the following must be set.
// If none are specified, then no additional port level rules are applied.
type L7Rules struct {
// HTTP specific rules.
//
// +optional
HTTP []PortRuleHTTP `json:"http,omitempty"`
// Kafka-specific rules.
//
// +optional
Kafka []PortRuleKafka `json:"kafka,omitempty"`
// DNS-specific rules.
//
// +optional
DNS []PortRuleDNS `json:"dns,omitempty"`
}
3계층 및 4계층 정책과 달리 7계층 규칙 위반 시 패킷을 드랍하지 않고 애플리케이션 프로토콜별 접근 거부 메시지를 제공합니다. 예를 들어, HTTP 의 경우 403 Forbidden 을, DNS 의 경우, DNS 거부 응답을 보냅니다. 7 계층 정책은 Envoy 프록시를 통해 트래픽을 검사 후 처리를 진행합니다.

HTTP 정책의 경우 Path, Method, Hosts, Headers 를 정책의 구성요소로 사용합니다.
다음은 GET /public 만 허용하는 예제로 아래와 같이 구성할 수 있습니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "rule1"
spec:
description: "Allow HTTP GET /public from env=prod to app=service"
endpointSelector:
matchLabels:
app: service
ingress:
- fromEndpoints:
- matchLabels:
env: prod
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
path: "/public"
헤더가 설정된 경우에만 모든 GET /path1 및 PUT /path2 를 허용하는 예제입니다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l7-rule"
spec:
endpointSelector:
matchLabels:
app: myService
ingress:
- toPorts:
- ports:
- port: '80'
protocol: TCP
rules:
http:
- method: GET
path: "/path1$"
- method: PUT
path: "/path2$"
headers:
- 'X-My-Header: true'
DNS 정책은 DNS 트래픽에 적용되어 특정 DNS 쿼리 이름 또는 이름 패턴을 허용하거나 거부할 수 있습니다.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: "tofqdn-dns-visibility"
spec:
endpointSelector:
matchLabels:
any:org: alliance
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchName: "cilium.io"
- matchPattern: "*.cilium.io"
- matchPattern: "*.api.cilium.io"
- toFQDNs:
- matchName: "cilium.io"
- matchName: "sub.cilium.io"
- matchName: "service1.api.cilium.io"
- matchPattern: "special*service.api.cilium.io"
toPorts:
- ports:
- port: "80"
protocol: TCP
참고로 쿠버네티스에서 DNS 정책을 적용할 때, service.namespace.svc.cluster.local에 대한 쿼리는 명시적으로 허용되어야 합니다. (matchPattern: *.*.svc.cluster.local.) 마찬가지로, FQDN을 완성하기 위해 DNS 검색 목록에 의존하는 쿼리는 전체가 허용되어야 합니다. 예를 들어, servicename로 성공하는 쿼리는 또는 servicename.namespace.svc.cluster.local.로 허용되어야 합니다.
Cilium NetworkPolicy

Cilium 은 표준 Kubernetes 의 Network Policy 보다 더 많은 기능을 제공합니다.
Cilium Network Policy 정책은 statefull 하며 응답 패킷은 자동으로 허용됩니다. 보안 정책은 수신 또는 송신 시점에 적용되어 네트워크 트래픽을 제어합니다.
정책이 로드되지 않은 경우 모든 통신을 기본으로 허용합니다. 하지만 첫 번째 정책 규칙이 로드되는 즉시 정책 적용이 자동으로 활성화되며, 이후부터는 허용 목록 방식으로 동작하여 명시적으로 허용되지 않은 패킷은 드랍됩니다. 마찬가지로 L4 정책이 적용되지 않은 엔드포인트는 모든 포트와의 통신이 허용되지만, 하나 이상의 L4 정책이 연결되면 명시적으로 허용하지 않는 한 모든 연결이 차단됩니다.
'인프라 > 쿠버네티스' 카테고리의 다른 글
| [cilium] k8s / cilium 성능 테스트 (0) | 2025.08.30 |
|---|---|
| [cilium] Ingress / Gateway API (0) | 2025.08.23 |
| [cilium] cluster mesh (2) | 2025.08.15 |
| [cilium] BGP 설정 방법 (1) | 2025.08.15 |
| [cilium] cilium 의 LoadBalancer 서비스 (2) | 2025.08.09 |