[k8s] Service 리소스 Overview (1) 공부/CLOUD

Date 2021. 8. 14. 19:26

클러스터 내부에서든 외부에서든 실제 Workload를 받는 부분인 Pod에 접근하기 위해서는 Pod의 IP정보+ port를 알아야 한다.

 

Replication Controller가 조정할 수도 있고 Node가 죽어서 다른 Node 로 파드를 옮기는 등 쿠버네티스에서 Pod라는 리소스는 항상 죽을 수 있다. 즉 Pod를 식별하는 IP는 계속 변경된다.

 

이런 문제를 해결하기 위해서 Pod에 접근하는 고정된 IP가 필요한데, 이를 담당하는 오브젝트가 바로 Service 이다.

 

서비스는 리소스가 살아있는 한 고정된 IP를 가지고 있으며, TCP/UDP 패킷을 Pod로 Redirect 해준다.

Service의 작동방식

우선 어떤 Pod로 트래픽을 분산할지 Pod를 찾아야 한다. Pod를 찾는 방법은 labelSelector가 있다. (다른 방법이 있을 수 있음~?)

 

우선 해당 Selector를 만족하는 Pod들을 찾는다. 또한 그 Pod의 IP를 이용해 Endpoint 리소스(IP:ContainerPort)를 생성한다.

 

EndPoint 리소스들은 서비스에 붙게되며, 클러스터 내부의 클라이언트가 해당 서비스에 요청을 보내면 서비스는 해당하는 Endpoint 중 하나로 트래픽을 redirect 하게 된다.

 

  • 만약 Pod가 요청에 대한 세션을 가지고 있어야 한다면 sessionAffinity 를 사용할 수 있다. 이를 통해 요청은 계속해서 동일한 Pod로 전달된다.
  • Service는 TCP/UDP 트래픽을 분산하므로 HTTP 메시지를 볼 수 없다. ( 따라서 Cookie 값을 보고 로드밸런싱 한다던지의 기능을 수행할 수 없다. )
  • 여러개의 Port를 서비스에 연결할 수 있다.
  • targetPort로 숫자 이외의 http,https 등 alias 등을 사용할 수 있다. 이렇게 사용하면 Pod의 포트가 변경되어도 서비스를 수정할 필요가 없다.

Discovering Service

클러스터 내부에서 Service로 요청을 보내려면 해당 Service의 IP를 알아야 한다. 어떻게 알아야 할까?

  1. ENV
    1. 파드가 실행되면 환경변수 값들로 서비스의 IP와 포트가 들어간다. 가장 처음 존재하는 쿠버네티스 서비스의 경우
KUBERNETES_SERVICE_HOST= ... 
KUBERNETES_SERVICE_PORT= ...

로 파드 컨테이너의 환경변수로 들어간다.

 

  1. DNS
    1. 내부 DNS 서버인 kube-dns를 이용한다. 해당 DNS 서버에 서비스의 FQDN을 쿼리함으로써 서비스의 IP를 찾을 수 있다.

Service outside the cluster

Pod가 클러스터 외부 리소스에 접근할 때도 Service 리소스를 사용할 수 있다. externalName 타입의 서비스로 클러스터 외부의 도메인을 등록함으로써 서비스의 FQDN을 통해 클러스터 외부의 서비스에 접근할 수 있다.

 

Service를 클러스터 외부에 노출하기

 

클러스터 외부의 클라이언트가 Service에 요청을 보내기 위해서는 다양한 방식이 존재한다.

 

  1. NodePort
    1. 말 그대로 (워커)Node의 Port를 오픈한다. 해당 NodeIP:Port로 요청을 보내면 NodePort서비스는 Pod로 트래픽을 redirect 한다.
    2. 서비스에 dedicated한 Node의 Port를 할당한다. 해당 서비스로 트래픽을 보내려면 두가지 방법이 존재한다. 
    3. SERVICE_IP:PORT, nth NODE IP:NODEPORT
    4. SERVICE_IP의 경우 클러스터 내부 IP이고, 클러스터 외부에서는 NODE의 IP를 통해 접근할 수 있다.(물론 인바운드 NODEPORT에 대한 트래픽을 받아야 한다.)
    5. 이 방법의 경우 특정 노드가 죽어버리면 그 IP를 통해서는 더이상 트래픽을 받지 못한다는 단점이 있다.
  1. LoadBalancer
    1. Kubernetes Cloud Provider들이 제공해주는 LoadBalancer 리소스를 통해 dedicated IP로 트래픽을 받아 NodePort로 트래픽을 redirect한다.
    2. public하게 접근가능한 IP를 할당한다. 내부적으로는 NodePort서비스로 구현된다.
    3. LB의 IP:PORT로 접근 시 특정 NodePort로 연결한다. 해당 NodePort는 또 Pod로 트래픽을 분산한다.(implicitly assigned Nodeport)
  1. Ingress
  • 주로 HTTP 패킷을 받아 여러 서비스로 패킷을 전달한다. (다음 글에서 설명)

 

Peculiarities of External Connection

  1. 불필요한 Network hops
    1. 외부에서 Pod로 트래픽을 보내려면 LB -> NodePort -> Pod를 거친다. 여기서 Node에 Pod가 존재할 수도 있고 없으면 다른 Node로 보낼 수도 있는데, 이는 불필요한 hop수를 증가시킨다.
    2. Service 오브젝트의 스펙에 externalTrafficPolicy: local 을 명시하면 해당 Node에 존재하는 파드로만 트래픽을 분산한다. ( 이 경우 해당 Node에 실행중인 Pod가 없다면 hanging된다. 또한 트래픽을 불균등하게 받을 수 있다.. 특정 Node에 실행중인 Pod가 많으면)

 

  1. Client IP를 잃어버린다.
    1. Nodeport 서비스의 경우 SNAT해서 원래의 IP를 잃어버리고 Pod에 트래픽이 도달한다.

 

References

Service, Kubernetes up & running

Recent Posts

Popular posts

Recent Comments

Tag List

IAC ORM 네임스페이스 JavaScript AWS 리눅스 운영체제 파이썬 DB 백준 테라폼 알고리즘 DNS 인가 인증 도커 TypeScript 네트워크 API k8s JWT GCP 클라우드 컨테이너
Total : Today : Yesterday :
Blog powered by Tistory, Designed by hanarotg