Ansible自动化(自动化工具、批量化管理工具)

一、什么是Ansible?
Ansible 是一款开源的 IT 自动化工具,用于配置管理、应用部署、任务自动化和持续交付。它通过 SSH(无需在目标主机安装客户端)或 PowerShell 进行远程管理,采用 YAML 语言编写剧本(Playbook),以声明式的方式描述系统状态。

二、Ansible的主机清单(/etc/ansible/hosts)
1.作用:用于定义和管理所有需要被 Ansible 控制的目标主机
2.定义方式

点击查看代码
1)单台定义
10.0.0.7 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
[IP]         [用户名]                  [端口]                 [登录密码]
2)定义别名
web01 ansible_ssh_host=10.0.0.7 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
[别名]
3) 定义多台
LNMP ansible_ssh_host=10.0.0.7 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
web02 ansible_ssh_host=10.0.0.9 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
mariadb ansible_ssh_host=10.0.0.8 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
4)划分小组
NFS ansible_ssh_host=10.0.0.10 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'

[db]
mariadb ansible_ssh_host=10.0.0.8 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'

[web]
LNMP ansible_ssh_host=10.0.0.7 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
web02 ansible_ssh_host=10.0.0.9 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
注:单台定义必须放在组的上方,否则单台会被划分到组内
5)域名定义(单独使用域名定义,域名需要被DNS解析成IP才能访问)
www.wp.com   ansible_ssh_host=10.0.0.7 
6)支持序列(通过hosts解析获得IP)
web[01:02] ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'
7)给组设置变量 在lnmp组中的所有主机共同使用定义好的vars变量
NFS ansible_ssh_host=10.0.0.10 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='wq123456.com'

[db]
mariadb ansible_ssh_host=10.0.0.8 

[web]
LNMP ansible_ssh_host=10.0.0.7 
web02 ansible_ssh_host=10.0.0.9 

[lnmp:children]
db
web

[lnmp:vars]
ansible_ssh_user=root
ansible_ssh_port=22
ansible_ssh_pass='wq123456.com'

三、Ansible常用模块
1.模块使用方法查询
ansible-doc [模块]
2.常用模块
1)file模块(创建、删除目录或文件,更改文件或目录的属主属组和权限)

点击查看代码
file:
  path: file dir
  state: 
       touch    # 创建文件
       directory# 创建目录
       absent   # 删除文件
   owner: www   # 文件的属主
   group: www   # 文件的属组
   mode: 0644   # 文件的权限
案例.创建1个文件1.txt 属主属组为www 权限是0600
ansible webs -m file -a 'path=/root/1.txt state=touch owner=www group=www mode=0600
2)group模块(创建组)
点击查看代码
group:
   name: wq  # 定义小组的名称
   gid: 777    # 小组的gid号
3)user模块(创建用户)
点击查看代码
user:
   name: wq  # 定义用户名
   uid: 777  
   group: wq
   state: present  # 创建
   		  absent   # 删除用户
   remove: yes     # 删除家目录 类似userdel -r 参数
   shell: /sbin/nologin
          /bin/bash
   create_home: true
   				false

案例.创建uid gid 777的wq虚拟用户
ansible webs -m user -a 'name=wq uid=777 group=wq state=present shell=/sbin/nologin create_home=false'
4)systemd模块(启停服务)
点击查看代码
systemd:
	 name: nginx  # 服务名称
	 state: started   # 启动服务
	 		stopped   # 停止服务
	 		restarted # 重启服务
	 		reloaded  # 重新加载
	 enabled: yes  # 开机自动启动
	          no   # 开机禁止运行
	          
案例.停止webs上运行的nginx
[root@m01 ~]# ansible webs -m systemd -a 'name=nginx state=stopped'

5)yum模块(安装服务)
点击查看代码
yum:
  name: wget    # 服务、命令名称
        xxx.rpm # 也可以是本地的rpm包
  state: present  # 安装
  		 absent   # 卸载
  download_only: true  # 只下载不安装
  download_dir: /opt   # 下载到哪个目录
 
案例.安装wget
[root@m01 ~]# ansible webs -m yum -a 'name=wget state=present'
6) command模块(执行命令)
点击查看代码
不建议使用command和shell: 核心原因、违背了 Ansible 的设计哲学、只有在万不得已的情况下使用!
command: 命令

