侧边栏壁纸
博主头像
运维匠-运维工程师知识分享经验和最佳实践博主等级

生活百般滋味,人生需要笑对

  • 累计撰写 60 篇文章
  • 累计创建 3 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Ansible2

运维匠
2023-07-19 / 0 评论 / 0 点赞 / 10 阅读 / 47792 字
温馨提示:
本文最后更新于 2024-07-15,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

运维自动化工具Ansible(二)

Playbook

playbook介绍

官方链接

https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html

Playbook 组成

1677299110747

  • 一个 playbook(剧本)文件是一个YAML语言编写的文本文件
  • 通常一个playbook只包括一个play
  • 一个 play的主要包括两部分: 主机和tasks. 即实现在指定一组主机上执行一个tasks定义好的任务列表。
  • 一个tasks中可以有一个或多个task任务
  • 每一个Task本质上就是调用ansible的一个module
  • 在复杂场景中,一个playbook中也可以包括多个play,实现对多组不同的主机执行不同的任务

Playbook 与 Ad-Hoc 对比

  • Playbook是对多个 AD-Hoc 的一种编排组合的实现方式
  • Playbook能控制任务执行的先后顺序
  • Playbook可以持久保存到文件中从而方便多次调用运行,而Ad-Hoc只能临时运行。
  • Playbook适合复杂的重复性的任务,而Ad-Hoc适合做快速简单的一次性任务

YAML 语言

YAML 语言介绍

YAML:YAML Ain't Markup Language,即YAML不是标记语言。不过,在开发的这种语言时,YAML的
意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
YAML是一个可读性高的用来表达资料序列的格式。
YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。
Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者
目前很多最新的软件比较流行采用此格式的文件存放配置信息,如:ubuntu,anisble,docker,kubernetes等
YAML 官方网站:

http://www.yaml.org

ansible 官网:

https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

YAML 语言特性

  • YAML的可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现
  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

YAML语法简介

  • 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件结尾
  • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
  • 使用#号注释代码
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结行来实现的
  • 缩进不支持tab,必须使用空格进行缩进
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • YAML文件内容是区别大小写的,key/value的值均需大小写敏感
  • 多个key/value可同行写也可换行写,同行使用,分隔
  • key后面冒号要加一个空格 比如: key: value
  • value可是个字符串,也可是另一个列表
  • YAML文件扩展名通常为yml或yaml

支持的数据类型

YAML 支持以下常用几种数据类型:

  • 标量:单个的、不可再分的值
  • 对象:键值对的集合,又称为: 字典(dictionary)/ 哈希(hashes) / 映射(mapping)
  • 数组:一组按次序排列的值,又称为: 列表(list)/ 序列(sequence)

scalar 标量

key对应value

name: wang
age: 18

使用缩进的方式

name:
wang
age:
18

标量是最基本的,不可再分的值,包括:

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期

Dictionary 字典

一个字典是由一个或多个key与value构成
key和value之间用冒号 :分隔
冒号 : 后面有一个空格
所有 k/v 可以放在一行,,每个 k/v 之间用逗号分隔
所有每个 k/v 也可以分别放在不同行,一对k/v放在独立的一行
格式

account: { name: wang, age: 30 }

使用缩进方式

account:
name: wang
age: 18

范例:

#不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite(社会精英)
#同一行,也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: "Example Developer", job: "Developer", skill: "Elite"}

List 列表

列表由多个元素组成
每个元素放在不同行,每个元素一行,且元素前均使用中横线 - 开头,并且中横线 - 和元素之间有一个空格
也可以将所有元素用 [ ] 括起来放在同一行,每个元素之间用逗号分隔
格式

course: [ linux , golang , python ]

也可以写成以 - 开头的多行

course:
- linux
- golang
- python
course:
- linux: manjaro
- golang: gin
- python: django

范例:

#不同行,行以-开头,后面有一个空格
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#同一行
[Apple,Orange,Strawberry,Mango]

范例:YAML 表示一个家庭

name: John Smith
age: 41
gender: Male
spouse: { name: Jane Smith, age: 37, gender: Female } # 写在一行里
  name: Jane Smith #也可以写成多行
  age: 37
  gender: Female
  children: [ {name: Jimmy Smith,age: 17, gender: Male}, {name: Jenny Smith, age:13, gender: Female}, {name: hao Smith, age: 20, gender: Male } ] #写在一行
  - name: Jimmy Smith #写在多行,更为推荐的写法
    age: 17
    gender: Male
  - {name: Jenny Smith, age: 13, gender: Female}
  - {name: hao Smith, age: 20, gender: Male }

三种常见的数据格式

  • XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
  • JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
  • YAML:YAML Ain't Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab

1677310138888

可以用工具互相转换,参考网站:

url
url1

Playbook 核心组件

官方文档

https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywords

一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:

  • Hosts 执行的远程主机列表
  • Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需少元素需包括 name 和 task,一个name只能包括一个task
  • Variables 内置变量或自定义变量在playbook中调用
  • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此 会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

hosts 组件

Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集
Websrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组

案例:

- hosts: websrvs:appsrvs

remote_user 组件

remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户

- hosts: websrvs
  remote_user: root
  tasks:
    - name: test connection
    ping:
    remote_user: magedu
    sudo: yes #默认sudo为root
    sudo_user:wang #sudo为wang

