k8s/concept

service/ service type > ClueterIP & NodePort & LoadBalancer

부엉이사장 2023. 12. 5. 18:39

## clusterIP

 

service/ 개념 & test

# deployment를 쓰는이유? 고가용성! 이렇게 deployment로 생성된 세개의 nginx pod들이 있다고 가정하자. 일단 우리가 deployment컨트롤러로 동일한 pod 세 개를 운영하는 목적은 뭐였니? 고가용성을 보장하

jacobowl.tistory.com

이전 포스팅에서 실제로 서비스를 만들어보면서 만든게 clusterIP타입 서비스이다.

서비스를 만들때 type을 딱히 안정해주면 알아서 clusterIP타입 서비스를 만들어준다.

떄문에 자세한 설명은 생략을 하려한다.

부족한부분을 몇개 추가하자면..

 

 

 

# yaml형식 + clusterIP 커스텀

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    pod-service: muzzi
  clusterIP: 10.96.1.1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

서비스 yaml양식에서 서비스의 spec필드에 clusterIP필드를 추가할 수 있다.

참고로 spec필드에 바로 type: ClusterIP로 정해줘도 된다. 안정해줘도 되고..

우리가 이전 포스팅에서 clusterIP필드는 설정하지 않았었는데 이렇게 설정안하면 클러스터IP가 임의로 랜덤하게 생긴다.

하지만 이걸 직접 설정해서 만들어줄수도 있다.

이 아이피는 10.96.0.0/12대역대로 만들어야 한다고 한다. k8s환경 네트워크에 제한을 받나보다.

한번 만들어보면

kubectl get svc

이렇게 지정한 clusterIP로 서비스가 만들어진다.

아 svc는 service의 약자이다. 커맨드상에서 쓰기 편하라고.. 난 탭충이지만

 

 

 

# clusterIP를 ㅈ대로 넣었을때

난 clusterIP필드에 1.1.1.1이라는 내 맘대로 아이피를 만들어서 넣었다.

10.96.0.0/12대역대 아이피 쓰라고 나온다..

근데 이전에 10.99.0.0/?아이피 대역대로 자동으로 만들어졌는데.. 그래서 이 대역대로 맘대로 넣어봄.

kubectl create -f test-svc.yaml

만들어진다ㅋ

물론 10.96.0.0/12대역대도 만들어진다.

 

 

 

 

 

## NodePort

얘는 clusterIP타입을 포함하는 상위버전의 service이다.

모든 기능은 clusterIP타입과 똑같지만, 이름그대로 NodePort를 열어준다.

service로 관리되는 pod들이 각각의 노드에 띄워져 있는데, 이 노드의 아이피를 지정한 nodePort로 (그림에선 30007번을 노드포트로 함) 열어주고 이 포트로 들어가면 해당 pod의 80포트와 link시켜준다.

그럼 외부에서 이 nginx컨테이너가 띄운 웹사이트에 접속 할 수 있게 되는거다.

 

 

 

# yaml 양식

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: MyApp
  ports:
      # 기본적으로 그리고 편의상 `targetPort` 는 `port` 필드와 동일한 값으로 설정된다.
    - port: 80
      targetPort: 80
      # 선택적 필드
      # 기본적으로 그리고 편의상 쿠버네티스 컨트롤 플레인은 포트 범위에서 할당한다(기본값: 30000-32767)
      nodePort: 30007

공식문서에서 가져온 NodePort타입의 서비스 yaml형식인데, 걍 clusterIP타입과 다 똑같다.

다만 spec필드에 type을 NodePort로 설정해줬고, ports필드에 nodePort: <원하는 포트>형식으로 되어있다.

공식문서 yaml주석에 써있는데 30000~332767범위내로 쓰라고 한다. 

더해서 yaml에서 nodePort필드로 포트를 안정해준다면 저 범위내에서 랜덤하게 만들어준다.

 

 

 

 

 

# 직접 해볼까?

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    pod-service: muzzi
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30007

난 이전 포스팅에서 실험했던 service를 그대로 가져왔고 그 곳에 type: NodePort랑, ports필드에 nodePort: 30007이란 내용을 추가했다. 그리고 서비스를 생성해보자.

(참고로 이전에선 service와 deployment를 한 yaml파일에서 같이 생성했지만, 이번에는 두 개를 분리했다.)

 

kubectl create -f test-node.yaml

뭐 경고문이 뜨지만 만들어지긴 했다.

 

그리고 deployment도 만들자.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      pod-deployment: dori
  template:
    metadata:
      labels:
        pod-deployment: dori
        pod-service: muzzi
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
kubectl create -f test-svc-deployment.yaml

 

 

이렇게 만들면 준비가 된거다. 아까 보여줬던 그림이랑 똑같은 구조다.

암튼 node아이피에 30007번 포트로 접속을 브라우저 하나 띄워서 해보면

웹사이트를 쿠버네티스 환경이 아닌 외부에서도 접근이 가능하게 되었다.

 

 

 

