puppet

SaltStack
Salt一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯。

Ansible
Ansible是新出现的运维工具是基于Python研发的糅合了众多老牌运维工具的优点实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。
在进行大规模部署时,手工配置服务器环境是不现实的,这时必须借助于自动化部署工具。

介绍

使用ansible管理网络设备 ansible 网络设备_使用ansible管理网络设备

Ansible 的命名由来?
此名取自 Ansible 作者最喜爱的《安德的游戏》小说,而这部小说更被后人改编成电影 -《战争游戏》。
大家或许早在电影中就已看过安塞波 (Ansible),它是虚构的超光速通讯装置。
片中主角安德 (Ender) 和他的伙伴们透过 Ansible 跨越时空指挥无数的战舰,就好比我们操控海量的远端服务器一样。

运维自动化工具本来是用来简化运维工作的,但如果工具本身比较复杂,甚至需要一定的程序开发能力,
就会增加使用和推广的难度。Ansible 有三个最吸引人的地方:无客户端、简单易用和 日志集中管控。
Ansible 很简单,上手方便,不需要啃一本很大本的书才能学会使用  ( 从这一点来看,这可谓业界良心)。
- 萧田国 (开放运维联盟联合主席,高效运维社区发起人 )

我希望自动化的事情尽快完成,这样我就能有更多时间投入在我更该关注的事情上面。Ansible 并不是一个你需要整天和
它打交道的系统。你可以很快地把它拿起来,很快地搞定,然后又很快地回到你更该关心的事情上面。
我希望这些也会成为你喜欢 Ansible 的原因。

- Michael DeHaan (Ansible 软件的创作者,Ansible, Inc. 前 CTO)

简而言之,现在的资讯人员 (IT Engineer) 除了要会管机器、管网络、on-call 之外,
还得要会写些自动化的工具来辅助自己,不然是难以在下一个世代生存的!

现代的 IT人 得具备十八般武艺,
从系统规划、部署 (Deployment)、开发 (Development)、测试 (QA)、运维 (Operations)、监控 (Monitoring) 到效能优化 (Performance Optimisation)
等样样都要融汇贯通。

在现代,有个叫「DevOps」的名词概括了不少技能和工具,
如 Ansible, Chef, Docker container, Git, Jenkins CI, Vagrant, Zabbix monitoring server … 等

借由虚拟化技术、云端运算和组态管理工具等,在相对快速的时间里完成任务

官方文档
https://docs.ansible.com/ansible/latest/index.html

基础介绍

ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,
实现了批量系统配置、批量程序部署、批量运行命令等功能。

Ansible可以完成哪些功能

1)批量执行远程命令,可以对N多台主机同时进行命令的执行。

2)批量配置软件服务,可以进行自动化的方式配置和管理服务。

3)实现软件开发功能,jumpserver底层使用ansible来实现的自动化管理。

4)编排高级的IT任务,Ansible的Playbook是一门编程语言,可以用来描绘一套T架构*。

ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

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

总体架构

使用ansible管理网络设备 ansible 网络设备_python_02

工作流程
第一步:
1,由ad-hoc(命令行)或者playbook传入命令预期以及要执行的主机、清单
2,ansbile框架解析相应的ad-hoc或者playbook得到host清单以及模块清单。
第二步:
1,通过匹配hosts清单得到要执行模块的远程主机由哪些。
2,通过ssh加密以及tcp链接形成安全的远程链接到匹配的主机。
第三步:
1,连接到远程主机之后,通过模块清单来调用远程主机上的python模块执行相关命令。
2,ansible将执行后的结果进行返回给操作机(观察是否达到期望预期)
特性

(1)、no agents:不需要在被管控主机上安装任何客户端;
(2)、no server:无服务器端,使用时直接运行命令即可;    (区别于其他工具的C/S 模式,这样的架构就让 ansible 变得更加易于维护)
(3)、modules in any languages:基于模块工作,可使用任意语言开发模块;
(4)、yaml,not code:使用yaml语言定制剧本playbook; (更加的易读,易懂)
(5)、ssh by default:基于SSH工作; (并发执行,加速模块,几乎所有的Linux主机都具备 ssh)
(6)、strong multi-tier solution:可实现多级指挥。

优点

(1)、轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
(2)、批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
(3)、使用python编写,维护更简单,ruby语法过于复杂;
(4)、支持sudo。

任务执行流程

使用ansible管理网络设备 ansible 网络设备_python_03

Ansible主要组成部分
ANSIBLE PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,
                   由Ansible顺序依次执行,通常是JSON格式的YAML文件
INVENTORY:Ansible管理主机的清单  /etc/anaible/hosts
MODULES:  Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
PLUGINS:  模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
API:      供第三方程序调用的应用程序编程接口 
ANSIBLE:  组合INVENTORY、API、MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具
Ansible命令执行来源:
    1> USER,普通用户,即SYSTEM ADMINISTRATOR
    2> CMDB(配置管理数据库) API 调用
    3> PUBLIC/PRIVATE CLOUD API调用  (公有私有云的API接口调用)
    4> USER-> Ansible Playbook -> Ansibile

利用ansible实现管理的方式:
    1> Ad-Hoc 即ansible单条命令,主要用于临时命令使用场景
    2> Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
Ansible-playbook(剧本)执行过程
    将已有编排好的任务集写入Ansible-Playbook
    通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行

Ansible主要操作对象
   HOSTS主机
   NETWORKING网络设备

注意事项:
   执行ansible的主机一般称为主控端,中控,master或堡垒机
   主控端Python版本需要2.6或以上
   被控端Python版本小于2.4需要安装python-simplejson
   被控端如果开启SELinux需要安装libselinux-python
   windows不能做为主控端
   ansible不是服务,不会一直启动,只是需要的时候启动

实验环境

主机名

ip

ansible1

192.168.245.180

ansible2

192.168.245.181

ansible3

192.168.245.182

安装

rpm包安装: EPEL源
    yum install ansible

编译安装:
    yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
    tar xf ansible-1.5.4.tar.gz
    cd ansible-1.5.4
    python setup.py build
    python setup.py install
    mkdir /etc/ansible
    cp -r examples/* /etc/ansible


Git方式:
    git clone git://github.com/ansible/ansible.git --recursive
    cd ./ansible
    source ./hacking/env-setup

pip安装: pip是安装Python包的管理器,类似yum
    yum install python-pip python-devel
    yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
    pip install --upgrade pip
    pip install ansible --upgrade

确认安装:
    ansible --version

我采用的是epel源yum安装

[root@ansible1 opt]# cd /opt/
[root@ansible1 opt]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@ansible1 opt]# yum clean all
[root@ansible1 opt]# yum makecache
[root@ansible1 opt]# yum -y install ansible   # 安装
[root@ansible1 opt]# ansible --version   # 验证版本
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg   # 配置文件
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']   # 模块存放
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
相关文件
配置文件
    /etc/ansible/ansible.cfg  主配置文件,配置ansible工作特性(一般无需修改)
    /etc/ansible/hosts        主机清单(将被管理的主机放到此文件)
    /etc/ansible/roles/       存放角色的目录

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

ansible 配置文件

Ansible 配置文件/etc/ansible/ansible.cfg (一般保持默认)

vim /etc/ansible/ansible.cfg

[defaults]
#inventory     = /etc/ansible/hosts      # 主机列表配置文件
#library       = /usr/share/my_modules/  # 库文件存放目录
#remote_tmp    = $HOME/.ansible/tmp      # 临时py命令文件存放在远程主机目录
#local_tmp     = $HOME/.ansible/tmp      # 本机的临时命令执行目录  
#forks         = 5                       # 默认并发数,同时可以执行5次
#sudo_user     = root                    # 默认sudo 用户
#ask_sudo_pass = True                    # 每次执行ansible命令是否询问ssh密码
#ask_pass      = True                    # 每次执行ansible命令是否询问ssh口令
#remote_port   = 22                      # 远程主机的端口号(默认22)

建议优化项: 
host_key_checking = False               # 检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log           # 日志文件,建议取消注释
module_name   = command                 # 默认模块
配置文件优先级

ANSIBLE_CONFIG环境变量指定的任何文件将覆盖所有其他配置文件。如果没有设置该变量,则接下来检查运行ansible命令的目录中是否有ansible.cfg文件。如果不存在该文件,则检查用户的家目录是否有 .ansible.cfg文件。只有在找不到其他配置文件时,才使用全局 /etc/ansible/ansible.cfg文件。如果 /etc/ansible/ansible.cfg配置文件不存在,Ansible包含它使用的默认值。
Ansible仅使用具有最高优先级的配置文件中的设置。即使存在优先级较低的其他配置文件,其设置也会被忽略,不会与选定配置文件中的设置结合。因此,如果你选择自行创建配置文件来取代全局 /etc/ansible/ansible.cfg配置文件,就需要将该文件中所有需要的设置复制到自己的用户级配置文件中。用户组配置文件中未定义的设置将保持设为内置默认值,即使已在全局配置文件中设为某个其他值也是如此。

总结:ANSIBLE_CONFIG环境变量 > 当前目录下的ansible.cfg > ~/.ansible.cfg(家目录) > /etc/ansible/ansible.cfg

修改配置文件
[root@ansible1 ansible]# cp /etc/ansible/hosts /etc/ansible/hosts.bak   # 备份配置文件
[root@ansible1 ansible]# grep -Ev "#|^$" ansible.cfg 
[defaults]
host_key_checking = False
log_path = /var/log/ansible.log
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
# 部分主要配置解释
#inventory      = /etc/ansible/hosts      #主机列表配置文件
#library        = /usr/share/my_modules/  #库文件存放目录
#remote_tmp     = ~/.ansible/tmp          #临时py文件存放在远程主机目录
#local_tmp      = ~/.ansible/tmp          #本机的临时执行目录
#forks          = 5                       #默认并发数
#sudo_user      = root                    #默认sudo用户
#ask_sudo_pass = True                     #每次执行是否询问sudo的ssh密码
#ask_pass      = True                     #每次执行是否询问ssh密码
#remote_port    = 22                      #远程主机端口
host_key_checking = False                 #跳过检查主机指纹
log_path = /var/log/ansible.log           #ansible日志

[privilege_escalation]					#如果是普通用户则需要配置提权
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False

# 有个发送密钥的配置项,不建议开,如下图

使用ansible管理网络设备 ansible 网络设备_CICD_04

主机清单inventory

Inventory 主机清单
1> ansible的主要功能在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名 
2> 默认的inventory file为/etc/ansible/hosts
3> inventory file可以有多个,且也可以动态生成

/etc/ansible/hosts文件格式
inventory文件遵循INI文件风格,中括号中的字符为组名。
可以将同一个主机同时归并到多个不同的组中;
此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明
    ntp.lin.com   不分组,直接加
    
    [webservers]     webservers组
    www1.lin.com:2222  可以指定端口
    www2.lin.com
    
    [dbservers]
    db1.lin.com
    db2.lin.com
    db3.lin.com

如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机
示例:
    [websrvs]
    www[1:100].example.com   ip: 1-100
    
    [dbsrvs]
    db-[a:f].example.com     dba-dbf
配置主机清单

以下有不同的写法,先举例再搭建

1.场景一、基于密码连接
[root@ansible1 ~]# cat /etc/ansible/hosts
#方式一、主机+端口+密码
[webservers]
172.16.1.7 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'
172.16.1.8 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'

#方式二、域名+密码
[webservers]
web[1:2].ansible ansible_ssh_pass='123456'

#方式三、域名组+密码组
[webservers]
web[1:2].ansible
[webservers:vars]			#给webservers主机组设置共用变量
ansible_ssh_pass='123456'
2.场景二、基于密钥连接

需要先创建公钥和私钥,并下发公钥至被控端

[root@ansible1 ~]# ssh-keygen
[root@ansible1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.7
[root@ansible1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.8

-----------------------------------------------------------
[root@ansible1 ~]# cat hosts 
#方式一、主机+端口+密钥
[webservers]
172.16.1.7
172.16.1.8

[root@ansible1 ~]# ansible webservers -m ping -i ./hosts 
172.16.1.8 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
172.16.1.7 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

-----------------------------------------------------------
[root@ansible1 ~]# cat hosts 	
#方式二、域名+主机+端口+密钥					#使用域名时,一定要注意/etc/hosts文件
[webservers]
web01 ansible_ssh_host=172.16.1.7 ansible_ssh_port=22
web02 ansible_ssh_host=172.16.1.8


[root@ansible1 ~]# ansible webservers -m ping -i ./hosts 
web02 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
web01 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
--------------------------------------------------
场景三、主机组使用方式
#1.定义两个组
[web]
192.168.245.181
192.168.245.182

[db]
192.168.245.183
[rsync]
192.168.245.184

#2.data组包括两个子组[db,web]
[data:children]
db
web

[webserver:children]
data
采用免密方式搭建(第一种)

设置免密

[root@ansible1 ansible]# ssh-keygen -t RSA -N '' -f ~/.ssh/id_rsa
[root@ansible1 ansible]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.188.21
[root@ansible1 ansible]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.245.181
[root@ansible1 ansible]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.245.182
[root@ansible1 ansible]# ssh 192.168.245.181
[root@ansible1 ansible]# ssh 192.168.245.182

原因方便和安全

[root@ansible1 ansible]# cp /etc/ansible/hosts /etc/ansible/hosts.bak   # 先备份原配置
[root@ansible1 ansible]# vim /etc/ansible/hosts 
[root@ansible1 ansible]# grep -Ev "#|^$" /etc/ansible/hosts
[web]
192.168.245.181
[db]
192.168.245.182

验证

[root@ansible1 ansible]# ansible web -m ping -i ./hosts   # ping一下web组的主机

[root@ansible1 ansible]# ansible db -m ping -i ./hosts   # ping一下db组的主机

[root@ansible1 ansible]# ansible all -m ping -i ./hosts   # ping一下所有组的主机

# 成功如下图

使用ansible管理网络设备 ansible 网络设备_配置文件_05

第二种写法
[root@ansible1 ansible]# vim /etc/ansible/hosts 
[root@ansible1 ansible]# grep -Ev "#|^$" /etc/ansible/hosts
[webservers]
web01 ansible_ssh_host=192.168.245.181 ansible_ssh_port=22
web02 ansible_ssh_host=192.168.245.182
[root@ansible1 ansible]# ansible webservers -m ping -i ./hosts

使用ansible管理网络设备 ansible 网络设备_使用ansible管理网络设备_06

第三种写法(子组)
[root@ansible1 ansible]# vim /etc/ansible/hosts 
[root@ansible1 ansible]# grep -Ev "#|^$" /etc/ansible/hosts
[web1]
web01 ansible_ssh_host=192.168.245.181
[web2]
web02 ansible_ssh_host=192.168.245.182
[server:children]
web1
web2
[root@ansible1 ansible]# ansible server -m ping -i ./hosts

使用ansible管理网络设备 ansible 网络设备_使用ansible管理网络设备_07

[root@ansible1 opt]# ansible all -m ping -i /etc/ansible/hosts --list-hosts   # 列出当前某个组有多少台主机
  hosts (2):
    192.168.245.181
    192.168.245.182

ansible基本命令

ansible通过ssh实现配置管理、应用部署、任务执行等功能,
建议配置ansible端能基于密钥认证的方式联系各被管理节点
语法:
ansible <host-pattern> [-m module_name] [-a args]
ansible +被管理的主机(ALL) +模块  +命令
    --version              显示版本
    -m module              指定模块,默认为command
    -a 					   后接命令
    -v                     详细过程 –vvv -vvvv为“debug模式”
    --list-hosts           显示主机列表,可简写 --list
    -k, --ask-pass         提示输入ssh连接密码,默认Key验证
    -i 					   后接inventory文件(自定义路径)
    -C, --check            检查,并不执行
    -T, --timeout=TIMEOUT  执行命令的超时时间,默认10s
    -u, --user=REMOTE_USER 执行远程执行的用户
    -b, --become           代替旧版的sudo切换
        --become-user=USERNAME 指定sudo的runas用户,默认为root
    -K, --ask-become-pass  提示sudo用户密码

ansible all --list  列出所有主机
ping模块: 探测网络中被管理主机是否能够正常使用  走ssh协议
          如果对方主机网络正常,返回pong
ansible-doc -s ping   查看ping模块的语法 

检测所有主机的网络状态
1>  默认情况下连接被管理的主机是ssh基于key验证,如果没有配置key,权限将会被拒绝
    因此需要指定以谁的身份连接,输入用户密码,必须保证被管理主机用户密码一致
    ansible all -m ping -k

2> 或者实现基于key验证 将公钥ssh-copy-id到被管理的主机上 , 实现免密登录
   ansible all -m ping
ansible系列命令1
Ansible系列命令
    ansible ansible-doc ansible-playbook ansible-vault ansible-console
    ansible-galaxy ansible-pull

ansible-doc: 显示模块帮助
    ansible-doc [options] [module...]
        -a            显示所有模块的文档
        -l, --list    列出可用模块
        -s, --snippet 显示指定模块的playbook片段(简化版,便于查找语法)

示例:
    ansible-doc -l      列出所有模块
    ansible-doc ping    查看指定模块帮助用法
    ansible-doc -s ping 查看指定模块帮助用法
ansible系列命令2
可以通过网上写好的
ansible-galaxy
    > 连接 https://galaxy.ansible.com 
      下载相应的roles(角色)
    
    > 列出所有已安装的galaxy
        ansible-galaxy list
    
    > 安装galaxy
        ansible-galaxy install geerlingguy.redis
    
    > 删除galaxy
        ansible-galaxy remove geerlingguy.redis
        
ansible-pull
    推送命令至远程,效率无限提升,对运维要求较高
    

ansible-playbook  可以引用按照标准的yml语言写的脚本
    执行playbook
    示例:ansible-playbook hello.yml
        cat hello.yml
        #hello world yml file
        - hosts: websrvs
          remote_user: root
          tasks:
            - name: hello world
              command: /usr/bin/wall hello world

ansible-vault  (了解)
功能:管理加密解密yml文件
    ansible-vault [create|decrypt|edit|encrypt|rekey|view]
        ansible-vault encrypt hello.yml 加密
        ansible-vault decrypt hello.yml 解密
        ansible-vault view hello.yml    查看
        ansible-vault edit hello.yml    编辑加密文件
        ansible-vault rekey hello.yml   修改口令
        ansible-vault create new.yml    创建新文件


Ansible-console:2.0+新增,可交互执行命令,支持tab  (了解)

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

    设置并发数:         forks n   例如: forks 10
    切换组:             cd 主机组 例如: cd web
    列出当前组主机列表: list
    列出所有的内置命令: ?或help
    示例:
        root@all (2)[f:5]$ list
        root@all (2)[f:5]$ cd appsrvs
        root@appsrvs (2)[f:5]$ list
        root@appsrvs (2)[f:5]$ yum name=httpd state=present
        root@appsrvs (2)[f:5]$ service name=httpd state=started
ansible的Host-pattern
ansible的Host-pattern
匹配主机的列表
    All :表示所有主机清单中的所有主机
        ansible all -m ping
    * :通配符
        ansible "*" -m ping  (*表示所有主机)
        ansible 192.168.1.* -m ping
        ansible "*srvs" -m ping
    或关系 ":"
        ansible "websrvs:appsrvs" -m ping
        ansible "192.168.1.10:192.168.1.20" -m ping
        在websrvs组或者在dbsrvs组中的主机
    逻辑与 ":&"
        ansible "websrvs:&dbsrvs" -m ping
        在websrvs组并且在dbsrvs组中的主机
    逻辑非 ":!"
        ansible 'websrvs:!dbsrvs' -m ping
        在websrvs组,但不在dbsrvs组中的主机
        注意:此处为单引号	也可以在!前加转义符\
        
    综合逻辑
        ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' -m ping
    正则表达式
        ansible "~(web|db).*\.lin\.com" -m ping
        		web.lin.com
ansible命令执行过程
ansible命令执行过程
    1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg
    2. 加载自己对应的模块文件,如command
    3. 通过ansible将模块或命令生成对应的临时py文件,
       并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
    4. 给文件+x执行
    5. 执行并返回结果
    6. 删除临时py文件,sleep 0退出

执行状态:
    绿色:执行成功并且不需要做改变的操作
    黄色:执行成功并且对目标主机做变更
    红色:执行失败
    
# 去其他机子ps会发现有进程在运行
[root@ansible2 opt]# ps -ef | grep yum
root      10608  10531  0 16:45 pts/1    00:00:00 /bin/sh -c /usr/bin/python /root/.ansible/tmp/ansible-tmp-1650271497.65-10690-151938432124301/AnsiballZ_yum.py && sleep 0
root      10619  10608  5 16:45 pts/1    00:00:00 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1650271497.65-10690-151938432124301/AnsiballZ_yum.py
root      10626   1133  0 16:45 pts/0    00:00:00 grep --color=auto yum
注意

1. 返回信息:红色是错误,黄色是系统发生变化(比如yum)、动态变化(用shell模块进行创文件),绿色是静态(ping)  ==> 一般是按照未来是否发生改变来判定

使用ansible管理网络设备 ansible 网络设备_Ansible_08

使用ansible管理网络设备 ansible 网络设备_Ansible_09

使用ansible管理网络设备 ansible 网络设备_Ansible_10

2. 紫色是警告

使用ansible管理网络设备 ansible 网络设备_Ansible_11

ansible使用示例
示例
    以wang用户执行ping存活检测
        ansible all -m ping -u wang -k
    以wang sudo至root执行ping存活检测
        ansible all -m ping -u wang -k -b
    以wang sudo至abc用户执行ping存活检测
        ansible all -m ping -u wang -k -b --become-user=abc
    以wang sudo至root用户执行ls
        ansible all -m command -u wang -a 'ls /root' -b --become-user=root -k -K

ansible ping模块测试连接
    ansible 192.168.38.126,192.168.38.127 -m ping -k
帮助手册

使用过程中需要先了解ansible-doc帮助手册

[root@ansible1 opt]# ansible-doc -l   # 查看所有模块说明

[root@ansible1 opt]# ansible-doc -s copy   # 表示指定模块参数

[root@ansible1 ansible]# ansible-doc yum   # ansible-doc 模块名
# 进去输入/,再输入EXA找到案例

模块

Ad-Hoc,常用模块
command             # 执行shell命令(不支持管道等特殊字符)
shell               # 执行shell命令
script             # 执行shell脚本
yum_repository      # 配置yum仓库
联网下载		get_url
安装			yum(ansible all -m yum -a "name=iftop state=present")
配置			copy
启动			service、systemd
创建用户与组	user、group
授权			file
定时任务		crond
挂载			mount
command默认执行bash命令模块

command默认执行bash命令模块,模块不支持重定向或管道

[root@ansible1 opt]# ansible web1 -m command -a "hostname"
192.168.188.31 | CHANGED | rc=0 >>
ansible2

command不能接管道;shell会暂时把权限提升到最高而且如果有漏洞很可能被入侵

shell远程主机上执行命令
[root@ansible1 opt]# ansible web1 -m shell -a "ps -ef |grep ssh"
192.168.188.31 | CHANGED | rc=0 >>
root        859      1  0 14:15 ?        00:00:00 /usr/sbin/sshd -D

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

    修改配置文件,使shell作为默认模块    
        vim /etc/ansible/ansible.cfg
        module_name = shell
script远程主机运行本地脚本
# script模块
# 作用:在远程主机运行本地的脚本;
# 调用格式:
# -m script -a "/PATH/TO/SCRIPT_FILE";
# 参数:
# creates:如果其后跟的文件存在,则不执行脚本;
# removes:如果其后跟的文件存在,则执行脚本;

[root@ansible1 opt]# cat /opt/test.sh 
#!/bin/bash
echo "hello word"
# 在本地运行模块,等同于在远程执行,不需要将脚本文件进行推送目标主机执行
[root@ansible1 opt]# ansible web1 -m script -a '/opt/test.sh'
192.168.188.31 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.188.31 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.188.31 closed."
    ], 
    "stdout": "hello word\r\n", 
    "stdout_lines": [
        "hello word"
    ]
}
yum安装软件模块
name        						
	httpd							#指定要安装的软件包名称,多个用“,”隔开
	file://							#指定从本地哪个目录安装rpm
	http://							#指定从哪个网站安装rpm包
state       						#指定使用yum的方法
				present 或installed #安装软件包
				absent 或remove     #移除软件包
				latest				#安装最新软件包 
list=ansible						#列出当前仓库可用的软件包
enablerepo=epel						#通过epel仓库安装,如果仓库关闭,也会临时开启
disablerepo="epel,local"		   #安装软件时,不从哪些仓库获取
download_only=true					#仅下载软件包,不安装
exclude=xxx							#排除某包
disable_gpg_check					#默认为no,即为开启检查
[root@ansible1 ansible]# rpm -qa | grep tree
[root@ansible1 ansible]# ansible all -m yum -a "name=tree state=present"   # 返回信息是黄色

#使用epel源安装htop软件包,并关闭gpg_key检查
[root@ansible1 yum.repos.d]# ansible test -m yum -a "name=htop enablerepo=epel state=present disable_gpg_check=yes"

#使用epel源只下载一个软件包(自选)
yum_repository配置yum源仓库
name 		#yum源的名字
baseurl 	#仓库路径
file		#指定yum配置文件的路径和名称 注意不需要以.repo结尾 默认使用name的内容作为文件名
enabled 	yes/no 是否开启yum源  默认是yes 开启
state 		#absent(删除)/present(默认为安装)
description	#描述信息




# 2号机没有epel源
[root@ansible2 opt]# ls /etc/yum.repos.d/
bak  CentOS-Base.repo  local.repo
# ansible批量创建yum源仓库(额外内容:需要添加gpgkey)
[root@ansible1 yum.repos.d]# ansible test -m yum_repository -a "name=epel baseurl=http://mirrors.aliyun.com/epel/7/$basearch enabled=0 description='Extra Packages for Enterprise Linux 7 - $basearch' "

[root@ansible1 yum.repos.d]# ansible test -a "cat /etc/yum.repos.d/epel.repo"
192.168.245.182 | CHANGED | rc=0 >>
[epel]
baseurl = http://mirrors.aliyun.com/epel/7/				#缺失变量
enabled = 0
name = Extra Packages for Enterprise Linux 7 - 			#缺失变量
192.168.245.181 | CHANGED | rc=0 >>
[epel]
baseurl = http://mirrors.aliyun.com/epel/7/
enabled = 0
name = Extra Packages for Enterprise Linux 7 - 


[root@ansible1 ansible]# ansible test -m yum_repository -a "name=epel baseurl=http://mirrors.aliyun.com/epel/7/\$basearch enabled=0 description='Extra Packages for Enterprise Linux 7 - \$basearch' "					#模块不支持使用变量,需要用转义符
192.168.188.32 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "repo": "epel", 
    "state": "present"
}
192.168.188.31 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "repo": "epel", 
    "state": "present"
}
# 此时再检查已经创建好
[root@ansible2 opt]# ls /etc/yum.repos.d/
bak  CentOS-Base.repo  epel.repo  local.repo
# 当ansible重新更改epel里面的内容会覆盖掉
get_url文件下载模块
dest		#到目标地址
url			#下载路径
src  		#源文件  
dest		#指定目标路径
mode 		#设置权限
checksum	#校验(md5  sha256)


1.通过get_url下载文件或者软件
[root@ansible1 yum.repos.d]# ansible 192.168.245.181 -m get_url -a "url=http://nginx.org/download/nginx-1.20.2.tar.gz dest=/opt mode=777"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum_dest": null, 
    "checksum_src": "59888fdeb78eec4979a8df89a80b43ee84b73eb7", 
    "dest": "/opt/nginx-1.20.2.tar.gz", 
    "elapsed": 1, 
    "gid": 0, 
    "group": "root", 
    "md5sum": "3bcc5ccdc052c35d0d3c5557cf56c7d2", 
    "mode": "0777", 
    "msg": "OK (1062124 bytes)", 
    "owner": "root", 
    "size": 1062124, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666233107.4-1751-92028453301044/tmp3Y01Jm", 
    "state": "file", 
    "status_code": 200, 
    "uid": 0, 
    "url": "http://nginx.org/download/nginx-1.20.2.tar.gz"
}


2.对一个文件先进行md5校验
[root@ansible2 opt]# md5sum nginx-1.20.2.tar.gz
3bcc5ccdc052c35d0d3c5557cf56c7d2  nginx-1.20.2.tar.gz

3.使用ansible下载文件,通过则下载,不通过则不下载
ansible 192.168.245.181 -m get_url -a "url=http://nginx.org/download/nginx-1.20.2.tar.gz dest=/opt mode=777 checksum=md5:3bcc5ccdc052c35d0d3c5557cf56c7d2 "
# 下载图片到主机清单里面的机子并指定目录与权限
[root@ansible1 ansible]# ansible all -m get_url -a "url=https://images.anime-pictures.net/091/0910ba3ebc65f07a718b15705ede599e.jpeg?if=ANIME-PICTURES.NET_-_649260-2382x3573-tensei+shitara+slime+datta+ken-8bit-rimuru+tempest-junkt729-single-long+hair.jpeg dest=/opt/ mode='0644'"
# 下载图片到主机清单里面的机子、指定目录并改名与权限
[root@ansible1 ansible]# ansible all -m get_url -a "url=https://images.anime-pictures.net/091/0910ba3ebc65f07a718b15705ede599e.jpeg?if=ANIME-PICTURES.NET_-_649260-2382x3573-tensei+shitara+slime+datta+ken-8bit-rimuru+tempest-junkt729-single-long+hair.jpeg dest=/opt/图片.jpeg mode='0644'"

使用ansible管理网络设备 ansible 网络设备_配置文件_12

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

1.copy文件拷贝模块
#1.拷贝文件文件至被控节点
[root@ansible1 yum.repos.d]# ansible 192.168.245.181 -m copy -a "src=/etc/hosts dest=/opt/ mode=600"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "35103ab3645ce6aaff9e923c035b9364800a8432", 
    "dest": "/opt/hosts", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "54ab6dbd73fb188db9614ca77008bc30", 
    "mode": "0600", 
    "owner": "root", 
    "size": 216, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666235917.0-2154-42402630981833/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible1 yum.repos.d]# ansible 192.168.245.181 -a "ls /opt"
192.168.245.181 | CHANGED | rc=0 >>
0910ba3ebc65f07a718b15705ede599e.jpeg
a.txt
base.sh
b.txt
hostname.sh
hosts
roles
图片.jpeg

#2.对远端已有文件进行备份,按照时间信息备份
[root@ansible1 ~]# ansible 192.168.245.181 -m copy -a "content='this is a good day' dest=/opt/hosts mode=600 backup=yes"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/opt/hosts.4158.2022-10-20@11:23:46~", 
    "changed": true, 
    "checksum": "eaf28278e6dccce4c32a99e73210382b35df1481", 
    "dest": "/opt/hosts", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5613384ade73a91c3cedf83743f61704", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666236225.83-2305-229613384813654/source", 
    "state": "file", 
    "uid": 0
}

[root@ansible1 ~]# ansible 192.168.245.181 -a "ls /opt"
192.168.245.181 | CHANGED | rc=0 >>
0910ba3ebc65f07a718b15705ede599e.jpeg
a.txt
base.sh
b.txt
hostname.sh
hosts
hosts.4158.2022-10-20@11:23:46~
roles
图片.jpeg


#3.向被控端主机写入数据,并且会覆盖远端文件内原有数据信息
[root@ansible1 ~]# ansible 192.168.245.181 -m copy -a "content='this is a good day' dest=/opt/a.txt mode=600"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "eaf28278e6dccce4c32a99e73210382b35df1481", 
    "dest": "/opt/a.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5613384ade73a91c3cedf83743f61704", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666236099.76-2253-41121094243075/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible1 ~]# ansible 192.168.245.181 -a "cat /opt/a.txt"
192.168.245.181 | CHANGED | rc=0 >>
this is a good day


#4.将管理主机上的数据信息传送给多台主机并改名
[root@ansible1 ~]# ansible 192.168.245.181 -m copy -a "src=/etc/hosts dest=/opt/a_hosts mode=600"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "35103ab3645ce6aaff9e923c035b9364800a8432", 
    "dest": "/opt/a_hosts", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "54ab6dbd73fb188db9614ca77008bc30", 
    "mode": "0600", 
    "owner": "root", 
    "size": 216, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666236442.77-2400-239949733288490/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible1 ~]# ansible 192.168.245.181 -a "ls /opt"
192.168.245.181 | CHANGED | rc=0 >>
a_hosts
# 差值拷贝
# 会在远程机子创建一个文件名加时间戳的文件,就是新的文件有差异的,需要远程机子有hosts文件而且修改再推送就会出现
[root@ansible1 ~]# ansible 192.168.245.181 -m copy -a "content='this is a good day' dest=/opt/hosts mode=600 "	#没添加backup
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/opt/hosts.4701.2022-10-20@11:29:43~", 
    "changed": true, 
    "checksum": "eaf28278e6dccce4c32a99e73210382b35df1481", 
    "dest": "/opt/hosts", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5613384ade73a91c3cedf83743f61704", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666236582.42-2474-264212795682500/source", 
    "state": "file", 
    "uid": 0
}


[root@ansible2 ~]# echo "this is a bad day" >> /opt/hosts 
[root@ansible1 ~]# ansible 192.168.245.181 -m copy -a "content='this is a good day' dest=/opt/hosts mode=600 backup=yes"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/opt/hosts.4701.2022-10-20@11:29:43~", 
    "changed": true, 
    "checksum": "eaf28278e6dccce4c32a99e73210382b35df1481", 
    "dest": "/opt/hosts", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5613384ade73a91c3cedf83743f61704", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666236582.42-2474-264212795682500/source", 
    "state": "file", 
    "uid": 0
}
# 可以创建文件和覆盖文件内容
[root@ansible1 ~]# ansible all -m copy -a "content='GuangZhou' dest=/opt/test3.text"
Fetch文件拉取模块
src             #推送数据的源文件信息
dest            #推送数据的目标路径
从远程主机提取文件至主控端,copy相反,目前不支持目录,可以先打包,再提取文件  ansible websrvs -m fetch -a 'src=/root/test.sh dest=/data/scripts'

会生成每个被管理主机不同编号的目录,不会发生文件名冲突
ansible all -m shell -a 'tar jxvf test.tar.gz /root/test.sh'
     > ansible all -m fetch -a 'src=/root/test.tar.gz dest=/data/'
file文件创建模块
path            #指定远程主机目录或文件
src             #推送数据的源文件信息
dest            #推送数据的目标路径
recurse         #递归授权
state           #状态
    directory   #在远端创建目录
    touch       #在远端创建文件
    link        #创建链接文件
    hard		#硬链接
    absent      #表示删除文件或目录
    mode        #设置文件或目录权限
    owner       #设置文件或目录属主
    group       #设置文件或目录属组

1.直接修改被控端的权限
[root@ansible1 ~]# ansible 192.168.245.181 -m file -a "dest=/opt/b.txt mode=600 state=touch "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/b.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0600", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}


2.在被控端创建目录
[root@ansible1 ~]# ansible 192.168.245.181 -m file -a "dest=/opt/abc state=directory "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/opt/abc", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

3.在被控端创建文件
[root@ansible1 ~]# ansible 192.168.245.181 -m file -a "dest=/opt/a.txt state=touch "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/a.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}


4.递归授权目录权限
[root@ansible1 ~]# ansible 192.168.245.181 -m file -a "dest=/opt/abc mode=600  recurse=yes"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0600", 
    "owner": "root", 
    "path": "/opt/abc", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

5.删除文件或目录
[root@ansible1 opt]# ansible 192.168.245.181 -m file -a "path=/opt/a.txt  state=absent"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/opt/a.txt", 
    "state": "absent"
}

[root@ansible2 opt]# ll
总用量 0
drw------- 2 root root  6 10月 20 11:41 abc
-rw------- 1 root root  0 10月 20 11:43 b.txt

6.软链接
[root@ansible1 opt]# ansible 192.168.245.181 -m file -a "src=/opt/a.txt dest=/opt/c.txt state=link"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/c.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/opt/a.txt", 
    "state": "link", 
    "uid": 0
}

[root@ansible2 opt]# ll
总用量 0
drw------- 2 root root  6 10月 20 11:41 abc
-rw------- 1 root root  0 10月 20 11:43 b.txt
lrwxrwxrwx 1 root root 10 10月 20 14:25 c.txt -> /opt/a.txt


或者
[root@ansible1 opt]# ansible 192.168.245.181 -m file -a "src=/opt/b.txt path=/opt/d.txt  state=link"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/d.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/opt/b.txt", 
    "state": "link", 
    "uid": 0
}

[root@ansible2 opt]# ll
总用量 0
drw------- 2 root root  6 10月 20 11:41 abc
-rw-r--r-- 1 root root  0 10月 20 11:39 a.txt
-rw------- 1 root root  0 10月 20 11:43 b.txt
lrwxrwxrwx 1 root root 10 10月 20 14:25 c.txt -> /opt/a.txt
lrwxrwxrwx 1 root root 10 10月 20 14:28 d.txt -> /opt/b.txt


# 两种写法
# 默认是软连接,state=hard是硬链接


7.硬链接
user模块
name			#用户名
uid             #指定用户的uid
group           #指定用户组名称
groups          #指定附加组名称
password        #给用户添加密码(记得单引号)
shell           #指定用户登录shell
create_home     #是否创建家目录
comment			#注释内容 
state			#present(创建)/absent(移除,但不会删除家目录)
remove			#清除账号(删除家目录)

1.创建用户指定uid和gid,不创建家目录也不允许登陆
[root@ansible1 opt]# ansible 192.168.245.181 -m user -a "name=abc uid=666 shell=/sbin/nologin create_home=no "

2.删除用户
[root@ansible1 opt]# ansible 192.168.245.181 -m user -a "name=abc state=absent "

3.清除用户,查看家目录是否存在
ansible 192.168.245.181 -m user -a "name=abc state=absent remove=yes"

4.给新创建的用户生成ssh密钥对(了解)
[root@ansible1 ~]# ansible 192.168.245.181 -m user -a "name=oo uid=6677 group=adm generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa" -i ./hosts 

5.将明文密码进行hash加密,然后进行用户创建
[root@ansible1 ~]# ansible localhost -m debug -a "msg={{ '123456' | password_hash('sha512', 'salt') }}"
localhost | SUCCESS => {
    "msg": "$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w.igcOo1R7vBYR65JquIQ/7siC7VRpmteKvZmfSkNc69."
}
[root@ansible1 ~]# ansible webservers -m user -a 'name=xlw password=$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w.igcOo1R7vBYR65JquIQ/7siC7VRpmteKvZmfSkNc69. create_home=yes shell=/bin/bash' -i ./hosts 


    安装mkpasswd 
    yum insatll expect 
    mkpasswd 生成口令
    openssl passwd -1  生成加密口令

指定密码生成,但是ansible不允许明文输入,所以需要密文输入,密文输入请参考这篇文章;也可以采用上面的方法

group组模块
name            #指定创建的组名
gid             #指定组的gid
state
    absent      #移除远端主机的组
    present     #创建远端主机的组(默认)

1.创建组名www,并设置gid为777
[root@ansible1 ~]# ansible web1 -m group -a "name=www gid=777" 

# 验证
[root@ansible2 ~]# tail -1 /etc/group
www:x:777:

2.修改www组的gid为888
[root@ansible1 ~]# ansible web1 -m group -a "name=www gid=888" 

# 验证
[root@ansible2 ~]# tail -2 /etc/group
shy2:x:1001:
www:x:888:

3. 删除组
[root@ansible1 ~]# ansible web1 -m group -a "name=www gid=888 state=absent"
Archive:打包压缩模块
将远程主机目录打包 
        path:   指定路径
        dest:   指定目标文件
        format: 指定打包格式
        owner:  指定所属者
        mode:   设置权限

#将ansible2上的/etc/sysconfig以bz2压缩包打包
ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777'
unarchive解压模块
unarchive
src             #推送数据的源文件信息
dest            #推送数据的目标路径
copy			#解压在哪里解压
备注:
1,copy等于yes时,是在控制机解压完成后把目录传送给远程机
   copy等于no时,控制机登录远程机进行压缩包的解压工作。
2,得注意解压的机器上必须有相应的解压工具,否则会解压失败(示例:如果压缩包时zip结尾,要解压的机器上必须得有unzip命令)


解压模块:
1、解压ansible管理机上的压缩文件到远程主机:
[root@ansible1 opt]# ansible 192.168.245.181 -m unarchive -a "src=/opt/nginx-1.20.2.tar.gz dest=/opt/ copy=yes"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/opt/", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1666249502.65-3235-195806870400684/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 76, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666249502.65-3235-195806870400684/source", 
    "state": "directory", 
    "uid": 0
}


2、解压远程主机上的文件到目录:
[root@ansible1 opt]# ansible 192.168.245.181 -m unarchive -a "src=/opt/nginx-1.20.2.tar.gz dest=/opt/ copy=no"    #当copy为no时,src的地址为目标主机的地址
192.168.245.181 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "msg": "Source '/opt/nginx-1.20.2.tar.gz' does not exist"
}

[root@ansible2 opt]# ll						#目标机器上没有压缩包
总用量 0
drw------- 2 root root   6 10月 20 11:41 abc
-rw-r--r-- 1 root root   0 10月 20 11:39 a.txt
-rw------- 1 root root   0 10月 20 11:43 b.txt
lrwxrwxrwx 1 root root  10 10月 20 14:25 c.txt -> /opt/a.txt
drwxr-xr-x 8 test test 158 11月 16 2021 nginx-1.20.2
管理服务的启动与停止,使用service、systemd
name        # 定义要启动服务的名称
state       # 指定服务状态
    started     #启动服务
    stopped     #停止服务
    restarted   #重启服务
    reloaded    #重载服务
enabled         #开机自启



#1.启动crond服务,并加入开机自启
[root@ansible1 ~]# ansible webservers -m service -a "name=crond state=started enabled=yes"
#2.停止crond服务,并删除开机自启
[root@ansible1 ~]# ansible webservers -m service -a "name=crond state=stopped enabled=no"
#3.重启crond服务
[root@ansible1 ~]# ansible webservers -m service -a "name=crond state=restarted"
#4.重载crond服务
[root@ansible1 ~]# ansible webservers -m service -a "name=crond state=reloaded"
#5.查看crond服务状态
[root@ansible1 opt]# ansible 192.168.245.181 -m command  -a "systemctl status crond"
192.168.245.181 | FAILED | rc=3 >>
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since 四 2022-10-20 15:16:14 CST; 49s ago
  Process: 536 ExecStart=/usr/sbin/crond -n $CRONDARGS (code=exited, status=0/SUCCESS)
 Main PID: 536 (code=exited, status=0/SUCCESS)

10月 20 09:22:41 ansible2 systemd[1]: Started Command Scheduler.
10月 20 09:22:41 ansible2 systemd[1]: Starting Command Scheduler...
10月 20 09:22:41 ansible2 crond[536]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 56% if used.)
10月 20 09:22:41 ansible2 crond[536]: (CRON) INFO (running with inotify support)
10月 20 15:16:14 ansible2 systemd[1]: Stopping Command Scheduler...
10月 20 15:16:14 ansible2 systemd[1]: Stopped Command Scheduler.non-zero return code
crond定时任务模块

*

*

*

*

*

echo 123456 >/opt/crond.txt

minute

hour

day

month

week

job

name 		#注释说明
state		#present(增加)/absent(删除)

# 正常使用crond服务(默认没写的时间都算*表示)
[root@ansible1 ~]# crontab -l
*/2 * * * * echo 123456 >/opt/crond.txt

