将 Spring Boot Java 应用部署到 Google Kubernetes Engine 上的 Kubernetes

Kubernetes 是一个开源项目,可在从笔记本电脑到高可用性多节点集群、从公有云到本地部署以及从虚拟机 (VM) 实例到裸金属等众多不同环境中运行。

在此 Codelab 中,您将向 GKE 上的 Kubernetes 部署一个简单的 Spring Boot Java Web 应用,目的是让您可以在 Kubernetes 上以复制应用的形式运行 Web 应用。您需要将在机器上开发的代码转换为 Docker 容器映像,并在 GKE 上运行该映像。

您将使用 Google Cloud 上的全代管式 Kubernetes 服务 GKE,让您能够更专注于体验 Kubernetes,而不是设置底层基础架构。

如果您有兴趣在本地机器(如开发笔记本电脑)上运行 Kubernetes,请考虑了解 Minikube,它可为开发和测试目的提供单节点 Kubernetes 集群的简单设置。如果需要,您可以使用 Minikube 完成此 Codelab。

此 Codelab 将使用使用 Spring Boot 构建应用指南中的示例代码。

前提条件

  • 熟悉 Java 编程语言和工具
  • 了解标准的 Linux 文本编辑器,例如 Vim、Emacs 和 nano

您将执行的操作

  • 将简单的 Java 应用打包为 Docker 容器。
  • 在 GKE 上创建 Kubernetes 集群。
  • 将 Java 应用部署到 GKE 上的 Kubernetes。
  • 扩大您的服务规模并发布升级。
  • 访问信息中心,这是基于网络的 Kubernetes 界面。

所需的条件

自定进度的环境设置

  1. 登录 Cloud Console,然后创建一个新项目或重复使用现有项目。(如果您还没有 Gmail 或 G Suite 帐号,则必须创建一个。)

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID

  1. 接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Google Cloud 资源。

在此 Codelab 中运行仅花费几美元,但是如果您决定使用更多资源或继续让它们运行,费用可能更高。

Google Cloud 的新用户有资格获享 $300 免费试用

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud Shell

如果您以前从未启动过 Cloud Shell,您将看到一个中间屏幕(非首屏),上面描述了它是什么。如果是这种情况,请点击继续(您将永远不会再看到它)。一次性屏幕如下所示:

预配和连接到 Cloud Shell 只需花几分钟时间。

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器或 Chromebook 即可完成本 Codelab 中的大部分(甚至全部)工作。

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:

  1. 在 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
  1. 您可以使用 Spring Boot 插件正常启动 Spring Boot 应用。
$ ./mvnw -DskipTests spring-boot:run
  1. 应用启动后,点击 Cloud Shell 工具栏中的网页预览 ,然后选择在端口 8080 上预览

您的浏览器会打开一个标签页,并连接到您刚启动的服务器。

接下来,您需要准备好应用以便在 Kubernetes 上运行。第一步是定义容器及其内容。

  1. 为应用创建可部署的 JAR。
$ ./mvnw -DskipTests package
  1. 启用 Container Registry 以存储您将创建的容器映像。
$ gcloud services enable containerregistry.googleapis.com
  1. 使用 Jib 创建容器映像并将其推送到 Container Registry。
$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \
  -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
  1. 导航到 Container Registry > 映像,如果一切进展顺利,您应该会看到控制台中列出的容器映像。您现在拥有一个适用于整个项目的 Docker 映像,Kubernetes 可对其进行访问和编排(几分钟后您便会看到)。
  1. 完成后(需要一些时间下载和解压缩所有内容),您可以使用以下命令在本地测试映像,这将从新创建的容器映像在端口 8080 上将 Docker 容器作为守护程序运行:
$ docker run -ti --rm -p 8080:8080 \
  gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
  1. 再次充分利用 Cloud Shell 的网页预览功能。

  1. 您应该会在新标签页中看到默认页面。确认应用正在 Docker 容器中本地运行后,您可以按 Control+C 停止正在运行的容器。

您已准备好创建 GKE 集群。集群由 Google 管理的 Kubernetes API 服务器和一组工作器节点组成。工作器节点是 Compute Engine 虚拟机。

  1. 首先,请确保启用相关的 API 功能。
$ gcloud services enable compute.googleapis.com container.googleapis.com
Operation "operations/..." finished successfully
  1. 创建一个包含两个 n1-standard-1 节点的集群(需要几分钟才能完成)。
$ 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 集群了!从现在开始,您将使用 kubectl 命令行(已在 Cloud Shell 环境中设置)。此 Codelab 的其余部分要求 Kubernetes 客户端和服务器版本为 1.2 或更高版本。kubectl version 将显示该命令的当前版本。

  1. Kubernetes Deployment 可以使用您创建的容器映像创建、管理和扩缩应用的多个实例。使用 kubectl run 命令将应用的一个实例部署到 Kubernetes。
$ kubectl create deployment hello-java \
  --image=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
  1. 要查看您创建的 Deployment,只需运行以下命令:
$ kubectl get deployments
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. 如需查看该 Deployment 创建的应用实例,请运行以下命令:
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

此时,您应该让容器在 Kubernetes 的控制下运行,但您仍须允许外部世界访问该容器。

默认情况下,Pod 只能通过其在集群内的内部 IP 访问。为了使 hello-java 容器可以从 Kubernetes 虚拟网络外部进行访问,您必须将 Pod 公开为 Kubernetes 服务。

  1. 在 Cloud Shell 中,您可以结合使用 kubectl expose 命令和 --type=LoadBalancer 标志向公共互联网公开 Pod。此标志在创建外部可访问的 IP 时是必需的。
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

该命令中使用的标志指定您将使用底层基础架构提供的负载均衡器。请注意,您直接公开了 Deployment,而不是 Pod。这会使生成的服务对 Deployment 管理的所有 Pod 的流量进行负载均衡(在本例中,只有一个 Pod,但稍后您将添加更多副本)。

Kubernetes 主实例会创建负载均衡器和相关的 Compute Engine 转发规则、目标池和防火墙规则,以使该服务完全可从 Google Cloud 外部进行访问。

  1. 如需查找服务的可公开访问的 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
  1. 请注意,系统针对您的服务列出了两个 IP 地址,它们均通过端口 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 可帮助您将新版本部署到生产环境,而不会影响您的用户。

  1. 点击 Cloud Shell 菜单中的启动编辑器 ,打开代码编辑器。
  2. 导航到 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!";
    }
}
  1. 使用 Jib 构建和推送新版本的容器映像。
$ ./mvnw -DskipTests package \
  com.google.cloud.tools:jib-maven-plugin:build \
  -Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2

您现在可以让 Kubernetes 顺利地将您的副本控制器更新到新版应用了!

  1. 如需更改正在运行的容器的映像标签,您需要修改现有的 hello-java Deployment,并将映像从 gcr.io/PROJECT_ID/hello-java:v1 更改为 gcr.io/PROJECT_ID/hello-java:v2
  1. 您可以使用 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
  1. 再次检查 http://EXTERNAL_IP:8080 以查看它是否返回了新响应。

糟糕!您是否在使用新版应用时出错?可能是因为新版本包含错误,您需要快速回滚。借助 Kubernetes,您可以轻松地将其回滚到先前的状态。通过运行以下命令回滚应用:

$ kubectl rollout undo deployment/hello-java

您已了解如何构建基于 Java 的新 Web 应用并将其部署到 GKE 上的 Kubernetes。

了解详情