1. 概览
Micronaut 简介
Micronaut 是一款基于 JVM 的现代全栈框架,用于构建模块化、易于测试的微服务和无服务器应用。Micronaut 旨在以最小的内存占用量实现出色的启动时间和快速的吞吐量。开发者可以使用 Java、Groovy 或 Kotlin 通过 Micronaut 进行开发。
Micronaut 提供:
- 启动时间短,内存消耗低 - 基于反射的 IoC 框架会加载并缓存代码中每个字段、方法和构造函数的反射数据,而使用 Micronaut 时,应用启动时间和内存消耗不受代码库大小的限制。
- 声明式、响应式、编译时 HTTP 客户端 - 以声明方式构建响应式 HTTP 客户端,这些客户端在编译时实现,可减少内存消耗。
- 基于 Netty 构建的非阻塞 HTTP 服务器 - Micronaut 的 HTTP 服务器具有平缓的学习曲线,可让您尽可能轻松地公开可供 HTTP 客户端使用的 API。
- 快速轻松的测试 - 在单元测试中轻松启动服务器和客户端,并立即运行。
- 高效的编译时依赖注入和 AOP - Micronaut 提供了一个不使用反射的简单编译时面向方面的编程 API。
- 构建完全反应式且非阻塞的应用 - Micronaut 支持任何实现 Reactive Streams 的框架,包括 RxJava 和 Reactor。
如需了解详情,请访问 Micronaut 网站。
关于 Kubernetes
Kubernetes 是一个开源项目,可在从笔记本电脑到高可用性多节点集群、从公有云到本地部署以及从虚拟机到裸金属等众多不同环境中运行。
在本实验中,您将一个基于 Groovy 的简单 Micronaut 微服务部署到在 Kubernetes Engine 上运行的 Kubernetes。
此 Codelab 的目标是让您以在 Kubernetes 上运行的复制服务的形式运行微服务。您需要将在机器上开发的代码转换为 Docker 容器映像,然后在 Kubernetes Engine 上运行该映像。
下图展示了此 Codelab 中涉及的各个部分,可帮助您了解这些部分如何组合在一起。在学习此 Codelab 的过程中,您可以参考此图;当您完成此 Codelab 时,您应该能够理解此图中的所有内容(但您现在可以忽略此图)。

在本 Codelab 中,借助 Kubernetes Engine(在 Compute Engine 上运行的 Google 托管式 Kubernetes 版本)这样的托管式环境,您可以把更多精力放在体验 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。
您可以在 GitHub 项目页面上详细了解 Jib。
关于本教程
本教程使用 Jib 工具中的示例代码来为 Java 应用构建容器。
此示例是一个简单的 hello world 服务,使用 Micronaut 框架和 Apache Groovy 编程语言。
学习内容
- 如何使用 Jib 将简单的 Java 应用打包为 Docker 容器
- 如何在 Kubernetes Engine 上创建 Kubernetes 集群。
- 如何将 Micronaut 服务部署到 Kubernetes Engine 上的 Kubernetes 中
- 如何扩容服务并发布升级。
- 如何访问 Kubernetes 图形信息中心。
所需条件
您打算如何使用本教程?
您如何评价自己在构建 HTML/CSS Web 应用方面的经验水平?
您如何评价自己在使用 Google Cloud Platform 服务方面的经验水平?
2. 设置和要求
自定进度的环境设置
请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
- 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。
运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分中的所有说明操作,该部分介绍了如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
3. 获取 Micronaut 示例源代码
在 Cloud Shell 启动后,您可以使用命令行在主目录中克隆示例源代码,然后使用 cd 命令进入包含示例服务的目录:
$ 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 上运行。为此,我们将利用 Jib 为我们完成繁重的工作,因为我们自己不必接触 Dockerfile!
我们来运行命令以构建容器:
$ ./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 Container Registry,这是一个私有代码库,用于存储您的 Docker 映像,可从每个 Google Cloud 项目(也可从 Google Cloud Platform 外部)访问。
在能够推送到注册表之前,我们先前往工具 > 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 实例,将映像标记为指向其在注册表中的位置,然后将其推送到注册表。
如果一切顺利,过一会儿您应该就能在控制台中看到列出的容器映像:工具 > Container Registry。现在,您拥有一个适用于整个项目的 Docker 映像,Kubernetes 可对其进行访问和编排(几分钟后您便会看到)。

8. 创建集群
现在,您可以创建 Kubernetes Engine 集群了,但在此之前,请前往 Web 控制台的 Google Kubernetes Engine 部分,等待系统初始化(只需几秒钟)。

集群由 Google 管理的 Kubernetes 主 API 服务器和一组工作器节点组成。工作器节点是 Compute Engine 虚拟机。我们来使用 CloudShell 会话中的 gcloud CLI 创建一个包含两个 n1-standard-1 节点的集群(此过程需要几分钟才能完成):
$ 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 集群了!从现在开始,您将使用 kubectl 命令行(已在 Cloud Shell 环境中设置)。此 Codelab 的其余部分要求 Kubernetes 客户端和服务器版本均为 1.2 或更高版本。kubectl version 将显示该命令的当前版本。
9. 将应用部署到 Kubernetes
Kubernetes Deployment 可以使用您刚刚创建的容器映像创建、管理和扩缩应用的多个实例。我们来使用 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. 允许外部流量
默认情况下,只能通过 pod 在集群内的内部 IP 访问该 pod。为了使 hello-micronaut 容器可以从 Kubernetes 虚拟网络外部进行访问,您必须将 Pod 公开为 Kubernetes 服务。
在 Cloud Shell 中,您可以结合使用 kubectl expose 命令和 --type=LoadBalancer 标志向公共互联网公开 pod。此标志在创建外部可访问的 IP 时是必需的:
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
此命令中使用的标志指定您将使用底层基础架构(在本例中为 Compute Engine 负载平衡器)提供的负载平衡器。请注意,您公开的是 Deployment,而不是直接公开 Pod。这会使生成的服务对 Deployment 管理的所有 Pod 的流量进行负载均衡(在本例中,只有一个 Pod,但稍后您将添加更多副本)。
Kubernetes 主实例会创建负载平衡器和相关的 Compute Engine 转发规则、目标池和防火墙规则,以使该服务完全可从 Google Cloud Platform 外部进行访问。
如需查找服务的可公开访问的 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
请注意,系统针对您的服务列出了 2 个 IP 地址,它们均通过端口 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
然后标记映像并将其推送到容器映像注册表中:
$ 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 的新 Web 微服务并将其部署到 Google Kubernetes Engine 上的 Kubernetes。
了解详情
- Jib 文档和示例:https://github.com/GoogleContainerTools/jib/
- Micronaut 网站:http://micronaut.io/
- Google Cloud Platform 上的 Java:https://cloud.google.com/java/
- 如需查看 Java 示例,请访问:https://cloud.google.com/java/samples
- 如需查看更长、更完整的 Kubernetes 教程,请访问 bit.ly/k8s-lab,该教程将引导您完成全栈应用的部署。
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。