개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 클러스터 유지와 보안, 트러블슈팅 - 네트워크 정책 적용

nineDeveloper 2021. 1. 22.
728x90

네트워크 정책 적용


네트워크 정책(Network Policy)

  • CNI 플러그인 Clico, Weavenet 을 설치해야지 사용가능
  • 포드 그룹이 서로 및 다른 네트워크 끝점과 통신하는 방법을 지정
  • NetworkPolicy 리소스는 레이블을 사용하여 포드를 선택
  • 선택한 포드에 허용되는 트래픽을 지정하는 규칙을 정의
  • 특정 포드를 선택하는 네임 스페이스에 NetworkPolicy가 있으면 해당 포드는 NetworkPolicy에서 허용하지 않는 연결을 거부


이그레스

https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource

  • 선택된 포드에서 나가는 트래픽에 대한 정책 설정
  • ipBlock을 통해 Block 하고자 하는 ip 대역 설정 가능
  • Ports에는 어떤 포드를 막고자 하는지 명시
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Egress # 외부로 나가는 정책을 막음
  egress:
  - to: # 나가는 예외 사항에 대한 정의
    - ipBlock: # 나가는 IP 대역 허용 설정
        cidr: 10.0.0.0/24
    ports: # 나가는 포트 허용 설정
    - protocol: TCP
      port: 5978

인그레스

https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource

  • 선택된 포드로 들어오는 트래픽에 대한 정책 설정
  • IpBlock은 기본적으로 막고자 하는 IP 대역을 설정하나
  • Except를 사용하여 예외 항목 설정 가능
  • NamespaceSelector와 podSelector를 사용
    • 그룹별 더욱 상세한 정책 설정 가능
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress # default deny 설정으로 변경됨
  ingress:
  - from: # 들어오는 예외 사항에 대한 정의
    - ipBlock: # 들어오는 IP 대역 허용 설정
        cidr: 172.17.0.0/16
        except: # 특정 IP 대역 제외 설정
        - 172.17.1.0/24
    - namespaceSelector: # 특정한 네임스페이스 에서만 접근 허용 설정
        matchLabels:
          project: myproject
    - podSelector: # 특정한 Pod 에서만 접근 허용 설정
        matchLabels:
          role: frontend
    ports: # 들어오는 포트 허용 설정
    - protocol: TCP
      port: 6379

인그레스 정책 만들어 보기

  • 앱 생성
$ kubectl run hello-web --labels app=hello \
--image=gcr.io/google-samples/hello-app:1.0 --port 8080 --expose
  • 네트워크 폴리시 적용
# hello-allow-from-foo
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1 
metadata:
  name: hello-allow-from-foo
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: hello
  ingress: 
  - from:
    - podSelector: 
        matchLabels:
          app: foo
  • 서로 다른 레이블을 가진 포드를 만들고 네트워크 폴리시 동작 확인
$ kubectl run -l app=foo --image=alpine --restart=Never --rm -i -t test-1 wget -qO- --timeout=2 http://hello-web:8080

$ kubectl run -l app=other --image=alpine --restart=Never --rm -i -t test-1 wget -qO- --timeout=2 http://hello-web:8080

여러 개의 정책이 겹치면 어떻게 될까?

  • OR 연산을 수행해 하나라도 허용하면 허용

이미지 출처: https://medium.com/@reuvenharrison/an-introduction-to-kubernetes-network-policies-for-security-people-ba92dd4c809d


실습

https://cloud.google.com/kubernetes-engine/docs/tutorials/network-policy?hl=ko

hellow-web server 및 pod 생성

$ kubectl run hello-web --labels app=hello \
  --image=gcr.io/google-samples/hello-app:1.0 --port 8080 --expose
service/hello-web created
pod/hello-web created

hello-allow-from-foo.yaml 파일 생성

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: hello-allow-from-foo
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: hello
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: foo

kubectl 로 생성 및 확인

$ kubectl create -f hello-allow-from-foo.yaml
networkpolicy.networking.k8s.io/hello-allow-from-foo created

$ kubectl get networkpolicy.networking.k8s.io
NAME                   POD-SELECTOR   AGE
hello-allow-from-foo   app=hello      34s

$ kubectl describe networkpolicy.networking.k8s.io
Name:         hello-allow-from-foo
Namespace:    default
Created on:   2021-01-22 12:02:40 +0900 KST
Labels:       <none>
Annotations:  <none>
Spec:
  PodSelector:     app=hello
  Allowing ingress traffic:
    To Port: <any> (traffic allowed to all ports) # 모든 포트에 대해서 허용
    From:
      PodSelector: app=foo # app=foo label에 대한 pod 만 받음
  Not affecting egress traffic # egress 외부로 나가는 트래픽 제한 사항 없음
  Policy Types: Ingress

