ansible-playbook 进阶 接上一章内容

1.异常中断

做法1:强制正常
编写 nginx 的 playbook 文件 01-zuofa .yml

  • hosts : web
    remote_user : root
    tasks :
  • name : create new user
    user : name = nginx-test system = yes uid = 82 shell =/ sbin / nologin
  • name : test new user
    shell : getend passwd | grep nginx-test || /bin/true
    .. .
    注: 在 test new user 任务的 shell 后面添加 || / bin / true
    做法2:忽略错误
    编写 nginx 的 playbook 文件 02-zuofa .yml
  • hosts : web
    remote_user : root
    tasks :
  • name : create new user
    user : name = nginx-test system = yes uid = 82 shell =/ sbin / nologin
  • name : test new user
    shell : getend passwd | grep nginx-test
    ignore errors: true
    .. .
    注: 在 test new user 任务的 shell下面 添加 ignore errors: true

2. 任务依赖

对于这种内容发生更改,服务应该重启的场景,在 playbook 中我们称之为 " 关系依赖 " , playbook 对于这种特殊的关系有两个语法可以满足解决方法的需求:
举例说明:
顺序依赖
安装并启动 Nginx 服务。先执行安装 Nginx 的任务,安装完成后再执行启动 Nginx 的任务。
"Start Nginx" 任务依赖于 "Install Nginx" 任务,只有 Nginx 成功安装后,才尝试启动它。如果不按此顺序,在 Nginx 未安装时就尝试启动,必然会失败。
条件依赖

一个任务是否执行取决于另一个任务的执行结果(成功或失败)。可以通过 when 语句结合任务执行结果的变量来实现。
数据依赖

一个任务需要使用另一个任务的输出数据作为输入。通常通过 register 关键字将一个任务的输出注册到变量,然后在其他任务中引用该变量。

为了解决这个问题,我们需要有⼀种⽅式能解决我们这种存在依赖关系的任务场景。
notify : 监控我们指定的动作涉及的内容是否发生了变化
handlers :接收到变化动作后,我们自动执行的其他操作命令

注:由于notify涉及到的动作是由handlers创建的,在实践过程先写handlers,再在notify中调用
1. 解决依赖[M] 增加了handler下面的内容

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: create new user
      user:
        name: nginx-test
        system: yes
        uid: 82
        shell: /sbin/nologin

    - name: test new user
      shell: getend passwd | grep nginx-test
      ignore_errors: True

    - name: create web root
      file:
        name: /data/webserver/html
        owner: nginx-test
        state: directory

    - name: touch web index
      shell: echo '<h1>welcome to ansible</h1>' > /data/webserver/html/index.html

    - name: install package
      apt:
        name: nginx
        state: present

    - name: copy config
      copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf

    - name: copy subconfig
      copy:
        src: nginx-define.conf
        dest: /etc/nginx/conf.d
      notify: restart nginx

    - name: start service
      service:
        name: nginx
        state: started
        enabled: yes  # 为了掩饰效果,不要改成restart

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

2. 触发多任务

文件名:05-nginx.yml
我们刚才基于 handler 和 notify 的实践实现的是一个 notify 触发一个 handler 的效果,但是生产中肯定会出现一个 notify 触发多个 handler 的效果。
在上面的文件最下面增加了下面的内容

  • name : check nginx
    shell : netstat - tnulp | grep nginx > / tmp / nginx.test
    sed - i 's/10089/10090/g' nginx-define.conf 更改端口
    ansible-playbook 05 - nginx.yml #启动任务
    ansible web -m shell -a "netstat -tnulp | grep nginx" 检查效果

3. 标签

一个 playbook 中有数十个任务,而我们只需要执行其中的一个 这就是标签存在的意义
ansible-playbook --list-tags 文件名 #查看标签
给任务添加标签

给playbook中的拷贝配置⽂件的⼦任务添加标签 假设修改后的文件是06-nginx.yml

sed - i 's/10090/10091/g' nginx-define.conf 修改启动端口
ansible-playbook -- tags copyconfig 06-nginx.yml 重新执⾏ playbook 效果
结果显示:只有指定的 tag 标签的任务被执行了
ansible web -m shell -a "netstat -tnulp | grep nginx" 检查效果

多标签案例实践
清除环境
ansible web - m service - a "name=nginx state=stopped"
ansible web - m yum - a "name=nginx,nginx-common state=absent"
ansible web - m file - a "path=/data/webserver state=absent"
ansible web - m user - a "name=nginx-test state=absent"
修改文件 假设文件名为07-nginx.yml

复制代码
- hosts: web
  tags: host-tags
  remote_user: root
  tasks:
    - name: create new user
      user:
        name: nginx-test
        system: yes
        uid: 82
        shell: /sbin/nologin
      tags: installtask

    - name: test new user
      shell: getend passwd | grep nginx-test
      ignore_errors: True
      tags: installtask

    - name: create web root
      file:
        name: /data/webserver/html
        owner: nginx-test
        state: directory
      tags: installtask

    - name: touch web index
      shell: echo '<h1>welcome to ansible</h1>' > /data/webserver/html/index.html
      tags: installtask

    - name: install package
      yum:
        name: nginx
        state: present
      tags: installtask

    - name: copy config
      copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      tags: installtask

    - name: copy subconfig
      copy:
        src: nginx-define.conf
        dest: /etc/nginx/conf.d
      notify:
        - restart nginx
        - check nginx
      tags:
        - changetask
        - installtask

    - name: start service
      service:
        name: nginx
        state: started
        enabled: yes
      tags: installtask

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

    - name: check nginx
      shell: netstat -tnulp | grep nginx > /tmp/nginx.test

sed - i 's/10091/10086/g' nginx-define.conf #更改端口
ansible-playbook --tags installtask 07-nginx.yml #重新启动执行playbook效果

sed - i 's/10086/10096/g' nginx-define.conf #再次更改端口
ansible-playbook --tags changetask 07 -nginx .yml #重新启动执行playbook效果

4综合实践**[T]**

暂定 未完待续。。。176

5. 变量进阶

ansible all -a "hostname" -o #查看主机名
ansible all -m hostname -a "name=xxx" #修改主机名
需求 想让三台主机的主机名不一样 用ansible如何来实现 例如
10.0.0.12 aaa

10.0.0.15 bbb

10.0.0.18 ccc

变量的多种设定方法
在 ansible 中有很多方式来设定变量,优先级从上到下依次增强。常见的方法有以下几种:
1 目标主机默认的属性
2 主机清单中定义的特有属性 /etc/ansible/hosts
3 playbook 通过 vars 定义的特有属性 例如:主机清单里面 vars的 值名:值变量
4 专用的 YAML 定义的特有属性文件 例:vars.yml 里面文件: qian:A hou:B
5 命令行定义的特定属性 例:ansible/ansible-playbook -e qian=xxx 01-v.yml
定制主机名
ansible 10.0.0.12 -m hostname -a "name=ansible.example.com"


涉及4个属性:ansible_domain 、 ansible_fqdn 、 ansible_hostname 、 ansible_nodename
定制 playbook.yml 文件名为01-v.yml

复制代码
- hosts: all
  remote_user: root
  tasks:
    - name: create file
      file:
        name: /var/log/var-{{ ansible_fqdn }}.log
        state: touch
        owner: daemon

ansible-playbook 01-v.yml #执行
ansible all -m shell -a "ls /var/log/var-* " -o 效果如下

结果显示:可以根据主机属性的方式获取独有的信息

1. 主机列表变量

在 / etc / ansible / hosts 文件中定义主机变量主要有两种样式:公共变量普通变量
普通变量比公共变量的优先级高
普通变量 例如:
10.0.0.12 nginx_port = 83
实践: 文件名02-v.yml

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: set hostname
      hostname:
        name: ansible-{{ name }}.example.com

主机清单下改成这个

ansible web -m shell -a "hostname" -o 得到下面的结果

公共(组) 变量例如:

web_group : vars

hostname = www
实践: 文件名03-v.yml
主机清单下改成这个

编写⼀个设定主机名的任务 03-v.yml

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: set hostname
      hostname: name={{ qian }}-{{ name }}{{ hou }}

nsible web -m shell -a "hostname" -o 得到下面的结果

2. 命令行

ansible命令
ansible 目标主机 - e 变量名 = 变量值 - m 模块 - a " 可执行命令 "
ansible 目标主机 - e ' 变量名 = 变量值 变量名 = 变量值 ' - m 模块 - a " 可执行命令 "
注意:可以直接设定多个环境变量名,彼此之间使用空格隔开,外侧使用单引号扩住即可。
ansible-playbook命令
ansible-playbook - e 变量名 = 变量值 playbook.yaml
ansible 命令设定变量
设定所有主机的 ip 地址
ansible web -e hou='.ansible.org' -m hostname -a "name={{ qian }}-{{ name }}{{ hou }}"
ansible web -m shell -a "hostname" -o 效果如下

3. playbook实践

执行playbook 的时候,设定 qian 的值为bushiba
ansible-playbook - e qian=bushiba 02-v.yml
ansible web -m shell -a "hostname" -o #效果如下

4. playbook变量基础

