导图社区 ansible
关于ansible的思维导图,包含环境搭建、帮助命令、剧本拆分、角色使用、数据加密、模块介绍等内容。
编辑于2021-10-12 21:15:50ansible
环境搭建
ansible的环境搭建要明白ansible本身就是为集群服务的。 所以环境搭建的每一个配置的修改都是为了更好的识别主机和掌控受控主机
修改主机名
hostnamectl set-hostname 主机名
设置静态ip地址
nmcli connection add con-name "网络连接名" type ethernet ifname 网卡名 autoconnect yes ipv4.method manual ipv4.addresses 静态ip地址 ipv4.gateway 网关地址 ipv4.dns 114.114.114.114
主机名与ip地址映射
vim /etc/hosts ip地址 主机名
ssh免密登录
注意,控制主机要远程登录哪台机子,就把自己的ssh公钥发送给谁。(难点在于用户的确定,如果是普通用户登录,那么首先将控制主机的用户切换成普通用户) ssh-keygen ssh-copy-id -i /home/普通用户/.ssh/id_rsa.pub 普通用户名@受控主机名
设置普通用户的sudo权限
进入受控主机,在root用户下将普通用户的sudo命令设置成免密使用。(所有机子都设置) [root@servera ~]# visudo 普通用户名 ALL=(ALL) NOPASSWD: ALL
安装anisble
yum install -y ansible 将/etc/ansible目录复制到用户的家目录。用户编写anisble项目。 [ansible@workstation ansible]$ ll total 24 -rw-r--r--. 1 root root 19985 Sep 4 06:31 ansible.cfg -rw-r--r--. 1 root root 1016 Sep 4 06:31 hosts drwxr-xr-x. 2 root root 6 Sep 4 06:31 roles [ansible@workstation ansible]$
设置清单文件
vim inventory #编辑清单文件 文件格式如下 [组名1] 主机名1 主机名2 [组名2] 主机名1 主机名3 [组名3:children] 组名1 组名2
设置ansible的配置文件
vim ansible.cfg #文件内容如下 [defaults] inventory=./inventory remote_user=user ask_pass=false [privilege_escalation] become=true become_method=sudo become_user=root become_ask_pass=false
一些额外的配置信息
fork 设置并行,例如fork=5,受控主机为10,那么会批量运行5台。 serial 管理滚动更新,例如在一共有5台机子,如果同时更新,那么服务就停止了,此次可以设置serial为2,那么只有2台在运行更新,其他3台保证服务正常运行。
帮助命令
在ansible里一定要善于使用帮助命令,而不是一味的死记硬背。 尤其学会查看和使用ansible-doc 模块名 中的例子
ansible --version
查看ansible版本以及所使用的的配置文件路径
ansible-doc -l
列出所有模块 该模块可以搭配grep命令进行模块过滤 例如,yum_repository模块 由于名字过长记不住时, 可以使用ansible-doc -l | grep yum [ansible@workstation test_project]$ ansible-doc -l | grep yum yum Manages packages with the `yum' package manager yum_repository Add or remove YUM repositories
ansible-doc 模块名
查看模块的使用方法 主要用于查看例子 [ansible@workstation test_project]$ ansible-doc yum EXAMPLES: - name: install the latest version of Apache yum: name: httpd state: latest
ad-hoc
注意:临时命令一般用于ansible的命令的测试或者结果查看,由于临时命令的一次性,不建议用于通过ansible控制受控节点的主要方式。
ansible hostname -m ping
查看控制节点和受控节点的联通性。注意:只是连通性。并不能测试ansible命令在受控主机的权限问题
ansible hostname -m shell -a "命令"
利用ansible临时命令在受控主机上执行shell命令 习惯使用该命令来查看受控主机的运行结果与状态。 例如查看每一台受控主机的块设备的情况 ansible all -m shell -a "lsblk"
ansible hostname -m command -a "命令"
command模块不支持shell中的管道和重定向等高级用法
利用shell执行ad-doc命令
示例安装yum仓库 #!/bin/bash ansible all -m yum_repository -a "name=EX300_BASE description='EX300 BASE software' baseurl=http://exam.redhat.com/BaseOS gpgcheck=yes gpgkey=http://exam.redhat.com/RPM-GPG-KEY-redhat-release enabled=yes " ansible all -m yum_repository -a "name=EX300_AppStream description='EX300 AppStream software' baseurl=http://exam.redhat.com/AppStream gpgcheck=yes gpgkey=http://exam.redhat.com/RPM-GPG-KEY-redhat-release enabled=yes " 完成后chmod a+x 脚本文件名.sh #赋予执行权限
playbook
playbook一般适用于小型项目的使用,比起ad-doc命令,它可以以yml文件的形式,保存在本地,并多次使用。
创建
playbook的创建时,要学会使用anisble-doc 模块名来查看手册。
yml文件
yml文件的文件名的后缀为.yml 文件内容以---开头,以...结束,但是...可以省略。 yml文件对于缩进有着严格的要求,这也是初学者最容易犯的错误 同一级别的元素必须具有相同的缩进 如果项目为其他项目的子项,那么缩进必须必父项大。 play的第一行开头应该为破折号加空格(表示该play是列表中的第一项) name:显示任务的用途 hosts:指定受控主机 tasks:要运行的任务列表
管理变量
变量的命名格式:必须以字母开头,并且只能含有字母,数字和下划线。 playbook中命名变量的位置,一般在playbook开头的vars块中以及通过vars_files访问外部定义的变量文件。 在不确定变量的输出值时,要多利用debug模块。
变量
一般变量是以键值的方式来定义的,可以通过{{}}来引用变量,但是如果该变量用作开始的第一个元素值,必须使用"" ,即 ....... vars: user:joe ....... tasks: ......... user: name:"{{ user }}" ...........
普通变量
普通变量一般就是指由用户自己定义的变量。
注册变量
注册变量其实是将整个任务的输出结果作为变量存储起来。可以利用debug模块来输出注册变量的值 
事实变量
事实变量是指ansible能够在受控主机上检测到的变量。里面包含了受控主机的相关信息。通过对事实变量的调用来获取受控主机的信息。在ad-doc命令中可以使用ansible 主机名 -m setup来输出指定主机的事实变量(注意可以使用重定向来讲输出信息保存到本地,从而利于查找过滤命令来找相关值。)当然也可以直接在命令行中使用filter来过滤出直接想要的信息(支持*模糊查询) 示例:[ansible@workstation test_project]$ ansible servera -m setup -a "filter=*ipv4*" 在playbook中可以使用gather_facts来控制事实收集的开关 常见的事实变量有: 短主机名 ansible_facts['hostname'] 完全限定的域名 ansible_facts['fqdn'] 主要IPv4地址 ansible_facts['default_ipv4']['address'] 所有网络接口的名称列表 ansible_facts['interfaces'] /dev/vda1磁盘分区大小 ansible_facts['devices']['vda']['partitions']['vda1']['size'] dns服务器列表 ansible_facts['dns']['namservers'] 当前运行的内核版本 ansible_facts['kernel']
魔法变量
魔法变量也是用来显示受控主机的相关信息,但并不属于setup模块和事实变量。 常用的有4个: hostvars: 包含受控主机的变量,可以用于获取另一台受控主机变量的值,可以利用它来收集另一个受控主机的事实变量 group_name: 列出当前受控主机的所属的所有组 groups: 列出清单中所有组和主机 inventory_hostname: 包含清单中配置的当前受控主机的主机名。
数组
变量的方式都是以键值的方式来定义的,我们通过键来访问保存在键中的值。 而一般变量是一键一值。注意:使用数值的取值最好也使用循环,这样效率高也不容易出问题。 而数组的形式是一键多值的方式(当然一键一值也是可以的。)  运行结果 
字典
数组如果是一键多值,那么字典和散列就是多键多值。 
判断
在ansible里所谓的判断其实就是判断是否满足条件。满足条件才运行,如果不满足则不运行。 使用的是when语句(注意:when语句是和任务同一级别。)。示例:测试my_service变量是否具有值,如果有值则运行任务,如果没有值,则跳过任务。  一些常见的判断条件。(多个条件判断可以使用and或者or连接,并搭配括号来设置分组条件。) 
循环
在ansible中,循环的本质就是遍历。普通变量的一键一值是不需要用到循环的。而一般用到循环的情况,都是数组和字典格式的变量。利用循环可以遍历和取出数组和字典里的每一个值。 使用的是loop语句。注意loop应该是和任务同一级别的。不需要额外缩进。
触发器
触发器其实就是根据任务运行中的change参数是否发生改变来决定是不是运行,一旦发生改变触发后就会运行handlers里的任务。 注意:notify中可以放入多个触发任务。使用方法如下。 
忽略失败
忽略任务失败使用的是ignore_errors语句,可以防止因为任务失败而导致程序运行的终止。 
块处理
通过block块语句可以搭配其他语句对多个任务进行统一管理,例如when,ignore_errors
异常处理
利用block块语句,可以结合rescue和always语句来处理错误。 block : 定义要运行的主要任务 rescue: 定义要在block子句中定义的任务失败时运行的任务。 always: 定义始终都独立运行的任务,无论block和rescue子句中定义的任务是成功还是失败。(但是运行的触发条件还是block中的任务) 
运行
虽然playbook的运行方式看起来很烦,但是三种运行方式的使用,能大大提高排错的效率,缩小排错的范围。
ansible-playbook --syntax-check yml文件名
该命令用来检测语法。如果这一步报错,排错一般从2个角度考虑。第一个缩进是否对齐,第二ansible关键词的语法和拼写是否写错,例如:name写成names之类
ansible-playbook -C yml文件名
这一步是用来模拟运行,但是注意模拟运行成功不代表真实运行就一定成功,因为受控主机的环境是有区别的。有时候playbook本身没有问题,但是受控端主机自己出问题了。 当然,模拟运行失败也不代表真实运行就失败,典型的例子就是磁盘管理中的,卷组的建立,需要加入分区,而模拟运行并不会真正创建分区,导致卷组创建失败,但真实运行不会有这个问题。
ansible-playbook yml文件名
真实运行,注意真实运行时修改受控主机的配置等信息。
排错
playbook的排错有以下思路: 在语法检查时报错: 查看缩进有没有问题 playbook中的语法和关键词有没有写错 模拟运行时报错: 模块中的关键词中所需的参数有没有写错。如state:present 写成state: persent 判断语句或者循环语句中的逻辑关系有没有理清 模拟运行本身的缺陷。例如磁盘管理中。卷组的创建需要前面分区成功。模拟运行并不会真正的产生分区。 真实运行时报错(包含了不报错但是结果不对) 一般前面2个都运行没有报错的话,到这边报错,是不是when这些语句写错。比如由于主机名写错,虽然进行了判断,但是却没有真正执行。 事实变量和魔法变量在取用时,格式有没有问题。 注意:ansible的本质就是将控制主机上编写的任务交给受控节点去执行,所以所有编写的ansible脚本都可以转换成我们学过的shell命令直接在受控主机上跑一遍,如果觉得自己的playbook没有问题,但是还是报错,那么可以使用该方法去受控主机上排错。查看是不是受控主机本身出了问题。
剧本拆分
将任务和变量进行拆分,便于对playbook项目的统一管理,所以对比于一般的playbook任务,经过拆分的剧本更适合中等项目。
变量拆分
变量的拆分本质就是将堆在playbook中的变量,放在外部存储变量文件中,然后使用vars_files关键字将外部变量文件导入。 虽然vars_files从外部文件读取变量,但是外部变量文件的编写也要遵守yml文件的格式 具体示例如下 变量文件 cat vars_test.yml --- - name1: xxr users: - user_name: a age: 12 - user_name: b age: 13 arrays: - 15 - 16 - 17 playbook文件 cat vars.yml --- - name: test vars_files hosts: servera vars_files: - ./vars_test.yml tasks: - name: msg var debug: msg: "{{name1}}" - name: msg var debug: msg: "{{item.age}}" loop: "{{ users }}" - name: msg arrays debug: msg: "{{arrays}}"
任务拆分
动态任务和静态任务的区别,可以使用ansible-playbook --list-tasks列出playbook中的任务,可以看到区别。静态任务,在运行前就已经提前加载好,而动态任务,在运行时才会主动加载。
import_tasks
将任务文件静态导入playbook内的play中。
include_tasks
利用include_tasks将任务动态的导入playbook内的play中。只有在运行到该任务时,才会加载。
角色使用
其实无论是项目拆分还是角色都是为了更好的管理playbook,由项目的拆分到角色,其实就是由官方指定了一种框架,围绕着这个框架来编写playbook,将功能细化。 角色可以分组内容,从而与他人轻松共享代码。 可以编写角色来定义系统类型的基本要素:例如web服务器 角色使得较大型项目更容易管理 角色可以由不同的管理员并行开发。 ansible-galaxy list命令可以列出本地能找到的角色
系统角色
由官方提供,用来管理系统的角色 rhel-system.roles.kdump 配置kdump崩溃恢复服务。 rhel-system.roles.network 配置网络接口。 rhel-system.roles.selinux 配置和管理SELinux模式、文件和端口上下文。布尔定义值设置,以及selinux用户 rhel-system.roles.tiemsync 使用网络时间协议或精确时间协议配置时间同步。 rhel-system.roles.postfix 使用Postfix服务将每个主机配置为邮件传输代理。 rhel-system.roles.firewall 配置主机的防火墙。 rhel-sysstem.roles.tuned 配置tund服务,以调优系统性能。
安装软件
yum install rhel-system-roles 注意: 如果忘记了包的具体名字。可以使用yum list | grep role 来过滤出完整的系统包名。 系统角色的默认安装位置在/usr/share/ansible/roles/ 为了方便统一管理,建议将安装在默认位置下的角色复制到项目目录下的roles目录。
查看手册
系统角色文档默认的安装位置在/usr/share/doc/rhel-system-role-<version>/目录中查看README文件来查看 当然在系统角色的安装位置也有查看的README文档
使用方法
注意:角色只是playbook的各个组件,就像一辆汽车的零件,虽然是在不同的产地生成,但是真正在使用时就要把这些零件给组装起来。 要访问角色,可以在play中使用roles: 部分来引用。 例子:
Galaxy角色
galaxy是一个公共的ansible角色资源库,类似yum仓库一样。
安装软件
ansible-galaxy search "角色名" --platforms EL (适用于EL级企业linux平台的角色) ansible-galaxy info 角色名 从ansible-galaxy安装角色 ansible-galaxy install 角色名 -p 指定安装路径 (可以使用-p来指定安装路径,防止安装到默认路径上) 使用要求文件安装角色 首先编辑一个yml文件用来存放定义的变量 例如最常见的2种写法:  注意:src首先是匹配的是ansible galaxy中的角色,如果没有则将使用指明角色的url。 如果角色托管在来源控制存储库中,则需要使用scm属性。ansible-galaxy命令能够从基于git等 软件存储库下载和安装角色。 name用来覆盖角色的本地名称。 2.使用-r指定role文件的安装位置。 
查看手册
下载可以进入角色目录查看README来参考。
使用方法
建立playbook然后使用roles:来使用角色。
创建角色
创建角色目录结构 定义角色内容 在playbook中使用角色 注意:每个角色应该有自己特定的用途,而不是把任何任务都堆在同一个角色中。
角色结构
使用命令ansible-galaxy init来创建新角色的目录结构。 角色完成后,可以将没有用到的目录删掉。
defaults
默认变量值
files
执行任务时所需要的静态文件
handlers
notify触发任务时,所编写的触发任务。
meta
编写角色相关的信息,如作者,许可证,平台以及角色的依赖
templates
角色所需的jinja2模板
tests
可以包含清单和test.yml playbook,可以用于测试角色
vars
定义角色的变量值,此处的变量值优先级较高,用于角色内部的定义
README.md
一般用来解释该角色的使用方法和功能。
jinja2语法
Jinja2是Python下一个被广泛应用的模版引擎,他的设计思想来源于Djanjo的模板引擎,并扩展了其语法和一系列强大的功能。ansible的模板配置文件就是用jinja2这种模板编程语言写
变量
jinja2模板中使用 {{ }} 语法表示一个变量
循环
在jinja2使用的是for循环 结构如下: {% for user in users %} {{ user }} {% endfor %}
判断
单分支
{% if vhost.server_name is defined %} server_name {{ vhost.server_name }} {% endif %}
多分支
{%if vhost.port is undefined %} http_port=80 {%elif vhost.port == 81%} http_port=81 {%else%} http_port = 83 {%endif%}
注释
{# 需要注释的代码 #}
defalult('')
当想要输出的值不存在的话,可以利用管道符,显示default("")中的值。例如 "{{ 变量值 | default('默认值')}}"
使用角色
建立playbook然后使用roles:来使用角色。
数据加密
ansible-vault
create
创建playbook的同时设置密码
edit
对加密的文件进行编辑
view
查看加密的文件内容
encrypt
对已有文件进行加密
rekey
重置密码
decrypt
取消设置的密码
ansible-playbook
由于文件设置了密码,所以在使用ansible-playbook时,也要进行解密。
--ask-vault-pass
以交互的方式来输入密码,注意该方式只支持输入一份密码,即如果playbook出现多个加密文件,且密码各不相同,那么改方法不行。
--vault-id @prompt
以交互的方式来输入密码,但是支持多份密码输入。可以使用 --vault-id 加密文件名@prompt 来指明对特定文件的解密
--vault-password-file
将密码以文件的形式保存在本地,然后指定密码的路径来进行解密。注意:多个密码文件可以无序,命令运行时会自动测试密码的正确,如果不对会自动尝试下一个。
模块介绍
用户管理
user
示例: - name: Add the user 'johnd' with a specific uid and a primary > user: name: johnd uid: 1040 group: admin 参数补充1:(为用户添加附加组) groups: 附加组 append: yes 参数补充2: password: 密码 | password_hash( "sha512" )
group
- name: Ensure group "somegroup" exists group: name: somegroup state: present
软件管理
yum_repository
- name: Add multiple repositories into the same file yum_repository: name: epel #仓库名 description: EPEL YUM repo #源的描述 file: external_repos #yum配置的文件名,如果不设置的话,默认以name的值为配置文件名。 baseurl: https://download.fedoraproject.org/pub/epel/$relea> # yum包的制定路径 enabled: yes #启用仓库 gpgcheck: no #启用gpg校验 gpgkey: gpg校验路径 #指明gpg校验的路径 注意:如果使用shell脚本来执行yum_repository模块,要使用到ad-doc命令,但是参数由冒号改用等号=
yum
示例1:(安装软件组,) - name: install the 'Development tools' package group yum: name: "@Development tools" state: present 示例2:(安装软件) - name: install one specific version of Apache yum: name: httpd state: present 注意: state中有3个选择,present(如果没有安装,那么安装)。latest(更新软件,如果没有安装,自动安装最新版本)。absent(如果已安装,则删除该软件)
systemd
示例1: - name: enable httpd systemd: name: httpd #启动的软件包 state: started #启动,关闭是stoppd enabled: yes #设置开机自启
firewalld
- firewalld: service: http # 需要放过的服务 permanent: yes # 永久生效 zone: public # 属于public配置 state: enabled # 是否启用 immediate: yes # 立即生效
文件管理
file
示例1:创建目录,权限为0775,其中第一个0的位置指的是特殊权限 - name: Create a directory if it does not exist file: path: /etc/some_directory state: directory mode: '0755' 其他参数: ower: 文件所有者 group: 文件所属组 示例2:创建链接 - name: Create a symbolic link file: src: /file/to/link/to dest: /path/to/symlink owner: foo group: foo state: link
copy
示例1:(将content后面的内容复制到dest后面的地址上) - name: Copy using inline content copy: content: '# This file was moved to /etc/other.conf' dest: /etc/mine.conf 注意:copy命令是将控制主机上的文件复制到受控主机上。
template
template可以用来处理jinjia2文件。通过对jinjia2语法进行解析,在受控主机上生成配置文件。 - name: Template a file to /etc/files.conf template: src: /mytemplates/foo.j2 dest: /etc/file.conf
lineinfile
# NOTE: Before 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path' - name: Ensure SELinux is set to enforcing mode lineinfile: path: /etc/selinux/config regexp: '^SELINUX=' line: SELINUX=enforcing 通过正则表达式来对指定文件/etc/selinux/config的行进行替换。
get_url
- name: Download file from a file path get_url: url: file:///tmp/afile.txt dest: /tmp/afilecopy.txt 从受控主机指定路径复制文件到受控主机路径。
磁盘管理
parted
- name: Create a new primary partition with a size of 1GiB parted: device: /dev/sdb number: 1 state: present part_end: 1GiB
lvg
- name: Create a volume group on top of /dev/sda1 with physical extent size = 32MB lvg: vg: vg.services pvs: /dev/sda1 pesize: 32 创建卷组,vg后跟卷组名,pvs:将分区转化成物理卷并加入卷组,多个分区用逗号隔开。 pesize:指定pe的大小,默认单位M
lvol
- name: Create a logical volume of 512g. lvol: vg: firefly lv: test size: 512g 参数说明: vg:卷组名 lv: 逻辑卷名 size: 逻辑卷大小
filesystem
- name: Create a ext2 filesystem on /dev/sdb1 filesystem: fstype: ext4 dev: /dev/sdb1 参数说明: fstype: 文件系统类型 dev: 要格式化的目标路径
mount
- name: Mount a volume mount: path: /system/new_volume/boot src: /boot state: mounted fstype: ext4 参数说明: path: 存储设备路径 src: 挂载点 state: mount(临时挂载),(mounted,永久挂载)