查看原文
其他

ansible自动化:操作系统初始化具体实现

木讷大叔爱运维 木讷大叔爱运维 2022-07-13





读完需 10 分钟

速读需 6 分钟 



运维思索:操作系统配置规范化、自动化》一文介绍了对于一台基于安装规范交付的操作系统,还不能够直接用于生产环境,我们还需要进一步的优化,如内核参数、时间同步、排查工具、安全加固等等,保证主机安全的同时、避免因操作系统配置引发的问题。


需求

在此我们将操作系统基于安全、审计、管理等角度出发,进行了一系列优化:

  1. 用户
    服务器使用固定用户,主要为管理用户、应用用户、日志用户。此处可根据堡垒机的系统用户进行分配,避免用户混乱。

  2. 软件源
    安装基础组件需要通过统一的软件源。

  3. 关闭服务
    统一关闭selinux、iptables、sendmail、postfix等无用服务,保证服务的最小化。

  4. 初始目录
    创建固定的初始目录,如应用、日志、备份等目录,可参照《运维思索:目录管理规范的重要性》中的目录规范。

  5. limit及内核参数

    文件句柄、进程数等

  6. DNS及NTP

  7. 环境变量及历史命令记录
    终端超时
    历史命令记录及远程备份

  8. ssh优化
    禁止root登录
    ssh登录慢优化
    修改默认端口

  9. 安全设置
    密码复杂度及长度、禁止ctrl+alt+delete等,可按照具体的安全审计要求自行扩展。


规划

从上述需求来看,我们可以轻松利用ansible playbook来编排实现。但此时请先不要上头,我们还是来按以下场景来规划下:

  • 对于新服务器,我们可以playbook直接执行所有初始化操作;

  • 对于老服务器,我们只需单独执行某个优化即可;

  • playbook需要兼容Centos6、Centos7等多个版本;


因此,我们需要利用playbook的tag功能以及gather_facts获取操作系统版本,现将我们的需求按task进行分类:

vim task/main.yml- include: user.yml #用户管理- include: repo.yml #yum源- include: init_pkg.yml #安装基础组件- include: profile.yml #环境变量- include: selinux.yml #selinux- include: dir.yml #基础目录- include: limits.yml #系统参数- include: iptables.yml #防火墙- include: sysctl.yml #内核参数- include: rc.local.yml #开机启动- include: dns.yml #dns- include: ntp.yml #ntp- include: rsyslog.yml #日志同步- include: sshd.yml #ssh优化- include: safe.yml #安全配置


(1)需要区分操作系统版本号的task,如safe.yml、repo.yml、zabbix_agent.yml、iptables.yml、init_pkg.yml,可以通过gather_facts获取相关信息,并进行以下判断:

when: ansible_distribution_major_version == "7"when: ansible_distribution_major_version == "6"

(2)需要区分功能的task,如safe.yml、user.yml、zabbix-agent.yml等,可以通过tag打上自定义标签,以便后续的个性化执行:

#服务器配置完全化ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml#通过tag实现单独添加用户ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml -t user#通过tag实现单独安全配置ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml -t safe


通过以上两种方式,我们就可以通过playbook实现按需订制了,满足以后的多样性需求的优化。


另外,为方便订制,我们还需要提前规划变量,即将在不同场景下将可变参数提取为变量,这样减少了对playbook的侵入,如:

vim vars/main.yml# zabbix_server地址zabbix_server_ip: 10.10.2.34# 系统初始化组grouplist:  - name: app    gid: 500  - name: log    gid: 501# 系统初始用户userlist: - name: app pass: sljdoxf uid: 500    groups: wheel  - name: log    pass: welsdjf    groups: wheel      .........


具体实现

1.目录结构

[root@test roles]# tree os_init/os_init.ylroles├───os_init/├ ├── files│ │   ├── ansible_key│ │   │   └── id_rsa.pub│ │   ├── blueking_key│ │   │   └── id_rsa.pub│ │   ├── CentOS6-Base-LAN.repo│ │   ├── CentOS7-Base-LAN.repo│ │   ├── client.xml│ │   ├── deploy_key│ │   │   └── id_rsa.pub│ │   ├── epel7-LAN.repo│ │   ├── zabbix-agent-3.0.14-1.el7.x86_64.rpm│ │   ├── zabbix-agent-4.2.1-1.el6.x86_64.rpm│ │   ├── zabbix-release-3.0-1.el7.noarch.rpm│ │   ├── zabbix-release-4.2-1.el6.noarch.rpm│ │   ├── zabbix-sender-3.0.14-1.el7.x86_64.rpm│ │   └── zabbix-sender-4.2.1-1.el6.x86_64.rpm├ ├── handlers│ │   └── main.yml├ ├── tasks│ │   ├── dir.yml│ │   ├── dns.yml│ │   ├── init_pkg.yml│ │   ├── iptables.yml│ │   ├── limits.yml│ │   ├── main.yml│ │   ├── ntp.yml│ │   ├── profile.yml│ │   ├── rc.local.yml│ │   ├── repo.yml│ │   ├── rsyslog.yml│    │   ├── safe.yml│ │   ├── selinux.yml│ │   ├── sshd.yml│ │   ├── sysctl.yml│    │   ├── user.yml│ │   └── zabbix_agent.yml├ ├── templates│ │   └── sysctl.conf.j2└ └── vars        ├── main.yml


2.vars变量

vim vars/main.yml
# zabbix_server地址zabbix_server_ip: 10.10.2.34# 系统初始化组grouplist: - name: app gid: 500 - name: log gid: 501# 系统初始用户userlist: - name: app pass: sljdoxf uid: 500 groups: wheel - name: log pass: welsdjf    groups: wheel
#用户keysudo_key_user: appdeploy_key_user: log
#软件存放目录soft_dir: /usr/local/src
#系统初始统一目录common_directory: - /backup/logs - /backup/apps - /data/logs - /app
#Centos7基础工具centos7_pkgs: - vim - ntpdate - sysstat - lrzsz - tree - telnet - wget - gzip - zip - unzip - lsof - make - gcc - gcc-c++ - automake - autoconf - libtool - git - openssl - openssl-devel - cmake - net-tools - psmisc - bash-completion  - curl - rsync - bash
#Centos6基础工具centos6_pkgs: - vim - ntpdate - sysstat - lrzsz - tree - telnet - wget - gzip - zip - unzip - lsof - make - gcc - gcc-c++ - automake - autoconf - libtool - git - openssl - openssl-devel - cmake  - net-tools - curl - rsync  - bash

3.task 任务

(1)user.yml

# 用户订制vim user.yml- name: add group group: name: "{{ item.name }}" gid: "{{ item.gid }}" state: present loop: "{{ grouplist }}" tags: user
- name: add user user: name: "{{ item.name }}" password: "{{ item.pass | password_hash('sha512') }}" uid: "{{ item.uid }}" group: "{{ item.group }}" groups: "{{ item.groups }}" state: present loop: "{{ userlist }}" tags: user
- name: Set up multiple authorized keys authorized_key: user: '{{ sudo_key_user }}' state: present key: '{{ item }}' with_file: - ansible_key/id_rsa.pub - blueking_key/id_rsa.pub  tags: user
- name: Config /etc/sudoers lineinfile: dest=/etc/sudoers state=present line='{{item}}' with_items: - "{{ sudo_key_user }} ALL=(ALL) NOPASSWD: ALL" tags: user

(2)repl.yml

# 修改本地yum源- name: find repo file find: path: /etc/yum.repos.d patterns: '*.repo' register: repo_to_delete- name: delete repo file file: path: "{{ item.path }}" state: absent with_items: "{{ repo_to_delete.files }}"- name: centos7 yum.repos for lan copy: src={{ item.src_name }} dest=/etc/yum.repos.d/{{ item.dst_name }} force=yes with_items: - { src_name: "CentOS7-Base-LAN.repo", dst_name: "CentOS7-Base-LAN.repo" } - { src_name: "epel7-LAN.repo", dst_name: "epel7-LAN.repo" } when: ansible_distribution_major_version == "7" tags: centos7_yum_repos
- name: centos6 yum.repos for lan copy: src={{ item.src_name }} dest=/etc/yum.repos.d/{{ item.dst_name }} force=yes with_items: - { src_name: "CentOS6-Base-LAN.repo", dst_name: "CentOS6-Base-LAN.repo" } when: ansible_distribution_major_version == "6"  tags: centos6_yum_repos

(3)init_pkg.yml

# 安装基础包- name: centos7 init packages install yum: name={{ centos7_pkgs }} update_cache=yes #yum: name={{ item }} update_cache=yes #with_items: "{{ centos7_pkgs }}" when: ansible_distribution_major_version == "7" tags: centos7_init_package
- name: centos6 init packages install yum: name={{ centos6_pkgs }} update_cache=yes #yum: name={{ item }} update_cache=yes #with_items: "{{ centos7_pkgs }}" when: ansible_distribution_major_version == "6"  tags: centos6_init_package

(4)profile.yml

# 环境变量- name: /etc/profile lineinfile: path: /etc/profile line: "{{ item }}" with_items: - "readonly TMOUT=1800" - 'export HISTTIMEFORMAT="%F %T # "' - "export HISTSIZE=10240" - "export PROMPT_COMMAND=\'{ msg=$(history 1 | { read x y; echo $y; });logger -p local3.notice \"[euid=$(whoami)]\":$(who am i):[`pwd`]\"$msg\"; }\'"    - 'readonly PROMPT_COMMAND'

(5)selinux.yml

- name: stop selinux selinux: state=disabled tags: stop_selinux
- name: disable selinux replace: path=/etc/selinux/config regexp=^SELINUX=enforcing replace=SELINUX=disabled  tags: disable_selinux

(6)dir.yml

# 创建统一目录- name: create directory file: path: "{{ item }}" state: directory owner: hcuser group: wheel  with_items: "{{ common_directory }}"

(7)limit.yml

- name: change limits lineinfile: path=/etc/security/limits.conf line={{ item }} with_items: - "* soft nofile 655350" - "* hard nofile 655350" - "* soft nproc 65535" - "* hard nproc 65535"  tags: limits

(8)iptables.yml

- name: stop firewalld service: enabled=false name=firewalld state=stopped when: ansible_distribution_major_version == "7"
- name: stop iptables service: enabled=false name=iptables state=stopped  when: ansible_distribution_major_version == "6"

(9)sysctl.yml

- name: set sysctl.conf template: src: sysctl.conf.j2 dest: /etc/sysctl.conf backup: yes tags: set_sysctl
- name: "sysctl -p" command: sysctl -p ignore_errors: True  tags: reload_sysctl

(10)rc.local.yml

- name: chmod +x /etc/rc.d/rc.local  file: path=/etc/rc.d/rc.local mode=0755

(11)dns.yml

- name: config dns lineinfile: path: /etc/resolv.conf line: "{{ item }}" with_items: - "search test.com" - "nameserver 10.10.58.2"

(12)ntp.yml

- name: set ntp cron: name="time sync for ntp" job="/usr/sbin/ntpdate ntp.test.com && /sbin/hwclock -w" hour="*" state=present tags: set_ntp

(13)rsyslog.yml

- name: modify rsyslog.conf replace: path: /etc/rsyslog.conf regexp: 'cron.none' replace: 'cron.none;local3.none' notify: restart rsyslog tags: rsyslog
- name: add rsyslog.conf lineinfile: path: /etc/rsyslog.conf line: "{{ item }}" with_items: - "local3.notice @10.164.201.114:514" - ':msg, contains, "zabbix" ~' - 'authpriv.* @10.164.201.114:514' notify: restart rsyslog tags: rsyslog
- name: restart rsyslog service: enabled=true name=rsyslog state=restarted  tags: restart rsyslog

(14)zabbix_agent.yml

- name: copy zabbix-agent7 rpm file to server copy: src: "{{ item }}" dest: "{{ soft_dir }}" with_items: - "zabbix-agent-3.0.14-1.el7.x86_64.rpm" - "zabbix-release-3.0-1.el7.noarch.rpm" - "zabbix-sender-3.0.14-1.el7.x86_64.rpm" when: ansible_distribution_major_version == "7" tags: zabbix-agent
- name: install rpm yum: #name: ['/usr/local/src/zabbix-agent-3.0.14-1.el7.x86_64.rpm', '/usr/local/src/zabbix-release-3.0-1.el7.noarch.rpm', '/usr/local/src/zabbix-sender-3.0.14-1.el7.x86_64.rpm'] name: ['{{ soft_dir }}/zabbix-agent-3.0.14-1.el7.x86_64.rpm', '{{ soft_dir }}/zabbix-release-3.0-1.el7.noarch.rpm', '{{ soft_dir }}/zabbix-sender-3.0.14-1.el7.x86_64.rpm'] state: present when: ansible_distribution_major_version == "7" tags: zabbix-agent
- name: copy zabbix-agent6 rpm file to server copy: src: "{{ item }}" dest: "{{ soft_dir }}" with_items: - "zabbix-agent-4.2.1-1.el6.x86_64.rpm" - "zabbix-release-4.2-1.el6.noarch.rpm" - "zabbix-sender-4.2.1-1.el6.x86_64.rpm" when: ansible_distribution_major_version == "6" tags: zabbix-agent
- name: install rpm yum: #name: ['/usr/local/src/zabbix-agent-3.0.14-1.el7.x86_64.rpm', '/usr/local/src/zabbix-release-3.0-1.el7.noarch.rpm', '/usr/local/src/zabbix-sender-3.0.14-1.el7.x86_64.rpm'] name: ['{{ soft_dir }}/zabbix-agent-4.2.1-1.el6.x86_64.rpm', '{{ soft_dir }}/zabbix-release-4.2-1.el6.noarch.rpm', '{{ soft_dir }}/zabbix-sender-4.2.1-1.el6.x86_64.rpm'] state: present when: ansible_distribution_major_version == "6" tags: zabbix-agent- name: change /etc/zabbix/zabbix_agentd.conf lineinfile: path=/etc/zabbix/zabbix_agentd.conf regexp={{ item.conf_item }} line={{ item.conf_value }} backrefs=yes with_items: - { conf_item: "^Server=127.0.0.1", conf_value: "Server={{ zabbix_server_ip }}" } - { conf_item: "^ServerActive=127.0.0.1", conf_value: "ServerActive={{ zabbix_server_ip }}" } - { conf_item: "^Hostname=Zabbix server", conf_value: "Hostname={{ host_ip }}" } notify: restart zabbix-agent tags: zabbix-agent
- name: restart zabbix-agent service: name=zabbix-agent enabled=true state=restarted  tags: zabbix-agent

