Loading
Loading...

Kubernetes 开发 SpringCloud (二)、使用 SpringCloud Kubernetes 组件进行动态配置

相关博文:

系统环境:

一、介绍

组件简介

       SpringCloud 一般都是用 SpringBoot 来做脚手架,而 SpringBoot 的配置一般都在 resources 目录中的 application.yamlbootstrap.yaml 文件中。并且 SpringCloud 在本地开发模式中用的是组件 SpringCloud Config 配置中心来对配置文件进行统一管理、动态更新等,不过在我们开发环境中在这种模式下将配置文件存入 SVN 或者 Git,当网络不稳定发生波动时候,服务无法与这些仓库建立连接而导致不可用。

       由于 Kubernetes 本身存在 ConfigMapSecret 对象来存储配置,所以在 Kubernetes 部署 SpringCloud 的应用尝试不再采用统一配置中心管理配置,而是将配置文件存入 Kubernetes 的 ConfigMap 与 Secret 资源中,经过尝试这种做法确实可行。不过用这种方法还面临一个问题是直接存入 ConfigMap 或者 Secret 中如果配置发生变化,程序是无法感知到变化从而不会进行自动重启或刷新配置。

       由于上面问题,SpringCloud Kubernetes 提供了 spring-cloud-starter-kubernetes-config 组件来解决在 Kubernetes 环境中使用 ConfigMap 或 Secret 动态配置发现与更新问题,当存在 ConfigMap 中的配置或者存在 Secret 中的密码发生更改时候,在 Kubernetes 中的服务能及时监控到这一变化从而按照配置的配置更新策略进行动态更新或者服务重启。

功能简介

SpringCloud Kubernetes Config 组件主要提供以下几种功能:

  • 实时监控 ConfigMap、Secret 配置变化从而更新服务配置。
  • 定时轮询加载 ConfigMap、Secret 配置从而更新服务配置。

二、SpringCloud Kubernetes 动态配置示例

这里写一个使用 spring-cloud-starter-kubernetes-config 组件动态引用 Kubernetes 中的 Config 与 Secret 配置的示例。

注意:示例是在本地启动,通过 Kubectl 的配置文件 config 连接 Kubernetes 获取 ConfigMap、Secret 而并非 Kubernetes 中。如果需要将项目推送到 Kubernetes 中进行测试,需要提前创建好一个能读取 Config 与 Secret 的 ServiceAccount 账户供项目使用,防止因为没有权限而导致无法获取 Kubernetes 中的配置信息。

1、Kubernetes 中部署 ConfigMap、Secret

提前创建 ConfigMapSecret 两个配置文件,并操作 kubectl 工具将两个对象部署到 Kubernetes 集群方便测试。

test-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: test-config
data:
config.booleanValue: "false"
config.numberValue: "1000"
config.stringValue: "configMap中的字符串"

test-secret.yaml

apiVersion: v1
kind: Secret
type: Opaque
metadata:
labels:
secret: enabled
name: test-secret
data:
secret.username: YWRtaW4NCg== #值:admin
secret.password: MTIzNDU2 #值:123456

将两个对象部署到 Kubernetes

  • -n :创建资源到指定的 Namespace
Terminal window
$ kubectl apply -f test-configmap.yaml -n mydlqcloud
$ kubectl apply -f test-secret.yaml -n mydlqcloud

2、创建 SpringCloud Config 示例项目

这里用 SpringCloud Kubernetes 中的服务发现组件 spring-cloud-starter-kubernetes-config 来演示获取 Kubernetes 环境中的 ConfigSecret 示例。

(1)、Maven 引入相关变量

在”pom.xml”文件中引入 SpringBoot 与 SpringCloud Kubernetes Config 相关 Jar。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>club.mydlq</groupId>
<artifactId>springcloud-kubernetes-config-demo</artifactId>
<version>0.0.1</version>
<name>springcloud-kubernetes-config-demo</name>
<description>springcloud kubernetes config demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--SpringBoot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot Actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--SpringCloud Kubernetes Config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

(2)、配置 Bootstrap.yml 文件

创建 bootstrap.yml 文件并设置 flushconfigsecret 的相关配置参数。