# 노드포트 확인하기

kubectl get service

이 명령어로 서비스 리스트를 보게되면,

이렇게 노드포트를 확인 할 수 있다.

# 한 node에 두개의 pod가 만들어졌고 nodePort로 접속할때 어떤 pod가 요청을 받을까?

그림으론 이렇다. 워커노드2에 pod가 두 개 생성되었다.

워커노드는 아이피가 하나고 30007번 포트로 접속하면 해당 pod에 접속되게 NodePort서비스가 설정해줬는데, 만약 pod가 두 개이면 이 곳중 어디에 접속할까? 로드벨런싱으로도 될까?

난 node가 두 개 이기때문에 pod를 총 3개 뿌리면 두개는 한 node에 생성된다.

현재 보면 worker1노드에 pod 두 개가 생성되었다.

이제 외부에서 접속을 여러번 시도해보겠다.

그래서 해봤는데,

kubectl logs 파드이름

각 두 pod에서 접속로그를 보니까 fjm머시기 pod에만 접속이된다.

즉 nodePort로 접속했을때 두개이상의 pod일경우 로드밸런싱은 안되고 한 pod에만 접속기록이 남는걸 볼 수 있다.

어떤 pod를 선택하는지 어떤 기준인지는 모르곘다. get pods에서 순서대로 먼저있는거 선택하는것도 아니니까..

암튼 nodePort로 접속할경우 하나의 pod에만 접속이 된다.

 

근데 좀 시간지나서 해보니까 이번엔 다른 pod에만 접속이 된다.

거참 모르것네

 

 

 


# netstat

netstat -napt | grep 30007

난 안뜬다..

뭐가문젠지 모르겠음.. loaf ss nmap까지 다 확인해봤는데 안뜬다.

분명 외부로 포트가 열려서 크롬에서 접속이 됐는데 무슨이유인지 모르곘다.

 

 

++ 궁금점

마스터 노드의 아이피의 30007번 포트로 접속하면 이 service의 clusterIP로 접속하고 로드벨런싱하게 각각 pod의 웹사이트에 들어갈수 있는거 아닐까? 했는데 안되더라.

gpt한테 물어보니 마스터노드는 보안상 왠만해선 접속 못하게 해야한대서 그렇단다. 그럼 사실 master node에서 로드벨런싱은 관리자인 나만 쓸수있는건데.. 했는데 ingress배우라더라..  다음에 배울 type LoadBalancer 서비스로도 할 수 있긴한데 이건 퍼블릭 클라우드 구입해야 하니까.. 쩝

 

 

 

# LoadBalancer타입

얘는 퍼블릭클라우드를 써야된다는데 뭐 난 돈이없으니 못할것같고

암튼 얘는 위에 말한 clusterIP타입과 nodePort타입 둘다에다가 +외부 로드벨런서까지 해서 nodePort로 열린 서비스가 외부 로드벨런서로 접속할 수 있게 하는거다.

사실 구현해보지 못해서 잘 모르겠다만 service yaml쪽에 외부 로드벨런서를 명시해주거나 할것같음..

암튼 이런타입이라고 한다.

 

# 만들어나 보자~ yaml 형식

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    pod-service: muzzi
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

 

이게 yaml형식인데 이걸로 만들어보자.

 

kubectl create -f test-load.yaml

이렇게 만들었는데 external-ip컬럼이 pending이다. 외부 로드벨런서가 없기때문이다.

만약 외부 loadBalancer를 만들게 된다면 loadBalancer장비의 ip가 이곳에 나타나게 될 것이고

이곳에 접속하면 pod들에 연결시켜줄거다.

또한 포트를 보면 80:32565로 nodePort까지 열어주었고 type에 loadBalancer로 나와있다.

 

 

 

# 서비스 기능 종속개념

컨트롤러러처럼 deployment를 만들면 replicaSet이 자동으로 생성되는 개념이 아니라, 하위개념의 기능들을 포함하는걸 말한다. 

가장 기본적인 clusterIP 서비스는 컨트롤러로 만든 pod들에 loadBalancer로 접근하는 단일진입점 IP인 clusterIP를 생성해준다.

이 기능을 포함하여 NodePort서비스는 이 pod들이 있는 각각의 Node에 외부포트를 열어주고 이 외부포트를 pod들의 외부포트와 연결해준다.

마지막으로 LoadBalancer 서비스는 위에 두 기능을 모두 포함하는데, 각 Node에 열린 nodePort들에 연결된 퍼블릭 LoadBalancer을 연결시켜준다. 이 외부 로드밸런서는 L4장비일것이다.

 

 

 

 

'k8s > concept' 카테고리의 다른 글

service/ headless service  (0) 2023.12.07
service/ k8s의 dns구성, service type> externalName  (0) 2023.12.06
service/ 개념 & test  (0) 2023.12.04
controller/ cronJob  (0) 2023.12.03
controller/ job  (0) 2023.12.02