1. 개요
Micronaut 정보
Micronaut는 쉽게 테스트할 수 있는 모듈식 마이크로서비스 및 서버리스 애플리케이션을 빌드하기 위한 최신 JVM 기반의 풀 스택 프레임워크입니다. Micronaut는 메모리 공간을 최소화하면서 우수한 시작 시간과 빠른 처리량을 제공하는 것을 목표로 합니다. 개발자는 Java, Groovy 또는 Kotlin에서 Micronaut를 사용하여 개발할 수 있습니다.
Micronaut의 기능:
- 빠른 시작 시간 및 낮은 메모리 소비 — 리플렉션 기반 IoC 프레임워크는 코드의 모든 단일 필드, 메서드, 생성자에 대한 리플렉션 데이터를 로드하고 캐시하지만, Micronaut를 사용하면 애플리케이션 시작 시간과 메모리 소비가 코드베이스의 크기와 제한되지 않습니다.
- 선언적, 반응형, 컴파일 시간 HTTP 클라이언트 — 컴파일 시간에 구현되는 반응형 HTTP 클라이언트를 선언적으로 빌드하여 메모리 소비를 줄입니다.
- Netty를 기반으로 한 비차단형 HTTP 서버 — 원활한 학습 과정을 통해 Micronaut의 HTTP 서버를 사용하면 HTTP 클라이언트가 사용할 수 있는 API를 최대한 쉽게 노출할 수 있습니다.
- 빠르고 간편한 테스트 — 단위 테스트에서 서버와 클라이언트를 손쉽게 가동하고 즉시 실행할 수 있습니다.
- 효율적인 컴파일 시간 종속 항목 삽입 및 AOP — Micronaut는 리플렉션을 사용하지 않는 간단한 컴파일 시간 관점 지향 프로그래밍 API를 제공합니다.
- 완전 반응형 및 비차단 앱 빌드 — Micronaut는 RxJava, Reactor 등 반응형 스트림을 구현하는 모든 프레임워크를 지원합니다.
자세한 내용은 Micronaut 웹사이트를 참고하세요.
Kubernetes 정보
Kubernetes는 노트북에서 고가용성 다중 노드 클러스터, 퍼블릭 클라우드에서 온프레미스 배포, 가상 머신에서 베어 메탈까지 다양한 환경에서 실행할 수 있는 오픈소스 프로젝트입니다.
이 실습에서는 Kubernetes Engine에서 실행되는 Kubernetes에 간단한 Groovy 기반 Micronaut 마이크로서비스를 배포합니다.
이 Codelab의 목표는 마이크로서비스를 Kubernetes에서 실행되는 복제된 서비스로 실행하는 것입니다. 머신에서 개발한 코드를 가져와서 Docker 컨테이너 이미지로 변환한 다음 Kubernetes Engine에서 이미지를 실행합니다.
다음은 이 Codelab에서 작동하는 다양한 부분의 다이어그램으로, 각 부분이 어떻게 구성되는지 이해하는 데 도움이 됩니다. Codelab을 진행하면서 참고 자료로 사용하세요. 마지막에 다다를 때쯤이면 모두 이해가 될 것입니다 (하지만 지금은 무시해도 됩니다).
이 Codelab의 목적상 Kubernetes Engine (Compute Engine에서 실행되는 Kubernetes의 Google 호스팅 버전)과 같은 관리형 환경을 사용하면 기본 인프라를 설정하기보다는 Kubernetes를 경험하는 데 더 집중할 수 있습니다.
개발용 노트북과 같은 로컬 머신에서 Kubernetes를 실행하는 데 관심이 있다면 Minikube를 살펴봐야 합니다. 이는 개발 및 테스트 목적으로 단일 노드 Kubernetes 클러스터의 간단한 설정을 제공합니다. 원한다면 Minikube를 사용하여 이 Codelab을 진행할 수 있습니다.
Jib 정보
Jib는 Java 애플리케이션용 Docker 및 OCI 이미지를 빌드할 수 있는 오픈소스 도구입니다. Maven 및 Gradle용 플러그인과 Java 라이브러리로 사용할 수 있습니다.
Jib의 목표는 다음과 같습니다.
- 신속함 — 변경사항을 신속하게 배포합니다. Jib는 애플리케이션을 여러 레이어로 분리하여 클래스로부터 종속 항목을 분할합니다. 이제 Docker가 전체 Java 애플리케이션을 다시 빌드할 때까지 기다릴 필요 없이 변경된 레이어를 배포하기만 하면 됩니다.
- 재현 가능 — 동일한 콘텐츠로 컨테이너 이미지를 재현하면 항상 동일한 이미지가 생성됩니다. 불필요한 업데이트를 다시 실행하지 마세요.
- 데몬리스 — CLI 종속 항목을 줄입니다. Maven 또는 Gradle 내에서 Docker 이미지를 빌드하고 원하는 레지스트리로 푸시합니다. 더 이상 Dockerfile을 작성하고 docker build/push를 호출할 필요가 없습니다.
Jib에 관한 자세한 내용은 GitHub 프로젝트 페이지에서 확인할 수 있습니다.
이 튜토리얼 정보
이 가이드에서는 Jib 도구의 샘플 코드를 사용하여 자바 애플리케이션용 컨테이너를 빌드합니다.
이 샘플은 Micronaut 프레임워크와 Apache Groovy 프로그래밍 언어를 사용하는 간단한 Hello World 서비스입니다.
학습할 내용
- Jib를 사용하여 간단한 Java 애플리케이션을 Docker 컨테이너로 패키징하는 방법
- Kubernetes Engine에서 Kubernetes 클러스터를 만드는 방법
- Kubernetes Engine의 Kubernetes에 Micronaut 서비스를 배포하는 방법
- 서비스를 확장하고 업그레이드를 출시하는 방법
- Kubernetes 그래픽 대시보드에 액세스하는 방법
필요한 항목
본 가이드를 어떻게 사용하실 계획인가요?
HTML/CSS 웹 앱 빌드 경험을 평가해 주세요.
귀하의 Google Cloud Platform 서비스 사용 경험을 평가해 주세요.
<ph type="x-smartling-placeholder">2. 설정 및 요구사항
자습형 환경 설정
- Cloud Console에 로그인하고 새 프로젝트를 만들거나 기존 프로젝트를 다시 사용합니다. (Gmail 또는 G Suite 계정이 없으면 만들어야 합니다.)
모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID
라고 부릅니다.
- 그런 후 Google Cloud 리소스를 사용할 수 있도록 Cloud Console에서 결제를 사용 설정해야 합니다.
이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 가이드를 마친 후 비용이 결제되지 않도록 리소스 종료 방법을 알려주는 '삭제' 섹션의 안내를 따르세요. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.
3. Micronaut 샘플 소스 코드 가져오기
Cloud Shell이 실행되면 명령줄을 사용하여 홈 디렉터리의 예시 소스 코드를 클론하고 샘플 서비스가 포함된 디렉터리로 이동합니다.
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. 코드 간단히 살펴보기
Micronaut 간단한 서비스는 악명 높은 Hello World 메시지를 출력하는 컨트롤러로 구성됩니다.
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello World" } }
HelloController
컨트롤러는 /hello
경로 아래의 요청에 응답하고 index()
메서드는 HTTP GET 요청을 수락합니다.
Spock 테스트 클래스를 사용하여 올바른 메시지가 출력되었는지 확인할 수도 있습니다.
class HelloControllerSpec extends Specification { @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) @Shared @AutoCleanup RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) void "test hello world response"() { when: HttpRequest request = HttpRequest.GET('/hello') String rsp = client.toBlocking().retrieve(request) then: rsp == "Hello World" } }
이 테스트는 간단한 단위 테스트를 넘어 실제로 프로덕션에서 실행되는 동일한 Micronaut 서버 스택 (Netty 프레임워크 기반)을 실행합니다. 따라서 코드의 동작은 테스트에서와 제품 내에서 동일합니다.
테스트를 실행하려면 다음 명령어를 실행하여 모든 것이 정상인지 확인합니다.
./gradlew test
5. 애플리케이션을 로컬로 실행
다음 Gradle 명령어를 사용하여 Micronaut 서비스를 정상적으로 시작할 수 있습니다.
$ ./gradlew run
애플리케이션이 시작되면 작은 + 아이콘으로 추가 Cloud Shell 인스턴스를 연 다음 curl을 사용하여 예상대로 출력되는지 확인할 수 있습니다.
$ curl localhost:8080/hello
그러면 간단한 'Hello World'가 메시지가 나타납니다.
6. Jib를 사용하여 애플리케이션을 Docker 컨테이너로 패키징
다음으로 Kubernetes에서 실행할 앱을 준비합니다. 이를 위해 Dockerfile
를 직접 만질 필요가 없으므로 Jib를 활용하여 어려운 작업을 처리합니다.
다음 명령어를 실행하여 컨테이너를 빌드해 보겠습니다.
$ ./gradlew jibDockerBuild
다음과 같이 출력됩니다.
Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im age=<MY IMAGE> commandline flag. Containerizing application to Docker daemon as micronaut-jib:0.1... warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible Getting base image gcr.io/distroless/java... Building dependencies layer... Building resources layer... Building classes layer... Finalizing... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application] Loading to Docker daemon... Built image to Docker daemon as micronaut-jib:0.1
이제 이미지가 빌드되었으므로 Cloud Shell의 첫 번째 탭에서 Docker 이미지를 실행하여 친근한 인사 메시지를 볼 수 있는지 확인해 보겠습니다.
$ docker run -it -p 8080:8080 micronaut-jib:0.1 16:57:20.255 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp] 16:57:23.203 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080
서비스가 실행 중이므로 이제 두 번째 Cloud Shell 탭에서 curl 명령어를 실행하여 예상대로 작동하는지 확인할 수 있습니다.
$ curl localhost:8080/hello Hello World
Cloud Shell에서 Ctrl+C
키를 눌러 컨테이너를 중지할 수 있습니다.
7. 컨테이너화된 서비스를 레지스트리로 푸시
이제 이미지가 의도한 대로 작동하므로 모든 Google Cloud 프로젝트는 물론 Google Cloud Platform 외부에서도 액세스할 수 있는 Docker 이미지용 비공개 저장소인 Google Container Registry로 이미지를 푸시할 수 있습니다.
레지스트리로 푸시하기 전에 도구 > Container Registry를 사용합니다. 사용 설정되지 않은 경우 다음 대화상자가 표시되며 'Container Registry API 사용 설정'을 클릭합니다. 사용 설정하려면 다음 단계를 따르세요.
레지스트리가 준비되면 다음 명령어를 실행하여 이미지를 레지스트리에 푸시합니다.
$ gcloud auth configure-docker $ docker tag micronaut-jib:0.1 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
위의 명령어를 사용하면 gcloud SDK가 Docker가 Container Registry의 인스턴스로 이미지를 푸시하고 이미지에 레지스트리 내 해당 위치를 가리키도록 태그를 지정한 다음 레지스트리로 푸시하도록 Docker를 구성하고 승인할 수 있습니다.
모든 것이 순조롭게 진행되고 잠시 후 콘솔에 컨테이너 이미지가 표시됩니다. 도구 > Container Registry를 사용합니다. 이제 프로젝트 전체에서 사용할 수 있는 Docker 이미지가 생겼습니다. 이 이미지는 Kubernetes가 액세스하고 조정할 수 있으며, 이 이미지는 몇 분 후에 확인할 수 있습니다.
8. 클러스터 만들기
이제 Kubernetes Engine 클러스터를 만들 준비가 되었습니다. 그 전에 웹 콘솔의 Google Kubernetes Engine 섹션으로 이동하여 시스템이 초기화될 때까지 기다립니다 (몇 초 정도 소요됨).
클러스터는 Google에서 관리하는 Kubernetes 마스터 API 서버와 워커 노드 집합으로 구성됩니다. 워커 노드는 Compute Engine 가상 머신입니다. CloudShell 세션에서 gcloud
CLI를 사용하여 n1-standard-1
노드 2개가 포함된 클러스터를 만들어 보겠습니다. 이 작업은 완료하는 데 몇 분 정도 걸릴 수 있습니다.
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
최종적으로 클러스터가 생성된 것을 볼 수 있습니다.
Creating cluster hello-cluster in us-central1-c...done. Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test kubeconfig entry generated for hello-cluster. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-cluster us-central1-c 1.9.7-gke.7 35.239.224.115 n1-standard-1 1.9.7-gke.7 2 RUNNING
이제 Google Kubernetes Engine으로 구동되는 Kubernetes 클러스터가 완벽하게 작동합니다.
이제 컨테이너화된 애플리케이션을 Kubernetes 클러스터에 배포해 보겠습니다. 이제부터 Cloud Shell 환경에 이미 설정된 kubectl
명령줄을 사용합니다. 이 Codelab의 나머지 부분에서는 Kubernetes 클라이언트 및 서버 버전이 모두 1.2 이상이어야 합니다. kubectl version
은 명령어의 현재 버전을 표시합니다.
9. Kubernetes에 애플리케이션 배포
Kubernetes 배포에서는 방금 만든 컨테이너 이미지를 사용하여 애플리케이션의 여러 인스턴스를 생성, 관리, 확장할 수 있습니다. kubectl create deployment
명령어를 사용하여 Kubernetes에 애플리케이션 배포를 만들어 보겠습니다.
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
방금 만든 배포를 보려면 다음을 실행하면 됩니다.
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
배포로 생성된 애플리케이션 인스턴스를 보려면 다음 명령어를 실행합니다.
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
이 시점에서 Kubernetes가 제어하는 컨테이너를 실행해야 하지만 여전히 외부 세계에 액세스할 수 있도록 해야 합니다.
10. 외부 트래픽 허용하기
기본적으로 포드는 클러스터 내에서 내부 IP로만 액세스할 수 있습니다. Kubernetes 가상 네트워크 외부에서 hello-micronaut
컨테이너에 액세스할 수 있도록 하려면 포드를 Kubernetes 서비스로 노출해야 합니다.
Cloud Shell에서 kubectl expose
명령어와 --type=LoadBalancer
플래그를 함께 사용하여 포드를 공개 인터넷에 노출할 수 있습니다. 이 플래그는 외부에서 액세스 가능한 IP를 만드는 데 필요합니다.
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
이 명령어에서 사용된 플래그는 기본 인프라에서 제공하는 부하 분산기 (이 경우에는 Compute Engine 부하 분산기)를 사용하도록 지정합니다. 포드를 직접 노출하지 않고 배포를 노출합니다. 이로 인해 배포가 관리하는 모든 포드에 걸쳐 서비스가 트래픽을 부하 분산하게 됩니다. 이번 예시에서는 포드가 1개이지만 나중에 복제본을 더 추가하게 됩니다.
Kubernetes 마스터에서는 Google Cloud Platform 외부에서 서비스에 완전하게 액세스할 수 있도록 부하 분산기, 관련된 Compute Engine 전달 규칙, 타겟 풀 및 방화벽 규칙을 만듭니다.
공개적으로 액세스할 수 있는 서비스의 IP 주소를 찾으려면 kubectl
에 모든 클러스터 서비스를 나열하도록 요청하면 됩니다.
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-micronaut LoadBalancer 10.39.243.251 aaa.bbb.ccc.ddd 8080:30354/TCP 1m kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 31m
서비스에 IP 주소가 2개 있으며 둘 다 포트 8080
을 제공합니다. 하나는 클라우드 가상 네트워크 내에서만 볼 수 있는 내부 IP입니다. 다른 하나는 외부 부하 분산 IP입니다. 이 예시에서 외부 IP 주소는 aaa.bbb.ccc.ddd
입니다.
이제 브라우저에서 http://<EXTERNAL_IP>
:8080
/hello
주소로 서비스를 사용할 수 있습니다.
11. 서비스 확장하기
Kubernetes의 강력한 특징 중 하나는 애플리케이션을 손쉽게 확장할 수 있다는 점입니다. 애플리케이션에 용량이 더 필요하다고 가정해 보겠습니다. 복제 컨트롤러에 애플리케이션 인스턴스의 새로운 복제본 수를 관리하도록 지시하기만 하면 됩니다.
$ kubectl scale deployment hello-micronaut --replicas=3 deployment.extensions "hello-micronaut" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 3 3 3 3 16m
여기서 선언적 접근 방식에 유의하세요. 새 인스턴스를 시작하거나 중지하는 대신 항상 실행되어야 하는 인스턴스 수를 선언합니다. Kubernetes 조정 루프는 단순히 현재 상황이 요청과 일치하는지 확인하고 필요한 경우 조치를 취합니다.
12. 서비스 업그레이드하기
프로덕션에 배포한 애플리케이션에 버그 수정이나 추가 기능이 필요한 시점이 있습니다. Kubernetes를 사용하면 사용자에게 영향을 주지 않으면서 프로덕션에 새 버전을 배포할 수 있습니다.
먼저 애플리케이션을 수정해 보겠습니다. Cloud Shell에서 코드 편집기를 엽니다.
/jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy
로 이동하여 응답 값을 업데이트합니다.
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello Kubernetes World" } }
/jib/examples/micronaut/build.gradle
에서 다음 줄을 업데이트하여 이미지 버전을 0.1에서 0.2로 업그레이드합니다.
version '0.2'
그런 다음 최신 변경사항으로 애플리케이션을 다시 빌드하고 패키징합니다.
$ ./gradlew jibDockerBuild
이미지에 태그를 지정하고 Container 이미지 레지스트리로 푸시합니다.
$ docker tag micronaut-jib:0.2 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
이제 Kubernetes가 복제 컨트롤러를 새 버전의 애플리케이션으로 원활하게 업데이트할 준비가 되었습니다. 실행 중인 컨테이너의 이미지 라벨을 변경하려면 기존 hello-micronaut deployment
를 수정하고 이미지를 gcr.io/PROJECT_ID/micronaut-jib:0.1
에서 gcr.io/PROJECT_ID/micronaut-jib:0.2
로 변경해야 합니다.
kubectl set image
명령어를 사용하면 순차적 업데이트로 한 번에 한 인스턴스씩 전체 클러스터에 걸쳐 애플리케이션의 새 버전을 배포하도록 Kubernetes에 요청할 수 있습니다.
$ kubectl set image deployment/hello-micronaut \ micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 deployment.apps "hello-micronaut" image updated
http://EXTERNAL_IP:8080에서 새로운 응답이 반환되는지 다시 확인합니다.
13. 롤백
죄송합니다. 애플리케이션의 새 버전에서 실수를 하셨나요? 새 버전에 오류가 있을 수 있으므로 빠르게 롤백해야 합니다. Kubernetes를 사용하면 이전 상태로 쉽게 롤백할 수 있습니다. 다음을 실행하여 애플리케이션을 롤백해 보겠습니다.
$ kubectl rollout undo deployment/hello-micronaut
서비스의 출력을 살펴보면 처음 'Hello World'로 돌아가 메시지가 표시됩니다.
14. 요약
이 단계에서는 간단한 Apache Groovy 기반 Micronaut Hello World 서비스를 설정하고 Cloud Shell 내에서 직접 실행한 후 Jib를 사용하여 컨테이너로 패키징한 후 Google Kubernetes Engine에 배포했습니다.
15. 축하합니다.
새로운 Apache Groovy / Micronaut 웹 기반 마이크로서비스를 빌드하고 Google Kubernetes Engine의 Kubernetes에 배포하는 방법을 알아봤습니다.
자세히 알아보기
- Jib 문서 및 샘플: https://github.com/GoogleContainerTools/jib/
- Micronaut 웹사이트: http://micronaut.io/
- Google Cloud Platform의 자바: https://cloud.google.com/java/
- Java 예: https://cloud.google.com/java/samples
- 더 길고 완전한 Kubernetes 튜토리얼을 보려면 풀 스택 애플리케이션을 배포하는 과정을 안내하는 bit.ly/k8s-lab을 참조하세요.
라이선스
이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.