1. 概述

在构建微服务架构时,Spring CloudKubernetes 都是非常优秀的解决方案,它们分别解决了微服务开发和部署中的一些关键问题。如果我们决定使用 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 仓库 找到。


原始标题:Guide to Spring Cloud Kubernetes | Baeldung