Pod는 언제든 죽을 수 있는 리소스기 때문에 IP 주소들 같은 리소스들이 정적일 수 없다.
언제든 다른 Node로 할당된다던가 / 다른 인스턴스로 생성될 수 있다.
예를 들어 아래 그림을 봅시다.
클라이언트가 Pod 에 직접 접근을 하고 있다고 가정했을 때 pod가 죽어서 컨트롤러에 의해 새로운 pod 가 생성되면 별도의 새 IP 가 할당되나 사용자들은 이 사실을 알지 못합니다.
이런 상황을 극복하기 위해 쿠버네티스에서는 Label과 Selector를 통해 논리적으로 Pod를 그룹핑하고 접근할 수 있는 Service라는 상위 레벨의 추상화를 제공합니다.
Service
Label 을 통해 그룹핑 된 그림 예를 한번 보죠.
selector를 통해 ( app==frontent , app==db ) 우리는 이름을 부여한 두 개의 논리적 그룹( frontent-svc, db-svc )을 만들 수 있습니다.
Service는 클러스터내에서 접근이 가능한 IP 어드레스를 기본으로 할당받고 이를 그 Service의 ClusterIP라고 합니다.
클라이언트는 IP Adress를 통해 Service에 접근이 가능하게 되고 Service는 요청 트래픽을 넘겨줄 Pod들이 선택되는 동안에는 loadbalancing을 합니다.
서비스에서 트래픽을 전달하면서 포드에서 대상 포트를 선택할 수 있습니다.
위 그림에서 보면 80포트로 요청을 받아서 서비스에 묶인 Pod들 중 하나에 5000번 포트로 전달하게 세팅되어있고 트래픽을 받으면 해당 포트로 넘겨주게 됩니다.
위와 같은 서비스의 예제 Yaml 파일
kind: Service
api
Version: v1
metadata:
name: frontend-svc
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 5000
이 예제에서 app = frontend 라는 라벨을 가진 pods 들로 연결될 frontend-svc 라는 서비스를 만들었습니다.
각 서비스는 클러스터내에서만 접근이 가능한 IP 주소를 기본으로 갖게 되는데 예제에서는 172.17.0.4 ( frontend-svc ) , 172.17.0.5 ( db-svc ) 를 가지게 되고 각 서비스에 할당됩니다.
클라이언트는 각각 할당된 IP 주소의 80포트를 통해 해당 서비스에 접근하게 되고 서비스의 엔드포인트로( 10.0.1.3:5000, 10.0.1.4:5000, 10.0.1.5:5000) 트래픽을 포워딩합니다.
Kube-Proxy
모든 워커노드에는 Service와 endpoint의 생성과 추가를 API를 통해 감시하고 있는 kube-proxy라는 데몬이 동작합니다.
새로운 서비스가 등록/삭제되면 각 노드들에서 kube-proxy가 ClusterIP에 인입되는 트래픽을 잡아서 엔드포인트로 포워딩하기 위해 Iptable에 변경합니다.
Service Discovery
쿠버네티스에서 Service가 기본 소통방식이기때문에 런타임 환경에서 서비스들을 찾을 수 있어야 하며 쿠버네티스에서는 두 가지 방식을 제공합니다.
Environment Variables
Pod 가 어떤 노드에서 시작되는 순간 해당 노드에서 동작하는 kubelet 데몬은 해당 Pod 내에 현재 동작하는 Service를 위한 환경 변수를 추가합니다.
예를 들면 redis-master 라는 서비스가 있고 6379포트로 노출되며 ClusterIP가 172.17.0.6이라는 서비스가 있다고 한다면 새로 생기는 Pod에서는 아래와 같은 환경 변수를 볼 수 있습니다.
$ vi ~/.kube/config # kubectl이 참고하는 config 파일
$kubectl config view # 이렇게도 볼 수 있습니다.
$ kubectl config get-contexts # 컨텍스트 리스트를 볼 수도 있구요
$ kubectl config current-context # 현재 사용중인 컨텍스트가 무엇인지 확인합니다.
$kubectl config use-context docker-for-desktop # 현재 사용하는 컨텍스트를 바꿀 수도 있고
$ kubectl config get-contexts
$ kubectl config use-context minikube
$ kubectl config set-context --current --namesapace=default # 현재 사용하는 컨텍스트의 기본 네임스페이스를 지정하기도 합니다.