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

in Linux with 0 comment

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

参考链接

回复