# 使用ansible添加一条定时任务
[root@ansible1 opt]# ansible 192.168.245.181 -m cron -a "minute=*/2 job='echo "123456" >/opt/crond.txt' name='this is a test crond_job'"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "this is a test crond_job"
    ]
}
[root@ansible1 opt]# ansible 192.168.245.181 -a "crontab -l"
192.168.245.181 | CHANGED | rc=0 >>
#Ansible: this is a test crond_job
*/2 * * * * echo 123456 >/opt/crond.txt


# 设置定时任务注释信息,防止重复,name设定
[root@ansible1 ~]# ansible webservers -m cron -a "name='cron01' job='/bin/sh /server/scripts/test.sh'"

# 删除相应定时任务
[root@ansible1 opt]# ansible 192.168.245.181 -m cron -a "name='this is a test crond_job' state=absent "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}


[root@ansible1 opt]# ansible 192.168.245.181 -m cron -a "job='echo 123456 >/opt/crond.txt'  state=absent "
[DEPRECATION WARNING]: The 'name' parameter will be required in future releases.. This feature will be removed in version 2.12. 
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
192.168.245.181 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "envs": [], 
    "jobs": [
        "this is a test crond_job"
    ]
}
注:只能通过name来进行删除

#删除不是由ansible生成的计时任务
[root@ansible2 opt]# crontab -l

