[쿠버네티스] - Service Discovery

chancehee·2023년 10월 22일
0

쿠버네티스

목록 보기
11/17
post-thumbnail

[ 개요 ]

서버에게 데이터를 요청하려면 IP주소, Port가 필요하다.
MSA 환경에서는 여러 개의 서버끼리 유기적으로 통신하여 동작한다.

그런데, Auto Scaling 처럼 서비스가 동적으로 생성되거나, 컨테이너 기반의 배포로 인해서 서비스의 IP가 동적으로 변경되는 일이 잦아졌다. -> IP의 주소를 알아내기 위한 방법 필요.(Service Discovery 필요)

[ Service Discovery ]

서비스 클라이언트가 서비스를 호출할 때 서비스의 위치 (IP주소, Port)를 알아낼 수 있는 기능

Service Discovery는 크게 2가지 방법 존재
1. Client Side Discovery
2. Server Side Discovery

[ Client Side Discovery ]

서비스 클라이언트가 Service Registry에서 서비스의 위치를 찾아서 호출 하는 방식

[ Server Side Discovery ]

서비스 클라이언트가 Proxy 서버 (로드밸런서)를 호출하면 로드밸런서가 Service Registry에서 위치를 찾아서 리턴, 이를 기반으로 라우팅 하는 방식
ex) AWS의 ELB, Goole Cloud의 로드밸런서

[ Service Registry ]

서비스를 기억하고 있는 저장소.
Client Side Discovery 또는 Server Side Discovery 모두 Service Registry가 필수적이다.

구현 방법은 여러 가지가 있다.

  • 직접 구현
  • Apache Zookeeper
  • etcd
  • Netflix Eureka
  • Hashcorp Consul

[ Service Discovery on k8s ]

쿠버네티스는 Service Registryetcd를 사용한다.
etcd는 고가용성을 제공하는 분산 키/값 저장소로, 쿠버네티스 클러스터의 상태 정보, 구성 데이터, 서비스 디스커버리 정보를 저장하는 데 사용된다.

쿠버네티스의 서비스 디스커버리 동작과정은 아래와 같다.
1. 서비스 생성 및 IP 할당
2. DNS 레코드 생성
3. DNS 쿼리
4. 로드 밸런싱 및 서비스 디스커버리

즉, 쿠버네티스는 DNS를 이용하여 서비스 디스커버리를 수행하고, etcd에서 정보를 가져와 응답한다.

[ Spring APP 통신 테스트 ]

필자는 2개의 Spring Boot 기반 APP으로 통신 테스트를 진행했습니다.

개발 환경

  • 운영체제 : ubuntu 20.0.4 LTS (AWS EC2)
  • Docker, Kubernetes 환경 필요
  1. 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에 맞는 도커 이미지 빌드)

  2. 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 .

  3. Kubernetes Deployment, Service 생성

  4. CURL을 이용해 통신 테스트

0개의 댓글