ansible部署以及常用模块

ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

  1. 连接插件connection plugins:负责和被监控端实现通信;
  2. host inventory:指定操作的主机,是一个配置文件里面定义要操作的主机;
  3. 各种模块核心模块、command模块、shell模块、自定义模块;
  4. 借助于插件完成记录日志邮件等功能;playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

官网地址:

https://docs.ansible.com/

二进制文件下载地址:

https://releases.ansible.com/ansible/

参考文档:

http://www.ansible.com.cn/docs

环境准备:

主控端:192.168.170.132 centos7系统,要安装Python,否则会失败

被控端:192.168.170.134 centos7系统,要安装Python,否则会失败

被控端:192.168.170.135 centos7系统,要安装Python,否则会失败

安装:

1、首先在主控端安装ansible(被控端不需要安装),可通过yum进行安装,命令如下:

yum -y install ansible  或者 apt install ansible-core

2、在主控端配置到被控端的ssh免密登录,通过ssh-keygen与ssh-copy-id来实现快速证书的生成以及下发

方法一:

首先在主控端执行命令ssh-keygen命令,在.ssh目录下生成一对密钥,然后通过ssh-copy-id 192.168.170.134/135,然后输入密码将公钥下发的被控端,最后通过ssh 192.168.170.134/192.168.170.135测试是否可以登录。

方法二:

通过编写shell脚本来实现自动下发公钥,脚本内容如下:

上图中的ip.txt内容如下:

上图中实现自动交互输入密码主要通过expect命令实现,通过for循环遍历文件ip.txt中的内容。

使用

老版本Ansible:ansible通过定义好的主机与组规则对匹配的目标主机进行远程操作,老版本的ansible配置文件默认路径是/etc/ansible/hosts(/etc/ansible/ansible.cfg中指定的默认路径)

编辑文件,添加配置如下:

上图中的主机可以使用域名、IP、别名进行标识,其中webservers为组名,后面跟着的主机为其成员,组中的成员也可以使用域名、IP、别名进行标识。如果定义一个192.168.170.135:8000表示定义一个SSH服务端口为8000的主机

测试:

在192.168.170.132机器上,执行命令,测试ansible,如图:

上图中webservers表示组,在/etc/ansible/hosts中定义的,-a后面接主要接模块参数,-m后面接模块名

新版 Ansible:Ubuntu/Debian 的 ansible 从 Ansible 2.12+(ansible-core)​ 开始包遵循“最小侵入”原则:不自动建目录、不写空配置,Debian / Ubuntu 官方包 不再自动生成:

  • /etc/ansible
  • /etc/ansible/ansible.cfg
  • /etc/ansible/hosts

原因只有一个:避免隐式配置,强制用户明确自己的环境,虽然不创建ansible.cfg,也不影响使用,只是没那么方便,官方推荐采用项目级方式来使用ansible,创建项目目录,如下:

mkdir /data/ansible  && cd ansible-demo

在项目目录下定义ansible.cfg文件,写入文件内容,如下:

cat > ansible.cfg <<EOF

# ============================================================
# Ansible 主配置文件(项目级)
# 作用范围:当前目录及其子目录下的所有 ansible / ansible-playbook 命令
# 优先级:ANSIBLE_CONFIG > ./ansible.cfg > ~/.ansible.cfg > /etc/ansible/ansible.cfg
# ============================================================


[defaults]
# ------------------------------------------------------------
# 1. Inventory(机器清单)
# ------------------------------------------------------------
# 可以是:
#   - 单个文件:./hosts
#   - 目录(推荐):./inventory/
#   - 多个来源:./hosts,./inventory/production
#
# 生产建议:用目录,按环境拆分
inventory = ./inventory/production

# ------------------------------------------------------------
# 2. 并发与性能(生产必调)
# ------------------------------------------------------------
# 同时连接多少台主机(默认 5,生产建议 20~50)
forks = 20

# SSH / 连接超时时间(秒)
timeout = 10

