정책에 Kubernetes 구성 사용
정책에 Kubernetes 구성 사용 (Using Kubernetes Constructs In Policy)
Cilium 네트워크 정책에서 Kubernetes 관련 구성 요소(네임스페이스, 서비스 어카운트, 멀티 클러스터, 클러스터 전역 정책 등)를 어떻게 활용하는지 설명하는 문서예요.
본문
이 섹션은 Kubernetes 특정 네트워크 정책 측면을 다뤄요.
네임스페이스 (Namespaces)
Namespaces는 Kubernetes 클러스터 안에 가상 클러스터를 만드는 데 사용돼요. NetworkPolicy와 CiliumNetworkPolicy를 포함한 모든 Kubernetes 객체는 특정 네임스페이스에 속해요.
알려진 함정 (Known Pitfalls)
이 섹션은 정책에 Kubernetes 구성 요소를 사용할 때의 알려진 함정을 다뤄요.
네임스페이스 경계 고려 사항 (Considerations Of Namespace Boundaries)
정책이 정의·생성되는 방식에 따라 Kubernetes 네임스페이스가 자동으로 고려돼요. API Reference로 직접 가져온 네트워크 정책은 Example에서 설명하는 것처럼 네임스페이스 선택자가 지정되지 않는 한 모든 네임스페이스에 적용돼요.
예제 (Example)
이 예제는 ns1과 ns2 네임스페이스 모두의 모든 파드에 default-deny를 활성화한 다음, 같은 네임스페이스의 모든 파드 간 통신을 허용해 두 네임스페이스에 Kubernetes 네임스페이스 기반 경계를 시행하는 방법을 보여줘요.
참고: 이 예제는
ns1과ns2의 파드 ingress를 잠가요. 즉, 목적지가ns1이나ns2에 있지 않으면 파드가 egress로 어디든 통신할 수 있다는 뜻이에요. 목적지가ns1이나ns2에 있으면 출발지와 목적지가 모두 같은 네임스페이스여야 해요. egress에서 네임스페이스 경계를 시행하려면 egress에 규칙을 추가로 지정해 같은 예제를 사용할 수 있어요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "isolate-ns1"
namespace: ns1
spec:
endpointSelector:
matchLabels:
{}
ingress:
- fromEndpoints:
- matchLabels:
{}
---
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "isolate-ns1"
namespace: ns2
spec:
endpointSelector:
matchLabels:
{}
ingress:
- fromEndpoints:
- matchLabels:
{}
정책은 네임스페이스 안에서만 적용돼요 (Policies Only Apply Within The Namespace)
CiliumNetworkPolicy CRD와 NetworkPolicy로 생성·가져온 네트워크 정책은 네임스페이스 안에서 적용돼요. 즉, 정책은 해당 네임스페이스 안의 파드에만 적용돼요. 하지만 Example에서 설명하는 것처럼 다른 네임스페이스의 파드로/로부터 접근을 허용할 수는 있어요.
예제 (Example)
다음 예제는 ns1 네임스페이스의 name=leia 라벨을 가진 모든 파드를 ns2 네임스페이스의 name=luke 라벨을 가진 모든 파드에 노출해요. 서로 다른 네임스페이스에 배포된 파드를 포함한 완전한 기능의 예제는 example YAML 파일을 참고하세요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "k8s-expose-across-namespace"
namespace: ns1
spec:
endpointSelector:
matchLabels:
name: leia
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: ns2
name: luke
EndpointSelector, FromEndpoints, ToEndpoints에 네임스페이스 지정 (Specifying Namespace In EndpointSelector, FromEndpoints, ToEndpoints)
fromEndpoints와 toEndpoints 필드에 k8s:io.kubernetes.pod.namespace 라벨로 네임스페이스를 지정하는 것은 Example에서 설명하는 것처럼 지원돼요. 하지만 Kubernetes는 endpointSelector에 네임스페이스 지정을 금지해요. Kubernetes의 네임스페이스 격리 원칙을 위반하기 때문이에요. endpointSelector는 항상 CiliumNetworkPolicy 리소스 자체와 연결된 네임스페이스의 파드에 적용돼요.
예제 (Example)
다음 예제는 정책이 생성된 public 네임스페이스의 모든 파드가 kube-system 네임스페이스의 kube-dns와 53/UDP 포트로 통신하도록 허용해요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "allow-to-kubedns"
namespace: public
spec:
endpointSelector:
{}
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: '53'
protocol: UDP
네임스페이스 관련 정보 (Namespace Specific Information)
io.cilium.k8s.namespace.labels 같은 네임스페이스 관련 정보는 CiliumNetworkPolicy와 CiliumClusterwideNetworkPolicy 리소스 모두의 fromEndpoints와 toEndpoints에서 사용해, 파드가 속한 네임스페이스의 라벨에 기반해 파드를 일치시킬 수 있어요. 라벨 형식은 io.cilium.k8s.namespace.labels.<label-key>이며, 여기서 <label-key>는 Kubernetes 네임스페이스의 라벨에 해당해요.
CiliumNetworkPolicy 내의 fromEndpoints 또는 toEndpoints 선택자에 네임스페이스 라벨을 지정해도, 선택자는 정책 자신의 네임스페이스로 암묵적으로 제한되지 않아요. 이는 네임스페이스 라벨에 기반해 네임스페이스 간 파드를 일치시킬 수 있게 해 줘요.
참고:
endpointSelector는fromEndpoints나toEndpoints에서 사용된 네임스페이스 라벨과 무관하게 항상 CiliumNetworkPolicy 리소스 자체와 연결된 네임스페이스의 파드에 적용돼요.
예제 (Example)
다음 예제는 rebel-base 파드가 faction: alliance 라벨이 있는 네임스페이스의 파드하고만 통신하도록 제한해요. Rebel Alliance는 여러 네임스페이스에 걸쳐 운영되므로, 네임스페이스 라벨 덕분에 이 정책이 하나씩 나열하지 않고도 모든 Alliance 네임스페이스에 적용될 수 있어요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "alliance-only"
spec:
endpointSelector:
matchLabels:
name: rebel-base
ingress:
- fromEndpoints:
- matchLabels:
io.cilium.k8s.namespace.labels.faction: "alliance"
egress:
- toEndpoints:
- matchLabels:
io.cilium.k8s.namespace.labels.faction: "alliance"
일치 표현식 (Match Expressions)
CiliumNetworkPolicy 또는 CiliumClusterwideNetworkPolicy에서 matchExpressions를 사용할 때, 값 목록은 논리 AND로 처리돼요. 여러 키를 논리 OR로 일치시키려면 여러 matchExpressions를 사용해야 해요.
예제 (Example)
이 예제는 키와 값 사이에 논리 OR을 이루는 여러 matchExpressions로 정책을 시행하는 방법을 보여줘요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "or-statement-policy"
spec:
endpointSelector: {}
ingress:
- fromEndpoints:
- matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: "In"
values:
- "production"
- matchExpressions:
- key: "k8s:cilium.example.com/policy"
operator: "In"
values:
- "strict"
다음 예제는 단일 matchExpression으로 논리 AND를 보여줘요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "and-statement-policy"
spec:
endpointSelector: {}
ingress:
- fromEndpoints:
- matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: "In"
values:
- "production"
- key: "k8s:cilium.example.com/policy"
operator: "In"
values:
- "strict"
서비스 어카운트 (ServiceAccounts)
Kubernetes Service Accounts는 Kubernetes가 관리하는 파드나 프로세스에 신원을 연결하고, 그 신원에 Kubernetes 리소스와 시크릿 접근 권한을 부여하는 데 사용돼요. Cilium은 파드의 서비스 어카운트 신원에 기반한 네트워크 보안 정책 지정을 지원해요.
파드의 서비스 어카운트는 서비스 어카운트 admission controller를 통해 정의되거나, Pod, Deployment, ReplicationController 리소스에 직접 지정할 수 있어요.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: leia
# ...
예제 (Example)
다음 예제는 "luke" 서비스 어카운트로 실행되는 모든 파드가 "leia" 서비스 어카운트와 연결된 모든 파드에 TCP 80 포트로 HTTP GET /public 요청을 보낼 수 있도록 허용해요. 배포와 서비스 어카운트 리소스를 포함한 완전한 기능의 예제는 example YAML 파일을 참고하세요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "k8s-svc-account"
spec:
endpointSelector:
matchLabels:
io.cilium.k8s.policy.serviceaccount: leia
ingress:
- fromEndpoints:
- matchLabels:
io.cilium.k8s.policy.serviceaccount: luke
toPorts:
- ports:
- port: '80'
protocol: TCP
rules:
http:
- method: GET
path: "/public$"
멀티 클러스터 (Multi-Cluster)
클러스터 메시(cluster mesh)로 여러 클러스터를 운영할 때, 클러스터 이름은 io.cilium.k8s.policy.cluster 라벨로 노출되며 특정 클러스터로 정책을 제한하는 데 사용할 수 있어요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "allow-cross-cluster"
spec:
description: "Allow x-wing in cluster1 to contact rebel-base in cluster2"
endpointSelector:
matchLabels:
name: x-wing
io.cilium.k8s.policy.cluster: cluster1
egress:
- toEndpoints:
- matchLabels:
name: rebel-base
io.kubernetes.pod.namespace: default
io.cilium.k8s.policy.cluster: cluster2
정책 규칙의 io.kubernetes.pod.namespace: default에 주목하세요. 이는 x-wing이 배포된 cluster1의 네임스페이스와 무관하게 정책이 cluster2의 default 네임스페이스에 있는 rebel-base에 적용되도록 보장해요.
정책 규칙의 네임스페이스 라벨을 생략하면 정책 자체가 적용되는 네임스페이스와 같은 네임스페이스로 기본값 처리되는데, 이는 클러스터 간 정책을 배포할 때 원하지 않을 수 있어요. 어떤 네임스페이스로/로부터의 접근을 허용하려면 matchExpressions를 Exists 연산자와 함께 사용하세요.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "allow-cross-cluster-any-ns"
spec:
description: "Allow x-wing in cluster1 to contact rebel-base in cluster2 (in any NS)"
endpointSelector:
matchLabels:
name: x-wing
io.cilium.k8s.policy.cluster: cluster1
egress:
- toEndpoints:
- matchExpressions:
- key: "k8s:io.kubernetes.pod.namespace"
operator: "Exists"
- key: "k8s:io.cilium.k8s.policy.cluster"
operator: "In"
values:
- "cluster2"
- key: "k8s:name"
operator: "In"
values:
- "rebel-base"
클러스터 전역 정책 (Clusterwide Policies)
CiliumNetworkPolicy는 특정 네임스페이스로 제한된 정책만 바인딩할 수 있어요. 정책의 클러스터 범위 효과를 원하는 상황이 있을 수 있는데, 이는 Cilium의 CiliumClusterwideNetworkPolicy Kubernetes 커스텀 리소스로 할 수 있어요. 정책의 명세는 CiliumNetworkPolicy와 동일하지만 네임스페이스가 없어요.
이 클러스터 정책은 어느 네임스페이스에서든 name=luke 라벨을 가진 파드로부터, 어느 네임스페이스에서든 name=leia 라벨을 가진 파드로의 ingress 트래픽을 허용해요.
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "clusterwide-policy-example"
spec:
description: "Policy for selective ingress allow to a pod from only a pod with given label"
endpointSelector:
matchLabels:
name: leia
ingress:
- fromEndpoints:
- matchLabels:
name: luke
모든 Cilium 관리 엔드포인트가 Kube-dns와 통신하도록 허용 (Allow All Cilium Managed Endpoints To Communicate With Kube-dns)
다음 예제는 클러스터의 모든 Cilium 관리 엔드포인트가 kube-system 네임스페이스의 kube-dns와 53/UDP 포트로 통신하도록 허용해요.
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "wildcard-from-endpoints"
spec:
description: "Policy for ingress allow to kube-dns from all Cilium managed endpoints in the cluster"
endpointSelector:
matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
ingress:
- fromEndpoints:
- {}
toPorts:
- ports:
- port: "53"
protocol: UDP
예제: Health 엔드포인트 추가 (Example: Add Health Endpoint)
다음 예제는 클러스터 연결 상태를 확인하기 위해 모든 Cilium 관리 엔드포인트에 health entity를 추가해요.
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "cilium-health-checks"
spec:
endpointSelector:
matchLabels:
'reserved:health': ''
ingress:
- fromEntities:
- remote-node
egress:
- toEntities:
- remote-node