Linux 运维手册之 ANSIBLE 运维自动化工具

分类:Linux 评论: 0

Ansible 一种集成 IT 系统的配置管理、应用部署、执行特定任务的开源平台。

Ansible 工具简介

Ansible 一种集成 IT 系统的配置管理、应用部署、执行特定任务的开源平台,是 AnsibleWorks 公司名下的项目,该公司由 CobblerFunc 的作者于 2012 年创建成立。

常用的运维自动化工具(配置管理)有很多,例如:AnsibleSaltStackPuppetFabric 等。

Ansible 基于 Python 语言实现,由 ParamikoPyYAML 两个关键模块构建。

工具特点

官网资源


Ansible 工具部署

小贴士:本文环境在未特殊声明时默认为 CentOS 7.5

角色 内网IP(LAN) 主机名
管理端 172.16.1.61 m01
客户端 172.16.1.41 backup
客户端 172.16.1.31 nfs01

实现从管理机 m01 到其他机器的密钥认证

0). ansible 借助公钥批量管理

[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.41
[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.21

小贴士:利用非交换式工具实现批量分发公钥与批量管理服务器,需要先生成 RSA 密钥,此处不再复述。

1). ansible 安装

[root@m01 ~]# yum install ansible -y

2). ansible 版本

[root@m01 ~]# ansible --version
ansible 2.6.1

3). ansible 配置

[root@m01 ~]# vim /etc/ansible/hosts
[test]
172.16.1.31
172.16.1.41

注意:使用 [] 定义了一个组,下面的地址均属于此组。

4). ansible 验证

[root@m01 ~]# ansible test -m ping
172.16.1.41 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
172.16.1.31 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

test 是指测试整组全部目标,也可单独指定地址仅测试单机。pong 是指目标测试为连通。

小贴士:ansible 是通过 ssh 端口进行通信的。

5). ansible 格式

ansible test -m command -a 'uptime'
命令 主机组 模块参数 模块名称 指定模块执行时的动作 模块动作
[root@m01 ~]# ansible test -m command -a "hostname"
172.16.1.41 | SUCCESS | rc=0 >>
backup

172.16.1.31 | SUCCESS | rc=0 >>
nfs01

6). ansible 语法

ansible <host-pattern> [-f forks] [-m module_name] [-a args] ...

参数列表:

-v,–verbose
    详细模式,如果命令执行成功,输出详细的结果 (-vv –vvv -vvvv)

-i PATH,–inventory=PATH                      
    指定 hosts 文件的路径,不指定时使用默认 hosts。

-f NUM,–forks=NUM                            
    NUM 是指定一个整数,默认是 5 ,指定 fork 开启同步进程的个数。

-m NAME,–module-name=NAME                    
    指定使用的 module 名称,默认是 command

-m DIRECTORY,–module-path=DIRECTORY          
    指定 module 的目录来加载 module ,默认是/usr/share/ansible,

-a,MODULE_ARGS                                
    指定 module 模块的参数

-k,–ask-pass                                  
    提示输入 ssh 的密码,而不是使用基于 ssh 的密钥认证

–sudo                                        
    指定使用 sudo 获得 root 权限

-K,–ask-sudo-pass                            
    提示输入 sudo 密码,与 –sudo 一起使用

-u USERNAME,–user=USERNAME                   
    指定移动端的执行用户

-C,–check                                    
    测试此命令执行会改变什么内容,不会真正的去执行

Ansible 主机清单

Ansible 通过读取默认的主机清单配置 /etc/ansible/hosts,来同时连接到多个远程主机,来执行远程操作任务的,但是如果要修改默认路径可以通过修改主配置文件 /etc/ansible/ansible.cfginventory 参数指定相应的路径。

[root@m01 ~]# grep "#inventory" /etc/ansible/ansible.cfg
#inventory      = /etc/ansible/hosts
#inventory_plugins  = /usr/share/ansible/plugins/inventory
#inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo

主机和组

Ansible中主机和组(Hosts and Groups)可以将很多主机整理为一组,以组单位进行相同的操作。

[root@m01 ~]# cat /etc/ansible/hosts
[test]
10.0.0.31
10.0.0.41

也可以使用域名来代替地址(需要在 /etc/hosts 中进行定义)

# 添加三台主机至 web (初版)
[web]
web1.domain.com
web2.domain.com
web3.domain.com

# 添加三台主机至 web (改良版)
[web]
web[1:3].domain.com

# 添加三台主机至 web (自定义端口)
[web]
web1.domain.com:10222
web2.domain.com
web3.domain.com

# 添加三台主机至 web (指定密码版)
[web]
web1.domain.com ansible_ssh_pass='123456'
web2.domain.com ansible_ssh_pass='123456'
web3.domain.com ansible_ssh_pass='123456'

# 添加三台主机至 web (指定密码改良版,前提为密码统一)
[web]
web[1:3].domain.com ansible_ssh_pass='123456'

# 添加三台主机至 web (指定密码拆分版,前提为密码统一)
[web]
web1.domain.com
web2.domain.com
web3.domain.com
[web:vars]
ansible_ssh_pass='123456'

# 定义多组,多组汇总整合
[apache]
10.0.0.1
10.0.0.2
10.0.0.3
[apache:vars]
ansible_ssh_pass='123456'

[nginx]
10.0.0.4
10.0.0.5
10.0.0.6
[nginx:vars]
ansible_ssh_pass='123456'

# web 组包括两个子组 apache nginx
[web:children]
apache
nginx

可使用 --list-hosts 显示组的成员

ansible nginx --list-hosts
ansible apache --list-hosts
ansible web --list-hosts

内置主机变量

参数 用途
ansible_ssh_host 用于指定被管理的主机的真实IP
ansible_ssh_port 用于指定连接到被管理主机的ssh端口号,默认是22
ansible_ssh_user ssh连接时默认使用的用户名
ansible_ssh_pass ssh连接时的密码
ansible_sudo 定义 sudo 用户
ansible_sudo_pass 定义 sudo 连接用户时的密码
ansible_sudo_exec 如果sudo命令不在默认路径,需要指定sudo命令路径
ansible_ssh_private_key_file 秘钥文件路径,秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type 目标系统的shell的类型,默认sh
ansible_connection SSH 连接的类型: local , ssh , paramiko
ansible_python_interpreter 用来指定Python解释器的路径,默认为/usr/bin/python 同样可以指定ruby 、perl 的路径
ansible_*_interpreter 其他解释器路径,用法与ansible_python_interpreter类似,这里"*"可以是ruby或perl等其他语言

Ansible 常用模块

ansible 中是指需要快速执行一条命令,并且不需要保存的命令,对于复杂的命令则使用 playbook

注意事项:关于命令执行结果的颜色

:对远程节点已进行相应修改
绿:对远程节点不进行相应修改,或者只是对远程节点信息进行查看
:操作执行命令有异常
:表示对命令执行发出警告信息(可能存在的问题,提供建议)

command 模块

[root@m01 ~]# ansible test -m command -a "hostname"

提示:默认模块就是 command,因此 -m command 可省略,仅可用于执行命令,若需要使用管道,请使用 shell 模块。

补充:参数说明

argv       --- 允许用户以列表与字符串的形式提供命令。
chdir      --- 在运行命令之前切换到此目录。
creates    --- 文件名,当它已经存在时,将不会运行此步骤。
removes    --- 文件名,当它不存在时,不会运行此步骤。
stdin      --- 将命令的stdin直接设置为指定值。

官方文档:command - Executes a command on a remote node

shell 模块

[root@m01 ~]# ansible test -f 50 -m shell -a "ip a | grep eth0" 

提示:可以使用管道,以及命令的各种组合形式,但在编写剧本时此模块仅作为没有选择的最后方法,有专用模块的情况下推荐使用模块完成操作。

补充:参数说明

chdir       --- 在运行命令之前进入此目录
creates     --- 文件名,如果已存在,则不会运行此步骤。
removes     --- 文件名,如果不存在,则不会运行此步骤。
executable  --- 更改用于执行命令的shell。应该是可执行文件的绝对路径。
stdin       --- 将命令的stdin直接设置为指定值。

官方文档:shell - Execute commands in nodes.

copy 模块

使用模块推送文件

[root@m01 ~]# ansible test -m copy -a "src=/etc/hosts dest=/tmp/test.txt"

对远端已有文件进行备份,再进行推送(按照时间信息备份,文件名会加上时间戳)

[root@m01 ~]# ansible test -m copy -a "src=/etc/hosts dest=/tmp/test.txt backup=yes"

不对远端已有文件进行备份,直接对远端文件进行写入 content 中的字符串

[root@m01 ~]# ansible test -m copy -a "content='xuliangwei' dest=/tmp/oldboy"

补充:参数说明

src           --- 推送数据的源文件信息
dest          --- 推送数据的目标路径
backup        --- 对推送传输过去的文件,进行备份
content       --- 直接批量在被管理端文件中添加内容
group         --- 将本地文件推送到远端,指定文件属组信息
owner         --- 将本地文件推送到远端,指定文件属主信息
mode          --- 将本地文件推送到远端,指定文件权限信息

官方文档:copy - Copies files to remote locations

script 模块

第一步:编写脚本(在本地)

[root@m01 ~]# cat >> yum.sh <<'EOF'
#!/bin/bash
yum -y install glances
EOF

第二步:在本地使用模块推送至目标主机进行执行(并不需要进行传输脚本本身)

[root@m01 ~]# ansible test -m script -a "./yum.sh"

补充:参数说明

chdir         --- 在远端服务器运行脚本前切换目录
creates       --- 文件名,如果已存在,则不会运行此步骤
executable    --- 用于调用脚本的可执行文件的名称或路径
free_form     --- 本地脚本文件的路径,后跟可选参数。
removes       --- 文件名,如果不存在,则不会运行此步骤。

官方文档:script - Runs a local script on a remote node after transferring it

yum 模块

安装 Apache

[root@m01 ~]# ansible test -m yum -a "name=httpd state=latest"

补充:参数说明

name    ---指定要安装的软件包名称
state   ---指定使用yum的方法
    installed,present   ---安装软件包
    removed,absent      ---移除软件包
    latest               ---安装最新软件包(推荐使用)

官方文档:yum - Manages packages with the yum package manager

file 模块

创建 /data 文件夹,并递归设置属主

[root@m01 ~]# ansible test -m file -a "path=/data state=diretory recurse=yes owner=root group=root"

创建 555 权限文件

[root@m01 ~]# ansible test -m file -a "path=/tmp/tt state=touch mode=555 owner=root group=root"

创建软链接

[root@m01 ~]# ansible test -m file -a "src=/tmp/tt path=/tmp/tt_link state=link"

补充:参数说明

path        --- 指定远程主机目录或文件信息
src         --- 软链接/硬链接 源地址
mode        --- 文件权限
recurse     --- 递归设置指定的文件属性(仅适用于目录)
state       --- 
    directory   --- 在远端创建目录
    touch       --- 在远端创建文件
    link        --- link或hard表示创建链接文件
    absent      --- 表示删除文件或目录
    mode        --- 设置文件或目录权限
    owner       --- 设置文件或目录属主信息
    group       --- 设置文件或目录属组信息

官方文档:file - Sets attributes of files

service 模块

[root@m01 ~]# ansible test -m service -a "name=crond state=stopped enabled=yes"

补充:参数说明

name        --- 定义要启动服务的名称
state       --- 指定服务状态是停止或是运行,停止和运行指令要写成过去时
    started     --- 启动
    stopped     --- 停止
    restarted   --- 重启
    reloaded    --- 重载
enabled     --- 是否让服务开启自启动

官方文档:service - Manage services

user 模块

[root@m01 ~]# echo "bgx" | openssl passwd -1 -stdin
$1$1KmeCnsK$HGnBE86F/XkXufL.n6sEb.

[root@m01 ~]# ansible test -m user -a 'name=xlw password="$1$1KmeCnsK$HGnBE86F/XkXufL.n6sEb."'

补充:参数说明

append        --- no,则仅将用户添加到组中指定的组,并将其从所有其他组中删除。
                  yes,将用户添加到组中指定的组。
comment       --- 设置用户账户的描述
create_home   --- 是否创建家目录(默认:yes)
force         --- 与state = absent 一起使用时,行为与 userdel --force 一样
group         --- (可选)设置用户的主要组(采用组名称)
state         --- 账户是否存在,如果状态与所述状态不同,则采取行动。
system        --- 创建帐户时,将其设置为yes会使用户成为系统帐户。无法在现有用户上更改此设置。
uid           --- (可选)设置用户的UID。
扩展程序选项

官方文档:user - Manage user accounts

cron 模块

使用模块添加一条定时任务

[root@m01 ~]# ansible test -m cron -a "name='cron01' minute=* hour=* day=* month=* weekday=* job='/bin/bash /root/test.sh'"

禁用指定的定时任务

[root@m01 ~]# ansible test -m cron -a "name='ansible cron02' minute=0 hour=0 job='/bin/bash /root/test.sh' state=absent"

补充:参数说明

minute        --- 分(默认 * )
hour          --- 时(默认 * )
day           --- 日(默认 * )
month         --- 月(默认 * )
weekday       --- 周(默认 * )
job           --- 具体任务,要执行的命令,或者如果设置了env,则为环境变量的值。该命令不应包含换行符。
state         --- 是否确保作业或环境变量存在或不存在。
user          --- 定时任务的所属用户

官方文档:cron - Manage cron.d and crontab entries

mount 模块

挂载 NFS 分区

[root@m01 ~]# ansible test -m mount -a "path=/backup src=172.16.1.31:/data/www fstype=nfs opts=defaults,noatime state=mounted"

补充:参数说明

mounted     --- 挂载设备,并将配置写入/etc/fstab
unmounted   --- 卸载设备,不会清除/etc/fstab写入的配置
absent      --- 卸载设备,会清理/etc/fstab写入的配置

官方文档:mount - Control active and configured mount points

unarchive 模块

使用模块解压文件并传输至目标主机

[root@m01 ~]# ansible test -m unarchive -a "src=./upload.zip dest=/data/www owner=www-data group=www-data"

补充:参数说明

remote_src    --- 设置为 yes 表示存档文件已在远程系统上,而不是本地文件。
src           --- 源文件地址
dest          --- 解压至目录
mode          --- 解压出的文件权限
owner         --- 解压出的文件属主
group         --- 解压出的文件属组
list_files    --- 若为 yes 会输出解压文件的文件列表

官方文档:unarchive - Unpacks an archive after (optionally) copying it from the local machine.

查看帮助文档方法

查看所有模块说明信息

# ansible-doc -l

查看指定模块参数用法信息(以 yum 模块为例)

# ansible-doc yum

Ansible 剧本编写

playbook是由一个或多个 play 组成的列表。play 的主要功能在于将事先归并为一组的主机装扮成事先通过 ansible 中的 task 定义好的角色。
从根本上来讲,所谓的task无非是调用ansible的一个module将多个play组织在一个playbook中,即可以让他们联合起来按事先编排的机制完成某一个任务

注意: ansible 是通过 yaml 语法识别配置描述文件。扩展名是 .yaml

YAML基础语法

官方网址:YAML

YAML:
    1.缩进(层级关系)  2个空格,不能使用Tab。
    2.冒号  key: value
    3.短横线 - list1
            - list2

Playbook 组件

handlers

用于当关注的资源发生变化时采取一定的操作,notify 这个动作可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,

简而言之:在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

举个例子:

- hosts: all
- tasks:
    - name: Copy conf To Remote Host
      copy:
        src: ./httpd.conf
        dest: /etc/httpd/conf/httpd.conf
      notify: "Restart Apache"

  handlers:
    - name: Restart Apache
      service:
        name: apache
        state: restarted

import_playbook

在实际编写剧本时,为方便检查和书写,一般将对不同组的主机进行的操作分开编写为 .yaml ,然后使用一个文件统一将这些剧本统一起来。

注意:在之前的版本中可以使用 include ,此组件就是用来代替includeinclude 组件将在下个版本中取消)

举个例子:

# 按序执行以下 yaml
- import_playbook: base.yaml
- import_playbook: backup.yaml
- import_playbook: nfs.yaml
- import_playbook: web.yaml

操作案例

使用ansible playbook 批量部署 Apache

1. 创建环境

[root@m01 ~]# mkdir /srv/ansible -p
[root@m01 ~]# mkdir /srv/ansible/apache -p
[root@m01 ~]# cp /etc/httpd/conf/httpd.conf ./

2. 编辑剧本

[root@m01 ~]# vim /srv/ansible/apache/install.yaml

写入以下内容

- hosts: all

  handlers:
    - name: Restart Apache
      service:
        name: apache
        state: restarted

  tasks:
    - name: Install Apache Package
      yum:
        name: httpd
        state: latest

    - name: Copy conf To Remote Host
      copy:
        src: ./httpd.conf
        dest: /etc/httpd/conf/httpd.conf
        notify: "Restart Apache"

    - name: Ensure Apache is running
      service: 
        name: httpd
        state: started
        enabled: yes

3. 语法检测

[root@m01 ~]# ansible-playbook install.yaml --syntax-check

4. 模拟测试

[root@m01 ~]# ansible-playbook -C install.yaml

PLAY [web] ****************************************************************************************

TASK [Gathering Facts] ****************************************************************************
ok: [172.16.1.7]

TASK [install httpd] ******************************************************************************
changed: [172.16.1.7]

TASK [enable httpd service] ***********************************************************************
changed: [172.16.1.7]

PLAY RECAP ****************************************************************************************
172.16.1.7                 : ok=3    changed=2    unreachable=0    failed=0

5. 任务列表

[root@m01 ~]# ansible-playbook install.yaml --list-task

playbook: install.yaml

  play #1 (web): web    TAGS: []
    tasks:
      install httpd TAGS: []
      enable httpd service  TAGS: []

6. 实际执行

[root@m01 ~]# ansible-playbook install.yaml

附录

参考链接

回复