云原生俱乐部-RH294知识点归纳(1)
今天是8-20号,和预期的时间差不多。在此之前已经将mysql和shell的内容整理完毕,虽然这两个都很仓促。不过现在需要同一时间写ansible和k8s系列的内容了,难度要大一点,而且ansible的课程也正在进行中,今天是学习ansible的第二天,虽然五一的时候学过一遍(旁听)。
k8s还有篇草稿k8s知识点归纳(5),一直留着没发,因为突然意识到还有内容没有学到。毕竟是五天的课程,只能先把握住整体框架,不过今天会发布的。至于这篇文章的话,现在是十一点,大概晚上才能够发布,因为规划的本篇第四部分内容下午才开始讲。
我这篇文章主要会介绍ansible,实施ansible playbook,管理事实和变量以及实施任务控制这四部分内容。
介绍ansible
Ansible 是一款开源的自动化运维工具,红帽ansible自动化平台包括ansible core和ansible modules(ansible content collect内容集合)和自动化内容导航器和自动化执行环境等。
Ansible Core提供运行playbook的基础功能,并且定义了用于在YAML文件中编写ansible playbook的自动化语言。Ansible Content Collections是模块、插件、Playbook 的标准化分发单元。
自动化执行环境一个预配置的容器化环境,包含运行 Ansible 所需的ansible core、ansible内容集合,以及Python依赖库和其他可执行文件;自动化导航器则是一个命令行交互工具。
实施ansible playbook
[1]定义清单文件
ansible-navigator inventory -m stdout -i inventory 可以显示主机清单的信息,使用-i 是指定清单文件路径,不指定默认在/etc/ansible/hosts中。
如果未指定-m stdout则会以交互式的方式输入主机清单文件的信息,因为-m是mode的意思,stdout则是标准输出,默认是虚拟终端。
主机可以用192.168.241.[10:20]可以指定范围内的主机,主机组使用[],主机组可以使用[:children]来指定子主机组实现嵌套。
[2]管理ansible配置文件
ansible.cfg用于配置ansible的行为,基本配置包括[defaults]和[privilege_escalation]两部分,[defaults]部分包括inventory路径,remote_user远程用户和ask_pass(是否远程输入密码,默认false,使用ssh免密)等基础选项。
[privilege_escalation]用来定义ansible是否需要在受管主机执行升权。包括become、become_method、become_user和become_ask_pass这几个选项。一般不使用become_method=true选项,而是推荐在playbook中使用become: true,按需提权。
通过ansible-navigator.yml文件配置,可以指定自动化执行环境(容器镜像名称),还可以指定是否使用artifact。artifact叫工件,用于记录palybook的执行日志,如果使用ask_pass或者become_ask_pass,必须禁用工件避免将密码记录到日志中。
可以用ansible-navigator config命令来查看配置文件信息,包括加载的ansible.cfg和ansible-navigator.yml文件的配置信息。
[3]定义playbook
playbook 是 Ansible 的自动化脚本,文件里面包含一个或多个play,每个play使用name描述该play的主要功能,通过hosts指定目标主机,使用tasks定义任务列表,每个任务调用一个 Ansible 模块。
在YAML文件中,key: value 表示键值对,值有字符串类型,数值类型,bool值类型;注释符使用#和;,第二个是行间注释符;列表可以用-对齐,也可以用[]表示;使用 | + 换行缩进表示多行文本(保留换行),使用 > + 换行缩进表示多行文本(折叠为一行);{{ }}用于变量插值。
管理事实和变量
[1]管理变量
主机组变量、主机变量、主机事实、play变量、任务变量、命令行变量,这些变量的优先级由低到高。变量取值时建议将{{ variable }}用双引号引号括起来,可以避免YAML将变量视为关键字,如{{ service }}。
建议在项目中将变量和主机清单文件分离开来,比如使用host_vars和group_vars目录,里面定义对应的主机变量和主机组变量。不过可以在主机清单文件中使用[hosts:vars]定义主机组变量,主机变量则是跟在主机的后面。
[2]注册变量
使用register: install_result可以将该模块的输出注册到install_result变量中,并且同一个play中后面的task也能够使用该变量。`install_result` 是一个Python 字典,在 Ansible 中表现为类似 JSON 的结构。
然后可以使用ansible.builtin.debug来输出该变量的值,使用var就是完整打印变量内容,使用msg可以自定义输出部分字段。
[3]管理机密
ansible可能需要访问敏感的数据,可以使用ansible-vault命令行工具来创建、加密、编辑数据。推荐使用密码文件(chmod 600)给敏感文件加密,然后可以在ansible-navigator.yml文件中指定vault字段的passwrod_file的路径。
或者在命令行中使用--password-file-pass来指定密码文件的路径,否则就要使用--vault-id @prompt来手动输入密码。如果要手动输入密码的话需要禁用工件,如ansible-navigator run -m stdout --palybook-artifact false name.yml --syntax-check --vault-id @prompt。
[4]管理事实
事实由ansible.builtin.setup收集,都是预定义变量,如主机名称,内存情况,cpu数量,网络IP(接口),操作系统版本等,主机名称可以用ansible_facts['hostname']表示,也可以用ansible_facts.hostname来表示。
单引号禁用变量插值和转义字符,也就是\n换行也用不了,如果单引号内要嵌套单引号,用两个单引号表示一个。上面的ansible_facts['hostname']使用单引号,因为是键的匹配,键本身是字符串类型。
可以创建自定义事实,由ini格式或者json格式定义,文件扩展名必须为.fact,默认放在目标主机的/etc/ansible/facts.d目录下。使用ansible_facts.ansible_local(前缀)来获取该自定义变量,如果默认目录下有名为package.fact文件,可以用ansible_facts.ansible_local.package定位。
实施任务控制
[1]loop语句
通过loop语句定义items列表,使用循环变量item来取值。loop语句是task任务级别的,可以多次执行内容差不多的task。不过有时候使用loop不是最高效的解决方案,loop是运行多个task,但是有时候可以直接将变量列表传递给模块,这样就是一个task运行多次模块。
也可以先定义变量列表,再将变量列表赋值给loop,如loop: "{{ variableList }}"。如果是变量列表的话,如myservice: [httpd, sshd],可以直接用循环变量{{ item }};如果是字典列表的话,如
mydic: [service: sshd, state: started],需要使用{{ item['service'] }}来取值。
[2]条件语句
在task任务可以使用when字段,在条件满足时才运行任务;使用changed_when重新定义changed状态的触发条件,以及使用fialed_when重新定义task执行失败的条件,如果条件满足效果和正常失败是一样的,也就是会导致该play的后续tasks都不运行。
可以使用and 和 or来判断联合条件,可以使用()来将条件判断圈起来,如when: ( a >1 and b > 2 ) or ( c <3 and d <8 ),在when语句中使用变量不需要使用{{}}取值。
[3]handler处理程序
在playbook中,如果task的状态是changed,则可以使用在task中使用notify通知执行handler(notify的值与handler的name值相同);如果有通知才执行,一次或多次通知也只执行一次。并且hander处理程序是在所有的task执行后才开始按定义顺序执行。
当任务失败时,会中断play,后续的task并不会执行,但是该playbook的后续play会执行(如果handlers中的任务失败也会导致play的中断)。
如果play中任务处理失败,那么该play中所有的hanler都不会执行,即使使用ignore_errors来跳过失败任务,可以在tasks前定义force_handlers: yes来让handlers程序正常执行。
[4]block任务快
我们可以用block来将一组的task封装起来,然后在block(与原task同级别,子task需要缩进)同级别可以设置when,这样就可以让这组task都应用该条件判断。
block还可以和rescue以及always一起使用,这三个都是同级别的,只有在block失败时才运行rescue中的任务,always的任务一直都会运行。
如果给block设置when条件,失败时整个block、rescue和always都会跳过。如果block失败了,不会导致后面的tasks停止运行,即使没有配置ignore_errors,因为rescue会执行,除非rescue也失败了。