NetworkPolicy는 쿠버네티스가 지원하는 Pod 통신 접근 제한, 즉, 일종의 방화벽으로 트래픽이 들어오고(Inbound), 나가는(Outbound) 것을 설정하는 정책이다.
- Ingress : Inbound 정책, 들어오는 트래픽을 허용할 것인지 정의
- Egress: Outbound 정책, 트래픽이 나갈 수 있는 허용 범위 정의
IP 주소 또는 포트 수준(OSI 3 or 4 layer)에서 트래픽을 제어하려는 경우 Network Policy는 네트워크 트래픽을 제어하고 규칙을 관리하는 데 사용되는 리소스이다. 이를 통해 파드 간의 통신을 허용하거나 차단함으로써 클러스터 내의 네트워크 보안을 강화할 수 있다. 기본적으로 쿠버네티스는 모든 Pod 간 네트워크 연결을 허용하지만, NetworkPolicy를 사용하면 특정 트래픽만 허용하고 나머지는 차단할 수 있다.
- NetworkPolicy는 Pod에만 적용 가능하다.
- 기본적으로 NetworkPolicy가 없으면 모든 네트워크 트래픽이 허용된다.
- NetworkPolicy가 충돌되는 경우는 없고, 합산되어 적용된다.
NetworkPolicy를 지원하는 솔루션(Plugin) - CNI가 지원해줘야지만 사용 가능하다.
- Kube-router
- Calico
- Romana
- Weave-net
NetworkPolicy를 지원하지 않는 솔루션 : Flannel
- NetworkPolicy 조회
controlplane ~ ➜ kubectl get networkpolicies
NAME POD-SELECTOR AGE
payroll-policy name=payroll 18m
controlplane ~ ➜ kubectl get netpol
NAME POD-SELECTOR AGE
payroll-policy name=payroll 18m
# name=payroll이라는 레이블을 가진 파드에 대한 인그레스(Ingress) 트래픽만 허용하는 정책 설정
NetworkPolicy Resource
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db # 해당 정책이 role: db 라벨을 가진 Pod에 적용된다.
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject # 해당 라벨이 있는 네임스페이스에서 오는 트래픽 허용
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379 # redis와 같은 DB에서 사용하는 포트
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24 # 해당 범위로 나가는 트래픽 허용
ports:
- protocol: TCP
port: 5978
- 트래픽 컨트롤 정의 :
- ipBlock: CIDR IP 대역, 특정 IP 대역에서만 트래픽이 들어오도록 지정할 수 있다.
- podSelector: label을 이용하여 특정 label을 가지고 있는 Pod들에서 들어오는 트래픽만 받을 수 있다.
- namespaceSelector: 특정 namespace로부터 들어오는 트래픽만을 받는 기능이다.
- podSelector: 규칙이 적용될 파드를 지정한다.
- Protocol & Port: 특정 Protocol 또는 Port로 설정된 트래픽만 허용되는 포트를 정의할 수 있다.
- 참고: https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource
- Ingress와 Egress는 네트워크 트래픽 흐름을 정의하는 중요한 개념이다.
Ingress | 클러스터 외부 → 내부로 들어오는 트래픽을 제어 |
Egress | 클러스터 내부 → 외부로 나가는 트래픽을 제어 |
Ingress
기본적으로 Kubernetes에서는 Service의 NodePort 또는 LoadBalancer를 사용해야 외부에서 접근 가능하지만, Ingress를 활용하면 보다 정교한 라우팅을 설정할 수있다. 허용 설정만 해주면 나머지는 전부 금지된다.
클라이언트 → Ingress Controller → Kubernetes 서비스 → Pod
# app=backend 라벨이 있는 Pod에 대해 app=frontend인 Pod에서만 접근 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend # 적용 대상 Pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # frontend만 backend에 접근 가능
ports:
- protocol: TCP
port: 80 # 80 포트 허용
🚨 주의할 점: ingress 필드는 리스트 형태여야 한다.
NetworkPolicy의 ingress 필드는 여러 개의 규칙을 정의할 수 있도록 리스트([]) 형태를 가져야 한다. (최소한 -로 시작하는 배열)
모든 Ingress 허용
ingress:
- from:
- podSelector: {} # 모든 Pod에서 허용
ports:
- protocol: TCP
port: 80
# 또는
ingress:
-
ports:
- protocol: TCP
port: 80
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
Egress
클러스터 내부에서 외부(인터넷 등)로 나가는 트래픽을 제어하는 네트워크 정책리소스이다.
- 클러스터 내부 Pod가 외부 인터넷에 접근할 수 있도록 제한
- 기본적으로 쿠버네티스는 모든 외부 트래픽을 허용하지만 NetworkPolicy를 설정해서 Egress 제어가 가능하다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress
namespace: default
spec:
podSelector:
matchLabels:
app: backend # backend Pod에 적용
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.10/32 # 특정 DB 서버만 허용(10.0.0.10/32 IP로만 Egress 허용)
ports:
- protocol: TCP
port: 3306 # MySQL 포트 허용
포트 범위 지정
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports: # 대상 포트가 32000에서 32768 사이에 있는 경우
- protocol: TCP
port: 32000
endPort: 32768
모든 Ingress 및 Egress 차단
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector: {} # 네임스페이스 내 모든 Pod에 적용
policyTypes:
- Ingress
- Egress
[ 실습 ] Egress 적용
controlplane ~ ➜ vi internal-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: internal-policy
namespace: default
spec:
podSelector:
matchLabels:
name: internal
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
name: payroll
ports:
- protocol: TCP
port: 8080
- to:
- podSelector:
matchLabels:
name: mysql
ports:
- protocol: TCP
port: 3306
controlplane ~ ➜ kubectl create -f internal-policy.yaml
networkpolicy.networking.k8s.io/internal-policy created
controlplane ~ ➜ kubectl get netpol
NAME POD-SELECTOR AGE
internal-policy name=internal 5m17s
payroll-policy name=payroll 16m
controlplane ~ ➜ kubectl describe netpol internal-policy
Name: internal-policy
Namespace: default
Created on: 2025-02-04 06:53:35 +0000 UTC
Labels: <none>
Annotations: <none>
Spec:
PodSelector: name=internal
Not affecting ingress traffic
Allowing egress traffic:
To Port: 8080/TCP
To:
PodSelector: name=payroll
----------
To Port: 3306/TCP
To:
PodSelector: name=mysql
Policy Types: Egress
[ 실습 ] app:web 레이블을 가진 Pod에 특정 namespace의 Pod들만 접근 허용시켜보자
- app:web Pod 생성하기
- namespace 생성 및 라벨링
- purpose=production인 namespace에서만 ingress가 가능하도록 만들기
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-allow-prod
namespace: default
spec:
podSelector:
matchLabels:
app: web # only accessible when have this label
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: production
ports:
- protocol: TCP
port: 80
controlplane:~$ kubectl get netpol
NAME POD-SELECTOR AGE
web-allow-prod app=web 31s
controlplane:~$ kubectl describe netpol web-allow-prod
Name: web-allow-prod
Namespace: default
Created on: 2025-02-28 13:39:57 +0000 UTC
Labels: <none>
Annotations: <none>
Spec:
PodSelector: app=web #app=web인 파드에
Allowing ingress traffic: # 80포트로 들어오는 label 규칙을 만족하는 pod에서만 ingress 허용된다.
To Port: 80/TCP
From:
NamespaceSelector: purpose=production
Not affecting egress traffic
Policy Types: Ingress
- 접근 실패
- 접근 성공
NetworkPolicy | Ingress | Egress | |
목적 | Pod 간 네트워크 트래픽 제어 | 외부 → 클러스터 내부로 들어오는 트래픽 제어 | 클러스터 내부 → 외부로 나가는 트래픽 제어 |
적용 대상 | Pod 간 통신 (Ingress & Egress) | HTTP/HTTPS 요청 | Pod에서 외부 네트워크로 나가는 요청 |
설정 방식 | NetworkPolicy 리소스 | Ingress 리소스 | NetworkPolicy의 Egress |
보안 기능 | 내부 트래픽 제한 가능 | 외부에서 들어오는 트래픽 보호 | 외부 접속 제한 가능 |
예제 | 특정 네임스페이스에서만 접근 허용 | /api 경로를 특정 서비스로 라우팅 | 특정 IP(예: DB)만 허용 |
'Container > Kubernetes' 카테고리의 다른 글
[K8S] Network & CNI (0) | 2025.02.06 |
---|---|
[K8S] Deploy a Kubernetes Cluster using Kubeadm (0) | 2025.02.06 |
[K8S] Security Context (0) | 2025.02.03 |
[K8S] Image Security (0) | 2025.02.03 |
[K8S] Service Account(SA) (0) | 2025.02.03 |