02 Ansible-Playbook 快速入门


Playbook 快速入门

Playbook 简介

  1. Playbooks是Ansible的配置,部署和编排语言。
  2. 他们可以描述您希望在远程机器做哪些事或者描述IT流程中一系列步骤。
  3. 使用易读的YAML格式组织Playbook文件。
  4. 如果Ansible模块是您工作中的工具,那么Playbook就是您的使用说明书,而您的主机资产文件就是您的原材料。
  5. 与adhoc任务执行模式相比,Playbooks使用ansible是一种完全不同的方式,并且功能特别强大。
1
2
# 官方文档:
https://docs.ansible.com/ansible/latest/user_guide/playbooks.html

简单示例

1
2
# 卸载掉之前安装的nginx
# [root@master ansible]# ansible web -m yum -a "name=nginx state=absent"
1
2
3
# 创建 playbook 目录
[root@master ansible]# mkdir -p /etc/ansible/playbook
[root@master ansible]# cd /etc/ansible/playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@master playbook]# vim install_nginx.yaml

- hosts: web
remote_user: root
# 不动态获取客户端属性信息 优化执行速度
gather_facts: false

# tasks定义任务
tasks:
- name: YUM安装Nginx最新版本
yum:
name=http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
state=latest
- name: 启动Nginx
systemd:
name=nginx
state=started
enabled=yes
1
2
3
# 测试执行
[root@master playbook]# ansible-playbook install_nginx.yaml -C
[root@master playbook]# ansible-playbook install_nginx.yaml

1
2
3
4
5
6
7
# 客户端验证
[root@localhost ~]# netstat -tnlp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1819/nginx: master
[root@localhost ~]# rpm -qa|grep nginx
nginx-1.16.1-1.el7.ngx.x86_64
[root@localhost ~]# nginx -v
nginx version: nginx/1.16.1

常用定义

主机和主机组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# work          普通用户
# become 提权
# become_user 提权到root用户

- hosts: web
remote_user: work
become: yes
become_user: root

# 命令行使用
# -k 输入用户密码
# -b 提权
# -k 输入提权密码
ansible-playbook nginx.yaml -u work -k -b -K

定义变量

  1. 变量是应用于多个主机的便捷方式
  2. 实际在主机执行之前,变量会对每个主机添加,然后在执行中引用。

命令行传递

1
2
3
4
5
6
7
8
9
# -e VAR=VALUE 传递参数

[root@master playbook]# ansible web -m debug -a "var=user_name" -e user_name=leo
10.0.0.202 | SUCCESS => {
"user_name": "leo"
}
10.0.0.203 | SUCCESS => {
"user_name": "leo"
}

主机变量与组变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 在Inventory中定义变量
[root@master playbook]# vim /etc/ansible/hosts
[web]
10.0.0.202 role=node1
10.0.0.203 role=node2

[web:vars] # web主机组变量
work=k8s

[all:vars] # 所有主机组变量
user=harrisli

[root@master playbook]# ansible web -m debug -a "var=role"
10.0.0.202 | SUCCESS => {
"role": "node1"
}
10.0.0.203 | SUCCESS => {
"role": "node2"
}

[root@master playbook]# ansible web -m debug -a "var=work"
10.0.0.202 | SUCCESS => {
"work": "k8s"
}
10.0.0.203 | SUCCESS => {
"work": "k8s"
}

[root@master playbook]# ansible all -m debug -a "var=user"
10.0.0.201 | SUCCESS => {
"user": "harrisli"
}
10.0.0.202 | SUCCESS => {
"user": "harrisli"
}
10.0.0.203 | SUCCESS => {
"user": "harrisli"
}

单文件存储变量

1
2
3
4
5
6
1. Ansible中的首选做法是不将变量存储在Inventory中。
2. 除了将变量直接存储在Inventory文件之外,主机和组变量还可以存储在相对于Inventory文件的单个文件中。
3. 组变量:
group_vars 存放的是组变量
group_vars/all.yml 表示所有主机有效,等同于[all:vars]
grous_vars/etcd.yml 表示etcd组主机有效,等同于[etcd:vars]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 所有主机有效
[root@master ansible]# mkdir -p /etc/ansible/group_vars
[root@master group_vars]# vim /etc/ansible/group_vars/all.yaml
user: Harrisli

[root@master group_vars]# ansible all -m debug -a "var=user"
10.0.0.203 | SUCCESS => {
"user": "Harrisli"
}
10.0.0.201 | SUCCESS => {
"user": "Harrisli"
}
10.0.0.202 | SUCCESS => {
"user": "Harrisli"
}
1
2
3
4
5
6
7
8
9
10
11
# 主机组有效,文件名要与主机组一致
[root@master group_vars]# vim /etc/ansible/group_vars/web.yaml
work: Kubernetes

[root@master group_vars]# ansible web -m debug -a "var=work"
10.0.0.202 | SUCCESS => {
"work": "Kubernetes"
}
10.0.0.203 | SUCCESS => {
"work": "Kubernetes"
}

在Playbook中定义

1
2
3
4
- hosts: web
vars:
http_port: 80
server_name: www.ctnrs.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@master playbook]# vim install_nginx.yaml 

