Kubernetes는 노트북에서 고가용성 다중 노드 클러스터, 퍼블릭 클라우드에서 온프레미스 배포로, 가상 머신 (VM) 인스턴스에서 베어메탈로 다양한 환경에서 실행할 수 있는 오픈소스 프로젝트입니다.
이 Codelab에서는 GKE에서 간단한 Spring Boot 자바 웹 앱을 Kubernetes에 배포하여 웹 앱을 Kubernetes에서 복제된 앱으로 실행하는 것을 목표로 합니다. 머신에서 개발한 코드를 가져와 Docker 컨테이너 이미지로 변환하고 이미지를 GKE에서 실행합니다.
Google Cloud의 완전 관리형 Kubernetes 서비스인 GKE를 사용하면 기본 인프라를 설정하는 대신 Kubernetes를 경험하는 데 더욱 집중할 수 있습니다.
개발용 노트북처럼 로컬 머신에서 Kubernetes를 실행하는 데 관심이 있는 경우 개발 및 테스트 목적으로 단일 노드 Kubernetes 클러스터를 간단하게 설정하는 Minikube를 살펴보세요. 원하는 경우 Minikube를 사용하여 Codelab을 진행할 수 있습니다.
이 Codelab에서는 Spring Boot로 앱 빌드 가이드의 샘플 코드를 사용합니다.
기본 요건
- 자바 프로그래밍 언어 및 도구에 관한 기본 지식
- Vim, Emacs, nano와 같은 표준 Linux 텍스트 편집기에 대한 지식
실행할 작업
- 간단한 자바 앱을 Docker 컨테이너로 패키징합니다.
- GKE에서 Kubernetes 클러스터를 만듭니다.
- GKE에서 Kubernetes에 자바 앱을 배포합니다.
- 서비스 확장 및 업그레이드 출시
- 웹 기반 Kubernetes 사용자 인터페이스인 대시보드에 액세스합니다.
필요한 항목
- Google Cloud 프로젝트
- 브라우저(예: Chrome)
자습형 환경 설정
- Cloud Console에 로그인한 후 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. Gmail 또는 G Suite 계정이 아직 없다면 계정을 만들어야 합니다.
모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID
라고 부릅니다.
- 다음으로 Google Cloud 리소스를 사용하려면 Cloud Console에서 결제를 사용 설정해야 합니다.
이 Codelab을 진행하는 데는 비용이 몇 달러 이상 들지 않지만 더 많은 리소스를 사용하기로 결정하거나 계속 실행하는 경우 비용이 더 많이 들 수 있습니다.
Google Cloud 신규 사용자는 $300 무료 체험판을 사용할 수 있습니다.
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화
를 클릭합니다.
이전에 Cloud Shell을 시작하지 않았으면 설명이 포함된 중간 화면(스크롤해야 볼 수 있는 부분)이 제공됩니다. 이 경우 계속을 클릭합니다(이후 다시 표시되지 않음). 이 일회성 화면은 다음과 같습니다.
Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.
가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저나 Chromebook만 사용하여 수행할 수 있습니다.
Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 해당 프로젝트 ID로 이미 설정된 것을 볼 수 있습니다.
- Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list
명령어 결과
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
명령어 결과
[core] project = <PROJECT_ID>
또는 다음 명령어로 설정할 수 있습니다.
gcloud config set project <PROJECT_ID>
명령어 결과
Updated property [core/project].
Cloud Shell이 실행되면 명령줄을 사용하여 소스 코드 예를 홈 디렉터리에 클론할 수 있습니다.
$ git clone https://github.com/spring-guides/gs-spring-boot.git $ cd gs-spring-boot/complete
- Spring Boot 플러그인을 사용하여 Spring Boot 앱을 정상적으로 시작할 수 있습니다.
$ ./mvnw -DskipTests spring-boot:run
- 앱이 시작되면 Cloud Shell 툴바에서 웹 미리보기
를 클릭하고 포트 8080에서 미리보기를 선택합니다.
브라우저의 탭이 열리고 방금 시작한 서버에 연결됩니다.
다음으로 Kubernetes에서 실행할 앱을 준비해야 합니다. 첫 번째 단계는 컨테이너와 그 콘텐츠를 정의하는 것입니다.
- 앱에 배포할 수 있는 JAR을 만듭니다.
$ ./mvnw -DskipTests package
- Container Registry를 사용 설정하여 만들 컨테이너 이미지를 저장합니다.
$ gcloud services enable containerregistry.googleapis.com
- Jib를 사용하여 컨테이너 이미지를 만들고 Container Registry에 푸시합니다.
$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \ -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- 모두 성공하면 Container Registry > 이미지로 이동하여 Console에 나열된 컨테이너 이미지를 볼 수 있습니다. 이제 프로젝트 차원의 Docker 이미지가 준비되었으며, Kubernetes를 통해 몇 분 안에 확인할 수 있습니다.
- 이 작업이 완료되면 (모든 항목을 다운로드하고 추출하는 데 다소 시간이 소요됨) 다음 명령어를 사용하여 이미지를 로컬로 테스트할 수 있습니다. 그러면 새로 만든 컨테이너 이미지에서 포트 8080의 Docker 컨테이너로 데몬이 실행됩니다.
$ docker run -ti --rm -p 8080:8080 \ gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- Cloud Shell의 웹 미리보기 기능을 활용합니다.
- 새 탭에 기본 페이지가 표시됩니다. 앱이 Docker 컨테이너에서 로컬로 실행되는 것을 확인한 후
Control+C
를 눌러 실행 중인 컨테이너를 중지할 수 있습니다.
GKE 클러스터를 만들 준비가 되었습니다. 클러스터는 Google에서 관리하는 Kubernetes API 서버와 워커 노드 집합으로 구성됩니다. 워커 노드는 Compute Engine VM입니다.
- 먼저 관련 API 기능이 사용 설정되어 있는지 확인합니다.
$ gcloud services enable compute.googleapis.com container.googleapis.com Operation "operations/..." finished successfully
n1-standard-1
노드 2개로 클러스터를 만듭니다. 완료하는 데는 몇 분 정도 걸립니다.
$ gcloud container clusters create hello-java-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
마지막으로 생성된 클러스터가 표시됩니다.
Creating cluster hello-java-cluster...done. Created [https://container.googleapis.com/v1/projects/...]. kubeconfig entry generated for hello-dotnet-cluster. NAME ZONE MASTER_VERSION hello-java-cluster us-central1-c ...
이제 GKE를 통해 완전히 작동하는 Kubernetes 클러스터를 사용해야 합니다.
이제 컨테이너화된 앱을 Kubernetes 클러스터에 배포할 차례입니다. 이제부터 Cloud Shell 환경에 이미 설정된 kubectl
명령줄을 사용할 것입니다. 나머지 Codelab에서는 Kubernetes 클라이언트와 서버 버전이 1.2 이상이어야 합니다. kubectl version
은 명령어의 현재 버전을 보여줍니다.
- Kubernetes 배포에서는 개발자가 만든 컨테이너 이미지를 사용하여 앱의 여러 인스턴스를 만들고 관리하며 확장할 수 있습니다.
kubectl run
명령어를 사용하여 앱의 인스턴스 하나를 Kubernetes에 배포합니다.
$ kubectl create deployment hello-java \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
- 만든 배포를 보려면 다음 명령어를 실행하면 됩니다.
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-java 1 1 1 1 37s
- 배포에서 만든 앱 인스턴스를 보려면 다음 명령어를 실행합니다.
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-java-714049816-ztzrb 1/1 Running 0 57s
이 시점에서 Kubernetes는 Kubernetes의 제어하에 실행되어야 하지만 여전히 외부 사용자가 액세스할 수 있도록 해야 합니다.
기본적으로 클러스터 내에서 내부 IP로만 포드에 액세스할 수 있습니다. Kubernetes 가상 네트워크 외부에서 hello-java
컨테이너에 액세스할 수 있도록 하려면 포드를 Kubernetes 서비스로 노출해야 합니다.
- Cloud Shell에서
kubectl expose
명령어를--type=LoadBalancer
플래그와 함께 사용하여 pod를 공개 인터넷에 노출할 수 있습니다. 외부에서 액세스할 수 있는 IP를 만들려면 플래그가 필요합니다.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080
명령어에 사용된 플래그는 기본 인프라에서 제공하는 부하 분산기를 사용하도록 지정합니다. 포드가 아니라 배포를 직접 노출합니다. 그 결과 배포에서 배포로 관리되는 모든 포드의 트래픽을 부하 분산합니다. 이 경우에는 포드가 하나뿐이지만 나중에 복제본을 더 추가합니다.
Kubernetes 마스터는 Google Cloud 외부에서 서비스에 완전히 액세스할 수 있도록 부하 분산기와 관련 Compute Engine 전달 규칙, 대상 풀 및 방화벽 규칙을 만듭니다.
- 공개적으로 액세스할 수 있는 서비스의 IP 주소를 찾으려면
kubectl
에 모든 클러스터 서비스의 목록을 요청하세요.
$ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE Hello-java 10.3.253.62 aaa.bbb.ccc.ddd 8080/TCP 1m kubernetes 10.3.240.1 <none> 443/TCP 5m
- 서비스에 IP 주소가 2개 있으며 모두 포트 8080을 제공합니다. 하나는 Virtual Private Cloud 내부에만 표시되는 내부 IP 주소입니다. 다른 하나는 외부 부하 분산 IP 주소입니다. 이 예에서 외부 IP 주소는
aaa.bbb.ccc.ddd
입니다. 이제 브라우저가 http://<EXTERNAL_IP>:8080을 가리키도록 설정하여 서비스에 도달할 수 있습니다.
Kubernetes에서 제공하는 강력한 기능 중 하나는 앱을 얼마나 쉽게 확장할 수 있는지입니다. 갑자기 앱에 더 많은 용량이 필요하다고 가정해 보겠습니다. 복제 컨트롤러에 앱 인스턴스의 새 복제본을 관리하도록 지시하기만 하면 됩니다.
$ kubectl scale deployment hello-java --replicas=3 deployment "hello-java" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-java 3 3 3 3 22m
선언적 접근 방식을 확인합니다. 새로운 인스턴스를 시작하고 중지하는 대신 항상 실행 중이어야 하는 인스턴스의 개수를 선언합니다. Kubernetes 조정 루프는 실제 상황에서 요청한 것과 일치하는지 확인하고 필요에 따라 조치를 취합니다.
경우에 따라 프로덕션에 배포한 앱에 버그 수정 또는 추가 기능이 필요합니다. Kubernetes를 사용하면 사용자에게 영향을 주지 않고 새 버전을 프로덕션에 배포할 수 있습니다.
- Cloud Shell 메뉴에서 편집기 실행
을 클릭하여 코드 편집기를 엽니다.
src/main/java/hello/HelloController.java
로 이동하여 응답 값을 업데이트합니다.
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Greetings from Google Kubernetes Engine!";
}
}
- Jib를 사용하여 컨테이너 이미지의 새 버전을 빌드하고 푸시합니다.
$ ./mvnw -DskipTests package \ com.google.cloud.tools:jib-maven-plugin:build \ -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2
Kubernetes를 통해 복제 컨트롤러를 새 버전의 앱으로 원활하게 업데이트할 수 있습니다.
- 실행 중인 컨테이너의 이미지 라벨을 변경하려면 기존
hello-java
배포를 수정하고 이미지를gcr.io/PROJECT_ID/hello-java:v1
에서gcr.io/PROJECT_ID/hello-java:v2
로 변경해야 합니다.
kubectl set image
명령어를 사용하여 Kubernetes에 순차적 업데이트를 사용하여 한 번에 전체 클러스터에 앱의 새 버전을 배포하도록 요청할 수 있습니다.
$ kubectl set image deployment/hello-java \ hello-java=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2 deployment "hello-java" image updated
- http://EXTERNAL_IP:8080에서 다시 응답을 반환하는지 확인합니다.
죄송합니다. 앱의 새 버전을 실수로 추가하셨나요? 새 버전에 오류가 포함되어 있어 빠르게 롤백해야 할 수 있습니다. Kubernetes를 사용하면 이전 상태로 쉽게 롤백할 수 있습니다. 다음 명령어를 실행하여 앱을 롤백합니다.
$ kubectl rollout undo deployment/hello-java
새로운 자바 기반 웹 앱을 빌드하여 GKE에 있는 Kubernetes에 배포하는 방법을 배웠습니다.