ansible
1ansibel的入门和安装
1.1安装
rpm包安装: EPEL源
yum install ansible -y
编译安装:
yum -y install python-jinja2 PyYAML python-paramiko python-babel
python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
Git方式:
git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
pip安装: pip是安装Python包的管理器,类似yum
yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
查看版本
ansible --version
1.2相关配置文件
1.2.1配置文件
/etc/ansible/ansible.cfg #著配置文件
/etc/ansible/hosts #主机清单
/etc/ansible/roles #存放角色的目录
1.2.2主配置文件
[root@ansible ansible]# cat /etc/ansible/ansible.cfg
[defaults]
#inventory = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_modules/ #库文件存放目录
#module_utils = /usr/share/my_module_utils/
#remote_tmp = ~/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp = ~/.ansible/tmp # 本机的临时命令执行目录
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml
#forks = 5 #默认并发数
#sudo_user = root # 默认sudo 用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#ask_pass = True
#remote_port = 22
#host_key_checking = False # 检查对应服务器的host_key,建议取消注释
#log_path=/var/log/ansible.log #日志文件,建议启用
#module_name = command #默认模块,可以修改为shell模块
1.2.3
主机清单格式
[root@ansible ansible]# vim /etc/ansible/hosts [appsrvs]
192.168.39.131
192.168.39.62
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
[websrvs]
192.168.39.[132:133]
192.168.39.134
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
[dbsrvs]
db-[a:f].example.com
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
[webservers]
www1.linux.com:2222 #可以指定端口
www[1:100].example.com
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
ntp.linux.com #不分组,直接加
1.3相关工具
/usr/bin/ansible 主程序,临时命令执行工具 /usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具 /usr/bin/ansible-pull
远程执行命令的工具 /usr/bin/ansible-vault 文件加密工具 /usr/bin/ansible-console
基于Console界面与用户交互的执行工具
利用ansible实现管理的主要方式:
Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景
Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
1.3.1 ansible-doc
用来显示模块帮助
格式:
ansible-doc [options] [module…]
-l, --list #列出可用模块
-s, --snippet #显示指定模块的playbook片段
范例:
#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping
#列出所有主机
ansible all --list
1.3.2ansible 基于key验证
ansible通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能
建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点
实现基于key验证 将公钥ssh-copy-id到被管理的主机上 , 实现免密登录
[root@7-1 ~]# ssh-keygen
[root@7-1 ~]# ssh-copy-id -i ~./ssh/id_rsa.pub root@192.168.39.132
[root@7-1 ~]# ssh-copy-id -i ~./ssh/id_rsa.pub root@192.168.39.133
[root@7-1 ~]# ssh-copy-id -i ~./ssh/id_rsa.pub root@192.168.39.131
利用sshpass批量实现基于key验证
ssh-keygen -f /root/.ssh/id_rsa -P ''
NET=192.168.100
export SSHPASS=magedu
for IP in {1..200};do
sshpass -e ssh-copy-id $NET.$IP
done
1.3.3 格式和选项说明
格式:
ansible [-m module_name] [-a args]
选项说明:
–version #显示版本
-m module #指定模块,默认为command
-v #详细过程 –vv -vvv更详细
–list-hosts #显示主机列表,可简写 --list
-k, --ask-pass #提示输入ssh连接密码,默认Key验证
-C, --check #检查,并不执行
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-u, --user=REMOTE_USER #执行远程执行的用户
-b, --become #代替旧版的sudo 切换
–become-user=USERNAME #指定sudo的runas用户,默认为root
-K, --ask-become-pass #提示输入sudo时的口令
host-pattern
用于匹配被控制的主机的列表
All :表示所有Inventory中的所有主机
ansible all -m ping ansible websrvs -m ping
通配符
ansible "" -m ping #所有主机
ansible 192.168.39. -m ping
ansible “websrvs” -m ping
或关系
ansible “websrvs:appsrvs” -m ping
ansible “192.168.39.10:192.168.39.20” -m ping
逻辑与
#在websrvs组并且在dbsrvs组中的主机
ansible “websrvs:&dbsrvs” –m ping
逻辑非
#在websrvs组,但不在dbsrvs组中的主机
#注意:此处为单引号
ansible ‘websrvs:!dbsrvs’ –m ping
正则表达式
ansible “websrvs:&dbsrvs” –m ping
ansible “~(web|db).*.magedu.com” –m ping
1.3.4ansible的执行过程
(1) 加载自己的配置文件 默认/etc/ansible/ansible.cfg
(2) 加载自己对应的模块文件,如command
(3) 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
(4) 给文件+x执行
(5) 执行并返回结果
(6) 删除临时py文件,退出
1.4常用模块
1.4.1command模块
在远程主机执行命令,默认模块,可忽略-m选项
chdir: 进入到被管理主机目录
creates: 如果有一个目录是存在的,步骤将不会运行Command命令
ansible websrvs -a 'chdir=/data/ ls'
ansible srvs -m command -a 'service httpd start'
ansible srvs -m command -a 'echo centos |passwd --stdin yu'
1.4.2Shell模块
与command相似,用shell执行命令
可修改shell为默认模块
vim /etc/ansible/ansible.cfg
module_name = shell #可修改默认模式为shell
ansible all -m shell -a 'getenforce' 查看SELINUX状态
ansible all -m shell -a "sed -i 's/SELINUX=.*/SELINUX=disabled' /etc/selinux/config"
ansible srv -m shell -a 'echo magedu |passwd –stdin zhang'
1.4.3Script模块
在远程主机上运行ansible服务器上的脚本
ansible websrvs -m script -a /data/test.sh
1.4.4Copy模块
从主控端复制文件到远程主机
常见参数:
src : 源文件 指定拷贝文件的本地路径 (如果有/ 则拷贝目录内容,没有则拷贝目录本身)
dest: 指定目标路径
mode: 设置权限
backup: 备份源文件
content: 代替src 指定本机文件内容,生成目标主机文件
ansible all -m copy -a "src=/data/f1.txt dest=/data/test1.txt owner=zhang mode=600 backup=yes"
[root@ks7 ~]# ll /data
-rw------- 1 zhang root 0 Nov 27 20:57 test1.txt
1.4.5fetch模块
从远程主机提取文件至主控端,与copy模块相反,目前不支持目录
ansible all -m fetch -a"src=/data/test1.sh dest=/data/t1.sh"
1.4.6file模块
设置文件属性
常见参数:
path: 要管理的文件路径 (强制添加)
recurse: 递归,文件夹要用递归
src: 创建硬链接,软链接时,指定源目标,配合’state=link’ ‘state=hard’ 设置软链接,硬链接
state: 状态
absent 缺席,删除
#创建文件
ansible websrvs -m file -a 'path=/app/test.txt state=touch'
#创建目录
ansible websrvs -m file -a "path=/data/testdir state=directory"
#设置权限755
ansible websrvs -m file -a "path=/root/test.sh owner=wang mode=755"
#创建软链接
ansible websrvs -m file -a 'src=/data/testfile dest=/data/testfile-link state=link'
1.4.7unarchive模块
解包解压缩,有两种用法:
1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes.
2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
常见参数:
copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上寻找src源文件
src: 源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,
如果是远程主机上的路径,则需要设置copy=no
dest:远程主机上的目标路径
mode:设置解压缩后的文件权限
ansible websrvs -m unarchive -a 'src=foo.tgz dest=/var/lib/foo'
#默认copy为yes ,将本机目录文件解压到目标主机对应目录下
ansible websrvs -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
# 解压被管理主机的foo.zip到data目录下, 并设置权限777
ansible websrvs -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
1.4.8Archive:打包压缩
将远程主机目录打包
常见参数:
path: 指定路径
dest: 指定目标文件
format: 指定打包格式
owner: 指定所属者
mode: 设置权限
ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777'
1.4.9Hostname:管理主机名
ansible appsrvs -m hostname -a "name=net.yu.com"
#更改一组的主机名
ansible 192.168.39.62 -m hostname -a "name=ks8-2"
#更改单个主机名
hostname app_81.magedu.com
hostname 不支持"",认为""是非法字符
hostnamectl set-hostname app_80.magedu.com 可以更改主机名
1.4.10Cron模块
计划任务
支持时间:minute,hour,day,month,weekday
> #备份数据库脚本
> [root@centos8 ~]#cat mysql_backup.sh mysqldump -uroot -pcentos -A -F --single-transaction --master-data=2 -q |gzip > /data/mysql_backup`date +%F_%T`.sql.gzip
> #创建任务
> ansible appsrvs -m cron -a 'hour=2 minute=30 weekday=1-5 name="mysqlbackup" job=/root/mysql_backup.sh'
> ansible appsrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &> /dev/null' name=synctime"
> #禁用计划任务
> ansible appsrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes"
> #启用计划任务
> ansible appsrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no"
> #删除任务
> ansible appsrvs -m cron -a "name='mysql_backup' state=absent" ansibel appsrvs -m crom -a "name=synctime state=absent"
1.4.11 yum模块
软件包管理
ansible srv -m yum -a ‘name=httpd state=present’ #安装
ansible srv -m yum -a ‘name=httpd state=absent’ #删除
1.4.12 Service模块
服务管理
ansible all -m service -a 'name=httpd state=started enabled=yes'
ansible all -m service -a 'name=httpd state=stopped'
ansible all -m service -a 'name=httpd state=reload'
ansible all -m shell -a "sed -i 's/^Listen 80/^Listen 8080/' /etc/httpd/conf/httpd.conf"
ansibel all -m service -a 'name=httpd state=restarted'
1.4.13user模块
管理用户
#创建用户
ansible srv -m user -a 'name=user1 comment=“test user” uid=2048 home=/app/user1 group=root‘
ansible srv -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes'
#删除用户及家目录等数据
ansible srv -m user -a 'name=nginx state=absent remove=yes'
1.4.14group模块
管理组
#创建组 ansible websrvs -m group -a 'name=nginx gid=88 system=yes'
#删除组 ansible websrvs -m group -a 'name=nginx state=absent'
1.4.15setup模块
返回系统信息
ansible 192.168.39.131 -m setup |less
ansible_all_ipv4_addresses #IP地址
ansible_architecture": "x86_64" #架构
ansible_distribution": "CentOS" #操作系统版本 ansible_distribution_file_variety": "RedHat" #判断是否是红帽 ansible_distribution_major_version": "7" #操作系统主版本号 ansible_domain": "" #域名
ansible_memfree_mb: 83 #内存的剩余
ansible_memtotal_mb": 1490, #内存总大小
ansible_nodename":node18.magedu.com #hostname
ansible_processor_vcpus:4 #虚拟cpu个数
#过滤,使用setup模块实现
```bash
[root@CENTOS8 files]# ansible 192.168.39.132 -m setup -a 'filter="ansible_distribution_file_variety"'
192.168.39.132 | SUCCESS => {
"ansible_facts": {
"ansible_distribution_file_variety": "RedHat",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
[root@CENTOS8 ansible]# ansible 192.168.39.131 -m setup -a 'filter="ansible_fqdn"'
192.168.39.131 | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "ks7-1",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
1.5ansible命令
1.5.1可以通过网上写好的ansible-galaxy
> 连接 https://galaxy.ansible.com
下载相应的roles
> 列出所有已安装的galaxy
ansible-galaxy list
> 安装galaxy
ansible-galaxy install geerlingguy.redis
> 删除galaxy
ansible-galaxy remove geerlingguy.redis
1.5.2ansible-playbook 可以引用按照标准的yml语言写的脚本
执行playbook
示例:ansible-playbook hello.yml
cat hello.yml
---
#hello world yml file
- hosts: websrvs
remote_user: root
tasks:
- name: hello world
command: /usr/bin/wall hello world
2playbook
2.1yaml语言
YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,
序列(Sequence)里的项用"-“来代表,Map里的键值对用”:"分隔,下面介绍常见的数据结构。
2.1.1 List列表
列表由多个元素组成,且所有元素前均使用“-”打头
A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
2.1.2 Dictionary字典
字典通常由多个key与value构成
name: Example Developer
job: Developer
skill: Elite
#也可以将key:value放置于{}中进行表示,用,分隔多个key:value
{name: Example Developer, job: Developer, skill: Elite}
2.2playbook核心元素
Hosts # 执行的远程主机列表(应用到哪些主机上)
Tasks # 任务集
Variables # 内置变量或自定义变量在playbook中调用
Templates # 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
Handlers 和 notify #结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags #标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断 ansible-playbook -t tagsname useradd.yaml
2.2.1hosts组件
Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。
hosts用于指定要执行指定任务的主机,须事先定义在主机清单中
- hosts: websrvs:appsrvs
2.2.2remote_user组件
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,
其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs remote_user: root tasks:
- name: test connection
ping:
remote_user: magedu
sudo: yes #默认sudo为root
sudo_user:wang #sudo为wang
2.2.3task列表和action组件
play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行。task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
(1) action: module arguments
(2) module: arguments 建议使用
注意:shell和command模块后面跟命令,而非key=value
---
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
使用ignore_errors来忽略错误信息
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True 忽略错误
2.2.4ShellScripts VS Playbook
#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#Playbook实现
---
- hosts: websrvs
remote_user: root
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
2.2.5handlers和notify结合使用触发条件
Handlers
是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作。
Notify此action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
2.2.6 tags
tage: 添加标签
可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
vim httpd.yml
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
tage: install
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: conf
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
ansible-playbook –t install,conf httpd.yml #指定执行install,conf 两个标签
2.3playbook实例:安装httpd服务
vim install_httpd.yaml
---
#install httpd and config httpd
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: modfiy config
copy: src=/data/ansible/files/httpd.conf dest=/etc/httpd/conf/httpd.conf mode=644 owner=root group=root
notify: restart httpd #指定modfiy config 之后触发执行handlers
- name: start service
service: name=httpd state=started enabled=yes
handlers: #通过notify来触发执行
- name: restart httpd #handlers的name名字必须同notify的名字相同
service: name=httpd state=restarted
2.4playbook实例:卸载httpd服务
[root@CENTOS8 ansible]#vim remove_httpd.yaml
---
- hosts: websrvs
remote_user: root
tasks:
- name: remove httpd package
yum: name=httpd state=absent
- name: remove apache user
user: name=apache state=absent #查看家目录路径 getent passwd apache ll /usr/share/httpd/
- name: remove data file
file: path=/etc/httpd state=absent
2.5playbook中变量的使用
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量来源:
1> ansible setup facts 远程主机的所有变量都可直接调用 (系统自带变量)
setup模块可以实现系统中很多系统信息的显示
可以返回每个主机的系统信息包括:版本、主机名、cpu、内存
ansible all -m setup -a ‘filter=“ansible_nodename”’ 查询主机名
ansible all -m setup -a ‘filter=“ansible_memtotal_mb”’ 查询主机内存大小
ansible all -m setup -a ‘filter=“ansible_distribution_major_version”’ 查询系统版本
ansible all -m setup -a ‘filter=“ansible_processor_vcpus”’ 查询主机cpu个数
2> 在/etc/ansible/hosts(主机清单)中定义变量
普通变量:主机组中主机单独定义,优先级高于公共变量(单个主机 )
公共(组)变量:针对主机组中所有主机定义统一变量(一组主机的同一类别)
3> 通过命令行指定变量,优先级最高
ansible-playbook –e varname=value
4> 在playbook中定义
vars:
- var1: value1
- var2: value2
5> 在独立的变量YAML文件中定义
6> 在role中定义
变量命名:
变量名仅能由字母、数字和下划线组成,且只能以字母开头
变量定义:key=value
示例:http_port=80
变量调用方式:
1> 通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用“{{ variable_name }}”才生效
2> ansible-playbook –e 选项指定
ansible-playbook test.yml -e "hosts=www user=magedu"
2.5.1在主机清单中定义变量,在ansible中调用变量
[root@ansible ~]# vim /etc/ansible/hosts
[appsrvs]
192.168.39.131 http_port=817 name=www
192.168.39.62 http_port=827 name=web
调用变量
ansible appsrvs -m hostname -a'name={{name}}' #更改主机名为各自被定义的变量
针对组设置变量
[root@ansible ~]#vim /etc/ansible/hosts
[appsrvs]
192.168.39.131 http_port=817 name=www
192.168.39.62 http_port=827 name=web
[appsrvs:vars]
mark="-"
[root@ansible ~]# ansible all -m hostname -a 'name={{name}}{{mark}}{{http_port}}'
[root@ansible ~]# ansible all -e http_port=8000 -m hostname -a 'name={{name}}{{mark}}{{http_port}}' #优先级8000
测试
[root@ks7-1 ~]# hostname
www-817
2.5.2将变量写进单独的配置文件中引用
[root@ansible ~]#vim vars.yml
pack: vsftpd
service: vsftpd
#引用变量文件
[root@ansible ~]#vim yuan.yaml
vars_files:
- vars.yml
2.5.3使用setup变量
查看setup变量
[root@ansible ~]#ansible 192.168.39.131 -m setup |less
[root@ansible ~]#var.yml
- hosts: websrvs
remote_user: root
tasks:
- name: create log file
file: name=/var/log/ {{ ansible_fqdn }} state=touch
[root@ansible ~]#ansible-playbook var.yml
2.5.4实例:yaml文件中直接引用变量
[root@ansible ~]#var.yml
- hosts: websrvs
remote_user: root
vars:
- username: user1
- groupname: group1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} state=present
[root@ansible ~]#ansible-playbook var.yml
[root@ansible ~]#ansible-playbook -e "username=xiaoming groupname=xiaoming” var.yml
2.5.5实例:使用变量文件
[root@ansible ~]#cat vars.yml
var1log: httpd
var2log: nginx
[root@ansible ~]#cat var.yml
---
- hosts: all
remote_user: root
vars_files:
- vars.yml
tasks:
- name: create httpd log
file: name=/data/ansible/{{varlog}}.log state=touch
- name: create nginx log
file: name=/data/ansible/{{var2log}}.log state=touch
2.6模板template
文本文件,嵌套有脚本(使用模板编程语言编写) 借助模板生成真正的文件
Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
Jinja2:
#算术运算 Jinja 允许你用计算值。这在模板中很少用到,但为了完整性允许其存在 支持下面的运算符
+:把两个对象加到一起。
通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }}
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。
也可以用于重 复一个字符串多次。{{ ‘=’ * 80 }} 会打印 80 个等号的横条
**:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8
#比较操作符
== 比较两个对象是否相等
!= 比较两个对象是否不等
如果左边大于右边,返回 true
= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true
2.6.1利用template同步nginx的配置文件
首先准备好/data/ansible/templates/nginx.conf.j2文件
[root@ansible ansible]#vim /data/ansible/template.yml
---
- hosts: all
remote_user: root
tasks:
- name: templates config
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@ansible ansible]#ansible-playbook template.yml
#修改替换变量
[root@ansible ansible]#vim /data/ansible/templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpu*2 }};
2.6.2when 实现条件判断
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法格式
when语句
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
tasks:
- name: "shutdown rehat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat"
#当系统属于红帽系列,执行command模块
playbook中的when的条件判断
---
- hosts: websrvc
remote_user: root
tasks:
- name: install conf file to 7
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
- name: install conf file to 6
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"
2.6.3迭代: with_items
迭代: 当有需要重复执行的任务时,可以使用迭代机制
对迭代的应用,固定变量名为“item”
要在task中使用with_items给定要迭代的元素列表
列表格式
字符串
字典
实列1:
- name: create serveral users
user: name={{ item }} state=present group=wheel #{{item}}系统自定义变量
with_items:
- testuser1
- testuser2
上面语句的功能等同于下面的语句:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
实例2:
- name: add serveral users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
2.6.4迭代
[root@ansible ansible]# vim copy.yml
---
- hosts: all
remote_user: root
tasks:
- name: copy file
copy: src={{ item }} dest=/tmp/{{ item }}.bak
with_items:
- file1
- file2
- file3
- name: install apache
yum: name={{ item }} state=present
with_items:
- apr
- apr-util
- httpd
2.6.5迭代嵌套子变量
[root@ansible ansible]# vim items_user.yml
---
- hosts: all
remote_user: root
tasks:
- name: add serveral groups
group: name={{ item }} state=present
with_items:
- group1
- group2
- group3
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group1' }
- { name: 'user12', group: 'group2' }
- { name: 'user13', group: 'group3' }
2.6.6实例: playbook with_items管理端口
[root@ansible ansible]# vim items_port.yml
---
- hosts: all
remote_user: root
tasks:
- name: Use UFW module management port to open
ufw:
rule: "{{ item.rule }}"
port: "{{ item.port }}"
proto: "{{ item.proto }}"
with_items:
- { rule: 'allow', port: 22, proto: 'tcp' }
- { rule: 'allow', port: 80, proto: 'tcp' }
- { rule: 'allow', port: 123, proto: 'udp'}
- name: Configure default rules for network in and out
ufw:
direction: "{{ item.direction }}"
polocy: "{{ item.policy }}"
state: enabled
with_items:
- { direction: outgoing, policy: allow }
- { direction: incoming, policy: deny }
2.6.7 template中使用流程控制 fro 和 if
#temnginx1.yml
---
- hosts: websrvs
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
tasks:
- name: config file
template: src=nginx2.conf.j2 dest=/data/nginx2.conf
#templates/nginx.conf1.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
#生成的结果
server {
listen 8080
}
3roles角色
roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。
角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
3.1roles目录结构
每个角色,以特定的层级目录结构进行组织
roles目录结构: playbook.yml 调用角色 roles/ project/ (角色名称)
tasks/
files/
vars/
templates/
handlers/
default/ #不常用
meta/ #不常用
3.1.1roles个目录的作用
/roles/project/ : 项目名称,有以下子目录
files/ :存放由copy或script模块等调用的文件
templates/:template模块查找所需要模板文件的目录
tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;
其它的文件需要在此文件中通过include进行包含
handlers/:至少应该包含一个名为main.yml的文件;
其它的文件需要在此文件中通过include进行包含
vars/:定义变量,至少应该包含一个名为main.yml的文件;
其它的文件需要在此文件中通过include进行包含
meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,
其它文件需在此文件中通过include进行包含
default/:设定默认变量时使用此目录中的main.yml文件
roles/example_role/files/
#所有文件,都将可存放在这里
roles/example_role/templates/
#所有模板都存放在这里
roles/example_role/tasks/main.yml
#主函数,包括在其中的所有任务将被执行
roles/example_role/handlers/main.yml
#所有包括其中的 handlers 将被执行
roles/example_role/vars/main.yml
#所有包括在其中的变量将在roles中生效
roles/example_role/meta/main.yml
#roles所有依赖将被正常登入
3.2创建httpd角色
1.创建roles目录
[root@ansible data]# mkdir -pv /data/ansible/roles/{httpd,mysql,redis}/{files,handlers,tasks,templates}
#查看创建目录结构
[root@ansible data]# tree
[root@ansible ansible]# tree
.
├── role_httpd.yml
└── roles
├── httpd
│ ├── files
│ │ ├── httpd.conf
│ │ └── index.html
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── config.yml
│ │ ├── index.yml
│ │ ├── install.yml
│ │ ├── main.yml
│ │ └── service.yml
│ └── templates
2.创建角色
[root@ansible ~]# cd /data/ansible/roles/httpd/tasks/
#创建主控文件,调用单独的yml文件,定义了执行的先后顺序
[root@ansible tasks]# vim main.yml
- include: install.yml
- include: config.yml
- include: index.yml
- include: service.yml
#创建安装的yaml文件
[root@ansible tasks]# cat install.yml
- name: install httpd
yum: name=httpd
#创建配置文件的yaml文件
[root@ansible tasks]# cat config.yml
- name: config file
copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes
notify: restart
#创建网页的yaml文件
[root@ansible tasks]# cat index.yml
- name: index.html
copy: src=index.html dest=/var/www/html
#创建启动的yaml文件
[root@ansible tasks]# cat service.yml
- name: start service
service: name=httpd state=started enabled=yes
2在handlers目录下创建handler文件mian.yml 对应config文件的notify
[root@ansible ~]# cd /data/ansible/roles/httpd/handlers/
[root@ansible handlers]# cat main.yml
- name: restart
service: name=httpd state=restarted
3准备httpd.conf文件,放到httpd的文件目录下
[root@ansible ~]# cp /etc/httpd/conf/httpd.conf /data/ansible/roles/httpd/files/
4创建一个网页
[root@ansible ~]# cd /var/www/html/index.html /data/ansible/roles/httpd/files/
[root@ansible ~]# vim /data/ansible/roles/httpd/files/index.html
<h1>hello linux!<\h1>
5创建文件调用httpd角色
[root@ansible ~]# cd /data/ansible/
[root@ansible ansible]# cat role_httpd.yml
---
- hosts: all
remote_user: root
roles:
- role: httpd
6运行playbook
[root@ansible ansible]# ansible-playbook role_httpd.yml