task列表和action组件

play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。
如果未提供name,则action的结果将用于输出
task两种格式:

action: module arguments #示例: action: shell wall hello
module: arguments #建议使用 #示例: shell: wall hello

注意:shell和command模块后面跟命令,而非key=value
范例:

[root@ansible ansible]#cat hello.yml
---
#first yaml文件
#
- hosts: websrvs
  remote_user: root
  gather_facts: no
  tasks:
    - name: task1
      debug: msg="task1 running"
    - name: task2
      debug: msg="task2 running"
- hosts: appsrvs
  remote_user: root
  gather_facts: no
  tasks:
    - name: task3
      debug: msg="task3 running"
    - name: task4
      debug: msg="task4 running"

其它组件说明

某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers任务
还可以通过"tags"给task 打标签,可在ansible-playbook命令上使用-t指定进行调用

ShellScripts VS Playbook 案例

#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#Playbook实现
---
- hosts: websrvs
  remote_user: root
  gather_facts: no
  tasks:
  - name: "安装Apache"
    yum: name=httpd
  - name: "复制配置文件"
  copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
  - name: "复制配置文件"
  copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
  - name: "启动Apache,并设置开机启动"
  service: name=httpd state=started enabled=yes

playbook 命令

格式

ansible-playbook <filename.yml> ... [options]

选项

--syntax,--syntax-check #语法检查,功能相当于bash -n
-C --check #模拟执行dry run ,只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY, --inventory INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的name
-v -vv -vvv #显示过程

范例: 一个简单的 playbook

[root@ansible ansible]#cat hello.yml
---
- hosts: websrvs
  tasks:
    - name: hello
      command: echo "hello ansible"
[root@ansible ansible]#ansible-playbook hello.yml
[root@ansible ansible]#ansible-playbook -v hello.yml

范例: 检查和限制主机

ansible-playbook file.yml --check #只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs

范例: 一个playbook 多个play

cat test_plays.yaml
---
- hosts: localhost
  remote_user: root
  gather_facts: no
  tasks:
    - name: play1
      command: echo "play1"
- hosts: centos7
  remote_user: root
  gather_facts: no
  tasks:
    - name: play2
      command: echo "play2"

忽略错误 ignore_errors

如果一个task出错,默认将不会继续执行后续的其它task
利用 ignore_errors: yes 可以忽略此task的错误,继续向下执行playbook其它task

[root@ansible ansible]#cat test_ignore.yml
---
- hosts: centos7
  tasks:
    - name: error
      command: /bin/false
      ignore_errors: yes
    - name: continue
      command: wall continue

ansible-playbook案例

安装nginx

---
- hosts: centos7
# yum install nginx
  remote_user: root
  gather_facts: no
  tasks:
    - name: install nginx
      yum: name=nginx state=present
    - name:
      service: name=nginx state=started enabled=yes

卸载httpd

#remove_httpd.yml
---
- hosts: webservers
  remote_user: root
  gather_facts: no
  tasks:
  - name: remove httpd package
    yum: name=httpd state=absent
  - name: remove apache user
    user: name=apache state=absent
  - name: remove config file
    file: name=/etc/httpd state=absent
  - name: remove web html
    file: name=/data/html/ state=absent

Playbook中使用handlers和notify

handlers和notify

Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,只有在关注的资源发生变化时,才会采取一定的操作。
Notify对应的action 在所有task都执行完才会最后被触发,这样可避免多个task多次改变发生时每次都触发执行指定的操作,Handlers仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:

  • 如果多个task通知了相同的handlers, 此handlers仅会在所有task结束后运行一 次。
  • 只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
  • handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handle跳过执行

案例:

1677315798458

1677315812687

案例:

1677315839869

案例:

1677315862982

1677315872464

范例: 部署haproxy

1677315902745

force_handlers

如果不论前面的task成功与否,都希望handlers能执行, 可以使用force_handlers: yes 强制执行handler
范例: 强制调用handlers

1677315975960

Playbook中使用tags组件

官方文档:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html

默认情况下, Ansible 在执行一个 playbook 时,会执行 playbook 中所有的任务,在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件
可以一个task对应多个tag,也可以多个task对应同一个tag
还有另外3个特殊关键字用于标签, tagged, untagged 和 all,它们分别是仅运行已标记,只有未标记和所有任务。
tags 主要用于调试环境
范例: tag 标签

1677316033321

Playbook中使用变量

Playbook中同样也支持变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量定义:

variable=value
variable: value

范例:

http_port=80
http_port: 80

通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
变量来源:

  1. ansible 的 setup facts 远程主机的所有变量都可直接调用
  2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml

3.在playbook文件中定义

vars:
var1: value1
var2: value2

4.在独立的变量YAML文件中定义

- hosts: all
vars_files:
- vars.yml

在主机清单文件中定义
主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
组(公共)变量:针对主机组中所有主机定义统一变量
在项目中针对主机和主机组定义
在项目目录中创建 host_vars和group_vars目录
在role中定义

变量的优先级从高到低如下

-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组变量

使用 setup 模块中变量

使用 facts 变量

本模块自动在playbook调用,生成的系统状态信息, 并将之存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等
facts 变量的实际使用场景案例

  • 通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
  • 通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
  • 通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
  • 通过facts变量获取被控端网卡信息,从而生成不同的主机名

