본문 바로가기
CICD/AWS

msa구조 k8s 통해 백엔드 배포해보기 (2) Spring Cloud Kubernetes

by windy7271 2024. 5. 6.
728x90
반응형
2024-05-06 10:50:26.162  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBody]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [XForwardedRemoteAddr]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]

Spring Cloud 프로젝트에서 제공하던 기능들을 가진 Kubernetes의 대표적인 리소스는 다음과 같다.

  • 서비스 디스커버리 : Kubernetes Service / Ingress
  • 로드 밸런싱 : Kubernetes Service (LoadBalancer)
  • API 게이트웨이 : Kubernetes Service / Ingress
  • 설정 관리 : Kubernetes ConfigMap / Secrets

 

Spring Cloud Kubernetes는 개발자가 Kubernetes에서 Spring Cloud 애플리케이션을 구축하고 실행할 수 있도록 잘 알려진 Spring Cloud 인터페이스의 구현을 제공한다.

 

공식 문서에서 소개하는 주요 기능은 다음과 같습니다.

  • Kubernetes awareness
    • Spring Cloud 어플리케이션이 Kubernetes 환경에서 동작하는지 여부를 감지
  • DiscoveryClient implementation
    • Kubernetes의 Service를 활용, Spring Cloud의 서비스 디스커버리를 지원
  • PropertySoruce objects configured via ConfigMaps
    • Kubernetes의 ConfigMaps를 활용, Spring Cloud의 설정 서버/클라이언트를 지원
  • Client side loadbalancing via Netflix Ribbon
    • Netflix Ribbon + Kubernetes Service를 통해 클라이언트 사이드 로드 밸런싱 지원

출처 : https://velog.io/@mrcocoball2/Spring-Cloud-Spring-Cloud-Kubernetes-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EB%B0%8F-%ED%99%9C%EC%9A%A9

 

[Spring Cloud] Spring Cloud Kubernetes - 기본 개념 및 활용

Spring Cloud Kubernetes는 개발자가 Kubernetes에서 Spring Cloud 어플리케이션을 빌드 / 실행할 수 있도록 Spring Cloud 인터페이스 구현을 제공하는 프로젝트입니다.

velog.io

 

 

사용하기 전에 쿠버네티스의 대해 잘 모를 수도 있다고 생각하여

주요 자원, 동작 방식의 대해 설명해보도록 하겠다. 필요없으면 쭈욱 내려도 된다.

 

쿠버네티스 클러스터

쿠버네티스 클러스터에는 크게 두 가지로 나뉜다.

마스터노드, 워커노드

간단하게 줄이면 마스터 노드는 명령어를 날리는곳, 워커노드는 명령어를 실행하는 곳이라고 생각하면 된다.

마스터 노드 

  • 클러스터 관리, API 서버, 스케줄링 역할 등을 담당한다.
  • 사용자, 클러스터 내부 구성 요소 및 외부 도구가 쿠버네티스 API를 통해 통신할 수 있는 진입점을 제공한다.
  • 개발자의 명령어는 쿠버네티스 API 서버(kube-apiserver)로 전송
  • aws의 eks를 사용하게 되면, 마스터노드는 클러스터 생성시 aws차원에서 지원이되고, 개발자가 마스터노드에 대해 신경쓸일은 없다.

워커 노드 

  • 애플리케이션의 실제 실행을 담당하는 노드로서 각 워커 노드에는 Kubelet이라는 에이전트를 실행되어 마스터 노드와 통신한다
  • aws 기준으로는 ec2에 인스턴스가 실행되고, 해당 워커노드에서 서비스 pod가 실행된다

