Linux開機啟動分析與系統配置

mumangtao發表於2016-08-01

在業務運維中,經常需要做系統環境配置,環境配置要在當前執行環境中生效,也要持久化依然重啟生效。
通常,大家都會想到在/etc/rc.local中去新增業務自定義程式碼,但是也會發現,有些配置重啟無法生產生效。 而且rc.local中會出現大量的複雜的業務邏輯程式碼。修改系統配置、啟動業務程式等邏輯都會存在這個檔案中,呼叫關係複雜,維護很痛苦。

一些case :


1. 開啟iptables之後, 偶爾會遇到 `nf_conntrack: table full, dropping packet` 的資訊,並且業務無法訪問機器,這個是由於iptables的連線跟蹤表空間被使用完,無法對新建的連線建立跟蹤, 預設系統配置 `nf_conntrack_max=65535`。如果要放大這個配置,需要做:
    (a) modprobe nf_conntrack
    (b) sysctl -w "net.netfilter.nf_conntrack_max=100000" &&  sysctl -w "net.nf_conntrack_max=100000"
    當前環境生效,開機啟動後無效
    寫在rc.local ? 如果需要修改的引數是有 100個呢?

2. 業務需要系統引數修改。比如open_file_limit、dirty_ratio等等引數, 直接使用sed / echo的命令看起來都不合適.
    使用 echo : `echo "fs.file-max=655350" >> /etc/sysctl.conf `。sysctl中可能出現2個相同的配置項。
    使用 sed  :  `sed `。。。這個命令好難寫。。。 
    兩種方式都會侵入修改系統本身的/etc/sysctl.conf。 如果需要恢復系統本身的配置呢?

3. 一個機器上執行著多個業務程式,都需要開機啟動,相互之間啟動有依賴順序。
    使用rc.local 。每個元件rpm包安裝之後,rpm包內修改rc.local檔案, 解除安裝時候刪除rc.local 中的配置。 rc.local中刪除開機啟動的語句就會非常難寫。而且對安裝的順序嚴格要求。

曾經有幸看到過一些業務中看到rc.local中看到這樣的程式碼:

1  sysarg=1
...

50 sysarg=2
...

100 sysarg=3

在業務的發展中,檔案中不斷地增加程式碼。rc.local越來越臃腫且不可維護。

如何簡化配置管理,更優雅的方式去支援業務,就需要關注下主機開機啟動的細節,利用系統預留的介面達到目的。

有幾個常用的關注點:

  • Linux 服務啟動方式
  • 核心模組 啟動方式
  • sysctl 配置生效
  • rc.local

1. 主機啟動過程

主機啟動過程:

  1. 主機加電,從MBR開始引導系統
  2. 啟動核心
  3. 初始化系統配置
  4. 啟動服務
  5. 啟動使用者終端

本次主要的關注點在 3、4 流程。

1.1 啟動核心

一個機器上可以安裝多個核心。具體機器啟動中使用引導哪個核心,是在 /boot/grub/grub.conf 檔案中定義

比如一個機器grub檔案舉例
1
default 引數是選擇哪個核心作為預設啟動項

timeout 引數是指開機啟動時等待使用者選擇的時間

核心啟動可以帶多個引數,可以通過配置引數達到想要的啟動結果。

1.2 初始化系統配置

核心引導完成之後,就開始初始化系統配置。

這個功能的實現其實是呼叫 /etc/rc.sysinit 指令碼完成。

這個過程包括

(1)獲取網路環境與主機型別。首先會讀取網路環境設定檔案"/etc/sysconfig/network",獲取主機名稱與預設閘道器等網路環境。
(2)測試與載入記憶體裝置/proc及usb裝置/sys。除了/proc外,系統會主動檢測是否有usb裝置,並主動載入usb驅動,嘗試載入usb檔案系統。
(3)決定是否啟動SELinux。
(4)介面裝置的檢測與即插即用(pnp)引數的測試。
(5)使用者自定義模組的載入。使用者可以再"/etc/sysconfig/modules/*.modules"加入自定義的模組,此時會載入到系統中。
(6)載入核心的相關設定。按"/etc/sysctl.conf"這個檔案的設定值配置功能。
(7)設定系統時間(clock)。
(8)設定終端的控制檯的字形。
(9)設定raid及LVM等硬碟功能。
(10)以方式檢視檢驗磁碟檔案系統。
(11)進行磁碟配額quota的轉換。
(12)重新以讀取模式載入系統磁碟。
(13)啟動quota功能。
(14)啟動系統隨機數裝置(產生隨機數功能)。
(15)清楚啟動過程中的臨時檔案。
(16)將啟動資訊載入到"/var/log/dmesg"檔案中。