vars 格式

  • hosts : web
    remote_user : root
    vars :

  • 变量名 : 变量值
    .. .
    playbook 中专门设置变量的属性叫 vars
    vars 中的变量是以列表的形式展示的
    每一个变量都是以 " 变量名 : 变量值 " 的格式来展示的。
    vars应用 文件名04-v.yml

    • hosts: web
      remote_user: root
      vars:
      • head: ni
      • hostid: hao
      • tail: .shuai.com
        tasks:
      • name: set hostname
        hostname:
        name: "{{ qian }}-{{ name }}{{ hou }}"

出来的结果不是想要的结果 疑? 待解决
ansible-playbook 04-v.yml 执行
ansible web -m shell -a "hostname" -o #查看结果

-e 设定的环境变量优先级高
ansible-playbook - e qian =nene 04 - v.yml

文件变量实践
在 playbook.yaml ⽬录下创建专⽤变量⽂件
vim vars.yaml
qian : A
hou : .B
定制plybook文件 文件名06-v.yml

复制代码
- hosts: web
 remote_user: root
 vars_files:
   
- vars.yaml
 vars:
   
- head: www
   
- tail: .ansible.top
 tasks:
   
- name: set hostname
     hostname: name={{ qian }}-{{ name }}{{ hou }}

ansible web -a "hostname" -o 查看效果

6. 模板

Jinja2 是一种现代的、设计友好的 Python 模板语言,而 Ansible 作为自动化运维工具,大量使用 Jinja2 来处理配置文件、动态生成内容和实现复杂的逻辑控制。
在 Ansible 中, Jinja2 模板主要用于
使用 template 模块生成动态配置文件
在 playbook 中使用 {{ }} 语法进行变量插值
在 when 条件语句中使用 Jinja2 表达式
在循环 (with_items, with_dict 等 ) 中处理复杂数据结构
清理之前的环境
ansible web - m service - a "name=nginx state=stopped"
ansible web - m yum - a "name=nginx,nginx-common state=absent"
ansible web - m file - a "path=/data/webserver state=absent"
ansible web - m user - a "name=nginx-test state=absent"
案例实践

  1. 准备基准配置⽂件
    mkdir / data / ansible / playbook / templates / templates - p
    cd / data / ansible / playbook / templates
    2.定制主机清单
    10.0.0.12 nginx_port = 81
    10.0.0.15 nginx_port = 82
    10.0.0.18 nginx_port = 83
    3.改造基准配置文件
    vim templates/nginx-define.conf.j2

    server {
    listen {{ nginx_port }};
    root /data/webserver/html;

    复制代码
     location / {
     }

    }

4.改造playbook.yaml
vim /data/ansible/playbook/templates/01-template.yml

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: install package
      yum:
        name: nginx
        state: present

    - name: create web root
      file:
        name: /data/webserver/html
        state: directory

    - name: touch web index
      shell: echo '<h1>welcome to ansible</h1>' > /data/webserver/html/index.html

    - name: delete default nginx conf
      file:
        name: /etc/nginx/sites-enabled/default
        state: absent

    - name: copy config
      template:
        src: ./templates/nginx-define.conf.j2
        dest: /etc/nginx/conf.d/nginx-define.conf
      notify:
        - restart nginx

    - name: start service
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

注:上面的文件只是将 copy 模块更改为了 template 模块
src 如果采用相对路径的话,其 根路径就是 playbook.yaml 所在目录

实践后期出现这个报错,但是01-template.yml 格式是正确的 原因是nginx有残留

做法:在每台主机上都yum autoremove 一下 清理掉nginx残存的东西

得到下面的结果


清理环境
ansible web - m service - a "name=nginx state=stopped"
ansible web - m yum - a "name=nginx,nginx-common state=absent"
ansible web - m file - a "path=/data/webserver state=absent"

1.条件管理

复制代码
在ansible动态生成配置文件的场景中,when语句可以对变量facts的值进行条件判断,从而实现不同的效果。
- hosts: web
  remote_user: root
  tasks:
    - name: install package
      apt: name=nginx state=present
      when: ansible_os_family == "RedHat"

位置: when 语句是针对条件判断是否执行动作的,所以他是 task 下面的一条配置项
格式: when : 条件对象 判断操作符 判断值
内容: when 语句中的条件对象可以是变量、 Facts 、命令结果等
判断: when 语句中的条件判断操作符可以是以下几种类型:
算术运算 + , - , , / , // , % , * 等
比较操作 == , != , > , >= , < , <= 等
逻辑运算 and, or, not, ( 表达式组 )
代码示例

满足多个条件

tasks :

  • name : "shut down CentOS 6 systems"
    command : / sbin / shutdown - t now
    when :
  • ansible_facts[ 'distribution' ] == "CentOS"
  • ansible_facts[ 'distribution_major_version' ] == "6"

