分布式远程配置是应用程序开发的一个重要特性,目前有多种流行的工具,比如:spring-cloud-config, apollo, disconf, nacos 等。
在云原生时代,应用都部署到 k8s/istio 环境中,远程配置在原生 K8S 环境下有没有方案呢?答案是有的。
最容易想到的一个方案就是:使用 ConfigMap 将 配置文件的内容映射到运行目录。ConfigMap 会在改变后自动下发,应用程序只需要监视配置文件的改变,进行热替换就可以了。
但 Spring Cloud 早就有 K8S 环境下的远程配置方案。这就是 spring-cloud-kubernetes,使用 spring-cloud-starter-kubernetes-config 这个 SDK 包,就可以实现动态远程配置。这篇文章将会实践这一方案。
在 Springboot 项目下增加如下的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>
1、bootstrap.yaml 文件里会存储基本信息,这些信息是全局信息,基本不会改变:
spring:
application:
name: config-k8s
cloud:
kubernetes:
reload:
enabled: true
mode: polling
period: 5000
config:
namespace: autoconfig
sources:
- name: ${spring.application.name}
management:
endpoint:
restart:
enabled: true
health:
enabled: true
info:
enabled: true
上面的配置中:每隔 5s 去更新配置, config.namespace 将是你的 ConfigMap 部署的命名空间,而 sources.name 就是你的 ConfigMap 的 名字。在这个例子中,ConfigMap 的 metadata.name 就是 config-k8s。
2、application.yaml 的配置如下,我们的实验就是要动态修改 bean.message 的值。
bean:
message: "配置文件中的消息"
1、编写一个 bean 用于实体化配置。
@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "bean")
public class MyConfig {
private String message = "默认的消息";
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
2、编写一个 Controller 来输出
@RestController
public class HelloController {
@Autowired
MyConfig myConfig;
@RequestMapping("/")
public String hello() {
return "读取配置 bean.message: " + myConfig.getMessage();
}
}
至此,我们的代码编写配置工作基本完事。在本地开发环境中运行,他会读取 本地的配置,打开浏览器 http://localhost:8080/
读取配置 bean.message: 配置文件中的消息
应用打包上传等过程略过。
看看 ConfigMap 的代码:
apiVersion: v1
kind: ConfigMap
metadata:
name: config-k8s
namespace: autoconfig
data:
bean.message: 这是从 K8S 的 config 中来。
由于应用需要使用 K8S 的 api server 来更新配置,需要进行授权。代码如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: config-reader
namespace: autoconfig
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: autoconfig
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods","configmaps"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader
namespace: autoconfig
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-reader
subjects:
- kind: ServiceAccount
name: config-reader
namespace: autoconfig
创建了服务账号,记得使用此服务账号允许应用,配置如下,请注意:serviceAccountName: config-reader。
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
app: config-k8s
version: v1
name: config-k8s
namespace: autoconfig
spec:
replicas: 1
selector:
matchLabels:
app: config-k8s
version: v1
template:
metadata:
labels:
app: config-k8s
version: v1
spec:
serviceAccountName: config-reader
containers:
- image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/config-k8s:1.0.2
imagePullPolicy: IfNotPresent
name: config-k8s
ports:
- containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
labels:
app: config-k8s
name: config-k8s
namespace: autoconfig
spec:
ports:
- name: http
port: 8080
protocol: TCP
selector:
app: config-k8s
部署完成后,运行K8S 环境中的应用,会显示:
读取配置 bean.message: 这是从 K8S 的 config 中来。
试着修改 ConfigMap,并刷新页面,可以看到相应的变动。
我们还可以将配置更新的方式改为事件模式,这样可以进行配置的实时更改。修改 bootstrap.yaml 文件夹中的:
spring.cloud.kubernetes.reload.mode=event
并删除 spring.cloud.kubernetes.reload.period 节点。
使用 K8S 自带的 ConfigMap 和 API Server 可以直接完成远程配置,这种做法的好处显而易见:无需部署额外的 Config Server 系统。
缺点也有:ConfigMap 的作用范围一般是集群内,所以如果要跨集群使用会稍麻烦,并且相较于其他独立的Config Server,K8S Config Map 的功能可能有点少。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。