label 이 app=foo 인 임시 pod 실행하고 shell 시작하고
hello-web:8080 엔드포인트에 들어오는 트래픽이 허용되는지 확인하도록 요청시
방화벽이 허용하여 통신이 잘되는 것을 확인할 수 있음

$ kubectl run -l app=foo --image=alpine --restart=Never --rm -i -t test-1
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://hello-web:8080
Hello, world!
Version: 1.0.0
Hostname: hello-web

label 이 app=other 인 임시 pod 실행하고 shell 시작하고
hello-web:8080 엔드포인트에 들어오는 트래픽이 허용되는지 확인하도록 요청
방화벽이 차단하여 time out 처리됨

$ kubectl run -l app=other --image=alpine --restart=Never --rm -i -t test-1
If you don't see a command prompt, try pressing enter.
/ # wget -qO- --timeout=2 http://hello-web:8080
wget: download timed out
/ #

연습문제

network-policy-exercise.yaml

# network-policy-exercise.yaml
apiVersion: v1
kind: Pod
metadata:
  name: http-go-v1
  labels:
    app: http-go-v1
spec:
  containers:
  - name: http-go
    image: gasbugs/http-go:v1
    ports:
    - containerPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
  name: http-go-v2
  labels:
    app: http-go-v2
spec:
  containers:
  - name: http-go
    image: gasbugs/http-go:v2
    ports:
    - containerPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
  name: http-go-v3
  labels:
    app: http-go-v3
spec:
  containers:
  - name: http-go
    image: gasbugs/http-go:v3
    ports:
    - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: http-go-v1
spec:
  selector:
    app: http-go-v1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: http-go-v2
spec:
  selector:
    app: http-go-v2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: http-go-v3
spec:
  selector:
    app: http-go-v3
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

kubectl 로 생성

$ kubectl create -f network-policy-exercise.yaml
pod/http-go-v1 created
pod/http-go-v2 created
pod/http-go-v3 created
service/http-go-v1 created
service/http-go-v2 created
service/http-go-v3 created

통신 확인 http-go-v3 만 안되는 것을 확인

$ kubectl exec -it pod/http-go-v3 -- curl http-go-v1
Welcome! v1

$ kubectl exec -it pod/http-go-v3 -- curl http-go-v2
Welcome! v2

$ kubectl exec -it pod/http-go-v3 -- curl http-go-v3
curl: (7) Failed to connect to http-go-v3 port 80: Connection refused
command terminated with exit code 7

https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource

network-policy-answer.yaml 파일 생성 후 위의 내용 참조해서 작성

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: http-go-v1-ingress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: http-go-v1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: http-go-v2

---

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: http-go-v2-ingress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: http-go-v2
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: http-go-v3

---

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: http-go-v3-ingress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: http-go-v3
  policyTypes:
  - Ingress

kubectl 로 ingress 정책 설정 적용

$ kubectl create -f network-policy-answer.yaml
networkpolicy.networking.k8s.io/http-go-v1-ingress created
networkpolicy.networking.k8s.io/http-go-v2-ingress created
networkpolicy.networking.k8s.io/http-go-v3-ingress created
  • ingress 정책 설정 후 통신 성공 테스트
    • http-go-v3 -> curl http-go-v2
    • http-go-v2 -> curl http-go-v1
$ kubectl exec -it pod/http-go-v3 -- curl http-go-v2
Welcome! v2

$ kubectl exec -it pod/http-go-v2 -- curl http-go-v1
Welcome! v1
  • ingress 정책 설정 후 통신 실패 테스트
    • http-go-v1 -> curl http-go-v2
    • http-go-v2 -> curl http-go-v3
    • http-go-v1 -> curl http-go-v3
    • http-go-v3 -> curl http-go-v1
$ kubectl exec -it pod/http-go-v1 -- curl http-go-v2
^Ccommand terminated with exit code 130

$ kubectl exec -it pod/http-go-v2 -- curl http-go-v3
^Ccommand terminated with exit code 130

$ kubectl exec -it pod/http-go-v1 -- curl http-go-v3
^Ccommand terminated with exit code 130

$ kubectl exec -it pod/http-go-v3 -- curl http-go-v1
^Ccommand terminated with exit code 130
728x90

댓글

💲 추천 글