閱讀rc.sysinit的程式碼, 關注核心模組的載入sysctl配置

關於核心模組的載入

2

需要在/etc/sysconfig/modules/ 建立*.modules 檔案,並且具有可執行許可權。在開機啟動過程中,會自動的被執行。

關於sysctl配置

/etc/rc.sysinit 中有呼叫 apply_sysctl的函式。
3
/etc/init.d/functions 指令碼中有大量的被呼叫方法,其中
4
可以看到

  1. 使用 sysctl -p /etc/sysctl.conf 將預設的引數刷入系統
  2. /etc/sysctl.d/目錄下讀取檔案,如果檔案是正常檔案,就執行sysctl -p $file 的方式載入配置檔案。

1.3 Linux 服務啟動

在系統引數配置完成之後,就可以啟動系統程式了。

Linux有個啟動等級的概念。

/etc/inittab 中有定義
5
總共有 0-6 7個啟動登記, 預設的啟動啟動登記是 3。每種啟動登記分別代表不同的啟動功能。

0 系統停止
1 單使用者系統,不需要登陸
2 多使用者系統但不支援NFS,命令列模式登陸
3 完整多使用者模式,命令列模式登陸
4 未用
5 X11圖形模式,圖形模式登陸
6 重新啟動系統

對於Linux Service,

  • /etc/init.d/ 目錄下存放具體執行的執行的服務命令 ,
  • chkconfig 命令管理著Linux Service的在各個啟動等級下的是否啟動的配置。
  • 系統通過 $service start $service stop $service status的方式呼叫服務。

如何實現的呢?

系統啟動的過程中, 通過執行 /etc/rc.d/rc $RUNLEVEL 的方式啟動程式
/etc/rc.d/rc 檔案中。

6

可以看到:

  1. 首先,迴圈執行 /etc/rc$runlevel.d/K*的所有檔案都執行一遍 $file stop

    
    比如:
    runlevel是 3,那麼`/etc/rc3.d/K*`的檔案列表是:

    8

    可以看出來,其實就是按照檔名排序後的順序,就是執行的順序。
    
    每個檔案又其實是 `/etc/init.d/`目錄下檔案的軟連
    
    
  2. 接著,同上,迴圈執行/etc/rc$runlevel.d/S* 的所有檔案都執行一遍 $file start

    即。將所有S開頭的檔案都執行一遍 start 方法
    
    rc.local 什麼時候執行呢
    
    可以看到,S99local 軟連到 /etc/rc.local 檔案, 即rc.local是最後一個要啟動 指令碼。
    

Linux系統就這樣管理器Linux服務的啟動。所有的檔名都是以 [KS]+<數字><程式名>的方式命名,最終都軟鏈到目標可執行檔案。

現在那麼很多問題都解釋的清楚了。

(a) chkconfig 是怎麼管理linux服務的?


通過給不同的執行等級目錄`/etc/rc{$runlevel}.d` 增加和刪除對應的軟鏈,達到控制啟動的效果。如果是啟動,新檔案則已S開頭,如果是停止,新檔案則已K開頭。

(b) S K後面的數字是做什麼的?

 
 在編寫服務的時候,啟動指令碼頭部,一般會後這樣的說明。

chkconfig:  - 85 15

chkconfig 後面的兩個數字,分別代表該服務本身在註冊到系統中後,系統啟動時被執行的順序。可選項[20-80], 第一個數字是start的配置,數字越大,啟動的越晚, 第二個數字是stop的配置, 數字越小,執行的越找。
對於基礎服務,應該是start 的配置較小,stop 的配置較大。
對於應用服務,應該是start 的配置較大,stop 的配置較小。

現在我們知道, 其實就是生成的檔名的排序的問題。      

(c) Linux的多個啟動等級是如何實現的?
9


觀察 /etc/rc3.d/ 和 /etc/rc0.d 下的檔案列表。
rc0.d 目錄下存在大量的 K 開頭的stop 呼叫,start 呼叫 也是 S00killall 、 S01halt 這樣的關機操作。 
rc3.d 目錄下有 很多 start 呼叫, 
    S55sshd
    S58ntpd
    S90crond
    S99local    
通過這樣啟動系統服務,達到機器可用的效果。
由此控制了不同的啟動登記帶來的不同操作
依賴此,我們也可以定義自己的啟動登記。

2. 常見問題解決方案

