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를 통해 클라이언트 사이드 로드 밸런싱 지원
사용하기 전에 쿠버네티스의 대해 잘 모를 수도 있다고 생각하여
주요 자원, 동작 방식의 대해 설명해보도록 하겠다. 필요없으면 쭈욱 내려도 된다.
쿠버네티스 클러스터
쿠버네티스 클러스터에는 크게 두 가지로 나뉜다.
마스터노드, 워커노드
간단하게 줄이면 마스터 노드는 명령어를 날리는곳, 워커노드는 명령어를 실행하는 곳이라고 생각하면 된다.
마스터 노드
- 클러스터 관리, 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 작성까지 해보겠다.
댓글