ansible使用记录
Ansible 安装教程
ansible 的安装轻而易举,许多发行版的第三方软件仓库中都有现成的软件包,可以直接安装。其他简单的安装方法包括使用 pip 安装它,或者从 github 里获取最新的版本。若想使用你的软件包管理器安装,在基于 RHEL/CentOS Linux 的系统里你很可能需要 EPEL 仓库。
在基于 RHEL/CentOS Linux 的系统中安装 ansible
输入如下 yum 命令:
1 | $ sudo yum install ansible |
在基于 Debian/Ubuntu Linux 的系统中安装 ansible
输入如下 apt-get 命令:
1 | $ sudo apt-get install software-properties-common$ sudo apt-add-repository ppa:ansible/ansible$ sudo apt-get update$ sudo apt-get install ansible |
使用 pip 安装 ansible
pip 命令是一个安装和管理 Python 软件包的工具,比如它能管理 Python Package Index 中的那些软件包。如下方式在 Linux 和类 Unix 系统中通用:
1 | $ sudo pip install ansible |
从源代码安装最新版本的 ansible
你可以通过如下命令从 github 中安装最新版本:
1 | $ cd ~$ git clone git://github.com/ansible/ansible.git$ cd ./ansible$ source ./hacking/env-setup |
当你从一个 git checkout 中运行 ansible 的时候,请记住你每次用它之前都需要设置你的环境,或者你可以把这个设置过程加入你的 bash rc 文件中:
1 | # 加入 BASH RC$ echo "export ANSIBLE_HOSTS=~/ansible_hosts" >> ~/.bashrc$ echo "source ~/ansible/hacking/env-setup" >> ~/.bashrc |
ansible 的 hosts 文件包括了一系列它能操作的主机。默认情况下 ansible 通过路径 /etc/ansible/hosts 查找 hosts 文件,不过这个行为也是可以更改的,这样当你想操作不止一个 ansible 或者针对不同的数据中心的不同客户操作的时候也是很方便的。你可以通过命令行参数 -i 指定 hosts 文件:
1 | $ ansible all -m shell -a "hostname" --ask-pass -i /etc/some/other/dir/ansible_hosts |
不过我更倾向于使用一个环境变量,这可以在你想要通过 source 一个不同的文件来切换工作目标的时候起到作用。这里的环境变量是 $ANSIBLE_HOSTS,可以这样设置:
1 | $ export ANSIBLE_HOSTS=~/ansible_hosts |
一旦所有需要的组件都已经安装完毕,而且你也准备好了你的 hosts 文件,你就可以来试一试它了。为了快速测试,这里我把 127.0.0.1 写到了 ansible 的 hosts 文件里:
1 | $ echo "127.0.0.1" > ~/ansible_hosts |
现在来测试一个简单的 ping:
1 | $ ansible all -m ping |
或者提示 ssh 密码:
1 | $ ansible all -m ping --ask-pass |
我在刚开始的设置中遇到过几次问题,因此这里强烈推荐为 ansible 设置 SSH 公钥认证。不过在刚刚的测试中我们使用了 –ask-pass,在一些机器上你会需要安装 sshpass 或者像这样指定 -c paramiko:
1 | $ ansible all -m ping --ask-pass -c paramiko |
当然你也可以安装 sshpass,然而 sshpass 并不总是在标准的仓库中提供,因此 paramiko 可能更为简单。
设置 SSH 公钥认证
于是我们有了一份配置,以及一些基础的其他东西。现在让我们来做一些实用的事情。ansible 的强大很大程度上体现在 playbooks 上,后者基本上就是一些写好的 ansible 脚本(大部分来说),不过在制作一个 playbook 之前,我们将先从一些一句话脚本开始。现在让我们创建和配置 SSH 公钥认证,以便省去 -c 和 –ask-pass 选项:
1 | $ ssh-keygen -t rsa |
现在显然有很多种方式来把它放到远程主机上应该的位置。不过既然我们正在使用 ansible,就用它来完成这个操作吧:
1 | $ ansible all -m copy -a "src=/home/xxx/.ssh/id_rsa.pub dest=/tmp/id_rsa.pub" --ask-pass -c paramiko |
下一步,把公钥文件添加到远程服务器里。输入:
1 | $ ansible all -m shell -a "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys" --ask-pass -c paramiko |
样例输出:
1 | SSH password:127.0.0.1 | FAILED | rc=1 >>/bin/sh: /root/.ssh/authorized_keys: Permission denied |
矮油,我们需要用 root 来执行这个命令,所以还是加上一个 -u 参数吧:
1 | $ ansible all -m shell -a "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys" --ask-pass -c paramiko -u root |
样例输出:
1 | SSH password:127.0.0.1 | success | rc=0 >> |
请注意,我刚才这是想要演示通过 ansible 来传输文件的操作。事实上 ansible 有一个更加方便的内置 SSH 密钥管理支持:
1 | $ ansible all -m authorized_key -a "user=xxx key='{{ lookup('file', '/home/xxx/.ssh/id_rsa.pub') }}' path=/home/xxx/.ssh/authorized_keys manage_dir=no" --ask-pass -c paramiko |
现在这些密钥已经设置好了。我们来试着随便跑一个命令,比如 hostname,希望我们不会被提示要输入密码
1 | $ ansible all -m shell -a "hostname" -u root |
样例输出:
1 | 127.0.0.1 | success | rc=0 >> |
成功!!!现在我们可以用 root 来执行命令,并且不会被输入密码的提示干扰了。我们现在可以轻易地配置任何在 ansible hosts 文件中的主机了。让我们把 /tmp 中的公钥文件删除:
1 | $ ansible all -m file -a "dest=/tmp/id_rsa.pub state=absent" -u root |
样例输出:
1 | 127.0.0.1 | success >> { "changed": true, "path": "/tmp/id_rsa.pub", "state": "absent"} |
下面我们来做一些更复杂的事情,我要确定一些软件包已经安装了,并且已经是最新的版本:
1 | $ ansible all -m zypper -a "name=apache2 state=latest" -u root |
样例输出:
1 | 127.0.0.1 | success >> { "changed": false, "name": "apache2", "state": "latest"} |
很好,我们刚才放在 /tmp 中的公钥文件已经消失了,而且我们已经安装好了最新版的 apache。下面我们来看看前面命令中的 -m zypper,一个让 ansible 非常灵活,并且给了 playbooks 更多能力的功能。如果你不使用 openSuse 或者 Suse enterprise 你可能还不熟悉 zypper, 它基本上就是 suse 世界中相当于 yum 的存在。在上面所有的例子中,我的 hosts 文件中都只有一台机器。除了最后一个命令外,其他所有命令都应该在任何标准的 *nix 系统和标准的 ssh 配置中使用,这造成了一个问题。如果我们想要同时管理多种不同的机器呢?这便是 playbooks 和 ansible 的可配置性闪闪发光的地方了。首先我们来少许修改一下我们的 hosts 文件:
1 | $ cat ~/ansible_hosts |
样例输出:
1 | [RHELBased]121.12.12.12 |
首先,我们创建了一些分组的服务器,并且给了他们一些有意义的标签。然后我们来创建一个为不同类型的服务器执行不同操作的 playbook。你可能已经发现这个 yaml 的数据结构和我们之前运行的命令行语句中的相似性了。简单来说,-m 是一个模块,而 -a 用来提供模块参数。在 YAML 表示中你可以先指定模块,然后插入一个冒号 :,最后指定参数。
1 | --- |
现在我们有一个简单的 playbook 了,我们可以这样运行它:
1 | $ ansible-playbook testPlaybook.yaml -f 10 |
注意,你会看到 ansible 联系到的每一台机器的输出。-f 参数让 ansible 在多台主机上同时运行指令。除了指定全部主机,或者一个主机分组的名字以外,你还可以把导入 ssh 公钥的操作从命令行里转移到 playbook 中,这将在设置新主机的时候提供很大的方便,甚至让新主机直接可以运行一个 playbook。为了演示,我们把我们之前的公钥例子放进一个 playbook 里:
1 | --- |
除此之外还有很多可以做的事情,比如在启动的时候把公钥配置好,或者引入其他的流程来让你按需配置一些机器。不过只要 SSH 被配置成接受密码登陆,这些几乎可以用在所有的流程中。在你准备开始写太多 playbook 之前,另一个值得考虑的事情是,代码管理可以有效节省你的时间。机器需要不断变化,然而你并不需要在每次机器发生变化时都重新写一个 playbook,只需要更新相关的部分并提交这些修改。与此相关的另一个好处是,如同我之前所述,你可以从不同的地方管理你的整个基础结构。你只需要将你的 playbook 仓库 git clone 到新的机器上,就完成了管理所有东西的全部设置流程。
现实中的 ansible 例子
我知道很多用户经常使用 pastebin 这样的服务,以及很多公司基于显而易见的理由配置了他们内部使用的类似东西。最近,我遇到了一个叫做 showterm 的程序,巧合之下我被一个客户要求配置它用于内部使用。这里我不打算赘述这个应用程序的细节,不过如果你感兴趣的话,你可以使用 Google 搜索 showterm。作为一个合理的现实中的例子,我将会试图配置一个 showterm 服务器,并且配置使用它所需要的客户端应用程序。在这个过程中我们还需要一个数据库服务器。现在我们从配置客户端开始:
1 | --- |
这部分很简单。下面是主服务器:
1 | --- |
还凑合。请注意,从某种意义上来说这是一个任意选择的程序,然而我们现在已经可以持续地在任意数量的机器上部署它了,这便是配置管理的好处。此外,在大多数情况下这里的定义语法几乎是不言而喻的,wiki 页面也就不需要加入太多细节了。当然在我的观点里,一个有太多细节的 wiki 页面绝不会是一件坏事。
扩展配置
我们并没有涉及到这里所有的细节。Ansible 有许多选项可以用来配置你的系统。你可以在你的 hosts 文件中内嵌变量,而 ansible 将会把它们应用到远程节点。如:
1 | [RHELBased] |
尽管这对于快速配置来说已经非常方便,你还可以将变量分成存放在 yaml 格式的多个文件中。在你的 hosts 文件路径里,你可以创建两个子目录 groupvars 和 hostvars。在这些路径里放置的任何文件,只要能对得上一个主机分组的名字,或者你的 hosts 文件中的一个主机名,它们都会在运行时被插入进来。所以前面的一个例子将会变成这样:
1 | ultrabook:/etc/ansible # pwd |
1 | 2 directories, 5 files |
改善 Playbooks
组织 playbooks 也已经有很多种现成的方式。在前面的例子中我们用了一个单独的文件,因此这方面被大幅地简化了。组织这些文件的一个常用方式是创建角色。简单来说,你将一个主文件加载为你的 playbook,而它将会从其它文件中导入所有的数据,这些其他的文件便是角色。举例来说,如果你有了一个 wordpress 网站,你需要一个 web 前端,和一个数据库。web 前端将包括一个 web 服务器,应用程序代码,以及任何需要的模块。数据库有时候运行在同一台主机上,有时候运行在远程的主机上,这时候角色就可以派上用场了。你创建一个目录,并对每个角色创建对应的小 playbook。在这个例子中我们需要一个 apache 角色,mysql 角色,wordpress 角色,mod_php,以及 php 角色。最大的好处是,并不是每个角色都必须被应用到同一台机器上。在这个例子中,mysql 可以被应用到一台单独的机器。这同样为代码重用提供了可能,比如你的 apache 角色还可以被用在 python 和其他相似的 php 应用程序中。展示这些已经有些超出了本文的范畴,而且做一件事总是有很多不同的方式,我建议搜索一些 ansible 的 playbook 例子。有很多人在 github 上贡献代码,当然还有其他一些网站。
ansible命令集:
/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界面可与用户交互的命令执行工具
/usr/share/ansible_plugins:Ansible高级自定义插件目录(需要python基础)
/etc/ansible/ansible.cfg:配置文件
/etc/ansible/hosts:主机清单
Ansible 配置文件
绝大多数配置保持默认就好
1)[defaults] 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#inventory = /etc/ansible/hosts # 主机列表配置文件
#library = /usr/share/my_modules/ # 库文件存放目录
#remote_tmp = $HOME/.ansible/tmp # 生成的临时py命令文件存放在远程主机的目录
#local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录
#forks = 5 # 默认并发数
#poll_interval = 15 # 默认的线程池
#sudo_user = root # 默认sudo 用户
#ask_sudo_pass = True
#ask_pass = True
#transport = smart
#remote_port = 22
#module_lang = C
#module_set_locale = False
host_key_checking = False ### 检查对应服务器的host_key
(2)[privilege_escalation]
(3)[paramiko_connection]
(4)[ssh_connection]
(5)[accelerate]
(6)[selinux]
(7)[colors]
Ansible命令使用说明
ansible
1 | 调用ping模块检测node3主机是否存活(node2,3,4能基于主机名通信,且已做过免密钥通信) |
Ansiblie命令执行过程 (-vvvv)
加载自己的配置文件 默认/etc/ansible/ansible.cfg
加载自己对应的模块文件,如command
通过ansible将模块或命令生成对应的临时py文件,并将该 文件传输至远程服务器的
对应执行用户的家目录的.ansible/tmp/XXX/XXX.PY文件
给文件+x执行
执行并返回结果
删除临时py文件,sleep 0退出
ansible主机清单的配置
/ect/ansible/hosts,定义方式:
直接指明主机地址或主机名
node3
172.16.47.104
定义一个主机组,把主机地址或主机名写进去,然后通过组名来调用这个组
[webservers]
node3
node4
如果没有使用公钥,想要使用密码,也可以这样写(适用于第一次登陆控制)
格式:【主机名】 【主机地址】 【主机密码】 默认是root用户来进行的
[keepalived]
keepalived1 ansible_ssh_host=192.168.146.136 ansible_ssh_pass=”test”
keepalived2 ansible_ssh_host=192.168.146.137 ansible_ssh_pass=”test”
10.0.1.5 ansible_ssh_private_key_file=ssh_keys/10.0.1.5.key ansible_ssh_user=rootansible-docansible-doc -l :获取模块信息
ansible-doc -s MOD_NAME: 获取指定模块的使用帮助
1 | [root@node2 ~]# ansible-doc -h |
Ansible模块
command模块:
使用ansible自带模块执行命令 如果要用 > < | & ‘ ‘ 使用shell模块
1 | [root@node2 ~/.ssh]# ansible all -m command -a "ls /root/.ssh" |
相关选项如下:
creates:一个文件名,当该文件存在,则该命令不执行
free_form:要执行的linux指令
chdir:在执行指令之前,先切换到该目录
removes:一个文件名,当该文件不存在,则该选项不执行
executable:切换shell来执行指令,该执行路径必须是一个绝对路径
shell 模块:
调用bash执行命令 类似 cat /tmp/stanley.md | awk -F’|’ ‘{print $1,$2}’ &> /tmp/stanley.txt 这些复杂命令,即使使用shell也会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器(执行Ansible命令的机器往往称为:Master机或者中控机或者堡垒机)。
注意:command和shell模块的核心参数直接为命令本身;而其它模块的参数通常为“key=value”格式;’’
copy模块:
复制本地文件至远程服务器,并且能够改属性等
直接复制:
1 | ansible all -m copy -a "src=txt dest=/tmp mode=540" |
生成内容的复制:
1 | ansible all -m copy -a "content='hellow' dest=/tmp/test mode=540" |
注意:这两种方法是互斥的,即src和content不能同时使用
相关选项如下:
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
content:用于替代“src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归设定目录的权限,默认为系统默认权限
force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others:所有的file模块里的选项都可以在这里使用
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
file模块:
设置文件属性
-a “path=PATH state=directory” # 创建目录
1 |
-a “path=PATH src=FILE state=link” #创建链接文件
[root@node2 ~]# ansible all -m file -a “path=/root/haha src=/tmp/hehe state=link”
-a “path=PATH state=absent” #删除文件
[root@node2 ~]# ansible all -m file -a “path=/root/haha state=absent”
相关选项如下:
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
fetch模块: 从远程服务器拉取文件至本机,只能fetch文件,不能fetch目录,如果拉目录,先tar/zip 再拉到本机即可
[root@node2 ~]# ansible all -m fetch -a “src=/tmp/txt dest=/root/txt.txt”
cron模块: 管理cron计划任务
[root@node2 ~]# ansible all -m corn -a “minute=’*/5’ job=’/usr/sbin/ntpdate 172.16.0.1 &> /dev/null’ name=’Synctime’” #每5分钟同步一下时间
[root@node2 ~]# ansible all -m corn -a “state=absent name=’Synctime’” #删除上面的定时任务
相关选项如下:
- a “”: 设置管理节点生成定时任务
action: cron
backup= # 如果设置,创建一个crontab备份
cron_file= #如果指定, 使用这个文件cron.d,而不是单个用户crontab
day= # 日应该运行的工作( 1-31, , /2, etc )
hour= # 小时 ( 0-23, , /2, etc )
job= #指明运行的命令是什么
minute= #分钟( 0-59, , /2, etc )
month= # 月( 1-12, , /2, etc )
name= #定时任务描述
reboot # 任务在重启时运行,不建议使用,建议使用special_time
special_time # 特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state #指定状态,prsent表示添加定时任务,也是默认设置,absent表示删除定时任务
user # 以哪个用户的身份执行
weekday # 周 ( 0-6 for Sunday-Saturday, *, etc )
yum模块:yum安装软件,也有apt,zypper
[root@node2 ~]# ansible all -m yum -a “name=httpd state=latest” #安装httpd包
相关选项如下:
conf_file #设定远程yum安装时所依赖的配置文件。如配置文件没有在默认的位置。
disable_gpg_check #是否禁止GPG checking,只用于present' or
latest’。
disablerepo #临时禁止使用yum库。 只用于安装或更新时。
enablerepo #临时使用的yum库。只用于安装或更新时。
name= #所安装的包的名称
state #present安装, latest安装最新的, absent 卸载软件。
update_cache #强制更新yum的缓存。
service模块: 服务程序管理
[root@node2 ~]# ansible all -m service -a “name=httpd state=restarted” #重启httpd
[root@node2 ~]# ansible all -m service -a “name=httpd enabled=true” #开机启动
相关选项如下:
arguments #命令行提供额外的参数
enabled #设置开机启动。
name= #服务名称
runlevel #开机启动的级别,一般不用指定。
sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。
state #started启动服务, stopped停止服务, restarted重启服务,>
group模块: 组管理
[root@node2 ~]# ansible-doc -s group
- name: 添加或删除组
action: group
gid # 设置组的GID号
name= # 管理组的名称
state # 指定组状态,默认为创建,设置值为absent为删除
system # 设置值为yes,表示为创建系统组
User模块:用户管理
-a “”
action: user
comment # 用户的描述信息
createhom # 是否创建家目录
force # 在使用state=absent'是, 行为与
userdel –force’一致.
group # 指定基本组
groups # 指定附加组,如果指定为(‘groups=’)表示删除所有组
home # 指定用户家目录
login_class #可以设置用户的登录类 FreeBSD, OpenBSD and NetBSD系统.
move_home # 如果设置为home='时, 试图将用户主目录移动到指定的目录
name= # 指定用户名
non_unique # 该选项允许改变非唯一的用户ID值
password # 指定用户密码
remove # 在使用
state=absent’时, 行为是与 `userdel –remove’一致.
shell # 指定默认shell
state #设置帐号状态,不指定为创建,指定值为absent表示删除
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户。
uid #指定用户的uid
update_password # 更新用户密码
expires #指明密码的过期时间
ansible all -m user -a ‘name=magedu home=/tmp/magedu/ shell=/bin/bash uid=2000 comment=”test user” group=root’
ping 模块: 检测主机存活
setup模块:获取指定主机的facts。
facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装,而debian系列用apt来安装软件。
ansible node3 -m setup
selinux模块: 管理selinux
关闭selinux
ansible all -m selinux -a ‘state=disabled’
conf #指定应用selinux的配置文件。
state=enforcing|permissive|disabled #对应于selinux配置文件的SELINUX。
policy=targeted|minimum|mls #对应于selinux配置文件的SELINUXTYPE
script模块:发送脚本到各被管理节点,并执行;不需要参数
ansible all -m script -a ‘test.sh’ #直接在-a 后面指定脚本即可
未完待续……
最后打个广告,Stanley老师的Ansible权威指南,你,值得拥有
DSC0007.png (64.81 KB, 下载次数: 0)
下载附件 保存到相册
2017-6-9 08:59 上传