文章目录
一、ansible基本目录架构
yum install epel-release
yum install ansible
1、目录及文件说明
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
/etc/ansible/hosts 管理主机清单
/etc/ansible/roles 角色
常用二进制文件
/usr/bin/ansible
/usr/bin/ansible-doc
/usr/bin/ansible-playbook
2、主配置文件参数说明
cat /etc/ansible/ansible.cfg
#inventory = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_modules/ #库文件存放目录
#remote_tmp = ~/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp = ~/.ansible/tmp #本机的临时命令执行目录
#forks = 5 #默认并发数
#sudo_user = root #默认sudo用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#remote_port = 22
#host_key_checking = False #检查对应服务器的host_key,建议取消注释
#log_path = /var/log/ansible.log #日志文件
二、ansible SSH优化
1、关闭密钥检测(远程主机公钥检测,不要提示yes)
#vim /etc/ansible/ansible-cfg
host_key_checking=False
cat /etc/.ssh/known_hosts
2、openssh连接优化 (远程主机)
vim /etc/ssh/sshd_config
GSSAPIAuthentication no
UseDNS no
3、ansible facts缓存优化
在playbook中,加入:
gather_facts: no
4、ControlPcrsist SSH优化 (远程主机)
SSH会话保持功能,客户端 一次连接上SSH后,再去连接时,不用重新连接,直接复用会话
cat>>/root/.ssh/config <<-EOF
Host *
Compression yes
ServerAliveInterval 60
ServerAliveCountMax 5
ControlMaster auto
ControlPath ~/.ssh/%r@%h-%p
ControlPersist 4h
EOF
三、ansible基本命令使用
1、语法简介
ansible ansible-doc ansible-playbook ansible-vault
ansible-console ansible-galaxy ansible-pull
ansible-doc
ansible-doc: 后接模块名,显示模块帮助
-a 显示所有模块的文档
-l,--list 列出可用模块
-s,--snippet 简短说明(常用),显示指定模块的playbook片段,如:ansible-doc ping ; ansible-doc -s ping 查看指定模块帮助用法
ansible通过ssh实现配置管理,应用部署,任务执行等功能,建议配置ansible端能基于密钥认证的方式联系各被管理节点
语法:
ansible <host-pattern> [-m module_name] [-a args]
(ansible 主机 -m 模块名 -a 参数),如ansible all -m shell -a 'ping -c 2 www.baidu.com' -k
--version 显示版本
-m module 指定模块,默认为command
-v 详细过程 -vv -vvv更详细
--list-host 显示主机列表,可简写 --list
-k,--ask-pass 提示输入ssh连接密码,默认key验证
-K ,--ask-become-pass 提示输入sudo时的口令
-C ,--check 检查,并不执行
-T, --timeout=TimeOut 执行命令的超时时间,默认10s
-u ,--user=Remote_user 执行远程执行的用户
2、ansible的host-pattern 匹配主机的列表
all: 表示所有的inventory中的所有主机
* :通配符
ansible "*" -m ping
ansible 192.168.1.* -m ping
ansible "*server" -m ping
或关系 ":"
ansible 'web:db' -m ping
ansible '192.168.1.10:192.168.1.11' -m ping
逻辑与 ":&"
ansible 'web:&db' -m ping
在web组并且在db组 中都存在的主机
逻辑非
ansible 'web:!db' -m ping
在web组,但不在db组中的主机,注:这里为单引号
综合逻辑
ansible 'web:db:&app:!ftp' -m ping #在web或db中,且在app中,且不在ftp中
正则表达式
ansible "web:&db" -m ping
ansible "~(web|db).*\.otoyix\.com" -m ping
3、ansible命令执行过程
1)、加载自己的配置文件,默认/etc/ansible/ansible.cfg
2)、加载自动对应的模块文件,如command
3)、通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-xxxx/xxx.py文件
4)、给文件+x 执行权限
5)、执行并返回结果
6)、删除临时py文件,sleep 0 退出
4、执行状态
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
5、ansible-vault
功能:管理加密解密yml文件
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
ansible-vault encrypt hello.yml #加密
ansible-vault decrypt hello.yml #解密
ansible-vault view hello.yml #查看
ansible-vault edit hello.yml #编辑加密文件
ansible-vault rekey hello.yml #修改口令
ansible-vault create new.yml #创新新文件
6、ansible-console: 2.0+ 新增加的,可交互执行命令,支持tab
执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$
设置并发数:forks 3 #设置并发为3
切换组: cd 主机组 #cd dbserver
列出当前组主机列表:list
列出所有的内置命令: ?或help
示例:
root@all (3)[f:5]$ cd 192.168.1.12
root@192.168.1.12 (1)[f:5]$ list
192.168.1.12
root@192.168.1.12 (1)[f:5]$ hostname name=1_12
192.168.1.12 | CHANGED => {
"ansible_facts": {
"ansible_domain": "",
"ansible_fqdn": "1_12",
"ansible_hostname": "1_12",
"ansible_nodename": "1_12",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "1_12"
}
四、ansible常用模块 详解
1、Command模块 :
在远程主机执行命令,默认模块,可忽略-m选项
ansible dbserver -m command -a 'pwd'
ansible all -m command -a 'pwd|grep oo' 不成功
注: 此命令在-a 中不支持 $varname < > | ; &等,可以用shell模块来实现
chdir : 相当于cd
ansible all -a 'chdir=/boot ls' #进入boot目录中再执行命令ls
creates
ansible all -a 'creates=/etc/passwd df -Th' #如果/etc/passwd文件存在,则不执行后面的命令操作
removes
ansible all -a 'removes=/etc/passwd2 df -Th' # 如果文件存在,则执行后面的操作,也就是如果文件不存在,则不执行后面的命令操作(与creates相反的意思)
2、shell 模块
和command相似,用shell执行命令
ansible all -m shell -a 'pwd|grep oo'
调用bash命令,支持command不支持的复杂命令。但也有可能会失败,建议先写脚本、copy到远程 再执行脚本,再把需要的结果拉回执行命令的机器
注:也同样使用cddir creates removes参数
3、script 模块
运行脚本
#不需要将脚本文件发送至远程服务器,只要ansible机器中存在,可以直接运行
ansible db -m script -a "/root/ansible/f1.sh"
4、copy 模块
backup 如果远程主机存在同名且内容不一致时的文件时,则会备份远程主机中的文件
dest #远程主机 文件存放路径
mode #权限
owner #所有者
src #源,ansible机器中要复制的哪个文件
content #直接将内容写入到目标主机中
ansible all -m copy -a 'content="hello\notoyix\nsss" dest=/tmp/f1.txt' #如果文件存在,则直接清除内容后写入
ansible all -m copy -a 'src=/root/test dest=/root/test backup=yes mode=0777 owner=test2 group=test2'
注:
1、当文件内容一样时,不会发重复制
2、目录时,会复制到dest/下,且backup时,不会备份整个目录,而是备份其中相同文件名(内容不一样时)
ansible 192.168.1.10,192.168.1.12 -m copy -a 'src=/root/dir dest=/root/ backup=yes mode=0777 owner=test2 group=test2'
5、Fetch 模块
从客户端拉取文件(一个文件且不能是目录)至ansible主机,与copy相反,目录时,建议先执行tar打包后 再拉取
ansible 192.168.1.12 -m fetch -a 'src=/data/a.log dest=/data/logs/'
拉取后,会多生成目录,上面一条路径为 /data/logs/192.168.1.12/data/a.log
6、file 模块
设置文件属性
ansible 192.168.1.12 -m file -a 'path=/tmp/test.log state=touch'
#创建文件,这里的path可以换成name或dest,效果一样
ansible web -m file -a 'src=/app/testfile dest=/app/testfile-link state=link'
state :
directory(目录,没有则创建)、
file(与directory,返回文件的状态,不会创建)、
touch(空文件) 、
link(软链接)、
absent(删除及递归删除)
也有mode owner group参数
ansible 192.168.1.12 -m file -a 'name=/tmp/test state=absent' #删除文件与目录
7、hostname 模块
修改主机名
ansible 192.168.1.12 -m hostname -a 'name=12'
#立即且永久生效,centos7中改了/etc/hostname文件,但没有改/etc/hosts文件
8、cron 模块 :计划任务
支持时间:minute,hour,day,month,weekday
ansible web -m cron -a 'minute=*/5 weeekday=1,2,5 job="/usr/sbin/sh /data/sh/a.sh" name=a_script' #创建任务
ansible db -m cron -a 'state=absent name=a_script' #删除任务
ansible db -m cron -a 'disabled=true job="/usr/sbin/sh /data/sh/a.sh" name=a_script' #禁用任务
ansible db -m cron -a 'disabled=flase job="/usr/sbin/sh /data/sh/a.sh" name=a_script' #启动任务,disabled也可以使用yes或no
9、yum 模块 :包管理
ansible dbserver -m yum -a 'mane=httpd,vsftpd state=latest' #安装
ansible dbserver -m yum -a 'name=httpd,vsftpd state=absent' #卸载
state:
installed/latest/present(安装,默认选项) 、
absent/removed(卸载)
ansible dbserver -m yum -a 'name=/data/xxx.rpm disable_gpg_check=yes' #在远程主机上安装离线rpm包,禁用gpg检查
ansible dbserver -m yum -a 'name=dstat update_cache=yes' #更新缓存(需要附带装一个包)
10、service 模块 :管理服务
pattern: 模式
enabled : 是否开机启动
name: 服务名
runlevel: 启动级别
state: stopped/started/reloaded/restarted
ansible db -m service -a 'name=httpd state=started enabled=yes'
11、User 模块 :管理用户
comment: 注释
create_home: 是否创建家目录
expires: 过期时间
group: 主组
groups: 附加组
home: 家目录
shell: shell类型,/sbin/noloin等
name: 用户名
password: 加密口令
remove: 删除用户家目录
state: absent、persent(创建、修改 默认)等
system: 是否是系统帐号
ansible all -m user -a 'name=user1 system=yes comment="test user" uid=1000 home=/home/user1 group=user1 groups=root,bin'#创建、修改用户
ansible all -m user -a 'name=user1 state=absent remove=yes'#删除用户及家目录
12、Group 模块 :管理组
gid : 组ID
name: 组名
state: absent、present(默认)
system: yes/no(默认)
ansible all -m group -a 'name=testgroup system=yes'
ansible all -m group -a 'name=testgroup state=absent'
ansible all -m group -a 'name=test10 gid=1011' #常用 修改组ID
13、setup 模块 : 查看远程主机变量信息
(变量名查看,以被ansible-playbook引用)
filter: 过滤,返回 正则匹配后的信息
ansible 192.168.1.12 -m setup -a 'filter=*address*'
14、template 模板
将一个文件当作为模块文件传至远程主机
注:
jinja2为模板语言 且 只能用于 playbook中,不用用于AD hoc
template 示例:
./
├── nginxtemplates.yml
└── templates
└── nginx.conf.j2
cat nginxtemplates.yml
---
- hosts: all
remote_user: root
tasks:
- name: 'cp nginx.conf'
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf backup=yes
notify: restart nginx
when: ansible_all_ipv4_addresses==192.168.1.12
cat templates/nginx.conf.j2 |grep process
#worker_processes auto;
worker_processes {{ ansible_processor_vcpus + 1 }};
五、ansible-galaxy
url https://galaxy.ansible.com 下载相应的roles
列出所有已安装的galaxy
ansible-galaxy list
安装galaxy #联网安装
ansible-galaxy install geerlingguy.nginx
会自动下载解压 /root/.ansible/roles/geerlingguy.nginx
删除galaxy
ansible-galaxy remove geerlingguy.nginx
六、ansible playbook基础
1、语法: ansible-playbook [options] playbook.yml [playbook2 …]
options:
-C,--check :#只检查不真正执行
--list-hosts : #列出运行任务的主机
--limit #主机列表,只在特定主机列表中的主机执行 ,也可以为单台主机,示例:ansible-playbook file.yml --limit webs #只在webs中执行
-v ,-vv ,-vvv 更详细
--list-tasks #查看tasks任务列表
--list-tags #只看tags
ansible-playbook hello.yml
cat hello.yml
---(这里习惯写---开头,可以不写)
#hello world yml file
- hosts: webs
remote_user: root
tasks:
- name: hello word
command: /usr/bin/wall hello word
2、原理:
playbook是由一个或多个’play’组成的列表
play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们连同起来按事先编排的机制同唱一台大戏
playbook采用yaml语言编写
3、playbook核心元素
hosts: 执行的远程主机列表
tasks: 任务集
varniables: 内置变量或自定义变量在playbook中调用
templates: 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
handlers 和notity: 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags: 标签,指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过这些代码片段
ansible-playbook -t tagsname useradd.yml
4、playbook基础组件
hosts:
playbook中的每一个play的目的都是为了让某个或些主机以某个指定的用户身份执行任务。
hosts用于指定要执行指定任务的主机,须事先定义在主机清单中:
可以是如下形式:
a.otoyix.com
a.otoyix.com:b.otoyix.com
192.168.1.12
192.168.1.*
webs:dbs #两个组的并集
webs:&dbs #两个组的交集
webs:!dbs #webs,但不在dbs组中
示例: - hosts: webs:dbs
remote_user:
可用于hosts和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;
此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: webs
remote_user: root
tasks:
- name: test connect
ping:
remote_user: test
sudo: yes #默认sudo为root
sudo_user: wang #sudo为wang
task列表和action
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自上而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name ,则action的结果将用于输出
格式语法:
语法方法一: action: module arguments
语法方法二: module: arguments (建议使用)
方法二语法格式示例:
tasks:
- name: path
shell: pwd
注:shell和command模块后面跟命令,而非 key=value
1、 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers。
2、 任务可以通过"tags" 打标签,而后可以ansible-playbook命令上使用-t指定进行调用。
3、在tasks中,一个name对应一个模块,哪怕是相同的模块,如果有,会有一个不执行,建议分多个name中
5、playbook错误不退出,继续执行的方法
方法一:||/bin/true 或一个为真的语句,让此行的整体结果为真
tasks:
- name: run command
shell: /usr/bin/xxxx || /bin/true #在后面加上||/bin/true,相当于在后面 或了一个为真的执行语句,这样整体结果值为 真了,就不会能出
方法二:使用ignore_errors来忽略错误信息
tasks:
- name: run command
shell: /usr/bin/xxx
ignore_errors: True #加上ignore_errors: True
注:playbook中的相对路径为 /root/ansible/ (用户家目录下的ansible目录)
七、notify 与 handlers、tags 及 变量使用
1、notify和 handlers结合使用触发条件
handlers 是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作
notify此action可用于每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
notify和 handlers示例:
- hosts: webs
remote_user: root
tasks:
- name: "安装httpd包"
yum: name=httpd
- name: "复制替换配置文件"
copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
notify: #当这块action发生变化时,会触发notify,会通知下面的两个handlers 动作,这里可以匹配1个或多个 handlers 动作
- restart service
- check process
- name: "启动服务"
service: name=httpd state=started enabled=yes
handlers:
- name: restart service
service: name=httpd state=started
- name: check process
shell: killall -0 httpd >>/var/log/test.log
2、playbook中tags使用
注:如果 ansible-playbook 时没有加上 -t 或–tags 时,那么代表标签不生效,代表自动匹配上了所有的标签,会执行有或没有标签的任务
tags示例:
- hosts: webs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: cp config 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
可以
tags:
- install
- deploy
ansible-playbook -t conf httpd.yml #只执行 指定conf标签的动作,其他不作执行
注: 在一个yml文件中,tags可以相同,ansible-playbook时按先后顺序执行,ansible-playbook时也可以使用多个–tag= --tag=
3、playbook 变量
优先级:playbook -e > epl.yml > hosts
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量来源:
1)、ansible setup facts 远程主机的所有变量都可直接调用
ansible -m setup
2)、在/etc/ansible/hosts中定义
变通变量:主机组中主机单独定义,优先级高于公共变量
[websrvs]
192.168.1.12 http_port=82
192.168.1.11 http_port=81
公共(组)变量:针对主机组中所有主机定义统一变量
[websrvs]
......
[websrvs:vars] #对websrvs组中所有成功有效
env=www
domainname=otoyix.com
3)、通过命令行指定变量,优先级最高
示例
---
- hosts: appsrvs
remote_user: root
tasks:
- name: '安装软件包'
yum: name={{ appname }}
- name: '启动服务 及 设置开机自动启动'
service: name={{ appname }} state=started enabled={{ appenable }}
调用
ansible-playbook xxx.yml -e 'appname="nginx" appenable="yes"'
4)、在playbook中定义
示例:
---
- hosts: appsrvs
remote_user: root
vars:
- appname: vsftpd
- appenable: yes
tasks:
- name: '安装软件包'
yum: name={{ appname }}
- name: '启动服务 及 设置开机自动启动'
service: name={{ appname }} state=started enabled={{ appenable }}
5)、在role中定义(vars.yml文件)
使用变量文件中定义
示例:
tree .
.
├── appinstll.yml
└── vars.yml
cat vars.yml
var1: httpd
var2: vsftpd
cat appinstll.yml
- hosts: web12
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ var1 }}
- name: create file
file: name=/tmp/{{ var2 }}.log state=touch mode=644
八、playbook 模板templates
文本文件,嵌套有脚本(使用模板编程语言编写)
1、Jinja2语言,使用字面量,有下面形式
字符串: 使用单引号或双引号
数字: 整数,浮点数
列表: [item1,item2...]
元组: (item1,item2,...)
字典: {key1:value1,key2:value2,...}
布尔型: true/false
算术运算: +,-,*,/,//(整除,不要小数点),%(取模),**(幂次方,取指数)
比较运算: ==,!=,>,>=,<, <=
逻辑运算: and,or,not
流表达式: For IF When
2、templates功能:
根据模块文件动态生成对应的配置文件
templates文件必须存放在templates目录下,且命名为.j2结尾
yaml/yml文件需和templates目录平级,目标结构如下:
./
├── nginx.yml
└── templates
└── nginx.conf.j2
基础 templates示例:
cp /etc/nginx/nginx.conf templates/nginx.conf.j2
vim testtemplates.yml
---
- hosts: 192.168.1.12
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: cp templates
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf #这里的模块文件得放至templates目录中,或写绝对路径
- name: start nginx
service: name=nginx state=started enabled=yes
ansible-playbook testtemplates.yml
变量 templates 示例
./
├── nginxtemplates.yml
└── templates
└── nginx.conf.j2
cat nginxtemplates.yml
---
- hosts: all
remote_user: root
tasks:
- name: 'install package'
yum: name=nginx
- name: 'cp nginx.conf'
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf backup=yes
notify: restart nginx
when: ansible_all_ipv4_addresses==192.168.1.12
- name: 'service nginx'
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
cat templates/nginx.conf.j2 |grep process
#worker_processes auto;
worker_processes {{ ansible_processor_vcpus + 1 }};
#注:上面 notify触发handlers的执行器,变量为ansible_processor_vcpus
七、playbook 条件判断when
条件测试:如果需要根据变量、facts或此前任务执行结果来做为某task执行与否的前提时,要用到条件测试,通过when语句实现,在task中使用,jinja2的语法格式
when语句
在task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法
示例:
- name: 'cp nginx.conf'
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf backup=yes
notify: restart nginx
when: ansible_all_ipv4_addresses == ["192.168.1.12"]
九、playbook字典 with_items
1、迭代:当有需要重复性执行的任务时,可以使用迭代机制
对迭代项的引用,固定变量名为“item”
要在task中使用with_items给定要迭代的元素列表
表格格式:
字符串
字典
示例:
---
- hosts: web
remote_user: root
tasks:
- name: '创建多个文件'
file: name=/tmp/{{ item }} state=touch mode=755
with_items:
- file1
- file2
- file3
- name: install package
yum: name={{ item }}
with_items:
- vsftpd
- sl
- hping3
2、playbook中迭代嵌套子变量:
示例:创建user1 user2 user3分别属于g1 g2 g3组,用户与组ID分别为 1051 1052 1053
---
- hosts: web
remote_user: root
tasks:
- name: create some groups
group: name={{ item.name }} gid={{ item.gid }}
with_items:
- {name: 'g1',gid: '1051'}
- {name: 'g2',gid: '1052'}
- {name: 'g3',gid: '1053'}
- name: create users
user: name={{ item.name }} uid={{ item.uid }} group={{ item.gruop }}
with_items:
- {name: 'user1',uid: '1051',gruop: 'g1'}
- {name: 'user2',uid: '1052',gruop: 'g1'}
- {name: 'user3',uid: '1053',gruop: 'g1'}
3、template中使用 for
cat testfor.yml
---
- hosts: web
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: copy conf
template: src=testfor.conf.j2 dest=/tmp/for.conf
cat templates/testfor.conf.j2
{% for port in ports %}
server {
listen {{ port }}
}
{% endfor%}
结果:目标主机
cat /tmp/for.conf
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
另:“template中使用 for” 可以演变为 字典 键值对形式
vim testfor.yml(改vars中的一段)
vars:
ports:
- web1:
domain: a.otoyix.com
port: 81
- web2:
domain: b.otoyix.com
port: 82
- web3:
domain: c.otoyix.com
port: 83
vim templates/testfor.conf.j2
{% for listenport in ports %}
server {
listen {{ listenport.port }} #注:这里的web1后也可以写内容,与domain port是平级的,这里为了好看,就没有写内容了
}
{% endfor%}
结果一样
4、template中使用 if
vim testif.yml
---
- hosts: web
remote_user: root
vars:
ports:
- web1:
domain: a.otoyix.com
port: 81
- web2:
domain: b.otoyix.com
port: 82
- web3:
domain: c.otoyix.com
port: 83
tasks:
- name: copy conf
template: src=testif.conf.j2 dest=/tmp/if.conf
vim templates/testif.conf.j2
{% for p in ports %}
server {
listen {{ p.port }}
{% if p.domain is defined %} #意思是:如果p.domain被定义,则下面执行下面一下,否则跳过本次if
servicename {{ p.domain }}
{% endif%}
}
{% endfor%}
结果:
server {
listen 81
servicename a.otoyix.com
}
server {
listen 82
servicename b.otoyix.com
}
server {
listen 83
servicename c.otoyix.com
}
十、ansible roles
roles
ansible自1.2版本引入新特性,用于层次性、结构性地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
也就是将之前一个playbook中的内容,全部拆分,在多个目录中,像templates files等,把变量 task 主机等放至不同的目录中。
模块化:把不同内容分类至不同的目录中,使用时,直接引用即可,可重复调用
复杂场景:建议使用roles,代码复用高
变更指定主机或主机组
如命名不规范维护和传承成本大
某些功能需多个playbook,通过includes即可实现
角色(roles): 角色集合
在任意目录下创建roles目录,官方建议放在/etc/ansible/roles
1、 roles目录结构
每个角色,以特定的层级目录结构进行组织
roles目录结构:
blaybook_role.yml
roles/
project/
tasks/
main.yml
group.yml
user.yml
copyfile.yml
start.yml
files/
vars/ 不常用
main.yml
default/ 不常用
templates/
handlers/
main.yml
meta/ 不常用
2、roles各目录作用
/roles/project/: 项目名称,有以下子目录
files/: 存放由copy或script模块等调用的文件
templates/: template模块查找所需要模板文件的目录
tasks/: 定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其他的文件需要在些文件中通过include进行包含调用
handlers/: 至少应该包含一个名为main.yml的文件;其他的文件需要在些文件中通过include进行包含调用
vars/: 定义变量,至少应该包含一个名为main的文件;其他的文件需要在些文件中通过include进行包含调用
meta/: 定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main的文件,其他的文件需要在些文件中通过include进行包含调用
default/: 设置默认变量时使用此目录中的main.yml文件
3、roles示例
:
[root@ansible ~]# tree /etc/ansible/
/etc/ansible/
├── ansible.cfg
├── hosts
├── hosts.bak
├── nginx_role.yml
└── roles
├── httpd
├── mysql
└── nginx
├── tasks
│ ├── group.yml
│ ├── main.yml
│ ├── restart.yml
│ ├── start.yml
│ ├── templ.yml
│ ├── user.yml
│ └── yum.yml
└── templates
└── nginx.conf.j2
cat nginx_role.yml
- hosts: web
remote_user: root
roles:
- role: nginx
cat roles/nginx/tasks/main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: start.yml
cat roles/nginx/tasks/group.yml
- name: '创建组www'
group: name=www gid=1010
cat roles/nginx/tasks/restart.yml
- name: restart nginx
service: name=nginx state=restarted
cat roles/nginx/tasks/start.yml
- name: start nginx
service: name=nginx state=started enabled=yes
cat roles/nginx/tasks/templ.yml
- name: copy conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
cat roles/nginx/tasks/user.yml
- name: '创建用户www'
user: name=www uid=1010 group=www system=yes shell=/sbin/noloin
cat roles/nginx/tasks/yum.yml
- name: 'install package'
yum: name=nginx
cat roles/nginx/templates/nginx.conf.j2 |head
user www;
worker_processes {{ ansible_processor_vcpus + 1 }};
结果: ps -ef|grep nginx
root 30022 1 0 13:49 ? 00:00:00 nginx: master process /usr/sbin/nginx
www 30023 30022 0 13:49 ? 00:00:00 nginx: worker process
www 30024 30022 0 13:49 ? 00:00:00 nginx: worker process
www 30025 30022 0 13:49 ? 00:00:00 nginx: worker process
4、可以调用多个角色
xxxx_role.yml
- hosts: web
remote_user: root
roles:
- role: nginx
- role: redis
5、引用另外一个角色的任务(task)
vim main.yml
- include: roles/vsftpd/tasks/copyfile.yml
-
#这里的roles 会自动向上找,这里为上上一级的roles目录。
注:如果有相对的文件,需要把文件放在本main.yml角色下的files/templates中 或绝对路径
6、角色中也可以加标签tags
hosts: web
remote_user: root
roles:
- { role: nginx, tags: ['deploy','web'] }
- { role: vsftpd, tags: ['deploy','web'] }
执行playbook时,可以匹配执行相关标签
也可以加when
roles:
- { role: nginx, tags: ['deploy','web'],when: ansible_distribution_major_version == "7" }
十一、roles 结合 上面内容综合示例
(未测试)
mkdir -p /etc/ansible/roles/app
cd /etc/ansible/roles/app
mkdir tasks templates vars handlers files
cd tasks
vim group.yml
- name: create group app
group: name=app system=yes gid=1011
vim user.yml
- name: create group app
user: name=app uid=1011 group=app system=yes shell=/sbin/noloin
vim yum.yml
- name: install nginx
yum: name=nginx
vim restart.yml
- name: start service
service: name=nginx state=started enabled=yes
vim templ.yml
- name: copy templ conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
vim ../templates/nginx.conf.j2 #下面2段
user {{ username }};
worker_processes {{ ansible_processor_vcpus + 1 }};
server {
listen {{ hpptport }};
listen [::]:{{ httpport }};
vim ../vars/main.yml
username: app
httpport: '80'
vim handlers/main.yml
- name: restart service
service: name=nginx state=restarted
touch files/vhosts.conf
vim tasks/copyfile.yml
- name: copy file
copy: src=vhosts.conf dest=/etc/nginx/vhosts/ owner=app mode=755
cd tasks
vim main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: copyfile.yml
- include: start.yml
vim /etc/ansible/app_reloe.yml
---
- hosts: web
remote_user: root
roles:
- app
--------------------
十二、结合jenkins前端发版本,示例 (已测试)
pipeline脚本
pipeline {
agent any
environment {
ProJect_Name = 'exam'
PROJECT_PATH = "/var/www/${ProJect_Name}"
Host = "web"
}
stages {
stage('pull') {
dir ("${env.PROJECT_PATH}") {
steps {
script {
sh "node --version"
sh "npm --version"
sh "git fetch origin && git checkout ${env.branch} && git checkout ./* && git pull"
}
}
}
}
stage('build') {
dir ("${env.PROJECT_PATH}") {
steps {
script {
sh "npm install"
sh "npm run build:test"
sh "\cp -rf dist /etc/ansible/roles/frontend_deploy/files/${ProJect_Name}/"
sh "ls -l /etc/ansible/roles/frontend_deploy/files/${ProJect_Name}/dist/"
}
}
}
}
stage('Deploy') {
steps {
script {
sh "ansible-playbook -e 'ProJect_Name=${ProJect_Name} hosts=${Host}' -t frontend_deploy /etc/ansible/frontend_deploy_roles.yml"
}
}
}
}
}
roles
mkdir -p /etc/ansible/roles/frontend_deploy/{files,tasks}
cd /etc/ansible/roles/frontend_deploy/tasks
tree /etc/ansible/
/etc/ansible/
├── ansible.cfg
├── frontend_deploy_roles.yml
├── hosts
├── hosts.bak
└── roles
├── frontend_deploy
│ ├── files
│ │ └── exam
│ │ ├── dist
│ │ │ └── test.txt
│ └── tasks
│ ├── copyfile.yml
│ ├── group.yml
│ ├── main.yml
│ └── user.yml
roles/frontend_deploy/tasks/copyfile.yml
- name: '将dist目录使用mv 备份'
shell: mv /var/www/{{ ProJect_Name }} /var/www{{ ProJect_Name }}.bak`date +%Y-%m-%d--%H-%M-%S`
tags:
- frontend_deploy
- name: '将dist目录至远程服务器/var/www/{{ ProJect_Name }}/dist'
copy: src={{ProJect_Name}}/dist dest=/var/www/ owner=www group=www mode=755 backup=yes
tags:
- frontend_deploy
roles/frontend_deploy/tasks/group.yml
- name: '创建组www'
group: name=www gid=1020
tags:
- frontend_deploy
- install
roles/frontend_deploy/tasks/main.yml
- include: group.yml
- include: user.yml
- include: copyfile.yml
roles/frontend_deploy/tasks/user.yml
- name: '创建www用户'
user: name=www uid=1020 group=www
tags:
- frontend_deploy
- install
---
- hosts: "{{ hosts }}"
remote_user: root
roles:
- frontend_deploy
ansible-playbook -e 'ProJect_Name=exam hosts=web' -t frontend_deploy /etc/ansible/frontend_deploy_roles.yml
---------------------------end