K8S 环境下的使用 ConfigMap 进行远程配置
分布式远程配置是应用程序开发的一个重要特性,目前有多种流行的工具,比如: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: "配置文件中的消息"
Java 应用代码
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: 配置文件中的消息
部署到 K8S 环境中
应用打包上传等过程略过。
看看 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 的功能可能有点少。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 第十五章 并发版爬虫第二版 -- 完结
- 第十六章 分布式爬虫--准备工作
- go 搭建并行处理管道
- 新一代基于大数据的管理信息系统(MIS)报表需求开发
- 3. docker-compose实战--ghost app
- 2.1 Kubernetes--Pod
- 3. Kubernetes集群安装
- macOS VirtualBox 桥接模式 设置静态ip 且能和联网
- 重新初始化k8s master节点
- 5.k8s基本命令汇总
- 6. k8s + jenkins 实现持续集成(完)
- 7. 复制k8s Node节点 并重新初始化k8s-nodes2节点 (k8s连载)
- 8.k8s连载--重新生成k8s token(kubeadm join报错及解决)
- 3. dcoker容器的命令
- 4. 镜像的原理