1. 概览
Micronaut 简介
Micronaut 是一种基于 JVM 的现代全栈框架,用于构建易于测试的模块化微服务和无服务器应用。Micronaut 旨在以极低的内存占用量实现极佳的启动时间、快速的吞吐量。开发者可以使用 Micronaut 使用 Java、Groovy 或 Kotlin 进行开发。
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 中,通过使用 Kubernetes Engine(在 Compute Engine 上运行的一种由 Google 托管的 Kubernetes 版本)等代管式环境,您可以更专注于体验 Kubernetes,而不是设置底层基础架构。
如果您有兴趣在本地机器(例如开发笔记本电脑)上运行 Kubernetes,则应考虑使用 Minikube。这提供了用于开发和测试目的的单节点 Kubernetes 集群的简单设置。如果您愿意,可以使用 Minikube 完成此 Codelab。
Jib 简介
Jib 是一种开源工具,可让您为 Java 应用构建 Docker 和 OCI 映像。它可以作为 Maven 和 Gradle 的插件以及 Java 库提供。
Jib 的目标是:
- 快速 - 快速部署您的更改。Jib 将应用拆分为多个层,将依赖项与类分离。现在,您不必等待 Docker 重建整个 Java 应用,只需部署更改的层即可。
- 可重现 - 具有相同内容重建容器映像始终会生成相同的映像。再也不会触发不必要的更新。
- Daemonless - 减少 CLI 依赖项。在 Maven 或 Gradle 中构建 Docker 映像,并将其推送到您选择的任何注册表。无需再编写 Dockerfile 和调用 Docker build/push。
如需详细了解 Jib,请访问 GitHub 项目页面。
关于本教程
本教程使用 Jib 工具中的示例代码为 Java 应用构建容器。
此示例是一个使用 Micronaut 框架和 Apache Groovy 编程语言的简单 hello world 服务。
学习内容
- 如何使用 Jib 将简单的 Java 应用打包为 Docker 容器
- 如何在 Kubernetes Engine 上创建 Kubernetes 集群。
- 如何将 Micronaut 服务部署到 Kubernetes Engine 上的 Kubernetes 中
- 如何对服务进行纵向扩容和发布升级。
- 如何访问 Kubernetes 图形信息中心。
所需条件
您打算如何使用本教程?
您如何评价自己在构建 HTML/CSS Web 应用方面的经验水平?
您如何评价自己在使用 Google Cloud Platform 服务方面的经验水平?
<ph type="x-smartling-placeholder">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 映像,看看能否看到友好的 Hello 消息:
$ 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
要查看您刚刚创建的 Deployment,只需运行以下命令:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
如需查看该 Deployment 创建的应用实例,请运行以下命令:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
此时,您应该让容器在 Kubernetes 的控制下运行,但您仍必须使其可供外部用户访问。
10. 允许外部流量
默认情况下,Pod 只能通过其在集群中的内部 IP 访问。为了使 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 的流量进行负载均衡(在本例中,只有 1 个 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
查看一下 Service 的输出,我们将返回到最初的“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 通用许可授权。