1.模型

首先会在每一个节点上安装一个叫 agent 端 agent 端要做的作用就是监听当前的目标配置中心的配置选项是否发送更新动作 如果有的话 我的agent 端的话要从远程的配置中心 去下载最新的配置文件 替换我当前的 再去触发nginx实现重载 当然对于后期的运维工程师 如果想去发布新的版本的话 我只需要在配置中心对于的域名下 域名服务下 去添加最新的 stable 版本 那这样的话 我们就可以让我们的agent 指向到 我们的最新版本 再一次的去出发后端真实服务器的更新和重载 整个过程是对于我们来说完全是无痕的 不需要我们去做任何的动作 那这就是我们的configmap的模型

2.注入机制
是注入而不是共享
将文件分发给三台机器是不是有两种考虑
1.挂载形式 共享
第一种方式 我们从我们的分发的机器上 那需要的分发的这个文件 我们能不能把它挂载到 你可以在这里搭一个NFS通过共享的方式去实现 没有问题

2.注入的形式
我们通过注入的方式让数据达到一致 比如真的有一个文件发生变化了 那我们类似于执行一条指令来 比如 catt 1.txt 2.txt 文件 用一个新的数据将原来的文件内部去替换掉 那这是不是也可以保证 我们多个pod之间的文件是一样的 这就是让多个不同 服务之间的文件 达到一致性的两种思想 一个是共享一个是注入
3.利弊
当然对于这两种方案啊 各有利弊
我们configmap 的机制 是通过注入的方式
1.注入的优势
一次注入后 ,多次读取不在消耗 网络 IO
可以分批注入 对于网络 IO 的峰值更低
2.注入的劣势
3.共享的优势
4.共享的劣势
每一次在读取文件的时候,都会发生网络IO
对于共享的io同时去向我们的共享服务器读取这个配置文件 那就可能产生峰值的网络IO 的出现
5.总结
共享适合那种有好多不同的小文件 我一起共享给你 你用哪一个 我读取哪一个
那注入的话更适用于那种一两个配置文件 而且大概率回去使用它 那这时候就用注入
3.创建
这里没有提到 --from-env-file, 建议同学们延展了解下 --from-file 和 --from-env-file 的区别
1.--from-file 文件名为 key 文件内容为 value
bash
kubectl create configmap 对象名 --from-file=文件路径
1.文件内部必须是一行一对的 k=v,可以在使用的适合注入至pod的内部变成环境变量
1.txt
name=zhangsan
passwd=123
2.文件内部不是一行一对 的k=v 不能被当作环境变量使用
2.txt
今天天气真不错,适合爬山
2.--from-literal 我们直接把对应需要去创建出来的key value 对象直接编写在了我们的选项中或者创建命令里 所以这种方式更适合那种key value比较简短的 比如就写一个用户名
bash
kubectl create configmap literal-config --from-literal=name=dave --from-literal=password=pass
3.使用第一种方式创建
1.创建一个jmj.txt文件 文件名随便取
文件内容
bash
name=zhangsan
password=123456
执行
bash
kubectl create configmap jmj-config --from-file=jmj.file

创建成功
查看一下
bash
kubectl get configmap
简写
bash
kubectl get cm

获取对象里面的信息
bash
kubectl get cm jmj-config -o yaml
建议用文件的方式创建
如果你想把 jmj-config 打出 yaml 可以执行
bash
kubectl create configmap jmj-config --from-file=jmj.file --dry-run -o yaml > 2.cm.yaml
1..另一种查看方式
bash
kubectl describe cm jmj-config
4.使用第二种方式创建
bash
kubectl create configmap literal-config --from-literal=name=dave --from-literal=password=pass
这样创建两个文件 里面分别是 dave 和 pass 然后执行下面的命令 和上面那条命令是一个效果
bash
kubectl create configmap aa-config --from-file=name --from-file=password
5.yaml
可以通过yaml创建

6.小实验 将当前的configmap 注入到pod内部环境变量
创建 1.pod.yaml
bash
apiVersion: v1
kind: ConfigMap
metadata:
name: literal-config
namespace: default
data:
name: dave
password: pass
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
---
apiVersion: v1
kind: Pod
metadata:
name: cm-env-pod
spec:
containers:
- name: myapp-container
image: wangyanglinux/myapp:v1.0
command: [ "/bin/sh", "-c", "env" ]
env:
- name: USERNAME
valueFrom:
configMapKeyRef:
name: literal-config
key: name
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: literal-config
key: password
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
env加入环境变量 来源于 某个 configmap name 为 cm 名称 key 为 key
envFrom 直接把这个configmap的所有key value 注入到环境变量 但是不能修改了
bash
kubectl create -f 1.pod.yaml
看一下pod的日志
bash
kubectl logs cm-env-pod

7.小实验 将当前的configmap 注入到 mainC的启动命令
configmap可以当做启动参数
创建 2.pod.yaml
bash
apiVersion: v1
kind: Pod
metadata:
name: cm-command-pod
spec:
containers:
- name: myapp-container
image: wangyanglinux/myapp:v1.0
command: [ "/bin/sh", "-c", "echo $(USERNAME) $(PASSWORD)" ]
env:
- name: USERNAME
valueFrom:
configMapKeyRef:
name: literal-config
key: name
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: literal-config
key: password
restartPolicy: Never
bash
kubectl create -f 2.pod.yaml

8.小实验 将当前 Configmap 变成我们的文件去使用
创建 3.pod.yaml
bash
apiVersion: v1
kind: Pod
metadata:
name: cm-volume-pod
spec:
containers:
- name: myapp-container
image: wangyanglinux/myapp:v1.0
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: literal-config
restartPolicy: Never
创建一个卷 卷名 叫 config-volume 挂载到当前容器的 /etc/config
bash
kubectl create -f 3.pod.yaml
进入容器内部查看
bash
kubectl exec -it cm-volume-pod -- /bin/bash


为什么它是蓝色的呢
他不是文件 而是链接
牵扯到 热更新
1.什么是热更新呢
我挂载以后后续我的原文件发送变化 ,我都会把帮你把所有的 现在老版本的给替换掉 这就是为什么要做链接的原因
当我第一次注入的时候 这是原文件 我做一个链接 链接到你的文件上了 如果我要去进行热更新了 换了一个内容 那我注入到第二个文件里 再把第一个链接关系清除 再把第二个文件链接到这个文件名上 你依然用的是这个文件名 但是很显然它的背后发生了变化 而不会在你使用的时候影响你 这就是为什么要做链接的原因
2.创建 nginx 默认 default.conf文件
bash
server {
listen 80 default_server;
server_name example.com www.example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
3.将default.conf 配置文件转化为 configmap对象
bash
kubectl create cm default-nginx --from-file=default.conf

4.将 configmap对象 输出为 yaml形式
bash
kubectl get cm default-nginx -o yaml

5.创建一个deployment 控制器
bash
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hotupdate-deploy
name: hotupdate-deploy
spec:
replicas: 5
selector:
matchLabels:
app: hotupdate-deploy
template:
metadata:
labels:
app: hotupdate-deploy
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d/
volumes:
- name: config-volume
configMap:
name: default-nginx
bash
kubectl apply -f deployment.yaml
6.进入一个pod里
bash
kubectl exec -it pod名 -- /bin/bash
循环查看 default.conf
bash
while true; do cat default.conf;sleep 2s; done
7.开启另一个终端修改configmap对象里的 default.conf
bash
kubectl edit cm default-nginx

改成8080
esc wq 保存退出

bash
kubectl get cm default-nginx -o yaml


8.回到之前那个终端

发现配置文件已经改变了
kubernetes会根据服务器的压力自己去调控注入的阶段 什么时候注入第一个 我们会有序的执行 基本会在一两分钟内完成大部分的替换 是没有任何问题的 那从这里我们可以看到这就是热更新的一种标学
所以在后面我们部署服务的时候 我们都建议 大家把 可能会后期修改的配置文件 抽象在 configmap对象里 然后在挂载回我们pod内部 这样做的好处就是 一旦后续我们需要修改的时候 我不需要重新封装镜像 我不需要去重新写控制器 我只需要通过edit 等方式 修改configmap 对象本身就可以修改所有的配置文件
9.还有一个问题 文件内部发生变化了 但是nginx 没有读取变化的配置

默认能够访问到80端口
nginx不支持热更新 配置文件
比如有 traefik web 服务器 支持监听配置文件 热更新 根本不需要重启 ,你改配置文件改完以后就生效了 就这么简单 所以说不是这个机制不好用 而是我们现在内部封装的这个nginx 有点太老了不支持我们所谓的热更新 或者监控文件变化自动趋向到新版
官方为了解决这个问题推出了 改变pod annotations的方式 让他强制滚动更新

patch命令
bash
kubectl patch deployment hotupdate-deploy --patch '{"spec":{"template":{"metadata":{"annotations":{"version/config":"666666666"}}}}}'
因为完全可以放入脚本里去执行 ,不想我们的edit我们是一种交互的方式

edit命令修改
bash
kubectl edit deployment hotupdate-deploy
修改
esc wq保存退出

滚动更新中
在annotations下,随便打出任意字符的键值对都可以触发滚动更新,比如helloworld:"12345"一样可以触发,原来应该是,只要打的补丁能使资源清单发生变化,都能触发更新
这里再插入一个小知识点
因为镜像加载 默认 是 always 就是如果你的镜像 是 latest 默认就回去远程拉取镜像 然后在启动
你可以把当前镜像下载策略改成如果有就不下载
提醒
使用该configmap挂载的env环境变量的方式 ,那么修改configmap原对象 是环境变量并不会发生改变
使用该configmap 挂载的Volume 中 的数据需要一段时间 (实测大概10秒) 才能同步更新


然后就改不了了 而且是不可逆的
要想再改回去只能把configmap 这个对象删除