编辑主机清单
$ vim /etc/ansible/hosts
直接在文件里面加IP地址。主机清单只是可以控制谁
ansible中有一个模块叫ping
$ ansible 10.10.108.91 -m ping -k
# -k 是手动输入密码
# -m 是执行模块
可以用都逗号分隔主机。如果有多个主机,密码只输入一次。
为了加速ssh连接,需要修改:
$ vim /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no
GSSAPICleanupCredentials no
查看ssh连接过程
$ ssh -v
主机清单可以分组。可以用ansible_password指定密码。使用密码需要安装yum install -y sshpass
[p9]
10.10.108.91 ansible_password=123456
10.10.108.93 ansible_password=123456
10.10.108.94 ansible_password=123456
[p7]
# 7[1:6]表示71到76
10.10.108.7[1:6] ansible_password=123456
不过上面加密码的方式不太安全
直接运行
$ ansible p9 -m ping
会出错,
10.10.108.93 | FAILED! => {
"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host."
}
10.10.108.94 | FAILED! => {
"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host."
}
解决方法:
$ vim /etc/ansible/ansible.cfg
# 取消注释下面一行:
#host_key_checking = False
# 在这个配置文件里面还有打开日志记录:
#log_path = /var/log/ansible.log
查看模块文档
$ ansible-doc ping
$ ansible-doc -l # 列出可用模块
命令解释
$ ansible <host-pattern> [-m module_name] [-a args]
--version
-v, -vv, -vvv, -vvvv 详细过程
-u 用户名
-k 手动输入密码
$ ansible all --list-hosts
$ ansible p9 --list-hosts # -list也行
直接执行命令 (command模块,默认模块,可以省略)
$ ansible p9 -u wang -k -m command -a'ls /root'
$ ansible p9 -a 'ls /root'
把对方的ssh公钥复制过来, 然后使用ansible就不用输入密码了
# 在控制端执行
$ ssh-copy-id 10.10.108.96
ansible
支持通配符
$ ansible 10.10.108.* -m ping
$ ansible 10.10.108.* -m ping
ansible的host-pattern: 匹配主机的列表
# all: 表示所有清单中的所有主机
$ ansible all -m ping
# *: 通配符
$ ansible '*' -m ping
$ ansible 192.168.1.* -m ping
$ ansible '*srvs' -m ping
# 或关系
$ ansible 'p9:p7' -m ping
# 交集
$ ansible 'p9:&p7' -m ping
# 逻辑非
$ ansible 'p9:!p7' -m ping
# 综合逻辑
$ ansible 'p9:&p7:!p7' -m ping
# 正则表达式
$ ansible '~表达式' -m ping
执行状态:
- 红色:错误
- 绿色:没有修改任何内容
- 蓝色:详细过程
- 黄色:执行成功,并对目标主机做了变更
常见模块
command
$ ansible-doc command
# 可以看到支持很多选项
- argv Passes the command as a list rather than a string.
- chdir Change into this directory before running the command.
- creates A filename or (since 2.0) glob pattern. If it already exists, this step won't be run.
- removes A filename or (since 2.0) glob pattern. If it already exists, this step will be run.
- stdin Set the stdin of the command directly to the specified value.
# 示例
$ ansible all -a 'removes=/etc/fs cat /etc/fstab'
command对重定向、管道、环境变量等都有问题,所以要用shell模块
shell
# 参数都放单引号里
$ ansible p9 -m shell -a 'echo $HOSTNAME'
script
运行脚本。在控制端写好脚本,不需要自己推送
$ vim /root/test.sh
#!/bin/bash
hostname # 查看主机名
$ ansible p9 -m script -a '/root/test.sh'
copy
从服务器复制文件到客户端
例子:查看selinux
状态,然后全部关闭
$ ansible all -a 'getenforce'
# 查看ansible文档
$ ansible-doc -s copy
dest:
(required) Remote absolute path where the file should be copied to. If `src' is a directory, this must be a directory too. If
`dest' is a non-existent path and if either `dest' ends with "/" or `src' is a directory, `dest' is created. If `dest' is a relative path, the starting directory is determined by the remote host. If `src' and `dest' are files, the parent directory of `dest' is not created and the task fails if it does not already exist.
backup:
Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.
# 复制一下本地selinux配置
$ cp /etc/selinux/config /root/selinux
# 发送到每一个客户端
$ ansible all -m copy -a 'src=/root/selinux dest=/etc/selinux/config backup=yes'
fetch
从客户端取文件到服务器。目录可以先tar再传
参数:
dest: 要存文件的目录,文件被放到目录/主机名/文件名
src: 源文件
$ ansible all -m fetch -a 'src=/var/log/message dest=/root/logs'
$ tree /root/logs
logs
|-- 10.10.108.71
| `-- var
| `-- log
| `-- messages
|-- 10.10.108.72
| `-- var
| `-- log
| `-- messages
|-- 10.10.108.73
| `-- var
| `-- log
| `-- messages
...
传输文件夹:先压缩再传
$ ansible all -m shell -a 'tar Jcf log.tar.xz /var/log/*.log'
# 有专门的压缩文件模块
$ ansible all -m fetch -a 'src=/root/log.tar.xz dest=/root/logs'
2、解压ansible管理机上的压缩文件到远程主机:
ansible all -m unarchive -a "src=/tmp/install/zabbix-3.0.4.tar.gz dest=/tmp/ mode=0755 copy=yes"
3、解压远程主机上的文件到目录:
ansible all -m unarchive -a "src=/tmp/install/zabbix-3.0.4.tar.gz dest=/tmp/ mode=0755 copy=no"
file
设置文件属性(创建文件夹等)
# 创建新文件
$ ansible all -m file -a 'name=/root/ANSIBLE_TEST state=touch'
# 删除文件或文件夹
$ ansible all -m file -a 'name=/root/ANSIBLE_TEST state=absent'
# 创建文件夹
$ ansible all -m file -a 'name=/root/FOLDER_TEST state=directory'
debug
---
- hosts: test70
remote_user: root
tasks:
- set_fact:
testvar: "testtest"
- debug:
msg: "{{testvar}}"
wait_for
检查端口是否打开/等待端口打开
等待文件出现等
参考资料:http://blog.timd.cn/ansible-wait-for/
- wait_for:
timeout: 5
connect_timeout: 5
port: 80
其他模块
hostname: 管理主机名
cron: 计划任务
yum: 管理包
service: 管理服务
user: 管理用户
group: 管理组
playbook
galaxy 模块库
https://galaxy.ansible.com/
模块下载
# https://galaxy.ansible.com/geerlingguy/nginx
$ ansible-galaxy install geerlingguy.nginx
ansible-pull
推送命令到客户端,效率提升
ansible-vault
脚本加密
# 新建一个yaml文件 first.yaml
- hosts: p9
remote_user: root
tasks:
- name: hello
command: hostname
$ ansible-playbook first.yaml
# 加密yaml文件可能有敏感信息
$ ansible-vault encrypt first.yaml
# 解密
$ ansible-vault decrypt first.yaml
# 查看加密的内容
$ ansible-vault view xxx
# 编译
$ ansible-vault edit xxx
# 修改密码
$ ansible-vault rekey xxx
# 创建加密的文件
$ ansible-vault create xxx
ansible-console
交互执行命令。用于临时测试
$ ansible-console
Welcome to the ansible console.
Type help or ? to list commands.
root@all (9)[f:5]$ cd p9 # 通过进文件夹的方式切换主机
root@p9 (3)[f:5]$
playbook
tasks 顺序执行的任务
- hosts: p9
remote_user: root
tasks:
- name: create new file
file: name=/home/temp_by_ykh state=touch
ignore_errors: True # 遇到错误继续(如果不加遇到错误就终止)
- name: install package
yum: name=ntp
ansible-playbook
常见选项
--check 只检测可能会发生的改变,但不真正执行操作
--list-hosts 列出运行任务的主机
--limit 主机列表 只针对主机列表的主机执行
--v 显示过程
示例:安装apache
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=present
- name: install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf
- name: start service
service: name=httpd state=started enabled=yes
handlers 指定任务的触发条件
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd
tags: inshttpd
- name: copy conf files
copy: src=files/httpd.conf dest=/etc/httpd/conf
notify: restart service # 如果命令执行了(文件变化了)就重启服务
- name: start service
service: name=httpd state=started enabled=yes
tags: rshttpd
notify:
- handler N # notify可以是列表,
- check nginx process
handlers:
- name: restart service
service: name=httpd state=started enabled=yes
- name: check nginx process
shell: killall -0 nginx > /tmp/nginx.log
tags 指定标签, 可以只执行标签
$ ansible -t rshttpd some.yaml
变量的指定
- ansible setup facts 远程主机的所有变量都可以直接调用
ansible XXX -m setup 查看ansible的参数(变量),里面也有系统变量
比如ansible_eth* 关于网卡的参数
- 在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组所有主机统一定义变量
[websrvs]
92.168.30.101 http_port=81
192.168.30.102 http_port=82
[dbsrvs]
92.168.30.101
192.168.30.103
[appsrvs]
192.168.30.10[1:3]
-
通过命令行指定变量,优先级最高
-
在playbook中定义:
- hosts: appsrvs
remote_user: root
vars:
- pkname: vsftpd
- key: value
tasks:
- name: install package
yum: name={{ pkname }}
- name: start service
service: name= {{ pkname }} state=started enabled=yes
$ ansible-playbook -e 'pkname=vsftpd' test.yaml # 覆盖脚本中的变量
- 可以单独创建变量文件,例如放在~/ansible/vars.yml文件中
var1: httpd
var2: vsftpd
创建一个Playbook,还在上面的目录中。
- hosts: websrvs
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ var1 }}
- name: create file
file: name=/data/{{ var2 }}.log state=touch
然后ansible-playbook -C 上面的.yaml
模板
文本文件,嵌套有脚本(使用模板编程语言编写)
Jinja2语言,使用字面量,有下面的形式
- 字符串:使用单引号或双引号
- 数字:整数,浮点数
- 列表:[item1, item2]
- 元组:(item1, item2)
- 字典:{key1:value1, key2:value2}
- 布尔型:true/false
算术运算:+ - * / // % **
比较操作:== != > >= < <=
逻辑比较:and or not
流表达式:for if when
一般在playbook脚本的同级目录中新建templates文件夹
示例:将nginx.conf作为模板
$ cp /etc/nginx/nginx.conf templates/nginx.conf.j2
$ vim !$
worker_processes {{ ansible_processor_vcpus*2 }} # 修改这一行
# 创建Playbook
$ vim run.yml
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy template
# 自动前往templates目录查找,也可以用绝对路径。跟复制模块的语法类似。
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
- name: start service
service: name=nginx state=started enables=yes
handlers:
- name: restart service
service: name=nginx state=restarted enables=yes
when关键字
条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提,要用条件测试,通过when语句实现,在tasks中使用,jinja2的语法格式。
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy template
template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
notify: restart service
- name: copy template
template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"
notify: restart service
- name: start service
service: name=nginx state=started enables=yes
handlers:
- name: restart service
service: name=nginx state=restarted enables=yes
with_items
迭代
示例:创建多个文件,安装多个yum包
- hosts: websrvs
remote_user: root
tasks:
- name: create some files
# item是特殊变量,就是下面的列表项
file: name=/data/{{ item }} state=touch
with_items:
- file1
- file2
- file3
- name: install some packages
yum: name={{ item }}
with_items:
- htop
- dstat
- hping3
嵌套子变量
- hosts: websrvs
remote_user: root
tasks:
- name: create some users
user: name={{ item.name }} group={{ item.group }}
with_items:
- { name: 'user1', group: 'g1' }
- { name: 'user2', group: 'g2' }
for & if in template
for示例
- hosts: websrvs
vars:
ports:
- 80
- 81
- 83
key2:
- p: 1
k: 1
- p: 2
k: 2
- 模板文件 xxx.j2
{% for port in ports %}
server {
listen {{ port }}
}
{% endfor %}
- 模板文件 yyy.j2
{% for key in key2 %}
server {
listen {{ key.p }}
}
{% endfor %}
if示例
{% if xxx is defined %}
{% endif %}
roles
ansible子1.2版本开始引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次性结构自动装载所有变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include他们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以用于构建守护进程等场景中。
推荐把roles放到:/etc/ansible/roles
mkdir还可以用大括号表示集合 mkdir a/{1,2,3}
示例
/roles/nginx/tasks/create-group.yml
- name: create group
group: name=nginx
/roles/nginx/tasks/create-user.yml
- name: create user
user: name=nginx group=nginx system=yes shell=/sbin/nologin
/roles/nginx/tasks/install-nginx.yml
- name: install package
yum: name=nginx
/roles/nginx/template/nginx.conf.j2
同上
/roles/nginx/tasks/main.yml
- include: create-group.yml
- include: create-user.yml
- include: install-nginx.yml
# # 可以引用其它的roles, 但是复制文件可能有路径问题
- include: roles/project2/tasks/copyfile.yml
/nginx_role.yml
- hosts: websrvs
remote_user: root
roles:
- role: nginx # 从roles目录下查找
- {role: httpd, tags: ['web', 'httpd'] }
- role: app
tags: ['web', 'app']
when: ansible_distrubtion_major_version == "7"
可以用ansible-playbook -t
选择标签