案例:使用setup变量

[root@ansible ~]# ansible localhost -m setup -a 'filter="ansible_default_ipv4"'
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "192.168.32.133",
            "alias": "ens160",
            "broadcast": "192.168.32.255",
            "gateway": "192.168.32.2",
            "interface": "ens160",
            "macaddress": "00:0c:29:7c:80:cd",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.32.0",
            "prefix": "24",
            "type": "ether"
        }
    },
    "changed": false
}
[root@ansible ~]# 

范例:显示ens33的网卡的IP地址

---
- hosts: centos7
  tasks:
    - name: show ens33 ip
      debug:
        msg: IP address {{ ansible_ens33.ipv4.address }}
        #msg: IP address {{ ansible_facts["ens33"]["ipv4"]["address"] }}
        #msg: IP address {{ ansible_facts.ens33.ipv4.address }}
        #msg: IP address {{ ansible_default_ipv4.address }}
        #msg: IP address {{ ansible_ens33.ipv4.address }}
        #msg: IP address {{ ansible_ens33.ipv4.address.split('.')[-1] }}  #取IP中的最后一个数字
[root@ansible ansible]# ansible-playbook -v show_ip.yml 
Using /etc/ansible/ansible.cfg as config file

PLAY [centos7] *************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [192.168.32.179]
ok: [192.168.32.178]

TASK [show ens33 ip] *******************************************************************************************************************
ok: [192.168.32.178] => {
    "msg": "IP address 192.168.32.178"
}
ok: [192.168.32.179] => {
    "msg": "IP address 192.168.32.179"
}

PLAY RECAP *****************************************************************************************************************************
192.168.32.178             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.32.179             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]# 

范例:修改主机名称为web-IP

- hosts: centos7
  tasks:
  - name: 打印facts变量
    debug: msg={{ ansible_ens33.ipv4.address }}
  - name: 修改主机名
    hostname: name=web-{{ ansible_ens33.ipv4.address }}
  #- name: 获取facts变量提取IP地址,以.结尾的最后一列,修改主机名为web-hostid
    #hostname: name=web-{{ ansible_ens33.ipv4.address.split('.')[-1] }}
[root@ansible ansible]# ansible-playbook change_hostname.yml 

PLAY [centos7] *************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [192.168.32.178]
ok: [192.168.32.179]

TASK [打印facts变量] *******************************************************************************************************************
ok: [192.168.32.178] => {
    "msg": "192.168.32.178"
}
ok: [192.168.32.179] => {
    "msg": "192.168.32.179"
}

TASK [修改主机名] **********************************************************************************************************************
changed: [192.168.32.179]
changed: [192.168.32.178]

PLAY RECAP *****************************************************************************************************************************
192.168.32.178             : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.32.179             : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]# 

性能优化

每次执行playbook,默认会收集每个主机的所有facts变量,将会导致速度很慢,可以采用下面方法加速
方法1
关闭facts采集加速执行,此方法将导致无法使用facts变量

- hosts: all
  gather_facts: no

方法2
当使用 gather_facts: no 关闭 facts,确实能加速 Ansible 执行,但是有时候又需要使用 facts 中的内容,还希望执行的速度快,这时候可以设置facts 的缓存,将facts变量信息存在redis服务器中

[root@ansible ~]# cat /etc/ansible/ansible.cfg
[defaults]
# smart 表示默认收集 facts,但 facts 已有的情况下不会收集,即使用缓存 facts
# implicit 表示默认收集 facts,要禁止收集,必须使用 gather_facts: False
# explicit 则表示默认不收集,要显式收集,必须使用gather_facts: True
gathering = smart #在使用 facts 缓存时设置为smart
fact_caching_timeout = 86400 #缓存时长
fact_caching = redis #缓存存在redis中
fact_caching_connection = 10.0.0.100:6379:0 #0表示redis的0号数据库
#若redis设置了密码
fact_caching_connection = 10.0.0.100:6379:0:password

register 注册变量

在playbook中可以使用register将捕获命令的输出保存在临时变量中,方便后续调用此变量,比如可以使用debug模块进行显示输出
范例: 利用debug 模块输出变量

---
- hosts: centos7
  tasks:
    - name: get variable
      shell: hostname
      register: name
    - name: print variable
      debug:
        msg: "{{ name }}" #输出register注册的name变量的全部信息,注意变量要加" "引起来
         #msg: "{{ name.cmd }}" #显示命令
         #msg: "{{ name.rc }}" #显示命令成功与否
   #msg: "{{ name.stdout }}" #显示命令的输出结果为字符串形式,所有结果都放在一行里显示,适合于结果是单行输出
      #msg: "{{ name.stdout_lines }}" #显示命令的输出结果为列表形式,逐行标准输出,适用于多行显示
    #msg: "{{ name['stdout_lines'] }}" #显示命令的执行结果为列表形式,和效果上面相同
    #msg: "{{ name.stdout_lines[0] }}" #显示命令的输出结果的列表中的第一个元素
#说明 第一个 task 中,使用了 register 注册变量名为 name ;当 shell 模块执行完毕后,会将数据放到该变量中。第二给 task 中,使用了 debug 模块,并从变量name中获取数据。
[root@ansible ansible]# ansible-playbook -C register.yml 

