为ansible定义了管理主机的策略。
一般小型环境下我们只需要在host文件中写入主机的ip地址即可。
但是当中大型环境下,我们可能需要使用静态inventory
或者动态主机清单
来生成我们需要执行的目标主机。
默认路径为/etc/ansible/hosts
Ansible Inventory
文件是一个纯文本文件,用于定义 Ansible 执行命令的目标主机和组,以及这些主机和组的变量和属性。
主机:一个主机就是目标机器,可以是 IP 地址、域名或在 SSH 配置中定义的别名,也可以使用 ansible_host
指定。
组:可以将多个主机划分到同一个组中,并可以对组进行操作。
#示例
[ServerA]
192.168.x.xx http_port=80 https_port=443
[ServerB]
serverb.example.com ansible_user=admin ansible_password=1234
vars 关键字
设置变量,可以在组间共享变量#示例
#所有主机指定 `ansible_ssh_user` 变量,这意味着每个主机都具有该变量。
#为每个主机定义唯一的 `name` 变量。
[WebServer]
192.168.1.10 name=webserver1
192.168.1.11 name=webserver2
192.168.1.12 name=webserver3
[DatabaseServer]
192.168.1.20 name=dbserver1
192.168.1.21 name=dbserver2
[all:vars]
ansible_ssh_user=centos
:children 关键字
。#示例
#将 `WebServer` 和 `DatabaseServer` 组嵌套到 `Production` 组中。
[WebServer]
192.168.1.10
192.168.1.11
192.168.1.12
[DatabaseServer]
192.168.1.20
[Production:children]
WebServer
DatabaseServer
Alias(别名)
来引用 Inventory 中的主机。#为 `WebServer` 和 `DatabaseServer` 组定义别名,并将它们作为两个分离的组 `Web` 和 `Db` 的成员
#创建了一个名为 `Production` 的组,该组由这两个组的别名组成。
[WebServer]
192.168.1.10
192.168.1.11
192.168.1.12
[DatabaseServer]
192.168.1.20
[Web:children]
WebServer
[Db:children]
DatabaseServer
[Production]
@Web
@Db
在 hosts 文件
中为主机或组定义变量,在 playbook
中可以直接调用变量。
变量名 | 含义 |
---|---|
ansible_host |
ansible连接节点时的IP地址 |
ansible_port |
连接对方的端口号,ssh连接时默认为22 |
ansible_user |
连接对方主机时使用的用户名。不指定时,将使用执行ansible或ansible-playbook命令的用户 |
ansible_password |
连接时的用户的ssh密码,仅在未使用密钥对验证的情况下有效 |
ansible_ssh_private_key_file |
指定密钥认证ssh连接时的私钥文件 |
ansible_ssh_common_args |
提供给ssh、sftp、scp命令的额外参数 |
ansible_become |
允许进行权限提升 |
ansible_become_method |
指定提升权限的方式,例如可使用sudo/su/runas等方式 |
ansible_become_user |
提升为哪个用户的权限,默认提升为root |
ansible_become_password |
提升为指定用户权限时的密码 |
playbook 是由一个或多个play组成的列表
play的主要功能在于将直线归并为一组的主机装扮实现通过ansible
中的task
定义好的角色。
从根本来讲,所谓的task无非是调用ansible
的一个module
。
将多个play组织在一个playbook
内,即可以让它们联动起来按实现编排的机制唱一台大戏
playbook采用YAML语言编写
xxx.yaml/xxx.yml
--- #表示开始
- name: #指定play的名称
hosts: #指定主机清单中定义的主机组名
remote_user: #指定远程主机的执行用户
grather_facts: ture|fales #指定是否要收集远程主机的facts信息
vars: #自定义变量,只能在当前play有效
- 变量1: 值1 #格式为key: value
- 变量2: 值2
tasks: #定义任务列表,默认从上往下依次执行
- name: #定义任务的名称
模块名: 模块参数
ignore errors: true #忽略任务的失败
- name: #可以定义多个任务
模块名: 模块参数
notify: 任务名 #如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
##条件判断##
- name:
模块名: 模块参数
when: #定义条件表达式(== != > < >= <=),条件成立时执行此task任务,否则不执行任务
##循环##
- name:
模块名: 模块参数={{item}}
with_items: #定义循环列表
##tags模块,标签##
- name:
模块名: 模块参数
tags:
- 标签1
- 标签2
handlers:
- name: 任务名 #和notify中的任务名相同
模块名: 模块参数
#无注释版
---
- name:
hosts:
remote_user:
grather_facts: ture|fales
vars:
- 变量1: 值1
- 变量2: 值2
tasks:
- name:
模块名: 模块参数
ignore errors: true
- name:
模块名:
notify: 任务名
- name:
模块名:
when:
- name:
模块名: 模块参数={{item}}
with_items:
handlers:
- name: 任务名
模块名: 模块参数
Ansible
在执行完某个任务之后并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完后再去执行handler。
这样的好处是可以多次触发notify,但最后只执行一次对应的handler
,从而避免多次重启。
横向写法一般是数组类型
纵向写法一般是
task任务的模块语法格式
横向格式:
模块名: 参数1=值 参数2={{变量名}} ...
纵向格式:
模块名:
参数1: 值
参数2: "{{变量名}}"
...
with_items 和 vars 的语法格式
横向格式:
with_items: ["值1", "值2", "值3", ...]
值为对象(键值对字段)时:
with_items:
- {key1: "值1", key2: "值2"}
- {key1: "值3", key2: "值4"}
...
纵向格式:
with_items:
- 值1
- 值2
- 值3
...
值为对象(键值对字段)时:
with_items:
- key1: "值1"
key2: "值2"
- key1: "值3"
key2: "值4"
...
vim /etc/ansible/hosts
/etc/ansible
#编写yaml文件,安装nginx的剧本
vim test.yaml
---
- name: first play
hosts: webservers #指定执行脚本的目标
remote_user: root
gather_facts: false
tasks:
- name: firewalld
service: name=firewalld state=stopped enabled=no
- name: selinux
command: '/usr/sbin/setenforce 0 '
ignore_errors: true
- name: mount
mount: src=/dev/sr0 path=/mnt state=mounted fstype=iso9660
- name: nginx.repo file
copy: src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/nginx.repo #需要提前准备好源
- name: epel.repo
copy: src=/etc/yum.repos.d/epel.repo dest=/etc/yum.repos.d/
- name: nginx install
yum: name=nginx state=latest
- name: configuration file
copy: src=/opt/nginx.conf dest=/etc/nginx/nginx.conf #需要提前准备好配置文件
notify: "reload nginx"
- name: start nginx
service: name=nginx state=started enabled=yes
handlers:
- name: reload nginx
service: name=nginx state=reloaded
ansible-playbook test.yaml
systemctl status firewalld
getenforce
systemctl status nginx
#执行playbook
ansible-playbook xx.yaml/yml [参数]
常用参数 | 描述 | 使用场景 |
---|---|---|
–syntax-check | 检查yaml文件的语法是否正确 | |
–list-task | 检查tasks任务 | |
–list-hosts | 检查生效的主机 | |
–start-at-task=’ name ’ | 指定从某个task开始运行 | 一般用于剧本较长且不想从头重复执行的场景 |
-k | 用来交互输入ssh密码 | -ask-pass |
-K | 用来交互输入sudo密码 | -ask-become-pass |
-u | 指定用户 |
#检查yaml文件的语法是否正确
ansible-playbook test.yaml --syntax-check
#检查tasks任务
ansible-playbook test.yaml --list-task
#检查生效的主机
ansible-playbook test.yaml --list-hosts
#指定从 nginx install 开始运行
ansible-playbook test.yaml --start-at-task='nginx install'
vars: #自定义变量,只能在当前play有效
- 变量1: 值1 #格式为key: value
- 变量2: 值2
tasks: #在任务列表中引用变量
-name:
module: {{变量1}}
vim test2.yml
---
- name: second play
hosts: webservers
remote_user: root
gather_facts: true
vars:
- groupname: mysql
- username: nginx
tasks:
- name: create group
group: name={{groupname}} system=yes gid=306 #使用 {{key}} 引用变量的值
- name: create user
user: name={{username}} uid=306 group={{groupname}}
- name: copy file
copy: content="{{ansible_default_ipv4.network}}" dest=/opt/vars.txt #在setup模块中可以获取facts变量信息
#ansible_default_ipv4为facts变量信息中的字段
#ansible_default_ipv4.network中的 .network表示只提取信息中network部分
ansible-play test2.yml
ansible-playbook test1.yml -e "username=nginx"
#通过 -e 参数传递一个额外的变量 "username=nginx" 给 playbook
#playbook 将会使用变量 "username" 的值设置为 "nginx"
使用-k
和-K
参数实现。
vim test3.yml
---
- hosts: webservers
remote_user: test
become: yes #2.6版本以后的参数,之前是sudo,意思为切换用户运行
become_user: root #指定sudo用户为root
tasks:
- name: ts
command: ls ./
#执行playbook,加上参数-k和-K
ansible-playbook test3.yml -k -K
在Ansible中,提供的唯一一个通用的条件判断是when指令
。
当when指令的值为true时,则该任务执行,否则不执行该任务。
When指令一个比较常见的应用场景是实现跳过某个主机不执行任务 或者 只有满足条件的主机执行任务。
vim test4.yaml
---
- name: secend play
hosts: all
remote_user: root
vars:
- dirname: /var/www/html
tasks:
- name: create dir
file: path={{dirname}} state=directory
when: ansible_default_ipv4.address == "192.168.67.101"
#when指令中的变量名不需要手动加上 {{}}
或
when: inventory_hostname == "<主机名>"
ansible-playbook test4.yaml
Ansible提供了很多种循环结构,一般都命名为with_items
,作用等同于 loop 循环
。
#循环创建文件
vim test5.yaml
---
- name: diedai play
hosts: dbservers
remote_user: root
tasks:
- name: create file
file: path={{item}} state=touch
with_items: ["/opt/a", "/opt/b", "/opt/c", "/opt/d"]
ansible-playbook test5.yml
#循环创建目录与文件
vim test6.yml
---
- name: diedai play
hosts: webservers
remote_user: root
vars:
- myfiles: ["/opt/a", "/opt/b", "/opt/c", "/opt/d"]
- mydirs:
- /opt/aaa
- /opt/bbb
- /opt/ccc
- /opt/ddd
tasks:
- name: create file
file: path={{item}} state=touch
with_items: "{{myfiles}}"
- name: create dir
file: path={{item}} state=directory
with_items: "{{mydirs}}"
ansible-playbook test6.yml