線上部署的過程中,需要調整系統引數,引數包括各個方面,調整的方式也不同,需要找到合適的方式。

優雅的引數設定方式: 要易於設定,易於清理。 不能侵入系統檔案.

所有的引數配置環境包括: 存量、增量、當前環境、重啟環境

  • 存量 : 已經線上上執行的主機,引數需要熱修改。
  • 增量 : 以後新部署的業務,保證引數配置正確。
  • 當前環境 : 在當前機器的執行環境中,引數設定生效。
  • 重啟環境 : 設定配置,使機器重新啟動後引數設定依然生效。
2.1 磁碟 io scheduler 調整

Linux 儲存裝置的 預設IO 排程策略是 cfq , 在DB 場景下, 需要 調整成 deadline 模式,使每個IO請求都能在deadline前得到滿足。

  • 當前環境 : echo `deadline` > /sys/block/$disk/queue/scheduler
  • 重啟環境 : grubby --grub --update-kernel=ALL --args="elevator=deadline"

通過給 echo 修改核心變數,修改當前執行環境的配置,通過grubby 命令修改 grub.conf,設定核心載入引數, 這樣當機器重啟的時候,自動的會把每個裝置的 IO schedular 變成 deadline 。

2.2 分割槽掛在引數 data=writeback

Linux /etc/fstab檔案中記錄了每個分割槽被開機掛在的引數。

ext4檔案系統掛載的時候,預設引數使用 data=order模式,可以通過 cat /proc/mounts 來檢視。

場景:PostgreSQL 在使用者請求的時候,會頻繁的建立和釋放臨時檔案,在請求量大的時候,機器的IO會hang, 是因為ext4檔案系統在記錄檔案的時候,需要多次硬碟IO,為了保證資料的一致性,以同步的方式記錄後設資料/日誌/資料,導致機器IO跟不上,需要把掛在引數修改成 data=writeback 模式,可以非同步記錄檔案的後設資料、資料,提高效能。

  • 存量 : 安裝熱修改的hotfix 。
  • 增量 :

    1. umount /data
    2. sed -i "s/noatime/noatime,data=writeback/" /etc/fstab #修改fstab, 中裝置的掛載引數
    3. mount -a

__注__: 關於 ext4的引數的更多資訊,請自行搜尋

2.3 系統引數 sysctl 修改

很多情況下都是需要修改系統引數,來調優系統. 很容易想到的是 /etc/sysctl.conf。 不管是 echo 或者sed 的方式都會破壞 sysctl.conf的可讀性,入侵性太大,且需要求變更修改的時候,會很麻煩。根據/etc/rc.sysinit的指令碼我們知道他的載入方式.可以採用這樣的方式。

  1. 編寫一個和/etc/sysctl.conf類似的 mysysconf 檔案,其中定義了業務關心的,需要求改的引數列表.
  2. mkdir -p /etc/sysctl.d
  3. cp mysysconf /etc/sysctl.d
  4. sysctl -p /etc/sysctl.d/mysysconf

增量/存量/當前環境/重啟環境均可生效。

2.4 nf_conntrack_max 引數修改

當時用iptable的時候, 預設nf_conntrack_max的配置值是 65536,當請求多的時候,機器上就會報 : nf_conntrack: table full, dropping packet 機器也會連不上,是由於nf_conntrack中的雜湊表滿了, 這種就需要放大 nf_conntrack_max的值。

如果直接修改sysctl, sysctl -p 的時候會提示:
error: "net.nf_conntrack_max" is an unknown key

所以需要先 modprobe nf_conntrack, 然後才能刷 系統引數.

推薦的方式:

  1. 編寫 my.modules檔案,內容:

    modprobe nf_conntrack

  2. cp my.modules /etc/sysconfig/modules/&&chmod +x /etc/sysconfig/modules/my.modules #參見 /etc/rc.sysinit 核心模組的載入方式。
  3. sh /etc/sysconfig/modules/my.modules # 在當前環境中,載入核心模組
  4. cp mysysconf /etc/sysctl.d/ #系統配置引數其中定義了 nf_conntrack_max 為更大的值
  5. sysclt -p /etc/sysctl.d/mysysconf 在當前系統中使配置生效

2.5 開機啟動管理:Linux Service

當機器上部署多個服務時,服務管理就是一個問題。

改造應用, 讓應用以Linux 標準服務方式,交給chkconfig 管理,還可以自定義開機器元件之間的啟動順序。

如何可以,儘量不用rc.local

參考 :http://blog.chinaunix.net/uid-23069658-id-3142047.html


相關文章