PLAY [centos7] *************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [192.168.32.179]
ok: [192.168.32.178]

TASK [get variable] ********************************************************************************************************************
skipping: [192.168.32.179]
skipping: [192.168.32.178]

TASK [print variable] ******************************************************************************************************************
ok: [192.168.32.178] => {
    "msg": {
        "changed": false,
        "cmd": "hostname",
        "delta": null,
        "end": null,
        "failed": false,
        "msg": "Command would have run if not in check mode",
        "rc": 0,
        "skipped": true,
        "start": null,
        "stderr": "",
        "stderr_lines": [],
        "stdout": "",
        "stdout_lines": []
    }
}
ok: [192.168.32.179] => {
    "msg": {
        "changed": false,
        "cmd": "hostname",
        "delta": null,
        "end": null,
        "failed": false,
        "msg": "Command would have run if not in check mode",
        "rc": 0,
        "skipped": true,
        "start": null,
        "stderr": "",
        "stderr_lines": [],
        "stdout": "",
        "stdout_lines": []
    }
}

PLAY RECAP *****************************************************************************************************************************
192.168.32.178             : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
192.168.32.179             : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

[root@ansible ansible]# 

范例: 安装启动服务并检查

---
- hosts: centos7
  vars:
    package_name: nginx
    service_name: nginx
  tasks:
  - name: install {{ package_name }}
    yum: name={{ package_name }}
  - name: start {{ service_name }}
    service: name={{ service_name }} state=started enabled=yes
  - name: check
    shell: ps axu|grep {{ service_name }}
    register: check_service
  - name: debug
    debug:
      msg: "{{ check_service.stdout_lines }}"

范例: 修改主机名形式为 web_<随机字符>

- hosts: centos7
  tasks:
  - name: genarate random
    shell:
      cmd: openssl rand -base64 12 |tr -dc '[:alnum:]'
    register:
      num
  - name: show random
    debug:
      msg: "{{ num }}"
  - name: change hostname
    hostname:
      name: web-{{ num.stdout }}

范例: 修改主机名形式为 web_随机数

- hosts: centos7
  tasks:
  - name: 定义一个随机数,设定为变量,然后后续调用
    shell: echo $((RANDOM%255))
    register: web_number
  - name: 使用debug输出变量结果
    debug: msg={{ web_number }}
  - name: 使用hostname模块将主机名修改为web_随机数
    hostname: name=web_{{ web_number.stdout }}

范例: 批量修改主机名为随机字符

- hosts: centos7
  vars:
    host: web
    domain: wang.org
  tasks:
  - name: get variable
    shell: echo $RANDOM | md5sum | cut -c 1-8
    register: get_random
  - name: print variable
    debug:
      msg: "{{ get_random.stdout }}"
  - name: set hostname
    hostname: name={{ host }}-{{ get_random.stdout }}.{{ domain }}

范例: 批量修改主机名为IP最后1位数字

- hosts: centos7
  vars:
    host: web
    domain: wang.org
  tasks:
    - name: get variable
      shell: hostname -I | awk '{print $1}'
      register: get_ip
    - name: print variable
      debug:
        msg: "{{ get_ip.stdout.split('.')[3] }}"
    - name: set hostname
      hostname: name={{ host }}-{{ get_ip.stdout.split('.')[3] }}.{{ domain }}

在 Playbook 命令行中定义变量

范例:

---
- hosts: centos7
  remote_user: root
  tasks:
  - name: install nginx
    yum: name={{ pkname }} state=present
    
    
[root@ansible ~]#ansible-playbook -e pkname=nginx var2.yml

范例:

