feat: 为helm chart添加WebUI的辅助容器,用于反向同步配置到ConfigMap

This commit is contained in:
zhangxinhui02
2025-11-21 01:38:50 +08:00
parent 14514ba837
commit 4f6e159000
13 changed files with 232 additions and 94 deletions

View File

@@ -0,0 +1,10 @@
# 此镜像用于辅助麦麦的WebUI更新配置文件随core容器持续运行
FROM python:3.13-slim
WORKDIR /MaiMBot
COPY . /MaiMBot
RUN pip3 install --no-cache-dir -r requirements.txt
ENTRYPOINT ["python3", "core-webui-cm-sync.py"]

View File

@@ -0,0 +1,89 @@
#!/bin/python3
# 这个程序的作用是辅助麦麦的WebUI更新配置文件随core容器持续运行。
# 麦麦的配置文件存储于ConfigMap中挂载进core容器后属于只读文件无法直接修改。
# 此程序将core容器内的配置文件替换为可读写的中间层临时文件。启动时将实际配置文件写入并在后台持续检测文件变化实时同步到k8s apiServer反向修改ConfigMap。
# 工作目录:/MaiMBot/webui-cm-sync
import os
import time
from datetime import datetime
from kubernetes import client, config
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
work_dir = '/MaiMBot/webui-cm-sync'
os.chdir(work_dir)
config.load_incluster_config()
core_api = client.CoreV1Api()
with open("/var/run/secrets/kubernetes.io/serviceaccount/namespace", "r") as f:
namespace = f.read().strip()
release_name = os.getenv("RELEASE_NAME")
configmap_name = f'{release_name}-maibot-core'
# 过滤列表,只监控指定文件
target_files = {
os.path.abspath("model_config.toml"): "model_config.toml",
os.path.abspath("bot_config.toml"): "bot_config.toml"
}
def get_configmap():
"""获取core的ConfigMap内容"""
cm = core_api.read_namespaced_config_map(name=configmap_name, namespace=namespace)
return cm.data
def set_configmap(configmap_data: dict[str, str]):
"""设置core的ConfigMap内容"""
core_api.patch_namespaced_config_map(configmap_name, namespace, {'data': configmap_data})
class ConfigObserverHandler(FileSystemEventHandler):
"""配置文件变化的事件处理器"""
def on_modified(self, event):
if os.path.abspath(event.src_path) in target_files:
print(
f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] File `{event.src_path}` was modified. Start to sync...')
with open(event.src_path, "r", encoding="utf-8") as _f:
current_data = _f.read()
new_cm = {
target_files[os.path.abspath("model_config.toml")]: current_data
}
try:
set_configmap(new_cm)
except client.exceptions.ApiException as _e:
print(f'\tError while setting configmap:\n'
f'\t\tStatus Code: {_e.status}\n'
f'\t\tReason: {_e.reason}')
if __name__ == '__main__':
# 初始化配置文件
print(f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] Initializing config files...')
try:
__initial_model_config = get_configmap()['model_config.toml']
__initial_bot_config = get_configmap()['bot_config.toml']
except client.exceptions.ApiException as e:
print(f'\tError while getting configmap:\n'
f'\t\tStatus Code: {e.status}\n'
f'\t\tReason: {e.reason}')
exit(1)
with open('model_config.toml', 'w') as f:
f.write(__initial_model_config)
with open('bot_config.toml', 'w') as f:
f.write(__initial_bot_config)
with open('ready', 'w') as f:
f.write('true')
print(f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] Initializing done. Ready to sync.')
# 持续检测变化并同步
observer = Observer()
observer.schedule(ConfigObserverHandler(), '', recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()

View File

@@ -0,0 +1,3 @@
toml~=0.10.2
kubernetes~=34.1.0
watchdog~=6.0.0