쿠버네티스에서 Pod는 컨트롤러가 관리하므로 노드를 옮겨다니면서 실행되기도 하고 클러스터 안 Pod의 IP가 변경되기도 한다. 이렇게 동적으로 변하는 Pod에 고정적으로 접근할 때 사용하는 방법이 Service다.
Service란, 쿠버네티스의 기본 오브젝트로 수신한 트래픽을 여러 파드로 로드밸런싱(부하 분산)하는 기능을 제공한다.
ClusterIP: 쿠버네티스(클러스터) 내부에서만 사용 가능한 가상 IP를 가진 엔드포인트를 제공하는 로드밸런서 구성(L4)
NodePort: 외부 클라이언트가 서비스를 통해서 클러스터 내부의 파드로 접속할 때 사용 가능(L7)
ClusterIP
동작 방식: 클라이언트(TestPod)가 'CLUSTER-IP' 접속 시 해당 노드의 iptables 룰에 의해서 DNAT(Dastination NAT:도착지 주소를 변경하는 NAT) 처리되어 목적지 Pod와 통신
서비스(ClusterIP) 생성 시, apiserver → (kubelet) → kube-proxy → iptables 에 rule이 생성됨
kube-proxy란, 쿠버네티스에서 Service를 만들었을 때 ClusterIP나 NodePort로 접근할 수 있게 만들어 실제 조작 하는 컴포넌트다. 쿠버네티스 클러스터의 노드마다 실행되면서 클러스터 내부 IP로 연결하려는 요청을 적절한 파드로 전달한다. 이러한 kube-proxy가 네트워크를 관리하는 방법은 userspace, iptables, IPVS 모드가 있다.
이 중에서도 iptables 모드는 클라이언트에서 오는 모든 요청이 iptables를 거쳐 파드로 직접 전달된다. 그래서 파드 하나로의 연결 요청이 실패하면 재시도를 하지 않고 그냥 요청이 실패하게 된다. 따라서 컨테이너에 ReadinessProbe가 설정되어 있고, 그에 따른 헬스체크가 정상적으로 되어야 연결 요청이 이루어진다.
작동 방식 확인을 위한 실습
목적지 Pod 생성
클라이언트(TestPod) 생성
서비스(ClusterIP) 생성
생성된 모든 리소스 확인
클라이언트(TestPod) Shell 실행 후 Pod IP로 직접 curl 테스트
서비스(ClusterIP) 부하분산 접속 확인
for문을 이용하여 해당 서비스 IP:포트에 curl 명령어를 100번 반복하였을 때, 3개의 목적지(backend) 파드로 랜덤 부하 분산 접속되는 것을 확인할 수 있음
sessionAffinity: ClientIP
만약, ClusterIP 서비스 사용시 파드에서 ClusterIP로 보내진 트래픽은 서비스에 연결된 어느 하나의 파드에 전송된 후 다음 트래픽도 계속해서 같은 파드에 고정적으로 전달하고 싶다면 sessionAffinity를 사용할 수 있다. (NodePort나 LoadBalancer에서도 세션 어피니티 자체는 활성화 할 수 있는 경우들이 있으나 여러가지 제한되는 부분이 많아서 주로 사용하지 않는다.)
NodePort
동작 방식: 외부 클라이언트가 '노드IP:NodePort' 접속 시 해당 노드의 iptables 룰에 의해서 SNAT(Source NAT: 출발지 주소를 변경하는 NAT) /DNAT 되어 목적지 파드와 통신 후 리턴 트래픽은 최초 인입 노드를 경유하여 외부로 되돌아감
모드 노드(마스터 포함)에 iptables rule 이 설정되므로, 모든 노드에 NodePort 로 접속 시 iptables rule 에 의해서 분산 접속
작동 방식 확인을 위한 실습
목적지(backend) 디플로이먼트(Pod) 파일 생성
서비스(NodePort) 파일 생성
생성된 리소스 확인
NodePort 확인
NodePort를 변수에 지정
노드 포트 Listen 확인 : ss 옵션 -4(ipv4) -t(TCP) -l(Listen) -n(숫자로 출력) -p(프로세스)