emptyDir + initContainer实现ConfigMap的动态更新(K8s相关)

1. 絮絮叨叨

  • K8s部署服务时,一般都需要使用ConfigMap定义一些配置文件
  • 例如,部署分布式SQL引擎Presto,会在ConfigMap中定义coordinator、worker所需的配置文件
  • node.properties为例,node.environmentnode.data-dir的值将由Helm的values.yaml进行渲染
    data:node.properties: |# node.id由系统使用uuid自动赋值node.environment={{ .Values.environment }}node.data-dir={{ .Values.server.data_dir }}
    
  • 工作过程中,笔者接到了一个新的需求:node.id需要与podName保持一致,而非毫无规律的UUID
  • 如果是毫无规律的UUID,将nodeId与pod映射需要一个复杂的过程,笔者的做法一般是:
    1. 通过Presto的worker lists实现nodeId与pod IP的映射在这里插入图片描述
    2. 通过kubectl -n ${namespace} get pod -owide | grep ${IP}实现pod IP与pod的映射,从而最终实现nodeId与pod的映射(图片可能上下文不一致,忽略即可)在这里插入图片描述
  • 所谓的podName其实就是K8s中的metadata.name,也是kubectl -n ${namespace} get pod展示的NAME在这里插入图片描述

2. 一些前期调研

2.1 初始想法

拿到这个需求后,自己的想法很简单,以StatefulSet方式部署的coordinator为例:

  1. 更新node.properties的定义

    data:node.properties: |node.id=NODE_IDnode.environment={{ .Values.environment }}node.data-dir={{ .Values.server.data_dir }}
    
  2. 定义 POD_NAME env,其值为metadata.name

    env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name
    
  3. 通过container中的command,获取env、使用sed命令更新node.properties中的NODE_ID关键字

    command: [ 'sh', '-c', 'sed -i "s/NODE_ID/$POD_NAME/g" /opt/presto/etc/node.properties' ]
    
  • 存在的问题: 服务部署失败,提示ConfigMap所在卷是read-only的,read-only file system(当时触发这个问题的实现方案可能与描述存在差异,反正类似的方法行不通)

2.2 ConfigMap能否智能地动态更新? —— No

  • 由于当时对Helm values.yaml如何实现ConfigMap的更新机制不了解,笔者期望ConfigMap能智能加载容器的环境变量,自己实现更新
    • 保持上面的env定义不变,将node.properties的定义修改成如下样式
      data:node.properties: |node.id=$(POD_NAME)node.environment={{ .Values.environment }}node.data-dir={{ .Values.server.data_dir }}
      
    • 期望ConfigMap像Shell脚本一样,动态加载env
  • 笔者试验后发现,node.properties中node.id=$(POD_NAME)原封不动、未被修改

2.3 学习官方文档 —— 未解

  • 阅读K8s官方文档,发现有关ConfigMap的文档,主要是描述如何定义、使用ConfigMap,并未提及如何动态更新ConfigMap
    • 《ConfigMaps》:如何定义ConfigMap,两种使用方式:
      • ConfigMap映射为文件,一般都是作为etc/config/目录下的配置文件
      • 基于ConfigMap定义环境变量env,ConfigMap中的key-value及时一个环境变量
    • 《Configure a Pod to Use a ConfigMap》中的使用描述更加详细

3. 终极解决方案:emptyDir + initContainer

  • 通过read-only file system这个错误薪资,笔者找到了类似问题的交流帖:
    • Error config Map volume mount read-only file system error
    • k8s 使用 statefulset 如何在 pod 内获取序号并设置到环境变量里
  • 使用emptyDir + initContainer,实现了ConfigMap的动态更新

3.1 具体实现方案

  1. 定义volumes
    volumes:# 加载原始的ConfigMap- name: config-template-volumeconfigMap:name: onequery-coordinator# 定义一个emtyDir- name: config-volumeemptyDir: {}
    
  2. 创建initContainer,在initContainer中实现nodeId的动态更新
    initContainers:- name: config-templateimage: "{{ .Values.Images.onequery }}"# 将ConfigMap拷贝到emptyDir映射的路径,并使用sed命令、基于环境变量动态修改NODE_ID为podNamecommand: [ 'sh', '-c', 'cp /etc/config-templates/* /opt/onequery/etc && (cat /etc/config-templates/node.properties | sed "s/NODE_ID/$POD_NAME/" > /opt/onequery/etc/node.properties)' ]volumeMounts:# 定义volumeMounts,分别将ConfigMap、emptyDir映射到container的指定路径- name: config-template-volumemountPath: /etc/config-templates- name: config-volumemountPath: /opt/onequery/etcenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name
    
  3. coordinator对应的container中,定义volumeMount、与initContainer保持一致(也可以不一致)。启动后的coordinator container,可以访问写入emptyDir的、动态更新后的node.properties文件
    volumeMounts:- name: config-volumemountPath: /opt/onequery/etc
    

