本文主要对kubesphere项目中的ks-installer模块进行分析,并提出改进思路。ks-installer是用于在k8s集群中部署kubesphere的程序。
查看ks-installer的dockerfile,发现使用了一个叫shell-operator的基础镜像
https://github.com/flant/shell-operator
shell-operator通过k8s的事件触发,调用对应的钩子脚本。脚本需要放在/hooks目录,也可以指定
https://github.com/flant/shell-operator/blob/main/HOOKS.md
shell-operator启动时会扫描目录,用--config
参数执行所有钩子,钩子需要输出自己运行的配置
ks-installer的钩子放在controller目录,build时拷贝到镜像的/hooks/kubesphere/目录。钩子有两个:
installRunner.py
监听clusterconfigurationschedule.sh
定时任务installRunner.py
主要是通过分析clusterconfiguration,然后调用对应的ancible playbook。主要流程:
python if len(sys.argv) > 1 and sys.argv[1] == "--config":
print(ks_hook)
else:
config.load_incluster_config()
api = client.CustomObjectsApi()
generate_new_cluster_configuration(api)
generateConfig(api)
# execute preInstall tasks
preInstallTasks()
resultState = getResultInfo()
resultInfo(resultState, api)
--config
输出的配置是:
yaml{
"onKubernetesEvent": [{
"name": "Monitor clusterconfiguration",
"kind": "ClusterConfiguration",
"event": [ "add", "update" ],
"objectName": "ks-installer",
"namespaceSelector": {
"matchNames": ["kubesphere-system"]
},
"jqFilter": ".spec",
"allowFailure": false
}]
}
也就是说,当kubesphere-system的名为ks-installer的clusterconfiguration有add或update事件时,这个脚本会被调用。
前面几个流程都是在更新和生成配置。
generate_new_cluster_configuration
会读取集群的clusterconfiguration,对里面的字段做预处理,并写回clusterconfiguration
generateConfig
再次读取clusterconfiguration,保存到generateConfig
中,供后面getComponentLists
使用
preInstallTasks
主要是执行几个每次都要运行的步骤(文件在playbooks目录):
preinstall.yaml metrics_server.yaml common.yaml ks-core.yaml traefik.yaml
getResultInfo
设计成可插拔的模块化结构,每次只运行enabled的模块。通过调用getComponentLists
获取enabled和disabled的模块,代码里默认写了三个(最新版是四个):
multicluster openpitrix network
没有disabled的。其它的从clusterconfiguration里面把enabled的加上。
然后generateTaskLists
把这些模块的任务生成一个列表,调用ansible执行对应的playbook。每个task执行结束,都会在文件里记录执行结果。
最后一个函数ResultInfo
,会先执行ks-config
和result-info
两个playbook,然后把运行结果写回clusterconfiguration的status.
ks-installer的playbook放在playbooks
目录,以monitoring.yaml
为例,内容是:
yaml---
- hosts: localhost
gather_facts: false
roles:
- kubesphere-defaults
- ks-monitor
可以看到引用了两个role,这两个role在roles
目录可以看到对应的目录。每个role的目录里面可能会有很多子目录,子目录里面的main.yaml
会被作为入口解析执行。比如ks-monitor
,有两个子目录有main.yaml
:
ks-monitor/ ~ defaults/ main.yaml ~ tasks/ main.yaml
defaults主要是配置一些默认变量,tasks是主要执行安装任务的。
在clusterconfiguration的monitoring为true的情况下,将etcd的monitoring项从false改成true,etcd的servicemonitor正常安装,但是prometheus容器没有挂载etcd的secret
查看prometheus-stack.yaml
,看到只有clusterconfiguration的status中monitoring为false或没有值时,才会调用prometheus.yaml
,也就是说如果之前已经将monitoring
设置为true
了,那prommetheus的yaml是不会更新的。
yaml- import_tasks: prometheus.yaml
when:
- "status.monitoring is not defined or status.monitoring.status is not defined or status.monitoring.status != 'enabled'"
查看etcd.yaml
,当etcd.monitoring
为true时,安装prometheus/etcd
目录内的yaml,也就是说没有更新prometheus的deployment
yaml---
- name: Monitoring | Installing etcd monitoring
shell: "{{ bin_dir }}/kubectl apply -f {{ kubesphere_dir }}/prometheus/{{ item }}"
loop:
- "etcd"
register: import
failed_when: "import.stderr and 'Warning' not in import.stderr and 'spec.clusterIP' not in import.stderr"
until: import is succeeded
retries: 5
delay: 3
when:
- etcd.monitoring is defined
- etcd.monitoring == true
解决方法:在etcd.yaml
里,loop加上prometheus
疑问:为何prometheus.yaml
里loop里有两个prometheus
将metrics-server,common和ks-core从preInstallTasks中去掉,只保留preinstall
ks-core在配置文件中没有体现,通过检查是否有上次运行的配置,来决定是否运行ks-core
去掉readyToEnableLists默认的三个模块
每次运行生成新配置后,保存到一个last-applied-configs.yaml文件中;下次运行时,对比新配置和之前的配置,只运行配置有变化的模块
如果模块的enabled字段从true变成false,加入到readyToDisableList中,并返回
每个模块对应的uninstall模块,在generateTaskLists中调用
本文作者:renbear
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC 2.0 许可协议。转载请注明出处!