架设网站 软件,东莞外贸网站推广,怎么建网站新手入门,wordpress调用函数大全Ansible自动化
自动化的需求#xff1a; 1. 在什么样的场景下需要自动化#xff1f; 批量化的工作#xff1a; 装软件包、配置服务、升级、下发文件… 2. 为什么在自动化工具中选择ansible#xff1f;
对比shell脚本#xff1a; 相对于用shell的脚本来实现自动化#x…Ansible自动化
自动化的需求 1. 在什么样的场景下需要自动化 批量化的工作 装软件包、配置服务、升级、下发文件… 2. 为什么在自动化工具中选择ansible
对比shell脚本 相对于用shell的脚本来实现自动化ansible更加的灵活比如ansible的变量、ansible的模块、ansible的剧本通过ansible的高级特性可以轻松的完成自动化的任务
对比其他自动化工具 ansible 简单 、 强大 简单 人工可读的自动化 剧本的语言使用yaml来进行编写 强大 在所有的被控节点不需要安装任何客户端代理 可以通过应用原生的方式管理应用本身而无需代理
什么是ansible ansible是一个自动化的工具ansible可以完成基础设施的自动化管理包括但不限于服务器、网络设备、存储、公私有云都能进行自动化在滚动更新、配置下发上有天然的优势 ansible的特点 1. 不需要再被控节点被管理节点不需要安装任何客户端代理 应用原生的方式来管理应用本身所谓应用原生的方式指的就是应用自带的管理方式例如Linux的ssh、windows的 winrm、公私有云的API接口、网络设备的SNMP… 2. ansible是一个工具没有任何的服务需要启动只需要执行ansible命令即可 3. ansible是基于python进行开发但是ansible的模块可以使用任意语言进行开发 4. ansible通过剧本来对任务进行编排使得任务具有可移植性 5. ansible 默认使用ssh 来管理被控因此Linux不需要做配置即可被管理 6. ansible支持多级控制 ansible的架构 核心ansible核心模块Core Modules这些都是ansible自带的模块扩展模块Custom Modules如果核心模块不足以完成某种功能可以添加扩展模块插件Plugins完成模块功能的补充剧本Playbooks把需要完成的多个任务定义在剧本中连接插件Connectior Pluginsansible基于连接插件连接到各个主机上虽然ansible是使用ssh连接到各个主机的但是它还支持其他的连接方法所以需要有连接插件主机清单Host Inventoryansible在管理多台主机时可以选择只对其中的一部分执行某些操作
ansible工作机制 Ansible 在管理节点将 Ansible 模块通过 SSH 协议或者 Kerberos、LDAP推送到被管理端执行执行完之后自动删除可以使用版本控制系统git/svn来管理自定义模块及playbooks ansible的安装方式 1.通过源码包进行安装 wget https://kkgithub.com/ansible/ansible/archive/refs/tags/v2.9.0.zip unzip v2.9.0.zip python3 setup.py build 构建包 python3 setup.py install 安装包 wget https://raw.kkgithub.com/bikashhite/ansible.cfg/master/cfg%20file 下载配置文件 2.通过发行包进行安装RHELRPM包、ubuntuDeb包 配置YUM仓库地址 Index of /ansible/rpm/release 适用于RHEL9 yum install ansible-core -y 适用于RHEL8 yum install ansible -y 3.通过第三方PIP包管理器进行安装 pip install ansible2.9.0 -i https://pypi.tuna.tsinghua.edu.cn/simple 4.通过容器进行安装——ansible的导航器 安装ansible的导航器 yum install ansible-navigator 拉取容器镜像 podman login registry.redhat.io 使用导航器运行容器 ansible-navigator images 查看运行的ansible环境 在RHEL9中将ansible拆分成两部分 ansible的核心包 ansible核心主程序 只携带了ansible的必要模块 ansible的扩展包 ansible的附加模块 集合
主机清单的定义方式 1. 直接使用主机名进行定义 node1.example.com
node2.example.com
node3.example.com 2. 使用IP地址定义主机 192.168.1.10 3. 使用主机组定义主机 [webserver] 组名
172.16.0.100 组的成员
172.16.0.200 4. 使用嵌套组调用多个主机组 [allserver:children] 嵌套组名
mysql
webserver 注意 在定义主机和主机组时主机需要定义在主机组的前面如果定义在主机组后面无论有多少空行该主机都会成为组的成员 5. 通过数字或者字母范围批量定义主机 lvs[1:100] 表示一百台lvs也就是从lvs1 - lvs100 一共100台 demo[a:z]
清单主机的查询方式 如何使用ansible选择主机 1. 直接选择所有的主机 ansible all --list-hosts 2. 选择指定的主机或者主机组 ansible node1.example.com --list-hosts ansible webserver --list-hosts 3. 选择指定的多个主机或多个主机组 ansible node1.example.com,db1.example.com --list-hosts ansible webserver,mysql --list-hosts 4. 选择没有主机组的主机 ansible ungrouped --list-hosts 5. 使用通配符来选择主机 ansible node* --list-hosts ansible *.example.com --list-hosts ansible db*com --list-hosts 6. 使用感叹号反向过滤 ansible *.example.com,!node3* --list-hosts 对指定主机取反 7. 使用and符号来联合选择主机 ansible mysql,webserver --list-hosts 选择即在mysql组中又在webserver中 8. 通过正则进行选择主机 ansible ~^(d|n) --list-hosts 9. 通过limit进行选择主机 ansible node1.example.com --list-hosts ansible all --limit host.txt --list-hosts
ansible的配置文件优先级 优先级最高的是 ANSIBLE_CONFIG 环境变量 优先级其次的是 当前工作目录下的ansible.cfg 优先级较次的是 当前用户家目录下的.ansible.cfg 隐藏文件 优先级最低的是 /etc/ansible/ansible.cfg 全局默认文件
ansible的配置文件 [defaults]通用配置项
[inventory]与主机清单相关的配置项
[privilege_escalation]特权升级相关的配置项
[paramiko_connection]使用paramiko连接的相关配置项Paramiko在RHEL6以及更早的版本中默认使用的ssh连接方式
[ssh_connection]使用OpenSSH连接的相关配置项OpenSSH是Ansible在RHEL6之后默认使用的ssh连接方式
[persistent_connection]持久连接的配置项
[accelerate]加速模式配置项
[selinux]selinux相关的配置项
[colors]ansible命令输出的颜色相关的配置项
[diff]定义是否在运行时打印diff变更前与变更后的差异 ansible的配置案例 被控端配置 创建devops用户 useradd devops echo redhat|passwd --stdin devops 配置sudo免密提权 echo devop ALL(ALL) NOPASSWD:ALL /etc/sudoers.d/devops 主控端配置 ansible.cfg配置文件 [defaults]
inventory ./hosts
ask_pass False
remote_user devops
deprecation_warningsFalse
module_name shell
host_key_checking False
[privilege_escalation]
become True
become_method sudo
become_ask_pass False
become_user root
[ssh_connection]
ssh_args -C -o ControlMasterauto -o ControlPersist60 hosts文件
node1
node2 ssh生成公私钥并拷贝给node1和node2节点:
ssh-keygen
ssh-copy-id devopsnode1
ssh-copy-id devopsnode2
ansible连通性测试
ansible all -m ping ansible运行任务的方式 1. 使用ad-hoc运行任务 —— ansible的临时指令 用来执行简单的任务 2. 使用playbook运行任务 —— ansible 的剧本 用来执行复杂的任务 注意在ansible的导航器中也就是容器版本中ansible的ad-hoc已经废除 ad-hoc的执行 语法格式 ansible 主机/主机组 -m 模块 -a ‘模块的参数’ ansible的参数 ansible的模块 ansible-doc -l 列出当前系统中ansible的所有模块 ansible-doc -s 模块名 查看模块的参数 ansible-doc 模块名 查看模块的详细信息 包括用法 ansible的四大命令执行模块 command、shell、raw、script 四个模块专门用来执行Linux的指令 ansible默认使用command模块作为默认的命令执行模块 command 有四个例外如果命令中出现了 、、、|符号则command无法执行 shell 模块相当于在本机执行bash shell一样可以让ansible执行Linux的指令并且支持一些高阶参数例如chdir可以在执行命令前切换到指定的目录creates、removes等 raw 模块 也相当于在本机执行命令但是缺少chdir、creates、removes的高阶参数 creates 当文件存在时命令不执行 removes 当文件不存在时命令不执行 script模块 将主控端的shell复制到被控端执行没有将脚本文件拷贝到对端执行而是将文件中shell的内容复制到被控端执行 Ansible Playbook playbook 是一系列ansible命令的集合通过playbook的高级特性可以完成很多复杂的自动化任务比如在playbook中可以进行任务的判断、循环、还可以将任务的执行结果作为变量以及从外部或者其他位置获得变量让playbook 更加的灵活 playbook语言 playbook 使用yaml作为配置语言yaml 是非标记型语言其实还是一种标记型语言这类语言通俗易懂并且不需要掌握编程技能就可以写好这个配置 yaml的约束 1. 大小写敏感— 变量的大小写是完全不同的两个变量 2. 使用缩进表示层级关系 3. 只能使用空格进行缩进不能使用tab从RHEL8.4开始会将yaml中的tab转成空格个人感觉是vim的版本有关系vim的版本更高了 4. 空格的数量不重要相同的元素向左对齐很重要 5. 使用#符号注释内容注释一整行 yaml的数据类型 纯量 不可再分的值 数组序列、列表 一组有次序的值 通常使用短横线开头 “-” 对象字典/哈希/映射 键值对 key vaule 用冒号进行表示也就是key和vaule之间使用冒号分隔并且vaule前需要使用空格 playbook的示例需求 1. 在所有节点上安装apache 2. 在所有节点上生成一个名为/var/www/html/index.html的文件内容为hello rhce 3. apache服务需要开机自启动且当前立即启动 4.配置firewalld防火墙允许web服务器的规则 - name: configure website hosts: all remote_user: devops tasks: - name: install httpd yum: name: httpd state: present - name: create file for index.html copy: content: hello rhce\n dest: /var/www/html/index.html mode: 0777 - name: start service systemd: name: httpd state: started enabled: yes - name: enable firewalld for 80/tcp firewalld: service: http permanent: yes immediate: yes state: enabled
ansible-playbook的执行选项 -v v越多信息越详细 -syntax-check 检查语法错误 -C 测试运行playbook测试运行下不会对目标造成真正的影响则测试剧本能否成功执行 playbook的定义 playbook由一个或者多个play组成的列表而一个play就是一组任务的集合一个play中tasks的任务列表就是play中要完成的需求而每一个需求或者说每一个tasks的任务都是对一个模块的调用因此将play根据一定的顺序或者是逻辑组合在一起完成一个复杂的大任务我们将其称为playbook的编排
playbook的结构 Target section目标、指的是play中需要定义的远程主机、远程用户、是否开启提权、是否需要密码连接等都在此定义如果没有定义则使用ansible.cfg中默认的配置如果用户进行了定义则以用户定义的为准 Variable section 变量、指的是在playbook的执行过程中需要传递给任务或者是其他插件的变量在此定义该段落专门用来给playbook定义变量 Task section 任务、指的是play中所有需要执行的任务在此定义也就是play的任务列表 Handler section特定任务、该任务是有条件执行的任务只有当达到特定条件是该任务才会被触发一般情况下该任务不会自动执行该任务在所有tasks任务执行完成后根据触发的条件来决定是否执行 playbook的任务列表 1. 任务列表中的所有任务都是从上向下执行 2. 任务列表中任务一旦在某个主机上执行失败则playbook接下来的任务不会在该主机上执行也就是在该主机上停止 3. 任务列表中有任务执行失败只需要修复该任务后继续执行playbook即可完成失败的任务这是因为ansible具有幂等性期望值一致期望状态一致则任务是执行成功的 幂等性对同一个系统使用同样的条件一次请求和重复的多次请求对系统资源的影响是一致的 解决ansible的任务报错 命令执行模块报错shell、raw 可以使用逻辑或 通过|| /usr/bin/true 让其返回值永远为零则任务不会失败 其他模块执行报错file、user等模块通过ignore_errors: true 来忽略报错 handlers 在Ansible Playbook中handler事实上也是个task只不过这个task默认并不执行只有在被触发时才执行。 handler通过notify来监视某个或者某几个task一旦task执行结果发生变化则触发handler执行相应操作。 handler会在所有的play都执行完毕之后才会执行这样可以避免当handler监视的多个task执行结果都发生了变化之后而导致handler的重复执行handler只需要在最后执行一次即可
- hosts: node1 force_handlers: yes tasks: - name: install vsftpd dnf: name: vsftpd state: present notify: get_status - name: create file file: path: /opt/vsftpd.txt state: touch - shell: ls -l /opt/abbbb.txt handlers: - name: aaaaa systemd: name: vsftpd state: started listen: get_status Ansible的变量 变量的约束 1. ansible的变量名不能以数字开头但是不表示不能使用数字 2. ansible的变量名只能是字母或者是下划线和数字组成只能以字母开头 3. 自定义ansible的变量时最好不要以ansible作为变量名的开头以防止和系统中已经存在的变量冲突 调试变量的方式 ansible中使用 debug模块来调试变量 debug模块有两个参数且不能共用也就是两个参数不能一起使用 msg 输出字符串内容 var 输出变量的内容
ansible中定义变量的位置 1. 在inventory的清单中进行定义 # 一般连接
ansible_host #用于指定被管理的主机的真实IP
ansible_port #用于指定连接到被管理主机的ssh端口号默认是22
ansible_user #ssh连接时默认使用的用户名
# 特权升级
ansible_become #相当于ansible_sudo或者ansible_su允许强制特权升级
ansible_become_user #通过特权升级到的用户相当于ansible_sudo_user或者ansible_su_user
ansible_become_pass # 提升特权时如果需要密码的话可以通过该变量指定相当于ansible_sudo_pass或者ansible_su_pass
ansible_sudo_exec #如果sudo命令不在默认路径需要指定sudo命令路径
# 特定ssh连接
ansible_connection #SSH连接的类型local, ssh, paramiko默认是ssh
ansible_ssh_pass #ssh连接时的密码
ansible_ssh_private_key_file #秘钥文件路径如果不想使用ssh-agent管理秘钥文件时可以使用此选项
ansible_ssh_executable #如果ssh指令不在默认路径当中可以使用该变量来定义其路径 #自定义主机变量变量 node1 webservernginx #自定义主机组变量 [group1]
node1
node2
[group2]
node1
[group1:vars]
webservertomcat 注意如果主机组和主机的变量发生了冲突则以主机的变量为准主机的变量会覆盖主机组的变量 2. 在playbook的vars关键字段落定义变量 - name: vars demo hosts: group1 vars: test: hello tasks: - name: print debuginfo debug: msg: {{ test }} 3. 通过vars_files外部文件引入变量 引入的外部文件的格式为yaml的格式 vim users.yml users: - name: ituser001 uid: 1000 - name: ituser002 uid: 2000 vim vars.yml - name: vars demo hosts: group1 vars_files: - users.yml tasks: - name: print debuginfo debug: msg: {{ users }}
如果是字典结构要取到具体的某一项的值使用点来表示对象的层级结构 4. 通过主机和主机组的目录文件中来定义变量 host_vars、group_vars 在host_vars中定义变量以主机名称作为文件名在其中进行变量的定义 在group_vars中定义变量以主机组名称作为文件名在其中定义变量 在文件中定义的变量的格式为yaml的格式 如果主机和主机组的变量发生冲突主机的变量优先级更高 5. 注册变量 所谓的注册变量指的是将一个任务的执行结果注册成为变量给到其他的任务来进行调用
- name: vars demo hosts: node1 tasks: - shell: touch /opt/ansible1.txt register: get_file - name: print debuginfo debug: msg: {{ get_file.rc }} 6. 通过命令行来定义变量 ansible-playbook test.yml -e helloredhat ansible node1 -m debug -a varhello --extra-vars helloredhat 7. 收集facts的事实变量 所谓的事实变量指的是ansible被控主机上的信息将其收集成为变量通过一个setup的模块以facts的方式将其作为变量facts是setup模块的一个方法专门用来收集被控主机的信息我们将这种收集的被控端的信息称为facts变量事实变量 7.1 使用filter过滤facts的变量 filter在过滤时只能过滤到ansible_facts的下一个层级也就是ansible_开头的这一部分变量除此以外其他的变量都不能过滤到 例如
无法过滤 ansible node1 -m setup -a filteransible_ens160.ipv4.address
可以过滤 ansible node1 -m setup -a filteransible_ens160 7.2 使用通配符过滤facts的变量 ansible node1 -m setup -a filteransible_ens* 可以在变量中未知的部分使用*号来进行通配 7.3 导出facts的变量到文件 ansible node1 -m setup --tree /tmp/facts 在导出文件中只有一行内容不容易查看 ansible node1 -m setup /tmp/node1.facts 重定向导出以原有的格式存储到文件 7.4 facts变量的引用方式 facts的变量中ansible_facts层级可以省略因为所有的变量都注册在ansible_facts中facts的下一个层级通过点来进行调用 例子 取值ens160的网卡IP ansible_ens160.ipv4.address 7.5 禁止剧本收集facts变量 - hosts: node1 gather_facts: no 如果是yes /true则收集默认为trueno/false则关闭 tasks: - debug: var: ansible_ens160.ipv4.address 7.5 自定义主机facts变量 实现每一台主机都有其不同的自定义facts变量 每一台主机的facts变量都存储在/etc/ansible/facts.d/ 目录下 文件可以是ini或者是yaml的格式一般是ini文件的后缀必须以fact结尾自定义的facts变量都存储在ansible_local这个变量中因此调用时需要使用ansible_local 案例 自定义node1主机 facts变量 编写facts文件 vim test.facts [dbserver] name mysql conf /etc/my.cnf service mysql.service 将文件传输到被控端的 /etc/ansible/facts.d目录下 通过剧本 定义两个任务 创建目录、copy文件 通过ansible facts 来测试是否生效 ansible node1 -m setup -a filteransible_local 7.6 整合facts变量将多个facts变量生成一个新的变量 通过set_fact模块将多个facts变量结合在一起进行调用 - hosts: node1 gather_facts: yes tasks: - name: define vars set_fact: get_rhel: {{ ansible_distribution }}-{{ ansible_distribution_version }} 其中get_rhel 就是定义的变量名后面就是facts的变量 - debug: var: get_rhel 8. 通过lookup插件来生成变量 lookup的插件有很多方式可以将外部的数据源作为变量例如文件、命令、环境变量…… 使用文件的内容作为变量 “{{ lookup(‘file’,’文件的路径’) }}” 使用命令的结果作为变量 “{{ lookup(‘pipe’,’执行的命令’) }}” 使用环境变量值作为变量 “{{ lookup(‘env’,’环境变量’) }}” lookup变量使用lookup(‘方法’,’内容’) 内容都是在主控节点上获取的 lookup获取的数据源都是在主控节点上获取的 9. ansible的魔法变量 所谓ansible的魔法变量其实就是ansible的内置变量只是这一些变量有特殊意义我们将其称为魔法变量 hostvars 用来获取清单中指定主机的facts变量 {{ hostvars[node1].ansible_ens160.ipv4.address }} 其中node1 只能是主机名并且是清单中的名称不能是IP地址但是如果清单中只使用了IP地址则可以将地址作为主机名 inventory_hostname 列出当前任务正在执行的主机 groups 列出清单中的所有主机组 groups.all 列出所有主机 groups.test 列出指定主机组的主机 group_names 列出当前运行任务的主机所在主机组 其他的魔法变量 https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html#magic-variables ansible的条件判断 ansible的判断应用场景
在目标主机上定义了一个硬限制比如目标主机的最小内存必须达到多少才能执行该task捕获一个命令的输出根据命令输出结果的不同以触发不同的task根据不同目标主机的facts以定义不同的task根据目标机的cpu的大小以调优相关应用性能用于判断某个服务的配置文件是否发生变更以确定是否需要重启服务
1. 比较运算符
比较两个对象是否相等相等则返回真。可用于比较字符串和数字
!比较两个对象是否不等不等则为真。比较两个对象的大小左边的值大于右边的值则为真比较两个对象的大小左边的值小于右边的值则为真比较两个对象的大小左边的值大于等于右边的值则为真比较两个对象的大小左边的值小于等于右边的值则为真
2. 逻辑运算符
and逻辑与当左边和右边两个表达式同时为真则返回真or逻辑或当左右和右边两个表达式任意一个为真则返回真not逻辑否/非对表达式取反()当一组表达式组合在一起形成一个更大的表达式组合内的所有表达式都是逻辑与的关系
例子
逻辑与 when: ansible_hostname node1 and ansible_distribution RedHat
逻辑或 when: ansible_hostname node1 or ansible_distribution RedHat
逻辑非 when: not ansible_hostname node1
逻辑组合条件 when: (ansible_hostname node1 and ansible_distribution RedHat) or (ansible_distribution_version 9.0 and ansible_ens160.ipv4.address 172.18.0.139)
3. 判断shell模块的任务是否执行成功 通过对shell任务的rc的值来判断任务是否执行成功 - hosts: node1 tasks: - shell: ls -l /opt/hello.txt register: get_file ignore_errors: yes - debug: msg: Tasks Ok when: get_file.rc 0 - debug: msg: Tasks Failed when: get_file.rc ! 0
4. 对路径进行判断 路径的所有判断都是判断的主控端上的路径不能判断被控端的路径 file判断指定路径是否为一个文件是则为真directory判断指定路径是否为一个目录是则为真link判断指定路径是否为一个软链接是则为真mount判断指定路径是否为一个挂载点是则为真exists判断指定路径是否存在存在则为真
表达式为: when: 变量 is file/directory/link/mount/exists when: /etc/hostname is file
- hosts: node1 gather_facts: yes vars: file_path: /etc/hostname tasks: - debug: msg: hello ansible when: file_path is file
5. 对任务的执行结果进行判断 ok目标状态与期望值一致没有发生变更 à 任务执行成功change或changed目标发生变更与期望值一样sucess或succeeded目标状态与期望值一致或者任务执行成功failure或failed任务执行失败skip或skipped任务被跳过 注意 是对任务的执行结果进行判断是整个任务的状态而不是任务中命令的执行状态
6. 对变量的判断 defined判断变量是否已定义已定义则返回真undefined判断变量是否未定义未定义则返回真
none判断变量的值是否为空如果变量已定义且值为空则返回真前提是变量要定义
例子 - hosts: node1 gather_facts: yes vars: hello: tasks: - debug: msg: hello ansible when: hello is none 判断变量的值为空前提是变量需要先定义
7. 对字符串进行判断 lower判断字符串中的所有字母是否都是小写是则为真upper判断字符串中的所有字母是否都是大写是则为真
例子 when: hello is upper
8. 判断整除
even判断数值是否为偶数是则为真odd判断数值是否为奇数是则为真divisibleby(num)判断是否可以整除指定的数值是则为真
- hosts: test gather_facts: no vars: num1: 6 num2: 8 num3: 15 tasks: - debug: msg: num1 is an even number when: num1 is even - debug: msg: num2 is an odd number when: num2 is odd - debug: msg: num3 can be divided exactly by when: num3 is divisibleby(3)
9. 判断集合 subset 判断一个list是不是另一个list的子集when: a is subset(b)superset 判断一个list是不是另一个list的父集when: b is superset(a)
例子 - hosts: node1 gather_facts: yes vars: os_list: - centos - rhel - openeuler - fedora test_list: - centos - rhel tasks: - debug: msg: hello ansible when: test_list is subset(os_list) 判断test_list 是不是os_list的子集 when: os_list is superset(test_list) 判断os_list是不是test_list的父集 10. 判断关键字是否出现在列表或者字符串中
in 判断一个字符串是否存在于另一个字符串中也可用于判断某个特定的值是否存在于列表中 - hosts: node1 gather_facts: yes vars: os_list: - centos - RedHat - openeuler - fedora tasks: - debug: msg: hello ansible when: ansible_distribution in os_list when: “’字符串’ in 变量” 直接判断字符串是否在一个变量之中 11. 判断对象是否是一个数字或者是字符串
string 判断对象是否为一个字符串是则为真 when: var1 is stringnumber 判断对象是否为一个数字是则为真 when: var3 is number
- hosts: node1 gather_facts: yes vars: RHCE9: ansible10.0 RHCE8: 2.9 tasks: - debug: msg: str when: RHCE9 is string - debug: msg: num when: RHCE8 is number 12. 对多个任务使用同一个条件判断 通过block关键字使用同一个条件对多个任务进行判断也就是使用when来判断block如果block中的条件成立则block中的所有任务都会执行如果条件不成立则任务不会执行
- hosts: node1 gather_facts: yes vars: RHCE9: ansible10.0 RHCE8: 2.9 tasks: - block: - debug: msg: hello1 - debug: msg: hello2 - debug: msg: hello3 - debug: msg: hello4 when: ansible_distribution RedHat 12.1 使用rescue修复 block中的报错 也就是如果block中的任务出错则触发rescuerescue也是一组特殊的任务只有当block报错其中的任务才会执行
12.2 通过always来执行必须执行的任务 也就是不管block中的任务是否出错都执行always其也是特殊的任务列表
- hosts: node1 gather_facts: yes tasks: - block: - debug: msg: hello1 - shell: ls -l /opt/key00000.txt - debug: msg: hello3 - debug: msg: hello4 rescue: - debug: msg: file not always: - debug: msg: hello always when: ansible_distribution RedHat 13. fail模块帮助剧本在特定条件下终止执行
- hosts: node1 gather_facts: yes vars: RHCE9: ansible10.0 RHCE8: 2.9 tasks: - debug: msg: hello1 - shell: ls -l /opt/key00000.txt register: get_status ignore_errors: yes - fail: msg: playbook exit when: get_status.rc ! 0 如果shell的任务执行失败则终止剧本执行 - debug: msg: hello3 除了使用fail模块来终止剧本的执行也可以使用failed_when将判断和fail结合在一起只要达到条件立即退出剧本 - hosts: node1 gather_facts: yes vars: RHCE9: ansible10.0 RHCE8: 2.9 tasks: - debug: msg: hello1 - shell: ls -l /opt/key0000aaa.txt register: get_status ignore_errors: yes - debug: msg: hello3 failed_when: get_status is failed - debug: msg: hello4
Ansible的循环语句 1. 基于列表的循环 with_items 循环列表 表现形式 形式一
- hosts: node1 vars: pkgs: - vsftpd - cifs-utils - samba - mariadb tasks: - name: install pkgs yum: name: {{ item }} state: present with_items: {{ pkgs }} 形式二:
- hosts: node1 vars: tasks: - name: install pkgs yum: name: {{ item }} state: present with_items: - vsftpd - cifs-utils - samba - mariadb 形式三: 不常用
- hosts: node1 vars: tasks: - name: install pkgs yum: name: {{ item }} state: present with_items: [vsftpd,cifs-utils,samba,mariadb]
比较特殊的列表
- hosts: node1 vars: users: - name: bob uid: 2000 comment: dev user - name: alice uid: 3000 comment: oc user tasks: - name: create user user: name: {{ item.name }} uid: {{ item.uid }} comment: {{ item.comment }} state: present with_items: {{ users }}
基于字典的循环
with_dict 进行字典的结构循环
- hosts: node1 vars: users: dev: name: bob uid: 2000 oc: name: alice uid: 3000 tasks: - name: create user user: name: {{ item.value.name }} 如果不知道取值使用debug进行输出查看 uid: {{ item.value.uid }} state: present with_dict: {{ users }}
统一的循环语句 从ansible2.6 开始使用loop进行循环不再需要with的各种前缀关键字但是部分with依然保留使用注意loop本身只能循环列表可以通过过滤器来对字典进行循环
loop 直接循环列表
loop {{ 变量|dict2items }} 使用dict2items 过滤器进行循环字典结构
过滤器在ansible中专门用来对数据或者是变量进行处理过滤器的种类非常多如果需要查看较为全面的过滤器可以看python中jinja2的文档
- hosts: node1 vars: users: dev: name: bob uid: 2000 oc: name: alice uid: 3000 tasks: - name: create user user: name: {{ item.value.name }} uid: {{ item.value.uid }} state: present loop: {{ users|dict2items }} 常用到的过滤器 dict2items 将字典转化成列表 password_hash(‘sha512’) 将数据使用sha512 进行加密通常用在用户的密码上 default(‘值’) 如果变量不存在则给变量赋予默认的值
修改配置文件
单行修改lineinfile模块 path要修改的文件
regexp正则表达式匹配要修改的行
line修改或者插入行的内容
insertbefore在匹配的行前面插入
insertafter在匹配的行后面插入
backup是否备份文件
create文件不存在则创建文件
backrefs: 默认值为 no如果该项为yes则不匹配关键字时不在文件的末尾追加内容默认找不到关键字则在文件末尾追加内容
validate验证文件修改的有效性需要文件自带验证机制ansible本身不能校验配置文件的主要靠服务自身携带的校验机制例如httpd -t 、visudo 这样的校验方式如果需要校验使用%s 来通配path的路径eg /usr/sbin/httpd -tf %s 校验apache的配置文件 多行增加blockinfile 模块 除了使用lineinfile的参数外还支持如下参数 block要插入的文本内容
marker指定块标记# {mark} ANSIBLE MANAGED BLOCK 通过将lineinfile和blockinfile 结合起来删除文件中的段落
- hosts: node1 tasks: - lineinfile: path: /opt/passwd insertbefore: ^root line: A BEGIN blockinfile test - lineinfile: path: /opt/passwd insertafter: ^adm line: A END blockinfile test - blockinfile: path: /opt/passwd state: absent marker: A {mark} blockinfile test
生成通用配置文件模板
Jinja2是基于python的模板引擎那么什么是模板
在服务器的批量管理中如果需要对某个服务进行批量配置例如在10台主机上安装apache每一个apache的web服务都需要监听本机的IP地址那就会出现我们要对每一台机器都需要修改配置文件如果机器的数量多修改的配置项多效率就会低下但是在这些配置文件中除了要修改的少部分配置以外绝大部分的配置每台机器都是相同的因此需要一个通用解决方案来解决配置文件的分发问题也就是每台机器都可以差异化配置文件 template模块: template 将配置文件中的变量复制到被控端时会将配置文件中的变量渲染成具体的值它与copy模块的参数相同但是可以将变量渲染成具体的值因此我们将template拷贝的配置文件称为通用模板该模板使用j2结尾表示其是一个jinja2的模板文件 jinja2中进行判断 {% if 表达式 %} 表达式和when中的条件一致
执行语句
{% elif 表达式%}
执行语句
{% else %}
执行语句
{% endif %} 例子 {% if ansible_hostname node1 %}
hello node1
{% elif ansible_hostname node2 %}
hello node2
{% else %}
hello master
{% endif %} jinja2中的循环 {% for 变量 in 循环的对象 %} 循环体结构 {% endfor %} 复杂的循环例子在 node1上生成ansible中所有主机的ip和主机名的映射清单文件文件名为/opt/get_hosts.txt;文件每一行应该包含受管主机的IP地址完全限定的域名以及主机名格式如下 172.18.0.136 node1.example.com node1 172.18.0.139 node2.example.com node2 172.18.0.135 host1.sina.com host1 template的模板 hosts.j2 {% for host in groups.all %}
{{ hostvars[host].ansible_ens160.ipv4.address }} {{ hostvars[host].ansible_fqdn }} {{ hostvars[host].ansible_hostname }}
{% endfor %}
playbook的剧本 hosts.yml
- hosts: all tasks:
- hosts: node1 tasks: - template: src: hosts.j2 dest: /opt/get_hosts.txt
roles角色管理 roles的作用就是为了更好的移植项目playbook如果在大型项目中例如openstack的部署ceph的部署等项目中可能会有很多的任务以及外部依赖的文件还有各种需要拷贝的模板如果仅仅只是将playbook复制给其他人进行使用其他人因为缺少文件或者是模板将导致playbook执行失败那么roles的引入就是为了将一个项目的playbook 以及该项目用到文件、模板、外部的变量等打包成一个文件我们将这个文件称为roles角色 直接在角色中对项目进行开发 ansible 2.9 以前 使用的是角色—— r roles oles 包含playbook、文件模板、普通文件、变量…. ansible 2.9 以后 使用的是集合 —— collection 包含 模块、插件、角色 ansible 将不再和 模块同步更新也就是模块可以更新的更快 将ansible以容器的方式提供给用户进行使用可以通过安装集合来获得指定的模块 角色的组成
files用于存放一些非模板文件的文件如https证书等。
tempaltes用于存放角色相关的Jinja2模板文件当使用角色相关的模板时如未明确指定模板路径则默认使用此目录中的模板
tasks角色所要执行的所有任务文件都存放于此包含一个主文件main.yml可以在主文件中通过include的方式引入其他任务文件
handlers用于定义角色中需要调用 的handlers包含一个主配置文件main.yml可通过include引入其他的handlers文件。
vars用于定义此角色用到的变量包含一个主文件main.yml
meta用于存储角色的元数据信息这些元数据用于描述角色的相关属性包括作者角色的主要作用角色的依赖关系等。默认这些信息会写入到当前目录下的main.yml文件中
defaults除了vars目录defaults目录也用于定义此角色用到的变量与vars不同的是defaults中定义的变量的优先级最低。 创建角色的步骤 1. 在roles的目录中创建一个以角色名命名的目录目录的名字就是角色的名称 2. 在创建的目录下创建所需的角色配置的子目录如tasks、file、defaults、templates… 不需要的角色配置目录可以不创建或者保留空白目录 3. 编写playbook来调用这个角色
拆分角色中的任务 通过include_tasks 来对tasks目录中的任务进行拆分 在tasks目录中的main.yml中使用 include_tasks: file: 拆分的任务文件 进行引入任务
在playbook中有两类特殊的任务 pre_tasks 中的任务在执行角色之前执行 post_tasks 中的任务在执行角色之后执行
- hosts: node1 pre_tasks: - debug: msg: start roles roles: - apache post_tasks: - debug: msg: end roles
获得角色的方式 1.通过ansible的仓库来进行获取 ansible-galaxy galaxy.ansible.com 来搜索下载角色 ansible-galaxy search role-name 搜索角色 ansible-galaxy role install role-name 安装角色 ansible-galaxy list 查看角色 ansible-galaxy init role-name 创建一个角色目录结构 ansible-galaxy role install url的地址 -p 角色存放的目录 离线进行安装 ansible-galaxy role install -r download.yml -p roles -r 表示后面接yml文件 -p 角色的存放的目录 download.yml - name: 角色名此处写什么角色名安装后角色就叫这名称 src: url的地址 ansible-galaxy remove role-name 删除角色 ansible-galaxy info role-name 查看角色的详细信息 2. 红帽提供了RHEL的系统管理角色包 selinux、时间同步、postfix、firewalld … 可以通过使用红帽的role角色来管理系统 yum install rhel-system-roles -y
Ansible Vault 加解密 1. 创建一个加密文件 ansible-vault create file.yml 2. 查看一个加密文件 ansible-vault view file.yml 3. 解密一个加密文件 ansible-vault decrypt file.yml 4.加密一个存在的文件 ansible-vault encrypt file.yml 5.修改加密文件的密码 ansible-vault rekey file.yml 6. 运行带有加密内容的剧本 6.1 在运行playbook时通过命令行指定密码 ansible-playbook file.yml --ask-vault-pass 6.2 在运行playbook时 通过文件读取密码 ansible-playbook file.yml --vault-password-file pass.txt cat pass.txt 将密码写入到pass.txt文件中通过文件传递密码给playbook redhat
Ansible的导航器 使用容器来运行ansible的playbook用容器运行playbook的优势在于可以摆脱对物理机上ansible版本的依赖 ansible的导航器只能用来运行playbook 而不能运行ad-hoc ansible-navigator run -i 主机清单的位置 file.yml -m stdout run 用来运行playbook -i 指定主机清单的位置 -m 指定输出的模式 可视化模式在容器中以可视化的形式显示 字符模式 -m stdout 就是字符模式
ansible的自动化执行环境 vim ~/.ansible- navigator.yml
ansible-navigator: execution-environment: image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8 pull: policy: missing