이 가이드는 Kubernetes에 Spring Boot 애플리케이션을 배포하는 과정을 안내합니다. Spring Boot 및 Kubernetes를 사용하여 작업을 수행하는 다양한 방법 중에서 선택할 수 있습니다. 이 가이드의 목적은 모든 대안을 논의하거나 프로덕션에 도달하는 방법에 대한 모든 세부 사항을 설명하는 것이 아니라 가능한 한 빨리 진행하도록 하는 것입니다.
쿠버네티스(Kubernetes)에서 애플리케이션을 배포하고 관리하기 위해 사용되는 주요 요소들과 그들 간의 상호작용 과정을 간략히 설명하겠습니다.
파드(Pod):
서비스(Service):
인그레스(Ingress):
쿠버네티스 이벤트 순환 과정:
이러한 주요 요소들과 과정을 통해 쿠버네티스는 애플리케이션을 배포하고 관리하는 데 필요한 기능을 제공합니다.
Kubernetes는 컨테이너화된 애플리케이션의 배포(deployment), 확장(scaling) 및 관리(management)를 자동화하기 위한 오픈 소스 시스템입니다. 쉽게 관리하고 검색할 수 있도록 애플리케이션을 구성하는 컨테이너를 논리 단위로 그룹화합니다. 이 가이드에서는 간단한 Spring 부팅 애플리케이션을 구축하고 배포합니다.
컨테이너 이미지 빌드에 대한 배경 지식을 다루는 시작 가이드 및 Docker 관련 주제 가이드도 찾을 수 있습니다.
Linux 또는 Linux와 유사한 명령줄이 필요합니다. 이 가이드의 명령줄 예제는 Linux, 셸이 있는 MacOS 터미널 또는 Windows의 WSL에서 작동합니다.
https://kubernetes.io/docs/tasks/tools/
https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
kubectll 체크섬 파일 다운로드
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
체크섬 파일에 대해 kubectl 바이너리의 유효성을 검사합니다.
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client
kubectl이 Kubernetes 클러스터를 찾고 액세스하려면 kube-up.sh
를 사용하여 클러스터를 생성하거나 Minikube 클러스터를 성공적으로 배포할 때 자동으로 생성되는 kubeconfig
파일이 필요합니다. 기본적으로 kubectl 구성(configuration)은 ~/.kube/config
에 있습니다.
클러스터 상태(cluster state)를 가져와서 kubectl이 올바르게 구성되었는지 확인하세요.
kubectl cluster-info
URL 응답이 표시되면 kubectl이 클러스터에 액세스하도록 올바르게 구성된 것입니다. 다음과 유사한 메시지가 표시되면 kubectl이 올바르게 구성되지 않았거나 Kubernetes 클러스터에 연결할 수 없는 것입니다.
The connection to the server <server-name:port> was refused - did you specify the right host or port?
예를 들어, 노트북에서 (로컬로) Kubernetes 클러스터를 실행하려는 경우 먼저 Minikube
와 같은 도구를 설치한 다음 위에 설명된 명령을 다시 실행해야 합니다.
kubectl cluster-info가 URL 응답을 반환하지만 클러스터에 액세스할 수 없는 경우 클러스터가 올바르게 구성되었는지 확인하려면 다음을 사용하세요.
kubectl cluster-info dump
minikube는 Kubernetes를 쉽게 배우고 개발할 수 있도록 하는 데 중점을 둔 로컬 Kubernetes입니다. 필요한 것은 Docker(또는 이와 유사하게 호환되는) 컨테이너 또는 가상 머신 환경뿐이며 Kubernetes는 단 하나의 명령 minikube start
으로 사용할 수 있습니다.
바이너리 다운로드를 사용하여 x86-64 Linux에 최신 minikube 안정 릴리스를 설치하려면:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
관리자 액세스 권한이 있는 터미널(root로 로그인하지 않음)에서 다음을 실행합니다.
minikube start
Minikube가 시작되지 않으면 드라이버 페이지에서 호환 가능한 컨테이너 또는 가상 머신 관리자 설정에 대한 도움말을 참조하세요.
이미 kubectl을 설치했다면(문서 참조) 이제 이를 사용하여 반짝이는 새 클러스터에 액세스할 수 있습니다.
kubectl get po -A
Kubernetes 클러스터와 명령줄 도구 Kubectl
도 필요합니다. Kind
(Docker에서) 또는 Minikube
를 사용하여 로컬로 클러스터를 생성할 수 있습니다. 또는 Google Cloud Platform
, Amazon Web Services
또는 Microsoft Azure
와 같은 클라우드 공급자를 사용할 수 있습니다. 계속 진행하기 전에 셸에서 kubectl
명령을 실행할 수 있는지 확인하세요. 다음 예에서는 kind
를 사용합니다.
$ kubectl cluster-info
Kubernetes master is running at https://127.0.0.1:46253
KubeDNS is running at https://127.0.0.1:46253/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
또한 다음 명령을 실행해야 합니다.
$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 7m13s
먼저 Spring Boot 애플리케이션을 만듭니다. 이미 github에서 사용하고 싶은 것이 있다면 터미널에서 복제할 수 있습니다(git
및 java
는 이미 설치되어 있습니다). 또는 start.spring.io
를 사용하여 처음부터 애플리케이션을 생성할 수 있습니다.
curl https://start.spring.io/starter.tgz -d dependencies=webflux,actuator | tar -xzvf -
그런 다음 애플리케이션을 빌드할 수 있습니다.
그레이들(Gradle)을 사용하여 애플리케이션을 빌드할 수 있어요! ./gradlew
명령어는 프로젝트 루트 디렉토리에서 Gradle 래퍼(wrapper)를 실행하여 빌드하는 데 사용됩니다. 이 명령어를 실행하면 프로젝트의 Gradle 스크립트가 실행되어 프로젝트를 빌드하고 필요한 의존성을 다운로드합니다. 만약 Gradle을 사용하여 Java 또는 Kotlin 기반의 애플리케이션을 빌드하려면 ./gradlew build
명령어를 사용할 수 있어요.
그러면 빌드 결과를 볼 수 있습니다. 빌드가 성공하면 다음과 유사한 JAR 파일이 표시됩니다.
ls -l target/*.jar
-rw-r--r-- 1 root root 19463334 Nov 15 11:54 target/demo-0.0.1-SNAPSHOT.jar
./gradlew build
로 빌드한 파일은 build/libs
디렉토리에 저장되어있습니다.
JAR은 실행 가능합니다.
java -jar 파일이름.jar
프로젝트를 다운로드할 때 추가한 액추에이터 종속성 때문에 애플리케이션에는 몇 가지 기본 제공 HTTP 엔드포인트가 있습니다. 시작 시 로그에 다음과 유사한 출력이 표시됩니다.
...
2019-11-15 12:12:35.333 INFO 13912 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2019-11-15 12:12:36.448 INFO 13912 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
...
그런 다음 다른 터미널에서 endpoint을 curl할 수 있습니다.
$ curl localhost:8080/actuator | jq .
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/actuator/health/{*path}",
"templated": true
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
}
}
}
curl
: 커맨드 라인에서 URL을 통해 데이터를 전송하고 받을 수 있는 도구입니다.localhost:8080/actuator
: 로컬 호스트의 8080 포트에서 액추에이터 엔드포인트에 요청을 보냅니다. 액추에이터는 스프링 부트 애플리케이션의 모니터링 및 관리를 위한 엔드포인트를 제공합니다.jq .
: curl로 받은 JSON을 파싱하고, 보기 좋게 출력하는데 사용되는 도구입니다. .
은 jq에게 입력을 그대로 출력하도록 지시합니다.이 단계를 완료하려면 Ctrl+C를 눌러 애플리케이션을 중지하세요.
Spring Boot 애플리케이션을 컨테이너화하는 데는 여러 가지 옵션이 있습니다. 이미 Spring Boot jar 파일을 빌드하고 있는 경우에는 플러그인을 직접 호출하기만 하면 됩니다.
$ ./gradlew bootBuildImage
컨테이너를 로컬로 실행할 수 있습니다.
$ docker run -p 8080:8080 demo:0.0.1-SNAPSHOT
그런 다음 다른 터미널에서 작동하는지 확인할 수 있습니다.
$ curl localhost:8080/actuator/health
컨테이너를 중지하여 완료합니다.
Dockerhub(docker login
)로 인증하지 않으면 이미지를 푸시할 수 없지만 작동해야 하는 이미지가 이미 있습니다. 인증을 받은 경우 다음을 수행할 수 있습니다.
$ docker tag demo:0.0.1-SNAPSHOT springguides/demo
$ docker push springguides/demo
실제로는 Kubernetes가 일반적으로 로컬 docker 데몬에 연결되지 않는 Kubelets(노드) 내부에서 이미지를 가져오기 때문에 이미지를 Dockerhub(또는 다른 액세스 가능한 저장소)에 푸시해야 합니다. 이 시나리오의 목적에 따라 푸시를 생략하고 이미 있는 이미지를 사용할 수 있습니다.
테스트를 위해 안전하지 않은 (예를 들어,)로컬 레지스트리에서
docker push
가 작동하도록 하는 해결 방법이 있지만 이는 이 가이드의 범위를 벗어납니다.
쿠버네티스에 애플리케이션을 배포하는 것은 당신이 개발한 애플리케이션을 쿠버네티스 클러스터에서 실행할 수 있도록 설정하는 과정을 의미합니다. 이는 애플리케이션을 컨테이너 이미지로 패키징하고, 쿠버네티스가 이 이미지를 사용하여 클러스터 내에서 여러 노드에 분산하여 실행하도록 지시하는 것을 포함합니다.
일반적으로 쿠버네티스에서 애플리케이션을 배포하는 단계는 다음과 같습니다:
컨테이너 이미지 준비: 먼저 애플리케이션을 실행할 수 있는 컨테이너 이미지를 준비합니다. 이 이미지에는 애플리케이션 코드, 실행에 필요한 종속성 및 설정이 포함됩니다.
쿠버네티스 리소스 정의: 쿠버네티스는 YAML 또는 JSON 포맷의 매니페스트 파일을 사용하여 애플리케이션 배포를 정의합니다. 이 매니페스트 파일은 애플리케이션을 실행할 파드, 서비스, 인그레스 등의 쿠버네티스 리소스를 정의합니다.
쿠버네티스 클러스터에 배포: 정의된 쿠버네티스 리소스를 사용하여 쿠버네티스 클러스터에 애플리케이션을 배포합니다. 이 단계에서 쿠버네티스는 애플리케이션을 실행하고 네트워킹 및 로드 밸런싱을 구성합니다.
상태 모니터링 및 관리: 배포된 애플리케이션의 상태를 모니터링하고 필요한 경우 스케일링, 롤링 업데이트 등의 작업을 수행하여 애플리케이션을 관리합니다.
따라서 쿠버네티스에 애플리케이션을 배포한다는 것은 애플리케이션을 실행할 환경을 설정하고, 클러스터 내에서 안정적으로 실행되도록 하는 과정을 의미합니다.
이제 포트 8080을 실행하고 노출하는 컨테이너가 있으므로 Kubernetes를 실행하는 데 필요한 것은 YAML뿐입니다. YAML을 보거나 편집할 필요가 없도록 지금은 kubectl
에 YAML 생성을 요청할 수 있습니다. 여기서 변경될 수 있는 유일한 것은 --image
이름입니다. 컨테이너를 자체 리포지토리에 배포한 경우 다음 태그 대신 해당 태그를 사용하세요.
$ kubectl create deployment demo --image=springg--image=springguides/demo --dry-run=client -o=yaml > deployment.yaml
$ echo --- >> deployment.yaml
$ kubectl create service clusterip demo --tcp=8080:8080 --dry-run -o=yaml >> deployment.yaml
해당 명령어는 먼저 쿠버네티스에 애플리케이션을 배포하기 위해 YAML 매니페스트 파일을 생성하는 과정을 수행합니다.
kubectl create deployment demo --image=springg--image=springguides/demo --dry-run=client -o=yaml > deployment.yaml
: 이 명령은 쿠버네티스 클러스터에 demo
라는 이름의 배포(deployment)를 생성하고, 해당 배포에 springguides/demo
라는 이미지를 사용하도록 지정합니다. --dry-run=client -o=yaml
옵션은 실제로 클러스터에 배포를 만들지 않고 YAML 형식으로 출력하도록 지시합니다. 이를 deployment.yaml
파일에 리다이렉션하여 파일로 저장합니다.
echo --- >> deployment.yaml
: 이 명령은 deployment.yaml
파일에 구분을 위해 ---
를 추가합니다. 이는 다음 명령어의 결과를 구분하기 위한 것입니다.
kubectl create service clusterip demo --tcp=8080:8080 --dry-run=client -o=yaml >> deployment.yaml
: 이 명령은 demo
라는 이름의 ClusterIP 서비스를 생성하며, 이 서비스는 8080 포트로 들어오는 트래픽을 배포된 파드의 8080 포트로 전달합니다. 이 또한 --dry-run=client -o=yaml
옵션을 사용하여 YAML 형식으로 출력하고, 이를 deployment.yaml
파일에 추가합니다.
따라서 위 명령어를 실행하면 deployment.yaml
파일에 배포 및 서비스에 대한 정의가 YAML 형식으로 저장됩니다. 이 파일을 사용하여 쿠버네티스 클러스터에 애플리케이션을 배포할 수 있습니다.
위에서 생성된 YAML을 가져와 원하는 경우 편집하거나 그대로 적용할 수 있습니다.
$ kubectl apply -f deployment.yaml
deployment.apps/demo created
service/demo created
애플리케이션이 실행 중인지 확인합니다.
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/demo-658b7f4997-qfw9l 1/1 Running 0 146m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 2d18h
service/demo ClusterIP 10.43.138.213 <none> 8080/TCP 21h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/demo 1/1 1 1 21h
NAME DESIRED CURRENT READY AGE
replicaset.apps/demo-658b7f4997 1 1 1 21h
d
데모 팟(Pod)이
Running
상태로 표시될 때까지kubectl get all
을 반복하십시오.
이제 Kubernetes에서 서비스로 노출한 애플리케이션에 연결할 수 있어야 합니다. 개발 시에 잘 작동하는 한 가지 방법은 SSH 터널을 만드는 것입니다.
$ kubectl port-forward svc/demo 8080:8080
이제 다른 터미널에서 해당 앱이 실행 중인지 확인할 수 있습니다.
$ curl localhost:8080/actuator/health
{"status":"UP"}