Ansible安装、配置与常用模块介绍

前言:

假如让你在一组服务器安装某个软件,服务器少的话还可以接受,但如果有上百台服务器的话,这样会耗费大量时间,在这时候Ansible就由此而生;

Ansible简介:

ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

Ansible安装:

一台控制主机:172.16.47.165

一台管理主机:172.16.47.166

安装要求:

控制主机:需要安装python2.6/2.7

管理主机:需要安装 Python2.4 以上版本,若低于 Python2.5 需要安装 pythonsimplejson; 若启用了selinux,则需要安装libselinux-python。

安装环境:

系统环境:CentOS Linux release 7.4.1708 (Core)
软件环境:Python 2.7.5

安装:
本文使用yum安装:
yum -y install epel-release
yum -y install ansible

Ansible配置:

在控制主机中的hosts文件中添加管理主机的IP地址:

vim /etc/ansible/hosts

在配置文件最下面添加管理主机的IP地址

配置控制主机SSH密钥:

ssh-keygen -t rsa
将公钥拷贝到管理主机中.ssh/authorized_keys文件中,实现免密登录远程管理主机:

ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.47.166

修改ansible配置文件

vim /etc/ansible/ansible.cfg

1、禁用每次执行ansible命令检查ssh key host:

host_key_checking = False

2、开启日志记录:

log_path = /var/log/ansible.log

3、ansible连接加速配置:

[accelerate]
accelerate_port = 10000
accelerate_multi_key = yes

测试:

ansible all -m ping
回复pong则表示主机在线

Ansible playbooks:

Playbooks是Ansible的配置,部署和编排语言。他们可以描述您希望远程系统执行的策略,或者描述一般IT流程中的一系列步骤。
如果Ansible模块是您车间的工具,那么剧本就是您的使用说明书,并且您的主机清单是您的原材料。
对于Ansible,几乎每个YAML文件都以一个列表开始。列表中的每个项目都是键/值对列表,通常称为“散列”或“字典”。所以,我们需要知道如何在YAML中编写列表和字典。


示例:
---  #这是YAML将文件解释为正确的文档的要求
- hosts: all #指定的主机,这里指定了所有
  vars:
    http_port: 80 #端口
    max_clients: 200 #最大链接数
  remote_user: root #以root账户执行
  tasks: 
  - name: Installs nginx web server
    yum: name=nginx state=installed
  - name: write the nginx config file
    template: src=/srv/nginx.j2 dest=/etc/nginx.conf
    notify:
    - start nginx

  handlers:
  - name: start nginx
    command: systemctl restart nginx

在上面这个示例当中值得注意的是notify,它会调用hadlers下的name,执行下面的操作

Tasks:
每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task.(注:此处翻译未必准确,暂时保留原文)
在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook 的 rotation 中移除. 如果发生执行失败的情况,请修正 playbook 中的错误,然后重新执行即可.
每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables).
modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性 (不是必要的).
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.
如果要声明一个 task,以前有一种格式: “action: module options” (可能在一些老的 playbooks 中还能见到).现在推荐使用更常见的格式:”module: options” ,本文档使用的就是这种格式.
下面是一种基本的 task 的定义,service moudle 使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
tasks:
  - name: make sure apache is running
    service: name=httpd state=running
比较特别的两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数,而是这样:
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
使用 command module 和 shell module 时,我们需要关心返回码信息,如果有一条命令,它的成功执行的返回码不是0, 你或许希望这样做:
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true


Handlers: 在发生改变时执行的操作:
’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.
举例来说,比如多个 resources 指出因为一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次.
这里有一个例子,当一个文件的内容被改动时,重启两个 services:
- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache
‘notify’ 下列出的即是 handlers.
Handlers 也是一些 task 的列表,通过名字来引用,它们和一般的 task 并没有什么区别.Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行.不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次.
这里是一个 handlers 的示例:
handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted
Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了

Ansible常用模块:

ping模块:

检查主机是否在线,如果主机在线则回复pong

示例:
ansible all -m ping //如果不需要检查全部主机,可将all改为定义的组名或单>独ip

yum模块:

使用yum软件包管理器管理软件包,其选项有: 
– config_file:yum的配置文件 (optional) 
– disable_gpg_check:关闭gpg_check (optional) 
– disablerepo:不启用某个源 (optional) 
– enablerepo:启用某个源(optional) 
– name:要进行操作的软件包的名字,默认最新的程序包,指明要安装的程序包,可以带上版本号,也可以传递一个url或者一个本地的rpm包的路径 
– state:状态(present,absent,latest),表示是安装还卸载
    present:默认的,表示为安装
    lastest: 安装为最新的版本 
    absent:表示删除 

示例:
ansible all -m yum -a 'name=httpd state=lastest' //根据软件包名字安装
ansible all -m yum -a 'name=“@Development tools” state=present' //根据软件包安装
ansible all -m yum -a 'name=http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm state=present' //传递url安装

service模块:

用于服务管理,如果你的系统是centos7就不要使用该模块了,因为centos7服务管理默认是systemctl
-arguments:给命令行提供一些选项
-enabled:是否开机启动yes/on,要求状态(state)和启动(enabled)中至少有一个
-name:必须项,服务名称
-runlevel:运行级别
-sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
-state:对当前服务执行启动,停止、重启、重新加载等(started,stopped,restarted,reloaded)

示例:
ansible all -m service -a 'name=httpd state=started' //表示启动httpd服务
ansible all -m service -a 'name=httpd state=stopped' //表示关闭httpd服务
ansible all -m service -a 'name=httpd enabled=yes' //表示将httpd服务设为开机启动

user模块:

user模块是请求的是useradd, userdel, usermod三个指令
-home:指定用户的家目录,需要与createhome配合使用。
-groups:指定用户的属组。
-uid:指定用户的uid。
-password:指定用户密码。 //注意!指定password参数时,不能使用明文密码,因为密码会被直接传送到被管理主机的/etc/shadow文件中,所以需将密码字符串进行加密处理,然后将得到的字符串放到password中即可。
-name:指定用户名。
-createhome:是否创建家目录yes/no。
-system:是否为系统用户。
-remove:当state=absent时,remove=yes表示连同家目录一起删除。
-state:present=创建,absent=删除
-shell:指定用户shell环境。
-append:如果没有指定group,append为yes,那么会添加到用户同名组,append设定为no,那么会添加到user组。如果指定了group,那么都会添加在指定的group组。
-generate_ssh_key:是否为相关用户生成ssh密钥,这不会覆盖现有的SSH密钥。
-ssh_key_bits:可选择指定要创建的ssh密钥中的位数。
-ssh_key_passphrase:设置ssh密钥的密码,如果没有提供密码,ssh密钥将默认没有密码。
-ssh_key_file:指定ssh密钥文件名(可选), 如果这是一个相对的文件名,那么它将是相对于用户的主目录。
-ssh_key_type:指定要生成的ssh密钥的类型(可选),可用的SSH密钥类型将取决于目标主机上的实现。

示例:
ansible all -m user -a 'name=macro shell=/bin/shell groups=macro456 state=present' //用户名=macro,shell环境=bash,用户组=macro456
ansible all -m user -a 'name=macro state=absent remove=yes' //删除用户
ansible all -m user -a "name=macro123 shell=/bin/shell generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa" //新建用户并创建sshkey

group模块:

-gid:指定用户的gid。
-name:指定组名。
-state:创建=present,删除=absent。
-system:如果等于yes,则表示创建的组为系统组。

示例:
ansible all -m group -a "name=macro state=present"

copy模块:

copy模块用于将本地或远程机器上的文件拷贝到远程主机上。

-backup:若是相同文件,在覆盖之前会将原文件备份,注意!传输过程中copy模块会检查该文件的md5值,若md5值与目的主机的文件相同,backup选项就会不起作用。
-content:当使用content而不是src时,可以将文件的内容之际设置成指定的值。
-desc:复制到目标主机的绝对路径,如果原文件是一个目录,那该路径也必须是个目录。
-force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
-others:所有的file模块里的选项都可以在这样使用。

示例:
ansible all -m copy -a "src=test.txt backup=yes desc=/root"

file模块:

file模块主要用于远程主机上的文件操作。

-force: 需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no。
-group:定义文件/目录的属组。
-mode:定义文件/目录的权限。
-owner:定义文件/目录的属主。
-path:必选项,定义文件/目录的路径。
-recurse:递归的设置文件的属性,只对目录有效。
-src:要被链接的源文件路径,只应用于state=link。
-dest:呗链接到的路径,只应用于state=link。
-state:directory:如果目录不存在则创建目录。
    file:即使文件不存在,也不会创建。
    link:创建软链接。
    hard:创建硬链接。
    touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间。
    absent:删除目录、文件或者取消链接文件。

示例:
ansible all -m file -a "path=/root/macro.txt owner=macro group=root mode=0755 state=touch" #创建文件,所属用户为macro,所属组为root,权限为755

ansible all -m file -a "src=/root/macro.txt dest=/root/macro state=link" #将刚创建的macro.txt文本链接到/root/macro下

ansible all -m file -a "path=/root/macro123 state=directory mode=777" #创建一个名为macro123的目录,权限为777

ansible all -m file -a "path=/root/macro state=absent" #删除刚创建的软链接,删除文件/目录同样方法

template模块:

基于模版方式将一个文件复制到远程主机(格式是以jinja2的模版语言处理)
-backup:如果原目标文件存在,则先备份目标文件(类似于copy模块到backup参数)
-src:控制主机上的jinja2格式化模版的路径,这可以是相对路径或绝对路径
-dest:将模版复制到管理主机的目录/文件
-owner:目标文件属主
-group:目标文件属组
-mode:目标文件的权限模式,模式可以被指导为符号模式(例如,u+rwx,g=rw,o=r)

示例:
ansible all -m template -a "src=/srv/nginx.j2 dest=/etc/nginx.conf”
#将做好的模版文件替换为管理主机上的目录/文件,与copy模块同理,传输过程中会检查该文件的md5值,若md5值与目的主机的文件相同,将不会做任何操作。

[root@ansible ~]# ansible all -m template -a "src=/srv/nginx.j2 dest=/etc/nginx.conf"
172.16.47.159 | SUCCESS => {
    "changed": true,
    "checksum": "73469bd9c223d66cfb607eec2c1be09be9e3e027",
    "dest": "/etc/nginx.conf",
    "gid": 0,
    "group": "root",
    "md5sum": "a4c9ea3d8d375456e755edcc3e2c3ecb",
    "mode": "0644",
    "owner": "root",
    "size": 12,
    "src": "~None/.ansible/tmp/ansible-tmp-1529485644.53-114255598932213/source",
    "state": "file",
    "uid": 0
}
[root@ansible ~]# ansible all -m template -a "src=/srv/nginx.j2 dest=/etc/nginx.conf"
172.16.47.159 | SUCCESS => {
    "changed": false,
    "checksum": "73469bd9c223d66cfb607eec2c1be09be9e3e027",
    "dest": "/etc/nginx.conf",
    "gid": 0,
    "group": "root",
    "mode": "0644",
    "owner": "root",
    "path": "/etc/nginx.conf",
    "size": 12,
    "state": "file",
    "uid": 0
}

观察上面输出发现第一次执行changed状态为true,第二次执行changed为false,可以发现第二次执行并没有成功

command模块:

command模块接受命令名称后接空格分隔参数列表,给定的命令将在选定的节点上执行,它不会通过shell进行处理,像一些特殊字符,例如”<”,”>”,”|”,”;”和“&”将无法正常工作,如果需要用这些功能则需要调用shell模块。
-chdir:在运行该命令之前cd进入该目录

示例:
ansible all -m command -a ‘cat /etc/passwd’

shell模块:

shell模块接受命令名称后接空格分隔参数列表,几乎与command模块完成一样,但通过远程节点上的shell(/bin/sh)运行命令。
-chdir:在运行该命令之前cd进入该目录
-executable:更改用于执行该命令的shell,可执行文件的绝对路径。

示例:
ansible all -m shell -a 'cat < ~/test.txt executable=/bin/bash’