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,一经查实,立即删除!

相关文章

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

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

【web】2、集成插件

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

matlab编辑稀疏单位方阵

创建 10001000 稀疏单位方阵,并查看稀疏模式。 (1) I speye(1000); spy(I)(2) 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开发环境配置杂记

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

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

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

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

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

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

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

忍法:声音克隆之术

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

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

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

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

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

目标检测常用涨点方法:注意力机制小结(空间注意力、通道注意力、CBAM等)

1.通道注意力 通道注意力(Channel Attention)是在通道维度上对输入数据进行学习,再对不同的通道分配相应的权重表示重要性,从而达到“分配注意力”的效果。SENet(Squeeze and Excitation networks) 是一个典型的使用通…

Swift宏的实现

上篇介绍了Swift宏的定义与生声明,本篇主要看看是Swift宏的具体实现。结合Swift中Codable协议,封装一个工具让类或者结构体自动实现Codable协议,并且添加一些协议中没有的功能。 关于Codable协议 Codable很好,但是有一些缺陷&…

yaklang window安装 vscode运行得到“hello world”

资源来源:旅程伊始:Yak 语言环境安装与搭建环境 | Yak Program Language 安装yak语言非常简单,管理员权限打开命令行运行以下命令: powershell (new-object System.Net.WebClient).DownloadFile(https://yaklang.oss-cn-beijing…

1085 PAT单位排行(测试点5)

solution 测试点5:总分是在每个学生加权后再取整,所以用来存学生分数的变量要用浮点型学校排序: 若成绩不同,则按成绩降序若成绩相同,人数不同,则按成绩升序若成绩和人数都相同,则按单位名升序…

理解GPT2:无监督学习的多任务语言模型

目录 一、背景与动机 二、卖点与创新 三、几个问题 四、具体是如何做的 1、更多、优质的数据,更大的模型 2、大数据量,大模型使得zero-shot成为可能 3、使用prompt做下游任务 五、一些资料 一、背景与动机 基于 Transformer 解码器的 GPT-1 证明…

NAS教程丨铁威马如何登录 SSH终端?

适用型号: 所有TNAS 型号 如您有特殊操作需要通过 SSH 终端登录 TNAS,请参照以下指引: (注意: 关于以下操作步骤中的"cd /"的指令,其作用是使当前 SSH/Telnet 连接的位置切换到根目录,以免造成对卷的占用.请不要遗漏它.) Windows…

数据分析的线上云端数据库搭建及Excel和Tableau连接

数据分析的线上云端数据库搭建及Excel和Tableau连接 SQL基础知识 线上SQL训练: SQlZOO: https://www.sqlzoo.net/wiki/SQL_Tutorial 牛客网SQL真题:https://www.nowcoder.com/ta/sql select,from,where, order by, limit, group by, having, substr(),…

【SpringBoot】SpringBoot使用mail实现登录邮箱验证

📝个人主页:哈__ 期待您的关注 目录 一、前期准备 1 开启邮箱服务 2 SpringBoot导入依赖 3 创建application.yml配置文件 4 创建数据库文件 5 配置redis服务 二、验证邮件发送功能 三、注册功能实现邮箱验证 1 创建User实体类 2 创建UserPa…

DEBOPIE框架:打造最好的ChatGPT交易机器人

本文介绍了如何利用 DEBOPIE 框架并基于 ChatGPT 创建高效交易机器人,并强调了在使用 AI 辅助交易时需要注意的限制以及操作步骤。原文: Build the Best ChatGPT Trading Bots with my “DEBOPIE” Framework 如今有大量文章介绍如何通过 ChatGPT 帮助决定如何以及在…