在業務運維中,經常需要做系統環境配置,環境配置要在目前運作環境中生效,也要持久化依然重新開機生效。
通常,大家都會想到在<code>/etc/rc.local</code>中去添加業務自定義代碼,但是也會發現,有些配置重新開機無法生産生效。 而且rc.local中會出現大量的複雜的業務邏輯代碼。修改系統配置、啟動業務程序等邏輯都會存在這個檔案中,調用關系複雜,維護很痛苦。
一些case :
曾經有幸看到過一些業務中看到rc.local中看到這樣的代碼:
在業務的發展中,檔案中不斷地增加代碼。rc.local越來越臃腫且不可維護。
如何簡化配置管理,更優雅的方式去支援業務,就需要關注下主機開機啟動的細節,利用系統預留的接口達到目的。
有幾個常用的關注點:
linux 服務啟動方式
核心子產品 啟動方式
sysctl 配置生效
rc.local
主機啟動過程:
主機加電,從mbr開始引導系統
啟動核心
初始化系統配置
啟動服務
啟動使用者終端
本次主要的關注點在 3、4 流程。
一個機器上可以安裝多個核心。具體機器啟動中使用引導哪個核心,是在 <code>/boot/grub/grub.conf</code> 檔案中定義
比如一個機器grub檔案舉例
<code>default</code> 參數是選擇哪個核心作為預設啟動項
<code>timeout</code> 參數是指開機啟動時等待使用者選擇的時間
核心啟動可以帶多個參數,可以通過配置參數達到想要的啟動結果。
核心引導完成之後,就開始初始化系統配置。
這個功能的實作其實是調用 <code>/etc/rc.sysinit</code> 腳本完成。
這個過程包括
閱讀<code>rc.sysinit</code>的代碼, 關注<code>核心子產品的加載</code> 和 <code>sysctl配置</code>
關于核心子產品的加載
需要在<code>/etc/sysconfig/modules/</code> 建立<code>*.modules</code> 檔案,并且具有可執行權限。在開機啟動過程中,會自動的被執行。
關于sysctl配置
在 <code>/etc/rc.sysinit</code> 中有調用 <code>apply_sysctl</code>的函數。
在<code>/etc/init.d/functions</code> 腳本中有大量的被調用方法,其中
可以看到
使用 <code>sysctl -p /etc/sysctl.conf</code> 将預設的參數刷入系統
從 <code>/etc/sysctl.d/</code>目錄下讀取檔案,如果檔案是正常檔案,就執行<code>sysctl -p $file</code> 的方式加載配置檔案。
在系統參數配置完成之後,就可以啟動系統程序了。
linux有個啟動等級的概念。
在<code>/etc/inittab</code> 中有定義
總共有 <code>0-6</code> 7個啟動登記, 預設的啟動啟動登記是 <code>3</code>。每種啟動登記分别代表不同的啟動功能。
對于linux service,
<code>/etc/init.d/</code> 目錄下存放具體執行的執行的服務指令 ,
<code>chkconfig</code> 指令管理着linux service的在各個啟動等級下的是否啟動的配置。
系統通過 <code>$service start</code> <code>$service stop</code> <code>$service status</code>的方式調用服務。
如何實作的呢?
系統啟動的過程中, 通過執行 <code>/etc/rc.d/rc $runlevel</code> 的方式啟動程序
在<code>/etc/rc.d/rc</code> 檔案中。
可以看到:
首先,循環執行 <code>/etc/rc$runlevel.d/k*</code>的所有檔案都執行一遍 <code>$file stop</code>。
接着,同上,循環執行<code>/etc/rc$runlevel.d/s*</code> 的所有檔案都執行一遍 <code>$file start</code>
linux系統就這樣管理器linux服務的啟動。所有的檔案名都是以 <code>[ks]+<數字><程式名></code>的方式命名,最終都軟鍊到目标可執行檔案。
現在那麼很多問題都解釋的清楚了。
(a) <code>chkconfig</code> 是怎麼管理linux服務的?
(b) <code>s</code> <code>k</code>後面的數字是做什麼的?
(c) linux的多個啟動等級是如何實作的?
線上部署的過程中,需要調整系統參數,參數包括各個方面,調整的方式也不同,需要找到合适的方式。
優雅的參數設定方式: 要易于設定,易于清理。 不能侵入系統檔案.
所有的參數配置環境包括: 存量、增量、目前環境、重新開機環境
存量 : 已經線上上運作的主機,參數需要熱修改。
增量 : 以後新部署的業務,保證參數配置正确。
目前環境 : 在目前機器的運作環境中,參數設定生效。
重新開機環境 : 設定配置,使機器重新啟動後參數設定依然生效。
linux 儲存設備的 預設io 排程政策是 <code>cfq</code> , 在db 場景下, 需要 調整成 <code>deadline</code> 模式,使每個io請求都能在deadline前得到滿足。
目前環境 : <code>echo 'deadline' > /sys/block/$disk/queue/scheduler</code>
重新開機環境 : <code>grubby --grub --update-kernel=all --args="elevator=deadline"</code>
通過給 echo 修改核心變量,修改目前運作環境的配置,通過grubby 指令修改 grub.conf,設定核心加載參數, 這樣當機器重新開機的時候,自動的會把每個裝置的 io schedular 變成 deadline 。
linux /etc/fstab檔案中記錄了每個分區被開機挂在的參數。
ext4檔案系統挂載的時候,預設參數使用 <code>data=order</code>模式,可以通過 <code>cat /proc/mounts</code>來檢視。
場景:postgresql 在使用者請求的時候,會頻繁的建立和釋放臨時檔案,在請求量大的時候,機器的io會hang, 是因為ext4檔案系統在記錄檔案的時候,需要多次硬碟io,為了保證資料的一緻性,以同步的方式記錄中繼資料/日志/資料,導緻機器io跟不上,需要把挂在參數修改成 <code>data=writeback</code> 模式,可以異步記錄檔案的中繼資料、資料,提高性能。
存量 : 安裝熱修改的hotfix 。
增量 :
<code>umount /data</code>
<code>sed -i "s/noatime/noatime,data=writeback/" /etc/fstab</code> #修改fstab, 中裝置的挂載參數
<code>mount -a</code>
__注__: 關于 ext4的參數的更多資訊,請自行搜尋
很多情況下都是需要修改系統參數,來調優系統. 很容易想到的是 <code>/etc/sysctl.conf</code>。 不管是 echo 或者sed 的方式都會破壞 <code>sysctl.conf</code>的可讀性,入侵性太大,且需要求變更修改的時候,會很麻煩。根據<code>/etc/rc.sysinit</code>的腳本我們知道他的加載方式.可以采用這樣的方式。
編寫一個和<code>/etc/sysctl.conf</code>類似的 <code>mysysconf</code> 檔案,其中定義了業務關心的,需要求改的參數清單.
<code>mkdir -p /etc/sysctl.d</code>
<code>cp mysysconf /etc/sysctl.d</code>
<code>sysctl -p /etc/sysctl.d/mysysconf</code>
增量/存量/目前環境/重新開機環境均可生效。
當時用iptable的時候, 預設<code>nf_conntrack_max</code>的配置值是 65536,當請求多的時候,機器上就會報 : <code>nf_conntrack: table full, dropping packet</code> 機器也會連不上,是由于nf_conntrack中的哈希表滿了, 這種就需要放大 <code>nf_conntrack_max</code>的值。
如果直接修改sysctl, sysctl -p 的時候會提示:
<code>error: "net.nf_conntrack_max" is an unknown key</code>
是以需要先 <code>modprobe nf_conntrack</code>, 然後才能刷 系統參數.
推薦的方式:
編寫 <code>my.modules</code>檔案,内容:
modprobe nf_conntrack
<code>cp my.modules /etc/sysconfig/modules/&&chmod +x /etc/sysconfig/modules/my.modules</code> #參見 <code>/etc/rc.sysinit</code> 核心子產品的加載方式。
<code>sh /etc/sysconfig/modules/my.modules</code> # 在目前環境中,加載核心子產品
<code>cp mysysconf /etc/sysctl.d/</code> #系統配置參數其中定義了 <code>nf_conntrack_max</code> 為更大的值
<code>sysclt -p /etc/sysctl.d/mysysconf</code> 在目前系統中使配置生效
當機器上部署多個服務時,服務管理就是一個問題。
改造應用, 讓應用以linux 标準服務方式,交給chkconfig 管理,還可以自定義開機器元件之間的啟動順序。
如何可以,盡量不用<code>rc.local</code>