일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- argocd
- 카오스 엔지니어링
- tekton
- opensearch
- Argo
- Model Serving
- xdp
- Litmus
- CI/CD
- Pulumi
- serving
- kubernetes operator
- 오퍼레이터
- eBPF
- Kubernetes
- Kopf
- opentelemetry
- CANARY
- MLflow
- keda
- seldon core
- Kubeflow
- nginx ingress
- knative
- mlops
- Kubernetes 인증
- blue/green
- gitops
- Continuous Deployment
- operator
- Today
- Total
Kubernetes 이야기
Network Policy 본문
Kubernetes에서는 다양한 Resource들 ( Deployment, Service, Secret, Configmap, PVC ... ) 존재한다. 이러한 Resource들은 Namespace에 속하고, RBAC 권한에 따라 다른 Namespace의 Resource들을 참조하지 못하도록 엄격하게 통제할 수 있다.
하지만, 네트워크의 경우 동일한 Cluster에서는 기본적으로 Network 격리가 안되고 모든 소스에서 트래픽을 받아들이도록 구성된다.
즉, 아래와 같이 Namespace 별로 배포된 앱에서 다른 Namespace의 앱을 직접 호출할 수 있다.
Kubernetes에서는 사용자 애플리케이션이 작동하는 컨테이너를 보호하기 위해 네트워크 폴리시 ( NetworkPolicy ) 를 이용해 네트워크에서의 접근을 제한할 수 있다.
네트워크 폴리지 규칙은 Kubernetes API에서 Query 되고 CNI ( Container Networking Interface ) Plugin ( 예: Calico, Cillium 등 )에 의해 시행된다.
네트워크 폴리시는 OSI 3 또는 4 계층 수준에서 트래픽 흐름을 제어한다. 또한 3가지 유형에 대해 접근 제한이 가능하며 그 유형은 아래와 같다.
1. 허용되는 파드
2. 허용되는 네임스페이스
3. IP 블록
클러스터 내의 데이터 트래픽은 네트워크 정책 없이는 완전히 제한되지 않으므로 모든 연결을 방지하는 네트워크 정책을 먼저 적용해야 한다. 그런 다음 추가 네트워크 정책(화이트리스트)을 통해 원하는 연결을 허용할 수 있다.
네트워크 폴리시는 podSelector 와 policyTypes 그리고 ingress, egress 를 이용해 설정한다.
podSelector | 네트워크 폴리시가 적용되는 파드를 설정한다. (필수) |
policyTypes | 네트워크 폴리시는 인그레스와 이그레스 각각에 트래픽 정책을 설정할 수 있다. 미 설정시 인그레스에 대해 정 책을 적용한다. 만약 policyTypes 에 Ingress 와 Egress 둘 다 설정이 되어 있으면 인그레스와 이그레스 모두에 대해 정책을 적용한다. ( 선택사항이지만 명시적으로 지정하는 것이 좋다. ) |
ingress | 화이트 리스트 기반의 ingress 규칙을 구성한다. ingress 규칙은 from 과 ports 로 설정하며 두 조건을 만족 하는 트래픽을 허용한다. (선택사항) |
egress | 화이트 리스트 기반의 egress 규칙을 구성한다. egress 규칙은 to 와 ports 로 설정하며 두 조건을 만족하는 트래픽을 허용한다. (선택사항) |
NetworkPolicy의 일반적은 구문은 아래와 같다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
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
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
설치된 네트워킹 플러그인이 네트워킹 정책을 지원하지 않으면 클러스터의 API 서버에 적용하더라도 효과가 없다.
예시
예시1) Namespace 들간의 네트워크 허용
- Namespace db에 Postgresql 배포
- Namespace app1에 nginx 배포
- Namespace app2에 nginx 배포
- db namespace에 app1 namespace만 허용하고 다른 namespace에서는 접근 금지
그럼 먼저 db namespace에 postgres를 설치해 보자. ( 테스트를 위한 것으로 별도 PVC는 없음 )
# kubectl create ns db
# cat <<EOF | kubectl create -n db -f -
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: postgres
name: postgres
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: postgres
serviceName: postgres-svc
template:
metadata:
labels:
app: postgres
spec:
containers:
- env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
value: test
- name: POSTGRES_PASSWORD
value: test
- name: POSTGRES_DB
value: test
image: postgres:12.4-alpine
imagePullPolicy: IfNotPresent
name: postgres
ports:
- containerPort: 5432
protocol: TCP
EOF
statefulset.apps/postgres created
# cat <<EOF | kubectl create -n db -f -
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: ClusterIP
clusterIP: None
ports:
- name: postgres
port: 5432
targetPort: 5432
protocol: TCP
selector:
app: postgres
EOF
이제 app1과 app2 namespace에 앱을 배포해 보자.
# kubectl create ns app1
# kubectl create ns app2
# cat <<EOF | kubectl create -n app1 -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
EOF
# cat <<EOF | kubectl create -n app2 -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
EOF
그럼 app1과 app2 namespace에서 db namespace의 postgres 접근이 되는지 확인해 보자.
# k exec -it -n app1 nginx-deployment-7848d4b86f-55t89 -- /usr/bin/curl postgres.db.svc.cluster.local:5432
curl: (52) Empty reply from server
command terminated with exit code 52
# k exec -it -n app2 nginx-deployment-7848d4b86f-krzwt -- /usr/bin/curl postgres.db.svc.cluster.local:5432
curl: (52) Empty reply from server
command terminated with exit code 52
참고로 간단히 테스트를 위해 curl로 postgres port인 5432 접근 여부만 확인하였다.
이제 아래와 같이 NetworkPolicy를 설정해 보자.
# cat <<EOF | kubectl create -n db -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db.postgres
namespace: db
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: app1
policyTypes:
- Ingress
EOF
이제 다시, nginx에서 postgres에 접근해 보자.
# k exec -it -n app1 nginx-deployment-7848d4b86f-55t89 -- /usr/bin/curl postgres.db.svc.cluster.local:5432
curl: (52) Empty reply from server
command terminated with exit code 52
# # k exec -it -n app2 nginx-deployment-7848d4b86f-krzwt -- /usr/bin/curl postgres.db.svc.cluster.local:5432
curl: (28) Failed to connect to postgres.db.svc.cluster.local port 5432: Connection timed out
command terminated with exit code 28
위와 같이 app2 namespace에서는 접근이 안되는것을 확인할 수 있다.
예시2) 특정 서비스에 대한 여러 조건에 대한 인그레스 트래픽 거부
아래와 같은 조건으로 테스트 해보자.
- db namespace 있는 app=postgres 인 label을 가진 pod에 대한 ingress 접근 제한 ( 외부에서 접근이 가능하도록 NodePort로 변경한다. )
- 10.10.0.0/16 ip 대역의 접근 허용
- namespace: app1에서 app=nginx label을 가진 pod의 접근 허용 (AND 조건임)
예시1에서 사용한 앱을 그대로 사용하고 아래와 같은 NetworkPolicy로 생성해 보자.
먼저 postgres service를 아래와 같이 수정한다.
cat <<EOF | kubectl create -n db -f -
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: NodePort
ports:
- name: postgres
port: 5432
targetPort: 5432
protocol: TCP
selector:
app: postgres
EOF
참고로, 외부 PC에서 접속하기 위해 externalTrafficPolicy를 Local로 설정해야 인식하는 경우가 있다.
Network Policy는 아래와 같다.
cat <<EOF | kubectl create -n db -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: network-policy
namespace: db
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 10.10.0.0/16
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: app1
podSelector:
matchLabels:
app: nginx
EOF
테스트결과
1) 10.10.x.x ip를 가진 PC에서 테스트 (성공)
# curl 10.60.200.122:30726
curl: (52) Empty reply from server
2) 10.60.x.x ip를 가진 PC에서 테스트 (실패)
# curl 10.60.200.122:30726
curl: (7) Failed connect to 10.60.200.122:30726; 연결 시간 초과
3) 같은 cluster상에 다른 pod에서 접근시 (실패)
# k exec -it sampleapp-67447b449f-v8jf2 -- /usr/bin/curl postgres.db.svc.cluster.local:5432
curl: (28) Failed to connect to postgres.db.svc.cluster.local port 5432: Connection timed out
command terminated with exit code 28
4) namespace2의 app: nginx label을 가진 pod에서 접근시 (실패)
# k exec -it -n app2 nginx-deployment-7848d4b86f-krzwt -- /usr/bin/curl 10.107.93.117:5432
curl: (28) Failed to connect to 10.107.93.117 port 5432: Connection timed out
command terminated with exit code 28
5) namespace1의 app: nginx2 label을 가진 pod에서 접근시 (실패)
# cat <<EOF | kubectl create -n app1 -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment2
labels:
app: nginx2
spec:
replicas: 1
selector:
matchLabels:
app: nginx2
template:
metadata:
labels:
app: nginx2
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
EOF
# # k exec -it -n app1 nginx-deployment2-577dd96cd7-fzzjd -- /usr/bin/curl 10.107.93.117:5432
curl: (28) Failed to connect to 10.107.93.117 port 5432: Connection timed out
command terminated with exit code 28
6) namespace1의 app: nginx label을 가진 pod에서 접근시 (성공)
]# k exec -it -n app1 nginx-deployment-7848d4b86f-55t89 -- /usr/bin/curl 10.107.93.117:5432
curl: (52) Empty reply from server
command terminated with exit code 52
참고자료
https://kubernetes.io/docs/concepts/services-networking/network-policies/
'Kubernetes > 보안' 카테고리의 다른 글
Container/Kubernetes Compliance ( 컨테이너/쿠베네티스 규정 준수 ) (0) | 2022.06.17 |
---|---|
Kubernetes scan 도구 - popeye (0) | 2022.05.15 |
Kubescape (0) | 2022.05.01 |
Falco로 Kubernetes 위협 탐지 모니터링 (3) | 2022.04.28 |
Kubernetes 에서 Vault 활용 (0) | 2022.03.14 |