Triển khai ứng dụng Java Khởi động mùa xuân cho Kubernetes trên Google Kubernetes Engine

1. Trước khi bắt đầu

Kubernetes là một dự án nguồn mở, có thể chạy trong nhiều môi trường khác nhau, từ máy tính xách tay đến các cụm nhiều nút có tính sẵn sàng cao, từ đám mây công khai đến các hoạt động triển khai tại cơ sở hạ tầng riêng và từ các thực thể máy ảo (VM) đến máy chủ vật lý.

Trong lớp học lập trình này, bạn sẽ triển khai một ứng dụng web Java Spring Boot đơn giản lên Kubernetes trên GKE, với mục tiêu là chạy ứng dụng web của bạn dưới dạng một ứng dụng được sao chép trên Kubernetes. Bạn sẽ lấy mã mà bạn phát triển trên máy, chuyển mã đó thành một hình ảnh vùng chứa Docker và chạy hình ảnh đó trên GKE.

Bạn sẽ sử dụng GKE, một dịch vụ Kubernetes được quản lý hoàn toàn trên Google Cloud, để có thể tập trung hơn vào việc trải nghiệm Kubernetes thay vì thiết lập cơ sở hạ tầng cơ bản.

Nếu bạn muốn chạy Kubernetes trên máy cục bộ (chẳng hạn như máy tính xách tay phát triển), hãy xem xét Minikube. Minikube cung cấp một chế độ thiết lập đơn giản cho cụm Kubernetes một nút nhằm phục vụ mục đích phát triển và kiểm thử. Bạn có thể sử dụng Minikube để tham gia lớp học lập trình này nếu muốn.

Lớp học lập trình này sẽ sử dụng mã mẫu trong hướng dẫn về cách Tạo ứng dụng bằng Spring Boot.

Điều kiện tiên quyết

  • Làm quen với ngôn ngữ lập trình và các công cụ Java
  • Kiến thức về các trình chỉnh sửa văn bản tiêu chuẩn trên Linux, chẳng hạn như Vim, Emacs và nano

Bạn sẽ thực hiện

  • Đóng gói một ứng dụng Java đơn giản dưới dạng một vùng chứa Docker.
  • Tạo cụm Kubernetes trên GKE.
  • Triển khai ứng dụng Java của bạn lên Kubernetes trên GKE.
  • Mở rộng quy mô dịch vụ và ra mắt bản nâng cấp.
  • Truy cập vào Trang tổng quan, một giao diện người dùng Kubernetes dựa trên web.

Bạn cần có

  • Một dự án trên Google Cloud
  • Một trình duyệt, chẳng hạn như Google Chrome

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tốc độ của riêng bạn

  1. Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn luôn có thể cập nhật thông tin này.
  • Mã dự án là mã duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có được chấp nhận hay không. Bạn không thể thay đổi tên này sau bước này và tên này sẽ tồn tại trong suốt thời gian của dự án.
  • Để bạn nắm được thông tin, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên đám mây. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Nếu đây là lần đầu tiên bạn khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

9c92662c6a846a5c.png

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

9f0e51b578fecce5.png

Máy ảo này được trang bị tất cả các công cụ phát triển cần thiết. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc của mình trong lớp học lập trình này bằng trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Đầu ra của lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project

Đầu ra của lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt nó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Đầu ra của lệnh

Updated property [core/project].

3. Lấy mã nguồn

Sau khi Cloud Shell khởi động, bạn có thể dùng dòng lệnh để sao chép mã nguồn ví dụ trong thư mục chính.

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete

4. Chạy ứng dụng cục bộ

  1. Đảm bảo JAVA_HOME được đặt thành phiên bản chính xác:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Bạn có thể khởi động ứng dụng Spring Boot như bình thường bằng trình bổ trợ Spring Boot.
$ ./mvnw -DskipTests spring-boot:run
  1. Sau khi ứng dụng khởi động, hãy nhấp vào Web Preview (Xem trước trên web) 1a94d5bd10bfc072.png trong thanh công cụ Cloud Shell rồi chọn Preview on port 8080 (Xem trước trên cổng 8080).

6252b94905f3f7bd.png

Một thẻ trong trình duyệt sẽ mở ra và kết nối với máy chủ mà bạn vừa khởi động.

9b6c29059957bd0.jpeg

5. Đóng gói ứng dụng Java dưới dạng một vùng chứa Docker

Tiếp theo, bạn cần chuẩn bị ứng dụng để chạy trên Kubernetes. Bước đầu tiên là xác định vùng chứa và nội dung của vùng chứa đó.

  1. Tạo JAR có thể triển khai cho ứng dụng.
