CKA를 준비해보자 26일차 - Network Policies

0

CKA

목록 보기
26/43

Network Policies

client-server구조에서 client가 web server에 요청을 보내어 traffic이 server안으로 들어오는 것을 ingress라고 한다.

반대로 server에서 client로 보내는 traffic을 egress라고 한다.

kubernetes cluster는 하나의 private network망으로, 내부의 각 pod들끼리의 통신을 지향한다. 즉, 내부의 모든 pod들은 각 pod들과 통신이 가능한데, 이를 All Allow방식이라고 한다. 문제는 이를 원치않는 pod가 있을 수 있다는 것이다.

가령, database의 경우 port 3306을 통해서 요청이 들어오면 data를 전달해주는데, 특정 api pod만 받고, 다른 pod의 요청은 무시하고싶다고 하자. 이를 위해서 하나의 policy를 새우는 것인데, 우리의 경우 database pod의 3306 port로 오는 ingress중에서 api pod만을 받도록 하자고 policy를 세우는 것이다.

그럼 어떻게 이 policy를 pod에 부여할 수 있을까?? 이는 service와 pod의 방식처럼 label과 label selector를 이용한다.

pod가 다음의 label을 가진다고 하자.

labels:
  role: db

network policy는 다음의 label selector로 pod를 지정할 수 있다.

podSelector:
  matchLabels:
    role: db

role: db라는 라벨을 가진 pod에 해당 network policy가 적용되는 것이다.

이제 network policy를 만들어보도록 하자. network policy는 다음의 rule을 가진다.

policyTypes:
- Ingress
ingress:
- from:
  - podSelector:
      matchLabels:
        name: api-pod
  ports:
  - protocol: TCP
    port: 3306

위의 rule은 api-pod라는 라벨을 가진 pod에 대해서만 ingress로 3306 포트만 허용하겠다는 것이다. 단, policyTypesIngress만 있으니 ingress만 적용되고 egress에 대해서는 적용되지 않는다. 따라서, 모든 egress에 대해서는 자유롭게 통신이 가능하다. 만약 egress역시도 추가하고 싶다면 policyTypes에 추가하면 된다.

이제 완전한 NetworkPolicy를 만들어보도록 하자.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          name: api-pod
    ports:
    - protocol: TCP
      port: 3306

단, NetworkPolicykube-router, calico, Romana, Weave-net과 같은 CNI에서는 제공하지만 Flannel에서는 제공하지 않는다.

특정 pod뿐만 아니라 namespace로 지정할 수도 있다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: prod
    ports:
    - protocol: TCP
      port: 3306

prod namespace에서의 모든 pod들에 대해서 db pod에 대한 3306 ingress 요청을 허용하겠다는 것이다.

ip로도 from을 설정할 수 있는데, 다음과 같다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.5.10/32
    ports:
    - protocol: TCP
      port: 3306

192.168.5.10/32 규칙을 만족하는 pod에 대해서만 3306 port ingress를 받겠다는 것이다.

만약 위의 podSelector, namespaceSelector, ipBlock을 같이 쓴다면 하나의 and조건처럼 사용된다.

참고로 ingress는 from을 쓰지만 egressto를 쓴다. 또한, policyTypesEgress를 추가해야한다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          name: api-pod
    ports:
    - protocol: TCP
      port: 3306
  egress:
  - to:
    - ipBlock:
        cidr: 192.168.5.10/32
    ports:
    - protocol: TCP
      port: 80

192.168.5.10/32 cidr를 만족하는 pod에 대해서 80 port egress를 허용한다는 것이다. 즉, db server가 192.168.5.10/32 cidr를 만족하는 pod에 대해서 80 port로 데이터를 보내는 것을 허용한다는 것이다.

마지막으로 DNS서비스를 이용하기 위해서 egresskube-dnsport들을 모두 열고, 다른 mysql, payroll pod에 egress요청을 보내는 코드를 확인해보도록 하자.

kube-system   kube-dns           ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   61m

53/UDP, 53/TCP이므로 DNS서비스를 이용하기 위해 egress network policy를 설정하도록 하자.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: internal-policy
spec:
  podSelector:
    matchLabels:
      name: internal
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          name: mysql
    ports:
    - protocol: TCP
      port: 3306
  - to:
    - podSelector:
        matchLabels:
          name: payroll
    ports:
    - protocol: TCP
      port: 8080
  - ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP 

0개의 댓글