Saturday, April 27, 2019

CentOS 7.6安装使用Ansible Part1

(一):Ansible简介、安装、配置文件及常用选项


一、Ansible简介:
Ansible是一个基于Python开发的开源自动化工具,实现了批量运行命令、批量部署程序、批量配置系统等功能。默认通过SSH协议(也可使用其它协议)进行远程命令执行或下发配置,无需部署任何客户端代理软件(agentless)在被管控主机上,并可同时支持多台主机并行管理。Ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署的是Ansible所运行的模块,Ansible只是提供一种框架。Ansible 2.7帮助文档:https://docs.ansible.com/ansible/latest/index.html


Ansible特性:
Ø  模块化:调用特定模块完成特定任务;
Ø  基于Python语言实现,依赖paramikoPyYAMLJinja2httplib2simplejsonpycrypto等模块
Ø  部署简单:agentless,无需在被管控主机中安装任何软件,而是通过一些标准的协议,如:SSH
Ø  支持自定义模块;
Ø  支持playbook
Ø  幂等性:Ansible是以“结果为导向的”,如果指定了一个“目标状态”,ansible会自动判断,“当前状态”是否与“目标状态”一致,如果一致,则不进行任何操作,如果不一致,那么就将“当前状态”变成“目标状态”,这就是幂等性,幂等性可以保证重复执行同一项操作时,得到的结果是一样的。

Ansible架构图:
image.png
从上图可以了解到其由以下部分组成:
Ø  Host Inventory:主机清单,定义Ansible管理的远程主机,默认是在Ansible hosts配置文件中定义
Ø  Ansible:核心程序
Ø  Connection Plugins:连接插件,用于和被管理主机实现通信,除支持使用SSH连接被管理主机外,Ansible还支持其它的连接方式
Ø  Playbooks:剧本,集中定义Ansible任务的配置文件,即将多个任务定义在一个剧本中Ansible自动执行,可以由控制主机针对多台被管理主机同时运行多个任务
Ø  Core Modules:核心模块,Ansible自带模块,使用这些模块将资源分发至被管理主机,使其执行特定任务或匹配特定状态
Ø  Custom Modules:自定义模块,用于扩展核心模块功能,支持多种语言
Ø  Plugins:插件,可借助相关插件完成记录日志、发送邮件等功能

二、Ansible安装、常用配置文件、常用命令集及命令选项介绍:
1、演示环境:
IP
操作系统
主机名
服务器角色
192.168.1.143
CentOS   7.6 x86_64
143
Ansible主机
192.168.1.144
CentOS   7.6 x86_64
144
被管控主机
192.168.1.220
CentOS   6.10 x86_64
220
被管控主机
2、Ansible主机安装前准备工作:
(1)配置/etc/hosts# tail -3 /etc/hosts
image.png
(2)生成密钥对,基于密钥认证:# ssh-keygen -t rsa -P ""
image.png
(3)复制公钥至所有被管控主机:
# ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected]
image.png
# ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected]
image.png
3、Ansible主机安装epel源和ansible# yum -y install epel-release  # yum -y install ansible
备注:CentOS 7.6yum安装的ansible版本为2.7.10python版本为2.7.5
4、常用配置文件:
Ø  /etc/ansible/ansible.cfg:主配置文件,配置ansible工作特性
Ø  /etc/ansible/hosts:定义被管控主机主机清单的配置文件
Ø  /etc/ansible/roles:存放角色的目录
5、常用命令集:
Ø  /usr/bin/ansibleAnsibe ad-hoc临时命令执行工具
Ø  /usr/bin/ansible-docAnsible模块功能查看工具
Ø  /usr/bin/ansible-galaxy:下载/上传优秀代码或Roles模块至官网平台
Ø  /usr/bin/ansible-playbookAnsible定制自动化的任务集编排工具
Ø  /usr/bin/ansible-pullAnsible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
Ø  /usr/bin/ansible-vaultAnsible文件加密工具
Ø  /usr/bin/ansible-consoleAnsible基于Linux Console界面与用户交互的命令执行工具
6、Ansible主机配置被管控主机的主机清单文件:
# vim /etc/ansible/hosts,末尾新增如下代码:
[websrvs]
192.168.1.144
192.168.1.220
[dbsrvs]
192.168.1.144
备注:
Ø  websrvsdbsrvs表示主机组名
Ø  主机可以使用域名、主机名、IP地址表示,使用前两者时,也需要主机能反解析到相应的IP地址
7、Ansible主机对被管控主机的操作方式说明:
(1)ad-hoc模式(点对点模式):使用单个模块,支持批量执行单条命令。ad-hoc命令是一种可以快速输入的命令,而且不需要保存的命令。
(2)playbook模式(剧本模式):Ansible主要管理方式,也是Ansible功能强大的关键所在。playbook通过多个task集合完成一类功能,可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。
8、ad-hoc临时命令执行工具ansible的使用格式:# ansible <host-pattern> [options]
(1)<host-pattern>:在/etc/ansible/hosts中定义的被管控主机IP地址或域名的列表
Ø  all*表示匹配所有主机,?表示匹配单个字符
Ø  *?使用时必须要加'',如:# ansible '*' -m ping# ansible '192.168.1.22?' -m ping
Ø  'websrvs:dbsrvs'表示目标主机在websrvs组或dbsrvs组中,2个组中所有的主机
Ø  'websrvs:&dbsrvs'表示目标主机同时在websrvs组和dbsrvs组中
Ø  'websrvs:!dbsrvs'表示目标主机在websrvs组,但不在dbsrvs组中
Ø  192.168.1.*表示匹配192.168.1网段的所有目标主机
(2)[options]
Ø  -m MODULE_NAME:执行的模块名称,可通过命令“# ansible-doc -l | less”查看目前已安装的所有模块,不指定模块时,默认使用的是command模块,在配置文件/etc/ansible/ansible.cfg的“#module_name = command”中定义
Ø  -a MODULE_ARGS:模块参数,通常为key=value的格式,可通过命令“# ansible-doc -s 模块名”查看具体的用法及详细参数
Ø  --syntax-check:对playbook执行语法检查,并不真正执行
Ø  -C:尝试预测可能发生的一些变化,并不真正执行
Ø  --list-hosts:列出匹配的远程主机列表,并不执行任何其它操作
Ø  -f FORKS:指定一次批量管控多少台主机,默认一批管控5台主机
Ø  -u REMOTE_USER:以哪个用户连接远程主机,默认为None
Ø  -T TIMEOUT:连接远程主机的超时时长,默认10
Ø  --version:查看ansible主配置文件、ansible配置的模块搜索路径、ansible python模块位置、可执行程序位置和python版本信息
Ø  -h:显示帮助信息
9、ansible-doc命令常用选项:
Ø  -l:列出所有已安装的模块
Ø  -s:显示指定模块的用法
Ø  -h:显示帮助信息
备注:Ansible所有支持的模块,https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

