Markus Gulden 2024-01-08
使用 Minikube 运行 Spring Boot 应用程序
1. 概述
在上一篇文章中,我们对 Kubernetes 进行了理论性的介绍。
在本教程中,我们将讨论如何在本地 Kubernetes 环境(即 Minikube)上部署一个 Spring Boot 应用程序。
本文将涵盖以下内容:
- 在本地机器上安装 Minikube
- 开发一个包含两个 Spring Boot 服务的示例应用程序
- 使用 Minikube 在单节点集群中设置该应用程序
- 使用配置文件部署应用程序
2. 安装 Minikube
Minikube 的安装主要包括三个步骤:安装 Hypervisor(如 VirtualBox)、安装 CLI 工具 kubectl,以及安装 Minikube 本身。
官方文档为每个步骤提供了详细的说明,并支持所有主流操作系统。
完成安装后,我们可以启动 Minikube,设置 VirtualBox 作为 Hypervisor,并配置 kubectl 与名为 minikube 的集群通信:
$> minikube start
$> minikube config set vm-driver virtualbox
$> kubectl config use-context minikube
之后,我们可以验证 kubectl 是否能正确与集群通信:
$> kubectl cluster-info
输出应类似于:
Kubernetes master is running at https://192.168.99.100:8443
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
此时,请记住响应中的 IP 地址(例如本例中的 192.168.99.100)。我们稍后会将其称为 NodeIP,用于从集群外部(例如浏览器)访问资源。
最后,我们可以检查集群的状态:
$> minikube dashboard
此命令将在默认浏览器中打开一个页面,提供关于集群状态的详细概览。
4. 示例应用程序
现在我们的集群已运行并准备好部署应用,接下来需要一个演示应用。
为此,我们将创建一个简单的“Hello world”应用,包含两个 Spring Boot 服务,分别命名为 frontend 和 backend。
- backend 在端口 8080 上提供一个 REST 接口,返回包含其主机名的字符串。
- frontend 在端口 8081 上可用,它会调用 backend 的接口并返回其响应。
接下来,我们需要为每个应用构建 Docker 镜像。所有相关文件也可在 GitHub 上找到。
有关如何构建 Docker 镜像的详细说明,请参阅《Dockerizing a Spring Boot Application》。
这里需要注意的是:我们必须在 Minikube 集群的 Docker 主机上触发构建过程,否则 Minikube 在后续部署时将找不到这些镜像。此外,还需将本地主机的工作目录挂载到 Minikube 虚拟机中:
$> minikube ssh
$> cd /c/workspace/tutorials/spring-cloud/spring-cloud-kubernetes/demo-backend
$> docker build --file=Dockerfile \
--tag=demo-backend:latest --rm=true .
完成后,退出 Minikube 虚拟机。后续所有操作都将在本地主机上通过 kubectl 和 minikube 命令行工具执行。
5. 使用命令式命令进行简单部署
首先,我们将为 demo-backend 应用创建一个 Deployment(仅包含一个 Pod)。在此基础上,我们将介绍一些命令,用于验证部署、查看日志,并在最后清理资源。
5.1 创建 Deployment
我们将使用 kubectl,并通过参数传递所有必要信息:
$> kubectl run demo-backend --image=demo-backend:latest \
--port=8080 --image-pull-policy Never
如上所示:
- 我们创建了一个名为
demo-backend的 Deployment; - 使用的镜像也叫
demo-backend,版本为latest; - 通过
--port指定 Pod 监听 8080 端口(因为我们的 backend 应用监听该端口); --image-pull-policy Never确保 Minikube 不尝试从远程仓库拉取镜像,而是直接使用本地 Docker 主机上的镜像。
5.2 验证 Deployment
现在可以检查部署是否成功:
$> kubectl get deployments
输出如下:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
demo-backend 1 1 1 1 19s
如果想查看应用日志,需先获取 Pod ID:
$> kubectl get pods
$> kubectl logs <pod id>
5.3 为 Deployment 创建 Service
为了让 backend 的 REST 接口对外可用,我们需要创建一个 Service:
$> kubectl expose deployment demo-backend --type=NodePort
--type=NodePort表示该 Service 可从集群外部访问;- 它将以
<NodeIP>:<NodePort>的形式暴露服务,即将所有发往<NodePort>的请求转发到 Pod 的 8080 端口。
使用 expose 命令时,NodePort 由集群自动分配(这是技术限制),默认范围是 30000–32767。若要指定特定端口,需使用配置文件(见下一节)。
验证 Service 是否创建成功:
$> kubectl get services
输出如下:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-backend NodePort 10.106.11.133 <none> 8080:30117/TCP 11m
可以看到:
- Service 名为
demo-backend,类型为NodePort; - 集群内部 IP 为
10.106.11.133; PORT(S)列显示:外部可通过端口30117访问,该端口映射到 Pod 的 8080 端口。
5.4 调用 Service
现在可以首次调用 backend 服务:
$> minikube service demo-backend
该命令会自动在默认浏览器中打开 <NodeIP>:<NodePort>,例如:http://192.168.99.100:30117。
5.5 清理 Service 和 Deployment
完成后,可删除 Service 和 Deployment:
$> kubectl delete service demo-backend
$> kubectl delete deployment demo-backend
6. 使用配置文件进行复杂部署
对于更复杂的部署场景,使用配置文件比通过命令行参数传递所有选项更为合适。
配置文件便于记录部署细节,并可纳入版本控制系统。
6.1 Backend 应用的 Service 定义
我们使用配置文件重新定义 backend 的 Service:
kind: Service
apiVersion: v1
metadata:
name: demo-backend
spec:
selector:
app: demo-backend
ports:
- protocol: TCP
port: 8080
type: ClusterIP
说明:
- 创建名为
demo-backend的 Service; - 选择带有标签
app: demo-backend的 Pod; - 监听 TCP 8080 端口;
- 类型为
ClusterIP,表示仅在集群内部可访问(因为 frontend 会调用它,无需从浏览器直接访问)。
6.2 Backend 应用的 Deployment 定义
接下来定义实际的 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-backend
spec:
selector:
matchLabels:
app: demo-backend
replicas: 3
template:
metadata:
labels:
app: demo-backend
spec:
containers:
- name: demo-backend
image: demo-backend:latest
imagePullPolicy: Never
ports:
- containerPort: 8080
说明:
- Deployment 名为
demo-backend; - 通过
selector.matchLabels匹配带有app: demo-backend标签的 Pod; - 启动 3 个副本(
replicas: 3); - 每个 Pod 运行一个名为
demo-backend的容器,使用本地镜像,监听 8080 端口。
6.3 部署 Backend 应用
执行部署:
$> kubectl create -f backend-deployment.yaml
验证部署:
$> kubectl get deployments
输出:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
demo-backend 3 3 3 3 25s
检查 Service:
$> kubectl get services
输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-backend ClusterIP 10.102.17.114 <none> 8080/TCP 30s
注意:此次 Service 类型为 ClusterIP,没有分配 30000–32767 范围内的外部端口。
6.4 Frontend 应用的 Service 与 Deployment 定义
接着为 frontend 定义 Service 和 Deployment:
kind: Service
apiVersion: v1
metadata:
name: demo-frontend
spec:
selector:
app: demo-frontend
ports:
- protocol: TCP
port: 8081
nodePort: 30001
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-frontend
spec:
selector:
matchLabels:
app: demo-frontend
replicas: 3
template:
metadata:
labels:
app: demo-frontend
spec:
containers:
- name: demo-frontend
image: demo-frontend:latest
imagePullPolicy: Never
ports:
- containerPort: 8081
主要区别:
- frontend 的 Service 类型为
NodePort(需对外暴露); - 显式指定了
nodePort: 30001,以便从外部访问。
6.5 部署 Frontend 应用
执行部署:
$> kubectl create -f frontend-deployment.yaml
快速验证:
$> kubectl get deployments
$> kubectl get services
最后,调用 frontend 的 REST 接口:
$> minikube service demo-frontend
该命令将在浏览器中打开 http://192.168.99.100:30001。
6.6 清理 Services 和 Deployments
完成测试后,清理资源:
$> kubectl delete service demo-frontend
$> kubectl delete deployment demo-frontend
$> kubectl delete service demo-backend
$> kubectl delete deployment demo-backend
7. 结论
在本文中,我们快速了解了如何在本地 Kubernetes 集群(Minikube)上部署一个 Spring Boot “Hello world” 应用。
我们详细讨论了以下内容:
- 如何在本地机器上安装 Minikube;
- 如何开发并构建包含两个 Spring Boot 应用的示例项目;
- 如何在单节点集群中部署服务,既使用了
kubectl的命令式操作,也使用了 YAML 配置文件进行声明式部署。
通过这种方式,开发者可以在本地高效地测试和调试基于 Kubernetes 的微服务架构。