주요 요소는 다음과 같다.

  • kubelet
    • API 서버와 통신하여 파드를 시작, 중지, 관리하는 등의 작업을 수행
    • 스케줄러가 파드를 실행할 노드를 결정하면, 해당 노드의 kubelet에 파드를 생성하라는 명령이 전달
    • kubelet은 파드의 스펙에 따라 컨테이너 런타임을 사용하여 컨테이너를 시작
    • kubelet은 파드가 성공적으로 시작되었는지 확인하고, 파드의 상태를 주기적으로 API 서버에 보고
  • kube-proxy
    • 네트워크 프록시 및 로드 밸런서 역할을 하는 노드 수준 구성 요소
    • kube-proxy는 네트워크 트래픽을 적절히 포워딩하도록 네트워크 규칙을 설정하여 파드 간의 통신이나 외부에서 파드로의 접근을 가능
  • 컨테이너 런타임
    • 실제로 컨테이너를 실행하는 소프트웨어(예: Docker).
    • 이미지를 가져오고, 컨테이너를 패키지화된 애플리케이션과 함께 실행하고, 컨테이너의 생명주기를 관리
    • docker등의 주요 소프트웨어는 eks등을 사용하여 클러스터 구성시 자동 설치
  • 컨테이너 네트워크 인터페이스 (CNI) 플러그인
    • 다양한 CNI 플러그인을 통해, 노드 간 및 파드 간 네트워킹을 구성
    • 네트워크 연결을 설정하고, IP 주소를 파드에 할당하며, 네트워크 격리를 관리

내용이 많다.

 

 

동작 방식은 아래와 같다

동작방식

 

주요 리소스 종류에 대해 알아보겠다.

Service:

Service는 클러스터 외부로부터 요청을 받을 수 있게 IP를 노출하는 역할을 하는 리소스다. 그리고 Deployment로 Pod를 수평확장하는 상황에, 트래픽을 적절히 분산시키기는 역할을 할 수 있는 리소스이다.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: my-nginx # 위에 label과 싱크가 같다.
  • port
    • Service가 클러스터 내부에서 리슨(listen)하는 포트
    • 즉, 클러스터 내부의 다른 컴포넌트나 Pod들이 이 Service와 통신하기 위해 사용하는 포트
  • targetPort
    • Service가 포워딩(forward)하는 대상 Pod의 포트
    • targetPort는 Pod의 컨테이너 포트와 직접 매핑
    • NodePort
      • 클러스터 외부에서 Service에 접근하기 위해 노드(node)가 리슨하는 포트
      • NodePort 서비스를 사용하면, 클러스터 외부에서 특정 노드의 IP 주소와 이 NodePort를 통해 Service에 접근
  • 네임스페이스 내에서 파드와 서비스를 함께 사용할 때, 서비스는 해당 네임스페이스 내에서만 파드를 찾아 트래픽을 전달할 수 있음에 유의
    • 메타데이터에 namespace: test-namespace 추가 필요

deployment:

Deployment는 파드와 레플리카셋의 선언적 업데이트를 관리하고 스케일링, 롤아웃, 롤백 등을 포함한 파드의 배포 과정을 자동화 할 수 있다. pod매니저라고 생각하면 편하다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector: # 참조하겠다.
    matchLabels:
      app: my-nginx 
  template: # 파트의 정보
    metadata:
      labels:
        app: my-nginx # 이름을 맞춰 줘야함
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

 

  • 선택자의 라벨 (spec.selector.matchLabels)
    • 이 라벨은 Deployment가 관리해야 할 파드를 결정하는 데 사용
    • spec.selector.matchLabels는 Deployment에 의해 관리되어야 하는 파드가 어떤 라벨을 가지고 있어야 하는지 정의
    • 즉, 이 라벨은 Deployment가 "내가 관리해야 할 파드는 이러한 라벨을 가진 것들이다"라고 식별하는 기준

간단하게 말하면 위에서 만든 service에 이름과 , labels의 app 이름을 맞춰주면 된다.

  • kubectl
    • kubectl은 Kubernetes 클러스터를 제어하기 위한 커맨드 라인 인터페이스(CLI) 도구
    • kubectl을 사용하여 사용자는 클러스터에 있는 리소스를 생성, 조회, 업데이트 및 삭제
  • pod
    • Pod는 쿠버네티스에서 배포할 수 있는 가장 작은 단위이며, 1개 이상의 컨테이너로 구성된 배포 단위이다
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  labels:
    app: mypod
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
  - name: redis-container
    image: redis
    ports:
    - containerPort: 6379

 

보통 파드를 이렇게 만든다.

 

그 외로 namespace, secret, replica 등이 있다.

 

 

다시 Spring Cloud Kubernetes 를 사용해 보겠다.

 

1.  의존성 추가

Gateway . build.gradle

	implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client'
	implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client-all'
	implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client-loadbalancer'
	implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'
   
   중복제거하면
    
implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client'
implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'

 

 

이렇게 사용할 수 있다.

 

