【實操乾貨】做好這 16 項優化,你的 Linux 作業系統煥然一新

雲叔_又拍雲發表於2022-06-16

大家好,這次跟大家談談又拍雲的作業系統優化方案。往簡單地說,我們使用的 Linux 作業系統主要都是基於 CentOS6/7 的精簡和優化。往復雜地說,則是我們有兩套系統,業務上使用的定製 Linux 系統和資料中心使用的優化版 Linux 系統。

業務上我們使用裁剪過的定製 Linux 系統,目的是為了更安全、更高效、更加貼近業務需求,方便全國各點進行閃電式部署,但這套系統不具備普適性,所以我們今天暫時不談它。今天主要分享資料中心常用的 Linux 優化版本,因為這個比較通用,適合大家在使用時進行參考。我會從以下幾個方面來進行分享。

主機名設定和永久生效

在 CentOS 或 RHEL 中,有以下三種定義的主機名:

  • 靜態的(static):“靜態”主機名也稱為核心主機名,是系統在啟動時從 /etc/hostname 自動初始化的主機名。
  • 瞬態的(transient):“瞬態”主機名是在系統執行時臨時分配的主機名如通過 DHCP 或 mDNS 伺服器分配。
  • 靈活的(pretty):“靈活”主機名則允許使用自由形式(包括特殊/空白字元)的主機名,以展示給終端使用者(如 Gemini's Computer)。

好的主機名,可以讓非運維的機房人員一目瞭然地瞭解和定位機器。比如: 用途名 + 省份 + 機房名 + 機櫃號 + 編號,示例如下:

HOST="DBS-ZJ-FUD-009"
hostnamectl set-hostname --static $HOST
hostnamectl set-hostname --pretty $HOST
hostnamectl set-hostname --transient  $HOST
echo "$HOST" > /proc/sys/kernel/hostname

定製遠端登入介面

登陸 Linux 的歡迎介面可由 /etc/issue和/etc/motd 控制。如下顯示,不用登入系統就能一目瞭然的知道系統版本、CPU 和記憶體型號容量、執行狀態、應用版本號及網路連線情況。

字符集配置

好的字符集,可以避免終端顯示下的亂碼。建議使用 en_US.utf8 字符集。

# 檢視作業系統支援的所有字符集
# locale -a

cat > /etc/locale.conf <<EOF
LANG=en_US.utf8
LC_CTYPE=en_US.utf8
EOF
localectl set-locale LANG=en_US.UTF8

常規基礎軟體安裝

因為使用的都是基於 CentOS 的最小化精簡安裝,安裝後會缺少一些常規的基礎軟體,所以我們會適當補充一些基礎軟體,以幫助快速排查和定位問題。

yum install -y tree ntpdate  bc nc net-tools wget lsof rsync nmon bash-completion iptables-services firewalld sysstat mtr htop bind-utils yum-utils epel-release smartmontools supervisor python-setuptools python-pip pkgconfig

時區和時間同步設定

在實際生產環境中,保障伺服器時區和時間的一致性非常重要。尤其是分散式系統、多機叢集環境、資料庫主從備份、以及依賴時間同步的定時任務等場景,時區和時間同步是非常有用的,一旦二者不一致很容易導致各種各樣的問題。

timedatectl set-timezone Asia/Shanghai
timedatectl set-ntp 1
timedatectl set-local-rtc 0
#timedatectl set-time "2018-08-08 18:08:08"
ntpdate -u cn.pool.ntp.org

強烈建議同時把時間同步操作也寫入 crontab 裡做雙保險。

# crontab -l
0 * * * * root(ntpdate -o3 192.168.1.10 211.115.194.21 )

禁用 SELinux

SELinux 為安全增強型 Linux(Security-Enhanced Linux),主要由美國國家安全域性開發。它概念嚴謹、結構及配置複雜、操作嚴格。因此在使用時可以視情況決定是否要開啟使用,可以在有機密和資訊敏感機構等的特殊場景下可以啟用。

sed -r -i  '/^SELINUX=/s^=.*^=disabled^g' /etc/selinux/config
set enforce 0

新增普通使用者並 sudo

sudo 是 Linux 系統管理指令,是允許系統管理員讓普通使用者執行一些或者全部的 root 命令的一個工具,如 halt、reboot、su 等等。 這樣不但可以減少 root 使用者的登入和管理時間,也能夠提高安全性。

需要注意的是,生產環境儘量不要直接用 root,建議先新建普通使用者再提升許可權。

[root@OPS-FDI-020 ~]# useradd shaohy
[root@OPS-FDI-020 ~]# usermod -G wheel  shaohy
[root@OPS-FDI-020 ~]# sed -i '/pam_wheel/s/^#//g'  /etc/pam.d/su

為使用者 shaohy 新增 sudo,除關機外的其他所有操作:

[root@OPS-FDI-020 ~]# visudo
Cmnd_Alias SHUTDOWN = /sbin/halt, /sbin/shutdown, /sbin/poweroff, /sbin/reboot, /sbin/init
shaohy         ALL=(ALL)       ALL,!SHUTDOWN
%wheel         ALL=(ALL)       ALL,!SHUTDOWN    #修改wheel組的許可權,禁止關機
Defaults logfile=/var/log/sudo.log

配置防火牆規則和 iptables

自 CentOS7 以後都是預設使用 firewalld 管理 netfilter 子系統,需要注意的是底層呼叫的命令仍然使用了 iptables。二者的區別對比如下:

  • firewalld 可以動態修改單條規則,動態管理規則集,允許更新規則而不破壞現有會話和連線。而 iptables,在修改了規則後必須得全部重新整理才可以生效。
  • firewalld 使用區域和服務而不是鏈式規則。
  • firewalld 預設是拒絕的,需要設定以後才能放行。而 iptables 預設是允許的,需要拒絕的才去限制。

所以在選擇時可以考慮不拒絕 firewalld,去嘗試接受它。

#!/bin/sh
IPS="192.168.0.0/16"
firewall-cmd --zone=public --remove-service=ssh
firewall-cmd --new-zone=openssh --permanent
firewall-cmd --zone=openssh --add-port=22222/tcp --permanent
firewall-cmd --permanent --zone=public --set-target=default
for ip in  $IPS;do
        firewall-cmd --zone=openssh --add-source=$ip --permanent
done
firewall-cmd --reload
firewall-cmd --runtime-to-permanent

GPT 分割槽和分割槽掛載

又拍雲每一臺 CDN 伺服器上都有大量硬碟,且不說 4T、6T 這類量比較小的,即便是 10T 的也有 12 塊之多,所以需要自動化格式化和劃分割槽這些硬碟的運維操作。

早期的主開機記錄(Master Boot Record,縮寫:MBR),又叫做主引導扇區,也就是計算機開機後訪問硬碟時所必須要讀取的首個扇區,無法支援大於 2T 的硬碟引導。雖然打了補丁的 MBR 也可以支援大於 2T 的分割槽,但 GPT 已經成為了新的趨勢。相比 MBR 而言,GPT 分割槽方案有以下特點:

  • GPT 是 UEFI 標準的一部分(UEFI 是一種個人電腦系統規格,用來定義作業系統與系統韌體之間的軟體介面,作為 BIOS 的替代方案)。
  • GPT 分割槽列表支援最大 128PB(1PB=1024TB)。
  • 可以定義 128 個分割槽。
  • 沒有主分割槽,擴充套件分割槽和邏輯分割槽的概念,所有分割槽都能格式化。
#!/bin/sh
DEV=`lsscsi | awk '/HGST/{print $NF}'` # 篩選所有的sata硬碟
i=1
for dev in $DEV;do
        label="/disk/sata0$i"
        echo $dev $label
        parted -m -s $dev rm 1
        parted -m -s $dev mklabel gpt
        parted -m -s $dev mkpart primary ext4 2048s 100%
        partx -a $dev
        ((i++))
        nohup mkfs.ext4 -L $label ${dev}1 >/dev/null &
done

ulimit 配額設定

因為 CentOS7 / RHEL7 系統中使用 Systemd 替代了之前的 SysV,導致 /etc/security/limits.conf 檔案的配置只適用於通過 PAM 認證登入使用者的資源限制,對 systemd 的service 資源限制不生效。

因為 systemd service 的資源限制,所以我們將全域性配置放置於 /etc/systemd/system.conf 和 /etc/systemd/user.conf 中。其中 system.conf 用於系統例項,user.conf 用於使用者例項。

sed -r -i -e '/DefaultLimitCORE/s^.*^DefaultLimitCORE=infinity^g' -e '/DefaultLimitNOFILE/s^.*^DefaultLimitNOFILE=100000^g' -e '/DefaultLimitNPROC/s^.*^DefaultLimitNPROC=100000^g' /etc/systemd/system.conf

加大開啟檔案數的限制, 預設設定了非 root 使用者的最大程式數為 4096。

cat > /etc/security/limits.d/20-nproc.conf <<EOF
*       soft  nproc  10240
root    soft  nproc  unlimited
EOF

sysctl.conf 配置生效

sysctl.conf 檔案配置引數較多且複雜,如果需要詳解每一個引數的作用需要很長時間。這裡我們之間看一部分常見調優引數來感受一下。主要是集中在網路和 TCP 引數優化、 swap 禁用、檔案控制程式碼放大 。


net.ipv4.ip_forward=1
net.ipv4.ip_local_port_range=1000 65535

net.ipv4.tcp_slow_start_after_idle=0
net.ipv4.tcp_no_metrics_save=1
net.ipv4.tcp_rfc1337=1
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_dsack=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_rmem=4096 102400 16777216
net.ipv4.tcp_wmem=4096 102400 16777216
net.ipv4.tcp_mem=786432 1048576 1572864
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_syn_retries=3
net.ipv4.tcp_synack_retries=5
net.ipv4.tcp_retries1=3
net.ipv4.tcp_retries2=15
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_max_syn_backlog=262144                                  
net.ipv4.tcp_max_orphans=262144
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_keepalive_time=30
net.ipv4.tcp_keepalive_intvl=10
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_max_tw_buckets=600000
net.ipv4.tcp_congestion_control=bbr

net.core.somaxconn=8192
net.core.rmem_default=131072
net.core.wmem_default=131072
net.core.rmem_max=33554432
net.core.wmem_max=33554432
net.core.dev_weight=512
net.core.optmem_max=262144
net.core.netdev_budget=1024
net.core.netdev_max_backlog=262144

vm.swappiness=0
vm.dirty_writeback_centisecs=9000
vm.dirty_expire_centisecs=18000
vm.dirty_background_ratio=5
vm.dirty_ratio=10
vm.overcommit_memory=1
vm.overcommit_ratio=50
vm.max_map_count=200000

fs.file-max=524288
fs.aio-max-nr=1048576 

/etc/passwd 安全性檢查

使用者的 shell 許可權檢查,通常考慮到安全性的問題,不允許有非 root 使用者擁有 shell 許可權。

# 過濾出有uid==0, gid==0的潛伏使用者,判斷有沒有bash
awk -F: '($3==0||$4==0) {print $0}' /etc/passwd|grep -i bash
# 除root外的使用者shell全部為nologin
sed -r -i '/^[^root]/s:/bin/bash:/sbin/nologin:g' /etc/passwd

sshd 服務配置

因為幾乎所有 Linux 伺服器都通過 SSH 來進行遠端管理,這很容易招來許多不速之客,想方設法通過 SSH 來取得您的伺服器許可權。所以 SSH 安全不容忽視!強烈建議禁用口令登入,修改之前先改用公金鑰的方式來 SSH 登入管理伺服器。

sed -r -i '/#Port 22/s^.*^Port 22222^g;/^PasswordAuthentication/s^yes^no^g' /etc/ssh/sshd_config

關閉不必要服務

Linux 服務(Linux services)對於每個應用 Linux 的使用者來說都很重要。關閉不必要的服務,可以讓 Linux 執行更高效,但並不是所有的 Linux 服務都可以關閉,這個要自己權衡。

systemctl disable network  postfix irqbalance tuned rpcbind.target

如果有基於 udp 的服務,如ntpd、dns,要注意 udp 的反射攻擊。因為 udp 的反射攻擊破壞力極大,最好關閉掉無用相關的服務, 或者選擇高防機房去部署此類服務。

logrotate 縮減輪轉日誌包

當伺服器程式較多,日誌檔案大小增長較快,就會不斷消耗磁碟空間並觸發告警。這時就需要人為定期按照各種維度去手動清理日誌,如果不及時清理則很容易變成運維事故。

通常可以使用 logrotate 日誌滾動機制將日誌檔案按時間或大小分成多份,刪除時間久遠的日誌檔案,從而節省空間和方便整理。

sed -r -i 's@weekly@daily@g;s@^rotate.*@rotate 7@g;s@^#compress.*@compress@g' /etc/logrotate.conf
systemctl daemon-reload; systemctl restart rsyslog

journalctl 調整 journal 日誌

在 Systemd 出現之前,Linux 系統及各應用的日誌都是分別管理的,而 Systemd 統一管理了所有 Unit 啟動日誌。這樣的好處就是可以只用一個 journalctl 命令,檢視所有核心和應用的日誌。

適當的配置可以讓 journal 體積可控,不至於容量爆炸。

sed -r -i -e '/Compress=/s@.*@Compress=yes@g; /SystemMaxUse=/s@.*@SystemMaxUse=4G@g; ' -e '/SystemMaxFileSize=/s@.*@SystemMaxFileSize=256M@g;' -e '/MaxRetentionSec=/s@.*@MaxRetentionSec=2week@g' /etc/systemd/journald.conf

綜上所述,完成以上這些優化後,一個安全可靠的作業系統就可以正式上線提供服務了, 祝大家 Linux 之旅玩得愉快!

推薦閱讀

面試官問,Redis 是單執行緒還是多執行緒我懵了

Base64 編碼知識,一文打盡

相關文章