[K8s] Service Object

김지환·2022년 11월 12일
0

Service

파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법
쿠버네티스는 파드에게 고유한 IP 주소와 파드 집합에 대한 단일 DNS 명을 부여하고, 그것들 간에 로드-밸런스를 수행할 수 있다.

Service 를 왜 사용해야 하는가?

Pod들은 각자 고유한 IP address 를 할당 받는다. 또한 이를 이용해서 Pod 들 간의 통신이 가능하다. 하지만 Pod 는 영구적이기 보다는 일시적인 특징을 갖는다. 그 예로 Deployment 형태로 배포를 하게 된다면 Pod는 뜨고 짐을 반복할 수 있다.

이렇게 Pod 가 재생성 될 때마다 Pod의 IP는 계속 바뀌게 된다. 따라서 Pod 간의 Networking binding 을 Hard coding방식으로 묶을 수 없다.

이러한 문제를 Serivce reousrce 를 사용하여 해결 할 수 있다.

Service 명세서

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

위 명세는 대상이 될 Pod 의 TCP port 9376 을 열기 위한 설정이다. Service object 가 생성되면 spec.selector에 설정된 정보에 매칭되는 Pod 를 스캔한다. 그 후 Endpoints object 에 해당 내역을 Update 한다.
만약 Selector가 존재하지 않는다면 service 는 연결될 Pod 가 없기 때문에 Endpoint object 는 형성되지 않는다. ( 따로 Endpoint 객체를 만들어서 연결해줄 수 있음 이 때 service object 와 같은 이름으로 만들어 주어야 한다. )

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service #<------ Should match the name of Service
subsets:
  - addresses:
      - ip: 192.0.2.45 << 목표 Pod의 IP
    ports:
      - port: 9376

spec.ports

아래에는 port, targetPort, nodePort 등을 정의할 수 있다.

port 는 Service 객체가 외부에서 받아들일 때의 포트번호이고 targetPort는 service가 받은 요청을 pod에게 전달할 때 전달할 포트의 번호이다.

nodePort는 Service의 NodePort 타입을 사용할 때 각 node에게 어떤 port 를 열어서 cluster 외부의 요청을 받을지를 설정할 때 사용하게 된다.

Service type

External Name

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: github.com

위와 같이 type을 ExternalName으로 지정하고 externalName 에 지정하고자 하는 외부 DNS를 기입하면 된다.

위와 같이 연결을 해주게 되면 pod 는 해당 service를 보는 것으로 외부 DNS에 접근이 가능하게 되고 Pod의 재배포에 상관없이 service만 재배포 해준다면 파드의 변경 없이 자유롭게 DNS를 변경할 수 있다.

NodePort

Service 를 특정 node의 포트 번호를 통해 노출시키게 하는 방식이다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: MyApp
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 80
      targetPort: 80
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30007

type: NodePort를 설정해주면 된다.

NodePort는 특별한 설정을 하지 않았다면 service-node-port-range 인 30000-32767 번 사이에서 부여받게 된다.

이렇게 Service 가 등록되면 Cluster 내의 모든 node 에서 해당 port 번호를 해당 service와 맞추게 된다.

nodePort의 번호를 지정하고 싶다면 spec.ports.nodePort에 직접 값을 넣어주면 된다.

LoadBalanceer

별도의 외부 로드 밸런서를 제공하는 클라우드(AWS, Azure, GCP 등) 환경을 고려하여, 해당 로드 밸런서를 클러스터의 서비스로 프로비저닝할 수 있는 LoadBalancer 유형도 제공된다.

이 유형은 서비스를 클라우드 제공자 측의 자체 로드 밸런서로 노출시키며, 이에 필요한 NodePort와 ClusterIP 역시 자동 생성된다. 이때 프로비저닝된 로드 밸런서의 정보는 서비스의 status.loadBalancer 필드에 게재된다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.0.171.239
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 192.0.2.127

이렇게 구성된 환경에서는, 외부의 로드 밸런서를 통해 들어온 트래픽이 서비스의 설정값을 따라 해당되는 파드들로 연결된다. 이 트래픽이 어떻게 로드 밸런싱이 될지는 클라우드 제공자의 설정에 따르게 된다.

만약 이러한 방식의 로드 밸런서 프로비저닝을 지원하지 않는 클라우드 환경일 경우, 이 유형으로 지정된 서비스는 NodePort와 동일한 방식으로 동작하게 된다.

Service 의 활용

Headless service

로드 밸런싱과 단일 서비스 IP가 필요하지 않을 경우가 있는데 이 때 Headless service 를 이용할 수 있다.

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None

Headless 서비스의 경우 클러스터 IP 가 할당되지 않고, kube-proxy가 이러한 서비스를 처리하지 않기 때문에 플랫폼에 의해 로드밸런싱 또는 프록시 되지 않는다.

Headless 를 만들기 위해서는 Pod 또한 hostname, subdomain설정을 해주어야 한다.

apiVersion: v1
kind: Pod
metadata:
  name: application
spec:
  hostname: nginx
  subdomain: headless-service
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

위와 같은 설정으로 아래와 같이 DNS가 형성된다.

FQDN (Fully Quailified Domain Name )

podname.servicename.namespace.svc.cluster.local

application.headless-service.default.svc.cluster.local

따라서 Pod 가 재생성됨에 상관없이 고정된 DNS를 가질 수 있다.

Reference

https://ykarma1996.tistory.com/179
https://kubernetes.io/docs/concepts/services-networking/#the-kubernetes-network-model

profile
Developer

0개의 댓글