spring:
application:
name: springcloud-kubernetes-config-demo
cloud:
kubernetes:
reload:
enabled: true
mode: polling #监听模式:
# (1)、polling:从 ConfigMap 和 Secret 中定期刷新配置,检测是否进行了修改。
# (2)、event(默认):监视配置映射或机密的更改。任何事件都会对配置进行重新检查,如果发生更改,则会重新加载。
period: 5000 #刷新间隔,单位(ms)
strategy: shutdown #刷新模式:
# (1)、refresh(默认):仅注释@ConfigurationProperties或@RefreshScope重新加载的配置Bean
# (2)、restart_context:整个Spring ApplicationContext正常重启。使用新配置重新创建Bean。
# (3)、shutdown:关闭以激活容器的重启。使用此级别时,请确保将所有非守护程序线程的生命周期绑定到该级别,
# 并将ApplicationContext 复制控制器或副本集配置为重新启动该pod。
monitoring-secrets: true #是否监控 Secret 的更改来执行更新
config:
enabled: true #启用 ConfigMap 配置功能
enableApi: true #启用通过 K8S API 发现 ConfigMap 配置
sources:
- namespace: mydlqcloud #指定 Namespace 名称
name: test-config #指定 ConfigMap 名称
secrets:
enabled: true #启用 Secret 配置功能
enableApi: true #启用通过 K8S API 发现 Secret 配置,默认不开启
namespace: mydlqcloud #指定 Namespace 名称
name: test-secret #指定 Secret 名称,根据这个名词引入对应 Secret 配置
#labels: #指定 Label 标签名词,根据这个标签筛选 Secret,读取其中配置
# secret: enabled #自定义的 Label

(3)、配置 application 文件

自定义本地配置,变量名保持和 ConfigMapSecret 中的一致,并且值要设置的不同,这样方便测试时候区分获取的变量是从本地获取的还是从 Kubernetes 中的 ConfigMapSecret 中获取的。

服务动态配置需要设置”management.endpoint.restart.enabled=true”这个参数,否则启动会报错。

management: #Actuator 配置
server:
port: 8081
endpoints:
web:
exposure:
include: "*"
endpoint:
restart:
enabled: true
config: #自定义程序中的 ConfigMap 参数配置
numberValue: 1
stringValue: 这是在程序中的配置
booleanValue: "true"
secret: #自定义程序中的 Secret 参数配置
username: application
password: 123456

(4)、设置 ConfigRead 类读取自定义配置

设置 ConfigRead 类用于测试读取 Kubernetes 中 ConfigMap 中的配置。

ConfigRead.java

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "config")
public class ConfigRead {
private String stringValue;
private Integer numberValue;
private boolean booleanValue;
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public Integer getNumberValue() {
return numberValue;
}
public void setNumberValue(Integer numberValue) {
this.numberValue = numberValue;
}
public boolean isBooleanValue() {
return booleanValue;
}
public void setBooleanValue(boolean booleanValue) {
this.booleanValue = booleanValue;
}
}

(5)、设置 SecretRead 类读取自定义配置

设置 SecretRead 类用于测试读取 Kubernetes 中 Secret 中的配置。

SecretRead.java

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "secret")
public class SecretRead {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

(6)、创建 Controller 类显示自定义配置信息

创建 ConfigController 类中写两个接口,分别用于测试调用 ConfigMapSecret

import club.mydlq.admin.configMap.ConfigRead;
import club.mydlq.admin.secret.SecretRead;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ConfigController {
@Autowired
private ConfigRead configRead;
@Autowired
private SecretRead secretRead;
@GetMapping("/configmap")
public Map<String,Object> getConfig() {
Map<String,Object> map = new HashMap<>();
map.put("StringValue:",configRead.getStringValue());
map.put("NumberValue:",configRead.getNumberValue());
map.put("BooleanValue:",configRead.isBooleanValue());
return map;
}
@GetMapping("/secret")
public Map<String,Object> getSecret() {
Map<String,Object> map = new HashMap<>();
map.put("username:",secretRead.getUsername());
map.put("password:",secretRead.getPassword());
return map;
}
}

(7)、创建启动类并启用服务发现注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

3、调用接口测试

上面定义了两个接口分别为:

  • 服务发现列表接口:/configmap
  • 服务实例信息接口:/secret

然后进行测试,首先测试直接调用接口查看是否能获取 Kubernetes 中 ConfigMapSecret 中的参数信息。之后更改 Kubernetes 中 ConfigMap、Secret 参数的值后等待一段时间再次调用接口测试,检测新获取的参数信息中的值是否发生变化。最后将 Kubernetes 中的 ConfigMapSecret 删除,查看是否能获取程序内部设定的默认的参数。

下面按上面的步骤进行测试:

调用接口读取 ConfigMap 与 Secret 配置测试

/configmap 信息:

{
"StringValue:": "configMap中的字符串",
"NumberValue:": 1000,
"BooleanValue:": false
}

/secret 信息:

{
"username:": "admin",
"password:": "123456"
}

更新 ConfigMap 与 Secret 后调用接口测试

在 Kubernetes 中更改 ConfigMap 中的 StringValue 参数,往后面追加两个字符 AB,再 更改 Secret 中的 Username 参数的值 “admin” 往后面追加两个字符 AB 形成新的 Base64字符串值为 “YWRtaW5BQgo=” ,用这个值替换 Secret 的参数 Username 值,这时候等几秒后再次调用接口测试,查看配置是否发生变化。

/configmap 信息:

{
"StringValue:": "configMap中的字符串AB",
"NumberValue:": 1000,
"BooleanValue:": false
}

/secret 信息:

{
"username:": "adminAB",
"password:": "123456"
}

本人这里调用接口获取的信息跟之前的已经发生变化。

将 ConfigMap 与 Secret 删除后调用接口测试

将 Kubernetes 中的 ConfigMapSecret 删除后再次调用接口进行测试。

{
"StringValue:": "这是在程序中的配置",
"NumberValue:": 1,
"BooleanValue:": true
}

/secret 信息:

{
"username:": "application",
"password:": "123456"
}

可以看到配置已经变成程序中设定的配置,由此可以推测出使用 SpringCloud Kubernetes Config 可以获取 Kubernetes 中 ConfigMapSecret 的配置。如果配置发生更改,程序能够及时检测到并更新程序中的配置。如果不能获取 Kubernetes 中的配置信息,则直接使用程序中配置的默认信息。

三、可配置的参数列表

SpringCloud kubernetes Config 中可以设置 ConfigMap 与 Secret 动态配置参数,如下:

ConfigMap 可配置参数

读取 ConfigMap 的配置

参数名称类型默认值参数描述
spring.cloud.kubernetes.config.enabledBooleantrue是否启动 Config 动态配置
spring.cloud.kubernetes.config.nameString${spring.application.name}设置要查找的 ConfigMap 的名称
spring.cloud.kubernetes.config.namespaceStringClient名称空间设置在哪个 Kubernetes Namespace 查找 ConfigMap 资源
spring.cloud.kubernetes.config.pathsListnull设置ConfigMap装入实例的路径
spring.cloud.kubernetes.config.enableApiBooleantrueConfigMap通过API 启用或禁用使用实例

Secret 可配置参数

读取 Secret 的配置

参数名称类型默认值参数描述
spring.cloud.kubernetes.secrets.enabledBooleantrue是否启动 Secret 动态配置
spring.cloud.kubernetes.secrets.nameString${spring.application.name}设置要查找的 Secret 的名称
spring.cloud.kubernetes.secrets.namespaceStringClient名称空间设置在哪个 Kubernetes Namespace 查找 Secret 资源
spring.cloud.kubernetes.secrets.labelsMapnull设置用于查找 Secret 的标签
spring.cloud.kubernetes.secrets.pathsListnull设置安装 Secret 的路径
spring.cloud.kubernetes.secrets.enableApiBooleanfalse启用或禁用通过 API 监听 Secret

Reload 可配置参数

配置动态更新配置

参数名称类型默认值参数描述
spring.cloud.kubernetes.reload.enabledBooleanfalse启动动态配置监控
spring.cloud.kubernetes.reload.monitoring-config-mapsBooleantrue允许监视 ConfigMap 中的更改
spring.cloud.kubernetes.reload.monitoring-secretsBooleanfalse允许监控 Secret 的变化
spring.cloud.kubernetes.reload.strategyEnumrefresh配置更新策略:
- refresh(更新)
- restart_context(重启Spring容器)
- shutdown(杀死应用使Kubernetes对其重启))
spring.cloud.kubernetes.reload.modeEnumevent指定监听策略:
- event:配置发生变化就执行更新
- polling:定时检测配置变化从而更新配置
spring.cloud.kubernetes.reload.periodDuration15s使用 polling 策略时检测间隔时间
---END---
如果本文对你有帮助,可以关注我的公众号 "小豆丁技术栈" 了解最新动态,顺便也请帮忙 Github 点颗星哦,感谢~

本文作者:超级小豆丁 @ 小豆丁技术栈

本文链接:http://www.mydlq.club/article/32/

本文标题:Kubernetes 开发 SpringCloud (二)、使用 SpringCloud Kubernetes 组件进行动态配置

本文版权:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!