案例.执行df命令
ansible webs -m command -a 'df -h'
7) copy模块(复制)
点击查看代码
copy:
   src: a.txt   # 源文件
   dest: /root/ # 目标路径
   owner: www   # 属主
   group: www   # 文件属组
   mode: 0644   # 文件权限
   backup: yes  # 拷贝前是否需要备份
   content: 字符串 # 将content后面的内容写入到目标文件
案例.将a.txt拷贝webs两台的root家目录
[root@m01 ~]# ansible webs -m copy -a 'src=a.txt dest=/root/'
8)cron模块(定时任务)
点击查看代码
cron:
   name: 时间同步
   minute: 1-59 分钟
   hour:  0-23  小时
   job:  具体执行的命令
案例.创建时间同步定时任务 每分钟执行1次
[root@m01 ~]# ansible webs -m cron -a 'name=时间同步 minute=* hour=* job="ntpdate ntp1.aliyun.com &>/dev/null"'

四、Ansible-ad-hoc快速执行单条命令的临时任务模式
语法:ansible [主机名] -m [模块] -a 'path=[绝对地址] state=[动作]'

五、Ansible-playbook描述在远程主机上执行的策略和步骤,Ansible 的自动化脚本,采用 YAML 格式编写
1.语法:
YAML基本语法规则

规则 描述 实例
缩进 使用空格进行缩进(通常为2个空格),禁止使用制表符 (Tab)。 不同缩进级别表示不同的层级关系。
键值对 使用冒号 : 加空格来分隔键和值。 name: Install Nginx # 冒号后面必须有空格
列表 使用短横线 - 加空格来表示列表项。所有列表项具有相同的缩进级别。
- apple
注释 使用井号 # 来添加注释 # This is a comment
点击查看代码
- hosts: all 			#指定主机(play角色)
  remote_user: root	#用户
  vars:				#变量
    file_name:
  tasks:				#具体动作(tasks剧本)
    - name: touch new files
      shell: touch /tmp/{{file_name}}
扩展名 说明 使用场景
.yml 更常见、更简洁的扩展名 这是 Ansible Playbook 社区中的事实标准和首选。几乎所有 Ansible 示例和文档都使用 .yml。
.yaml 更正式、更完整的扩展名 在某些其他生态系统中可能更受青睐,但在 Ansible 领域远不如 .yml 常见。

语法检测:ansible-playbook --syntax-check b.yml
执行ansible文件:ansible-playbook b.yml

六、变量
1.定义变量

点击查看代码
第一步: 在当前运行playbook的目录下创建两个目录
group_vars   # 在目录下面组名称命名的文件、然后在文件中直接定义变量
hosts_vars   # 在目录下面主机命名的文件,然后在文件中直接定义变量
#第二步: 在group_vars下创建webs文件、all表示所有
[root@m01 ansible]# vim group_vars/webs 
pk1: wget
pk2: tree
#注意all表示所有
[root@m01 ansible]# vim group_vars/all 
pk1: wget
pk2: tree
#第三步: 在playbook中调用变量
[root@m01 ansible]# vim a.yml
- hosts: webs
  tasks:
    - name: Install package
      yum:
        name: 
          - "{{ pk1 }}"
          - "{{ pk2 }}"
        state: absent
2.变量注册(将ansible执行命令的结果赋值给变量,再将变量输出到屏幕)
点击查看代码
- hosts: 10.0.0.7
  tasks:
    - name: list /root/ file 
      command: ls -l /root/
      register: list_file     #变量注册


    - name: print list_file env
      debug:				#输出
        msg: "{{ list_file }}"

#按照层级关系输出我们想要的行 只获取rc的返回值
[root@m01 ansible]# cat a.yml 
- hosts: 10.0.0.7
  tasks:
    - name: list /root/ file 
      command: ls -l /root/
      register: list_file     #变量注册


    - name: print list_file env
      debug:				#输出
        msg: "{{ list_file.rc }}"  #只输出rc行
3.层级定义变量
点击查看代码
层级定义变量:
[root@m01 ansible]# cat vars1.yml 
lnmp:
  nginx:
    pk1: wget
    pk2: tree

