Ansible 使用基础 ( 二 )------ Playbook 基本使用
YAML 基本语法规则:
- YAML文件内同区分大小写,其中的key/valye的值均大小写敏感
- 使用缩进表示层级关系,缩进的空格数目不重要,只要相同层级的元素左侧对齐即可【空格和tab不能混用】
- 多个key/value 可以分行也可以写在一行,以 , 分开
- value 可以是一个字符串,也可以是一个列表
- 一个完整的代码功能最少需要包含 name 和 task 元素
- 一个 name 只能包括一个 task
- YAML 文件扩展名通常为 yml 或 yaml
- # 表示注释,从这个字符一直到行尾,都会被解析器忽略。
YAML 支持的数据结构有:
字典,写法如下:
{name: 'eeeeee',jog: 'kkkk',skill: 'ddddd'}
name: eeeeeee
job: kkkkkk
skill: ddddd
列表,写法如下:
[A,B,C,D]
- A
- B
- C
- D
纯量:单个的、不可再分的值
PLAYBOOK 核心元素:
• Hosts 执行的远程主机列表
• Tasks 任务集
• Variables 内置变量或自定义变量在 playbook 中调用
• Templates 模板,可以替换模板文件中的变量实现一些简单的逻辑文件
• Handlers 和 notigy 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
• tags 标签,指定某条任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些大吗为测试其确定没有便哈的时间任然会非常长。此时如果确信其没有变化,可以使用tags跳过这些代码片段
HOSTS 组件【用于指定执行任务的主机,必须事先定义在主机清单中】
- hosts: web:db ## 指定主机模式与 Ansible 命令中主机模式相同
remote_user 组件[用于Host和task中,也可以通过指定通过sudo的方式在远程主机上执行任务]:
- hosts: web
remote_user: root
Task 列表
tasks:
- name: INSTALL httpd
yum: name=httpd
- name: start/enable httpd
service: name=httpd state=started enabled=yes
ps: shell 和 command 模块后不需要跟键值对,直接写 shell 命令为参数
Playbook 中使用 handlers 和 notify
Handlers 本质是 task list,类似于 MYSQL中的触发器的出发行为,其中task 与前所述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个 play 的最后被触发,这样可以避免多次有改变发生时每次都执行的操作,仅当所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作被称为 handler ,也即 notify 中调用handler 中定义的操作。
---
- hosts: '220'
remote_user: root
gather_facts: no
tasks:
- name: INSTALL httpd
yum: name=httpd
- name: INSTALL configure file httpd.conf
copy: src=cile/httpd.conf dest=/etc/httpd/conf/
- name: INSTALL web htmls
copy: src=/data/html/ dest=/var/www/html/
notify: restart httpd
- name: ENSURE apache is running
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted
## 修改配置 文件后通知 restart httpd ;重启 httpd 服务
Playbook中变量的使用 【变量名只能是数字、字母、下划线;必须要以字母开头】
变量定义:
http_port=80
变量调用:
{{ variable_name }}调用变量,变量名前后建议加上空格,有时用上 "{{ variable_name }}" 才生效
变量来源:
1. ansible 的setup facts 远程之际的所有变量都可以直接调用 【在playbook 中使用,且不能在有 gather_facts=no 参数后使用】
---
# ansible_fqdn 模块使用
- hosts: '220'
remote_user: root
tasks:
- name: '创建空文件'
file: name=/data/{{ ansible_fqdn }}.log state=touch
- name: '写入内容'
copy: content='\t\t静夜思\n\t\t\t[李白]\n\t床前明月光,疑似地上霜。\n\t举头望明月,低头思故乡。\n' dest=/data/{{ ansible_fqdn }}.log
ps:添加 gather_facts=no ,不在主动收集被控主机的 setup facts,无法继续调用 setup facts 中的变量
2. 在 playbook 命令中定义变量
---
- hosts: '220'
remote_user: root
gather_facts: no
tasks:
- name: istall paskegs
yum: name={{ pkname }} state=present
ansible-playbook -e pkname=httpd e-install-test.yaml
3. 在playbook 中定义变量
---
- hosts: '220'
remote_user: root
gather_facts: no
vars:
- data: Of course,pikaqiu is pikaqiu.PiKaQiuKings is the king of PIKAQIUS.
tasks:
- name: shell test
shell: echo {{ data }} > /data/pikaqiukings.txt
4. 使用变量文件中变量
可以在一个独立的 playbook 文件中定义变量,在另一个 playbook 文件中应用变量文件中的变量,比 playbook 中定义的变量优先级更高
5. 在 /etc/ansible/hosts 中定义变量:
单个主机变量
[web]
192.168.162.128 fqdn=centos8.2-128
192.168.162.222 fqdn=centos8.2-222
192.168.162.220 fqdn=centos8.2-220
组变量:
[web:vars]
domain=njit.edu.pikaqiu.cn
ps:出现单个主机变量和组变量重名:
[web]
192.168.162.128 fqdn=centos8.2-128 domain=njit.edu.dingxu.cn
192.168.162.222 fqdn=centos8.2-222 domain=njit.edu.dingxu.cn
192.168.162.220 fqdn=centos8.2-220 domain=njit.edu.dingxu.cn
[web:vars]
domain=njit.edu.pikaqiu.cn
按照单个主机变量的值来处理
Template 模板: 【模板是一个文本文件,可以作为生成文件的模板,并且模板中还可以嵌套 jinja 语法】
jinha2 语法:
• 字符串: 使用单引号或双引号定义
• 数字: 整数、浮点数
• 列表: [item1,item2,.....]
• 元组: (item1,item2,.....)
• 字典: {k1:v1,k2:v2,.....}
• boolean: true,false
• 算术运算: +,-,*,/,//,%,**
• 比较操作: ==,!=,>,>=,<,<=
• 逻辑符号: and,or,not
• 流表达式: for,if,when
Playbook 简单示例:
1. 取单字典中 value
yaml:
---
- hosts: '220'
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
tasks:
- name: template test3
template: src="/data/ansible/yamls/template/nginx.conf2.j2" dest=/data/nginx.conf2-res
template:
{% for vhosts in nginx_vhosts %}
server{
listen {{ vhosts.listen }}
}
{% endfor %}
res:
server{
listen 8080
}
2. 循环取 list 值
yaml:
---
- hosts: '220'
remote_user: root
vars:
nginx_vhosts: [ 81,82,83 ]
tasks:
- name: telplate test
template: src="/data/ansible/yamls/template/nginx.conf.j2" dest=/data/template-test-res
template:
{% for vhost in nginx_vhosts %}
server{
listen {{ vhost }}
}
{% endfor %}
res:
server{
listen 81
}
server{
listen 82
}
server{
listen 83
}
3. 较复杂的字典列表:
yaml:
---
- hosts: '220'
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
server_name: "web1.mangedu.com"
root: "/var/www/nginx/web1"
- listen: 8081
server_name: "web2.mangedu.com"
root: "/var/www/nginx/web2"
- { listen: 8082, server_name: "web3.magedu.com", root: "/var/www/nginx/web3/" }
tasks:
- name: template test3
template: src="/data/ansible/yamls/template/nginx3.conf.j2" dest=/data/nginx3.conf-res
template:
{% for vhost in nginx_vhosts %}
server{
listen_port= {{ vhost.listen }}
server_name= {{ vhost.server_name }}
root_src= {{ vhost.root }}
}
{% endfor %}
res:
server{
listen_port= 8080
server_name= web1.mangedu.com
root_src= /var/www/nginx/web1
}
server{
listen_port= 8081
server_name= web2.mangedu.com
root_src= /var/www/nginx/web2
}
server{
listen_port= 8082
server_name= web3.magedu.com
root_src= /var/www/nginx/web3/
}
4. 条件判断 if 的使用
---
- hosts: '220'
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
root: "/var/www/nginx/web1"
- listen: 8081
server_name: "web2.mangedu.com"
root: "/var/www/nginx/web2"
- listen: 8082
hostname: 'pikaqiushishabi'
server_name: "web3.magedu.com"
root: "/var/www/nginx/web3/"
tasks:
- name: template test3
template: src="/data/ansible/yamls/template/nginx3.conf.j2" dest=/data/nginx3.conf-res
template:【位置可能不对齐,需要后期根据格式调整】
{% for vhost in nginx_vhosts %}
server{
listen_port= {{ vhost.listen }}
{% if vhost.server_name is defined %}server_name= {{ vhost.server_name }}
{% endif %}
root_src= {{ vhost.root }}
}
{% endfor %}
res:
server{
listen_port= 8080
root_src= /var/www/nginx/web1
}
server{
listen_port= 8081
server_name= web2.mangedu.com
root_src= /var/www/nginx/web2
}
server{
listen_port= 8082
server_name= web3.magedu.com
root_src= /var/www/nginx/web3/
}
5. 条件判断 when
---
- hosts: '220'
remote_user: root
tasks:
- name: "shutdown redhat flavored systems"
shell: /sbin/shudtdown -h now
when: aisible_os_family == "RedHat"
---
- hosts: all
remote_user: root
tasks:
- name: add group nginx
tags: group
group: name=nginx state=present
- name: add user nginx
tags: user
user: name=nginx state=present group=nginx
- name: install nginx
yum: name=nginx state=present
- name: start nginx
service: name=nginx state=started enabled=yes
when: ansible_distribution_major_version == "8" ## centos8 启动服务nginx,其他版本不启动
---
## 根据不同版本的 centos 上传不同版本的nginx 配置文件
- hosts: all
remote_user: root
tasks:
- name: install conf file of centos7
template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
- name: install conf file of centos8
template: src=nginx.conf.c8.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "8"
- name: install conf file of centos6
template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"
---
#根据centos fqdn 名称 来判断安装nginx 或者 httpd
- hosts: all
remote_user: root
tasks:
- name: install nginx centos-220
yum: name=nginx
when: ansible_fqdn == "centos8.2-220"
- name: start nginx
service: name=nginx state=started enabled=yes
when: ansible_fqdn == "centos8.2-220"
- name: instal httpd centos-222
yum: name=httpd
when: ansible_fqdn == "centos8.2-222"
- name: start httpd
service: name=httpd state=started enabled=yes
when: ansible_fqdn == "centos8.2-222"
6. with_items 迭代【当有需要重复执行的任务时,可以使用迭代机制】
对迭代的应用,固定变量名为 item ,要求 task 中使用 with_items 给定要迭代的元素列表 ; 列表元素的格式: 字符串 / 字典; 可以嵌套
---
- hosts: web
remote_user: root
tasks:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuesr2
##等同于下面的语句:
- name: add user1
uesr: name=testuser1 state=present groups=wheel
- name: add user2
user: name=testuser2 state=present groups=wheel
---
#remove mariadb server
- hosts: '220'
remote_user: root
tasks:
- name: stop service
shell: /etc/init.d/mysqld stop
- name: delete files and directory
file: path={{ item }} state=absent
with_items:
- /usr/local/mysql
- /usr/local/mariadb-10.2.27-linux-x86_64
- /etc/init.d/mysqld
- /etc/profile.d/mysql.sh
- /etc/my.cnf
- /data/mysql
- name: delete user
user: name=mysql state=absent remove=yes
---
- hosts: web
remote_user: root
tasks:
- name: install some packeges
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-rfm
---
- hosts: web
remote_user: root
tasks:
- name: copy file
copy: src={{ item }} dest=/tmp/{{ item }}
with_items:
- file1
- file2
- file3
- name: yum install httpd
yum: name={{ item }} state=present
with_items:
- apr
- apr-util
- httpd
迭代嵌套自变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用【使用 字典 作为迭代参数】
---
- hosts: web
remote_user: root
tasks:
- name: add some groups
group: name={{ item }} state=present
with_items:
- nginx
- mysql
- apache
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'nginx', group: 'nginx' }
- { name: 'mysql', group: 'mysql' }
- { name: 'apache',group: 'apache' }