轉自:https://www.ustack.com/blog/ceph%e9%85%8d%e7%bd%ae%e9%a1%b9%e5%8a%a8%e6%80%81%e5%8f%98%e6%9b%b4%e6%9c%ba%e5%88%b6%e6%b5%85%e6%9e%90/
OpenStack做一個log級別的變更就得重啟,很耗費時間。本篇主要是向大家介紹一下ceph tell是如何便捷地實現log級別的變更的,並展開來介紹Ceph是如何動態管理配置項的。Ceph tell命令tell命令能夠讓你在一台主機上操作所有的osd,會對運維工作帶來很大的便利,首先來看一下ceph tell都能做哪些事情呢?
我們再來看看tell是怎么做到的,這里我們將主要精力放在osd的injectargs上面(因為能夠動態改變配置),其它的都可以,以此類推。簡單的說在osd啟動的時候會初始化一些工作隊列,也就是wq,而其中一個就是command_wq,該隊列的處理函數主要是調用do_command函數,在該函數中對injectargs的處理是調用md_confit_t 的apply_changes,最終是調用注冊的觀察者,來對改變的配置做出響應。可以從以下三個方面展開來分析:
1、配置存放在哪里?
在osd啟動的時候會初始化兩個全局的指針g_ceph_context和g_conf。g_ceph_context是CephContext *的類型,g_conf是md_config_t*的類型。它們的關系是g_conf = g_ceph_context->_conf 。在初始化osd之前就會將g_ceph_context和g_conf給准備好,g_conf會從配置文件,環境變量,和命令行參數三個地方來初始化全局配置。這樣為后續的操作做好准備。比如data目錄,journal目錄,osd的網絡都需要從g_conf里讀取。所以在osd init之前必須得把g_conf給准備好。
g_conf里配置項的內容是從配置文件解析得到的,首先會檢查有沒有設置環境變量$CEPH_CONF,然后再依次從$data_dir/config, /etc/ceph/$cluster.conf, ~/.ceph/$cluster.conf, $cluster.conf”;來讀取配置,如果在前一個位置有配置,就會讀取並解析,不會再去后面讀取。所以不會出現前面的覆蓋后面的情況。
2、配置的更新是如何做到的?
首先每一個osd都繼承了md_config_obs_t類,md_config_obs_t 就是md_config_t的一個觀察者,其關注的對象可以通過get_tracked_conf_keys()這個虛函數來獲取到。OSD在pre_init的時候,將自己注冊到md_confit_t的觀察者map中,當md_confit_t apply_change的時候,會找到哪些觀察者對要更新的參數感興趣,然后就調用這些觀察者的handle_conf_change()。從而實現obs狀態的更新。具體到每一個obs,會根據不同的配置項調用相應的set方法,來完成配置項的更新。這里看一點代碼應該就更清楚了。
從上面可以看到如果inject的參數沒有觀察者對其感興趣,則你是沒有辦法改變的,而且會給你提示。但是conf確實發生了變化,只不過這個變化沒有生效而已。
這里總結tell的流程如下:
3、關於配置項
從conf_opts.h文件來看,配置項主要有兩類:一類是SUBSYSTEM的,一類是OPTION。
SUBSYSTEM主要定義了日志子系統寫日志的級別。OPTION則主要定義了特定配置項的類型和初始的值。當injectargs的時候可以通過–debug_${system}=int/int 來改變子系統日志的級別。
總結
本篇從tell 命令出發,詳解介紹了和osd相關的tell命令,然后深入到osd的配置管理中,講述了Ceph是如何通過injectargs來實現動態改變配置的。