# 每个任务最多重试几次(默认 3)
# 网络抖动场景可适当提高
retries = 2

# ------------------------------------------------------------
# 3. SSH 行为
# ------------------------------------------------------------
# 是否检查主机指纹(第一次连接时)
# True  = 安全,但自动化会卡住
# False = 自动化友好,内网生产常见选择
host_key_checking = False

# SSH 连接复用(大幅提升执行速度)
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey

# 管道模式(减少 Python 解释器拷贝,提升性能)
pipelining = True

# ------------------------------------------------------------
# 4. 输出与日志
# ------------------------------------------------------------
# 输出格式(推荐 yaml,比默认 JSON 可读性强)
stdout_callback = yaml

# 显示任务执行时间(排查慢任务很有用)
callback_whitelist = timer, yaml

# 是否显示被控端的差异(diff)
# 对文件/模板变更非常有用
always_show_diff = True

# 日志路径(生产强烈建议开启)
log_path = ./logs/ansible.log

# ------------------------------------------------------------
# 5. 行为与兼容性
# ------------------------------------------------------------
# 是否收集 facts(系统信息)
# 如果 playbook 不需要 {{ ansible_facts }},可设为 False 提速
gathering = smart
fact_caching = jsonfile
fact_caching_connection = ./facts_cache
fact_caching_timeout = 86400

# 是否创建失败重试文件(hosts that failed)
retry_files_enabled = False

# 默认远程用户(如果 inventory 里没指定)
remote_user = ansible

# 默认 SSH 端口(如果 inventory 里没指定)
# remote_port = 22

# ------------------------------------------------------------
# 6. 安全与权限(默认提权)
# ------------------------------------------------------------
# 默认不开启 become,由 playbook 自行决定
# 如果你希望全局默认提权,取消下面注释
# become = True
# become_method = sudo
# become_user = root

# ------------------------------------------------------------
# 7. 模块与插件
# ------------------------------------------------------------
# 角色搜索路径(多个用冒号分隔)
# roles_path = ./roles:~/.ansible/roles:/usr/share/ansible/roles

# 模块过滤(生产安全加固可选)
# 禁止危险模块(示例)
# module_blacklist = shell,command,raw


[privilege_escalation]
# ------------------------------------------------------------
# 提权配置(可被 playbook / task 级别覆盖)
# ------------------------------------------------------------
# become = True
# become_method = sudo
# become_user = root
# become_ask_pass = False


[ssh_connection]
# ------------------------------------------------------------
# SSH 连接优化(生产推荐)
# ------------------------------------------------------------
# 使用 scp 而不是 sftp(某些受限环境更稳定)
# scp_if_ssh = True

# 控制持久化连接的空闲超时
control_path = %(directory)s/%%h-%%r-%%p

# pipelining 已在 [defaults] 开启,这里无需重复


[inventory]
# ------------------------------------------------------------
# Inventory 行为
# ------------------------------------------------------------
# 忽略某些后缀文件(避免误读备份文件)
ignore_files = .git,.bak,~,.retry

# 启用 inventory 插件(2.12+ 推荐)
enable_plugins = host_list,script,auto,yaml,ini,toml


[galaxy]
# ------------------------------------------------------------
# Ansible Galaxy
# ------------------------------------------------------------
# 私有 Galaxy 服务器(企业内网)
# server = https://galaxy.example.com

EOF

✅ 优点:

  • 不污染系统
  • 多项目互不干扰
  • 最适合真实运维/CI

检查ansible.cfg文件的语法是否正确,如下:

ansible-config dump --only-changed
ansible all -m setup | head

新版本的Ansible安装后采用项目级的配置的项目目录结构推荐如下:

project/
├── ansible.cfg
├── inventory/
│   ├── production/          #自定义名字
│   │   ├── hosts.yml        #可自定义,表示机器清单
│   │   └── group_vars/      #组级别变量,固定语法,不可自定义
|   |   └── host_vars/       #主机级变量,固定语法,某台机器的特殊配置
│   └── staging/
├── playbooks/
├── roles/
├── logs/
└── facts_cache/

