네트워크 접근 제어(Network Policy)
k8s에는 Pod의 네트워크 접근을 제어할 수 있는 메커니즘이 존재한다. 다만, 모든 제품이 접근제어기능을 지원하지는 않고 일부 CNI(Container Network Interface)만 지원한다.
Network Policy 모듈 설치 - Canal
k3s 기본적으로 flannel을 네트워크 제공자로 사용한다. flannel에 Network Policy를 적용하려면 Canal을 설치해야 한다.
kubectl apply -f <https://docs.projectcalico.org/manifests/canal.yaml>
# configmap/canal-config created
# ...
# serviceaccount/canal created
# deployment.apps/calico-kube-controllers created
# serviceaccount/calico-kube-controllers created
쿠버네티스 네트워크 기본 정책
쿠버네티스 네트워크 기본 정책은 다음과 같다.
- 기본적으로 네트워크 정책은 없다.
- 하나도 설정된게 없다면 네임스페이스의 모든 트래픽이 열려있다. (default-allow)
- 만약 한 개의 네트워크 정책이라도 설정이 되면 정책의 영향을 받는 Pod에 대해서 다른 모든 트래픽은 막힌다. (default-deny)
NetworkPolicy 문법
관리자는 네트워크를 제어하기 위해서 NetworkPolicy 리소스를 사용한다. NetworkPolicy 정책은 네임스페이스 레벨에서 동작하며 라벨 셀렉터를 이용하여 특정 Pod에 네트워크 정책을 적용한다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- {}
egress:
- {}
- namespace: 네임스페이스를 지정
- podSelector: 적용할 Pod를 선택
- policyTypes: 정책의 유형
- ingress: 들어오는 트래픽 정책
- egress: 나가는 트래픽 정책
예제의 네트워크 정책의 의미는 default 네임스페이스에 대해서 전체 오픈된 규칙이다. 이는 default 네임스페이스에 존재하는 모든 Pod의 인바운드, 아웃바운드 트래픽이 열려져 있다는 것을 의미한다.
- podSelector: {}의 의미는 특정 라벨을 지정하지 않는 모든 Pod을 의미한다.
- policyType: 인바운드와 아웃바운드에 대해서 둘 다 규칙을 지정하는 것을 의미한다.
- ingress: - {}: 인바운드로 들어오는 모든 트래픽을 허용한다.
- egress: - {}: 아웃바운드로 나가는 모든 트래픽을 허용한다.
네트워크 구성
Private Zone
기본적으로 전체 인바운드 트래픽을 차단해 외부 트래픽이 들어올 수 없게 private zone으로 만든다.
# deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-all
namespace: default
spec:
podSelector: {}
ingress: []
deny-all은 빈 리스트([])를 선언한다, 이것은 0개의 정책을 허용한다는 것을 의미하며 default 네임스페이스에 대해서 기본적으로 모든 인바운드 트래픽을 막는다.
Web pod 오픈
# web-open.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-open
namespace: default
spec:
podSelector:
matchLabels:
run: web
ingress:
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 80
Web pod 오픈 보통 웹 서비스는 외부 사용자들이 서비스에 접근할 수 있도록 열어둔다. 하지만 전체 트래픽이 막혀있어서 run-web 라벨이 적용된 Pod의 80포트만 허용하려 한다. 다음과 같이 Wev-open 정책을 생성한다.
Web과의 통신만 허용된 app
# allow-from-web.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-from-web
namespace: default
spec:
podSelector:
matchLabels:
run: app
ingress:
- from:
- podSelector:
matchLabels:
run: web

DB 접근 Pod
DE도 마찬가지로 특정 white-list 서버와만 연결을 허용합니다.
# db-accessable.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: db-accessable
namespace: default
spec:
podSelector:
matchLabels:
run: db
ingress:
- from:
- podSelector:
matchLabels:
db-accessable: "true"
ports:
- protocol: TCP
port: 80
- 적용대상: run=db 라벨을 가진 Pod
- 허용소스: db-accessable=true 라벨을 가진 Pod에 대해서만 허용
- 허용포트: 80포트