* */2 * * * echo 123456 >/opt/crond1.txt
#Ansible: this is a test crond_job
*/2 * * * * echo 123456 >/opt/crond.txt

添加andible注释:
[root@ansible2 opt]# crontab -l
#Ansible: crond1
* */2 * * * echo 123456 >/opt/crond1.txt
#Ansible: this is a test crond_job
*/2 * * * * echo 123456 >/opt/crond.txt

[root@ansible1 opt]# ansible 192.168.245.181 -m cron -a " name=crond1  state=absent "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "this is a test crond_job"
    ]
}

[root@ansible2 opt]# crontab -l
#Ansible: this is a test crond_job
*/2 * * * * echo 123456 >/opt/crond.txt



# 注释相应定时任务,使定时任务失效
[root@ansible1 opt]# ansible 192.168.245.181 -m cron -a " name='this is a test crond_job' job='echo 123456 >/opt/crond.txt'  disabled=yes "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "this is a test crond_job"
    ]
}
[root@ansible1 opt]# ansible 192.168.245.181 -a "crontab -l"
192.168.245.181 | CHANGED | rc=0 >>

#Ansible: this is a test crond_job
#* * * * * echo 123456 >/opt/crond.txt			#发现计划任务注释掉


删除与注释有点小区别
mount挂载模块
src				# 源分区
path			# 目标分区
state
	present     # 开机挂载,仅将挂载配置写入/etc/fstab
	mounted     # 挂载设备,并将配置写入/etc/fstab
	unmounted   # 卸载设备,不会清除/etc/fstab写入的配置
	absent      # 卸载设备,会清理/etc/fstab写入的配置