4. 后记

4.1 关于emptyDir卷

  • K8s官方文档对emptyDir卷的描述可知:emptyDir的生命周期与pod一致,特别适合在pod的不同容器中共享文件
  • 上面的实现方案中,即使initContainer、coordinator container中emptyDir卷的挂载路径不同,也可以共同读写emptyDir中的文件

4.2 volumes vs volumeMounts

  • volumes(存储卷):是K8s中的一种资源,用于将持久化存储与Pod绑定,与Pod具有相同的生命周期
  • volumeMounts(挂载点):
    • 在容器描述符中定义volumeMount,可以将 volume 挂载到容器中的指定路径
    • 在容器中读写上述路径下的文件,实际就是读写持久化存储中相应路径下的文件
  • 举个例子,阐述二者之间的关系:
    • volumes定义如下,将log-path与宿主机的/data00/basic_log/svc_logs/presto目录绑定
      volumes:- name: log-pathhostPath:path: /data00/basic_log/svc_logs/presto/logtype: DirectoryOrCreate # 支持动态创建目录
      
    • 在container中定义volumeMount,使得容器中的/opt/data/var/log路径对应
      volumeMounts:- name: log-path # volume namemountPath: /opt/data/var/log# 将基于环境变量POD_NAME、在宿主机磁盘上动态创建子目录,最终coordinator-0在宿主机上的路径为/data00/basic_log/svc_logs/presto/log/coordinator/coordinator-0subPathExpr: coordinator/$(POD_NAME) 
      
    • coordinator运行起来后,会在/opt/data/var/log下生成launcher.log。相应地,其所在宿主机的/data00/basic_log/svc_logs/presto/log/coordinator/coordinator-0目录下将出现launcher.log文件
    • 在容器中对launcher.log的读写操作,实际就是在读写宿主机中对应目录的launcher.log

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/38090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解析三大跨平台开发框架:Flutter、React Native 和 uniapp

深入解析三大跨平台开发框架:Flutter、React Native 和 uniapp 在移动开发中,跨平台开发框架已经成为开发者的首选工具。本篇将深入解析三大主流跨平台开发框架:Flutter、React Native 和 uniapp。下面将详细探讨它们的原理、优势和劣势。 …

接口设计原则与最佳实践指南

接口设计原则与最佳实践指南 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 什么是接口? 在软件开发中,接口是定义类或模块之间通…

C++ 嵌套和递归使用模板类

在C11之前&#xff0c;嵌套使用模板类的时候&#xff0c;> >之间要加空格。 #include <iostream> // 包含头文件。 using namespace std; // 指定缺省的命名空间。template <class DataType> class Stack // 栈类 { private:DataType* …

scp和rsync

全量和增量 全量就是把所有文件一股脑的全部传输过去&#xff0c;也不管他一不一样&#xff0c;比如scp 增量就是在传输前先对比一下两边的文件一不一样&#xff0c;有一样的部分&#xff0c;哪一样的部分就不传输&#xff0c;只传输不一样的部分&#xff0c;和新增的部分 &…

android 通过gradle去除aar的重复资源图片

背景&#xff1a;项目中引入了aar包&#xff0c;结果导致资源出问题了&#xff0c;于是需要对下面aar包进行重复资源去除操作 操作具体如下&#xff1a; 目录&#xff1a;app/build.gradle 末尾配置 apply from: "${project.rootDir}/scripts/excludewidgetAar.gradle&qu…

【web】2、集成插件

1、element-plus 官网地址:设计 | Element Plus 安装 plus 及 icon 图标库 1.1 官网提供plus安装方法&#xff1a; 1.2 官网提供 icon 安装方法 1.3 安装 pnpm install element-plus element-plus/icons-vue main.ts全局安装element-plus,element-plus默认支持语言英语设…

《战神4》开发团队繁忙的一天

早晨&#xff1a;准备与规划 8:00 AM - 团队到达 《战神4》开发团队的成员们陆续到达位于加利福尼亚圣莫尼卡的Santa Monica Studio。每个人先整理自己的工作站&#xff0c;准备迎接一天的工作。大家彼此问候&#xff0c;分享昨天的灵感和想法。 8:30 AM - 早会 整个开发团队…

【TensorFlow深度学习】“自我监督学习框架解析:生成模型、对比学习与混合方法“

"自我监督学习框架解析&#xff1a;生成模型、对比学习与混合方法" 在人工智能的快速迭代中&#xff0c;自我监督学习&#xff08;Self-supervised Learning, SSL&#xff09;作为一股新兴力量&#xff0c;正逐步改变着深度学习的面貌。它通过巧妙利用数据内部结构作…

matlab编辑稀疏单位方阵

创建 10001000 稀疏单位方阵&#xff0c;并查看稀疏模式。 &#xff08;1&#xff09; I speye(1000); spy(I)&#xff08;2&#xff09; S speye(400,800); spy(S)此命令等同于 speye([400 800])。

Nginx中封装的数据结构

Nginx中封装的数据结构 Nginx中封装的数据结构整型ngx_str_t【字符串】ngx_list_t【链表】ngx_table_elt_t【key/value】ngx_buf_tngx_chain_t Nginx中封装的数据结构 整型 typedef intptr_t ngx_int_t; typedef uintptr_t ngx_uint_t;ngx_str_t【字符串】 typ…

qt6开发环境配置杂记

很多同学不重视环境配置问题&#xff0c;这是工程问题&#xff0c;实际工作中&#xff0c;如果不真正搞懂环境配置&#xff0c;后期可能会遇到各种坑。 QT是一套开发框架&#xff0c;最终要翻译成c去执行。总体而言&#xff0c;就是下面三张框图&#xff1a; &#xff08;工程…

Spring底层原理之bean的加载方式一 用XML方式声明bean 自定义bean及加载第三方bean 2024详解

目录 用XML方式声明bean 首先我们创建一个空的java工程 我们要导入一个spring的依赖 注意在maven工程里瞅一眼 我们创建一个业务层接口 还有四个实现类 我们最初的spingboot生命bean的方式是通过xml声明 我们在resources文件夹下创建一个配置文件 我们书写代码 首先初…

AI Agent:技术原理与未来趋势

在人工智能的快速发展中&#xff0c;AI Agent作为一项创新技术&#xff0c;正逐渐成为研究和应用的热点。AI Agent不仅仅是执行命令的程序&#xff0c;它们能够感知环境、做出决策并采取行动&#xff0c;展现出类似人类的群体协作能力。本文将探讨AI Agent的技术原理、开源框架…

使用vite官网和vue3官网分别都可以创建vue3项目

问: npm init vitelatest 和 npm create vuelatest创建的vue3项目有什么区别? 回答: npm init vitelatest 和 npm create vuelatest 分别是使用 Vite 和 Vue CLI 工具创建 Vue 项目的两种方式&#xff0c;它们之间有几个主要区别&#xff1a; 1. **构建工具&#xff1a;** …

【PYG】定义数据集报错AttributeError: can‘t set attribute

当你遇到 AttributeError: cant set attribute 错误时&#xff0c;通常是因为你试图在一个类的实例上设置一个属性&#xff0c;但该类不允许直接设置属性。在Python中&#xff0c;某些类&#xff0c;特别是那些继承自某些基类&#xff08;比如 torch.utils.data.Dataset&#x…

忍法:声音克隆之术

前言&#xff1a; 最近因为一直在给肚子里面的宝宝做故事胎教&#xff0c;每天&#xff08;其实是看自己心情抽空讲下故事&#xff09;都要给宝宝讲故事&#xff0c;心想反正宝宝也看不见我&#xff0c;只听我的声音&#xff0c;干脆偷个懒&#xff0c;克隆自己的声音&#xf…

Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程

方法一&#xff1a;PHP_diseval_extension禁用 Linux CentOS 禁用php的eval函数详细图文教程_centos php 禁用 eval-CSDN博客 这个方法make报错&#xff0c;懒得费时间处理&#xff0c;直接用第二种 方法二&#xff1a;suhosin禁用 不支持PHP8&#xff0c;官方只支持PHP7以下…

【电源专题】为什么带电量计芯片的电池MOS保护要放在高侧

在实际的电量计电池开发中,发现一个很奇怪的现象。传统电池保护IC往往都是将充电保护和放电保护的两个MOS管放在低侧的。如下所示是文章:【电源专题】读一读单节锂电池保护IC规格书 可以看到M1和M2两个MOS管是放在PB-(也就是电池的负端),我们叫做低端。 而BQ28Z610电…

Python爬虫背后技术详解

在互联网时代&#xff0c;信息量巨大&#xff0c;如何高效地获取和处理这些信息变得尤为重要。Python 爬虫作为一种自动化获取网页信息的技术&#xff0c;已成为许多程序员和数据分析师必备技能之一。本文将深入探讨 Python 爬虫背后的技术原理&#xff0c;并结合实际代码示例来…

股票回购(Stock repurchases)和派发股息(Dividend distributions)有什么相同点和不同点?

中文版 股票回购和派发股息是公司将利润返还给股东的两种主要方式&#xff0c;二者各有优缺点。下面是它们的相同之处和不同之处&#xff0c;并通过具体公司数据进行说明。 相同之处 股东回报&#xff1a;股票回购和派发股息都是公司向股东返还利润的一种方式。股东从中受益…