• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    如何使用ansible批量初始化服务器

    发布者: 嘉6148 | 发布时间: 2025-8-13 09:22| 查看数: 84| 评论数: 0|帖子模式

    简介

    本文详细介绍ansible怎么批量初始化服务器,包括ansible批量初始化服务器详细配置和步骤,有需要的小伙伴们可以参考借鉴,希望对大家有所帮助。

    详细步骤


    1、ansible要初始化的主机
    1. [root@nginx ansible]# tail -3 /etc/ansible/hosts   #要初始的主机如下
    2. [node]
    3. 192.168.20.4
    4. 192.168.20.5
    复制代码
    2、配置ssh免密登录

    playbook文件内容如下:
    1. [root@nginx ansible]# cat ssh.yaml
    2. ---
    3. - name: configure ssh connection
    4.   hosts: node
    5.   gather_facts: false
    6.   connection: local
    7.   tasks:
    8.     - name: configure ssh connection
    9.       shell: |
    10.         ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hosts
    11.         sshpass -p '123.com' ssh-copy-id root@{{inventory_hostname}}
    12. ...
    复制代码
    注:

    • gather\_facts:如果值为false,则表示不收集目标主机上的节点信息,默认为true,为收集节点信息,如果收集节点信息,则会慢很多,如果在接下来的操作中,不需要节点上的信息,可设置为false。
    • connection:local表示在ansible端本地执行任务,hosts:localhost和connection:local容易搞混,虽然两者的效果都是在本地执行任务,但是hosts:localhost是从inventory中筛选出了目标节点localhost来执行任务,而connection:local则筛选出来执行任务的目标主机是node组中的节点,但因为指定了local连接类型,使得node组中有多少个节点,就会在ansible本地执行几次该play。

    3、配置主机名

    配置主机名可以使用shell模块,但是对于不太专业,ansible提供了一个专用于配置主机名的模块:hostname模块。
    当然,要使用ansible去设置多个主机名,要求目标主机和目标名称已经关联好,否则多个主机和多个主机名之间无法对应去设置。
    例如:分别设置node组中的两个节点主机名为node01和node02,playbook内容如下:
    1. [root@ansible ansible]# cat test.yaml
    2. ---
    3. - name: set hostname
    4.   hosts: node
    5.   gather_facts: false
    6.   vars:
    7.     hostnames:
    8.       - host: 192.168.20.4
    9.         name: node01
    10.       - host: 192.168.20.5
    11.         name: node02
    12.   tasks:
    13.     - name: set hostname
    14.       hostname:
    15.         name: "{{item.name}}"
    16.       when: item.host == inventory_hostname
    17.       loop: "{{hostnames}}"
    复制代码
    在上面的hostname模块中,需要详细介绍vars指令以及when、loop指令。
    1)vars设置变量
    vars指令可用于设置变量,可以设置一个或多个变量。下面几种方式都是合理的:
    1. # 设置单个变量
    2. vars:
    3.   var1: value1
    4. vars:
    5.   - var1: value1
    6. # 设置多个变量
    7. vars:
    8.   var1: value1
    9.   var2: value2
    10. vars:
    11.   - var1: value1
    12.   - var2: value2
    复制代码
    vars可以设置在play级别,也可以设置在task级别,设置在play级别,该play范围内的task可以访问这些变量,其他play范围内则无法访问;设置在task级别,只有该task能访问这些变量,其他task和其他play则无法访问。
    例如:
    1. [root@ansible ansible]# cat test.yaml
    2. ---
    3. - name: play1
    4.   hosts: localhost
    5.   gather_facts: false
    6.   vars:
    7.     - var1: "value1"
    8.   tasks:
    9.     - name: access var1
    10.       debug:
    11.         msg: "var1's value: {{var1}}"
    12. - name: play2
    13.   hosts: localhost
    14.   gather_facts: false
    15.   tasks:
    16.     - name: cat's access vars from play1
    17.       debug:
    18.         var: var1
    19.     - name: set and access var2 in this task
    20.       debug:
    21.         var: var2
    22.       vars:
    23.         var2: "value2"
    24.     - name: cat't accesss var2
    25.       debug:
    26.         var: var2
    复制代码
    执行结果如下:
    1. [root@ansible ansible]# ansible-playbook test.yaml PLAY [play1] **************************************************************************TASK [access var1] ********************************************************************ok: [localhost] => {    "msg": "var1's value: value1"}PLAY [play2] **************************************************************************TASK [cat's access vars from play1] ***************************************************ok: [localhost] => {    "var1": "VARIABLE IS NOT DEFINED!"}TASK [set and access var2 in this task] ***********************************************ok: [localhost] => {    "var2": "value2"}TASK [cat't accesss var2] *************************************************************ok: [localhost] => {    "var2": "VARIABLE IS NOT DEFINED!"} PLAY RECAP ****************************************************************************localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    复制代码
    回到我们更改主机名的配置vars指令中:
    1.   vars:
    2.     hostnames:
    3.       - host: 192.168.20.4
    4.         name: node01
    5.       - host: 192.168.20.5
    6.         name: node02
    复制代码
    上面只设置了一个变量hostnames,但这个变量的值是一个数组结构,数组的两个元素又都是对象(字典/hash)结构。
    所以想要访问主机名node01和它的IP地址192.168.20.4,可以:
    1.   tasks:
    2.     - debug:
    3.         var: hostnames[0].name
    4.     - debug:
    5.         var: hostnames[0].host
    复制代码
    2)when条件判断
    在ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则执行该任务,否则不执行该任务。
    例如:
    1. [root@ansible ansible]# cat test.yaml
    2. ---
    3. - name: play1
    4.   hosts: localhost
    5.   gather_facts: false
    6.   vars:
    7.     - myname: "Ray"
    8.   tasks:
    9.     - name: task will skip
    10.       debug:
    11.         msg: "myname is : {{myname}}"
    12.       when: myname == "lv"
    13.     - name: task will execute
    14.       debug:
    15.         msg: "myname is : {{myname}}"
    16.       when: myname == "Ray"
    复制代码
    在上面的myname值设置为Ray,第一个任务因为when的判断条件是myname==“lv”,所以判断结果为false,该任务不执行,同理,第二个任务因为when的值为true,所以执行了。
    该playbook的执行结果:
    1. PLAY [play1] ************************************************************************** TASK [task will skip] *****************************************************************skipping: [localhost] TASK [task will execute] **************************************************************ok: [localhost] => {    "msg": "myname is : Ray"} PLAY RECAP ****************************************************************************localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0  
    复制代码
    4、互相添加DNS解析记录
    1. [root@ansible ansible]# cat add_dns.yaml
    2. ---
    3. - name: play1
    4.   hosts: node
    5.   gather_facts: true
    6.   tasks:
    7.     - name: add DNS
    8.       lineinfile:
    9.         path: "/etc/hosts"
    10.         line: "{{item}} {{hostvars[item].ansible_hostname}}"
    11.       when: item != inventory_hostname
    12.       loop: "{{ play_hosts }}"
    复制代码
    执行结果如下:
    1. TASK [Gathering Facts] ****************************************************************ok: [192.168.20.4]ok: [192.168.20.5] TASK [add DNS] ************************************************************************skipping: [192.168.20.4] => (item=192.168.20.4) changed: [192.168.20.4] => (item=192.168.20.5)changed: [192.168.20.5] => (item=192.168.20.4)skipping: [192.168.20.5] => (item=192.168.20.5) 
    复制代码
    5、配置yum镜像源并安装软件

    需求如下:

    • 备份原有yum镜像源文件,并配置清华大学的yum镜像源:os源和epel源
    • 安装常用软件,包括lrzsz、dos2unix、wget、curl、vim等;
    playbook如下:
    1. [root@ansible ansible]# cat config_yum.yaml
    2. - name: config yum repo add install software
    3.   hosts: node
    4.   gather_facts: false
    5.   tasks:
    6.     - name: backup origin yum repos
    7.       shell:
    8.         cmd: "mkdir bak; mv *.repo bak"
    9.         chdir: /etc/yum.repos.d
    10.         creates: /etc/yum.repos.d/bak
    11.     - name: add os repo and epel repo
    12.       yum_repository:
    13.         name: "{{item.name}}"
    14.         description: "{{item.name}} repo"
    15.         baseurl: "{{item.baseurl}}"
    16.         file: "{{item.name}}"
    17.         enabled: 1
    18.         gpgcheck: 0
    19.         reposdir: /etc/yum.repos.d
    20.       loop:
    21.         - name: os
    22.           baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"
    23.         - name: epel
    24.           baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"
    25.     - name: install pkgs
    26.       yum:
    27.         name: lrzsz,vim,dos2unix,wget,curl
    28.         state: present
    复制代码
    在上面的yaml文件中,第一个任务是将所有系统默认的repo文件备份到bak目录中,chdir参数表示在执行shell模块的命令前先切换到/etc/yum.repos.d目录下,creates参数表示bak目录存在时则不执行shell模块。
    第二个任务是使用yum\_repository模块配置yum源,该模块可添加或移除yum源。
    1. 相关参数如下:name:指定repo的名称,对应于repo文件中的[name];description:repo的描述信息,对应repo文件中的name:xxx;baseurl:指定该repo的路径;file:指定repo的文件名,不需要加.repo后缀,会自动加上;reposdir:repo文件所在的目录,默认为/etc/yum.repos.d目录;enabled:是否启用该repo,对应于repo文件中的enabled;gpgcheck:该repo是否启用gpgcheck,对应于repo文件中的gpgcheck;state:present表示保证该repo存在,absent表示移除该repo。
    复制代码
    在上面的配置中使用了一个loop循环来添加两个repo:os和epel。
    第三个任务是使用yum模块安装一些rpm包,yum模块可以更新、安装、移除、下载包。
    1. yum常用参数说明:
    2. <ul><li>name:指定要操作的包名<ul><li>可以带版本号;</li><li>可以是单个包名,也可以是包名列表,或者逗号分隔多个包名;</li><li>可以是url;</li><li>可以是本地rpm包</li></ul></li><li>state:<ul><li>present和installed:保证包已安装,它们是等价的别名;</li><li>latest:保证包已安装了最新版本,如果不是则更新;</li><li>absent和removed:移除包,它们是等价的别名;</li></ul></li><li>download\_only:仅下载不安装包(ansible 2.7才支持)</li><li>download\_dir:下载包存放在哪个目录下(ansible 2.8才支持)</li></ul>
    复制代码
    yum模块是RHEL系列的包管理器,如果是ubuntu则无法使用,可以使用另一个更为通用的包管理器模块:package,它可以自动探测目标节点的包管理器类型并使用它们去管理软件。大多数时候使用package来代替yum或代替apt-install等不会有什么问题,但是有些包名在不同的操作系统上是不一样的,这是需要注意的。

    6、时间同步

    保证时间同步可以避免很多玄学性的问题,特别是对集群中的节点。
    通常会使用ntpd时间服务器来保证时间的同步,这里使用aliyun提供的时间服务器来保证时间同步,并将同步后的时间同步到硬件。
    playbook文件如下:
    1. ---
    2. - name: sync time
    3.   hosts: node
    4.   gather_facts: false
    5.   tasks:
    6.     - name: install and sync time
    7.       block:
    8.         - name: install ntpdate
    9.           yum:
    10.             name: ntpdate
    11.             state: present
    12.         - name: ntpdate to sync time
    13.           shell: |
    14.             ntpdate ntp1.aliyun.com
    15.             hwclock -w
    复制代码
    上面使用了一个block指令来组织了两个有关联性的任务,将他们作为了一个整体。block更多的用于多个关联性任务之间的异常处理。

    7、关闭selinux

    关闭selinux的playbook如下:
    1. [root@ansible roles]# cat disable_selinux.yaml
    2. ---
    3. - name: disable selinux
    4.   hosts: node
    5.   gather_facts: false
    6.   tasks:
    7.     - name: disable on the fly
    8.       shell: setenforce 0
    9.       ignore_errors: true   #由于上条命令执行后的返回状态码不一定为0,所以为了防止非0报错并停止palsybook接下来的任务,所以使用ignore_errors忽略错误
    10.     - name: disable forever in config
    11.       lineinfile:
    12.         path: /etc/selinux/config
    13.         line: "SELINUX=disabled"     #修改配置文件中的值,以便永久关闭
    14.         regexp: '^SELINUX='          #要修改的内容
    复制代码
    注:ignore\_errors也经常结合block使用,因为在block级别上设置异常处理,可以处理block内部的所有错误。

    8、配置iptables规则

    playbook文件如下:
    1. - name: Set Firewall
    2.   hosts: node
    3.   gather_facts: false
    4.   tasks:
    5.     - name: set iptables rule
    6.       shell: |
    7.         # 备份已有规则
    8.         iptables-save > /tmp/iptables.bak$(date +"%F-%T")
    9.         # 给它三板斧
    10.         iptables -X
    11.         iptables -F
    12.         iptables -Z
    13.         # 放行lo网卡和允许ping
    14.         iptables -A INPUT -i lo -j ACCEPT
    15.         iptables -A INPUT -p icmp -j ACCEPT
    16.         # 放行关联和已建立连接的包,放行22、443、80端口
    17.         iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    18.         iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
    19.         iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
    20.         iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
    21.         # 配置filter表的三链默认规则,INPUT链丢弃所有包
    22.         iptables -P INPUT DROP
    23.         iptables -P FORWARD DROP
    24.         iptables -P OUTPUT ACCEPT
    复制代码
    9、远程修改sshd配置文件并重启

    有时候为了服务器的安全,可能会去修改目标节点上sshd服务的默认配置,比如禁止root用户登录、禁止密码认证登录而只允许使用ssh密码认证等。
    在修改服务的配置文件时,一般有几种方法:

    • 通过远程执行sed等命令进行修改配置文件;
    • 通过lineinfile模块去修改配置文件;
    • 在ansible本地段写好配置文件,然后使用copy模块或者template模块传输到目标节点上。
    相对来说,第三种方案是最统一、最易维护的方案。
    此外,对于服务进程来说,修改了配置文件往往意味着要重启服务,使其加载新的配置文件,对于sshd也一样如此,但是sshd要比其他服务特殊一些,因为ansible默认基于ssh连接,重启sshd服务会使ansible连接断开,好在ansible默认会重试建立连接,无非是多等待几秒。但重建连接有可能会失败,比如修改了配置文件不允许重试、修改了sshd的监听端口等,这可能会使得ansible因连接失败而无法再继续执行后续任务。
    1. 所以,在修改sshd配置文件时,有如下建议:
    2. <ul><li>将此任务作为初始化服务器的最后一个任务,即使连接失败也无所谓;</li><li>在playbook中加入连接失败的异常处理;</li><li>如果目标节点修改了sshd端口号,建议通过ansible自动或者我们手动去修改inventory文件中的ssh连接端口号。</li></ul>
    复制代码
    这里为了简单,我准备使用lineinfile模块去修改配置文件,要修改的内容只有两项:

    • 将PermitRootLogin指令设置为no,禁止root用户直接登录;
    • 将PasswordAuthentication指令设置为no,不允许使用密码认证的方式登录
    playbook内容如下:
    1. [root@ansible roles]# cat sshd_config.yaml
    2. ---
    3. - name: modify sshd_config
    4.   hosts: node
    5.   gather_facts: false
    6.   tasks:
    7.     # 1.备份/etc/ssh/sshd_config文件
    8.     - name: backup sshd config
    9.       shell:
    10.         /usr/bin/cp -f {{path}} {{path}}.bak
    11.       vars:
    12.         - path: /etc/ssh/sshd_config
    13.     # 2.设置PermitRootLogin no
    14.     - name: disable root login
    15.       lineinfile:
    16.         path: "/etc/ssh/sshd_config"
    17.         line: "PermitRootLogin no"
    18.         insertafter: "^#PermitRootLogin"
    19.         regexp: "^PermitRootLogin"
    20.       notify: "restart sshd"
    21.     # 3.设置PasswordAuthentication no
    22.     - name: disable password auth
    23.       lineinfile:
    24.         path: "/etc/ssh/sshd_config"
    25.         line: "PasswordAuthentication no"
    26.         regexp: "^PasswordAuthentication yes"
    27.       notify: "restart sshd"
    28.   handlers:
    29.     - name: "restart sshd"
    30.       service:
    31.         name: sshd
    32.         state: restarted
    复制代码
    关于notify和handlers的作用如下:
    ansible会监控playbook执行后的changed的状态,如果changed=1,则表示关注的状态发生了改变,即本次任务的执行不具备幂等性,如果changed=0,则表示本次任务要么没执行,要么执行了也没有影响,即本次任务具备幂等性。ansible提供了notify指令和handlers功能,如果在某个task中定义notify指令,当ansible在监控到该任务changed=1时,会触发该notify指令所定义的handler,然后去执行handler。所谓handler,其实就是task,无论是在写法上还是作用上它和task都没有什么区别,唯一的区别在于handler是被触发而被动执行的,不像普通task一样会按流程正常执行。
    唯一需要注意的是,notify和handler中任务的名称必须一致。比如: notify: "restart sshd",那么handlers中必须得有一个任务设置了 name: "restart sshd"。
    此外,在上面的playbook中,两个lineinfile任务都设置了相同的notify,但ansible不会多次去重启sshd,而是在最后重启一次。实际上,ansible在执行完某个任务之后,并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完成后再去执行handler,这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启。

    10、整合所有任务到单个playbook中

    这里将前面所有的playbook集合到单个playbook文件中去,这样就可以一次性执行所有任务。
    整合后的playbook如下:
    1. ---- name: Configure ssh Connection  hosts: node  gather_facts: false  connection: local  tasks:    - name: configure ssh connection      shell: |        ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hosts        sshpass -p'123.com' ssh-copy-id root@{{inventory_hostname}}- name: Set Hostname  hosts: node  gather_facts: false  vars:
    2.     hostnames:
    3.       - host: 192.168.20.4
    4.         name: node01
    5.       - host: 192.168.20.5
    6.         name: node02  tasks:     - name: set hostname      hostname:         name: "{{item.name}}"      when: item.host == inventory_hostname      loop: "{{hostnames}}"- name: Add DNS For Each  hosts: node  gather_facts: true  tasks:     - name: add DNS      lineinfile:         path: "/etc/hosts"        line: "{{item}} {{hostvars[item].ansible_hostname}}"      when: item != inventory_hostname      loop: "{{ play_hosts }}"- name: Config Yum Repo And Install Software  hosts: node  gather_facts: false  tasks:     - name: backup origin yum repos      shell:         cmd: "mkdir bak; mv *.repo bak"        chdir: /etc/yum.repos.d        creates: /etc/yum.repos.d/bak    - name: add os repo and epel repo      yum_repository:         name: "{{item.name}}"        description: "{{item.name}} repo"        baseurl: "{{item.baseurl}}"        file: "{{item.name}}"        enabled: 1        gpgcheck: 0        reposdir: /etc/yum.repos.d      loop:        - name: os          baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"        - name: epel          baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"    - name: install pkgs      yum:         name: lrzsz,vim,dos2unix,wget,curl        state: present- name: Sync Time  hosts: node  gather_facts: false  tasks:     - name: install and sync time      block:         - name: install ntpdate          yum:             name: ntpdate            state: present        - name: ntpdate to sync time          shell: |            ntpdate ntp1.aliyun.com            hwclock -w- name: Disable Selinux  hosts: node  gather_facts: false  tasks:     - block:         - name: disable on the fly          shell: setenforce 0        - name: disable forever in config          lineinfile:             path: /etc/selinux/config            line: "SELINUX=disabled"            regexp: '^SELINUX='      ignore_errors: true- name: Set Firewall
    7.   hosts: node
    8.   gather_facts: false
    9.   tasks:
    10.     - name: set iptables rule
    11.       shell: |
    12.         # 备份已有规则
    13.         iptables-save > /tmp/iptables.bak$(date +"%F-%T")
    14.         # 给它三板斧
    15.         iptables -X
    16.         iptables -F
    17.         iptables -Z
    18.         # 放行lo网卡和允许ping
    19.         iptables -A INPUT -i lo -j ACCEPT
    20.         iptables -A INPUT -p icmp -j ACCEPT
    21.         # 放行关联和已建立连接的包,放行22、443、80端口
    22.         iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    23.         iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
    24.         iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
    25.         iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
    26.         # 配置filter表的三链默认规则,INPUT链丢弃所有包
    27.         iptables -P INPUT DROP
    28.         iptables -P FORWARD DROP
    29.         iptables -P OUTPUT ACCEPT- name: Modify sshd_config  hosts: node  gather_facts: false  tasks:    - name: backup sshd config      shell:         /usr/bin/cp -f {{path}} {{path}}.bak      vars:         - path: /etc/ssh/sshd_config    - name: disable root login      lineinfile:         path: "/etc/ssh/sshd_config"        line: "PermitRootLogin no"        insertafter: "^#PermitRootLogin"        regexp: "^PermitRootLogin"      notify: "restart sshd"    - name: disable password auth      lineinfile:         path: "/etc/ssh/sshd_config"        line: "PasswordAuthentication no"        regexp: "^PasswordAuthentication yes"      notify: "restart sshd"  handlers:     - name: "restart sshd"      service:         name: sshd        state: restarted
    复制代码
    按照以上步骤一步一步操作,你将轻松完成批量服务器的初始化。
    到此这篇关于使用ansible批量初始化服务器的文章就介绍到这了,更多相关ansible批量初始化服务器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    浏览过的版块

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表