千家信息网

Ansible-Playbook批量初始化服务器的实现过程

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,初始化步骤配置ssh密钥认证远程配置主机名控制远程主机互相添加HOSTS解析配置远程主机的yum源以及一些软件时间同步配置关闭selinux/iptables修改sshd配置配置ssh密钥认证在主控节
千家信息网最后更新 2025年12月02日Ansible-Playbook批量初始化服务器的实现过程

初始化步骤

  • 配置ssh密钥认证
  • 远程配置主机名
  • 控制远程主机互相添加HOSTS解析
  • 配置远程主机的yum源以及一些软件
  • 时间同步配置
  • 关闭selinux/iptables
  • 修改sshd配置

配置ssh密钥认证

  • 在主控节点的/etc/ansible/hosts配置节点
$ vim /etc/ansible/hosts[new]192.168.56.12192.168.56.13
在控制节点配置到受控节点的ssh认证方式
# 主控节点执行$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ''$ for host in 192.168.56.{11..12};dossh-keyscan $host >> ~/.ssh/hnow_hosts 2> /dev/nullsshpass -p '123456' ssh-copy-id root@$host &> /dev/nulldone

将上面的方案playbook化:

---- name: config ssh connection  hosts: new  gather_facts: false  tasks:    - name: configure ssh connection      shell: |          ssh-keyscan {{inventory_hostname}} >> ~/.ssh/know_hosts          sshpass -p '123456' ssh-copy-id root@{{inventory_hostname}} 
ansible命令执行模块

以下的四个模块不满足幂等性

  • command:执行简单的shell命令
  • shell: 和command相同,但支持管道富豪
  • raw: 执行底层shell命令,通常在目标主机上安装python时才使用这个模块
  • script: 在远程主机上执行脚本

以下命令具备幂等性:

  • creates: 当指定的文件或者目录不存在时执行,存在不执行
  • removes:当指定的文件或者目录不存在时不执行,存在执行
---- name: modules use  hosts: new  gather_facts: false  tasks:      - name: use shell module        shell: cp /tmp/my.cnf /etc/my.cnf        args:          creates: /etc/my.cnf      - name: exec perl scripts         script: /opt/script.pl         args:           executable: perl
重点
  • connection: 连接方式(smart|ssh|paramiko|local|docker|winrm),默认为smart表示只能选择ssh或者paramiko
  • delegate_to: 只能定义在task级别上,效果和connection相似
---- name: play1  hosts: zabbix  gather_facts: false  tasks:    - name: task 1      debug:        msg: "{{ inventory_hostname }} is executing task"      delegate_to: localhost
authorized_key模块

特点:

  • 分发ssh公钥
  • 不负责主机认证阶段
    前提需要配置好hosts下的ansible_passwd字段
    [new]192.168.56.11 ansible_hostname="centos7-node1"192.168.56.12 ansible_hostname="centos7-node2"[new:vars]ansible_password="yeecallk8s"

    分发认证配置

---- name: "configure ssh connection"  hosts: new  gather_facts: false  tasks:    - authorized_key:        key: "{{lookup('file','~/.ssh/id_rsa.pub')}}"        state: present        user: root

外部数据读取的方式:

  • lookup() :支持从file,redis,etcd,pipe,vars,list,dict
    • fileglob: 支持统配文件名,file指定文件,pipe从命令执行结果中返回数据
---- name: "fileglob and file task"  hosts: new  gather_facts: false  tasks:    - name: task1      debug:        msg: "filenames: {{ lookup('fileglob','/etc/*.conf')}}"    - name: task2      debug:        msg: "filecontents: {{ lookup('file','/etc/hosts')}}
  • query() : 统配文件读取,返回list格式
---- name: "fileglob and files query"  hosts: new  gather_facts: false  tasks:    - name: "fileglob"      debug:        msg: "fileglob {{lookup('fileglob','/etc/*.conf')}}"    - name: "fileglob wantlist"      debug:        msg: "fileglob wantlist {{lookup('fileglob','/etc/*.conf',wantlist=True)}}"    - name: "query"      debug:        msg: "query {{q('fileglob','/etc/*.conf')}}"

设置主机名

使用的是hostname模块,会直接修改/etc/hostname 配置文件

---- name: set hostname  hosts: new  gather_facts: false  vars:    hostnames:      - host: 192.168.56.13        name: centos7-node3      - host: 192.168.56.14        name: centos7-node4  tasks:    - name: set hostname      hostname:        name: "{{ item.name }}"      when: item.host == inventory_hostname      loop: "{{ hostnames }}"

vars变量设置注意:

  • 设置在play级别,该play范围内的task都能访问这些变量,其他的play则无法访问
  • 设置在task级别,只有该task范围内才能访问这个变量
---- name: vars task1  hosts: new  gather_facts: false  vars:    - var1: "value1"  tasks:    - name: access value1      debug:        msg: "var1 in task1 {{var1}}"- name: vars task2  hosts: new  gather_facts: false  tasks:    - name: can not access vars from task1      debug:        msg: var1    - name: set and access var2 in this task      debug:        msg: var2      vars:        var2: "value2"    - name: cant access var2      debug:        msg: var2

