Playbook简介 Playbooks与Ad-Hoc相比,是一种完全不同的运用Ansible的方式,而且是非常之强大的;也是系统ansible命令的集合,其利用yaml语法 编写,运行过程,ansbile-playbook命令根据自上而下的顺序
依次执行任务。playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’为元素的列表,在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible模块的调用。当第一个任务依次在所有主机上执行完毕后,开始执行第二个任务。如果某个主机执行时发生错误,则所有操作将会回滚。
Playbook基础组件
hosts
:运行执行任务(task)的目标主机
remote_user
:在远程主机上执行任务的用户
tasks
:任务列表
handlers
:任务,与tasks不同的是只有在接受到通知时才会被触发
templates
:使用模板语言的文本文件,使用jinja2语法。
variables
:变量,变量替换
tag
:标签,为某tasks指定标签,运行该标签可以即运行特定的tasks,定义为always的tag总会执行
when
: 条件判断,当条件成立则执行tasks,不成立不执行表达式 判断表达式如:not
or
and
!=
=
with_items
:循环迭代需要重复执行的任务列表,用{item}}
引用列表值
例如一个简单的playbook文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 --- - hosts: test remote_user: root vars: - bsh: b.sh - httprpm: httpd task: - name: install httpd yum: name={{ httprpm }} state=present tags: install_httpd - name: copy b.sh copy: src=/root/{{ bsh }} dest=/root/ owner=ala group=ala mode=0644 notify: - reload httpd when: ansible_distribution == "CentOS" - name: copy b.sh copy: src=/root/{{ bsh }} dest=/opt/ owner=ala group=ala mode=0644 notify: - reload httpd when: ansible_distribution == "Ubuntu" - name: start httpd service: name=httpd state=started enabled=yes handlers: - name: reload httpd service: name=httpd state=reloaded
其中的ansible_distribution
是ansible收集的facts变量。
playbook定义变量 ansible 常见定义变量有以下 6 种
/etc/ansible/hosts文件主机中定义
/etc/ansible/hosts/文件主机组中定义
playbook的yaml文件中通过vars定义
获取系统变量,也称facts变量
分文件定义主机和主机组的变量
playbook 的role中定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 192.168.200.136 http_port=808 maxRequestsPerChild=808 192.168.200.137 http_port=8080 maxRequestsPerChild=909 [websers] 192.168.200.136 192.168.200.137 [websers:vars] ntp_server=ntp.exampl.com proxy=proxy.exampl.com --- - hosts: test remote_user: root vars: - bsh: b.sh - httprpm: httpd ansible 192.168.200.136 -m setup /etc/ansible/group_vars/websers /etc/ansible/host_vars/hostpc $ cat /etc/ansible/host_vars/hostpc --- ntp_server: acme.example.org database_server: storage.example.org $ cat /etc/ansible/roles/nginx/vars/main.yml --- nginx_port: 80 nginx_domain: www.abc.com nginx_user: nginx
playbook roles目录结构 Roles简介 Ansible为了层次化、结构化地组织Playbook,使用了角色(roles)。Roles能够根据层次型结构自动装载变量文件、task及handlers等。简单来讲,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷地include它们,roles一般用于基于主机构建服务的场景中,但也可以用于构建守护进程等场景中。
创建Roles 创建roles时一般需要以下步骤:首先创建以roles命名的目录。然后在roles目标下分别创建以这个角色名称命令的目录,如websevers等,然后在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录。最后在Playbook文件中调用各角色进行使用。
可以使用命令快捷创建
1 $ ansible-galaxy init websevers
roles内各目录含义解释
files
:用来存放由copy模块或script模块调用的文件。
templates
:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
tasks
:此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
handlers
:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
vars
:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
defaults
:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
meta
:此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
如下定义了一个nginx服务的playbook目录结构树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@k8s-master1 roles] /etc/ansible/roles/nginx ├── defaults │ └── main.yml ├── files │ └── nginx.tar.gz ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── tasks │ └── main.yml ├── templates │ └── nginx.conf.j2 │ └── default.conf.j2 └── vars └── main.yml
创建和使用角色 需求
1、创建名为 apache 的角色
2、httpd软件包已安装,设为在系统启动时启用
3、防火墙已启用并正在运行,并使用允许访问 Web 服务器的规则
4、模板文件 index.html.j2 已存在,用于创建具有以下输出的文件 /var/www/html/index.html:
Welcome to HOSTNAME on IPADDRESS
其中,HOSTNAME 是受管节点的完全限定域名,IPADDRESS 则是受管节点的 IP 地址。
5、按照下方所述,创建一个使用此角色的 playbook /home/ansible/ansible/newrole.yml
该 playbook 在 webservers 主机组中的主机上运行
实例环境
主机名
IP
系统
角色
ansible
192.168.20.210
rhel8.6
ansible控制器
servera
192.168.20.211
rhel8.6
web服务器1
serverb
192.168.20.212
rhel8.6
web服务器2
环境准备
每台web服务器创建用户,并设置sudo提权
1 2 3 $ useradd devops $ echo redhat | passwd --stdin devops $ echo 'devops ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/devops
控制器创建普通用户并设置免密登录
1 2 3 4 5 6 7 $ useradd ansible $ echo redhat | passwd --stdin ansible $ ssh-keygen $ ssh-copy-id devops@servera $ ssh-copy-id devops@serverb
配置ansible环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ su - ansible $ mkdir -p ansible/role $ cd ansible $ vim inventory [webserver] servera serverb $ cp /etc/ansible/ansible.cfg . $ vim ansible.cfg [defaults] inventory = /home/ansible/ansible/inventory remote_user = devops roles_path = /home/ansible/ansible/roles [privilege_escalation] become=True become_method=sudo become_user=root become_ask_pass=False
创建角色
1 $ ansible-galaxy init apache
定义tasks任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ vim apache/tasks/main.yml --- - name: install http yum: name: httpd state: present - name: config system service service: name: "{{ item }} " state: started enabled: yes loop: - httpd - firewalld - name: firewalld service firewalld: zone: public service: http permanent: yes immediate: yes state: enabled - name: use templates template: src: index.html.j2 dest: /var/www/html/index.html
定义模版文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $ vim apache/templates/index.html.j2 Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }} $ ansible node01 -m setup -a "filter=ansible_default_ipv4" node01 | SUCCESS => { "ansible_facts" : { "ansible_default_ipv4" : { "address" : "10.0.1.204" , "alias" : "ens192" , "broadcast" : "10.255.255.255" , "gateway" : "10.0.1.1" , "interface" : "ens192" , "macaddress" : "00:50:56:84:f7:a4" , "mtu" : 1500, "netmask" : "255.0.0.0" , "network" : "10.0.0.0" , "prefix" : "8" , "type" : "ether" }, "discovered_interpreter_python" : "/usr/libexec/platform-python" }, "changed" : false }
定义role入口文件
1 2 3 4 5 6 $ vim newrole.yml - name: use apache role hosts: webservers roles: - apache
playbook语法检测
1 2 $ ansible-playbook --syntax-check newrole.yaml playbook: newrole.yml
运行playbook
1 $ ansible-playbook newrole.yaml
验证安装结果
1 2 3 4 5 $ curl serverc Welcome to servera.lab.example.com on 192.168.20.211 $ curl serverd Welcome to serverb.lab.example.com on 192.168.20.212
playbook条件判断 在 Ansible Playbook 中,条件判断的基本语法是使用 when
关键字来控制任务的执行。例如:
1 2 3 4 5 - name: install software yum : name : software state : present when : ansible_os_type == 'redhat'
在这个例子中,when
关键字后面的表达式 ansible_os_type == 'redhat'
表示只有当受管节点的操作系统类型为 Red Hat 时,才会执行 install software
任务。
在 Ansible Playbook 中,可以使用变量来控制条件判断。例如:
1 2 3 4 5 6 7 - name: install software yum : name : software state : present when : ansible_os_type == 'redhat' vars : software_version : '7.0'
在这个例子中,software_version
变量被定义在 vars
关键字后面,表示安装的软件版本为 7.0。在 when
关键字后面的表达式中,可以使用 software_version
变量来控制任务的执行。
同样也可以使用ansible内置变量来控制条件判断。比如:
1 2 3 4 5 6 - name: create lv 600m lvol: vg: research lv: data size: 600m when: "'research' in ansible_lvm.vgs"
在这个例子中,当research
vg存在时,则执行创建lv步骤。
playbook任务控制 在 Ansible Playbook 中,block
、rescue
和 always
是三个常用的关键字,用于控制任务的执行流程。
block
关键字用于定义一个任务块,包含多个任务。在任务块中,可以使用 rescue
关键字来定义一个救援块,用于处理任务执行过程中可能出现的错误。always
关键字用于定义一个总是在任务块中执行的任务。
例如,下面是一个使用 block
、rescue
和 always
的 Playbook 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 --- - hosts: all vars: software_version: '7.0' tasks: - name: install software yum: name: software state: present when: ansible_os_type == 'redhat' and software_version == '7.0' block: - name: install additional software yum: name: additional_software state: present when: ansible_os_type == 'redhat' and software_version == '7.0' rescue: - AnsibleError msg: "Error installing software" always: - name: restart services service: name: httpd state: restarted
在这个例子中,install software
任务只有在受管节点的操作系统类型为 Red Hat,并且软件版本为 7.0 时才会执行。在任务块中,install additional software
任务只有在 install software
任务成功执行后才会执行。如果 install additional software
任务执行过程中出现错误,可以使用 rescue
关键字来定义一个救援块,处理错误。always
关键字用于定义一个总是在任务块中执行的任务,例如在这个例子中,restart services
任务总是在任务块中执行,无论前面的任务是否成功执行。
block
、rescue
和 always
是 Ansible Playbook 中常用的关键字,用于控制任务的执行流程,提高 Playbook 的可读性和可维护性。
本文介绍了 Ansible Playbook 的基本概念、组件、目录结构和创建使用方法。通过使用 Playbook,可以更方便地管理和维护多个服务器。同时,Playbook 也提供了更高级的特性,如条件判断、循环迭代等,能够满足更复杂的需求。