一、基础介绍
1、简介
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
2、总体架构
3、特性
(1)、no agents:不需要在被管控主机上安装任何客户端;
(2)、no server:无服务器端,使用时直接运行命令即可;
(3)、modules in any languages:基于模块工作,可使用任意语言开发模块;
(4)、yaml,not code:使用yaml语言定制剧本playbook;
(5)、ssh by default:基于SSH工作;
(6)、strong multi-tier solution:可实现多级指挥。
4、优点
(1)、轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
(2)、批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
(3)、使用python编写,维护更简单,ruby语法过于复杂;
(4)、支持sudo。
5、任务执行流程
二、Ansible基础安装与配置
使用Ansible管理您的AWS资源,官方文档: https://www.freecodecamp.org/news/ansible-manage-aws/
2-1、yum源安装
配置epel 源后,可以直接通过yum 进行安装。
-
centos,默认在源里没有ansible,不过在 fedora epel源里有ansible:
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm
yum install ansible -
Amazon Linux,默认在源里没有ansible:
amazon-linux-extras install epel
yum -y install ansible
rpm -qa | grep ansible //查看是否已安装成功
2-2、pip安装
###如果pip您的系统上尚不可用,请运行以下命令进行安装:
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py --user
###使用pip安装最新版本的ansible
#一旦pip安装,您可以安装Ansible:
python -m pip install --user ansible
#为了使用需要的paramiko连接插件或模块paramiko,请安装所需的模块1:
python -m pip install --user paramiko
#如果要全局安装 Ansible,请运行以下命令:
sudo python get-pip.py
sudo python -m pip install ansible
#指定版本安装
sudo python -m pip install ansible-core==2.11.6
#卸载
sudo python -m pip uninstall ansible
2-3、Ubuntu 安装
配置 PPA 或者安装 Ansible:
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
2-4、源码安装
(1)、安装devtoolset
yum groupinstall "Development tools"
(2)、安装编译Python需要的包
yum install gcc zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel libffi-devel
(3)、python2.7安装
bash
wget https://www.python.org/ftp/python/2.7.14/Python-2.7.14.tgz
tar xvzf Python-2.7.14.tgz
cd Python-2.7.14
./configure
make && make altinstall(altinstall在安装时会区分已存在的版本)(解决libpython2.7.so.1.0办法:vi /etc/ld.so.conf 添加/usr/local/lib,然后ldconfig)
mv /usr/bin/python /usr/bin/python2.6.6
ln -s /usr/local/bin/python2.7 /usr/bin/python
## 将python头文件拷贝到标准目录,以避免编译ansible时,找不到所需的头文件
cd /usr/local/include/python2.7/
cp -a ./* /usr/include/
## 修改yum脚本,使其指向旧版本的python,已避免其无法运行
vim /usr/bin/yum
#!/usr/bin/python --> #!/usr/bin/python2.6.6
(4)、setuptools模块安装
bash
wget https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg --no-check-certificate
chmod +x setuptools-0.6c11-py2.7.egg
sh setuptools-0.6c11-py2.7.egg
(5)、pycrypto模块安装
bash
wget https://pypi.python.org/packages/source/p/pycrypto/pycrypto-2.6.1.tar.gz
tar zxvf pycrypto-2.6.1.tar.gz
cd pycrypto-2.6.1
python setup.py install
cd ..
(6)、PyYAML模块安装
bash
##安装libyaml
wget http://pyyaml.org/download/libyaml/yaml-0.1.5.tar.gz
tar zxvf yaml-0.1.5.tar.gz
cd yaml-0.1.5
./configure --prefix=/usr/local
make --jobs=`grep processor /proc/cpuinfo | wc -l`
make install
cd ..
##安装PyYAML
wget http://pyyaml.org/download/pyyaml/PyYAML-3.11.tar.gz
tar zxvf PyYAML-3.11.tar.gz
cd PyYAML-3.11
python setup.py install
cd ..
(7)、Jinja2模块安装
##安装MarkupSafe
wget https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-0.9.3.tar.gz
tar zxvf MarkupSafe-0.9.3.tar.gz
cd MarkupSafe-0.9.3
python setup.py install
cd ..
##安装Jinja
wget https://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.7.3.tar.gz
tar zxvf Jinja2-2.7.3.tar.gz
cd Jinja2-2.7.3
python setup.py install
cd ..
(8)、paramiko模块安装
##安装ecdsa
wget https://pypi.python.org/packages/source/e/ecdsa/ecdsa-0.11.tar.gz
tar xvzf ecdsa-0.11.tar.gz
cd ecdsa-0.11
python setup.py install
cd ..
##安装paramiko
wget https://pypi.python.org/packages/2b/27/b64860e7b208ff1dd36fe208d07bca1f9637a11fe733e2f2ceea587c3f75/paramiko-1.7.5.zip
unzip paramiko-1.7.5.zip
cd paramiko-1.7.5
python setup.py install
cd ..
(9)、simplejson模块安装
wget https://pypi.python.org/packages/08/48/c97b668d6da7d7bebe7ea1817a6f76394b0ec959cb04214ca833c34359df/simplejson-3.11.1.tar.gz
tar zxvf simplejson-3.11.1.tar.gz
cd simplejson-3.11.1
python setup.py install
cd ..(10)、ansible安装
wget https://github.com/ansible/ansible/archive/stable-2.3.zip
unzip stable-2.3.zip
cd ansible-stable-2.3/
python setup.py install
2、Ansible配置
配置用户名密码
(1)、使用examles包做为默认配置,具体如下:
mkdir -p /etc/ansible
cp -r examples/* /etc/ansible/
ls /etc/ansible/
ansible.cfg DOCUMENTATION.yml hosts hosts.yaml hosts.yml playbooks scripts
(2)、ansible配置
# mkdir -p /etc/ansible
# vim /etc/ansible/ansible.cfg
remote_port = 36000
[defaults]
# 跳过 ssh 首次连接提示验证部分。
host_key_checking = False
......
(3)、使用默认示例配置文件后,先备份文件,编辑/etc/ansible/hosts文件:
cp /etc/ansible/hosts /etc/ansible/hosts.bak
vim /etc/ansible/hosts
......
[all:children]
test
dev
[test]
#设置主机的默认连接用户,及密码
172.16.52.236 ansible_ssh_user=root ansible_ssh_pass=test
#设置ssh的连接方式,默认是openssh。官网推荐用openssh,因为paramiko查询key的时候,很耗时,效率不高。
172.16.52.226 ansible_connection=paramiko
[dev]
#给主机取个别名"qsh_test",如果ssh默认端口不是22,这里可以指定特定的端口
qsh_test ansible_ssh_host=172.16.52.100 ansible_ssh_port=21100
#指定ssh端口也可以像下面这么指定。
172.16.52.23[1:9]:22
---------------------------------------
注:
1、all这个组包含俩子组分别是下面的test,和dev
2、以上两种指定ssh端口方法,只针对我们有少部分的主机是特殊端口,配置文件里有个选项,改成我们需要的端口就OK了,修改后对全局有效
grep "remote_port" /etc/ansible/ansible.cfg remote_port = 22
3、172.16.52.236可以在不同的组中。在现实当中就像我一台服务器即可以装mysql也可以装apache是一个道理。
4、后面的用户和密码项是非必须的,在配置key认证的情况下,不使用密码也可以直接操作 。
未使用key的,也可以在ansible通过 -k参数在操作前询问手动输入密码。
(4)、列出目标组里的主机清单。
ansible <group_name>|host --list-host
ansible有两个默认组:
- all:包含每个主机;
- ungrouped:包含的主机仅属于all组且不属于其他任何组;
(5)、修改默认远程端口号
-
配置文件里有个选项,改成我们需要的端口就OK了,修改后对全局有效;
lixc@ansible:~$ grep "remote_port" /etc/ansible/ansible.cfg
remote_port = 2222 -
可在主机名之后加上端口号,用冒号分割;
(6)、匹配主机、主机组。
-
如果要添加大量格式类似的主机,不用列出每个主机名:在看一组相似的```
hostname或者ip,可简写如下:[webservers]
www[01:50].example.com
方括号[01:50]也可写为[1:50],表示从www1 到www50,webservers共有50台主机;
-
定义字母范围简写模式
[databases]
db-[a:f].example.com
表示从db-a到db-f,共6台主机;
-
如下写法分别表示一个或多个groups,多组之间以冒号分割表示或的关系;这意味着一个主机可以同时存在多个组;
webservers
webservers:databases -
排除一个特定组,如下示例中,所有执行命令的主机必须隶属webservers组但同时不在databases组中;
webservers:!databases
-
指定两个组的交集,如下实例中,所有执行命令的主机必须隶属webservers组和appservers组中;
webservers:&appservers
-
或者更复杂,如下实例中,webservers组和databases组中隶属于appservers组并且不属于test组的主机才执行命令;
webservers:databases:&appservers:!test
-
单个hostname、IP、groups都支持通配符,同时也支持通配和groups的混合使用;
*.example.com
.com
one.com:appservers -
也可以在groups中选择对应编号的server和一部分servers;
webservers[0] #匹配webservers组的第1个主机
webservers[0-25] #匹配webservers组的第1-26台主机 -
大多数人会使用正则表达式匹配,只需要以~开头即可;
~(web|db).*.example.com
-
也可以使用 --limit标记来添加排除条件,ansible 和 ansible-playbook都支持;
ansible-playbook nginx.yml --limit appserver02
-
通过文件读取hosts,文件名以@为前缀即可;
ansible-playbook nginx.yml --limit @limit.txt --list-host
(7)、通过以下方式验证ansible是否可用,有结果输出,证明安装成功。
ansible test -a 'uptime'
172.16.52.236 | SUCCESS | rc=0 >>
18:33:05 up 7 days, 8:07, 1 user, load average: 0.06, 0.05, 0.00
172.16.52.226 | SUCCESS | rc=0 >>
18:33:05 up 7 days, 8:08, 1 user, load average: 0.00, 0.00, 0.00
报错:"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n"
解决:
提示需要安装sshpass,安装sshpass,sshpass也是epel源提供的
[root@ansible~]# yum install -y sshpass
3、SSH免密钥登录设置
(1)、生成公钥/私钥
ssh-keygen -t rsa -P ''
写入信任文件(把本地的ssh公钥文件安装到远程主机对应的账户下):
ssh-copy-id -i ~/.ssh/id_rsa.pub <remote-host>
(2)、ansible配置
-
修改ansible配置文件
vim /etc/ansible/ansible.cfg
private_key_file = /root/.ssh/id_rsa_ansible
-
添加host文件
bash
# vim hosts
############################################################
[test]
<remote-host> ansible_ssh_port=22 ansible_ssh_private_key_file=/root/.ssh/id_rsa_ansible
(3)、简单测试
ansible test -m command -a 'uptime'
说明:第一次运行时,需要输入一下"yes"【进行公钥验证】,后续无需再次输入。
说说ansible的工作流程吧,工作流程差不多是这样的
-
ansible通过OPENSSH或者python的pramamiko连接客户端
-
把ansible module推送到客户端。推送到客户端哪里的呢,请看
[root@qsh_server ansible]# grep "remote_tmp" /etc/ansible/ansible.cfg
remote_tmp = $HOME/.ansible/tmp
[root@qsh_server ansible]# ansible test -a "ls ~/.ansible"
172.16.52.236 | SUCCESS | rc=0 >>
tmp
3.通过ssh执行客户端上的ansible module
4.执行完毕
5.删除刚刚推送过去的ansible module
4、常用模块使用
请查看:Ansible常用模块
5、一些概念补充
playbook的组成:playbook是由一个或多个"play"组成的列表,可以让它们联同起来按事先编排的机制执行;所谓task无非是调用ansible的一个module,而在模块参数中可以使用变量;模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致;
执行模型:task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在顺序运行某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在修改playbook后重新执行一次即可;
task组成:每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出;
notify指定handler的执行机制:"notify"这个action可用于在每个play的最后被触发,在notify中列出的操作称为handler,仅在所有的变化发生完成后一次性地执行指定操作。
错误小结
"module_stdout": "/bin/sh: 1: /usr/bin/python2.7: not found\r\n"
解决方法:
-
命令指定Python3
ansible-playbook --version -e 'ansible_python_interpreter=/usr/bin/python3'
-
host主机文件指定
vim /etc/ansible/hosts
127.0.0.1 ansible_python_interpreter=/usr/bin/python3
-
vars 指定环境变量
- name: Common package
hosts: all
gather_facts: no
vars:
ansible_python_interpreter: /usr/bin/python3
roles:- { role: python, tags: [ init, python, common, addusers] }
- name: Common package
[WARNING]: sftp transfer mechanism failed on [xx]. Use ANSIBLE_DEBUG=1 to see detailed information
解决方法:
一、修改sshd_config文件,取消注释Subsystem sftp /usr/lib/ssh/sftp-server
Subsystem sftp /usr/lib/ssh/sftp-server
当该行注释时,表示禁用sftp,需取消注释启用,修改配置后重启sshd服务
二、当sftp已启用时,报错仍然存在,修改ansible配置文件,添加scp_if_ssh=True
vi /etc/ansible/ansible.cfg
[ssh_connection]
scp_if_ssh=True
重新执行ansible,报错不存在了
一些学习资料
- http://lansgg.blog.51cto.com/5675165/1745040
- http://blog.xiaorui.cc/category/ansible/
- http://lixcto.blog.51cto.com/4834175/d-4
- https://github.com/ansible/ansible-examples
- http://rfyiamcool.blog.51cto.com/1030776/d-51
- http://dl528888.blog.51cto.com/2382721/d-4/p-1
- http://edu.51cto.com/course/course_id-2220.html
- http://edu.51cto.com/course/course_id-2032.html
- http://www.shencan.net/index.php/category/自动化运维/ansible/