Linux开机启动分析与系统配置-阿里云开发者社区

开发者社区> 阿里云SAP上云> 正文
登录阅读全文

Linux开机启动分析与系统配置

简介: 在业务运维中,经常需要做系统环境配置,环境配置要在当前运行环境中生效,也要持久化依然重启生效。 通常,大家都会想到在`/etc/rc.local`中去添加业务自定义代码,但是也会发现,有些配置重启无法生产生效。 而且rc.local中会出现大量的复杂的业务逻辑代码。修改系统配置、启动业务进程等逻辑都会存在这个文件中,调用关系复杂,维护很痛苦。 一些case : 1. 开启ipta

在业务运维中,经常需要做系统环境配置,环境配置要在当前运行环境中生效,也要持久化依然重启生效。
通常,大家都会想到在/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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: