Ops工具
Helm
Helm 包管理工具
Helm进阶
Ansible
Ansible入门
Ansible 常用模块指令
Ansible playbook详解
Vdbench
vdbench基础使用指南
vdbench在ARM服务器上出现共享库aarch64.so问题
GitLab
Gitlab自定义机器人
Gitlab安装和使用
CosBench
Cosbench测试
s3curl
s3curl常用命令大全
S3curl测试
FIO
FIO安装和使用方法
本文档使用 MrDoc 发布
-
+
首页
Ansible playbook详解
## Playbook简介 Playbooks与Ad-Hoc相比,是一种完全不同的运用Ansible的方式,而且是非常之强大的;也是系统ansible命令的集合,其利用[yaml语法](http://www.ansible.com.cn/docs/YAMLSyntax.html)编写,运行过程,ansbile-playbook命令根据`自上而下的顺序`依次执行任务。playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’为元素的列表,在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible模块的调用。当第一个任务依次在所有主机上执行完毕后,开始执行第二个任务。如果某个主机执行时发生错误,则所有操作将会回滚。 ## Playbook基础组件 * `hosts`:运行执行任务(task)的目标主机 * `remote_user`:在远程主机上执行任务的用户 * `tasks`:任务列表 * `handlers`:任务,与tasks不同的是只有在接受到通知时才会被触发 * `templates`:使用模板语言的文本文件,使用jinja2语法。 * `variables`:变量,变量替换{{ variable_name }} * `tag`:标签,为某tasks指定标签,运行该标签可以即运行特定的tasks,定义为always的tag总会执行 * `when`: 条件判断,当条件成立则执行tasks,不成立不执行表达式 判断表达式如:`not` `or` `and` `!=` `=` * `with_items`:循环迭代需要重复执行的任务列表,用`{item}}`引用列表值 例如一个简单的playbook文件: ```yaml --- - hosts: test # 指定运行任务的主机组 remote_user: root # 指定远程执行任务的用户 vars: # 指定变量 - bsh: b.sh - httprpm: httpd task: # 任务的开始 - name: install httpd # 一个安装httpd的任务 yum: name={{ httprpm }} state=present # ansible的yum模块 tags: install_httpd # 为该任务打一个install_httpd的标签 - name: copy b.sh # 又一个复制b.sh脚本的任务 copy: src=/root/{{ bsh }} dest=/root/ owner=ala group=ala mode=0644 notify: # 如果copy的文件内容发生改变就会触发 - reload httpd # 指定通知的哪个handlers when: ansible_distribution == "CentOS" # 通过变量判断系统为CentOS时才执行该copy任务 - name: copy b.sh copy: src=/root/{{ bsh }} dest=/opt/ owner=ala group=ala mode=0644 notify: - reload httpd when: ansible_distribution == "Ubuntu" # 通过变量判断系统为Ubuntu时才执行该copy任务 - name: start httpd # 又一个启动httpd服务的任务 service: name=httpd state=started enabled=yes handlers: # 满足触发条件则执行的任务 - name: reload httpd # 满足触发条件的任务名 service: name=httpd state=reloaded # 该任务为重新加载一下httpd服务 ``` > 其中的`ansible_distribution`是ansible收集的facts变量。 ## playbook定义变量 **ansible 常见定义变量有以下 6 种** * /etc/ansible/hosts文件主机中定义 * /etc/ansible/hosts/文件主机组中定义 * playbook的yaml文件中通过vars定义 * 获取系统变量,也称facts变量 * 分文件定义主机和主机组的变量 * playbook 的role中定义 ```bash # /etc/ansible/hosts文件主机中定义 主机变量 192.168.200.136 http_port=808 maxRequestsPerChild=808 192.168.200.137 http_port=8080 maxRequestsPerChild=909 # /etc/ansible/hosts文件主机中定义 主机组变量 [websers] 192.168.200.136 192.168.200.137 [websers:vars] ntp_server=ntp.exampl.com proxy=proxy.exampl.com # ntp_server和proxy变量可为websers组中主机使用 # playbook的yaml文件中通过vars定义 --- - hosts: test remote_user: root vars: # 定义bsh和httprpm的两个变量 - bsh: b.sh - httprpm: httpd # 获取系统facts变量 ansible 192.168.200.136 -m setup # 可以获取主机所有的facts变量,通过{{variable_name}}引用 # 分文件定义主机和主机组的变量 /etc/ansible/group_vars/websers # 定义主机组名为websers的变量文件 /etc/ansible/host_vars/hostpc # 定义主机名为hostpc的变量文件 $ cat /etc/ansible/host_vars/hostpc # 变量文件内容格式如下 --- ntp_server: acme.example.org database_server: storage.example.org # role中定义 (目录结构下文讲述) $ 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文件中调用各角色进行使用。 可以使用命令快捷创建 ```bash $ 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目录结构树。 ```bash [root@k8s-master1 roles]# tree /etc/ansible/roles/nginx /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提权 ```bash $ useradd devops $ echo redhat | passwd --stdin devops $ echo 'devops ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/devops ``` 控制器创建普通用户并设置免密登录 ```bash $ useradd ansible $ echo redhat | passwd --stdin ansible $ ssh-keygen $ ssh-copy-id devops@servera $ ssh-copy-id devops@serverb ``` 配置ansible环境 ```bash $ 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 # 定义roles路径 [privilege_escalation] # 这是一个标签,表示以下配置属于权限提升设置。 become=True # 表示允许在执行任务时进行权限提升。 become_method=sudo # 表示使用sudo命令进行权限提升。 become_user=root # 表示在进行权限提升后,用户身份将切换为root。 become_ask_pass=False # 表示在执行权限提升操作时,不需要输入root用户的密码。 ``` **创建角色** ```bash $ ansible-galaxy init apache ``` **定义tasks任务** ```yaml $ vim apache/tasks/main.yml --- # tasks file for apache - 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 # 开放service permanent: yes # 是否永久生效 immediate: yes # 是否立即生效 state: enabled # 启动并运行 - name: use templates # 第四个任务名称 template: # 模块名称 src: index.html.j2 # 源文件 dest: /var/www/html/index.html # 目标文件 ``` **定义模版文件** ```bash $ vim apache/templates/index.html.j2 # ansible_fqdn和ansible_default_ipv4.address都来源于ansible内置变量,可以通过setup模块获取 Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }} # setup示例 $ 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入口文件** ```yaml $ vim newrole.yml - name: use apache role hosts: webservers roles: - apache ``` **playbook语法检测** ```bash $ ansible-playbook --syntax-check newrole.yaml playbook: newrole.yml ``` **运行playbook** ```bash $ ansible-playbook newrole.yaml ``` **验证安装结果** ```bash $ 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` 关键字来控制任务的执行。例如: ``` - name: install software yum: name: software state: present when: ansible_os_type == 'redhat' ``` 在这个例子中,`when` 关键字后面的表达式 `ansible_os_type == 'redhat'` 表示只有当受管节点的操作系统类型为 Red Hat 时,才会执行 `install software` 任务。 在 Ansible Playbook 中,可以使用变量来控制条件判断。例如: ``` - 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内置变量来控制条件判断。比如: ```yaml - 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 示例: ``` --- - 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 的可读性和可维护性。
阿星
2024年1月21日 21:02
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码