调用:
[root@m01 ansible]# cat a.yml 
- hosts: 10.0.0.7
  vars_files: vars1.yml

  tasks:
    - name: Install package
      yum:
        name:
          - "{{ lnmp['nginx']['pk1'] }}"
          - "{{ lnmp['nginx']['pk2'] }}"
        state: absent
4.Facts缓存(查看调用主机信息) ansible [主机] -m setup #查看所有可调用的主机信息和变量
点击查看代码
案例.需求创建出以主机名命名+IP地址的目录
[root@m01 ansible]# cat a.yml 
- hosts: webs
  tasks:
    - name:  create hostname ip dir
      file:
        path: /root/{{ ansible_hostname }}_{{ ansible_default_ipv4.address }}
        state: directory

七、流程控制语句
1.when判断

点击查看代码
[root@m01 ansible]# cat when.yml
- hosts: webs
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
       when: (ansible_hostname == "web01") and (ansible_default_ipv4.address == "10.0.0.7")   #判断语句,都满足则执行

[root@m01 ansible]# cat when.yml 
- hosts: webs
  tasks:
    - name: Install wget
      yum:
        name: wget
        state: present
      when: ( ansible_hostname == "web01") or (ansible_default_ipv4.address == "10.0.0.8")  #判断语句,满足一个则执行

Nginx-when判断实战
点击查看代码
[root@m01 ansible]# cat nginx.yml
- hosts: 10.0.0.8
  tasks:
    - name: Configure Nginx Repo
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes

    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Create Group www
      group:
        name: www
        gid: 666
        state: present

    - name: Create User www
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/

    - name: nginx check to ng_re
      command: nginx -t
      register: ng_re
      ignore_errors: yes  # 当结果错误时候忽略掉、继续向下执行
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted
        enabled: yes
      when: ng_re is search "successful"   # 判断ng_re变量中是否存在successful(search查找)


或者使用其他的返回值作为执行标准
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted
        enabled: yes
      when: ng_re.rc is match "0"  #rc的返回值为0

#when条件表达式
when:  ansible_hostname == "web01"
when:  ansible_hostname is match "web01"
when:  ansible_hostname is search "web01"
ansible_hostname is search "web"   # 只要主机名称有web则运行
ansible_hostname is match "web"    # 只要主机名称有web则运行
#ignore_errors: yes  当tasks执行错误时、忽略继续执行。

八、handlers(监控文件是否被修改,并执行handerlers动作,通过notify触发handler)

点击查看代码
案例: 当nginx.conf配置文件被修改才会触发重启动作、如果不修改则不重启
[root@m01 ansible]# cat nginx.yml
- hosts: 10.0.0.8
  tasks:
    - name: Configure Nginx Repo
      yum_repository:
        name: nginx
        description: Nginx YUM repo
        baseurl: http://nginx.org/packages/centos/7/$basearch/
        gpgcheck: no
        enabled: yes
              
    - name: Install Nginx Server
      yum:
        name: nginx
        state: present

    - name: Create Group www
      group:
        name: www
        gid: 666
        state: present

    - name: Create User www
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false

    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/
      notify: Restart Nginx Server    #监控,触发handlers下的name下的动作

    - name: nginx -t
      command: nginx -t
      register: ng_re
      ignore_errors: yes
      
    - name: Start Nginx Server
      systemd:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: Restart Nginx Server
      systemd:
        name: nginx
        state: restarted
        enabled: yes
      when: ng_re.rc is match "0"

九、循环语句

点击查看代码
创建两个用户
oldboy01 uid gid 778的普通账号
oldboy02 uid gid 779的虚拟账号
[root@m01 ansible]# cat user.yml
- hosts: web02
  tasks:
    - name: Create User
      user: 
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        group: "{{ item.group }}"
        shell: "{{ item.shell }}"       #item指定调用loop下的内容
        create_home: "{{ item.home }}"
        state: present
      loop:
        - { name: wq01,uid: '778',group: wq01,shell: /bin/bash,home: true }
        - { name: wq02,uid: '779',group: wq02,shell: /sbin/nologin,home: false }

十、任务标签(指定运行标签内容)