$ ./mvnw -DskipTests package
  1. Bật Artifact Registry API để lưu trữ hình ảnh vùng chứa mà bạn sẽ tạo.
$ gcloud services enable artifactregistry.googleapis.com
  1. Tạo một kho lưu trữ Docker mới nếu chưa có. Bạn phải tạo một kho lưu trữ trước khi có thể đẩy bất kỳ hình ảnh nào vào đó:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. Hình ảnh của bạn sẽ có định dạng:

{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE-NAME}

Ví dụ: nếu bạn đã tạo kho lưu trữ ở vị trí us-central1 có tên là codelabrepo và bạn muốn đặt tên cho hình ảnh là hello-java:v1, thì hình ảnh sẽ là:

us-central1-docker.pkg.dev/{PROJECT-ID}/codelabrepo/hello-java:v1

  1. Sử dụng Jib để tạo hình ảnh vùng chứa và đẩy hình ảnh đó vào Artifact Registry.
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format="value(core.project)"`

$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/codelabrepo/hello-java:v1
  1. Bạn sẽ thấy hình ảnh vùng chứa xuất hiện trong bảng điều khiển bằng cách chuyển đến trang Hình ảnh trong Artifacts Registry trong Cloud Console. Giờ đây, bạn có một hình ảnh Docker trên toàn dự án mà Kubernetes có thể truy cập và điều phối như bạn sẽ thấy trong vài phút nữa.
  2. (Không bắt buộc) Sau khi hoàn tất (sẽ mất một khoảng thời gian để tải xuống và trích xuất mọi thứ), hãy kiểm thử hình ảnh bằng lệnh sau. Lệnh này sẽ chạy một vùng chứa Docker dưới dạng một chương trình nền trên cổng 8080 từ hình ảnh vùng chứa mà bạn vừa tạo. Nếu bạn gặp vấn đề về quyền, hãy chạy gcloud auth configure-docker us-central1-docker.pkg.dev trước:
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Một lần nữa, hãy tận dụng tính năng xem trước trên web của Cloud Shell.

6252b94905f3f7bd.png

  1. Bạn sẽ thấy trang mặc định trong một thẻ mới. Sau khi xác minh rằng ứng dụng đang chạy cục bộ trong một vùng chứa Docker, bạn có thể dừng vùng chứa đang chạy bằng cách nhấn Control+C.

6. Tạo cụm

Bạn đã sẵn sàng tạo cụm GKE. Cụm bao gồm một máy chủ API Kubernetes do Google quản lý và một nhóm các nút worker. Các nút worker là VM Compute Engine.

  1. Trước tiên, hãy đảm bảo rằng bạn đã bật các tính năng API có liên quan.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Tạo một cụm có 2 nút n1-standard-1 (quá trình này sẽ mất vài phút để hoàn tất).
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

Cuối cùng, bạn sẽ thấy cụm đã được tạo.

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  ...

Giờ đây, bạn đã có một cụm Kubernetes hoạt động đầy đủ nhờ GKE.

758c7fca14f70623.png

Giờ là lúc triển khai ứng dụng được chứa trong vùng chứa vào cụm Kubernetes! Từ giờ trở đi, bạn sẽ sử dụng dòng lệnh kubectl (đã được thiết lập trong môi trường Cloud Shell). Phần còn lại của lớp học lập trình yêu cầu phiên bản máy chủ và ứng dụng Kubernetes là 1.2 trở lên. kubectl version sẽ cho bạn biết phiên bản hiện tại của lệnh.

7. Triển khai ứng dụng trên Kubernetes

  1. Một hoạt động triển khai Kubernetes có thể tạo, quản lý và mở rộng quy mô nhiều phiên bản của ứng dụng bằng hình ảnh vùng chứa mà bạn đã tạo. Triển khai một phiên bản ứng dụng của bạn lên Kubernetes bằng lệnh kubectl run.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Để xem chế độ triển khai mà bạn đã tạo, chỉ cần chạy lệnh sau:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Để xem các thực thể ứng dụng do quá trình triển khai tạo ra, hãy chạy lệnh sau:
$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

Đến đây, bạn sẽ có vùng chứa chạy dưới sự kiểm soát của Kubernetes, nhưng bạn vẫn phải cho phép truy cập từ bên ngoài.

8. Cho phép lưu lượng truy cập bên ngoài

Theo mặc định, Pod chỉ có thể truy cập bằng IP nội bộ trong cụm. Để có thể truy cập vào vùng chứa hello-java từ bên ngoài mạng ảo Kubernetes, bạn phải hiển thị Pod dưới dạng một dịch vụ Kubernetes.

  1. Trong Cloud Shell, bạn có thể hiển thị Pod cho Internet công cộng bằng cách tạo dịch vụ Kubernetes LoadBalancer.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Xin lưu ý rằng bạn sẽ trực tiếp hiển thị việc triển khai chứ không phải Pod. Điều này sẽ khiến dịch vụ kết quả cân bằng tải lưu lượng truy cập trên tất cả các Pod do việc triển khai quản lý (trong trường hợp này, chỉ có một Pod, nhưng bạn sẽ thêm nhiều bản sao hơn sau này).

Kubernetes Master tạo bộ cân bằng tải và các quy tắc chuyển tiếp, nhóm mục tiêu và quy tắc tường lửa liên quan của Compute Engine để giúp dịch vụ có thể truy cập hoàn toàn từ bên ngoài Google Cloud.

  1. Để tìm địa chỉ IP có thể truy cập công khai của dịch vụ, bạn chỉ cần yêu cầu kubectl liệt kê tất cả các dịch vụ của cụm.
$ 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
  1. Giờ đây, bạn có thể truy cập vào dịch vụ này bằng cách trỏ trình duyệt đến http://<EXTERNAL_IP>:8080.

9. Mở rộng quy mô dịch vụ

Một trong những tính năng mạnh mẽ mà Kubernetes cung cấp là khả năng dễ dàng mở rộng quy mô ứng dụng của bạn. Giả sử bạn đột ngột cần thêm dung lượng cho ứng dụng của mình. Bạn chỉ cần yêu cầu bộ điều khiển sao chép quản lý một số lượng bản sao mới cho các phiên bản ứng dụng của mình.

$ 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

Hãy chú ý đến phương pháp khai báo. Thay vì bắt đầu hoặc dừng các phiên bản mới, bạn khai báo số lượng phiên bản cần chạy mọi lúc. Vòng lặp điều phối Kubernetes chỉ cần đảm bảo rằng thực tế khớp với những gì bạn yêu cầu và thực hiện hành động nếu cần.

10. Ra mắt bản nâng cấp cho dịch vụ của bạn

Đến một thời điểm nào đó, ứng dụng mà bạn triển khai cho phiên bản phát hành công khai sẽ cần được sửa lỗi hoặc bổ sung tính năng. Kubernetes có thể giúp bạn triển khai một phiên bản mới cho bản phát hành công khai mà không ảnh hưởng đến người dùng.

  1. Mở trình soạn thảo mã bằng cách nhấp vào Mở trình chỉnh sửa 2109d75686c889a.pngtrong trình đơn Cloud Shell.
  2. Chuyển đến src/main/java/com/example/springboot/HelloController.java rồi cập nhật giá trị của phản hồi.
package com.example.springboot;

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!";
    }
}
  1. Sử dụng Jib để tạo và đẩy một phiên bản mới của hình ảnh vùng chứa. Quá trình tạo và đẩy hình ảnh đã cập nhật sẽ diễn ra nhanh hơn nhiều vì bạn tận dụng tối đa bộ nhớ đệm.
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Bạn đã sẵn sàng để Kubernetes cập nhật bộ điều khiển sao chép lên phiên bản mới của ứng dụng một cách suôn sẻ!

  1. Để thay đổi nhãn hình ảnh cho vùng chứa đang chạy, bạn cần chỉnh sửa chế độ triển khai hello-java hiện có và thay đổi hình ảnh từ us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

đến us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v2

  1. Bạn có thể dùng lệnh kubectl set image để yêu cầu Kubernetes triển khai phiên bản mới của ứng dụng trên toàn bộ cụm, mỗi lần một phiên bản bằng cách cập nhật luân phiên.
$ kubectl set image deployment/hello-java hello-java=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

deployment "hello-java" image updated
  1. Kiểm tra lại http://EXTERNAL_IP:8080 để xem liệu hàm này có trả về phản hồi mới hay không.

11. Khôi phục

Rất tiếc! Bạn có gặp lỗi với phiên bản mới của ứng dụng không? Có thể phiên bản mới chứa lỗi và bạn cần nhanh chóng khôi phục phiên bản cũ. Với Kubernetes, bạn có thể dễ dàng khôi phục về trạng thái trước đó. Quay lại phiên bản trước của ứng dụng bằng cách chạy lệnh sau:

$ kubectl rollout undo deployment/hello-java

Bạn sẽ thấy câu trả lời cũ khi kiểm tra lại http://EXTERNAL_IP:8080.

12. Xin chúc mừng

Bạn đã tìm hiểu cách tạo và triển khai một ứng dụng web mới dựa trên Java lên Kubernetes trên GKE.

Dọn dẹp

$ gcloud container clusters delete hello-java-cluster --zone us-central1-c

$ gcloud container images delete us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1 us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Tìm hiểu thêm