- hosts: web
remote_user: root
# 不动态获取客户端属性信息 优化执行速度
gather_facts: false
# 变量引用
vars:
http_port: 80

# tasks定义任务
tasks:
# - name: YUM安装Nginx最新版本
# yum:
# name=http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
# state=latest
#
# - name: 启动Nginx
# systemd:
# name=nginx
# state=started
# enabled=yes

- debug:
var=http_port

[root@master playbook]# ansible-playbook install_nginx.yaml

Register变量

1
2
3
4
5
6
# 将命令的结果保存成一个变量

- shell: /usr/bin/uptime
register: result
- debug:
var: result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@master playbook]# vim install_nginx.yaml 

- hosts: web
remote_user: root
# 不动态获取客户端属性信息 优化执行速度
gather_facts: false
# 变量引用
vars:
http_port: 80

# tasks定义任务
tasks:
# - name: YUM安装Nginx最新版本
# yum:
# name=http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.16.1-1.el7.ngx.x86_64.rpm
# state=latest
#
# - name: 启动Nginx
# systemd:
# name=nginx
# state=started
# enabled=yes

- name: 测试playbook变量
debug:
var=http_port

- name: 测试register
shell: netstat -tnlp|grep 80
register: res
- debug: var=res # 返回一个字典
- debug: var=["stdout"] # 取出字典中的某个key的值
1
2
# 相当于将执行结果显示
[root@master playbook]# ansible-playbook install_nginx.yaml

任务列表

  1. 每个playbook包含一系列任务。这些任务按照顺序执行。
  2. 在playbook中,所有主机都会执行相同的任务指令。playbook目的是将选择的主机映射到任务。
1
2
3
4
5
6
7
8
9
[root@master playbook]# vim show.yaml

- hosts: web
gather_facts: false

tasks:
- name: 安装Tomcat
debug:
msg: "install tomcat"

语法检查与调试

1
2
3
# 测试运行,不实际操作:
# debug模块在执行期间打印语句,对于调试变量或表达式,而不必停止play。
# 与'when:'指令一起调试更佳。
1
2
3
4
5
6
7
8
9
10
11
12
[root@master playbook]# vim show.yaml

- hosts: web
gather_facts: false

tasks:
- name: 打印组名
debug:
msg: "{{group_names}}"
- name: 打印主机名
debug:
msg: "{{inventory_hostname}}"
1
[root@master playbook]# ansible-playbook -C show.yaml

任务控制

  1. 如果你有一个大的剧本,那么能够在不运行整个剧本的情况下运行特定部分。
  2. 使用tags标记
  3. 让程序按照阶段部署
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@master playbook]# vim show.yaml 

- hosts: web
gather_facts: false

tasks:
- name: 安装 Nginx
debug:
msg: "install Nginx start..."
tags: install_nginx

- name: 安装 Tomcat
debug:
msg: "install Tomcat start..."
tags: install_tomcat


# 单独执行 install_tomcat
[root@master playbook]# ansible-playbook -C show.yaml --tags install_tomcat

# 跳过 --skip-tags
[root@master playbook]# ansible-playbook -C show.yaml --skip-tags install_nginx

流程控制

条件 when

1
2
3
4
5
6
7
8
9
10
11
[root@master playbook]# vim when.yaml 

- hosts: web
gather_facts: false

tasks:
- name: 流程控制 条件
shell: echo 123
register: res
- debug: msg={{res}}
when: res.stdout == '123'

循环

  1. 常用循环语句

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master playbook]# vim create_file.yaml 

- hosts: web
gather_facts: false

tasks:
- name: 批量创建文件
file: path=/tmp/{{item}} state=touch
with_items:
- "1.txt"
- "2.txt"
- "3.txt"
tags: create
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master tmp]# touch {a,b,c}.html

[root@master playbook]# vim copy_file.yaml

- hosts: web
gather_facts: false

tasks:
- name: 批量复制文件
copy: src={{item}} dest=/tmp
with_fileglob:
- "/tmp/*.html"
tags: copy

模板 template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# template 调用jinjia模板 并copy文件
[root@master playbook]# mkdir config

[root@master config]# vim nginx.conf
# 也可有直接使用domain
{% set domain_name = domain %}
server {
listen: {{ http_port }};
server_name: {{ domain_name }};
location / {
root /usr/share/html;
}
}


[root@master playbook]# vim config_nginx.yaml

- hosts: web
remote_user: root
# 不动态获取客户端属性信息 优化执行速度
gather_facts: false
# 变量引用
vars:
http_port: 8080
domain: "www.teamshub.com"

tasks:
- name: 生成虚拟主机
template: src=config/nginx.conf dest=/tmp
tags: config_nginx

条件 和 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master config]# vim nginx.conf 

{% set domain_name = domain %}

upstream web{
# 拿到web组,循环得到web里所有的主机
{% for host in groups['web'] %}
# 取得每行配置的 hostname,如果是IP最好,如果是主机名需要取IP
server {{ hostvars[host].inventory_hostname }};
{% endfor %}
}

server {
listen: {{ http_port }};
server_name: {{ domain_name }};
location / {
root /usr/share/html;
}
}