ANSIBLE

ansible 介绍和架构

ansible 特性

  • 基于python实现
  • 模块化:支持自定义模块,可以使用任何语言编写模块
  • 安全:基于OpenSSH
  • 部署简单:被控端不需要配置环境
  • 幂等性:一个任何执行一遍和执行n遍效果一样,不因重复执行带来意外情况,此特性非绝对
  • 支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案 role

ansible 架构

  • INVENTORY:Ansible管理主机的清单/etc/anaible/hosts
  • MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

ansible 命令执行来源

  • USER:普通用户,即SYSTEM ADMINISTRATOR
  • PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
  • CMDB(配置管理数据库) API 调用
  • PUBLIC/PRIVATE CLOUD API调用
  • USER-> Ansible Playbook -> Ansibile

注意事项

  • 执行ansible的主机一般称为管理端, 主控端,中控,master或堡垒机
  • 主控端Python版本需要2.6或以上
  • 如果被控端Python版本小于2.4,则需要安装python-simplejson
  • 被控端如开启SELinux需要安装libselinux-python
  • windows 不能做为主控端

ansible 安装和入门

pip安装后没有配置文件,需要手动创建,有以下四种方式:

  1. ANSIBLE_CONFIG (environment variable if set)
  2. ansible.cfg (in the current directory)
  3. ~/.ansible.cfg (in the home directory)
  4. /etc/ansible/ansible.cfg

    ansible 相关文件

  • /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
  • /etc/ansible/hosts 主机清单
  • /etc/ansible/roles/ 存放角色的目录

ansible 主配置文件

默认为:/etc/ansible/ansible.cfg

参考文档:http://www.ansible.com.cn/docs/intro_configuration.html

inventory 主机清单

默认为:/etc/ansible/hosts

参考文档:http://www.ansible.com.cn/docs/intro_inventory.html?highlight=hosts

示例:

ntp.magedu.com
[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com
[websrvs]
www[1:100].example.com
[dbsrvs]
db-[a:f].example.com
[appsrvs]
# 表示 10.0.0.1 - 10.0.0.100
10.0.0.[1:100]
[ex-lb]
# 定义主机变量,这些变量定义后可在 playbooks 中使用
10.0.2.1 LB_ROLE=backup EX_APISERVER_VIP=10.0.2.188 EX_APISERVER_PORT=8443
10.0.2.2 LB_ROLE=master EX_APISERVER_VIP=10.0.2.188 EX_APISERVER_PORT=8443

给主机组设置变量,示例:

[all:vars]						# 为所有主机组设置变量
CONTAINER_RUNTIME="docker"
CLUSTER_NETWORK="calico"
PROXY_MODE="ipvs"
SERVICE_CIDR="192.168.0.0/16"
CLUSTER_CIDR="10.10.0.0/16"
NODE_PORT_RANGE="30000-60000"
CLUSTER_DNS_DOMAIN="ljk.local."
bin_dir="/usr/local/bin"
ca_dir="/etc/kubernetes/ssl"
base_dir="/etc/ansible"

注意:ansible 会隐式创建一个 localhost 主机,只是 localhost 不能匹配 all

ansible 相关工具

  • ansible:主程序,临时命令执行工具
  • ansible-doc:查看配置文档,模块功能查看工具,相当于man
  • ansible-playbook:定制自动化任务,编排剧本工具,相当于脚本
  • ansible-pull:远程执行命令的工具
  • ansible-vault:文件加密工具
  • ansible-console:基于Console界面与用户交互的执行工具
  • ansible-galaxy:下载/上传优秀代码或Roles模块的官网平台

ansible

通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能

注意:使用ansible之前,需要配置各个被控端基于key的密钥认证

ansible <host-pattern> [option]...
  • host-pattern:匹配被控主机

    • all:inventory中的所有主机
    • 支持通配符
    • 支持正则表达式:需要以 ‘~’ 开头
    • 使用:表示或关系
    • 使用:&表示与关系
    • 使用:!表示非关系

    示例:

    # all
    ansible all –m ping
    # 统配符
    ansible "*" -m ping
    ansible 192.168.1.* -m ping
    ansible "srvs" -m ping
    ansible "10.0.0.6 10.0.0.7" -m ping
    # 或
    ansible "websrvs:appsrvs" -m ping
    ansible "192.168.1.10:192.168.1.20" -m ping
    # 与
    ansible "websrvs:&dbsrvs" –m ping	# 在websrvs组并且在dbsrvs组中的主机
    # 非 注意此处为单引号
    ansible 'websrvs:!dbsrvs' –m ping	#在websrvs组,但不在dbsrvs组中的主机
    # 综合逻辑
    ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping
    # 正则表达式
    ansible "~(web|db).*\.magedu\.com" –m ping
  • 常用option

    • –version:显示版本等信息
    • -m module:指定模块,默认为command
    • -a|–args MODULE_ARGS:指定模块的参数
    • –list-hosts:显示主机列表,可简写 –lists
    • -C|–check:检查,并不执行
    • -T|–timeout=TIMEOUT:执行命令的超时时间,默认10s
    • -k|–ask-pass:提示输入ssh连接密码,默认Key验证
    • -u| –user REMOTE_USER:指定远程执行的用户
    • -b|–become:代替旧版的sudo 切换
    • –become-user=USERNAME:指定sudo的runas用户,默认为root
    • -K|–ask-become-pass:提示输入sudo时的口令
ansible 命令执行顺序
  1. 加载配置文件,默认/etc/ansible/ansible.cfg
  2. 加载对应的模块文件,如:command
  3. 将模块或命令生成临时py文件,并将该文件传输至远程服务器远程服务器:$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY
  4. 给文件+x权限
  5. 执行并返回结果
  6. 删除临时py文件,退出
ansible 执行状态

在ansible.cfg的[colors]配置项中设置:

  • 绿色:执行成功且没有对目标主机做更改
  • 黄色:执行成功且对目标主机做了更改
  • 红色:执行失败
ansible使用示例
(venv) [root@c71 bin]$ansible all -m command -a 'ls ~'     
10.0.0.72 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.82 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.81 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
(venv) [root@c71 bin]$ansible all -m ping
10.0.0.72 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.81 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.82 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

ansible-doc

显示模块帮助,相当于man

ansible-doc [options] [module...]

options:

  • -l|–list:列出可用模块
  • -s|–snippet:显示指定模块的playbook片段

示例:

#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping

ansible-playbook

执行编写好的 playbook 任务

ansible-playbook <filename.yml> ... [options]
  • –syntax-check:语法检查
  • -C|–check:只检测可能会发生的改变,但不真正执行操作
  • –list-hosts:列出运行任务的主机
  • –list-tags:列出tag
  • –list-tasks:列出task
  • –limit 主机列表:只针对主机列表中的特定主机执行
  • -v -vv -vvv:显示过程

ansible-vault

加密解密yml文件

ansible-vault {create,decrypt,edit,view,encrypt,encrypt_string,rekey} ...
  • encrypt:加密
  • decrypt:解密
  • view:查看
  • edit:编辑加密文件
  • rekey:修改口令
  • create:创建新文件

ansible-console

交互执行命令,支持tab,ansible 2.0+新增

执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$

常用子命令:

  • 设置并发数: forks n 例如: forks 10
  • 切换组: cd 主机组 例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?help

示例:

(venv) [root@c71 bin]$ansible-console 
Welcome to the ansible console.
Type help or ? to list commands.

root@all (3)[f:5]$ ping
10.0.0.72 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.82 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.81 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
root@all (3)[f:5]$ list
10.0.0.72
10.0.0.81
10.0.0.82
root@all (3)[f:5]$ ls ~
10.0.0.72 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.82 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
10.0.0.81 | CHANGED | rc=0 >>
anaconda-ks.cfg
init.sh
original-ks.cfg
root@all (3)[f:5]$ exit

(venv) [root@c71 bin]$

ansible-galaxy

连接 https://galaxy.ansible.com 下载相应的roles

示例:

#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.mysql
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy.redis

ansible 常用模块

本文以 ansible 2.10.5 为准

虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块

常用模块帮助文档参考:

# 官网
https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
# 中文翻译
http://www.ansible.com.cn/docs/modules.html

使用 ansible-doc 可以查看每个模块的具体用法:

# 以 command 模块为例
ansible-doc -s command			# 查看模块的可用选项
ansible-doc command				# 查看模块的详细帮助信息

# ansible-doc module 的内容是包含 ansible-doc -s module 的

# 打印模块的选项
$ansible-doc -s shell | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '      
chdir
cmd
creates
executable
free_form
removes
stdin
stdin_add_newline
warn

command

默认模块,可忽略 -m 选项
注意:此命令不支持 $VARNAME < > | ; & 等,用shell模块实现

# 以下两条命令是一样的,-m 可以省略,-a 不能省略
$ansible all -a 'hostname'
$ansible all -m command -a 'hostname'

$ansible all -a 'chdir=/etc pwd'
10.0.2.2 | CHANGED | rc=0 >>
/etc
10.0.2.3 | CHANGED | rc=0 >>
/etc
10.0.2.1 | CHANGED | rc=0 >>
/etc
# 选项:ansible-doc -s command
free_form  # 必须参数,指定需要远程执行的命令,free_form并不是一个"实际存在"的参数名,比如,当我们想要在远程主机上执行ls命令时,我们并不需要写成"free_form=ls" ,这样写反而是错误的,因为并没有任何参数的名字是free_form,当我们想要在远程主机中执行ls命令时,直接写成ls即可,这就是free_form参数的含义
chdir  # 指定一个目录,在执行对应的命令之前,会先进入到chdir参数指定的目录中
creates  # 当指定的文件存在时,就不执行对应命令
removes  # 与creates参数的作用正好相反,它的作用是当指定的文件不存在时,就不执行对应命令
stdin  # 

shell

和command相似,但是功能更丰富,支持各种符号,比如 *、$、>

注意:类似 cat /tmp/test.md | awk -F'|' '{print $1,$2}' &> /tmp/example.txt
些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的
结果拉回执行命令的机器

建议将 shell 模块替换 command,设为默认模块

$vim /etc/ansible/ansible.cfg
module_name = shell
$ansible-doc -s shell | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
chdir
cmd
creates
executable  # 指定执行程序,默认是 /bin/bash
free_form
removes
stdin
stdin_add_newline
warn

script

在远程主机上运行 ansible服务器上的脚本(无需执行权限)

$ansible-doc -s script | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
chdir
cmd
creates
decrypt
executable
free_form
removes

copy

从ansible服务器主控端复制文件到远程主机

src  # 需要copy的文件或目录
dest  # 文件将被拷贝到远程主机的哪个目录中,dest为必须参数
content  # 当不指定src时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错
force  # 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变
backup  #  当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机
owner  # 指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错
group  # 指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错
mode  # 指定文件拷贝到远程主机后的权限,如果你想将权限设置为"rw-r--r--",则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示
attributes
checksum
decrypt
directory_mode
follow
local_follow
remote_src
selevel
serole
setype
seuser
unsafe_writes
validate

示例:

ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/"
ansible test70 -m copy -a 'content="aaa\nbbb\n" dest=/opt/test'
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ force=no"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ backup=yes"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ owner=zsy"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ group=zsy"
ansible test70 -m copy -a "src=/testdir/copytest dest=/opt/ mode=0640"

fetch

从远程主机提取文件至ansible的主控端,和copy相反,目前不支持目录

$ansible-doc -s fetch | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
dest  # 保存文件的目录
fail_on_missing  # bool,当源文件不存在的时候,标识为失败
flat  # bool,文件覆盖
src  # 从远程主机上获取的文件,必须是文件,不能为目录
validate_checksum  # bool,文件fetch之后进行md5检查

file

file模块可以帮助我们完成一些对文件的基本操作,比如,创建文件或目录、删除文件或目录、修改文件权限等

path  # 指定要操作的文件或目录,在之前版本的ansible中,使用dest或者name
state  # 此参数非常灵活,此参数对应的值需要根据情况设定,比如,当我们需要在远程主机中创建一个目录的时候,我们需要使用path参数指定对应的目录路径,假设,我想要在远程主机上创建/testdir/a/b目录,那么我则需要设置path=/testdir/a/b,但是,我们无法从"/testdir/a/b"这个路径看出b是一个文件还是一个目录,ansible也同样无法单单从一个字符串就知道你要创建文件还是目录,所以,我们需要通过state参数进行说明,当我们想要创建的/testdir/a/b是一个目录时,需要将state的值设置为directory,"directory"为目录之意,当它与path结合,ansible就能知道我们要操作的目标是一个目录,同理,当我们想要操作的/testdir/a/b是一个文件时,则需要将state的值设置为touch,当我们想要创建软链接文件时,需将state设置为link,想要创建硬链接文件时,需要将state设置为hard,当我们想要删除一个文件时(删除时不用区分目标是文件、目录、还是链接),则需要将state的值设置为absent,"absent"为缺席之意,当我们想让操作的目标"缺席"时,就表示我们想要删除目标
src  # 当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源
force  # 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件,不过强制创建链接文件分为两种情况,情况一:当你要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当你要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,回将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当你要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件
owner  # 用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错
group  # 用于指定被操作文件的属组,属组对应的组必须在远程主机中存在,否则会报错
mode  # 用于指定被操作文件的权限,比如,如果想要将文件权限设置为"rw-r-x---",则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的,如果你想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700,很方便吧
recurse  # 当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性
access_time
access_time_format
attributes
follow
modification_time
modification_time_format
selevel
serole
setype
seuser
unsafe_writes

示例:

#创建空文件
ansible all -m file -a 'path=/data/test.txt state=touch'
ansible all -m file -a 'path=/data/test.txt state=absent'
ansible all -m file -a "path=/root/test.sh owner=wang mode=755"
#创建目录
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
#创建软链接
ansible all -m file -a 'src=/data/testfile path|dest|name=/data/testfile-link state=link'
#创建目录
ansible all -m file -a 'path=/data/testdir state=directory'
#递归修改目录属性
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"

# 在test70主机上创建一个名为testfile的文件,如果testfile文件已经存在,则会更新文件的时间戳,与touch命令的作用相同
ansible test70 -m file -a "path=/testdir/testfile state=touch"
# 在test70主机上创建一个名为testdir的目录,如果testdir目录已经存在,则不进行任何操作
ansible test70 -m file -a "path=/testdir/testdir state=directory"
# 在test70上为testfile文件创建软链接文件,软链接名为linkfile,执行下面命令的时候,testfile已经存在
ansible test70 -m file -a "path=/testdir/linkfile state=link src=/testdir/testfile"
# 在test70上为testfile文件创建硬链接文件,硬链接名为hardfile,执行下面命令的时候,testfile已经存在
ansible test70 -m file -a "path=/testdir/hardfile state=hard src=/testdir/testfile"
# 在创建链接文件时,如果源文件不存在,或者链接文件与其他文件同名时,强制覆盖同名文件或者创建链接文件,参考上述force参数的解释
ansible test70 -m file -a "path=/testdir/linkfile state=link src=sourcefile force=yes"
# 删除远程机器上的指定文件或目录
ansible test70 -m file -a "path=/testdir/testdir state=absent"
# 在创建文件或目录的时候指定属主,或者修改远程主机上的文件或目录的属主
ansible test70 -m file -a "path=/testdir/abc state=touch owner=zsy"
ansible test70 -m file -a "path=/testdir/abc owner=zsy"
ansible test70 -m file -a "path=/testdir/abc state=directory owner=zsy"
# 在创建文件或目录的时候指定属组,或者修改远程主机上的文件或目录的属组
ansible test70 -m file -a "path=/testdir/abb state=touch group=zsy"
ansible test70 -m file -a "path=/testdir/abb group=zsy"
ansible test70 -m file -a "path=/testdir/abb state=directory group=zsy"
# 在创建文件或目录的时候指定权限,或者修改远程主机上的文件或目录的权限
ansible test70 -m file -a "path=/testdir/abb state=touch mode=0644"
ansible test70 -m file -a "path=/testdir/abb mode=0644"
ansible test70 -m file -a "path=/testdir/binfile mode=4700"
ansible test70 -m file -a "path=/testdir/abb state=directory mode=0644"
# 当操作远程主机中的目录时,同时递归的将目录中的文件的属主属组都设置为zsy
ansible test70 -m file -a "path=/testdir/abd state=directory owner=zsy group=zsy recurse=yes"

unarchive

解包解压缩

copy  # 默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上寻找src源文件
remote_src  # 和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上
src  # 源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设置copy=no
dest  # 远程主机上的目标路径
mode  # 设置解压缩后的文件权限
attributes
creates
decrypt
exclude
extra_opts
group
keep_newer
list_files
owner
selevel
serole
setype
seuser
unsafe_writes
validate_certs

示例:

ansible all -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo owner=wang group=bin'
ansible all -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
ansible all -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
ansible websrvs -m unarchive -a 'src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/data/ owner=mysql remote_src=yes'

archive

打包压缩保存在被管理节点

$ansible-doc -s archive | tail -n +3 | egrep '^[[:space:]]{6}[^[:space:]]+:' | cut -d ':' -f 1 | tr -d ' '
attributes
dest
exclude_path
force_archive
format
group
mode
owner
path
remove
selevel
serole
setype
seuser
unsafe_writes

示例:

ansible websrvs -m archive -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=wang mode=0600'

hostname

管理主机名

示例:

ansible 10.0.0.18 -m hostname -a 'name=node18.magedu.com'

cron

计划任务,支持时间:minute,hour,day,month,weekday

# 示例1 每天的1点5分输出 test 字符
5 1 * * * echo test
# 示例2 每3天执行一次计划任务,于当天的1点1分执行,具体任务为输出 test 字符
1 1 */3 * * echo test
# 示例3 每次系统启动后需要执行一次计划任务,具体任务为输出 test 字符
@reboot echo test
# 示例4 每小时执行一次计划任务,具体任务为输出 test 字符
@hourly echo test
backup  # yes|no,当修改或者删除对应的计划任务时,是否先对计划任务进行备份,如果设置为yes,cron 模块会在远程主机的 /tmp 目录下创建备份文件
cron_file
disabled  # 当计划任务有名称时,我们可以根据名称使对应的任务”失效”(注释掉对应的任务)。注意,使用此参数时,除了需要指定任务的名称,还需要同时指定任务的job 以及任务的时间设定,而且任务的时间设定必须和对应任务完全相同,否则在注释任务的同时,任务的时间设定会被修改
env
minute  # 设置计划任务中分钟设定位的值,当不使用此参数时,分钟设定位的值默认为”*”
hour  # 设置计划任务中小时设定位的值,当不使用此参数时,小时设定位的值默认为”*”
day  # 设置计划任务中日设定位的值,当不使用此参数时,日设定位的值默认为”*”
month  # 设置计划任务中月设定位的值,当不使用此参数时,月设定位的值默认为”*”
weekday  # 设置计划任务中周几设定位的值,当不使用此参数时,周几设定位的值默认为”*”
insertafter
insertbefore
job  # 此参数用于指定计划的任务中需要实际执行的命令或者脚本,比如上例中的 “echo test” 命令
name  # 此参数用于设置计划任务的名称,计划任务的名称会在注释中显示,当不指定计划任务的名称时,ansible 会默认为计划任务加入注释,注释的内容为 #Ansible: None,假设指定计划任务的名称为 test,那么注释的内容为#Ansible: test,在一台机器中,计划任务的名称应该具有唯一性,方便我们以后根据名称修改或删除计划任务
reboot
special_time  # 在上述示例3与示例4中,计划任务的时间设定格式为 @reboot 或者@hourly。@reboot 表示重启时执行,@hourly 表示每小时执行一次,相当于设置成”0 0 * * *” ,这种@开头的时间设定格式则需要使用 special_time 参数进行设置,special_time 参数的可用值有 reboot(重启后)、yearly(每年)、annually(每年,与yearly相同)、monthly(每月)、weekly(每周)、daily(每天)、hourly(每时)
# 注意:当上述时间单位设定参数都未指定时,计划任务的时间设定默认会被设定为”* * * * *”,这样表示每秒都会执行一次计划任务,所以,在使用cron模块时,我们应该确定对应的时间参数设置正确
state  # 当计划任务有名称时,我们可以根据名称修改或删除对应的任务,当删除计划任务时,需要将 state 的值设置为 absent
user  # 此参数用于设置当前计划任务属于哪个用户,当不使用此参数时,默认为管理员用户

示例:

#备份数据库脚本
[root@centos8 ~]#cat /root/mysql_backup.sh
#!/bin/bash
mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`date +%F_%T`.sql.gz
#创建任务
ansible 10.0.0.8 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate ntp.aliyun.com &>/dev/null' name=Synctime"
#禁用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes"
#启用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no"
#删除任务
ansible websrvs -m cron -a "name='backup mysql' state=absent"
ansible websrvs -m cron -a 'state=absent name=Synctime'

yum、apt

yum:管理软件包,只支持RHEL,CentOS,fedora
apt:模块管理 Debian 相关版本的软件包

yum
allow_downgrade
autoremove
bugfix
conf_file
disable_excludes
disable_gpg_check
disable_plugin
disablerepo
download_dir
download_only
enable_plugin
enablerepo
exclude
install_repoquery
install_weak_deps
installroot
list
lock_timeout
name
releasever
security
skip_broken
state  # present|installed|latest|absent|removed,installed 和 present等效,表示安装;absent 和 removed 等效,表示卸载;latest 表示安装最新版本
update_cache
update_only
use_backend
validate_certs

示例:

ansible websrvs -m yum -a 'name=httpd state=present' #安装,state可以省略
ansible websrvs -m yum -a 'name=httpd state=absent' #删除
ansible websrvs -m yum -a 'name=sl,cowsay'	# 安装
apt
allow_unauthenticated
autoclean
autoremove
cache_valid_time
deb
default_release
dpkg_options
force
force_apt_get
install_recommends
name
only_upgrade
policy_rc_d
purge
state
update_cache
update_cache_retries
update_cache_retry_max_delay
upgrade

示例:

ansible 10.0.0.100 -m apt -a 'name=bb,sl,cowsay,cmatrix,oneko,hollywood,boxes,libaa-bin,x11-apps'
ansible websrvs -m apt -a 'name=rsync,psmisc state=absent'

serivce

管理服务

arguments
enabled
name
pattern
runlevel
sleep
state
use

示例:

ansible all -m service -a 'name=httpd state=started enabled=yes'
ansible all -m service -a 'name=httpd state=stopped'
ansible all -m service -a 'name=httpd state=reloaded'
ansible all -m shell -a "sed -i 's/^Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf"
ansible all -m service -a 'name=httpd state=restarted'

user

管理用户

append
authorization
comment
create_home
expires
force
generate_ssh_key
group
groups
hidden
home
local
login_class
move_home
name
non_unique
password
password_lock
profile
remove
role
seuser
shell
skeleton
ssh_key_bits
ssh_key_comment
ssh_key_file
ssh_key_passphrase
ssh_key_type
state
system
uid
update_password
#创建用户
ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes'

#remove=yes表示删除用户及家目录等数据,默认remove=no
ansible all -m user -a 'name=nginx state=absent remove=yes'

group

管理组

gid
local
name
non_unique
state
system

示例:

#创建组
ansible websrvs -m group -a 'name=nginx gid=88 system=yes'
#删除组
ansible websrvs -m group -a 'name=nginx state=absent'

lineinfile

参考:http://www.zsythink.net/archives/2542

我们可以借助lineinfile模块,确保”某一行文本”存在于指定的文件中,或者确保从文件中删除指定的”文本”(即确保指定的文本不存在于文件中),还可以根据正则表达式,替换”某一行文本”

ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,存在问题,无法正常进行替换 。所以ansible提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换

一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块

attributes
backrefs  # backrefs=yes 表示开启后向引用,并且当正则没有匹配到任何的行时,则不会对文件进行任何操作
backup  # 是否在修改文件之前对文件进行备份
create  # 当要操作的文件并不存在时,是否创建对应的文件
firstmatch
group
insertafter  # 将文本插入到“指定的行”之后
insertbefore  # 将文本插入到“指定的行”之前
line  # 使用此参数指定文本内容
mode
others
owner
path  # 必须参数,指定要操作的文件
regexp  # 使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除
selevel
serole
setype
seuser
state  # 默认值为present,absent表示删除
unsafe_writes
validate

示例:

# 查找内容为‘xxx’的行是否存在于文件/data/test/test.sh,如果不存在,则追加此行到此文件
ansible localhost -m lineinfile -a 'path=/data/test/test.sh line=xxx'

# 正则匹配,然后替换,如果匹配到多行,但是只能替换最后一行
ansible websrvs -m lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 80'"
ansible all -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"

# 正则匹配,然后删除,如果匹配到多行,就全部删除
ansible all -m lineinfile -a 'path=/etc/fstab state=absent regexp="^#"'

replace

lineinfile 模块的主要功能是操作 in file 的 line,只能替换单行文本,多行匹配进行替换需要使用replace模块

该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用

after
attributes
backup
before
encoding
group
mode
others
owner
path
regexp
replace
selevel
serole
setype
seuser
unsafe_writes
validate

示例:

ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"
ansible all -m replace -a "path=/etc/fstab regexp='^#(UUID.*)' replace='\1'"

setup

setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no 来禁止 ansible 收集 facts 信息

playbook

  • playbook 剧本是由一个或多个”play”组成的列表
  • play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
  • Playbook 文件是采用YAML语言编写的

playbook 核心组件

  • hosts:执行的远程主机列表
  • tasks:任务集
  • variables:内置变量或自定义变量在playbook中调用
  • templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • handlers 和 notify:两者结合使用,特定条件出发操作
  • tags:标签,指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

hosts 组件

playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在inventory主机清单中

示例:

- hosts: websrvs:appsrvs

remote_user、sudo、sudo_user 组件

  • remote_usr:指定远程主机执行任务的用户
  • sudo:支持使用sudo,默认切换到root
  • sudo_user:指定使用sudo时切换的用户
- hosts: websrvs
  remote_user: root
tasks:
  - name: test connection
    ping:
    remote_user: magedu
    sudo: yes
    sudo_user:lujinkai

tasks 和 action

tasks 是task列表,每个task的类型是字典

play的主体部分是tasks,所有task依次在所有远程主机上执行,注意是同步执行而非异步执行;

task的目的是使用指定的参数执行模块,

未完待续…

handlers 和 notify

tags组件

Playbook中使用变量

两类变量:

  1. ansible 内置变量 和 自定义变量,这些变量不仅可以在 playbook 中使用,在 ansible 中任何地方都可以使用

    # 使用debug模块可以格式化输出变量
    $ansible localhost -m debug -a "msg={{hostvars}}"
  2. facts信息,来自 setup 模块收集(允许自定义),可以禁止收集,这些变量只能在 playbook 中使用

    $ansible localhost -m setup

内置变量 hostvars

在playbook中,自己主机的变量,无论是ansible内置、自定义还是facts,都可以直接调用,其他主机的变量,可以通过hostvars间接调用,例如:

# 具体事例,待补充...

常用变量

  • groups:来自ansible内置,主机列表
  • group_names:来自ansible内置,当前主机在主机列表中的所属组

playbook 中使用 when

playbook 使用迭代 with_items(loop)

当有需要重复性执行的任务时,可以使用迭代机制

对迭代项的引用,固定内置变量名为”item”

要在 task 中使用 with_items 给定要迭代的元素列表

注意: ansible2.5 版本后,可以用 loop 代替 with_items

示例:

- name: 下载 kube-master 二进制
  copy: src={{ base_dir }}/bin/{{ item }} dest={{ bin_dir }}/{{ item }} mode=0755
  with_items:
  - kube-apiserver
  - kube-controller-manager
  - kube-scheduler
  - kubectl
  tags: upgrade_k8s

迭代嵌套子变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用

示例:

- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'nginx', group: 'nginx' }
- { name: 'mysql', group: 'mysql' }
- { name: 'apache', group: 'apache' }

管理节点过多导致的超时问题解决方法

roles

roles目录结构如下所示: