정책 시행 모드
정책 시행 모드 (Policy Enforcement Modes)
Cilium 에이전트와 네트워크 정책의 구성이 엔드포인트의 트래픽 수락 여부를 어떻게 결정하는지 설명하는 문서예요. 정책 시행 모드, 기본 정책, Deny 응답 처리, 규칙 기초를 다뤄요.
본문
Cilium 에이전트와 Cilium 네트워크 정책의 구성은 엔드포인트가 출처의 트래픽을 수락할지 여부를 결정해요. 에이전트는 다음 세 가지 정책 시행 모드 중 하나로 설정할 수 있어요.
- default: 이것은 정책 시행의 기본 동작이에요. 이 모드에서 엔드포인트는 정책에 선택될 때까지 제한 없는 네트워크 접근을 가져요. 정책에 선택되면 엔드포인트는 허용된 트래픽만 허용해요. 이 상태는 방향별이며 정책별로 조정할 수 있어요. 자세한 내용은 default 모드 전용 섹션을 참고하세요.
- always: always 모드에서는 어떤 규칙이 특정 엔드포인트를 선택하더라도 모든 엔드포인트에서 정책 시행이 활성화돼요.
enable-policy: always로 cilium-agent를 시작할 때 health entity가 클러스터 전역 연결을 확인하도록 구성하려면 health 엔드포인트로/로부터의 통신을 활성화하는 것이 좋아요. Example: Add Health Endpoint 참고. - never: never 모드에서는 규칙이 특정 엔드포인트를 선택하더라도 모든 엔드포인트에서 정책 시행이 비활성화돼요. 즉, 어떤 출처(ingress)나 목적지(egress)로부터의 모든 트래픽이 허용돼요.
정책 시행 모드를 구성하려면 Helm 값 policyEnforcementMode 또는 해당 구성 플래그 enable-policy를 조정하세요.
엔드포인트 기본 정책 (Endpoint default policy)
기본적으로 모든 엔드포인트의 모든 egress와 ingress 트래픽이 허용돼요. 네트워크 정책이 엔드포인트를 선택하면 엔드포인트는 default-deny 상태로 전환되어, 명시적으로 허용된 트래픽만 허용돼요. 이 상태는 방향별이에요.
- 어떤 규칙이 엔드포인트를 선택하고 ingress 섹션이 있으면, 그 엔드포인트는 ingress에 대해 default deny 모드로 들어가요.
- 어떤 규칙이 엔드포인트를 선택하고 egress 섹션이 있으면, 그 엔드포인트는 egress에 대해 default-deny 모드로 들어가요.
즉, 엔드포인트는 제한 없이 시작하고, 첫 번째 정책이 엔드포인트의 기본 시행 모드를(방향별로) 전환해요.
선택된 엔드포인트에 대해 default-deny 모드를 활성화하지 않는 정책을 만들 수도 있어요. EnableDefaultDeny 필드가 이를 구성해요. EnableDefaultDeny가 비활성화된 규칙은 기본 모드를 결정할 때 무시돼요.
예를 들어 이 정책은 모든 DNS 트래픽을 가로채지만, 엔드포인트에 적용되는 첫 번째 정책이어도 어떤 트래픽도 차단하지 않아요. 관리자는 이 정책을 클러스터 전역에 안전하게 적용할 수 있어요. 엔드포인트를 default-deny로 전환해 합법적인 트래픽이 버려질 위험이 없기 때문이에요.
경고:
EnableDefaultDeny는 레이어 7 정책에 적용되지 않아요. 레이어 7 allow-all을 포함하지 않는 레이어 7 규칙을 추가하면, default-deny가 명시적으로 비활성화됐어도 드롭이 발생해요.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: intercept-all-dns
spec:
endpointSelector:
matchExpressions:
- key: "io.kubernetes.pod.namespace"
operator: "NotIn"
values:
- "kube-system"
- key: "k8s-app"
operator: "NotIn"
values:
- kube-dns
enableDefaultDeny:
egress: false
ingress: false
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: TCP
- port: "53"
protocol: UDP
rules:
dns:
- matchPattern: "*"
정책 Deny 응답 처리 (Policy Deny Response Handling)
기본적으로 네트워크 정책이 파드의 egress 트래픽을 거부하면 Cilium은 패킷을 조용히 버려요. 즉, 애플리케이션은 금지된 목적지에 연결을 시도할 때 즉각적인 연결 실패 대신 연결 타임아웃을 경험해요. 하지만 일부 애플리케이션은 연결 타임아웃 대신 명시적인 거부 알림을 받는 것이 유익할 수 있어요. 이는 애플리케이션에 더 빠른 피드백을 제공하고 대기 시간을 줄여 사용자 경험을 개선할 수 있어요.
이 동작은 --policy-deny-response 옵션으로 구성할 수 있어요.
- none (default): 거부된 패킷을 조용히 버려요. 정책이 트래픽을 거부하면 애플리케이션은 연결 타임아웃을 경험해요.
- icmp (experimental): egress 트래픽이 정책에 의해 거부되면 출처 파드로 ICMP Destination Unreachable 응답을 보내요. 이는 애플리케이션에 연결이 거부됐다는 즉각적인 피드백을 제공해요.
참고: 이것은 실험적 기능이며, 네트워크 정책에 의해 거부된 ipv4와 ipv6 egress 파드 트래픽에만 적용돼요. Ingress 트래픽 거부 동작은 현재 지원되지 않아요. 업데이트는 GitHub issue 41859를 확인하세요.
경고:
--policy-deny-response=icmp를 사용할 때는 ICMP ingress 트래픽이 네트워크 정책에 의해 허용되는지 확인하세요. ICMP 트래픽이 ingress 정책에 의해 차단되면 애플리케이션은 거부 알림을 받지 못하고 여전히 연결 타임아웃을 경험해요.
규칙 기초 (Rule Basics)
모든 정책 규칙은 화이트리스트 모델에 기반해요. 즉, 정책의 각 규칙은 그 규칙과 일치하는 트래픽을 허용해요. 두 규칙이 있고 하나가 더 넓은 트래픽 집합과 일치한다면, 넓은 규칙과 일치하는 모든 트래픽이 허용돼요. 두 개 이상의 규칙 사이에 교집합이 있으면 그 규칙들의 합집합과 일치하는 트래픽이 허용돼요. 마지막으로, 어떤 규칙과도 일치하지 않는 트래픽은 Policy Enforcement Modes에 따라 버려져요.
정책 규칙은 공통 기본 타입을 공유하는데, 이 타입은 규칙이 적용되는 엔드포인트와 규칙을 식별하는 공통 메타데이터를 지정해요. 각 규칙은 ingress 섹션과 egress 섹션으로 나뉘어요. ingress 섹션에는 엔드포인트로 들어오는 트래픽에 적용되어야 하는 규칙이, egress 섹션에는 엔드포인트 선택자와 일치하는 엔드포인트에서 나가는 트래픽에 적용되는 규칙이 들어 있어요. ingress, egress 중 하나 또는 둘 다 제공할 수 있어요. 둘 다 생략하면 규칙은 아무 효과가 없어요.
type Rule struct {
// EndpointSelector selects all endpoints which should be subject to
// this rule. EndpointSelector and NodeSelector cannot be both empty and
// are mutually exclusive.
//
// +optional
EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"`
// NodeSelector selects all nodes which should be subject to this rule.
// EndpointSelector and NodeSelector cannot be both empty and are mutually
// exclusive. Can only be used in CiliumClusterwideNetworkPolicies.
//
// +optional
NodeSelector EndpointSelector `json:"nodeSelector,omitempty"`
// Ingress is a list of IngressRule which are enforced at ingress.
// If omitted or empty, this rule does not apply at ingress.
//
// +optional
Ingress []IngressRule `json:"ingress,omitempty"`
// Egress is a list of EgressRule which are enforced at egress.
// If omitted or empty, this rule does not apply at egress.
//
// +optional
Egress []EgressRule `json:"egress,omitempty"`
// Labels is a list of optional strings which can be used to
// re-identify the rule or to store metadata. It is possible to lookup
// or delete strings based on labels. Labels are not required to be
// unique, multiple rules can have overlapping or identical labels.
//
// +optional
Labels labels.LabelArray `json:"labels,omitempty"`
// Description is a free form string, it can be used by the creator of
// the rule to store human readable explanation of the purpose of this
// rule. Rules cannot be identified by comment.
//
// +optional
Description string `json:"description,omitempty"`
}
- endpointSelector / nodeSelector: 정책 규칙이 적용되는 엔드포인트 또는 노드를 선택해요. 선택자에 지정된 라벨과 일치하는 모든 엔드포인트에 정책 규칙이 적용돼요. 자세한 내용은 Endpoint Selector 및 Node Selector 섹션을 참고하세요.
- ingress: 엔드포인트의 ingress, 즉 엔드포인트로 들어오는 모든 네트워크 패킷에 적용되어야 하는 규칙 목록이에요.
- egress: 엔드포인트의 egress, 즉 엔드포인트를 떠나는 모든 네트워크 패킷에 적용되어야 하는 규칙 목록이에요.
- labels: 라벨은 규칙을 식별하는 데 사용돼요. 규칙은 라벨로 나열·삭제할 수 있어요. kubernetes를 통해 가져온 정책 규칙은 자동으로
io.cilium.k8s.policy.name=NAME라벨이 할당되는데, 여기서NAME은 NetworkPolicy 또는 CiliumNetworkPolicy 리소스에 지정된 이름에 해당해요. - description: description은 Cilium이 해석하지 않는 문자열이에요. 규칙의 의도와 범위를 사람이 읽을 수 있는 형태로 설명하는 데 사용할 수 있어요.
엔드포인트 선택자 (Endpoint Selector)
Endpoint Selector는 Kubernetes LabelSelector에 기반해요. Endpoint와 관련된 라벨에만 적용되기 때문에 Endpoint Selector라고 불러요.
노드 선택자 (Node Selector)
Endpoint Selector와 마찬가지로 Node Selector도 Kubernetes LabelSelector에 기반해요. 다만 Endpoint와 관련된 라벨을 일치시키는 대신 클러스터의 Node와 관련된 라벨에 적용돼요.
Node Selector는 CiliumClusterwideNetworkPolicies에서만 사용할 수 있어요. 노드 수준 정책의 범위에 대한 자세한 내용은 Host Policies를 참고하세요.