1. 概述
在构建微服务架构时,Spring Cloud 和 Kubernetes 都是非常优秀的解决方案,它们分别解决了微服务开发和部署中的一些关键问题。如果我们决定使用 Kubernetes 作为主要的容器管理和部署平台,我们仍然可以通过 Spring Cloud Kubernetes 项目来使用 Spring Cloud 的一些高级功能。
这个相对较新的项目为 Spring Boot 应用提供了与 Kubernetes 的无缝集成。在开始之前,建议先了解如何在本地 Kubernetes 环境 Minikube 中部署 Spring Boot 应用。
在本教程中,我们将:
- 在本地安装 Minikube
- 构建一个由两个独立 Spring Boot 应用组成的微服务架构,通过 REST 相互通信
- 使用 Minikube 搭建一个单节点 Kubernetes 集群
- 使用 YAML 配置文件部署应用
2. 场景说明
我们以一个旅游代理服务为例:代理提供各种旅行套餐,客户端会不定期地向代理服务发起查询请求。我们将通过这个场景演示以下功能:
✅ 服务发现(Service Discovery):通过 Spring Cloud Kubernetes 实现
✅ 配置管理(Config Management):使用 ConfigMap 和 Secret 注入配置
✅ 负载均衡(Load Balancing):基于 Spring Cloud Kubernetes Ribbon 实现
3. 环境准备
首先,我们需要在本地安装 Minikube,建议同时安装一个虚拟机驱动,比如 VirtualBox。如果你对 Kubernetes 不太熟悉,可以先了解其核心概念。
启动本地单节点 Kubernetes 集群:
minikube start --vm-driver=virtualbox
切换到 Minikube 上下文:
kubectl config use-context minikube
启动 Kubernetes 仪表盘(用于查看日志和监控服务):
minikube dashboard
3.1 部署流程
示例代码可以从 GitHub 获取:GitHub 仓库地址
你可以在项目根目录下运行部署脚本 deployment-travel-client.sh
,或者手动执行以下命令:
### 构建 Maven 项目
mvn clean install
### 设置 Docker 环境
eval $(minikube docker-env)
### 在 Minikube 中构建 Docker 镜像
cd travel-agency-service
docker build -t travel-agency-service .
cd ../client-service
docker build -t client-service .
cd ..
### 删除并创建 Secret 和 MongoDB
kubectl delete -f travel-agency-service/secret.yaml
kubectl delete -f travel-agency-service/mongo-deployment.yaml
kubectl create -f travel-agency-service/secret.yaml
kubectl create -f travel-agency-service/mongo-deployment.yaml
### 部署 travel-agency-service
kubectl delete -f travel-agency-service/travel-agency-deployment.yaml
kubectl create -f travel-agency-service/travel-agency-deployment.yaml
### 部署 client-service
kubectl delete configmap client-service
kubectl delete -f client-service/client-service-deployment.yaml
kubectl create -f client-service/client-config.yaml
kubectl create -f client-service/client-service-deployment.yaml
# 查看 Pod 状态
kubectl get pods
4. 服务发现(Service Discovery)
Spring Cloud Kubernetes 提供了 Kubernetes 环境下的服务发现实现。在微服务架构中,通常一个服务会有多个 Pod 实例运行。Kubernetes 将这些服务以 endpoint 的形式暴露出来,Spring Boot 应用可以通过这些 endpoint 进行访问。
例如,在我们的示例中,客户端服务通过 http://travel-agency-service:8080
访问旅行代理服务,但这个地址内部会解析为多个 Pod 实例,如 travel-agency-service-7c9cfff655-4hxnp
。
Spring Cloud Kubernetes Ribbon 利用这一特性实现服务的负载均衡。
要在客户端启用服务发现,只需添加如下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>
并在主类上添加 @EnableDiscoveryClient
,并注入 DiscoveryClient
:
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
public class ClientController {
@Autowired
private DiscoveryClient discoveryClient;
}
5. ConfigMap 配置管理
微服务通常需要集中管理配置信息。在传统 Spring Cloud 架构中,我们使用 Config Server。但在 Kubernetes 中,我们可以使用 ConfigMap 来管理非敏感配置信息。
在我们的示例中,client-service
使用 ConfigMap 注入配置。创建 client-config.yaml
文件:
apiVersion: v1
kind: ConfigMap
metadata:
name: client-service
data:
application.properties: |-
bean.message=Testing reload! Message from backend is: %s <br/> Services : %s
注意:ConfigMap 名称必须与应用名一致,这里是 client-service
。
部署 ConfigMap:
kubectl create -f client-config.yaml
创建配置类并注入:
@Configuration
@ConfigurationProperties(prefix = "bean")
public class ClientConfig {
private String message = "Message from backend is: %s <br/> Services : %s";
// getters and setters
}
@RestController
public class ClientController {
@Autowired
private ClientConfig config;
@GetMapping
public String load() {
return String.format(config.getMessage(), "", "");
}
}
更新 ConfigMap 会自动生效:
kubectl edit configmap client-service
6. Secret 敏感信息管理
Secret 用于管理敏感信息,比如数据库用户名和密码。下面以 MongoDB 连接配置为例说明如何使用 Secret。
6.1 创建 Secret
创建 secret.yaml
文件,Base64 编码用户名和密码:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
data:
username: dXNlcg==
password: cDQ1NXcwcmQ=
部署 Secret:
kubectl apply -f secret.yaml
6.2 创建 MongoDB 服务
在 travel-agency-deployment.yaml
中引用 Secret:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mongo
spec:
replicas: 1
template:
metadata:
labels:
service: mongo
spec:
containers:
- args:
- mongod
- --smallfiles
image: mongo:latest
name: mongo
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
6.3 配置 MongoDB 连接信息
在 application.properties
中引用环境变量:
spring.cloud.kubernetes.reload.enabled=true
spring.cloud.kubernetes.secrets.name=db-secret
spring.data.mongodb.host=mongodb-service
spring.data.mongodb.port=27017
spring.data.mongodb.database=admin
spring.data.mongodb.username=${MONGO_USERNAME}
spring.data.mongodb.password=${MONGO_PASSWORD}
在部署文件中注入 Secret:
env:
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
7. 使用 Ribbon 进行通信
在微服务环境中,负载均衡是必不可少的。Spring Cloud Kubernetes Ribbon 提供了一种自动发现服务 endpoint 的机制,并将其注入到 Ribbon 的 ServerList
中,从而实现负载均衡。
在 client-service
中添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
</dependency>
添加 @RibbonClient
注解:
@RibbonClient(name = "travel-agency-service")
启用 Ribbon:
ribbon.http.client.enabled=true
Ribbon 会自动发现当前命名空间下名为 travel-agency-service
的所有 endpoint,并进行负载均衡。
8. 其他功能
8.1 Hystrix 熔断机制
Hystrix 是一个用于构建容错、弹性系统的组件。它的核心思想是“快速失败”和“快速恢复”。
虽然 Hystrix 已不再积极维护,但在某些场景下仍可使用,尤其是在需要熔断和降级机制的微服务中。
9. 总结
本文详细介绍了 Spring Cloud Kubernetes 的使用方式,包括服务发现、配置管理(ConfigMap & Secret)、以及负载均衡等核心功能。
为什么选择 Spring Cloud Kubernetes?
如果你已经决定使用 Kubernetes 作为微服务的基础设施,但又希望保留 Spring Cloud 提供的开发便利性,那么 Spring Cloud Kubernetes 正是两者结合的最佳方案。
完整示例代码可在 GitHub 仓库 找到。