DMZ zone 연결
웹 서버의 네트워크 보안을 높이고자 프록시 서버를 거쳐 웹 서버로 들어오게 합니다.
새로운 네임스페이스를 생성하여 해당 네임스페이스를 마치 DMZ zone처럼 사용합니다.
웹서버가 zone=dmz라는 라벨을 가진 스페이스로부터만 트래픽을 받게 설정합니다.
# allow-dmz.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-dmz
namespace: default
spec:
podSelector:
matchLabels:
run: web
ingress:
- from:
- namespaceSelector:
matchLabels:
zone: dmz
ports:
- protocol: TCP
port: 80
- 적용대상: run=web라벨을 가진 Pod
- 허용소스= zone=dmz라는 라벨을 가진 네임스페이스로부터 오는 트래픽만 허용
- 허용포트= 80포트

네트워크 구성 - Egress
네트워크 정책을 이용해 인바운트 트래픽 뿐만 아닌 아웃바운드 트래픽 또한 제어가 가능합니다.
dev 외에 아웃바운드 차단
사용자에게 개발용 네임스페이스를 제공하고 그 속에서만 서비스를 개발하고 운영 중인 다른 네임스페이스에는 원천적으로 접근을 차단하고 싶을 때 특정 네임스페이스의 아웃바운드를 모두 막을 수 있습니다.
# dont-leave-dev.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: dont-leave-dev
namespace: dev
spec:
podSelector: {}
egress:
- to:
- podSelector: {}
- 적용대상: dev 네임스페이스의 모든 Pod
- 허용소스= dev 네임스페이스 존재하는 모든 Pod 접근 가능
- 허용포트= 전체 포트 허용
Metadata API 접근 금지
클라우드 서비스에서 제공하는 서버의 경우 특정 ip를 이용하고 인스턴스의 메타 데이터를 읽을 수 있습니다.
보안상 사용자들이 직접 메타데이터에 접근하지 못하도록 ip를 차단하고 싶을 때 inBlock을 가지고 특정 IP 대역을 차단할 수 있습니다.
# block-metadata.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: block-metadata
namespace: default
spec:
podSelector: {}
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
0.0.0.0/0으로 모든 대역을 열지만 169.254.169.254/32 ip는 차단합니다.
AND & OR 조건 비교
Network Policy의 ingress 허용 조건을 AND 와 OR로 구분하여 정책을 설정할 수 있습니다.
AND 조건
from property의 리스트 원소를 2개의 podSelector로 선언할 경우 2개의 조건이 AND로 설정됩니다.
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: and-condition
namespace: default
spec:
podSelector:
matchLabels:
run: web
ingress:
- from:
- podSelector:
matchLabels:
shape: circle
- podSelector:
matchLabels:
color: red
OR 조건
아래처럼 각각의 from으로 선언할 경우 OR 로 표현할 수 있습니다.
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: or-condition
namespace: default
spec:
podSelector:
matchLabels:
run: web
ingress:
- from:
- podSelector:
matchLabels:
shape: circle
- from:
- podSelector:
matchLabels:
color: red
네트워크 정책 전체 스펙
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: full-network-policy # 정책의 이름
namespace: default # 정책이 적용될 네임스페이스
spec:
podSelector:
matchLabels:
role: db # 'role: db' 라벨을 가진 포드들에 이 규칙이 적용됨
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16 # 172.17.0.0/16 대역의 접속을 허용함
except:
- 172.17.1.0/24 # 단, 172.17.1.0/24 대역은 예외적으로 접속을 차단함
- namespaceSelector:
matchLabels:
project: dev # 'project: dev' 라벨이 붙은 네임스페이스 내 모든 포드의 접속 허용
- podSelector:
matchLabels:
role: web # 동일한 네임스페이스 내에서 'role: web' 라벨을 가진 포드의 접속 허용
ports:
- protocol: TCP
port: 3306 # 위 조건(1, 2, 3 중 하나라도 만족)을 충족할 때 TCP 3306 포트만 열어줌
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24 # 오직 10.0.0.0/24 대역으로 나가는 통신만 허용함
ports:
- protocol: TCP
port: 53 # 오직 TCP 53번 포트(보통 DNS 통신용)만 사용 가능함
'개발 > DevOps' 카테고리의 다른 글
| [Kubenetes] 접근제어 - HTTP Basic Authentication, X.509 인증서, RBAC (1) | 2025.12.23 |
|---|---|
| [Kubenetes] 스토리지 - PersistentVolume, PersistentVolumeClaim, StorageClass (1) | 2025.11.11 |
| [kubernetes] Ingress 리소스 - Basic Auth, cert-manager, Issuer (0) | 2025.11.04 |
| [kubernetes] helm 패키지 매니저 (0) | 2025.10.06 |