콤퓨우터/필기: KodeKloud CKA 강의

177-178. Kubernetes Network Policy

파란화면 2024. 5. 17. 00:40
반응형

Kubernetes Network Security

여러 노드로 구성된 클러스터가 있다고 하자.
이 클러스터에는 노드, 서비스, Pod 등등이 존재한다.

  • 그리고 이 노드, 서비스, Pod에는 모두 IP가 존재한다.

쿠버에서는, (어떻게 구현을 했든지 상관없지만 아무튼) 같은 클러스터 내의 Pod들이 별도의 설정 없이도 서로 통신을 할 수 있어야 한다는 조건이 있다.

  • 예를 들어, 클러스터 전체가 VPN에 물려 있을 수도 있다. 이 경우 IP와 Pod/Service Name을 통해 서로에게 접근할 수 있을 것이다.
  • 기본적으로, 쿠버에서는, 클러스터 내부 Pod 간의 통신은 전부 허용 처리하는 것으로 되어 있다.

예를 들어 웹서버 Pod, API서버 Pod, DB Pod으로 구성된 애플리케이션에 대해 생각해보자.

  • Service를 생성하여 이 3개의 Pod간의 통신을 가능하게 할 수 있다.
  • 기본값으로는, 이 3개 Pod는 다른 클러스터 구성요소들과 자유롭게 통신이 가능하다.
    • 하지만 예를 들어, 프론트 서버가 DB 서버에 직접 접근하지 못해야 한다는 제약조건이 생긴다면?
      • Network Policy가 필요하다.

Network Policy

yet another Kubernetes object이다
NetworkPolicy를만든뒤, 1개 이상의 Pod에 물릴 수 있다.

  • 또 NetworkPolicy 내부에서 rule을 정할 수 있다.

label과 selector를 통해 어떤 NetworkPolicy를 어떤 Pod에 적용할지 선택 가능하다.

예를 들어, role: db label이 있는 Pod에서, Inbound 트래픽을 이름이 api-pod인 Pod에서 TCP/3306으로 들어오는 것만 허용하고, 나머지 Inbound 트래픽은 전부 차단하도록 구현해 보자.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels: # role:db label이 있는 Pod에 대해 해당 정책을 적용
      role: db
  policyTypes:
  - Ingress # 아래에서 허용된 것 이외의 모든 Inbound 트래픽은 차단

  ingress:
  - from:
    - podSelector: # api-pod에서 들어오는 TCP/3306 Inbound 트래픽을 허용
        matchLabels: 
          name: api-pod
    ports:
    - protocol: TCP
      port: 3306 

(참고: Ingress=Inbound, Egress=Outbound)

주의사항

앞에서 "어떻게 구현을 했든지 상관없지만 아무튼" 이라는 표현을 했다. 이것은 쿠버에 사용할 수 있는 네트워크 솔루션이 여러 가지 있기 때문이다. (kube-router, flannel, ...)
이 중, flannel은 NetworkPolicy를 지원하지 않는다.

네임스페이스와 Network Policy

만약 dev, test, prod 네임스페이스에 전부 api-pod이라는 이름의 API Pod이 존재한다고 해 보자.
위에서 만든 NetworkPolicy로는, 이 Pod들 전부가 prod.db에 접근할 수 있다.

prod 네임스페이스의 api-pod에서 보내는 요청만 받아들이도록 수정해보자.

  ingress:
  - from:
    - podSelector: # api-pod에서 들어오는 TCP/3306 Inbound 트래픽을 허용
        matchLabels: 
          name: api-pod
      namespaceSelector:
        matchLabels:
          name: prod

주의사항: 이렇게 NetworkPolicy를 만들기 전에, 해당 label의 namespace가 이미 생성되어 있어야 한다.

또, podSelector 없이 namespaceSelector만 사용하는 것도 가능하다.

Pod가 아닌 외부 엔티티의 접속

예를 들어, 외부 서버인 192.168.5.10에서 DB백업을 하기 위해 DB Pod에 접속해야 한다고 하자.
Pod이 아닌 외부 서버이기 때문에, podSelector는 이용할 수가 없다.

이런 상황의 대응을 위해 ipBlock selector가 존재한다.

  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.5.10/32

룰의 판정

  ingress:
  - from:
    - podSelector: # api-pod에서 들어오는 TCP/3306 Inbound 트래픽을 허용
        matchLabels: 
          name: api-pod
      namespaceSelector:
        matchLabels:
          name: prod

    - ipBlock:
        cidr: 192.168.5.10/32

다음과 같은 룰에서,

  • (podSelector AND namespaceSelector)가 1개의 rule이고,
  • ipBlock이 하나의 rule이다.
  • -로 분리된 각각의 rule은 또한 OR로 판정된다. (- 요건에 하나만 걸리면 OK판정)
반응형