如果主机清单的文件后缀是yml,那么就要遵循yml的语法来写,如下:

all:                              #固定写法,老版本都是ini格式的
  children:                       #固定写法
    web:                          #自定义名字
      hosts:                      #固定写法
        192.168.1.10:
        192.168.1.11:
    db:
      hosts:
        192.168.1.20:
    proxy:
      hosts:
        192.168.1.30:

这文件只干一件事:告诉 Ansible 有哪些机器,分了什么组

inventory/production/group_vars/下的文件名必须跟hosts.yml中组名一一对应,否则不生效

group_vars/
├── all.yml        # 所有机器都生效
├── web.yml        # 只对 web 组生效
├── db.yml         # 只对 db 组生效
└── proxy.yml      # 只对 proxy 组生效

group_vars/all.yml(所有机器通用)

ansible_user: ubuntu          #远程机器的用户名
ansible_ssh_private_key_file: ~/.ssh/id_rsa #本地ansible机器私钥,公钥要先放到远程机器的authorized_keys文件中
ansible_become: true
ansible_become_method: sudo

group_vars/web.yml(只给 web 组)

http_port: 80
nginx_worker_processes: 4
app_env: production

工作流程:

1. 读 hosts.yml → 找到 web 组有 192.168.1.10、192.168.1.11
2. 读 group_vars/all.yml → 用 ubuntu 用户 + 密钥 + sudo
3. 读 group_vars/web.yml → 加载 web 组专属变量
4. 连上机器,执行命令

ansible常用模块

模块用法可在命令行使用ansible-doc -s 模块名 来获取,如图:

1、script模块

模块包括command、script、shell,都可以实现远程shell命令运行,command作为ansible默认模块,可以执行远程权限范围的所有shell命令(也可以执行脚本),script功能是在远程主机上执行主控端存储的shell脚本文件,相当于shell+script组合,shell功能是执行远程主机的shell脚本文件和命令。

例如:在远程主机135、134上执行192.168.170.132上的脚本文件test.sh,通过script模块,如图:

注意:script命令要执行的脚本是要在ansible管理机器上的,不是远程机器上

在132机器上通过ansible命令在远程主机上执行脚本test.sh,通过shell模块,如图:

注意:shell命令要执行的脚本是在远程机器上的,不是在ansible管理机器上,与script不同

2、copy模块

主要功能是从主控端向目标机器拷贝文件,与scp功能类似,常见参数如下:

  • dest:指出复制文件的目标目录位置,使用绝对路径。如果源是目录,则目标也要是目录,如果目标文件已存在,会覆盖原有内容
  • src:指出源文件的路径,可以使用相对路径和绝对路径,支持直接指定目录。如果源是目录,则目标也要是目录
  • mode:指出复制时,目标文件的权限,可选
  • owner:指出复制时,目标文件的属主,可选
  • group:指出复制时目标文件的属组,可选
  • content:指出复制到目标主机上的内容,不能和src一起使用,相当于复制content指明的数据到目标文件中
  • force: 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no
  • backup: 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no

例如:将132机器上的root目录下的copy文件,拷贝到远程组webservers对应主机的/root目录下,并设置属主以及属组以及文件权限,如图:

下面命令是将content指定的内容复制到远程主机的copy.txt文件中,如下:

#注意:远程主机上只能是文件,因为内容不可能复制到目录中,只能复制到文件中
ansible webservers -m copy -a 'content="china guagndong shenzhen" dest=/tmp/copy.txt'

3、stat模块

主要功能为获取远程文件状态信息,包括atime、ctime、mtime、md5、uid、gid信息

例子:获取远程主机的文件test.sh的时间信息,如图:

4、get_url模块

主要功能为在远程主机下载指定URL地址到本地,支持sha256sum文件校验

例如:在主控端将百度的URL下载到被控端的本地路径,如图:

5、yum模块