#也可以将多个变量放在一个文件中
[root@ansible ~]#cat vars
pkname1: memcached
pkname2: vsftpd
[root@ansible ~]#vim var2.yml
---
- hosts: centos7
  remote_user: root
  tasks:
  - name: install package {{ pkname1 }
    yum: name={{ pkname1 }} state=present
  - name: install package {{ pkname2 }
    yum: name={{ pkname2 }} state=present
[root@ansible ~]#ansible-playbook -e pkname1=memcached -e pkname2=httpd var2.yml
[root@ansible ~]#ansible-playbook -e '@vars' var2.yml

在playbook文件中定义变量

此方式定义的是私有变量,即只能在当前playbook中使用,不能被其它Playbook共用
范例:

- hosts: webservers
  remote_user: root
  vars:
    username: user1
    groupname: group1
  tasks:
  - name: create group {{ groupname }}
    group: name={{ groupname }} state=present
  - name: create user {{ username }}
    user: name={{ username }} group={{ groupname }} state=present
    
[root@ansible ~]#ansible-playbook -e "username=user2 groupname=group2" var3.yml

范例:变量的相互调用

---
- hosts: centos7
  remote_user: root
  vars:
    collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"
  tasks:
  - name: create IP directory
    file: name="{{collect_info}}" state=directory

使用专用的公共的变量文件

可以在一个独立的playbook文件中定义公共变量,在其它的playbook文件中可以引用变量文件中的变量
此方式比playbook中定义的变量优化级高

vim vars.yml
---
# variables file
package_name: mariadb-server
service_name: mariadb

vim var5.yml
---
#install package and start service
- hosts: dbsrvs
  remote_user: root
  vars_files:
  # 指定变量文件名
    - vars.yml
  tasks:
  - name: install package
    yum: name={{ package_name }}
    tags: install
  - name: start service
    service: name={{ service_name }} state=started enabled=yes

在主机清单中定义主机和主机组的变量

所有项目的主机变量

在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用
范例:

[webservers]
www1.wang.org http_port=80 maxRequestsPerChild=808
www2.wang.org http_port=8080 maxRequestsPerChild=909

所有项目的组(公共)变量

在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量

案例:

[webservers:vars]
http_port=80
ntp_server=ntp.wang.org
nfs_server=nfs.wang.org
[all:vars]
# --------- Main Variables ---------------
# Cluster container-runtime supported: docker, containerd
CONTAINER_RUNTIME="docker"
# Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
CLUSTER_NETWORK="calico"
# Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
PROXY_MODE="ipvs"
# K8S Service CIDR, not overlap with node(host) networking
SERVICE_CIDR="192.168.0.0/16"
# Cluster CIDR (Pod CIDR), not overlap with node(host) networking
CLUSTER_CIDR="172.16.0.0/16"
# NodePort Range
NODE_PORT_RANGE="20000-60000"
# Cluster DNS Domain
CLUSTER_DNS_DOMAIN="magedu.local."

范例:

[root@ansible ~]#vim /etc/ansible/hosts
[webservers]
10.0.0.8 hname=www1 domain=magedu.io
10.0.0.7 hname=www2
[webservers:vars]
mark="-"
[all:vars]
domain=wang.org
[root@ansible ~]#ansible webservers -m hostname -a 'name={{ hname }}{{ mark }}
{{ domain }}'
#命令行指定变量:
[root@ansible ~]#ansible webservers -e domain=magedu.cn -m hostname -a 'name=
{{ hname }}{{ mark }}{{ domain }}'

针对当前项目的主机和主机组的变量

上面的方式是针对所有项目都有效,而官方更建议的方式是使用ansible特定项目的主机变量和组变量.生产建议在每个项目对应的目录中创建额外的两个变量目录,分别是host_vars和group_vars

  • host_vars下面的文件名和主机清单主机名一致,针对单个主机进行变量定义格式:host_vars/hostname
  • group_vars下面的文件名和主机清单中组名一致, 针对单个组进行变量定义格式: group_vars/groupname
  • group_vars/all文件内定义的变量对所有组都有效

范例: 特定项目的主机和组变量

[root@ansible ansible]#pwd
/data/ansible
[root@ansible ansible]#mkdir host_vars
[root@ansible ansible]#mkdir group_vars
[root@ansible ansible]#cat host_vars/10.0.0.8
id: 2
[root@ansible ansible]#cat host_vars/10.0.0.7
id: 1
[root@ansible ansible]#cat group_vars/webservers
name: web
[root@ansible ansible]#cat group_vars/all
domain: wang.org
[root@ansible ansible]#tree host_vars/ group_vars/
host_vars/
├── 10.0.0.7
└── 10.0.0.8
group_vars/
├── all
└── webservers
0 directories, 4 files
[root@ansible ansible]#cat test.yml
- hosts: webservers
tasks:
- name: get variable
command: echo "{{name}}{{id}}.{{domain}}"
register: result
- name: print variable
debug:
msg: "{{result.stdout}}"
[root@ansible ansible]#ansible-playbook test.yml
PLAY [webservers]
********************************************************************************
***************************************
TASK [Gathering Facts]
********************************************************************************
*******************************
ok: [10.0.0.7]
ok: [10.0.0.8]
TASK [get variable]
********************************************************************************
**********************************
changed: [10.0.0.7]
changed: [10.0.0.8]
TASK [print variable]
********************************************************************************
********************************
ok: [10.0.0.7] => {
"msg": "web1.wang.org"
}
ok: [10.0.0.8] => {
"msg": "web2.wang.org"
}
PLAY RECAP
********************************************************************************
*******************************************
10.0.0.7 : ok=3 changed=1 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0
10.0.0.8 : ok=3 changed=1 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

Template 模板

模板是一个文本文件,可以用于根据每个主机的不同环境而为生成不同的文件
模板文件中支持嵌套jinja2语言的指令,来实现变量,条件判断,循环等功能
需要使用template模块实现文件的复制到远程主机,但和copy模块不同,复制过去的文件每个主机可以会有所不同

jinja2语言

1677662324156

Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:
特性:

  • 沙箱中执行
  • 强大的 HTML 自动转义系统保护系统免受 XSS
  • 模板继承
  • 及时编译最优的 python 代码
  • 可选提前编译模板的时间
  • 易于调试。异常的行数直接指向模板中的对应行。
  • 可配置的语法

官方网站:

http://jinja.pocoo.org/
https://jinja.palletsprojects.com/en/2.11.x/

官方中文文档

http://docs.jinkan.org/docs/jinja2/
https://www.w3cschool.cn/yshfid/

jinja2 语言支持多种数据类型和操作:
字面量,如: 字符串:使用单引号或双引号,数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=

逻辑运算:and,or,not
流表达式:For,If,When

字面量:
表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。如"Hello World"
双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23
数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在 Python 里, 42 和 42.0 是不一样的

算术运算:
Jinja 允许用计算值。支持下面的运算符
+:把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接
它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 0.5
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
:用右边的数乘左边的操作数。 {{ 22 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ '=' * 80 }}
会打印 80 个等号的横条
:取左操作数的右操作数次幂。 {{ 23 }} 会返回 8

比较操作符

== 比较两个对象是否相等
!= 比较两个对象是否不等

如果左边大于右边,返回 true
= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true
逻辑运算符

对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and 如果左操作数和右操作数同为真,返回 true
or 如果左操作数和右操作数有一个为真,返回 true
not 对一个表达式取反
(expr)表达式组
true / false true 永远是 true ,而 false 始终是 false

template

template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件存建议放于templates目录下,且命名为 .j2 结尾

yaml/yml 文件和templates目录平级,此时playbook中指定模版文件时可不用指定路径, 目录结构如下
示例:

./
├── temnginx.yml
└── templates
   └── nginx.conf.j2

范例:利用template 同步nginx配置文件

#准备templates/nginx.conf.j2文件
[root@ansible ~]#vim temnginx.yml
---
- hosts: centos7
  remote_user: root
  tasks:
  - name: template config to remote hosts
    template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
[root@ansible ~]#ansible-playbook temnginx.yml

template变更替换
范例:

#修改文件nginx.conf.j2
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }};
......
[root@ansible ~]#vim temnginx2.yml
---
- hosts: centos7
  remote_user: root
  tasks:
  - name: install nginx
    yum: name=nginx
  - name: template config to remote hosts
    template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  - name: start service
    service: name=nginx state=started enabled=yes