fstype			#挂载类型
			 



1.在服务器上安装nfs
2.配置
3.创建目录修改所有者
4.启动服务并开机自启动
5.服务器上面进行挂载(本地测试)
6.web服务器进行挂载

1.在服务器上安装nfs
[root@ansible1 opt]# ansible 192.168.245.181 -m yum  -a "name=nfs-utils,rpcbind enablerepo=local state=present" -v

2.配置
[root@ansible1 opt]# ansible 192.168.245.181 -m copy -a "content='/opt/nfstest 192.168.245.*(rw)' dest=/etc/exports "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "044407139d78aee1365aab13cb68ddb50648a62e", 
    "dest": "/etc/exports", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "ea12d18fdba2081afd56b510c5f753c5", 
    "mode": "0644", 
    "owner": "root", 
    "size": 30, 
    "src": "/root/.ansible/tmp/ansible-tmp-1666255664.06-4205-21648177808721/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible1 opt]# ansible 192.168.245.181 -a "cat /etc/exports"
192.168.245.181 | CHANGED | rc=0 >>
/opt/nfstest 192.168.245.*(rw)



3.创建目录修改所有者
[root@ansible1 opt]# ansible 192.168.245.181 -m file -a "path=/opt/nfstest state=directory"
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/opt/nfstest", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
[root@ansible1 opt]# ansible 192.168.245.181 -a "ls /opt"
192.168.245.181 | CHANGED | rc=0 >>
abc
a.txt
b.txt
crond.txt
c.txt
nfstest
nginx-1.20.2