点击查看代码
默认情况下,Ansible在执行一个playbook时,会执行playbook中定义的所有任务,Ansible的标签(tag)功能可以给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,或不执行指定的任务。


#第一步给一个task打标签
vim nginx.yml
..
    - name: Configure Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/
      notify: Restart Nginx Server
      tags: config

    - name: nginx -t
      command: nginx -t
      register: ng_re
      ignore_errors: yes
      tags: config

...

#第二步: 查看yml中所有的标签
[root@m01 ansible]# ansible-playbook nginx.yml --list-tags

playbook: nginx.yml

  play #1 (web02): web02	TAGS: []
      TASK TAGS: [config]

#第三步: 通过-t指定某个标签运行
[root@m01 m01]# ansible-playbook tag.yml --list-tags  # 查看当前的所有tag
[root@m01 m01]# ansible-playbook tag.yml -t config   # 只运行带有config标签的tasks
[root@m01 m01]# ansible-playbook tag.yml --skip-tags config # 跳过带有config标签的tasks

十 一、文件复用(playbook调用文件中的tasks)

点击查看代码
#需求 nfs服务器上安装nfs服务 web02上安装nginx服务
#第一步准备两个tasks文件
[root@m01 ansible]# cat a.yml
- name: Install nfs Server
  yum:
    name: nfs-utils
    state: present

[root@m01 ansible]# cat b.yml
- name: Install nginx Server
  yum:
    name: nginx
    state: present
      
#第二步: 准备一个文件将上面两个文件包含引入
[root@m01 ansible]# cat all.yml
- hosts: all
  tasks:
    - include_tasks: a.yml         #调用a.yml中的tasks
      when: ansible_hostname is match "nfs"
    - include_tasks: b.yml
      when: ansible_hostname is match "web02"

十二、抑制changed(更改影响执行后的状态标记)
任务总是执行,changed_when只影响执行后的状态标记
颜色变化是状态的可视化,绿色=ok,黄色=changed
handlers只在任务状态为changed时触发
changed_when是判断逻辑,可以基于命令输出、变量、之前任务的结果等
changed_when和when不同:when控制是否执行,changed_when控制执行后的状态

点击查看代码
- name: nginx -t
      command: nginx -t
      register: ng_re
      ignore_errors: yes
      tags: config
      changed_when: false   # 将黄色修改为绿色

十三、template模块(与copy相似但是文件中的变量,可以调用playbook中的变量,文件要以.j2结尾)

点击查看代码
生成负载均衡的配置文件
[root@m01 ansible]# cat lb.conf.j2 
upstream {{ server_name }} {
{% for n in range(7,9) %} 
        server 172.16.1.{{ n }}:{{ up_port }};
{% endfor %}
}

server {
        listen 80;
        server_name {{ server_name }};

        location / {
                root /code;
                index index.html;
                proxy_pass http://{{ server_name }};
                proxy_set_header Host $http_host;
        }
}


拷贝到目标主机
[root@m01 ansible]# cat copy.yml
- hosts: web02
  vars:
    - server_name: www.wp.com
    - up_port: 8080
  tasks:
    - name: copy lb.conf to web02
      template:				#jinja2模块
        src: lb.conf.j2
        dest: /root/lb.conf
十四、Roles角色(将playbook中的动作放到指定目录中去调用)
点击查看代码
ansible-galaxy init backup(通过命令生成一个名为backup的roles目录)

[root@m01 ~]# mkdir roles
[root@m01 ~]# cd roles/
[root@m01 roles]# 
#通过命令生成roles角色目录
[root@m01 roles]# ansible-galaxy init backup
- Role backup was created successfully
#常用的目录
[root@m01 backup]# ll
total 0
drwxr-xr-x 2 root root  6 Aug 29 11:43 files  #文件
drwxr-xr-x 2 root root 22 Aug 29 11:43 handlers  #handlers监控执行的动作
drwxr-xr-x 2 root root 22 Aug 29 11:43 tasks   #动作
drwxr-xr-x 2 root root  6 Aug 29 11:43 templates #jinja模版
drwxr-xr-x 2 root root 22 Aug 29 11:43 vars  #变量

posted on 2025-12-16 12:09    阅读(17)  评论(0)    收藏  举报