(二):Ansible常用的27个模块

三、Ansible常用模块介绍:
1、ping:测试被管控主机连通性
# ansible all --list-hosts
image.png
# ansible dbsrvs --list-hosts
image.png
查看参数:# ansible-doc -s ping
示例:测试所有被管控主机的连通性
# ansible all -m ping
image.png
备注:ping模块后无需加key=value格式的参数列表
2、hostname:设置主机名
查看参数:# ansible-doc -s hostname
示例:将被管控主机192.168.1.144的主机名修改为144
# ansible 192.168.1.144 -m hostname -a 'name=144'
3、group:增加或删除用户组
查看参数:# ansible-doc -s group
示例1:在所有被管控主机创建gid2000的用户组testgroup
# ansible all -m group -a 'gid=2000 name=testgroup state=present system=no'
示例2:删除testgroup用户组
# ansible all -m group -a 'gid=2000 name=testgroup state=absent'
4、user:管理用户账户
查看参数:# ansible-doc -s user
示例1:在所有被管控主机创建uid3000、基本组为mygroup、附加组为testgroupshell/bin/bash、注释为test的非系统用户testuser
# ansible all -m user -a 'uid=3000 group=mygroup groups=testgroup shell=/bin/bash comment=test system=no state=present name=testuser append=yes'
备注:
Ø  基本组mygroup和附加组testgroup必须事先存在
Ø  当不使用group设置基本组时,默认基本组与用户名相同
Ø  当不使用groups设置附加组时,默认附加组与用户名相同
Ø  可以设置多个附加组,用逗号隔开
Ø  append:默认为no,覆盖原来多个附加组,设置为yes,表示追加附加组到现有的附加组
示例2:删除用户testuser及其家目录
# ansible all -m user -a 'uid=3000 state=absent name=testuser remove=yes'
5、shell:在被管控主机执行命令
查看参数:# ansible-doc -s shell
示例:在所有被管控主机设置用户testuser的密码为123456
# ansible all -m shell -a 'echo 123456 | passwd --stdin testuser'
备注:shell模块后直接加需要执行的命令,而非key=value格式的参数列表
6、command:在被管控主机执行命令(无法执行管道、重定向等命令)
查看参数:# ansible-doc -s command
示例:查看所有被管控主机的网卡信息
# ansible all -m command -a 'ip a l'
备注:command模块后直接加需要执行的命令,而非key=value格式的参数列表
7、fetch:从被管控主机拉取文件至Ansible主机
查看参数:# ansible-doc -s fetch
示例:将被管控主机中的/software/test.txt文件复制至本地Ansible主机的/tmp目录中
# ansible all -m fetch -a 'src=/software/test.txt dest=/tmp/'
备注:
Ø  被管控主机中文件/software/test.txt必须事先存在
Ø  参数src中指定的必须是文件,不能是目录
Ø  如果被管控主机在hosts文件中定义了主机别名,则Ansible主机本地保存的文件路径为:/tmp/被管控主机别名/software/test.txt;如果直接定义了IP地址,则路径为:/tmp/被管控主机IP/software/test.txt
8、copy:将Ansible主机文件复制至被管控主机
查看参数:# ansible-doc -s copy
示例1:将本地文件/etc/fstab复制至所有被管控主机的/software目录下,且重命名为fstab.ansible,文件属主为testuser,属组为testgroup
# ansible all -m copy -a 'src=/etc/fstab dest=/software/fstab.ansible owner=testuser group=testgroup backup=yes'
备注:
Ø  如果参数src和参数dest均为文件,则参数dest的父目录/software必须事先存在
Ø  远程主机用户testuser和用户组testgroup必须事先存在
Ø  参数backup:创建一个包含时间戳信息的备份文件
示例2:将本地/tmp目录中的所有文件复制至所有被管控主机的/software目录下,且文件权限修改为600
# ansible all -m copy -a 'src=/tmp/ dest=/software mode=0600'
备注:
Ø  目录/software必须事先存在
Ø  权限的写法
  ²  0600
    ²  "600"
    ²  1.8版本开始,支持类似u+rwxu=rw,g=r,o=r
    ²  2.3版本开始,支持mode=preserve,表示将授予该文件与源文件相同的权限