4.启动服务并开机自启动
[root@ansible1 opt]# ansible 192.168.245.181 -m systemd -a "name=nfs,rpcbind state=started enabled=yes "				#启动服务不支持多个一起启动
192.168.245.181 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "msg": "Could not find the requested service nfs,rpcbind: host"
}

[root@ansible1 opt]# ansible 192.168.245.181 -m systemd -a "name=nfs state=started enabled=yes "
192.168.245.181 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "nfs", 
    "state": "started",


[root@ansible1 opt]# ansible 192.168.245.181 -m systemd -a "name=rpcbind state=started enabled=yes "
192.168.245.181 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "enabled": true, 
    "name": "rpcbind", 
    "state": "started",


5.ansible2上面进行挂载
[root@ansible1 opt]# ansible 192.168.245.182 -m mount -a "src=192.168.245.181:/opt/nfstest  path=/opt/abc fstype=nfs state=mounted"
192.168.245.182 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dump": "0", 
    "fstab": "/etc/fstab", 
    "fstype": "nfs", 
    "name": "/opt/abc", 
    "opts": "defaults", 
    "passno": "0", 
    "src": "192.168.245.181:/opt/nfstest"
}
[root@ansible1 opt]# ansible 192.168.245.182 -a "df -h "
192.168.245.182 | CHANGED | rc=0 >>
文件系统                      容量  已用  可用 已用% 挂载点
/dev/sda3                      18G  1.4G   17G    8% /
devtmpfs                      479M     0  479M    0% /dev
tmpfs                         489M     0  489M    0% /dev/shm
tmpfs                         489M  6.7M  482M    2% /run
tmpfs                         489M     0  489M    0% /sys/fs/cgroup
/dev/sr0                      4.3G  4.3G     0  100% /mnt
/dev/sda1                     197M   97M  100M   50% /boot
tmpfs                          98M     0   98M    0% /run/user/0
192.168.245.181:/opt/nfstest   18G  1.5G   17G    8% /opt/abc
[root@ansible1 opt]# ansible 192.168.245.182 -a "cat /etc/fstab "
192.168.245.182 | CHANGED | rc=0 >>

#
# /etc/fstab
# Created by anaconda on Tue Mar 22 00:22:51 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=4bd69169-06a2-4098-91f4-27d19efe1cab /                       xfs     defaults        0 0
UUID=d3600a22-f307-4eca-a0fc-f6458fd3555a /boot                   xfs     defaults        0 0
UUID=03efe8dd-e26a-45da-b741-68632f697608 swap                    swap    defaults        0 0
/dev/sr0 /mnt iso9660 defaults 0 0
192.168.245.181:/opt/nfstest /opt/abc nfs defaults 0 0




#卸载分区
[root@ansible1 opt]# ansible 192.168.245.182 -m mount -a "src=192.168.245.181:/opt/nfstest  path=/opt/abc fstype=nfs state=unmounted"	


[root@ansible1 opt]# ansible 192.168.245.182 -m mount -a "src=192.168.245.181:/opt/nfstest  path=/opt/abc fstype=nfs state=absent"