ansiable学习笔记
介绍
Ansible 简单的说是一个配置管理系统(configuration management system)。你只需要可以使用 ssh 访问你的服务器或设备就行。它也不同于其他工具,因为它使用推送的方式,而不是像 puppet 等那样使用拉取安装agent的方式。你可以将代码部署到任意数量的服务器上。ansible可以帮助我们完成一些批量任务,或者完成一些需要经常重复的工作。
模块化:调用特定的模块,完成特定任务有Paramiko,PyYAML,Jinja2(模板语言)三个关键模块
- 支持自定义模块
- 基于Python语言实现
- 部署简单,基于python和SSH(默认已安装),agentless
- 安全,基于OpenSSH
- 支持playbook编排任务
- 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
- 无需代理不依赖PKI(无需ssl)
- 可使用任何编程语言写模块
- YAML格式,编排任务,支持丰富的数据结构
- 较强大的多层解决方案
安装
yum安装
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum -y install ansible
配置文件:/etc/ansible/ansible.cfg
主机清单:/etc/ansible/hosts
源码安装
下载
git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
复制ansible根目录中的examples目录下的ansible.cfg配置文件到/etc/ansible/目录下
cp examples/ansible.cfg /etc/ansible/
创建hosts文件
vim /etc/ansible/hosts
需要的python模块
sudo pip install paramiko PyYAML Jinja2 httplib2 six
启动
source ./hacking/env-setup
一旦运行env-setup脚本,就意味着Ansible从源码中运行起来了.默认的inventory文件是 /etc/ansible/hosts.inventory
$ echo "127.0.0.1" > ~/ansible_hosts
$ export ANSIBLE_HOSTS=~/ansible_hosts
SSH认证
在~/.ssh目录下生成钥id_rsa.pub(公钥)和id_rsa
ssh-keygen
将公钥发到被管节点的root用户下的.shh目录,生成authorized_keys
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.2.100
验证是否成功
ssh root@192.168.2.100
提示Failed to connect to the host via ssh
chown username: /home/username/.ssh
chown username: /home/username/.ssh/*
chmod 700 /home/username/.ssh
chmod 600 /home/username.ssh/*
目录结构
*配置文件或指令* | *描述* |
---|---|
/etc/ansible/ansible.cfg | 主配置文件,配置ansible工作特性 |
/etc/ansible/hosts | 主机清单 |
/etc/ansible/roles/ | 存放角色的目录 |
/usr/bin/ansible | 主程序,临时命令执行工具 |
/usr/bin/ansible-doc | 查看配置文档,模块功能查看工具 |
/usr/bin/ansible-galaxy | 下载/上传优秀代码或Roles模块的官网平台 |
/usr/bin/ansible-playbook | 定制自动化任务,编排剧本工具 |
/usr/bin/ansible-pull | 远程执行命令的工具 |
/usr/bin/ansible-vault | 文件加密工具 |
/usr/bin/ansible-console | 基于Console界面与用户交互的执行工具 |
配置文件
Ansible 配置文件/etc/ansible/ansible.cfg (一般保持默认)
[defaults]
inventory = /etc/ansible/hosts # 主机列表配置文件
library = /usr/share/my_modules/ # 库文件存放目录
remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录
local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录
forks = 5 # 默认并发数
sudo_user = root # 默认sudo 用户
ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
ask_pass = True #连接时提示输入ssh密码
remote_port = 22 #远程主机的默认端口,生产中这个端口应该会不同
log_path = /var/log/ansible.log #日志
host_key_checking = False # 检查对应服务器的host_key,建议取消注释。也就是不会弹出
Ansible必须通过Inventory 来管理主机(即/etc/anAnsible/hosts文件。)可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置。
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
ssh端口号.如果不是默认的端口号,通过此变量设置.这种可以使用 ip:端口 192.168.1.100:2222
ansible_ssh_user
默认的 ssh 用户名
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. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python 不是 2.X 版本的 Python.
我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
快速定义主机组
单台主机
green.example.com > FQDN192.168.100.10 > IP地址192.168.100.11:2222 > 非标准SSH端口
[webservers] > 定义了一个组名
alpha.example.org > 组内的单台主机192.168.100.10
[dbservers]
192.168.100.10 > 一台主机可以是不同的组,这台主机同时属于[webservers]
[group:children] > 组嵌套组,group为自定义的组名,children是关键字,固定语法,必须填写。
dns > group组内包含的其他组名
db > group组内包含的其他组名
[webservers]
www[001:006].hunk.tech > 有规律的名称列表,
这里表示相当于:
www001.hunk.tech
www002.hunk.tech
www003.hunk.tech
www004.hunk.tech
www005.hunk.tech
www006.hunk.tech
[databases]
db-[a:e].example.com > 定义字母范围的简写模式,
这里表示相当于:
db-a.example.com
db-b.example.com
db-c.example.com
db-d.example.com
db-e.example.com
以下这2条定义了一台主机的连接方式,而不是读取默认的配置设定
localhost ansible_connection=local
www.163.com ansible_connection=ssh ansible_ssh_user=hunk
最后还有一个隐藏的分组,那就是all,代表全部主机,这个是隐式的,不需要写出来的。
验证
ansible 10.128.50.53 -u root -m ping
返回
10.128.50.53 | success >> {
"changed": false,
"ping": "pong"
}
使用
测试命令
Anisble安装完成后(一般情况我们连ssh的免密登录一起做完,详见附录)我们会测试anisble是否可用。测试命令没有固定的格式,我们使用linux下hello world ,命令ping来测试是否可用。
指令成功和失败都会有不同的颜色反映出来且配合changed :false,changed :SUCCESS,可以让我们非常清晰的知道执行的结果。
绿色:执行成功并且不需要做改变的操作
×××:执行成功并且对目标主机做变更
红色:执行失败
可以在配置文件中定义
- highlight = white
- verbose = blue
- warn = bright purple
- error = red
- debug = dark gray
- deprecate = purple
- skip = cyan
- unreachable = red
- ok = green
- changed = yellow
- diff_add = green
- diff_remove = red
- diff_lines = cyan
命令执行过程
以 ansible db -m command -a 'ls -l /' -vvv
这条命令为例
1.加载自己的配置文件,默认/etc/ansible/ansible.cfg
Using /etc/ansible/ansible.cfg as config file
2.匹配主机清单
Parsed /etc/ansible/hosts inventory source with ini plugin
3.加载指令对应的模块文件,如command,生成.py的文件到本机的临时目录,这个目录就是在/etc/ansible/ansible.cfg定义的
Using module file /usr/lib/python2.7/site-packages/ansible/modules/commands/command.py
PUT /tmp/tmp4JvsLH TO /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py
4. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件,
这个目录就是在/etc/ansible/ansible.cfg定义的
( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861 `" ....)
sftp> put /tmp/tmp4JvsLH /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py\n'
5. 给文件+x 权限
'chmod u+x /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/ /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py && sleep 0'
6. 执行并返回结果
'/usr/bin/python /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py;
7. 删除临时py文件,sleep 0退出
rm -rf "/root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/" > /dev/null 2>&1 && sleep 0
8.断开远程主机连接
'Shared connection to 7-db-3.hunk.tech closed.\r\n')
高级话题Playbooks
playbook是ansible用于配置,部署,和管理被控节点的剧本。是由一个或多个play组成的列表,主要功能是将task定义好的角色归并为一组进行统一管理,也就是通过Ansible的模板将多个play组织在一个Playbook中运行。
Playbook可以理解为批处理任务,不过palybook有自己的语法格式,使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。比如安装nginx、mysql等服务。
yaml格式
playbook由YMAL语言编写。YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。
YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。
文件的第一行应该以 ”—” (三个连字符)开始,表明YMAL文件的开始。在同一行中,#之后的内容表示注释,类似于shell,python和ruby。YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
- apple - banana - orange等价于JSON的这种格式
[ “apple”, “banana”, “orange” ]
同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以”:”分隔表示,”:”后面还要增加一个空格。
house:
family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }
剧本以.yml后缀
如图所示:在mysql.yml中,主要由三个部分组成。
hosts部分:
使用hosts指示使用哪个主机或主机组来运行下面的tasks,每个playbook都必须指定hosts,hosts也可以使用通配符格式。主机或主机组在inventory清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行task的过程中。
remote_user:
指定远端主机中的哪个用户来登录远端系统,在远端系统执行task的用户,可以任意指定,也可以使用sudo,但是用户必须要有执行相应task的权限。
tasks:
指定远端主机将要执行的一系列动作。tasks的核心为ansible的模块,前面已经提到模块的用法。tasks包含name和要执行的模块,name是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。并且由不同颜色组成,便于识别。一般而言
绿色代表执行成功,系统保持原样
×××代表系统代表系统状态发生改变
红色代表执行失败,显示错误输出
Playbook的核心元素
· Playbook本身由以下各部分组成:
(1)Hosts:运行指定任务的目标主机;
(2)Tasks:任务,即调用模块完成的操作;
(3)Variables:变量;
(4)Templates:模板;
(5)Handles:处理器,当某条件满足时,触发执行的操作;
(6)Roles:角色
Play的主体是任务列表。任务列表中的任务依照次序逐个在hosts中指定的所有主机上执行,如果发生错误会将所有已执行任务回滚。
模块、模块参数格式
task的任务是按照指定的参数去执行模块。
(1)action:moudle options
(2)moudle:options,其中后者可以实现向后兼容。
注意:在Ansible自带模块中,command模块和shell模块只需要一个列表定义即可,无需使用key=value格式。
Handles和tags的使用
Handlers用于当关注的资源发生变化时所采取的操作。使用tags让用户选择跳过没有变化的代码,只运行Playbook中发生变化的部分代码。
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过“tags“打标签,通过 ansible-playbook命令 使用 --tags选项能实现仅运行指定的tasks。
- hosts: nginx
remote_user: root
tasks:
- name:yum install epel-release -y #安装epel源
yum: name=epel-release state=latest
- name: yum install nginx -y #安装nginx
yum: name=nginx state=latest
- name: copy nginx.conf #拷贝配置文件
copy: src=/opt/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
notify:
- reload #会触发handlers中名字为reload的任务
tags:
- reloadnginx
- name: start nginx #启动nginx服务
service: name=nginx state=started
tags:
- startnginx
handlers:
- name: reload #重载配置
service: name=nginx state=reloaded
执行:ansible-playbook nginx.yml
修改配置文件内容之后执行时调用标签ansible-playbook nginx.yml --tags= "reloadnginx",就会跳过安装步骤直接重载配置文件并启动服务。
variables:变量
(1) facts:可直接调用
注意:可使用setup模块直接获取目标主机的facters
ansible xxx -m setup
(2) 用户自定义变量:
通过命令行传递变量
ansible-playbook xxx.yml -extra-vars "host-www user-mageedu"
在playbook中定义变量的方法
vars:
- var1: value1
- var2: value2
(3)通过roles传递变量
(4)Host Inventory(主机清单)
Templates:模板文件以.j2后缀
Jinja是基于 Python的模板引擎。 Template类是 Jinja的另一个重要组件,可以看作是一个编译过的模板文件,用来产生目标文本,传递 Python的变量给模板去替换模板中的标记。
循环:迭代,即需要重复执行的任务。
(1)when 语句:只需要在task之后添加when语句即可。
vim /etc/ansible/when.yml
- hosts: nginx
remote_user: root
vars:
- username: user10
tasks:
- name: create {{username}} user
user: name={{username}}
when: ansible_fqdn=="promote.cache-dns.local"
执行:ansible-playbook when.yml 就会创建在nginx组的主机上
(2)迭代:直接将需要迭代的内容定义为item变量并进行引用,然后通过with_items语句来指明迭代的元素。
vim /etc/ansible/items.yml
- hosts: nginx
remote_user: root
tasks:
- name: install packages #安装with_items中列出的包
yum: name={{ item }} state=latest
with_items:
- php
- php-mysql
执行:ansible-playbook items.yml 就会安装列表中的包
角色列表: Roles
Ansible为了层次化、结构化地组织 Playbook,使用了角色( roles),可以根据层次结构自动装载变量文件、 tasks以及 handlers等。只需要在 Playbook中使用 include指令即可使用 roles。简单来讲, roles就是通过分别将变量、文件、任务、模块及处理器设置于单独的目录中,便捷地使用他们。
创建roles时的注意事项:
(1)目录名同角色名的定义
(2)目录结构有固定的格式:
files | 用来存放由copy模块或script模块调用的文件 |
---|---|
templates | 用来存放jinjia2模板 |
tasks | 至少有一个main.yml文件,定义各tasks |
handlers | 有一个main.yml文件,定义各handlers |
vars | 有一个main.yml文件,定义变量 |
default | 有一个main.yml文件,定义默认变量 |
meta | 有一个main.yml文件,定义此角色的特殊设定及其依赖关系 |
注意:在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、default和vars目录,用不到的目录可以创建为空目录,但不可以不创建。
示例
·、在roles目录下生成对应的目录结构
mkdir -pv /etc/ansible/roles/{httpd,mysql,php}/{files,templates,vars,tasks,handlers,meta,default}
2、在每个角色的handlers、tasks、meta、default、vars目录下创建main.yml文件,千万不能自定义
touch /etc/ansible/roles/{httpd,mysql,php}/{default,vars,tasks,meta,handlers}/main.yml
3、定义每个角色中tasks/main.yml的配置文件。
------编写httpd模块------
vim /etc/ansible/roles/httpd/tasks/main.yml
- name: ensure apache is at the latest version
yum: name={{item}} state=latest
with_items:
- httpd
- httpd-devel
- name: conf
template: src=/etc/ansible/roles/httpd/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
tags:
- httpdconf
notify:
- new conf to reload
tags:
- reload
- name: start service
service: name=httpd enabled=true state=started
-------编写mysql模块-------
vim /etc/ansible/roles/mysql/tasks/main.yml
- name: ensure mysql is at the latest version
yum: name={{item}} state=latest
with_items:
- mariadb
- mariadb-server
- mariadb-libs
- mariadb-devel
- name: start service
service: name=mariadb enabled=true state=started
-------编写php模块-----
vim /etc/ansible/roles/php/tasks/main.yml
- name: ensure php is at the latest version
yum: name={{item}} state=latest
with_items:
- php
- php-mysql
- php-gd
- php-ldap
- php-odbc
- php-pear
- php-xml
- php-xmlrpc
- php-mbstring
- php-snmp
- php-soap
- curl
- curl-devel
- php-bcmath
4、修改变量文件vars/main.yml
vim /etc/ansible/roles/httpd/vars/main.yml
http_port : 80 #添加变量
server_name : www.yun.com:80
5、定义handlers文件handlers/main.yml
vim /etc/ansible/roles/httpd/handlers/main.yml
- name: new conf to reload
service: name=httpd state=reloaded
6、定义/etc/ansible/lamp.yml的playbook文件
-----编写roles示例-----
vi /etc/ansible/lamp.yml
- hosts: lamp
remote_user: root
roles:
- httpd
- mysql
- php
7、执行lamp.yml的playbook文件
ansible-playbook lamp.yml
8、前往部署lamp的主机上编写php测试页,打开浏览器看网页是否正常。
vim /var/www/html/index.php
<?php
phpinfo();
?>
访问http://ip/index.php验证
常用命令
语法
ansible <host-pattern> [-m module_name] [options]
指令 匹配规则的主机清单 -m 模块名 选项
--version 显示版本
-a 模块参数(如果有)
-m module 指定模块,默认为command
-v 详细过程 –vv -vvv更详细
--list-hosts 显示主机列表,可简写--list
-k, --ask-pass 提示连接密码,默认Key验证
-K,--ask-become-pass 提示使用sudo密码
-C, --check 检查,并不执行
-T, --timeout=TIMEOUT 执行命令的超时时间,默认10s
-u, --user=REMOTE_USER 执行远程执行的用户
-U, SUDO_USER, --sudo-user 指定sudu用户
-b, --become 代替旧版的sudo 切换
ansible-doc: 显示模块帮助
ansible-doc [options] [module...]
-a 显示所有模块的文档-l, --list 列出可用模块-s, --snippet 显示指定模块的简要说明
命令
/usr/bin/ansible:Ansibe AD-Hoc 临时命令执行工具,常用于临时命的执行
/usr/bin/ansible-doc:Ansible 模块功能查看工具
/usr/bin/ansible-galaxy:下载/上传优秀代码或Roles模块 的官网平台,基于网络的
/usr/bin/ansible-playbook:Ansible 定制自动化的任务集编排工具
/usr/bin/ansible-pull:Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
/usr/bin/ansible-vault:Ansible 文件加密工具
/usr/bin/ansible-console:Ansible基于Linux Consoble界面可与用户交互的命令执行工具
Ansible-doc命令
查看 ansible-doc 的使用说明:
一般用法:
ansible-doc -l 获取所有模块信息
ansible-doc -s MOD_NAME 获取指定模块的使用帮助
ansible-doc
-h Usage: ansible-doc [options] [module...]
Options:
-h, --help show this help message and exit # 显示命令参数API文档
-l, --list List available modules #列出可用的模块
-M MODULE_PATH, --module-path=MODULE_PATH #指定模块的路径specify path(s) to module library (default=None)
-s, --snippet Show playbook snippet for specified module(s) #显示playbook制定模块的用法
--version show program's version number and exit # 显示ansible-doc的版本号查看模块列表:ion
ansible-doc -l
常用模块
模块 | 功能 |
---|---|
ping | 测试连通性 |
command | 命令行不能接收shell表达式 |
shell | 可以解析shell表达式、通配符等如管道 |
copy | 复制文件到远程主机,可以改权限等 |
file | file 设置文件属性 |
Fetch | fetch从远程某主机获取文件到本地 |
cron | cron 管理cron计划任务 |
group | 添加或删除组 |
user | 管理用户、获取用户信息 |
yum | 远程安装包 |
service | 管理服务 |
setup | 获取主机信息 |
script | 执行脚本 |
get_url | 下载指定文件存放到dest指定的目录 |