[root@ansible ~]#ansible-playbook temnginx2.yml

Roles 角色

角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
运维复杂的场景:建议使用 roles,代码复用度高
roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例

roles/
mysql/
nginx/
tomcat/
redis/

默认roles存放路径

/root/.ansible/roles
/usr/share/ansible/roles
/etc/ansible/roles

官方文档:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html

Ansible Roles目录编排

roles目录结构如下所示

1677664119238

每个角色,以特定的层级目录结构进行组织
roles目录结构:

playbook1.yml
playbook2.yml
roles/
project1/
tasks/
files/
vars/
templates/
handlers/
default/
meta/
project2/
tasks/
files/
vars/
templates/
handlers/
default/
meta/

Roles各目录作用
roles/project/ :项目名称,有以下子目录

  • files/ :存放由copy或script模块等调用的文件
  • templates/:template模块查找所需要模板文件的目录
  • tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
  • handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过include进行包含
  • vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含,也可以通过项目目录中的group_vars/all定义变量,从而实现角色通用代码和项目数据的分离
  • meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
  • default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低

创建 role

创建role的步骤

1 创建role的目录结构.在以roles命名的目录下分别创建以各角色名称命名的目录,如mysql等,在每个角色命名的目录中分别创建相关的目录和文件,比如tasks、files、handlers、templates和vars等目录;用不到的目录可以创建为空目录,也可以不创建
2 编写和准备指定role的功能文件,包括: tasks,templates,vars等相关文件
3 编写playbook文件调用上面定义的role,应用到指定的主机

针对大型项目使用Roles进行编排
范例: 利用 ansible-galaxy 创建角色目录的结构

#创建初始化目录结构
[root@ansible roles]#ansible-galaxy role init test_role
- Role test_role was created successfully
[root@ansible roles]#tree test_role/
test_role/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
8 directories, 8 files

范例:roles的目录结构

nginx-role.yml
roles/
└── nginx
├── files
│ └── nginx.conf
├── tasks
│ ├── groupadd.yml
│ ├── install.yml
│ ├── main.yml
│ ├── restart.yml
│ └── useradd.yml
└── vars
└── main.yml

Playbook 调用角色

调用角色方法1:

---
- hosts: webservers
  remote_user: root
  roles:
    - mysql
    - memcached
    - nginx

调用角色方法2:
键role用于指定角色名称,后续的k/v用于传递变量给角色

---
- hosts: all
  remote_user: root
  roles:
    - role: mysql
    username: mysql
    - { role: nginx, username: nginx }

调用角色方法3:
还可基于条件测试实现角色调用

---
- hosts: all
  remote_user: root
  roles:
   - { role: nginx, username: nginx, when: ansible_distribution_major_version == '7' }

Roles 中 Tags 使用

[root@ansible ~]#vi app-role.yml
---
#可以有多个play
- hosts: lbserver
  roles:
    - role: haproxy
    - role: keepalived
    - hosts: appsrvs
  remote_user: root
  roles:
    - { role: nginx ,tags: [ 'nginx', 'web' ] ,when:
    ansible_distribution_major_version == "6" }
    - { role: httpd ,tags: [ 'httpd', 'web' ] }
    - { role: mysql ,tags: [ 'mysql', 'db' ] }
    - role: mariadb
      tags:
      - mariadb
      - db
  tags: app #play的tag
[root@ansible ~]#ansible-playbook --tags="nginx,mysql" app-role.yml

实战案例

实现httpd角色

# 创建role目录
[root@ansible data]# ansible-galaxy role init httpd
- Role htppd was created successfully
[root@ansible data]# tree httpd/
httpd/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files
[root@ansible data]# 

