Service
는 Kubernetes
의 기본 오브젝트 중 하나입니다.
Kubernetes
에서 Pod
은 생성과 삭제가 자유로운 오브젝트입니다. Controller
를 통해 Pod
을 관리하는 경우 Pod
에 문제가 생기면 새로운 Pod
을 생성하게 되는데 이 때 Pod
의 IP주소가 랜덤하게 생성됩니다.
이 때, 트래픽을 전달할 대상인 Pod
의 IP를 Endpoint
라고 하며, 서비스는 Label
을 통해 Pod
의 라벨을 매칭해 Endpoint
정보를 수집하고, 자신에게 오는 트래픽을 적절한 Endpoint
로 분배합니다.
만약 사용자나 다른 애플리케이션이 어떤 Pod
에 접근할 때 Pod
의 IP주소를 이용해 접근한다면 그 Pod
에 문제가 생겨 IP가 변경되면 기존과 동일한 서비스를 제공하는 Pod
으로 접속하는 것을 보장할 수 없습니다.
Kubernetes
는 이를 Service
를 통해 해결하고 있습니다.
Kubernetes
에서 이러한 문제점을 해결하기 위해 Pod
의 네트워크 정보가 변경되어도 정상적으로 통신이 가능하도록 Pod
레벨의 네트워크를 추상화 하였는데 이것을 Service
라고 부르며, Control Plane
중 하나인 kube-proxy
가 이 Service
를 관리합니다.
Kubernetes
는 Service
를 통해 Pod
에서 실행중인 Container
를 외부로 노출시킵니다.
이 때, 동일한 기능을 하는 Pod
들의 Endpoint
정보를 Service
라는 네트워크 리소스로 추상화합니다.
Pod
에 접근을 하고자 하는 경우 해당 Pod
를 추상화한 Service
에 접근하면 Service
가 적절한 Pod
로 트래픽을 전달해 줍니다.
Service
라는 이름 때문에 혼동이 있을 수도 있지만, 쉽게 말하자면 Service
는 어떠한 기능을 제공하는 Pod
에 대한 연결을 보장해주는 중간 통로라고 볼 수 있을 것 같습니다.
Label selector
를 이용해 특정한 Label
을 가진 Pod
들을 Service
아래에 연결하고 사용자나 다른 애플리케이션은 해당 기능을 제공하는 Pod
에 접근할 때 Pod
의 IP주소가 아닌 Service
의 주소를 통해 접근합니다.
만약 기존 Pod
에 문제가 생겨 IP주소가 변경되더라도 새로 생성한 Pod
에 Label selector
에 정의한 Label
이 있다면 Service
는 새로 생성된 Pod
으로의 연결을 자동으로 제공해줍니다.
이렇게되면 만약 Cluster
내부적으로 Pod
에 문제가 생겨 IP주소가 변경되더라도 외부에서는 이런 문제에 대해 알 필요가 없습니다.
Service
에는 크게 3가지 종류가 있습니다.
위의 그림을 보면 알 수 있듯이 Cluster IP
, Node Port
, Load Balancer
입니다.
각각의 Service
들은 Pod
를 외부로 노출시키는 방법이나 형태가 조금씩 다릅니다.
Cluster IP
는 type
을 지정해주지 않으면 자동으로 생성되는 Service
입니다.
Cluster IP
라는 이름처럼 Cluster
내부에서만 이용할 수 있는 IP로 외부에서는 Cluster IP
를 통한 접근이 불가능합니다.
위의 그림과 같은 형태로 접근을 제공하며, 같은 Cluster
에 위치한 Pod
들은 Cluster IP
를 이용해 Service
가 관리하는 Pod
에 접근이 가능합니다.
서로 다른 Worker Node
에 있는 경우 kube-proxy
를 활용해 조금 복잡한 방식으로 통신이 이루어지는데 이에 대해서는 나중에 자세히 설명하겠습니다.
Node Port
란 이름 그대로 Pod
가 위치한 Node
즉 Worker Node
들의 특정 Port
를 통해 Service
에 접근하는 것을 의미합니다.
그림으로 보면 위의 그림과 같은 형태로 통신이 이루어지는데, 기존의 Cluster IP
상단에 Node Port
라는 새로운 Service
가 생성된 것을 확인할 수 있습니다.
이 그림을 보면 Cluster IP
는 마치 Node
안에 존재하는 것 처럼 보이지만 그렇지 않습니다.
위의 그림에서는 Node
가 하나만 표현되어 있기 때문에 혼동이 있을 수 있습니다.
Cluster IP
는 Label selector
를 통해 선택된 모든 Pod
들에 대한 접근을 제공해야 합니다.
그런데 일반적으로 Kubernetes
환경에서 Pod
들은 여러 Worker Node
에 걸쳐서 배포되어 있기 때문에 다수의 Worker Node
에 흩어져 있는 같은 Label
을 가진 Pod
에 접근하기 위해서는 Cluster IP
가 특정 Node
안에 존재하는 형태가 아닌 모든 Worker Node
가 접근할 수 있는 Cluster
의 어딘가에 위치해야 합니다.
마지막으로 LoadBalancer
란 말 그대로 Load balancing
을 제공해 줄 수 있는 Service
입니다.
LoadBalancer
로 접근하면, LoadBalancer
에 설정된 리시버, 타겟 설정에 따라 Worker Node
의 특정 Port
로 트래픽을 전달해주는 방식입니다.
LoadBalancer
타입 Service
를 사용하기 위해서는 실제 LoadBalancer
장비가 필요한데 물리적 장비를 이용하거나, AWS
, Azure
, GCP
등 Cloud Service Provider
가 제공하는 LoadBalancer
를 사용하면 됩니다.
온프레미스/베어메탈 환경에서 물리 장비의 사용이 어려울 경우 MetalLB
와 같은 가상의 로드밸런서를 사용할 수도 있습니다.
$ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.106.84.164
IPs: 10.106.84.164
LoadBalancer Ingress: 10.0.1.79
Port: http 8080/TCP
TargetPort: 80/TCP
NodePort: http 31181/TCP
Endpoints: 172.17.0.11:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
위의 코드는 어떤 LoadBalnacer
Service
의 정보를 조회한 결과입니다.
Type
이 LoadBalancer
인 것을 확인할 수 있고,
NodePort
와 Cluster IP(IP, IPs)
도 확인할 수 있습니다.
자세한 흐름은 아래와 같습니다.
- 외부에서
LoadBalancer
IP로 접근을 시도Service
가Label selector
을 통해 관리하는Pod
가 위치한Worker Node
중 하나의 31181번 Port로 트래픽이 전달- 10.106.84.164라는
Cluster IP
의 8080번 Port로 트래픽이 전달Label selector
에 의해 선택된Pod
들 중 하나로 트래픽 전달
Service
는 Kubernetes
의 기본 오브젝트 중 하나일 정도로 매우 중요한 오브젝트입니다.
Service
는 자동으로 Pod
이 생성되고 삭제되는 환경에서 Label selector
를 이용해 외부 사용자들에게 내부에 어떤 문제가 발생하던 동일한 기능을 제공하는 Pod
로의 접속을 보장합니다.