Engineering/Kubernetes (K8S)

[Kubernetes] 쿠버네티스 서비스(Service) Deep Dive - (4) Nodeport

[앙금빵] 2022. 6. 8.

 

리마인드 - 서비스 타입

서비스에는 여러 종류가 있으나, 주로 사용하는 타입은 3가지이다.

① Cluster IP 타입
쿠버네티스 내부에서만 포드에서 접근할 때 사용한다. 외부로 Pod를 노출하지 않기 때문에 쿠버네티스 클러스터 내부에서만 사용되는 Pod에 적합하다.

② NodePort 타입
Pod에 접근할 수 있는 포트를 Cluster의 모든 Node에 동일하게 개방한다. 따라서 외부에 Pod에 접근할 수 있는 서비스 타입이다. 접근할 수 있는 포트는 랜덤으로 정해지지만 특정 포트로 접근하도록 설정할 수도 있다.

③ LoadBalancer 타입
클라우드 플랫폼에서 제공하는 Load Balancer를 동적으로 Provisioning하여 포드에 연결한다. NodePort 타입과 마찬가지로 외부에서 포드에 접근할 수 있는 서비스 타입이다. 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼 환경에서만 이용할 수 있다.


NodePort 서비스 개요

앞서 실습한 ClusterIP는 외부에서 접근할 수 없으며 쿠버네티스 내부에서 접근할 때 이용되는 리소스이다. 그렇기에 클라이언트가 생성한 Service에 접근하기 위해서는 어떤 중간 매개체를 요구하게 된다. 이를 충족시켜 줄 첫번째 방법으로 NodePort 타입의 서비스를 사용하는 것이다.

 

노드포트 타입으로 서비스를 생성하면 쿠버네티스는 모든 노드에 특정 포트를 할당하며 서비스를 구성하는 파드로 들어오는 트래픽을 전달한다. 아래 그림과 같이 모든 노드에 대하여 동일한 포트 번호(30080)가 열려 있다. 그렇기에 어느 노드에 서비스 파드가 존재하던지 간에 노드포트를 통해 파드와 통신이 가능하다.

 

NodePort 서비스 생성

이제 노드포트를 생성해보자. 노트포트 서비스의 YAML 파일은 다음과 같다.

apiVersion: v1
kind: Service
metadata:
  name: kiada
spec:
  type: NodePort #서비스 유형을 노드포트로 설정
  selector:
    app: kiada
  ports:
  - name: http
    port: 80 #서비스 내부 클러스터 IP 포트
    nodePort: 30080 #각 클러스터의 노드의 포트 30080으로 서비스에 접근할 수 있다.
    targetPort: 8080 #서비스 대상 파드의 포트
  - name: https
    port: 443
    nodePort: 30443
    targetPort: 8443
NOTE
nodePort 항목을 반드시 지정해야 하는 것은 아니다. nodePort를 생략하면 쿠버네티스가 자동으로 임의의 포트를 선택한다. 이러한 방법으로 다른 nodePort 서비스와의  포트 충돌을 예방할 수도 있다.

 

앞서 생성한 NodePort 서비스는 총 6개의 다른 포트번호를 가진다. 복잡하게 들릴 수도 있겠지만, 아래 그림을 통해 생성한 서비스 구조를 이해하도록 하자.

 

생성한 서비스의 기본 정보를 살펴보자. 앞서 생성한 2개의 ClusterIP 서비스와는 달리 80:30080, 443:30443 항목을 확인할 수 있다. 현재 생성한 NodePort 서비스의 IP:Port 의 조합은 2개이지만, 만약 여러개인 경우 이러한 조합들을 일일이 파악하기 어렵다. 쿠버네티스에서는 NodePort 서비스에 설정된 IP:Port 항목을 일일이 기억할 필요 없이 kubectl get nodes -o wide 의 명령어를 쳤을 때 확인할 수 있는 INTERNAL-IP 와 EXTERNAL-IP 항목을 보면 된다.

만약, Cloud 환경에서 쿠버네티스가 동작하는 경우 EXTERNAL-IP가 존재한다. 나는 로컬환경(베어메탈)에서 구현하였기에 EXTERNAL-IP 항목이 존재하지 않는다.

 

앞서 언급했듯이, NodePort 의 특징은 모든 노드에 특정 포트를 할당한다. 이를 통해 서비스에 접근하기 위해 다양한 방법이 존재하며, 아래 예시는 80:30080에 대한 서비스 접근 방법이다. 443:30443 도 마찬가지로 같이 적용된다.

 

  • ClusterIP : Internal Port
    10.99.142.250: 80

  • INTERNAL-IP : nodePort
    - 192.168.100.10:30080 (ControlPlane External IP+ nodePort)
    - 192.168.100.101:30080 (node 1 External IP + nodePort)
    - 192.168.100.102:30080 (node 2 External IP + nodePort)
    - 192.168.100.103:30080 (node 3 External IP + nodePort)
root@k8s-m:~# curl 192.168.100.10:30080

... 중간내용 생략 ...

==== REQUEST INFO
Request processed by Kiada 0.5 running in pod "kiada-003" on node "k8s-w2".
Pod hostname: kiada-003; Pod IP: 172.16.46.4; Node IP: 192.168.100.102; Client IP: ::ffff:172.16.29.0

 

Controlplane IP : nodePort(30080) 을 입력하였지만 다른 노드 k8s-w2 내에 엤는 kiada-003 파드와 통신이 된 것을 확인할 수 있다. 이는 Controlplane이 k8s-w2로 포워딩 하였다는 것을 시사한다.

 


참조

Kubernetes - in - Action 2nd Edition

 

 

댓글