Kubernetes 에서 네임스페이스 네트워크 격리 및 특정 포트 허용하기 (Calico)

리눅스/DaaS|2024. 7. 22. 15:05
반응형

Kubernetes 에서 네임스페이스 내의 Pod 끼리 통신을 허용하고 모든 외부의 접근은 차단 시킬 수 있습니다. 또한 특정 서비스 접근이 필요한 경우 포트를 허용하여 접근하게 할 수 있습니다.

아래 웹페이지 내용을 참고하여 재작성하였습니다.

- 출처 : https://www.qovery.com/blog/basic-network-isolation-in-kubernetes/

 

 

1. 애플리케이션 생성

 

애플리케이션을 배포하고 외부에서 접근하기 위한 네트워크 설정 예제 입니다.

애플리케이션에 도메인 연결 필요시 다른 포스팅을 참고해 주세요.

(https://sysdocu.tistory.com/1851 , '5) Ingress 생성' 부분)

 

1) Namespace

애플리케이션을 생성하고 배포할 작업공간을 생성합니다.

# vi namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: sysdocu
  labels:
    role: sysdocu

 

# kubectl apply -f namespace.yaml

 

2) Deployment 생성

Deployment 를 사용하면 Pod 생성 및 여러가지 옵션을 추가하여 다양한 구성이 가능합니다.

Deployment yaml 파일을 작성합니다.

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: sysdocu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f deployment.yaml

 

3) Service 생성

네트워크 접근이 가능하도록 Service 를 생성해 줍니다.

테스트 목적이긴 하지만 외부 네트워크에서 접근이 되도록 해보겠습니다.

Service yaml 파일을 작성합니다.

# vi service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: sysdocu
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      nodePort: 30080  # 외부 트래픽이 접근하는 노드의 포트 (범위 : 30000~32767)
      port: 80                # 클러스터 내에서 서비스가 노출되는 서비스 포트
      targetPort: 80      # Pod 의 컨테이너가 리스닝하는 포트

 

* 참고

Service 에서 생성할 type 은 ClusterIP, NodePort, LoadBalancer 가 있습니다.

- ClusterIP : 클러스터 내부 통신만 가능한 IP

- NodePort : worker 노드의 IP 와 지정한 포트 (30000~32767 로 제한) 를 이용해 Pod 에 연결 가능

- LoadBalancer : 별도의 공인 IP 가 할당되고, 포트를 마음대로 사용 가능 (베어메탈 환경에서는 MetalLB 를 설치 필요)

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f service.yaml

 

외부 네트워크에서 애플리케이션에 접근되는지 확인합니다.

접근할 IP 는 Pod 가 위치하는 worker 노드인데, 아래 명령으로 확인 가능합니다.

# kubectl get pod -o wide

NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-694db9fb84-b5h2r   1/1     Running   0          7m22s   10.101.1.66   worker2   <none>           <none>

 

worker2 노드인것을 확인하였으며, 외부에서 worker2 노드의 공인 IP 와 위에서 설정한 포트 30080 으로 접근시 nginx 초기페이지가 출력되는것이 확인됩니다. 예제에서는 worker2 노드의 공인 IP 로 연결하였지만 실제로는 꼭 worker2 노드의 공인 IP 로 할 필요는 없습니다. NodePort 의 경우 master 또는 어떤 worker 노드로 연결하던 설정한 Pod 로 연결됩니다.

# curl 115.68.142.4:30080

 

 

2. 네트워크 정책 설정

 

Kubernetes 는 네트워크 방화벽처럼 작동하는 네트워크 트래픽을 허용/거부할 수 있는 네트워크 정책 (NetworkPolicy) 이라는 리소스를 제공합니다. 기본적으로 이 리소스를 사용하려면 먼저 이를 구현하는 Kubernetes Networking 플러그인 (Calico) 을 추가해야 합니다. 아래 URL 을 참고하세요.

(https://sysdocu.tistory.com/1851 , '4. Calico 설치' 부분)

 

아래 예제에서는 sysdocu 네임스페이스를 다른 모든 네임스페이스와 분리하되, sysdocu 네임스페이스 내에 배포된 모든 Pod 가 서로 연결 할 수 있도록 구성합니다.

 

1) 들어오는 모든 트래픽 차단

sysdocu 네임스페이스에 들어오는 트래픽을 차단하는 것은 다음과 같습니다.

# vi drop.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: no-inbound-traffic
  namespace: sysdocu
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels: {}

 

policyTypes : Ingress 는 들어오는 트래픽만 선택합니다. 참고로 나가는 트래픽 제어는 Egress 으로 변경하거나 추가하면 됩니다.

podSelector/matchLabels : 내용을 비우면 네임스페이스 내의 모든 Pod 에 규칙을 적용합니다. 입력 규칙이 정의되지 않았으므로 모든 것이 차단됩니다.

 

# kubectl apply -f drop.yaml

 

2) 동일한 네임스페이스 내의 Pod 간 트래픽 허용

sysdocu 네임스페이스 내의 모든 Pod 가 서로 통신할 수 있도록 하려면 네트워크 정책 규칙을 추가합니다.

# vi same.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace-traffic
  namespace: sysdocu
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          role: sysdocu

 

# kubectl apply -f same.yaml

 

3) 외부에서 들어오는 특정 포트 트래픽 허용

위에서 미리 만들어 둔 웹 애플리케이션 nginx 가 Pod 에서 80 포트로 서비스 되고 있습니다. 이를 공개적으로 액세스할 수 있도록 하려면 다음과 같은 규칙을 하나 더 추가해야 합니다.

# vi allow.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-port-80
  namespace: sysdocu
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - ports:
    - port: 80

 

# kubectl apply -f allow.yaml

 

주의할 것은, 노드의 포트 (30080) 가 아니고, Pod 의 포트 (80) 입니다.

이렇게 모든 Pod 를 선택하는 대신, sysdocu 네임스페이스의 레이블 app: nginx 가 있는 Pod 만 선택합니다. 그런 다음 규칙을 적용하면 누구나 웹 애플리케이션의 포트 80 번에 연결할 수 있습니다.

물론 외부에서 접근하기 때문에 NodePort 30080 으로 접근해야 합니다.

 

외부 네트워크 PC 에서 테스트 하는 방법입니다.

# curl 115.68.142.4:30080

 

4) 나가는 트래픽 모두 차단 (선택 사항)

네트워크 정책을 사용하여 트래픽이 나가는 것을 방지할 수도 있습니다.

차단 전에 테스트를 위해 telnet 패키지를 먼저 설치합니다.

Pod 이름은 먼저 확인해 주세요.

# kubectl exec -it nginx-deployment-7c79c4bf97-7wj9r -n sysdocu -- apt -y install telnet

 

구글 DNS 를 제외하고 모든 트래픽을 차단하는 설정입니다.

# vi drop.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: disable-outbound-traffic
  namespace: sysdocu
spec:
  policyTypes:
  - Egress
  podSelector:
    matchLabels: {}
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    - ipBlock:
        cidr: 8.8.4.4/32
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

 

# kubectl apply -f allow.yaml

 

Pod 쉘에 로그인하여 명령을 통해 확인해보면 됩니다.

# kubectl exec -it nginx-deployment-7c79c4bf97-7wj9r -n sysdocu -- bash

# telnet 164.124.101.2 53

# telnet 8.8.8.8 53

# apt update

 

반응형

댓글()