ansible 基于python开发,实现了批量操作系统配置,批量程序部署,批量运行命令等功能
可以实现:自动化部署APP 管理配置项 持续交付 云服务管理
选择配置管理软件要考虑的问题
活跃度(社区) 学习成本 使用成本 编码语言 性能 使用是否广泛
优点:
只需要ssh和python,无客户端 ,容易,门槛低
ansible功能强大,模块丰富,社区活跃
基于python开发,做二次开发更容易
特性:
模块化设计,调用特定的模块完成特定任务
基于python语言实现 paramiko PyYAML(半结构化语言) Jinja2
模块支持JSON等标准输出格式,可以采用任何编程语言重写
部署简单,易于使用,支持多层部署和异构IT环境
支持自定义模块,palybook,主从模式工作
部署ansible
依赖关系python2.6或2.7
模块:paramiko PyYAML Jinja2 httplib2 six
对于被托管主机(ansible默认通过ssh协议管理机器,被管理主机要开启ssh服务,如果节点开启了SELinux。需要安装libselinux-python)
可以基于源码运行
源码安装
pip 需要配置扩展软件包源extras
git
yum -y install epel-release
yum -y install git python2-pip
pip安装依赖模块
pip install paramiko PyYAML Jinja2 httplib2 six
ansible源码下载
git clone git://github.com/ansible/ansible.git
yum install python-setuptools python-devel
python setup.py build
python setup.py install
pip方式安装
pip install ansible
yum安装
添加ansible到自定义软件源
[root@guo ansible]# ls
ansible-2.4.2.0-2.el7.noarch.rpm python-paramiko-2.1.1-4.el7.noarch.rpm
python2-jmespath-0.9.0-3.el7.noarch.rpm python-passlib-1.6.5-2.el7.noarch.rpm
python-httplib2-0.9.2-1.el7.noarch.rpm sshpass-1.06-2.el7.x86_64.rpm
[root@guo ansible]# createrepo --update .
安装ansible
虚拟机:2cpu 2G内存,大于20G硬盘 ip 192.168.1.10 ansible
[root@ansible ~]# vim /etc/yum.repos.d/local.repo
[server]
name=server
baseurl=ftp://192.168.1.254/CentOS7.4
gpgcheck=0
enabled=1
[ansible]
name=ansible
baseurl=ftp://192.168.1.254/ansible
gpgcheck=0
enabled=1
[root@ansible ~]# yum -y install ansible
验证
[root@ansible ~]# ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
管理主机
主机定义与分组
ansible配置文件查找顺序
检测ANSIBLE_CONFIG变量--- 当前目录下的./ansible.cfg文件 ---再次检查当前用户家目录下~/ansible.cfg 文件 ---最后检查/etc/ansible/ansible.cfg文件
ansible.cfg配置文件/etc/ansible/ansible.cfg
inventory 定义托管主机地址配置文件
先编辑/etc/ansible/hosts文件,写入远程主机的地址
[root@ansible ~]# vim /etc/ansible/ansible.cfg
14 #inventory = /etc/ansible/hosts //去掉注释,定义管理的主机位置
...
61 #host_key_checking = False //去掉注释
分组/etc/ansible/hosts
[root@ansible ~]# vim /etc/ansible/hosts
[web]
web[1:10]
[databases]
db1
db2
[other]
cache
查看组和主机(可以单独链接主机,链接组,可以链接组,主机 all所有组主机)
[root@ansible ~]# ansible web --list-hosts
hosts (2):
web1
web2
[root@ansible ~]# ansible web,cache --list-hosts
hosts (3):
web1
web2
cache
实验环境,部署虚拟机
192.168.1.11 web1 , 192.168.1.12 web2 , 192.168.1.21 db1 , 192.168.1.22 db1 , 192.168.133 cache
[root@ansible ~]# vim /etc/hosts
192.168.1.11 web1
192.168.1.12 web2
192.168.1.21 db1
192.168.1.22 db2
192.168.1.33 cache
ping主机
[root@ansible ~]# ansible cache -m ping -k //交互式输入密码
SSH password:
cache | SUCCESS => {
"changed": false,
"ping": "pong"
}
inventory参数
ansible_ssh_pass ssh密码(这种方式并不安全,我们强烈建议使用--ask-pass或SSH密钥)
ansible_sudo_pass sudo密码(建议使用--ask-sudo-pass)
ansible_sudo_exe(new in version 1.8) sudo命令路径(适用于1.8及以上版本)
ansible_connection 与主机的链接类型 如:local, ssh或paramiko, 1.2以前使用paramiko 1.2使用smart 它会根据是否支持ControlPersist来判断 'ssh'方式是否可行
ansible_ssh_private_key_file ssh ssh使用的私钥文件,适用于有多个密钥,而你不想使用SSH代理的情况
ansible_shell_type 目标系统的shell类型,默认情况下,命令的执行使用"sh"语法,可设置为‘csh’或‘fish’
ansible_python_interpreter 目标主机的python路径,适用情况:系统中多个python,或者命令路径不是"/usr/bin/python"
[root@ansible ~]# vim /etc/ansible/hosts
[other]
cache ansible_ssh_pass="123456"
[root@ansible ~]# ansible cache -m ping
cache | SUCCESS => {
"changed": false,
"ping": "pong"
}
分组定义共性和应用分组
[root@ansible ansible]# vim hosts
[web]
web1
web2
[web:vars] //web组:变量(vars不改),web组的多台机器共用一个用户名和密码
ansible_ssh_user="root"
ansible_ssh_pass="123456"
自定义配置文件
[root@ansible ~]# mkdir test
[root@ansible ~]# ls
bin test
[root@ansible ~]# cd test
[root@ansible test]# vim ansible.cfg
[defaults]
inventory = hosts
host_key_checking = False
[root@ansible test]# vim hosts
[app1]
web1
db1
[app2]
web2
db2
[other]
cache
[root@ansible test]# ansible app1,app2 --list //从当前目录读取数据
hosts (4):
web1
db1
web2
db2
动态主机
ansible inventory 包含静态inventory(在文件/etc/ansible/hosts中的主机和组和动态的inventory (通过外部脚本获取主机列表,按照要求格式返回给ansible命令)
json
注意事项:主机部分必须是列表格式
hostdata行,其中的“hosts”部分可以省略,但使用时必须为"hosts"
批量执行
ansible命令 ansible <host-pattern> [options]
host-pattern 主机或者定义的分组 | |||
-M 指定模块路径 | -m 使用模块,默认command模块 | -a or --args 模块参数 | -i inventory 文件路径或可执行脚本 |
-k 使用交互式登陆密码 | -e 定义变量 | -v 详细信息,-vvvv开启debug模式 |
[root@ansible test]# ansible all -m command -a 'uptime' -k //查看所有机器负载
SSH password:
web2 | SUCCESS | rc=0 >>
14:10:14 up 3:26, 2 users, load average: 0.00, 0.01, 0.05
db2 | SUCCESS | rc=0 >>
14:10:15 up 3:25, 2 users, load average: 0.00, 0.01, 0.05
web1 | SUCCESS | rc=0 >>
14:10:15 up 3:26, 3 users, load average: 0.00, 0.01, 0.05
db1 | SUCCESS | rc=0 >>
14:10:15 up 3:25, 2 users, load average: 0.00, 0.01, 0.05
cache | SUCCESS | rc=0 >>
14:10:15 up 3:25, 2 users, load average: 0.00, 0.01, 0.05
给多台主机公钥和私钥
[root@ansible ansible]# cd /root/.ssh/
[root@ansible .ssh]# ssh-keygen -t rsa -b 1024 -N ''
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:hWw1IEou73hE8hbIRNdlKFSv41uwBxqvEn2LssYrejI root@ansible
The key's randomart image is:
+---[RSA 1024]----+
| .o.+ooo+.o |
| o =..o= o . |
| = =. = . |
| * . o . |
| .* = S |
| .=.=.= |
| ...+o+.o |
|E *....+ |
|o*o=. . |
+----[SHA256]-----+
[root@ansible ansible]# ansible all -m authorized_key -a "user=root exclusive=true manage_dir=true key='$(< /root/.ssh/id_rsa.pub)'" -k -v
Using /etc/ansible/ansible.cfg as config file
SSH password:
web2 | SUCCESS => {
"changed": true,
...
[root@ansible ansible]# ansible all -m ping
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
ansible-doc和ping模块
ansible-doc 模块的手册相当于shell的man
[root@ansible ansible]# ansible-doc -l //列出所有模块
[root@ansible ansible]# ansible-doc 模块名 //查看帮助
ping模块没有参数 测试网络联通性
command模块 默认模块,远程执行命令
ansible host-pattern -m command -a ‘[args]’
注意事项:该模块通过-a跟上要执行的命令可以直接执行,有“<”,">","|","&"等字符则不能成功
该模块不启动shell直接在ssh进程中执行,所有用到shell的命令执行都会失败 ,如:
[root@ansible ansible]# ansible all -m command -a 'ps aux | grep ssh'
cache | FAILED | rc=1 >>
...
[root@ansible ansible]# ansible all -m command -a 'set'
db2 | FAILED | rc=2 >>
[Errno 2] 没有那个文件或目录
...
shell | raw 模块
shell模块 基本和command一样,不过,它是通过/bin/sh执行命令,可以执行bash的任意命令
raw模块 用法和shell一样,也可以执行任意命令,不过它没有chdir creates removes参数
[root@ansible ansible]# ansible all -m shell -a 'set'
db1 | SUCCESS | rc=0 >>
BASH=/bin/sh
在web1,db2上创建用户张三,默认密码为abc 第一次登录需要修改密码
[root@ansible ansible]# ansible web1,db2 -m shell -a 'useradd zhangsan'
[root@ansible ansible]# ansible web1,db2 -m shell -a 'echo abc | passwd --stdin zhangsan'
[root@ansible ansible]# ansible web1,db2 -m shell -a 'chage -d0 zhangsan'
script模块 可以执行脚本 不限于shell脚本
在web1和web2上创建用户lisi ,设置默认密码为123 要求 lisi不能和张三同时出现
[root@ansible ansible]# vim lisi.sh
#!/bin/bash
id 'zhangsan'
if [ $? -gt 0 ];then
useradd lisi
echo 123 | passwd --stdin lisi
fi
[root@ansible ansible]# ansible web1,web2 -m script -a 'lisi.sh'
wb1| SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to db2 closed.\r\n",
"stdout": "uid=1000(zhangsan) gid=1000(zhangsan) 组=1000(zhangsan)\r\n",
"stdout_lines": [
"uid=1000(zhangsan) gid=1000(zhangsan) 组=1000(zhangsan)"
]
}
wb2 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to db1 closed.\r\n",
"stdout": "id: zhangsan: no such user\r\n更改用户 lisi 的密码 。\r\npasswd:所有的身份验证令牌已经成功更新。\r\n",
"stdout_lines": [
"id: zhangsan: no such user",
"更改用户 lisi 的密码 。",
"passwd:所有的身份验证令牌已经成功更新。"
]
}
copy模块 复制文件到远程主机
src | 复制远程主机的文件到本地,绝对和相对均可,路径为目录时会递归复制。如果路径以/结尾,只复制目录里的内容,若不是/结尾,则复制包含目录在内的所有内容 |
dest | 远程主机的绝对路径,如源文件是一个目录,那该路径必须是目录 |
backup | 覆盖前先备份原文件,备份文件包含时间信息 |
force | 若目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,设为no,则只有当目标主机的目标位置不存在该文件时才复制。默认为yes |
[root@ansible ansible]# vim /etc/resolv.conf //将nameserver值改为114.114.114.114
[root@ansible ansible]# ansible all -m copy -a 'src=/etc/resolv.conf dest=/etc/resolv.conf'
[root@ansible ansible]# ansible all -m shell -a 'cat /etc/resolv.conf'
web1 | SUCCESS | rc=0 >>
; generated by /usr/sbin/dhclient-script
nameserver 114.114.114.114
search localdomain
...
lineinfile | replace模块
类似于sed的一种行编辑替换模块
path目的文件(要修改的文件)
regexp 正则表达式(匹配要修改的地方)
line 替换后的结果(最终修改后的样子) (replace模块--replace替换指定的字符 最终修改后的样子)
[root@ansible ansible]# ansible db1,db2 -m lineinfile -a 'path="/etc/my.cnf" regexp="^binlog_format" line="binlog_format = mixed"
> '
db2 | SUCCESS => {
"backup": "",
"changed": true,
"msg": "line replaced"
}
db1 | SUCCESS => {
"backup": "",
"changed": true,
"msg": "line replaced"
}
[root@ansible ansible]# ansible db1,db2 -m replace -a 'path="/etc/my.cnf" regexp="mixed" replace="statement"'
db2 | SUCCESS => {
"changed": true,
"msg": "1 replacements made"
}
db1 | SUCCESS => {
"changed": true,
"msg": "1 replacements made"
}
yum模块 使用yum包管理器来管理软件包
name 要进行操作的软件包(一个或多个)名字,也可传递一个url或一个本地的rpm包的路径
state 状态(present,absent,latest,installed,removed)
enablerepo 启用某个源
disablerepo 不启用某个源
service模块 管理服务
name 服务的名称,必选项
state 动作 started,stopped,restarted,reloaded
enabled 是否开机启动 yes|no
sleep 执行restarted 会在stop和start 之间沉睡几秒钟
案例:给所有web服务器安装apache 修改端口8080 设置开机自启动,设置默认主页为 hello world
[root@ansible ansible]# ansible web -m yum -a 'name="httpd"'
[root@ansible ansible]# ansible web -m copy -a 'src="index.html" dest="/var/www/html/"'
[root@ansible ansible]# ansible web -m lineinfile -a 'path="/etc/httpd/conf/httpd.conf" regexp="^Listen " line="Listen 8080"'
[root@ansible ansible]# ansible web -m service -a 'name="httpd" state=started enabled="yes"'
setup模块
获取主机信息,playbooks里经常会用的另一个参数gather_facts与该模块相关,setup模块经常用的是filter参数
filter过滤所需信息