yum模块基于yum机制,对远程主机管理程序包。常用的参数如下 :

  • name:程序包名称,可以带上版本号。若不指明版本,则默认为最新版本;
  • state=present|latest|absent:指明对程序包执行的操作(present表明安装程序包,latest表示安装最新版本的程序包,absent表示卸载程序包)
  • disablerepo:在用yum安装时,临时禁用某个仓库的ID
  • enablerepo:在用yum安装时,临时启用某个仓库的ID
  • conf_file:yum运行时的配置文件,而不是使用默认的配置文件
  • disable_gpg_check=yes|no:是否启用完整性校验功能

例如:下面命令表示安装最新版本的httpd服务器,如图:

注意:test为组名,-i 命令意思是指定主机文件,默认情况下是读取的/etc/ansible/hosts文件,通过-i可以指定,可参考ansible常见命令行使用方式 – IT运维 (blog.ywdevops.cn)

6、cron模块

主要功能,执行远程主机的crontab配置

例子:通过主控机向被控机添加crontab定时功能,执行命令如下:

ansible webservers -m cron -a “name=’clear disk’ hour=5 job=’bash /root/aaa.sh'”

上述命令中,name表示说明此脚本是做什么的,会在crontab中作为注释存在,hour表示5个小时,job表示执行脚本位置或者执行命令,执行后在被控端查看crontab,如图;

cron模块参数如下:

  1. minute:表示设置分,不写默认为*,例如minute=5表示5分钟
  2. hour:表示时间,例如hour=5,表示5点执行
  3. day:表示日,例如:day=5表示5号执行
  4. month:表示月份,例如month=5表示5月执行
  5. weekday:表示周,例如:weekday=5表示周五执行

例如:下面的例子表示1月10号的5点零5分执行脚本,如图:

7,mount模块:

主要功能为远程主机分区挂载,

下面命令将设备/dev/sd0挂载到/mnt/data目录下,如下:

ansible webservers -m mount -a “name=/mnt/data src=/dev/sd0 fstype=ext4”

8,service 模块

主要功能为远程主机系统服务管理,常见参数如下:

  • name:被管理的服务名称
  • state=started|stopped|restarted:动作包含启动,关闭或重启
  • enable=yes|no:表示是否设置该服务开机自启动
  • runlevel:如果设定了enabled开机自启动,则要定义在哪些运行目标下自动启动

例如:通过service模块实现停止tomcat服务,执行命令如下:

9,user服务模块

主要功能为远程主机用户管理,常见参数如下:

  • name:必选参数,账号名称
  • state=present|absent:创建账号或者删除账号,present表示创建,absent表示删除
  • system=yes|no:是否为系统账户
  • uid:用户UID
  • group:用户的基本组
  • groups:用户的附加组
  • shell:默认使用的shell
  • home:用户的家目录
  • mve_home=yes|no:如果设置的家目录已经存在,是否将已存在的家目录进行移动
  • pssword:用户的密码,建议使用加密后的字符串
  • comment:用户的注释信息
  • remore=yes|no:当state=absent时,是否要删除用户的家目录

例如:下面命令表示创建一个用户,并用默认的shell(可以登录),如图:

删除用户并删除用户家目录,命令如下:

ansible test -i gong -m user -a “name=test state=absent remove=yes”

10、shell模块

可直接在远程主机执行任何linux命令和远程主机脚本,例如,查看远程主机的磁盘,如图:

shell支持管道符号、重定向的操作,command命令不支持管道和重定向

11、command模块

command模块也可以在远程主机执行Linux相关命令和远程主机脚本,但是不支持管道符号和重定向等操作,常用参数如下:

  • chdir:在远程主机上运行命令前要提前进入的目录;
  • creates:在命令运行时创建一个文件,如果文件已存在,则不会执行创建任务;
  • removes:在命令运行时移除一个文件,如果文件不存在,则不会执行移除任务;
  • executeable:指明运行命令的shell程序;

例如:运行命令前,提前进入机器的根目录,如图:

12、 hostname模块

hostname模块用于管理远程主机上的主机名 ,参数如下:

  • name:指明主机名

