[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를 알아야 한다. 어떻게 알아야 할까?
- ENV
- 파드가 실행되면 환경변수 값들로 서비스의 IP와 포트가 들어간다. 가장 처음 존재하는 쿠버네티스 서비스의 경우
KUBERNETES_SERVICE_HOST= ...
KUBERNETES_SERVICE_PORT= ...
로 파드 컨테이너의 환경변수로 들어간다.
- DNS
- 내부 DNS 서버인 kube-dns를 이용한다. 해당 DNS 서버에 서비스의 FQDN을 쿼리함으로써 서비스의 IP를 찾을 수 있다.
Service outside the cluster
Pod가 클러스터 외부 리소스에 접근할 때도 Service 리소스를 사용할 수 있다. externalName
타입의 서비스로 클러스터 외부의 도메인을 등록함으로써 서비스의 FQDN을 통해 클러스터 외부의 서비스에 접근할 수 있다.
Service를 클러스터 외부에 노출하기
클러스터 외부의 클라이언트가 Service에 요청을 보내기 위해서는 다양한 방식이 존재한다.
- NodePort
- 말 그대로 (워커)Node의 Port를 오픈한다. 해당 NodeIP:Port로 요청을 보내면 NodePort서비스는 Pod로 트래픽을 redirect 한다.
- 서비스에 dedicated한 Node의 Port를 할당한다. 해당 서비스로 트래픽을 보내려면 두가지 방법이 존재한다.
SERVICE_IP:PORT, nth NODE IP:NODEPORT
SERVICE_IP의 경우 클러스터 내부 IP이고, 클러스터 외부에서는 NODE의 IP를 통해 접근할 수 있다.(물론 인바운드 NODEPORT에 대한 트래픽을 받아야 한다.)
- 이 방법의 경우 특정 노드가 죽어버리면 그 IP를 통해서는 더이상 트래픽을 받지 못한다는 단점이 있다.
- LoadBalancer
- Kubernetes Cloud Provider들이 제공해주는 LoadBalancer 리소스를 통해 dedicated IP로 트래픽을 받아 NodePort로 트래픽을 redirect한다.
- public하게 접근가능한 IP를 할당한다. 내부적으로는 NodePort서비스로 구현된다.
- LB의 IP:PORT로 접근 시 특정 NodePort로 연결한다. 해당 NodePort는 또 Pod로 트래픽을 분산한다.(implicitly assigned Nodeport)
- Ingress
- 주로 HTTP 패킷을 받아 여러 서비스로 패킷을 전달한다. (다음 글에서 설명)
Peculiarities of External Connection
- 불필요한 Network hops
- 외부에서 Pod로 트래픽을 보내려면 LB -> NodePort -> Pod를 거친다. 여기서 Node에 Pod가 존재할 수도 있고 없으면 다른 Node로 보낼 수도 있는데, 이는 불필요한 hop수를 증가시킨다.
- Service 오브젝트의 스펙에
externalTrafficPolicy: local
을 명시하면 해당 Node에 존재하는 파드로만 트래픽을 분산한다. ( 이 경우 해당 Node에 실행중인 Pod가 없다면 hanging된다. 또한 트래픽을 불균등하게 받을 수 있다.. 특정 Node에 실행중인 Pod가 많으면)
- Client IP를 잃어버린다.
- Nodeport 서비스의 경우 SNAT해서 원래의 IP를 잃어버리고 Pod에 트래픽이 도달한다.
References
Service, Kubernetes up & running
'공부 > CLOUD' 카테고리의 다른 글
[GCP] Cloud Scheduler를 이용한 주기적 작업 실행 (0) | 2022.01.06 |
---|---|
Terraform 오버뷰 - GCP Cloud Run 배포하기 (0) | 2021.08.16 |
[k8s] Service 리소스 Overview (2) : Ingress와 Health check (0) | 2021.08.15 |
[GCP] Cloud Run CI/CD (0) | 2021.05.24 |