(15)safe.yml

# 禁止control-alt-delete- name: Centos7 ban control-alt-delete file: path: /usr/lib/systemd/system/ctrl-alt-del.target state: absent when: ansible_distribution_major_version == "7" tags: safe
# 禁止control-alt-delete- name: Centos6 ban control-alt-delete lineinfile: path: /etc/init/control-alt-delete.conf regexp: "start on control-alt-delete" line: "#start on control-alt-delete" when: ansible_distribution_major_version == "6" tags: safe
# 密码过期时间- name: set authentication rule lineinfile: path: /etc/login.defs regexp: "{{ item.regexp_string }}" line: "{{ item.rule }}" with_items: - { regexp_string: "^PASS_MAX_DAYS", rule: "PASS_MAX_DAYS 90"} - { regexp_string: "^PASS_MIN_DAYS", rule: "PASS_MIN_DAYS 0"} - { regexp_string: "^PASS_MIN_LEN", rule: "PASS_MIN_LEN 5"} - { regexp_string: "^PASS_WARN_AGE", rule: "PASS_WARN_AGE 10"} tags: safe  # 关闭无用服务- name: os close service service: name: "{{ item }}" state: stopped enabled: no with_items: - "httpd" - "postfix" - "sendmail" ignore_errors: yes  tags: safe

(16)ssh.yml

- name: set sshd_config replace: path=/etc/ssh/sshd_config regexp={{ item.regexp }} replace={{ item.replace }} with_items:# - { regexp: "#Port 22", replace: "Port 1022" } - { regexp: "#UseDNS yes", replace: "UseDNS no" } - { regexp: "#PermitRootLogin yes", replace: "PermitRootLogin no" } - { regexp: "GSSAPIAuthentication yes", replace: "GSSAPIAuthentication no" } notify: restart sshd tags: ssh
- name: restart sshd service: enabled=true name=sshd state=restarted  tags: restart_sshd


注意:请最后执行ssh.yml,由于进行了ssh优化,一旦过程中有问题,会导致root无法登录。


4.templates 模板

# 内核参数优化使用kernel.sysrq = 1vm.swappiness = 0kernel.threads-max = 655350kernel.pid_max = 65535vm.max_map_count = 131070net.ipv4.tcp_fin_timeout = 30net.ipv4.neigh.default.gc_stale_time=120net.ipv4.conf.all.rp_filter=0net.ipv4.conf.default.rp_filter=0net.ipv4.ip_local_port_range = 1024 65535net.ipv4.tcp_max_tw_buckets = 5000net.ipv4.tcp_syncookies = 1net.ipv4.tcp_max_syn_backlog = 131072net.ipv4.tcp_synack_retries = 2net.ipv4.tcp_tw_recycle = 0net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_timestamps = 1net.ipv4.tcp_keepalive_time = 1200net.ipv4.tcp_keepalive_intvl = 15net.ipv4.tcp_keepalive_probes = 3net.ipv4.tcp_max_orphans = 65536net.ipv4.tcp_rmem = 4096 87380 6291456net.ipv4.tcp_wmem = 4096 16384 4194304net.ipv6.conf.all.disable_ipv6 = 1net.ipv6.conf.default.disable_ipv6 = 1net.ipv6.conf.lo.disable_ipv6 = 1

5.handlers 

- name: restart sshd service: name=sshd state=restarted- name: restart rsyslog service: name=rsyslog state=restarted- name: restart zabbix-agent service: name=zabbix-agent state=restarted

6.files 

files目录中主要存放task所有需要的源文件。


执行

#服务器配置完全化ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml#通过tag实现单独添加用户ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml -t user#通过tag实现单独安全配置ansible-playbook -b -e host_ip=10.10.2.10 -v os_init.yml -t safe


总结

经过playbook的编排,我们实现了基于《操作系统安装规范》、《操作系统配置规范》、《目录管理规范》等的操作自动化。此过程中最重要的不是playbook的具体实现,而是我们怎样去根据规范去有目的的去配置


ansible自动化:mysql主从同步

K8SEASY:一键安装K8S高可用集群

运维思索:操作系统配置规范化、自动化

运维思索:目录管理规范的重要性

运维思索:操作系统安装规范化




你与世界

只差一个

公众号




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存