例如:设置远程主机的主机名为:shenzhen,执行命令如下:

13、template模块

如果你需要拷贝一个静态的文件,那么用copy 模块就够用了。但是如果你需要拷贝一个文件,并且根据需要修改部分内容, 那么就需要用到template模块,template模块同样具备设置文件属主(owner)、属组(group)、权限(mode)、备份(backup)、force(覆盖)等功能,用法可参考copy,template可通过定义yml文件方式,以playbook方式执行

例如:定义template.yml文件,copy路径templates下的file.html文件到远程机器的/tmp路径,并引用远程机器的变量,如图:

file.html文件的内容如下:

执行ansible-playbook template.yml,在远程机器192.168.226.130上查看file.html内容如下:

注意:上述中获取的变量都是facts变量,普通变量可以通过vars关键字定义,yml文件最上面的三个横杠可以不写,那么是区分多个资源文件时才需要写

14、file模块

file 模块设置远程主机上的文件、软链接(symlinks)和文件夹的权限,也可以用来创建和删除他们。(file下的所有操作都是在远程主机执行),参数如下:

  • path:必须参数,用于指定要操作的文件或目录
  • state:后面可跟touch表示创建文件、directory表示创建目录、absent表示删除文件或目录或链接文件、link表示创建链接文件
  • src:当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源
  • owner:修改文件或目录的属主
  • group:修改文件或目录的属组
  • mode:用于指定被操作文件的权限,比如,如果想要将文件权限设置为”rw-r-x---“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的。如果想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700
  • recurse参数:当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性

改变文件的权限:通过mode参数可以修改文件的权限(通过数字设置权限必须以0开头),如图:

结果如下:

创建文件的软链接,playbooks内容如下:

注意:这里面的src和dest参数的含义是和copy 模块不一样的,file模块里面所操作的文件都是远程节点上的文件

运行结果如下:

创建一个新文件,playbooks文件内容如下::

运行结果如下:

创建新的文件夹,playbooks文件内容如下:

运行结果如下:

15、systemd模块

如果使用systemctl 管理程序的话,可以使用systemd模块,systemctl 可以 控制程序启/停,reload,开机启动,观察程序状态(status)等 ,常用参数如下:

  • name: 必选,表示要管理的服务名字
  • deamon_reload:重新载入服务,值为yes或no
  • enabled :是否开机启动,值为yes或no
  • state : 管理服务状态,值为( reloaded、restarted、started、stopped )
# 刷新服务
ansible webservers -m systemd -a "deamon_reload=yes"
# 启动服务并开机启动
ansible webservers -m systemd -a "name=nginx enabled=yes state=started"
# 停止服务 开机禁止启动
ansible webservers -m systemd -a "name=nginx enabled=no state=stopped"
# 重启服务
ansible webservers -m systemd -a "name=nginx state=restarted"

16、synchronize模块

Ansible的synchronize模块是一个基于rsync的文件同步模块,它允许您在Ansible控制节点和远程主机之间同步文件和目录。这个模块特别适合于执行增量同步,只传输文件变化的部分,从而提高效率,常用参数如下:

  • src: 源文件或目录的路径
  • dest: 目标文件或目录的路径
  • mode: 同步模式,可以是push(推送模式,从控制节点向远程节点同步)或pull(拉模式,从远程节点向控制节点同步
  • rsync_opts: 传递给rsync的额外选项数组
  • compress: 是否在传输过程中启用压缩,默认为yes
  • recursive: 是否递归同步子目录,默认为yes
  • delete: 是否删除目标路径中不存在于源路径的文件,默认为no
  • checksum: 是否使用文件校验和来决定是否同步,默认为no

例如:将/data/test/目录下的目录同步到远程主机的/data/test目录,但是不包含defg目录,如下:

ansible 192.168.51.207 -m synchronize -a "src=/data/test/ dest=/data/test compress=yes rsync_opts=--exclude=defg"

注意:src=/data/test/后面需要加”/”,如果不加会把test目录名一起同步过去