when条件判断

  • 当when判断为true的时候执行任务,反之不执行
---- name: when judge  hosts: new  gather_facts: false  vars:    - myname: "alex"  tasks:    - name: task skip      debug:        msg: "my name is {{myname}}"      when: myname == "hello"   #这个判断条件是false的    - name: task will execute      debug:        msg: "my name is {{myname}}"      when: myname == "alex"

loop循环: 解决重复问题

  • 未使用循环的例子
---- name: make dirs for localhost  hosts: localhost  gather_facts: false  tasks:    - name: create test1      file:        path: /tmp/test1        state: directory    - name: create test2      file:        path: /tmp/test2        state: directory
  • 使用循环的例子
---- name: mkdir loop  hosts: localhost  gather_facts: false  tasks:    - name: create test1,2 directory      file:        path: "{{item}}"        state: directory      loop:        - /tmp/test01        - /tmp/test02

互相添加hosts(DNS)主机名解析

互相添加指定hosts组的host之间的hosts解析

---- name: add hosts DNS  hosts: new  gather_facts: false  tasks:    - name: add DNS      lineinfile:        path: /etc/hosts        line: "{{item}} {{hostvars[item].ansible_hostname}}"      when: item != inventory_hostname      loop: "{{ play_hosts }}"
  • lineinfile模块: 在源文件中插入,删除,替换行,跟sed类似
# 创建测试文件a.txt paragraph 1first line in paragraph 1second line in paragraph 1paragraph 2first line in paragraph 2second line in paragraph 2## lineinfile追加实例---- name: add line to a.txt  hosts: localhost  gather_facts: false  tasks:    - lineinfile:        path: "a.txt"        line: "append new line"        state: absent     # 删除上面的line定义的行(append new line)### 插入操作,定义在摸个行前或者行后新增(insertbefore,insertafter)---- name: lininfile demo for before and after insert  hosts: localhost  gather_facts: false  tasks:    - name: line infile      lineinfile:        path: "a.txt"        line: "LINE1"        insertbefore: '^para.* 2'        firstmatch: yes      lineinfile:        path: "a.txt"        line: "LINE2"        insertafter: '^para.* 2'        firstmatch: yes
  • play_hosts和hostvars变量
    • inventory_hostname: 表示在主机inventory中定义的名称
    • play_hosts和hostvars: 是预定义变量,执行任务时可以直接拿出来使用,play_hosts相当于是new这个主机组里面的所有主机列表;
      • hostvars: 保存了所有目标主机的变量
- name: add DNS      lineinfile:        path: /etc/hosts        line: "{{item}} {{hostvars[item].ansible_hostname}}"      when: item != inventory_hostname      loop: "{{ play_hosts }}"

配置yum源并下载安装软件

更换yum源,安装软件

---- name: "init yum"  hosts: new  gather_facts: false  tasks:    - name: "backup old yum_repo"      shell:        cmd: "mkdir bak; mv *.repo bak"        chdir: /etc/yum.repos.d        creates: /etc/yum.repos.d/bak    - name: "add new os repo and release 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/$releasever/os/$basearch"        - name: epel          baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/$releasever/$basearch"    - name: install pkgs      yum:        name: vim,net-tools,git-core,lrzsz,wget,curl,sysstat,iotop,gcc,gcc-c++,cmake,pcre,pcre-devel,zlib,zlib-devel,openssl,openssl-devel,vim,wget,telnet,setuptool,lrzsz,dos2unix,net-tools,bind-utils,tree,screen,iftop,ntpdate,tree,lsof,iftop,iotop,sysstat,procps        state: present

时间同步

使用ntpdate 同步时间

 ---- name: sync time  hosts: new  gather_facts: false  tasks:    - name: install and sync time      block:        - name: install ntpdate          yum:            name: ntpdate            state: present        - name: ntpupdate to sync time          shell: |            ntpdate ntp1.aliyun.com            hwclock -w
  • block是组织了两个有关联性的任务

关闭selinux

命令行关闭和修改配置文件两种手段

------- name: disable selinux  hosts: new  gather_facts: false  tasks:    - block:        - name: disable selinux by command          shell: setenforce 0        - name: disable selinux by config          lineinfile:            path: /etc/selinux/config            line: "SELINUX=disabled"            regexp: '^SELINUX='      ignore_errors: true

配置防火墙

---- name: set firewalld  hosts: new  gather_facts: false  tasks:    - name: set iptables rule      shell: |        iptables-save > /tmp/iptables.bak$(date +"%F-%T")        iptables -X        iptables -F        iptables -Z        systemctl disable firewalld        systemctl stop firewalld

配置sshd服务

  • 需求:
    • 禁止root用户登陆
    • 不允许使用密码登陆
---- name: "set sshd service"  hosts: new  gather_facts: false  tasks:    - name: backup old 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"        regexpr: '^PermitRootLogin'      notify: "restart sshd"    - name: disable passwd 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
0