#main.yml 是task的入口文件
[root@ansible tasks]# cat main.yml 
---
# tasks file for httpd
- include: group.yml
- include: user.yml
- include: install_httpd.yml
- include: config.yml
- inclusde: index.yml
- include: service.yml
[root@ansible tasks]# 

# 创建用户组
[root@ansible httpd]# cat tasks/group.yml 
- name: add group 
  group: name={{ httpd_group}} system=yes gid={{ httpd_gid }}
[root@ansible htppd]# 

# 创建用户
[root@ansible httpd]# cat tasks/user.yml 
- name: add httpd user
  user: name={{ httpd_user }} system=yes shel=/sbin/nologin home=/var/www uid={{ httpd_uid }} group={{ httpd_group }}
[root@ansible htppd]# 

# yum install httpd
[root@ansible httpd]# cat tasks/install_httpd.yml 
- name: install httpd
  yum: name=httpd
[root@ansible httpd]# 

# 拷贝配置文件
#注意: 文件是放在files目录下,但src的路径无需写files目录名
[root@ansible htppd]# cat tasks/config.yml
- name: httpd config
  copy: src=httpd.conf dest=/etc/httpd/conf backup=yes
  notify: restart httpd
 
 # 准备测试文件
[root@ansible htppd]# cat tasks/index.yml 
- name: copy index.html
  copy: src=index.html dest=/var/www/html
[root@ansible htppd]# 

# start httpd
[root@ansible htppd]# cat tasks/service.yml 
- name: start httpd
  service: name=httpd state=started enabled=yes
[root@ansible htppd]# 

# 配置文件修改则重启httpd
[root@ansible htppd]# cat handlers/main.yml 
---
# handlers file for httpd
- name: restart httpd
  service: name=httpd state=restarted
[root@ansible htppd]# 

#在files目录下准备两个文件
[root@ansible data]# ll httpd/files
total 16
-rw-r--r-- 1 root root 11753 Mar  1 18:36 httpd.conf
-rw-r--r-- 1 root root    23 Mar  1 21:10 index.html

# 准备变量文件
[root@ansible data]# cat httpd/vars/main.yml 
---
# vars file for httpd
httpd_group: apache
httpd_gid: 88
httpd_user: apache
httpd_uid: 88
[root@ansible data]# 

#在playbook中调用角色
[root@ansible data]# cat web_roles.yml 
---
- hosts: centos7
  remote_user: root
  roles:
    - httpd
    
#运行playbook
[root@ansible data]# ansible-playbook /data/web_roles.yml

实现Nginx角色

# 创建roles目录
[root@ansible data]# ansible-galaxy init nginx
- Role nginx was created successfully
[root@ansible data]# ll
total 12
-rw-r--r--  1 root root  614 Mar  1 21:07 ansible.cfg
-rw-r--r--  1 root root 1382 Mar  1 21:07 hosts
drwxr-xr-x 10 root root  154 Mar  1 18:07 httpd
drwxr-xr-x 10 root root  154 Mar  1 21:52 nginx
-rw-r--r--  1 root root   63 Mar  1 21:14 web_roles.yml
[root@ansible data]# 

# 创建tasks文件
[root@ansible data]# cat nginx/tasks/main.yml 
---
# tasks file for nginx
- include: install_nginx.yml
- import_playbook: config.yml
- include: index.yml
- import_playbook: service.yml
[root@ansible data]#

# 安装nginx
[root@ansible data]# cat nginx/tasks/install_nginx.yml
---
- name: install nginx
  yum:
    name: nginx
    state: present
[root@ansible data]# 

# 配置文件
[root@ansible data]# cat nginx/tasks/config.yml
---
- name: copy config
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart nginx
  
# 创建测试文件
[root@ansible data]# cat nginx/tasks/index.yml
---
- name: copt index.html
  copy: src=index.html dest=/usr/share/nginx/html/

# 启动nginx
[root@ansible data]# cat nginx/tasks/service.yml
---
- name: start nginx
  service: name=nginx state=started enabled=yes
  
#创建handler文件
[root@ansible data]# cat nginx/handlers/main.yml 
---
# handlers file for nginx
- name: restart nginx
  service: naem=nginx state=restarted
[root@ansible data]# ll

#创建template文件
[root@ansible data]# ll nginx/templates/
total 4
-rw-r--r-- 1 root root 2336 Mar  1 22:12 nginx.conf.j2
[root@ansible data]# 


# 创建测试文件
[root@ansible data]# ll nginx/files/
total 4
-rw-r--r-- 1 root root 23 Mar  1 22:14 index.html
[root@ansible data]#

#在playbook中调用角色
[root@ansible data]# cat web_roles.yml 
---
- hosts: centos7
  remote_user: root
  roles:
  #  - httpd
    - nginx
[root@ansible data]# 
#运行playbook
[root@ansible data]# ansible-playbook web_roles.yml 

实现MySql8角色

  • 创建角色目录
[root@ansible data]# ansible-galaxy init mysql8
[root@ansible data]# ll
total 12
-rw-r--r--  1 root root  614 Mar  1 21:07 ansible.cfg
-rw-r--r--  1 root root 1382 Mar  1 21:07 hosts
drwxr-xr-x 10 root root  154 Mar  1 18:07 httpd
drwxr-xr-x 10 root root  154 Mar  1 22:55 mysql8
drwxr-xr-x  8 root root  125 Mar  1 22:44 nginx
-rw-r--r--  1 root root   75 Mar  1 22:38 web_roles.yml
[root@ansible data]# 
  • 创建tasks yml文件