위에 꺼인 client를 사용하면 Kubernetes의 Service 엔드포인트를 검색할 수 있다. 

 

그러면 서비스로 검색을 할 수 있게 yml파일을 수정해주자

server:
  port: 8080
  error:
    include-binding-errors: always
    include-message: always
spring:
  application:
    name: gateway
  cloud:
    kubernetes:
      discovery:
        all-namespaces: true
      loadbalancer:
        mode: service
    gateway:
      routes:
        - id: batch-service
          predicates:
            - Path=/batch/**
          filters:
            - StripPrefix=1
          uri: lb://batch-service # k8s 에 등록된거로 감.
        - id: employee-service
          predicates:
            - Path=/employee/**
          filters:
            - StripPrefix=1
          uri: lb://employee-service
        - id: login-service
          predicates:
            - Path=/login/**
          filters:
            - StripPrefix=1
          uri: lb://login-service
        - id: salary-service
          predicates:
            - Path=/salary/**
          filters:
            - StripPrefix=1
          uri: lb://salary-service
        - id: total-service
          predicates:
            - Path=/total/**
          filters:
            - StripPrefix=1
          uri: lb://total-service

 

spring.cloud.kubernetes.discovery  디스커버리 설정을 할 수 있다.

all-namespace 이 값이 true로 설정되어 있으면 애플리케이션은 클러스터 내의 모든 네임스페이스에서 서비스를 검색할 수 있다.

 

제일 중요한 부분인데 Spring Cloud Kubernetes의 로드 밸런서 모드를 설정한다. 이 경우에는 "service"로 설정되어 있다. 이것은 Kubernetes 서비스를 통한 로드 밸런싱을 활성화한다.

 

즉 각각의 k8s 폴더안에 service를 보고 로드밸런싱을 한다.

 

그리고 gatway를 제외하고

@EnableDiscoveryClient

 

어노테이션을 달아줘야한다.

애플리케이션이 서비스 디스커버리를 활성화하고 이를 통해 서비스 레지스트리에 등록할 수 있도록 지원한다. 이 애노테이션을 사용하면 Spring Boot 애플리케이션이 서비스 디스커버리 클라이언트로 등록되어, 서비스 디스커버리 시스템(예: Netflix Eureka, Consul, Kubernetes 등)과 통합된다.

 

그럼 각 Service로 매칭된다

 

예를들어 windy7271.shop/admin/signup을 호출하면

gateway -> 게이트웨이에서 서비스를 매칭해서 admin/signup 을 해준다.

 

 

 

현재 나는 globalfilter 와 ,predicate가 구현되어있어서

 

predicate는 gateway web handler 이후로 들어가게 된다. 즉 서비스 이전

 

배포가 다 된 상태에서 실행해보면

2024-05-06 10:50:26.162  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBody]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [XForwardedRemoteAddr]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
2024-05-06 10:50:26.163  INFO 1 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]

 

마지막에 이런 로그가 나온다

 

이 로그는 Spring Cloud Gateway에서 Route Predicate Factory를 로드하는 과정을 보여준다. Spring Cloud Gateway는 요청을 받아 특정한 서비스로 전달하기 전에 이러한 라우트 프리디케이트를 사용하여 요청을 필터링하거나 조작할 수 있다.

여기서 로그에 나열된 각각의 RoutePredicateFactory는 다양한 요청 필터 및 조건을 나타낸다. 예를 들어, Path 프리디케이트는 요청의 경로를 기준으로 라우팅을 수행하고, Header 프리디케이트는 요청 헤더를 기반으로 라우팅을 수행한다. 이러한 다양한 프리디케이트를 조합하여 특정 요청을 특정 서비스로 라우팅하거나 필터링할 수 있다. 이 로그는 Spring Cloud Gateway가 시작될 때 이러한 라우트 프리디케이트를 로드하고 사용할 수 있도록 하는 초기화 과정을 보여준다. 이를 통해 Gateway가 요청을 적절히 라우팅하고 필터링할 수 있게 된다.

 

 

일단 그럼 배포할 준비가 완료 되었고. 유레카는 떼고 올라간다.

그럼 작성해야 하는 도커 파일은 유레카랑 프론트엔드빼고 6개다

 

다음은

Spring Cloud Kubernetes 자세히보기, ecr, 노드그룹 생성, 도커작성 ,depl, service 작성까지 해보겠다.

 

 

반응형

댓글