was 컨테이너와 DB 컨테이너 끼리의 통신을 하려면 여러가지를 고려해야한다.
쿠버네티스에서는 Pod 간 통신이 기본적으로 Pod IP를 통해 가능합니다. 하지만 WAS Pod와 DB Pod 간 통신에서 DB Pod가 재시작하면서 Pod IP가 변경되는 경우가 발생하면, 통신 설정을 매번 수정해줘야 하는 문제가 발생


예를 들어, 기존에 1.1.1.2 의 Pod IP를 갖고 있던 DB 컨테이너가 재생성되어 Pod IP가 1.1.1.3으로 변경 된 경우
다시 IP를 변경하던지 셋팅값을 1.1.1.3으로 변경해 주어야 한다.
이를 해결하기 위해, IP 대신 도메인(FQDN)을 사용하여 연결 정보를 설정하기로 했습니다.

위의 사진에서 JDBC 설정의 localhost 위치에
대신 Pod에 접근가능한 도메인(FQDN)을 넣어주기로 계획
이를 위해 도메인이 특정 파드에 대해 고유성을 갖게 하기 위해 headless service를 이용하기로 함
1. Headless service
service
먼저 Service에 대해 알아보면
기본적으로 쿠버네티스에서는 Pod IP를 이용해 Pod끼리 클러스터 내부에서 통신이 가능하다.
나아가 외부와 통신하기 위해서는 외부의 트래픽을 라우팅 해주는 "service"가 필요하다.
기본적인 service의 생성 후 원리는 아래와 같이 진행된다.

1. service 생성
2. control plane에서 ClusterIP할당
3. kube-proxy에 ClusterIP 전달
4. kube-proxy에 3의 Cluster IP에 할당된 Pod IP 전달
5. kube-proxy가 입력받은 IP로 IP table을 생성
이후 트래픽이 svc에 도달하면 kube-proxy가 이를 인지
하고 테이블을 참조해서 Pod에 트래픽 라우팅 진행
실제 연결과 패킷 처리는 CNI와 리눅스 커널이 맡는다.
kube-proxy에 라우팅은 round-robin이 기본값이고
IP 테이블이 아닌 IPSV를 참조하면 다른 알고리즘을 적용할 수 있다.
보통 서비스를 생성하면 위와 같은 과정을 지난 뒤에 해당 ClusterIP로 요청이 오면 kube-proxy가 매칭되는 Pod IP에 트래픽을 라우팅 하는 방식이다.
headless Service
ClusterIP없이 직접 Pod에 접속하기 위해 headless Service를 이용하면 좋다.
headless service는 하나의 FQDN에 하나의 Pod IP를 연결하는 레코드를 생성한다.
만약, 서비스에 해당하는 파드가 반드시 1개가 유지된다면 headless Service를 사용하지 않아도 된다.
결국 headless service는 FQDN과 연결되는 Pod의 유일성을 보장하는 리소스인 셈이기 때문이다.
headless service는 ClusterIP가 없다.
생성 방법도 ClusterIP: none 으로 옵션을 주면 형성된다.

동작원리는 다음과 같다.

외부에서 도메인(FQDN) 으로 요청이 들어오면 CoreDNS가 제일 먼저 확인한다.
그리고 요청받은 서비스가 headless-service인지 cluster-service인지 api-server에 질의 요청 후
레코드를 확인하여 FQDN과 매핑된 값을 확인한다.
cluster-service는 ClusterIP, headless-service는 Pod IP를 반환하게 된다.
이후 cluster-service는 kube-proxy에서 요청 받은 Cluster IP에 매칭되는 Pod로 트래픽을 보내고
headless-service는 반환 받은 Pod IP로 바로 트래픽을 라우팅한다.
쿠버네티스에서 pod 생성시 kube-dns나 coreDNS에서 FQDN을 생성하는데 그 형태는 아래와 같다.
<pod 이름>.<service 이름>.<name space 이름>.svc.cluster.local
위와 같은 형태의 FQDN을 이용해서 Pod간 통신 상태를 유지할 수 있다.
여기서 문제가 더 발생한다. 파드는 재 시작시 <Pod 이름>이 무작위로 정해진다
이 문제를 해결하기 위해 statefulset을 사용하였다.
2. statefulset
Pod 이름이 무작위로 정해지는 것에 대비하기 위해 statefulset을 사용하였다.
먼저 deployment에서 생성되는 파드 이름과 비교해보았다.
deployment에서의 Pod Name
일반적인 deployment로 형성되는 파드는
<deployment 이름>-<replicaset 이름>-<무작위>
이런식으로 이름이 정해진다.


컨테이너 재 시작시 가장 뒷부분이 변경된 것을 볼 수 있다.
statfulset에서의 Pod Name
deployment에서는 pod의 이름이 불규칙하게 무작위로 정해진다.
이렇게되면 FQDN 또한 불규칙하게 무작위로 재생성되는 것이므로 Pod IP와 다를 바 없다.
이런 경우를 방지하기 위해 statefulset을 이용한다. statefulset은 생성하는 pod의 이름을 규칙적으로 지정한다.
<statefulset 이름>-<0 이상의 정수>
예시로 postgresql을 statefulset으로 생성했다.
statefulset의 이름이 postgres 이고 Pod의 이름이 postgres-0 인 것을 볼 수 있다.
여기서 만약에 postgres의 replicas를 3으로 늘리면
postgres-0, postgres-1, postgres-2 가 될 것이고, 삭제시에는 역순으로 2부터 0의 순으로 삭제 될 것이다.
이렇게 해서 생성되는 postgres-0 Pod의 FQDN은
postgres-0.postgres-service.postgres-ns.svc.cluster.local
으로 될 것이다.
JSP 연결정보에 생성된 FQDN과 포트번호, 데이터베이스 이름을 적어서 테스트 한 결과 잘 연결이 됨을 볼 수 있다.
그리고 , statefulset으로 생성해서 pod가 재시작해도 같은 이름을 유지하기에 FQDN이 계속 유효함을 알 수 있다.
<h2>User List</h2>
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
<%
String url = "jdbc:postgresql://postgres-0.postgres-service.namespace.svc.cluster.local:5432/test"; // PostgreSQL DB URL
String user = "postgres"; // PostgreSQL username
String password = "postgres"; // PostgreSQL password

'kubernetes' 카테고리의 다른 글
| 파드의 상태 검사 (startProbe readinessProbe livenessProbe) (0) | 2025.03.06 |
|---|---|
| 노드에 파드 분배 - affinity (0) | 2025.03.02 |
| init container 이용 sysctl 실행 (3) | 2025.01.25 |
| sidecar 사용하여 수시로 git clone = git-sync (0) | 2025.01.21 |
| 파일 전송 용량 (0) | 2024.12.02 |
