hit restart 基本 查看 权限 release templates 列表 conf
一、template 模板
二、playbook 中的条件判断
三、PlayBook 中的循环
四、角色(roles)
一、template 模板
template 使用了 Jinjia2 格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被 ansible 标记为 "changed" 状态。基于模板方式生成一个文件复制到远程主机
常用参数:
- 参数名 是否必须 默认值 选项 说明
- backup no no yes/no 建立个包括timestamp在内的文件备份,以备不时之需.
- dest yes 远程节点上的绝对路径,用于放置template文件。//必须是绝对路径
- group no 设置远程节点上的的template文件的所属用户组
- mode no 设置远程节点上的template文件权限。类似Linux中chmod的用法//group,owner
- owner no 设置远程节点上的template文件所属用户
- src yes 本地Jinjia2模版的template文件位置。//绝对或者相对路径
一般编程语言都有把自己嵌入到文本的模板语言
php: 直接嵌入
python:Jinja2 //ansible 就是 python 写的
Jinja2 中常用的编程元素
字面量: 字符串, 单引号或者双引号引用即可
数字: 整数和浮点数
列表:[item1,item2,...]
元祖:(item1,itme2,...) // 不可变
字典:{key1:value1,key2:value2,...}
布尔型: true/false
算数运算:
+,-,*,/,%, //,** //: 表示只要熵
比较运算:
==,!=,>=,<=,<,
逻辑运算符:
and,or,not
ansible-doc -s template
利用模板: 实现对不同主机的 nginx 配置成不同的启动 processor
vim nginx.conf.j2
worker_processes {{ansible_processor_vcpus}}; // 使用模板变量
listen {{http_port}}; // 自定义变量
注: 这个参数是在 setup 模板中
worker_processes {{ansible_processor_vcpus-1}}; // 可以直接增加或减去
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=0644
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=bin group=wheel mode="u=rw,g=r,o=r"
vim ansible/hosts
[websrvs]
192.168.4.100 http_port=888
192.168.4.116 http_port=808 // 使用主机变量
[root@localhost ~]# cat nginx.yaml
- - hosts: websrvs
- remote_user: root
- tasks:
- - name: install nginx
- yum: name=nginx state=present
- - name: install conf
- template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=0644
- notify: restart nginx
- tags: instconf
- - name: start nginx service
- service: name=nginx state=started
- handlers:
- - name: restart nginx
- service: name=nginx state=restarted
ansible-playbook --check nginx.yaml
ansible-playbook nginx.yaml
注意: 6 和 7 的配置 nginx 配置文件不一样
执行结果
RUNNING HANDLER [restart nginx]
************************************************
changed: [192.168.4.110] // 发生改变的话, 就会执行 restart nginx
changed: [192.168.4.106]
handlers:用于当关注的资源发生变化时触发一定的操作。
"notify" 这个 action 可用于在每个 play 的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作
取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在 notify 中列出的操作称为 handler,也即 notify 中调用 handler 中定义的操作。
二、playbook 中的条件判断
多个条件:and/when/or
1. 条件测试: tasks 上使用 when 语句, 在 tasks 上使用, Jinja2 的语法格式。根据不同的 OS 分配不同的机制
字符串要加引号 {单双都可}, 数值一定不加引号
ansible all -m setup | grep "ansible_distribution" // 版本信息
"ansible_distribution": "CentOS",
"ansible_distribution_major_version": "6",
"ansible_distribution_release": "Final",
"ansible_distribution_version": "6.6",
tasks:
- name: install conf file
template: src=nginx.conf.7
when: ansible_distribution_major_version == '7' 4tasks:
- name: install conf file
template: src=nginx.conf.6
when: ansible_distribution_major_version == '6'
条件测试 1: when
- - hosts: websrvs
- remote_user: root
- tasks:
- - name: copy file 6
- template: src=/tmp/6.txt dest=/tmp
- when: ansible_distribution_major_version =='6'
- notify: restart nginx
- - name: copy file 7
- template: src=/tmp/7.txt dest=/tmp
- when: ansible_distribution_major_version =='7'
- notify: restart nginx
- handlers:
- - name: restart nginx
- service: name=nginx state=restarted
2.register
示例,判断 sda6 是否存在。存在就执行一些相应的脚本,则可以为该判断注册一个 register 变量,并用它来判断是否存在,存在返回 succeeded, 失败就是 failed.
- - name:Create a register to represent the status if the /dev/sda6 exsited
- shell: df -h | grep sda6
- register: dev_sda6_result
- ignore_errors:True
- tags: docker
- - name:Copy docker-thinpool.sh to all hosts
- copy: src=docker-thinpool.sh dest=/usr/bin/docker-thinpool mode=0755
- when: dev_sda6_result | succeeded
- tags: docker
假如我们想忽略某一错误, 通过执行成功与否来做决定, 我们可以像这样:
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
三、PlayBook 中的循环
循环: 迭代, 需要重复执行的任务;
例如需要同时安装, nginx,httpd,php-fpm,php-mysql,mariabd 等
对迭代项的引用,固定变量名为 "item"
而后, 要在 task 中使用 with_items 给定要迭代的元素列表
列表方法:
字符串:
字典:
1. 标准循环:
- - name: install some packages
- yum: name={{ item }} state=present
- with_items:
- - nginx
- - memcached
- - php-fpm
- //将可以安装多个软件同时安装
- 循环测试脚本:item
- [root@localhost ~]# cat e.yaml
- - hosts: websrvs
- remote_user: root
- tasks:
- - name: install pkgs
- yum: name={{ item }} state=present
- with_items:
- - telnet
- - vim
- - tree
循环测试脚本 3.
创建三个用户分别属于不同组
[root@localhost ~]# cat f.yaml
- - hosts: websrvs
- remote_user: root
- tasks:
- - name:groupadd
- group: name={{ item }} state=present //注意:引用的时候使用的是{{ }}没有s,列举参数的时候使用的是复数,items
- with_items:
- - group11
- - group12
- - group13
- - name:add users
- user: name={{ item.name }} group={{ item.group}} state=present
- with_items:
- -{ name:'user11',group:'group11'}
- -{ name:'user12',group:'group12'}
- -{ name:'user13',group:'group13'}
==============================
[root@localhost ~]# cat c.yaml
- - hosts: testweb
- remote_user: root
- tasks:
- - name: install user
- user: name={{ item.name }} state=present groups={{ item.groups }}
- with_items:
- -{ name:'testuser1', groups:'wheel'}
- -{ name:'testuser2', groups:'root'}
// 创建 testuser1{wheel},testuser2{root}
注意:
1.hosts 不是 host
2. 严格对齐, 列表和内容分开
3.name: 'user11' // 中间必须有空格, 字符必须用引号,
4. 目标主机存在 user11 或其中一个用户的话, 也会返回错误
5.whih_itmes 后的内容为下一个 key-value (先加空格)
2. 嵌套循环:
- -name:give users access to multiple databases
- mysql_user:name={{ item[0]}} priv={{ item[1]}}.*:ALL append_privs=yes password=foo
- with_nested:
- -['alice','bob'] //表示item[0],nested:嵌套
- -['clientdb','employeedb','providerdb']
- - name: here,'users' contains the above list of employees
- mysql_user: name={{ item[0]}} priv={{ item[1]}}.*:ALL append_privs=yes password=foo
- with_nested:
- -"{{users}}"
- -['clientdb','employeedb','providerdb']
[root@localhost ~]# cat c.yaml
- - hosts: testweb
- remote_user: root
- tasks:
- - name: install user
- user: name={{ item.name }} state=present groups={{ item.groups }}
- with_items:
- -{ name:'testuser1', groups:'wheel'}
- -{ name:'testuser2', groups:'root'}
- - name: give users access to multiple databases
- command:"echo name={{ item[0] }} priv={{ item[1] }} test={{ item[2] }}"
- with_nested:
- -['alice','bob']
- -['clientdb','employeedb','providerdb']
- -['1','2',]
- tags: netsted
输出:
3. 字典循环
- skipping:[192.168.2.122]=>(item=[u'alice', u'clientdb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'alice', u'clientdb', u'2'])
- skipping:[192.168.2.122]=>(item=[u'alice', u'employeedb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'alice', u'employeedb', u'2'])
- skipping:[192.168.2.122]=>(item=[u'alice', u'providerdb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'alice', u'providerdb', u'2'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'clientdb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'clientdb', u'2'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'employeedb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'employeedb', u'2'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'providerdb', u'1'])
- skipping:[192.168.2.122]=>(item=[u'bob', u'providerdb', u'2'])
假如你有以下变量:
users:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
你想打印出每个用户的名称和电话号码. 你可以使用 with_dict 来循环哈希表中的元素:
tasks:
- name: Print phone records
debug: msg="User {{item.key}} is {{item.value.name}} ({{item.value.telephone}})"
with_dict: "{{users}}"
4. 遍历文件 whith_file,whith_fileglob
with_file 是将每个文件的文件内容作为 item 的值
- - hosts: all
- tasks:
- # first ensure our target directory exists
- - file: dest=/etc/fooapp state=directory
- # copy each file over that matches the given pattern //注意copy必须要用 "-"
- - copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
- with_fileglob:
- -/playbooks/files/fooapp/*
with_fileglob 是将每个文件的全路径作为 item 的值, 在文件目录下是非递归的, 如果是在 role 里面应用改循环, 默认路径是 roles/role_name/files_directory
5. 并行数据循环
已知变量:
alpha: ['a', 'b', 'c', 'd']
numbers: [1, 2, 3, 4]
如果你想得到'(a, 1)'和'(b, 2)'之类的集合. 可以使用'with_together':
tasks:
- debug: msg="{{item.0}} and {{item.1}}"
with_together:
- "{{alpha}}"
- "{{numbers}}"
还有更多的循环介绍方法请参考本文尾部链接地址...
四、角色:(roles)
一个主机可以担任多种角色:
定义为多个身份, 用的时候直接调用该身份即可
角色名就是目录名, 任何角色都不能引用自己所属目录之外的其他目录文件
roles/
mysql/
httpd/
nginx/
memcached/
每个角色, 以特定的层级目录结构进行组织: 注意: 大多数都是复数 "s", 除了 meta
mysql/
files/ 存放由 copy 或 script 模块等调用的文件
templates/ template 模块查找所需要的模板文件目录;
handlers/ 至少应该包含一个名为 main.yml 文件
vars/ 至少一个 main.yml
tasks/ 基本元素: 至少一个名为 main.yml 的文件, 其他的文件需要在此文件中通过 include 进行包含
meta/ main.yml, 定义当前角色的特殊设定, 及其依赖关系
default/ 设定默认变量时使用此目录中的 main.yml 文件
调用角色:
- hosts: websrvs
remote_user: root
roles:
- mysql // 会自动到 mysql 目录中跑一遍
- memcached
- nginx
mkdir /etc/ansible/roles/nginx/{files,tasks,templates,handlers,vars,default,meta} -pv
cd /etc/ansible/roles/nginx/
1.tasks
[root@localhost nginx]# cat tasks/main.yml
- - name: install nginx pkg
- yum: name=nginx state=present
- - name: install conf file
- template: src=nginx.conf dest=/etc/nginx/nginx.conf.test ///nginx.conf不在同级目录,但是role可以直接识别为template中的文件
- - name: start nginx
- service: name=nginx state=started enabled=true
templates 目录中有存放的 nginx.conf
2. 在其他地方创建 nginx.yaml // 这个可以放在其他地方
- - hosts: websrvs
- remote_user: root
- roles:
- - nginx
执行:
ansible-playbook --check nginx.yaml
- /etc/ansible/roles/nginx/
- ├──default
- ├── files
- ├── handlers
- ├── meta
- ├── tasks
- │ └── main.yml
- ├── templates
- │ └── nginx.conf
- └── vars
3. 添加 handler
修改 handlers/main.yml
- name: restart nginx // 注意, 前面的 - 不可少, 代表是 handler 的一个清单
service: name=nginx state=restarted
创建 tasks/main.yml
- - name: install nginx pkg
- yum: name=nginx state=present
- - name: install conf file
- template: src=nginx.conf dest=/etc/nginx/nginx.conf.test
- notify: restart nginx
- tags: instconf
- - name: start nginx
- service: name=nginx state=started enabled=true
修改一下 nginx.conf // 否则不会触发 handler
ansible-playbook -t instconf --check g.yaml
4. 变量
[root@localhost yaml]# cat h.yaml
- - hosts: websrvs remote_user: root vars: - username: testuser1 - groupname: testgroup1 tasks: - name: create group group: name = {
- { groupname
- }
- } state = present - name: create user user: name = {
- { username
- }
- }group = {
- { groupname
- }
- } state = present
在 playbook 中定义变量的方法
vars:
- var1: value1
- var2: value2
ansible-playbook -e "groupname=mygrp1" -e "username=myuser" --check h.yaml
// 可以覆盖变量, 在命令行中定义的变量, 会覆盖
5. 变量使用, roles 中
vim nginx/vars/main.yml
username: nginx
vim templates/nginx.conf
user {{username}} // 让 nginx 以该用户的身份运行
其他不修改
ansible
问题:
[root@localhost yaml]# ansible-playbook --check g.yaml
ERROR! The vars/main.yml file for role 'nginx' must contain a dictio
nary of variables
原因: vars/main.yml 前面不需要 - , 和其他的 main.yml 不一样
ansible-playbook -e "username=adm" --check nginx.yml // 假如想改变运行 nginx 的用户, 直接修改即可
6. 在 playbook 中调用角色方法 2
vim nginx.yaml
- hosts: websrvs
remote_user: root
roles:
- {role: nginx, username: nginx} // 向该角色传递变量
键 role 用于指定角色名称, 后续的 k/v 用于传递变量给角色
还可以基于条件测试, 实现角色调用;
例如:
roles:
- {role: nginx,when:"ansible_distribution_major_version == '7'}
// 条件满足时, 应用该角色
[root@localhost yaml]# cat i.yaml
- hosts: websrvs
remote_user: root
roles:
- {role: nginx, username: nginx, when:"ansible_distribution_major_version == '7'"}
// 只有在 OS 为 7 才会执行
7. 安装 memcached,占用内从空间为当前可用空间的 1/3
mkdir -pv memcached/{tasks,vars,templates,hanlers}
- vim tasks/main.yml
- - name: install pack
- yum: name=memcached state=present
- - name: install conf
- template: src=memcached.j2 dest=/etc/sysconfig/memcached
- notify: restart memcached
- tags: memconf
- - name: start memcached
- service: name=memcached state=started enabled=true
- vim templates/memcached
- PORT="11211"
- USER="memcached"
- MAXCONN="1024"
- CACHESIZE="{{ ansible_memtotal_mb//4 }}" //除以4,可能是小数,因此// 取出整数
- OPTIONS=""
- vim handlers/main.yml
- - name: restart memcached
- service: name=memcached state=restarted
- vim lnm.yaml //同时调用两个role
- - hosts: websrvs
- remote_user: root
- - roles:
- -{ role: nginx,when: ansible_distribution_version =='7'}
- -{ role: memcached,when: ansible_hostname =='memcached'}
ansible-playbook -t memconf lnm.yaml
出错原因:
1.main.yml 中, template 是没有 s 的, 但是目录名是有 s 的
2.notify 不是 nofify
=======================================================
yaml 和 yml 格式的区别:
1.yml 不需要 hosts,remote_user // 这些在 yaml 中定义
- name: install pkgs
yum: name=memcached state=present
2.yaml 一定要 - hosts,-remote_user
- hosts: all
remote_user: root
roles:
- {role: nginx,when:ansible_distribution_version =='7'}
ansible all -m setup // 查看所有内置变量
www.ansible.com.cn // 站点,
推荐:参考 ansible 官方 role 的写法,自行创建 role 进行练习
http://blog.csdn.net/kellyseeme/article/details/50619562
http://www.ansible.com.cn/docs/playbooks_loops.html
https://www.cnblogs.com/v394435982/p/5593274.html
Ansible 详解(三)
来源: http://www.bubuko.com/infodetail-2452957.html