示例3:将本地/tmp目录递归复制至所有被管控主机的/test目录下,且新创建的目录权限为755,目录和文件的属主均为testuser,属组均为testgroup
# ansible all -m copy -a 'src=/tmp dest=/test directory_mode=0755 owner=testuser group=testgroup'
备注:
Ø  如果远程主机中不存在/test目录,并且参数dest以“/”结尾或参数src是目录,则远程主机会自动创建/test目录
Ø  远程主机用户testuser和用户组testgroup必须事先存在
Ø  directory_mode:递归的设定目录的权限,默认为系统默认权限
示例4:在所有被管控主机的/tmp目录中新建属主为testuser、属组为testgroup、权限为600,且名称为test.txt的文件,内容为hello world
# ansible all -m copy -a 'content="hello world\n" dest=/tmp/test.txt owner=testuser group=testgroup mode=0600'
9、file:设置文件属性
查看参数:# ansible-doc -s file
示例1:在所有被管控主机的/tmp目录中创建名称为a.txt的文件
# ansible all -m file -a 'path=/tmp/a.txt state=touch'
示例2:在所有被管控主机的/tmp目录中创建a.txt的符号链接文件a.link
# ansible all -m file -a 'src=/tmp/a.txt path=/tmp/a.link state=link'
备注:参数src只应用于state=linkstate=hard
示例3:在所有被管控主机的/tmp目录中创建属主为testuser、属组为testgroup、权限为700,且名称为test的目录
# ansible all -m file -a 'path=/tmp/test owner=testuser group=testgroup mode=0700 state=directory'
示例4:在所有被管控主机的/tmp目录中删除test目录
# ansible all -m file -a 'path=/tmp/test state=absent'
10、cron:管理任务计划
查看参数:# ansible-doc -s cron
示例1:在所有被管控主机执行任务计划,要求每3分钟同步内网NTP服务器192.168.1.142
# ansible all -m cron -a 'minute=*/3 job="/usr/sbin/ntpdate 192.168.1.142 &> /dev/null" name=ntpdate user=root state=present backup=yes'
备注:
Ø  被管控主机需要先安装ntpdate软件包
Ø  如果时间单位(minutehourday等)设定的参数都未指定时,任务计划的时间默认设定为“* * * * *”,表示每分钟都会执行一次任务计划
Ø  参数backup:如果此参数的值设置为yes,那么当修改或者删除对应的任务计划时,会先对任务计划进行备份,然后再对任务计划进行修改或者删除,cron模块会在被管控主机的/tmp目录中创建备份文件,以crontab开头且随机加入一些字符,具体的备份文件名称会在返回信息的backup_file字段中看到
示例2:在所有被管控主机执行任务计划,要求以testuser用户身份、每月的4号和每周一至周三的上午10点输出一次Hello World
# ansible all -m cron -a 'minute=0 hour=10 day=4 month=* weekday=1-3 job="echo Hello World" name=echo user=testuser state=present'
备注:CentOS 7.6echo路径为:/usr/bin/echoCentOS 6.10echo路径为:/bin/echo
示例3:所有被管控主机删除名称为ntpdate的任务计划
# ansible all -m cron -a 'name=ntpdate state=absent'
示例4:所有被管控主机创建名称为“test special time”的任务计划,任务将在重启时执行,任务内容为输出test字符
# ansible all -m cron -a 'name="test special time" special_time=reboot job="echo test" state=present'
备注:参数special_time的可选值包括reboot(重启时)、yearly(每年)、annually(每年,与yearly相同)、monthly(每月)、weekly(每周)、daily(每天)和hourly(每小时)
11、yum:使用yum包管理器管理软件包
查看参数:# ansible-doc -s yum
示例1:所有被管控主机以yum方式安装最新版本的httpdphp
# ansible all -m yum -a 'name=httpd,php state=latest'
备注:参数state的可选值包括安装(present=installedlatest)和卸载(absent=removed
示例2:被管控主机192.168.1.144中安装版本为1.12.2nginx
# ansible 192.168.1.144 -m yum -a 'name=nginx-1.12.2 state=present'
备注:CentOS 6.10 epel源中nginx的版本为1.10.2CentOS 7.6 epel源中nginx的版本为1.12.2
示例3:所有被管控主机安装/software目录下的rpm软件包
# ansible all -m yum -a 'name=/software/jdk-8u212-linux-x64.rpm state=present'
备注:rpm软件包在被管控主机,而非Ansible主机
示例4:所有被管控主机以yum方式删除php
# ansible all -m yum -a 'name=php state=absent'
示例5:所有被管控主机安装Development Tools软件包组:
# ansible all -m yum -a 'name="@Development Tools" state=present'
备注:使用命令# yum grouplist查看软件包组信息
12、service:管理服务
查看参数:# ansible-doc -s service
示例1:所有被管控主机启动httpd服务,并设置开机自启
# ansible all -m service -a 'name=httpd state=started enabled=yes'
备注:参数state的可选值包括startedstoppedrestartedreloaded
示例2:所有被管控主机停止httpd服务,并取消开机自启
# ansible all -m service -a 'name=httpd state=stopped enabled=no'
13、script:先将Ansible主机中的脚本传输至被管控主机,再执行
查看参数:# ansible-doc -s script
示例:所有被管控主机执行Ansible主机中的/scripts/test.sh脚本,目标是在所有被管控主机的/tmp目录中创建名称为script.txt的文件
# cat /scripts/test.sh
#!/bin/bash
touch script.txt
# ansible all -m script -a 'chdir=/tmp /scripts/test.sh'
备注:
Ø  脚本在Ansible主机中,而非被管控主机,无需手动复制脚本至被管控主机后再执行
Ø  script模块后直接加需要执行的脚本文件,可以无需加key=value格式的参数列表
14、setup:收集被管控主机信息
查看参数:# ansible-doc -s setup
示例1:收集所有被管控主机的所有信息
# ansible all -m setup | less
示例2:收集所有被管控主机的操作系统发行版信息
# ansible all -m setup -a 'filter=ansible_distribution'
备注:在playbook里经常会用到的一个参数gather_facts就与setup模块相关
15、template:将模板文件复制至被管控主机
查看参数:# ansible-doc -s template
示例:将redis模板文件redis.conf.j2复制至所有被管控主机
# ansible all -m template -a 'src=redis.conf.j2 dest=/etc/redis.conf owner=redis group=root mode=0640 backup=yes'
16、unarchive:将归档文件解压后复制至被管控主机指定路径
查看参数:# ansible-doc -s unarchive
示例:将Ansible主机中/software目录下的apache-tomcat-8.5.40.tar.gz解压至所有被管控主机的/usr/local目录下,无需复制apache-tomcat-8.5.40.tar.gz至所有被管控主机
# ansible all -m unarchive -a 'src=/software/apache-tomcat-8.5.40.tar.gz dest=/usr/local/'
 17、debug:执行命令过程中打印信息
查看参数:# ansible-doc -s debug
示例:输出“hello world”信息
# ansible all -m debug -a 'msg="hello world"'
18、reboot:重启被管控主机
查看参数:# ansible-doc -s reboot
示例:重启所有被管控主机
# ansible all -m reboot
备注:reboot模块后无需加key=value格式的参数列表
19、systemd:管理服务
查看参数:# ansible-doc -s systemd
示例1:被管控主机192.168.1.144重启httpd服务,并设置开机自启
# ansible 192.168.1.144 -m systemd -a 'name=httpd.service state=restarted enabled=yes'
备注:
Ø  systemd模块仅可用于CentOS 7.x系统
Ø  参数state的可选值包括startedstoppedrestartedreloaded
示例2:被管控主机192.168.1.144停止httpd服务,并取消开机自启
# ansible 192.168.1.144 -m systemd -a 'name=httpd.service state=stopped enabled=no'
20、sysctl:管理sysctl.conf
查看参数:# ansible-doc -s sysctl
示例:将所有被管控主机中/etc/sysctl.conf文件的net.ipv4.ip_forward值设置为1
# ansible all -m sysctl -a 'sysctl_file=/etc/sysctl.conf name=net.ipv4.ip_forward value=1 reload=yes state=present'
21、selinux:改变SELinux的策略和状态
查看参数:# ansible-doc -s selinux
示例:所有被管控主机禁用SELinux
# ansible all -m selinux -a 'state=disabled'
备注:被管控主机需要先安装libselinux-python软件包
22、stat:检索文件或者文件系统的状态
查看参数:# ansible-doc -s stat
示例:获取所有被管控主机中/etc/fstab文件的状态信息,包括atimectimemtimeuidgidinodemodemd5
# ansible all -m stat -a 'path=/etc/fstab get_checksum=yes checksum_algorithm=md5'
备注:参数checksum_algorithm的可选值包括md5sha1sha224sha256sha384sha512
23、replace:使用向后引用的正则表达式替换文件中特定字符串的所有实例
查看参数:# ansible-doc -s replace
示例:将被管控主机192.168.1.144/tmp/test.txt文件内的HELLOWORLD全部替换成helloworld
# cat /tmp/test.txt
HELLOWORLD
helloworld
HELLOworld
helloWORLD
# ansible 192.168.1.144 -m replace -a 'path=/tmp/test.txt regexp=HELLOWORLD replace=helloworld backup=yes'
24、lineinfile:管理文本文件中的行
查看参数:# ansible-doc -s lineinfile
示例:将所有被管控主机中/etc/selinux/config文件内的SELinux的值设置为disabled
# ansible all -m lineinfile -a 'path=/etc/selinux/config regexp="^SELINUX=" line="SELINUX=disabled" state=present backup=yes'
25、blockinfile:插入/更新/删除由标记线包围的文本块
查看参数:# ansible-doc -s blockinfile
示例1:在所有被管控主机中/tmp/service.txt文件的开头插入一行“hello world
# cat /tmp/service.txt
111111
222222
333333
# ansible all -m blockinfile -a 'path=/tmp/service.txt block="hello world" marker="#{mark} test echo" insertbefore=BOF state=present backup=yes'
备注:BOF --> Begin Of File
示例2:在所有被管控主机中/tmp/test.txt文件的末尾插入一行“welcome home
# cat /tmp/test.txt
111111
222222
333333
# ansible all -m blockinfile -a 'path=/tmp/test.txt block="welcome home" marker="#{mark} test" insertafter=EOF state=present backup=yes'
备注:EOF --> End Of File,默认操作就是将文本块插入到文档的末尾,可以不加参数EOF
示例3:在所有被管控主机中/tmp/script.sh文件的“#!/bin/sh”开头的行后插入HELLO WORLD
# cat /tmp/script.sh
#!/bin/sh

#Licensed to the Apache Software Foundation (ASF) under one or more
# ansible all -m blockinfile -a 'path=/tmp/script.sh block="HELLO WORLD" marker="#{mark} test reg" insertafter="^#!/bin/sh" state=present backup=yes'
26、yum_repository:增加或删除yum仓库
查看参数:# ansible-doc -s yum_repository
示例:在所有被管控主机中创建如下yum仓库
# cat /etc/yum.repos.d/MariaDB.repo                          //仓库名称由file参数定义
[mariadb]                                                                      //name参数定义
name=MariaDB Repo                                                  //description参数定义
baseurl=http://mirrors.ustc.edu.cn/mariadb/yum/10.3/centos7-amd64/
gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck=1
enabled=1
# ansible all -m yum_repository -a 'file=MariaDB name=mariadb description="MariaDB Repo" baseurl=http://mirrors.ustc.edu.cn/mariadb/yum/10.3/centos7-amd64/ gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB gpgcheck=yes enabled=yes owner=root group=root mode=0644 state=present'
27、mysql_user:增加或删除MySQL数据库中的用户
查看参数:# ansible-doc -s mysql_user
示例:在被管控主机的MySQL数据库中通过[email protected]用户,密码123456,增加[email protected]%用户,密码654321,并对所有库的所有表拥有任何权限
# ansible all -m mysql_user -a 'login_host=localhost login_user=root login_password=123456 name=testuser host="%" password=654321 priv=*.*:all state=present'

(三):Ansible Playbook和变量类型


四、Ansible Playbooks
1、PlaybookYAMLJinja2简介:
Playbook:包含Ansible指令的YAML格式的文件,#为注释,ansbile-playbook命令根据自上而下的顺序依次执行。
YAMLYAML Ain't a Markup LanguageYAML不是一种标记语言)的递归缩写。在开发这种语言时,YAML的意思其实是Yet Another Markup Language(仍是一种标记语言),但为了强调这种语言以数据为中心,而不是以标记语言为中心,采用反向缩略语重命名。YAML的语法和其它高级语言类似,并且可以简单表达清单、散列表、标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印除错内容、文件大纲。对于Ansible,每一个YAML文件都是从一个列表开始,列表中的每一项都是一个键值对,通常它们被称为一个“哈希”或“字典”。列表中的所有成员都开始于相同的缩进级别,并且使用一个“-”作为开头(一个横杠和一个空格)。一个字典是由一个简单的“键值”形式组成(冒号后必须是一个空格)。
Jinja2Python中被广泛应用的模版引擎,它的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,包括:
(1)字面量:
Ø  字符串:使用单引号或双引号
Ø  数字:整数、浮点数
Ø  列表:[item1, item2, ...]
Ø  元组:(item1, item2, ...)
Ø  字典:{key1:value1, key2:value2, ...}
Ø  布尔型:truefalse
(2)算术运算符:+-*///%**
(3)比较运算符:==!=>>=<<=
(4)逻辑运算符:andornot()
2、Playbook中的元素:
(1)hosts:执行指定任务的、定义在hosts文件中的被管控主机
192.168.1.144
[websrvs]
apache ansible_host=192.168.1.145
nginx ansible_host=192.168.1.220
备注:
Ø  如果定义了主机组名(websrvs)或主机别名(apachenginx),hosts可以使用组名或别名
Ø  如果只定义了IP地址(192.168.1.144),则hosts只能使用IP地址
(2)remote_user:在被管控主机上执行任务的用户
(3)tasks:定义要在被管控主机上执行的任务列表
(4)handlers:可以把handler理解成另一种形式的taskhandler中的任务会被task中的任务进行调用,但是被调用并不意味着一定会执行,只有当task中的任务真正执行以后(真正的进行实际操作,造成了实际的改变),handler中被调用的任务才会执行。如果task中的任务并没有做出任何实际的操作,那么handler中的任务即使被调用,也不会执行,另外handler执行的顺序与handlerplaybook中定义的顺序是相同的,与handlernotify的顺序无关。默认情况下,所有task执行完毕后,才会执行各个handler,并不是执行完某个task后,立即执行与其对应的handler
(5)vars:定义playbook运行时需要使用的变量
(6)templates:包含了模板语法的文件
(7)tags:用于让用户选择运行或略过playbook中的部分代码
3、ansible-playbook的使用格式:# ansible-playbook [options] playbook.yml [playbook2 ...]
[options]
Ø  -C:尝试预测可能发生的一些变化,并不真正执行
Ø  -e 'EXTRA_VARS':设置key=value的自定义变量
Ø  --syntax-check:对playbook执行语法检查,并不真正执行
Ø  --list-hosts:列出匹配的远程主机列表,并不执行任何其它操作
Ø  --list-tags:列出所有可用标签
Ø  --list-tasks:列出所有要执行的任务
Ø  -t TAGS:仅执行指定标签标记的任务
Ø  --skip-tags 'SKIP_TAGS':仅执行与指定标签不匹配的标记的任务
Ø  --start-at-task 'START_AT_TASK':从匹配指定标签标记的任务开始执行
Ø  -f FORKS:指定一次批量管控多少台主机,默认一批管控5台主机
Ø  -u REMOTE_USER:以哪个用户连接至被管控主机,默认为None
Ø  -T TIMEOUT:连接至被管控主机的超时时长,默认10
Ø  --version:查看ansible主配置文件、ansible配置的模块搜索路径、ansible python模块位置、可执行程序位置和python版本信息
Ø  -h:显示帮助信息
4、playbook示例:所有被管控主机安装memcached软件包,启动并实现开机自启
# mkdir -pv /playbooks
# vim /playbooks/memcached.yml
- hosts: all
remote_user: root
tasks:
- name: install memcached
yum: name=memcached state=latest
- name: start memcached service
service: name=memcached state=started enabled=yes
# ansible-playbook --syntax-check /playbooks/memcached.yml
# ansible-playbook -C /playbooks/memcached.yml
# ansible-playbook /playbooks/memcached.yml

五、Ansible Variables
1、内置变量:
(1)hostvars:获取被管控主机的主机变量信息
# ansible all -m debug -a 'msg={{hostvars}}'
(2)ansible_version:获取ansible的版本号
# ansible all -m debug -a 'msg={{ansible_version}}'
# ansible all -m debug -a 'msg={{ansible_version.full}}'
(3)group_names:获取当前被管控主机所在分组的组名
# ansible all -m debug -a 'msg={{group_names}}'
(4)groups:获取主机清单中所有主机及主机组的分组信息
# ansible all -m debug -a 'msg={{groups}}'
# ansible all -m debug -a 'msg={{groups.websrvs}}'
备注:所有主机默认被分成了组名为“all”的组,没有分组的主机分到了名为“ungrouped”的组,即组名为“未分组”的组
(5)inventory_file:获取主机清单文件存放的路径和名称
# ansible all -m debug -a 'msg={{inventory_file}}'
(6)inventory_hostname:获取被管控主机的主机名,此处的主机名并非系统的主机名,而是对应主机在主机清单中配置的名称
# ansible all -m debug -a 'msg={{inventory_hostname}}'
备注:如果使用IP配置主机,inventory_hostname返回的值就是IP,如果使用别名配置主机,返回的值就是别名
2、ansible_facts变量:
(1)ansible_distribution:获取被管控主机的系统类型
(2)ansible_distribution_major_version:获取被管控主机的系统主版本号
(3)ansible_hostname:获取被管控主机的主机名
(4)ansible_os_family:获取被管控主机的系统系列名称
(5)ansible_pkg_mgr:获取被管控主机的包管理器名称
# vim /playbooks/facts.yml
- hosts: all
remote_user: root
tasks:
- name: show distribution
debug: msg={{ansible_distribution}}
- name: show distribution major version
debug: msg={{ansible_distribution_major_version}}
- name: show hostname
debug: msg={{ansible_hostname}}
- name: show os family
debug: msg={{ansible_os_family}}
- name: show package manager
debug: msg={{ansible_pkg_mgr}}
# ansible-playbook --syntax-check /playbooks/facts.yml
# ansible-playbook -C /playbooks/facts.yml
# ansible-playbook /playbooks/facts.yml
备注:
Ø  使用命令# ansible all -m setup | less查看到的所有ansible_facts变量
Ø  所有ansible_facts变量只能在playbook中使用,不能在ad-hoc中直接使用,会提示没有定义
3、通过主机清单文件定义的主机及主机组变量:
# vim /etc/ansible/hosts
(1)主机变量:
192.168.1.144
[websrvs]
192.168.1.145 ansible_user=keyso ansible_ssh_pass=123456
192.168.1.220 ansible_user=keyso ansible_ssh_pass=123456
[dbsrvs]
146 ansible_host=192.168.1.146
[test:children]
websrvs
dbsrvs
备注:
Ø  定义了3个组,websrvsdbsrvstest组,且test组中包含了2个子组websrvsdbsrvs,当操作test组时就相当于操作了这2个子组中的所有主机
Ø  146 ansible_host=192.168.1.146146为主机别名,配置了主机别名,IP前需要增加参数ansible_host
Ø  常用主机变量:
  ²  ansible_host:要远程连接的主机IP
    ²  ansible_portSSH使用的端口号
  ²  ansible_userSSH连接时默认使用的用户名
  ²  ansible_ssh_passSSH连接时的密码
  ²  ansbile_sudo_pass:使用sudo连接用户时的密码
(2)主机组变量:
192.168.1.144
[websrvs]
192.168.1.145
192.168.1.220
[dbsrvs]
146 ansible_host=192.168.1.146
[test:children]
websrvs
dbsrvs
[websrvs:vars]
ansible_user=keyso
ansible_ssh_pass=123456
备注:在配置密钥认证的情况下,无需配置ansible_useransible_ssh_pass两个参数
4、通过ansible-playbook命令传入变量:
# vim /playbooks/test.yml
- hosts: all
remote_user: root
tasks:
- name: command line variable
debug: msg={{cmdvar}}
# ansible-playbook --syntax-check -e cmdvar=hello /playbooks/test.yml
# ansible-playbook -C -e cmdvar=hello /playbooks/test.yml
# ansible-playbook -e cmdvar=hello /playbooks/test.yml
备注:命令行传入的变量优先级最高
5、循环中的固定变量item
(1)示例:如果被管控主机是RedHat系列的系统,则安装tomcatmemcachedvarnish三个软件包:
# vim /playbooks/pkgs.yml
- hosts: all
remote_user: root
tasks:
- name: install packages
yum: name={{item}} state=latest
loop:
- tomcat
- memcached
- varnish
when: ansible_os_family=="RedHat"
# ansible-playbook --syntax-check /playbooks/pkgs.yml
# ansible-playbook -C /playbooks/pkgs.yml
# ansible-playbook /playbooks/pkgs.yml
备注:
Ø  循环:迭代,需要重复执行的任务。对迭代项的引用,固定变量名为item,并在tasks中使用loop给定要迭代的元素列表。列表表示方式:字符串和字典。
Ø  when语句:在tasks中使用,表示条件判断,如果符合条件,则执行,jinja2的语法格式
(2)示例:所有被管控主机按如下要求创建用户组和用户,并设置用户系统登录密码
用户user1,基本组group1,密码111111
用户user2,基本组group2,密码222222
用户user3,基本组group3,密码333333
# vim /playbooks/addusers.yml
- hosts: all
remote_user: root
tasks:
- name: add groups
group: name={{item}} state=present
loop:
- group1
- group2
- group3
- name: add users
user: name={{item.user}} group={{item.group}} state=present
loop:
- {user: user1, group: group1}
- {user: user2, group: group2}
- {user: user3, group: group3}
- name: set password
shell: echo {{item.passwd}} | passwd --stdin {{item.user}}
loop:
- {passwd: 111111, user: user1}
- {passwd: 222222, user: user2}
- {passwd: 333333, user: user3}
# ansible-playbook --syntax-check /playbooks/addusers.yml
# ansible-playbook -C /playbooks/addusers.yml
# ansible-playbook /playbooks/addusers.yml
6、自定义变量:
(1)playbook中使用vars关键字定义变量
(2)playbook中使用set_fact模块定义变量
(3)vars_files:将文件中的变量引入playbook,以便在task中使用
(4)include_vars:将文件中的变量动态引入playbook,以便在task中使用
# vim /playbooks/uservar.yml
- hosts: all
remote_user: root
vars:
- var1: test1
vars_files:
- /tmp/uservar.txt
tasks:
- name: show var1
debug: msg={{var1}}
- name: show var2
debug: msg={{var2}}
- name: set var3
set_fact: var3=test3
- name: show var3
debug: msg={{var3}}
- name: modify uservar file
shell: sed -i 's/var2/var4/g' /tmp/uservar.txt
- name: set var4
include_vars: /tmp/uservar.txt
- name: show var4
debug: msg={{var4}}
# cat /tmp/uservar.txt
var2: test2
# ansible-playbook --syntax-check /playbooks/uservar.yml
# ansible-playbook -C /playbooks/uservar.yml
# ansible-playbook /playbooks/uservar.yml
备注:
Ø  set_fact模块定义的变量在其它playbook中也能被正常引用,但vars关键字定义的变量不行
Ø  在变量文件/tmp/uservar.txt中通过sed命令将var2替换成了变量var4include_vars模块能够重新加载变量文件,并动态的以任务的方式引用变量var4
Ø  变量文件/tmp/uservar.txt位于Ansible主机,与被管控主机无关
7、 综合示例:
(1)如果被管控主机是CentOS 7.x系列的系统,则根据提供的模板文件redis.conf.j2安装、配置并启动redis
# vim /playbooks/redis.yml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=latest
- name: install configuration file
template: src=/playbooks/redis.conf.j2 dest=/etc/redis.conf owner=redis group=root mode=0640 backup=yes
when: ansible_distribution=="CentOS" and ansible_distribution_major_version=="7"
notify: restart redis service
tags: redis configuration file
- name: start redis service
service: name=redis state=started enabled=yes
handlers:
- name: restart redis service
service: name=redis state=restarted
# cat /playbooks/redis.conf.j2
bind {{ansible_host}}
requirepass keyso0728
# ansible-playbook --syntax-check /playbooks/redis.yml
# ansible-playbook -C /playbooks/redis.yml
# ansible-playbook /playbooks/redis.yml
备注:
Ø  Ansible节点中先安装redis,提取redis.conf,并修改为模板文件
Ø  CentOS 7.6CentOS 6.10redis.conf原始配置文件内容一致
Ø  redis启动后监听的端口为6379
Ø  修改模板文件redis.conf.j2中的内容,然后将模板文件复制至被管控节点,重启redis生效,可以执行命令:# ansible-playbook -t 'redis configuration file' /playbooks/redis.yml
(2)安全加固后的被管控主机不允许直接以root用户身份登录,需要通过普通用户testuser连接至被管控主机,然后suroot用户,执行那些需要root用户权限才能执行的命令
# vim /etc/ansible/hosts
192.168.1.144
[websrvs]
192.168.1.145
192.168.1.220
[dbsrvs]
146 ansible_host=192.168.1.146
[test:children]
websrvs
dbsrvs
# ansible all -a 'whoami' --> root用户
# ansible all -m user -a 'name=testuser state=present'
# ansible all -m shell -a 'echo 123456 | passwd --stdin testuser'
禁止root用户直接登录远程被管控主机:
# ansible all -m lineinfile -a 'path=/etc/ssh/sshd_config regexp="^#PermitRootLogin yes" line="PermitRootLogin no" state=present backup=yes'
# ansible all -m service -a 'name=sshd state=restarted'
再使用root用户连接至被管控节点会报错
# vim /etc/ansible/hosts
192.168.1.144
[websrvs]
192.168.1.145
192.168.1.220
[dbsrvs]
146 ansible_host=192.168.1.146
[test:children]
websrvs
dbsrvs
[websrvs:vars]
ansible_user=testuser
ansible_ssh_pass=123456
ansible_become_pass=hellolinux
备注:
Ø  ansible_user:定义普通用户名称
Ø  ansible_ssh_pass:定义普通用户密码
Ø  ansible_become_pass:定义切换root用户时需要的登录密码
# ansible all -a 'whoami' --> testuser用户
尝试以testuser用户身份在每台被管控主机的/root目录下创建a.txt文件,结果Permission denied
# ansible all -m file -a 'content= path=/root/a.txt state=touch'
# ansible all --become-method su -b -a 'whoami' --> root用户
备注:
Ø  --become-method:将权限提升的方式设置为su,默认为sudo
Ø  -b:使用become执行操作(不提示密码输入)
# ansible all --become-method su -b -m file -a 'content= path=/root/a.txt state=touch'

(四):Ansible Role及实战案例















No comments: