Kubernetes ConfigMap热更新测试 – 探究ConfigMap的创建和更新流程

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: ConfigMap热更新测试 ConfigMap是用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在etcd中,下文主要是探究 ConfigMap 的创建和更新流程,以及对 ConfigMap 更新后容器内挂载的内容是否同步更新的测试。

ConfigMap热更新测试

ConfigMap是用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在etcd中,下文主要是探究 ConfigMap 的创建和更新流程,以及对 ConfigMap 更新后容器内挂载的内容是否同步更新的测试。

测试示例


假设我们在 default namespace 下有一个名为 nginx-config 的 ConfigMap,可以使用 kubectl命令来获取:

$ kubectl get configmap nginx-config
NAME DATA AGE
nginx-config 1 99d

获取该ConfigMap的内容。

kubectl get configmap nginx-config -o yaml
apiVersion: v1
data:
 nginx.conf: |-
 worker_processes 1;

 events { worker_connections 1024; }

 http {
 sendfile on;

 server {
 listen 80; # a test endpoint that returns http 200s
 location / {
 proxy_pass http://httpstat.us/200;
 proxy_set_header X-Real-IP $remote_addr; } }

 server {

 listen 80;
 server_name api.hello.world;

 location / {
 proxy_pass http://l5d.default.svc.cluster.local;
 proxy_set_header Host $host;
 proxy_set_header Connection "";
 proxy_http_version 1.1;

 more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample'; } }

 server {

 listen 80;
 server_name www.hello.world;

 location / { # allow 'employees' to perform dtab overrides if ($cookie_special_employee_cookie != "letmein") {
 more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample'; } # add a dtab override to get people to our beta, world-v2 set $xheader ""; if ($cookie_special_employee_cookie ~* "dogfood") { set $xheader "/host/world => /srv/world-v2;"; }

 proxy_set_header 'l5d-dtab' $xheader;


 proxy_pass http://l5d.default.svc.cluster.local;
 proxy_set_header Host $host;
 proxy_set_header Connection "";
 proxy_http_version 1.1; } } }
kind: ConfigMap
metadata:
 creationTimestamp: 2017-08-01T06:53:17Z
 name: nginx-config
 namespace: default
 resourceVersion: "14925806"
 selfLink: /api/v1/namespaces/default/configmaps/nginx-config
 uid: 18d70527-7686-11e7-bfbd-8af1e3a7c5bd

ConfigMap中的内容是存储到etcd中的,然后查询etcd:

ETCDCTL_API=3 etcdctl get /registry/configmaps/default/nginx-config
/registry/configmaps/default/nginx-config

注意使用 v3 版本的 etcdctl API,下面是输出结果:

k8s

v1	ConfigMap

T

nginx-configdefault"*$18d70527-7686-11e7-bfbd-8af1e3a7c5bd28B
 �ʀ����xz�


nginx.conf�
 worker_processes 1;

events { worker_connections 1024; }

http {
 sendfile on;

 server {
 listen 80;

 # a test endpoint that returns http 200s
 location / {
 proxy_pass http://httpstat.us/200;
 proxy_set_header X-Real-IP $remote_addr;
 }
 }

 server {

 listen 80;
 server_name api.hello.world;

 location / {
 proxy_pass http://l5d.default.svc.cluster.local;
 proxy_set_header Host $host;
 proxy_set_header Connection "";
 proxy_http_version 1.1;

 more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample';
 }
 }

 server {

 listen 80;
 server_name www.hello.world;

 location / {


 # allow 'employees' to perform dtab overrides
 if ($cookie_special_employee_cookie != "letmein") {
 more_clear_input_headers 'l5d-ctx-*' 'l5d-dtab' 'l5d-sample';
 }

 # add a dtab override to get people to our beta, world-v2
 set $xheader "";

 if ($cookie_special_employee_cookie ~* "dogfood") {
 set $xheader "/host/world => /srv/world-v2;";
 }

 proxy_set_header 'l5d-dtab' $xheader;


 proxy_pass http://l5d.default.svc.cluster.local;
 proxy_set_header Host $host;
 proxy_set_header Connection "";
 proxy_http_version 1.1;
 }
 }
}"

输出中在 nginx.conf 配置文件的基础中增加了文件头内容,是kubernetes增加的。

代码

ConfigMap 结构体的定义:

// ConfigMap holds configuration data for pods to consume.
type ConfigMap struct {
	metav1.TypeMeta `json:",inline"` // Standard object's metadata. // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata // +optional
	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Data contains the configuration data. // Each key must be a valid DNS_SUBDOMAIN with an optional leading dot. // +optional Data map[string]string `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"` }

在 staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go 中ConfigMap 的接口定义:

// ConfigMapInterface has methods to work with ConfigMap resources.
type ConfigMapInterface interface { Create(*v1.ConfigMap) (*v1.ConfigMap, error) Update(*v1.ConfigMap) (*v1.ConfigMap, error) Delete(name string, options *meta_v1.DeleteOptions) error
	DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
	Get(name string, options meta_v1.GetOptions) (*v1.ConfigMap, error) List(opts meta_v1.ListOptions) (*v1.ConfigMapList, error) Watch(opts meta_v1.ListOptions) (watch.Interface, error) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConfigMap, err error) ConfigMapExpansion }

在 staging/src/k8s.io/client-go/kubernetes/typed/core/v1/configmap.go 中创建 ConfigMap 的方法如下:

// Create takes the representation of a configMap and creates it. Returns the server's representation of the configMap, and an error, if there is any.
func (c *configMaps) Create(configMap *v1.ConfigMap) (result *v1.ConfigMap, err error) {
	result = &v1.ConfigMap{}
	err = c.client.Post(). Namespace(c.ns). Resource("configmaps"). Body(configMap). Do(). Into(result) return }

通过 RESTful 请求在 etcd 中存储 ConfigMap 的配置,该方法中设置了资源对象的 namespace 和 HTTP 请求中的 body,执行后将请求结果保存到 result 中返回给调用者。

注意 Body 的结构

// Body makes the request use obj as the body. Optional. // If obj is a string, try to read a file of that name. // If obj is a []byte, send it directly. // If obj is an io.Reader, use it directly. // If obj is a runtime.Object, marshal it correctly, and set Content-Type header. // If obj is a runtime.Object and nil, do nothing. // Otherwise, set an error. 

创建 ConfigMap RESTful 请求中的的 Body 中包含 ObjectMeta 和 namespace。

HTTP 请求中的结构体:

// Request allows for building up a request to a server in a chained fashion. // Any errors are stored until the end of your call, so you only have to // check once.
type Request struct { // required
	client HTTPClient
	verb string

	baseURL *url.URL
	content ContentConfig
	serializers Serializers // generic components accessible via method setters
	pathPrefix string
	subpath string params url.Values
	headers http.Header // structural elements of the request that are part of the Kubernetes API conventions namespace string
	namespaceSet bool
	resource string
	resourceName string
	subresource string
	timeout time.Duration // output
	err error
	body io.Reader // This is only used for per-request timeouts, deadlines, and cancellations.
	ctx context.Context

	backoffMgr BackoffManager
	throttle flowcontrol.RateLimiter }

测试

分别测试使用 ConfigMap 挂载 Env 和 Volume 的情况。

更新使用ConfigMap挂载的Env

使用下面的配置创建 nginx 容器测试更新 ConfigMap 后容器内的环境变量是否也跟着更新。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: my-nginx
spec:
 replicas: 1 template:
 metadata:
 labels:
 run: my-nginx
 spec:
 containers: - name: my-nginx
 image: sz-pg-oam-docker-hub-001.tendcloud.com/library/nginx:1.9
 ports: - containerPort: 80
 envFrom: - configMapRef:
 name: env-config
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: env-config
 namespace: default
data:
 log_level: INFO

获取环境变量的值

$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` env|grep log_level
log_level=INFO

修改 ConfigMap

$ kubectl edit configmap env-config

修改 log_level 的值为 DEBUG。

再次查看环境变量的值。

$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` env|grep log_level
log_level=INFO

实践证明修改 ConfigMap 无法更新容器中已注入的环境变量信息。

更新使用ConfigMap挂载的Volume

使用下面的配置创建 nginx 容器测试更新 ConfigMap 后容器内挂载的文件是否也跟着更新。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: my-nginx
spec:
 replicas: 1 template:
 metadata:
 labels:
 run: my-nginx
 spec:
 containers: - name: my-nginx
 image: sz-pg-oam-docker-hub-001.tendcloud.com/library/nginx:1.9
 ports: - containerPort: 80
 volumeMounts: - name: config-volume
 mountPath: /etc/config
 volumes: - name: config-volume
 configMap:
 name: special-config
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: special-config
 namespace: default
data:
 log_level: INFO
$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /tmp/log_level
INFO

修改 ConfigMap

$ kubectl edit configmap special-config

修改 log_level 的值为 DEBUG。

等待大概10秒钟时间,再次查看环境变量的值。

$ kubectl exec `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` cat /tmp/log_level
DEBUG

我们可以看到使用 ConfigMap 方式挂载的 Volume 的文件中的内容已经变成了 DEBUG。

总结

更新 ConfigMap 后:

  • 使用该 ConfigMap 挂载的 Env 不会同步更新
  • 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新

ENV 是在容器启动的时候注入的,启动之后 kubernetes 就不会再改变环境变量的值,且同一个 namespace 中的 pod 的环境变量是不断累加的,参考 Kubernetes中的服务发现与docker容器间的环境变量传递源码探究。为了更新容器中使用 ConfigMap 挂载的配置,可以通过滚动更新 pod 的方式来强制重新挂载 ConfigMap,也可以在更新了 ConfigMap 后,先将副本数设置为 0,然后再扩容。

本文转自kubernetes中文社区-Kubernetes ConfigMap热更新测试 – 探究ConfigMap的创建和更新流程

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
jenkins 测试技术 应用服务中间件
【专业测试技能】全流程掌握:部署测试环境的策略与实践
本文分享了关于部署测试环境的策略与实践。文章讨论了部署测试环境的全过程,包括服务如MySQL、Redis、Zookeeper等的部署,以及解决服务间的依赖和兼容问题。文中还介绍了使用Jenkins、Docker等工具进行部署的方法,并通过实战案例讲解了如何创建和管理Jenkins Job、配置代理服务器Nginx、进行前后端服务的访问和优化。最后,作者强调了提问的重要性,并鼓励大家通过互联网解决遇到的问题。
88 2
【专业测试技能】全流程掌握:部署测试环境的策略与实践
|
1月前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
461 3
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
1月前
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
1459 1
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
45 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
1月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
350 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
98 0
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
53 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
173 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
1月前
|
机器学习/深度学习 算法 PyTorch
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-7.0版本进行目标检测的完整流程,包括算法介绍、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。YOLOv5以其高精度、快速度和模型小尺寸在计算机视觉领域受到广泛应用。
503 0
目标检测实战(五): 使用YOLOv5-7.0版本对图像进行目标检测完整版(从自定义数据集到测试验证的完整流程)
|
1月前
|
Ubuntu API Python
Chat-TTS chat-tts-ui 实机部署上手测试!Ubuntu服务器实机 2070Super*2 8GB部署全流程
Chat-TTS chat-tts-ui 实机部署上手测试!Ubuntu服务器实机 2070Super*2 8GB部署全流程
68 1