判断某个变量是否存在信息 is defined

  • name : Configure database connection
    template :
    src : db_config.j2
    dest : / etc / db.conf
    when : db_password is defined
    案例实践 [ M ] 文件名02-when.yml

    • hosts: web
      remote_user: root
      tasks:

      • name: ps_check
        shell: ps -ef | grep nginx | grep -v grep | wc -l
        register: nginx_num
        changed_when: false
        ignore_errors: true

      • name: print debug message
        debug:
        msg: "System {{ inventory_hostname }} has nginx service."
        when: nginx_num.stdout != "0"

      • name: install package
        yum:
        name: nginx
        state: present
        when: nginx_num.stdout == "0"

      • name: create web root
        file:
        name: /data/webserver/html
        state: directory

      • name: touch web index
        shell: echo '

        welcome to ansible

        ' > /data/webserver/html/index.html

      • name: delete default nginx conf
        file:
        name: /etc/nginx/sites-enabled/default
        state: absent

      • name: copy config
        template:
        src: ./templates/nginx-define.conf.j2
        dest: /etc/nginx/conf.d/nginx-define.conf
        notify:

        • restart nginx
      • name: start service
        service:
        name: nginx
        state: started
        enabled: yes

      handlers:

      • name: restart nginx
        service:
        name: nginx
        state: restarted

ansible-playbook 02-when.yml - l 10.0.0.12
ansible-playbook 02-when.yml - l 10.0.0.15
ansible web -m shell -a "netstat -tnulp | grep nginx" 测试结果如下

清楚环境
ansible web - m service - a "name=nginx state=stopped"
ansible web - m yum - a "name=nginx,nginx-common state=absent"
ansible web - m file - a "path=/data/webserver state=absent"
ansible web - m user - a "name=nginx-test state=absent"

2.迭代管理

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: add usergroup
      group:
        name: webgroup
        state: present

    - name: add several users
      user:
        name: "{{ item }}"
        state: present
        groups: webgroup
      with_items:
        - testuser1
        - testuser2

即:在所有主机上都重复创建两个用户
ansible web -m shell -a "getent passwd | grep testu"
ansible web -m shell -a "getent group | grep testu"

所有主机上的用户都是两个,而且都加入到了 wheel 组。
清空环境
ansible web - m user - a "name=testuser1,testuser2,webgroup state=absent"
ansible web - m group - a "name=testuser1,testuser2,webgroup state=absent"
扩展 特定主机 安装软件实践

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: install package
      yum:
        name: "{{ item }}"
        state: present
      with_items:
        - 'nginx'
        - 'redis'
        - 'mariadb-server'

如果安装不成功的话,原因之一就是:远程主机上有对应的软件,需要把远程主机的软件移除即可
ansible web - m yum - a "name=nginx,redis,mariadb-server state=absent"
3.多值迭代需求[M]

复制代码
- hosts: web
  remote_user: root
  tasks:
    - name: add some group
      user:
        name: "{{ item }}"
        state: present
      with_items:
        - group1
        - group2
        - group3

    - name: add some users
      user:
        name: "{{ item.name }}"
        group: "{{ item.group }}"
        state: present
      with_items:
        - { name: 'user1', group: 'group1' }
        - { name: 'user2', group: 'group2' }
        - { name: 'user3', group: 'group3' }

ansible 10.0.0.15 -m shell -a "id user1"

清空环境
for i in user{ 1..3 } group { 1..3 } ; do ansible web - m user - a "name= $i state=absent" ; done

3.流程语法解析

{{ }} 用于表达式,比如变量、表达式等
{ % % } 用于控制语句,比如 if 、 for 等语句结构
{ # #} 用于注释,当模板文件被渲染后,该部分内容不会被显示

相关推荐
2401_8368365916 分钟前
Haproxy搭建web群集
运维·服务器
C墨羽22 分钟前
服务器间文件传输
运维·服务器·网络
孞㐑¥1 小时前
Linux之进程间通信
linux·c++·经验分享·笔记
yan123686 小时前
Linux 驱动之设备树
android·linux·驱动开发·linux驱动
吐泡泡_6 小时前
进程间通信(消息队列)
linux
Li-Yongjun8 小时前
5G-A:开启通信与行业变革的新时代
运维·服务器·5g
待什么青丝8 小时前
【Ubuntu】摸鱼技巧之虚拟机环境复制
linux·运维·ubuntu
Demisse8 小时前
[MongoDB] 认识MongoDB以及在Windows和Linux上安装MongoDB
linux·windows·mongodb
独行soc9 小时前
2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)
linux·安全·web安全·面试·职场和发展·渗透测试
LB21129 小时前
Maven(黑马)
linux·服务器·maven