서버에게 데이터를 요청하려면 IP주소
, Port
가 필요하다.
MSA 환경에서는 여러 개의 서버끼리 유기적으로 통신하여 동작한다.
그런데, Auto Scaling 처럼 서비스가 동적으로 생성되거나, 컨테이너 기반의 배포로 인해서 서비스의 IP가 동적으로 변경되는 일이 잦아졌다. -> IP의 주소를 알아내기 위한 방법 필요.(Service Discovery 필요)
서비스 클라이언트가 서비스를 호출할 때 서비스의 위치 (IP주소
, Port
)를 알아낼 수 있는 기능
Service Discovery
는 크게 2가지 방법 존재
1. Client Side Discovery
2. Server Side Discovery
서비스 클라이언트가 Service Registry
에서 서비스의 위치를 찾아서 호출 하는 방식
서비스 클라이언트가 Proxy 서버 (로드밸런서)를 호출하면 로드밸런서가 Service Registry
에서 위치를 찾아서 리턴, 이를 기반으로 라우팅 하는 방식
ex) AWS의 ELB, Goole Cloud의 로드밸런서
서비스를 기억하고 있는 저장소.
Client Side Discovery 또는 Server Side Discovery 모두 Service Registry
가 필수적이다.
구현 방법은 여러 가지가 있다.
쿠버네티스는 Service Registry
로 etcd
를 사용한다.
etcd
는 고가용성을 제공하는 분산 키/값 저장소로, 쿠버네티스 클러스터의 상태 정보, 구성 데이터, 서비스 디스커버리 정보를 저장하는 데 사용된다.
쿠버네티스의 서비스 디스커버리 동작과정은 아래와 같다.
1. 서비스 생성 및 IP 할당
2. DNS 레코드 생성
3. DNS 쿼리
4. 로드 밸런싱 및 서비스 디스커버리
즉, 쿠버네티스는 DNS
를 이용하여 서비스 디스커버리를 수행
하고, etcd
에서 정보를 가져와 응답한다.
필자는 2개의 Spring Boot
기반 APP으로 통신 테스트를 진행했습니다.
개발 환경
ubuntu 20.0.4 LTS
(AWS EC2)Docker
, Kubernetes
환경 필요 Spring App 1 (JAR 빌드, Docker Image 생성)
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class AController {
// Bean으로 등록한 RestTemplate 주입
private final RestTemplate restTemplate;
@GetMapping("/health")
public String Health() {
return "A server ok!";
}
@GetMapping("/hello")
public String getHello() {
String response = "예외";
try {
response = restTemplate.getForObject("http://spring-app-2:8080/api/endpoint", String.class);
} catch (Exception e) {
log.error("통신 예외 발생");
}
return response;
}
}
./gradle clean build
: JAR 빌드
# Dockerfile 작성
FROM openjdk:11
WORKDIR /app
COPY build/libs/A-0.0.1-SNAPSHOT.jar /app/app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
docker buildx build --push --platform linux/amd64 -t chancehee/test-app1 .
(필자는 mac os에서 dockerfile을 빌드하기 때문에 ubuntu os에 맞는 도커 이미지 빌드)
Spring App 2 (JAR 빌드, Docker Image 생성)
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/health")
public String health() {
return "B server ok";
}
@GetMapping("/endpoint")
public String getHello() {
return "Hello from spring-app-2!";
}
}
./gradle clean build
: JAR 빌드
# Dockerfile 작성
FROM openjdk:11
WORKDIR /app
COPY build/libs/B-0.0.1-SNAPSHOT.jar /app/app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
docker buildx build --push --platform linux/amd64 -t chancehee/test-app2 .
Kubernetes Deployment, Service 생성
CURL을 이용해 통신 테스트