# 安装包
[root@ansible data]# cat mysql8/tasks/install_package.yml
---
- name: install package
  yum: name={{ item }} state=latest
  loop:
    - libaio
    - numactl-libs
    
# add group
[root@ansible data]# cat mysql8/tasks/group.yml
---
- name: add group
  group: name={{ group }} gid={{ group_gid }}
[root@ansible data]# 

# add user
[root@ansible data]# cat mysql8/tasks/user.yml
---
- name: add user
  user: name={{ user }} uid={{ user_uid }} shell=/sbin/nologin group={{ group }} create_home=no system=yes home=/data/mysql
[root@ansible data]# 

# 准备my.cnf文件
[root@ansible data]# cat mysql8/files/my.cnf
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock

# 准备mysql二进制包
[root@ansible data]# ll mysql8/files/
total 1176056
-rw-r--r-- 1 root root        181 Mar  1 23:10 my.cnf
-rw-r--r-- 1 root root 1204277208 Dec 18  2021 mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz
[root@ansible data]# 

# 将mysql二进制包解压到远程主机
[root@ansible data]# cat mysql8/tasks/unarchive.yml
---
- name: copy mysql tar host
  # mysql_tar 为mysql二进制的压缩包名称
  unarchive: src={{ mysql_tar }} dest=/usr/local/ owner=root group=root
[root@ansible data]# 

# 将远程主机解压出的二进制包创建软连接
[root@ansible data]# cat mysql8/tasks/linkfile.yml
---
- name: create link
  file: src=/usr/local/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64 dest=/usr/local/mysql state=link
[root@ansible data]# 

# 初始化数据库
[root@ansible data]# cat mysql8/tasks/init_mysql_data.yml
---
- name: create datadir dir
  file: path=/data/mysql state=directory owner={{ user }} group={{ group }
- name: init mysql data
  shell: /usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --datadir=/data/mysql
[root@ansible data]#

# copy config.con
[root@ansible data]# cat mysql8/tasks/config.yml
---
- name: copy my.cnf
  copy: src=my.cnf dest=/etc/my.cnf
[root@ansible data]# 

[root@ansible data]# cat mysql8/tasks/script.yml
---
- name: service script
  shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@ansible data]# 

[root@ansible data]# cat mysql8/tasks/path.yml
---
- name: path
  copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh

[root@ansible data]# 

[root@ansible data]# cat mysql8/tasks/service.yml
---
- name: service
  shell: chkconfig --add mysqld;/etc/init.d/mysqld start
[root@ansible data]#

[root@ansible data]# cat mysql8/tasks/main.yml 
---
# tasks file for mysql8
- include: install_package.yml
- include: group.yml
- include: user.yml
- include: unarchive.yml
- include: linkfile.yml
- include: linkfile.yml
- include: init_mysql_data.yml
- include: config.yml
- include: script.yml
- include: path.yml
- include: service.yml
- include: secure.yml

# 创建变量文件
[root@ansible data]# cat mysql8/vars/main.yml 
---
# vars file for mysql8
group: mysql
group_gid: 306
user: mysql
user_uid: 306
mysql_tar: mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz
mysql_version: 8.0.28
mysql_root_password: 123456
[root@ansible data]# 

# 调用角色
[root@ansible data]# cat web_roles.yml 
---
- hosts: centos7
  remote_user: root
  roles:
    - mysql8

# 运行
[root@ansible data]# ansible-playbook web_roles.yml

实现Redis角色

# 创建角色目录
[root@ansible data]# ansible-galaxy init redis
[root@ansible data]# tree redis/
redis/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml
    
# 创建tasks文件
[root@ansible data]# cat redis/tasks/main.yml 
---
# tasks file for redis
- name: Installed Redis Server
  yum:
    name: redis
    state: present
- name: Configure Redis Server
  template:
    src: redis.conf.j2
    dest: /etc/redis.conf
    owner: redis
    group: root
    mode: '0640'
  notify: Restart Redis Server
- name: Start Redis Server
  systemd:
    name: redis
    state: started
    enabled: yes
[root@ansible data]# 

# 创建handlers文件
[root@ansible data]# cat redis/handlers/main.yml 
---
# handlers file for redis
- name: Restart Redis Server
  systemd:
    name: redis
    state: restarted
[root@ansible data]# 
# 在/data/redis/templates目录下准备如下文件
[root@ansible data]# ll redis/templates/
total 48
-rw-r----- 1 root root 46729 Mar  2 02:51 redis.conf.j2
[root@ansible data]#

# 调用角色
# 调用角色
[root@ansible data]# cat web_roles.yml 
---
- hosts: centos7
  remote_user: root
  roles:
    - redis

# 运行
[root@ansible data]# ansible-playbook web_roles.yml

Ansible推荐学习资料

http://galaxy.ansible.com
https://galaxy.ansible.com/explore#/
http://github.com/
http://ansible.com.cn/
https://github.com/ansible/ansible
https://github.com/ansible/ansible-examples
0

评论区