클라우드/쿠버네티스

[Kubernetes] 6. 쿠버네티스 Service란? (NodePort, nginx 실습)

윤창이 2021. 5. 9. 02:45
728x90

[주의] 개인 공부를 위해 쓴 글이기 때문에 주관적인 내용은 물론, 쓰여진 정보가 틀린 것일 수도 있습니다!

피드백 부탁드립니다. (- -)(_ _) 꾸벅

 

k8s logo

 

https://kubernetes.io/ko/docs/concepts/services-networking/service/


[ Service ]

 위 그림을 보면, Service B는 10.10.10.2의 내부 아이피를 갖고있는 Pod와 그 옆에 10.10.10.3 ~ 10.10.10.4의 주소를 갖고 있는 Pod가 논리적으로 합쳐져 있음을 나타낸다. 물론 Service에도 내부 아아피가 부여되어있다. 마찬가지로 맨 밑에 그림처럼 Pod 하나만으로도 Service를 만들 수 있다. 

 

즉 Service란, Pod의 논리적 집합이며 어떻게 접근할지에 대한 정책을 정의해놓은 것을 말한다.

이 Service는 Label Selector 통해 어떤 Pod를 포함할지 정의가 가능하다. 

각 Pod의 IP로는 외부에서 직접적인 접근이 불가능하지만, 서비스는 이를 가능하게 허용해 준다.

 

Service.yaml에서 어떤 방식으로 외부에 노출시킬지에 대한 type에는 여러 종류가 있다.

  • ClusterIP (default) - 클러스터 내부에서만 접근 가능한 IP
  • NodePort - Port번호를 통해 외부에서 접근 (NAT 컨샙)
  • Load Balancer - 외부의 Load Balancer를 사용하는 방법
  • ExternalName - kube-dns 컴포넌트로 DNS를 이용하는 방법

 

이 글은 Nodeport에 대해 설명하며, minikube에서 실습을 후술하겠다.


[ NodePort 란? ]

Service와 Pod와 Node의 관계

 외부의 아이피가 192.168.1.1이면 31000번 Port를 통해 Node에 접근할 수 있다. (NodePort 서비스)

Node의 어느 Service를..? 어느 Pod로..?라는 의문이 생기는데, 이걸 yaml 파일에 미리 정의해두어 특정 Pod의 Application을 접근할 수 있게 되는 것이다. 

 

 즉 NodePort 서비스를 만든다는 것은 Service를 하나 만들어 외부의 어떤 Port 번호를 지정하여 붙게끔 하고, 내부의 어떤 Pod를 서비스할지를 Label Selector로 지정해주어 Target Port 번호를 정의하는 것이다.

 

NodePort는 30000 ~ 32767 대역의 포트 번호를 쓴다.

 


 

label과 selector예시

Service를 만들 때 지정해준 것

  1. 어떤 Pod를 묶을 것인지를 Selector로 지정 (app: MyApp)
  2. 외부에서 들어올 때 어떤 Port 값으로 들어올지에 대한 것

 


 

label과 selector예시2

label이 MyApp인 3개의 Pod를 Selector를 통해 서비스를 묶어주면 자동으로 연결되고, 자동으로 Load Balancing 기능을 수행하게 된다. (http://192.168.1.1:31000에 접근하게 되면 트래픽이 가장 원활한 곳에 자동으로 연결)

 


 

label과 selector예시2

서버가 세대인 경우에도, 레플리카 셋은 3개 만들라고 하면 스케줄러는 상황을 봐서 균등하게(이상적으로) 일거리가 가도록 만들어진다. 다른 곳에 흩어져있어도 Service를 정의할 때 selector를 MyApp이라 지정해주면 해당 라벨이 달린 파드만 자동으로 연결되는 서비스가 만들어진다. 

 

물론 서버마다 주소가 다르기 때문에 외부로 접근하는 주소는 3가지가 나오는데, 무조건 그 서버의 노드로 가는 것이 아니라, 논리적으로 서비스로 묶여있기 때문에 마찬가지로 트래픽 상황이 가장 좋은 노드(Load Balancing)로 접속하게 된다.

 

 


[ NodePort Service의 Yaml 파일 예시 ]

Yaml 파일 예시

 

- 오른쪽 Deployment yaml 파일

  • replicas는 하나 만듦
  • selector는 matchlabels로 "nginx-app"으로 지정
  • template에서 어떤 컨테이너를 지정할지 선택, 및 컨테이너 외부로 노출할 port 번호 지정

 

- 왼쪽 Service yaml 파일

  • selector로 "nginx-app" 지정
  • type은 NodePort 서비스로 지정 (맨 위에 여러 type 종류를 이미 기술했다.)
  • ports에서는 nodePort, ports, targerPort 등을 정의해준다. (왼쪽 그림 참조)
  • 오타가 있는데 끝에서 두 번째 줄 port 다음의 콜론 띄어쓰면 안된다

 

Yaml로 정의하여 배포하는 방법도 있지만 저걸 한 세월 적고 있기엔 하루는 너무 짧다 ㅜㅜ

가능한 명령형 커멘드를 통해 서비스를 배포할 수 있도록 하자 (하기는 expose 명령 예시)

$ kubectl expose deployment/nginx-deployment --type="NodePort" --port 80 --target-port=80 --protocol="TCP"

# 해당 명령은 현재까지는 아직 nodeport를 지정할 수 있는 파라미터가 없어 30000~32767 사이 포트가 랜덤으로 부여된다

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#expose

 


[ Minikube 실습 - 외부에 노출하기 ]

 

1. Minikube 실행

$ minikube start

 

 

2. nginx 예제 deployment 생성

$ vi nginx-deployment.yaml

아래 내용 적고 저장.

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

 

 

3. 만들었던 deployment.yaml 파일을 apply

$ kubectl apply -f nginx-deployment.yaml 

 nginx의 이미지로 3개의 Pod가 생겼다.

 

 

4. NodePort를 통해 외부로 expose

$ kubectl expose deployment/nginx-deployment --type="NodePort" --port 8080 --target-port=80 --protocol="TCP"

nginx-deployment라는 NodePort Service가 생성되었다.

 

 

5. describe 명령으로 자세한 정보 보기

$ kubectl describe services/nginx-deployment

 

 

6. 접속 확인

 아래 명령으로 nodes들의 정보를 자세히 표시 가능하다. minikube라는 노드에 접근해야 하므로 minikube 노드의 ip주소를 확인한다.

$ kubectl get nodes -o wide

 더 간단하게 아래 명령으로 minikube 노드의 ip 주소를 알 수 있다.

$ echo $(minikube ip)

 

services의 Port가 32161 이었으므로, (minikube node의 IP):32161로 nginx 서비스에 접근이 가능하다.

 

 

 

 

번외) expose 명령이 아닌, service.yaml 파일을 통해서도 Service 정의가 가능하다. 

 

nginx-service.yaml 파일에 아래 내용을 적고

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: NodePort     # 서비스 타입
  ports:
  - port: 8080       # 서비스 포트
    targetPort: 80   # 타켓, 즉 pod의 포트
    protocol: TCP
    name: http
  selector:
    app: nginx

 

yaml 파일 apply.

 

service가 정상적으로 올라갔고, node Port번호는 30058이다.

\

접속 확인

 

 


[ 만들어진 해당 Pod에 접속해보기 ] 

 

$ kubectl exec -it (Pod 이름) -- /bin/bash

 

접속 확인


 

728x90