自动化运维工具ansible的安装管理以及模块介绍

自动化运维工具ansible的安装管理以及模块介绍

一、ansible概述

1、几种常用运维工具比较

Puppet
—基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱
SaltStack
—基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使得配置脚本更简单
Ansible
—基于 Python paramiko 开发,分布式,无需客户端,轻量级,配置语法使用YAML 及 Jinja2模板语言,更强的远程命令执行操作

2、Ansible简介

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

在这里插入图片描述
在这里插入图片描述

connection plugins:连接插件,负责和被监控端实现通信,有SSH,ZEROMQ等,默认使用SSH连接
host inventory:主机清单,是一个配置文件里面定义监控的主机
modules : 模块,核心模块、command模块、自定义模块等
plugins : modules功能的补充,包括连接插件,邮件插件等
playbook:编排,定义 Ansible 多任务配置文件,非必需

3、Ansible特性

1)、no agents:不需要在被管控主机上安装任何客户端,更新时,只需在操作机上进行一次更新即可
2)、no server:无服务器端,使用时直接运行命令即可
3)、modules in any languages:基于模块工作,可使用任意语言开发模块
4)、yaml,not code:使用yaml语言定制剧本playbook
5)、ssh by default:基于SSH工作

6)、strong multi-tier solution:可实现多级指挥

二、ansible 安装

----关闭防火墙及安全机制----
[root@ansible ~]# systemctl stop firewalld && systemctl disable firewalld
[root@ansible ~]# setenforce 0 && sed -i "s/SELINUX=*/SELINUX=disabled/g" /etc/selinux/config

----配置在线YUM源----
[root@ansible ~]# mkdir -p /etc/yum.repos.d
[root@ansible ~]# mv -f /etc/yum.repos.d/* /etc/yum.repos.d/repos-0.bak
[root@ansible ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
[root@ansible ~]# yum clean all && yum makecache fast

----安装epel源及ansible----
[root@ansible ~]# yum install -y epel-release
'//epel:能为linux提供高质量软件包,相当于一个第三方源'
[root@ansible ~]# yum install -y ansible
'//建议下两遍,避免遗漏'

----查看ansible版本及结构----
[root@ansible ~]# ansible --version
ansible 2.9.18
  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)]

三、ansible 配置主机清单及密钥对验证

[root@ansible ~]# yum install -y tree
'//安装树形查看工具'
[root@ansible ~]# tree /etc/ansible/
/etc/ansible/
├── ansible.cfg		'//配置文件'
├── hosts			'//主机清单(管理)'
└── roles

1 directory, 2 files

----配置主机清单----
[root@ansible ~]# vim /etc/ansible/hosts 
25 [webserver]		'//插入,上面有模板,指向另外两台主机'
26 192.168.126.20
27 [mysql]
28 192.168.126.40

----配置密钥对验证----
[root@ansible ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 	'//输入要保存密钥的文件,这里直接选择默认回车'
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 		'//输入密码'
Enter same passphrase again: 		'//再次确认密码'
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:3g4zXJ+pp+DH460lQ0qiPPPXAb5GLxgAwxuC3WdNaeM root@localhost.localdomain
The key's randomart image is:
+---[RSA 2048]----+
|.o .   o..       |
|o * . o =        |
| . = o o .       |
|  . .   E        |
|     ...S.o      |
|   . ..=o=.. o   |
|    =  +O=+.=    |
|     +..=***.    |
|      .o.+*=.    |
+----[SHA256]-----+
[root@ansible ~]# ls -a		'//查看隐藏文件'
.                .bash_profile  .esd_auth             .tcshrc      图片
..               .bashrc        .ICEauthority         .viminfo     文档
anaconda-ks.cfg  .cache         initial-setup-ks.cfg  .Xauthority  下载
.ansible         .config        .local                公共         音乐
.bash_history    .cshrc         .pki                  模板         桌面
.bash_logout     .dbus          .ssh                  视频
[root@ansible ~]# cd .ssh/
[root@ansible .ssh]# ls
id_rsa  id_rsa.pub		'//生成的公钥和私钥文件'
[root@ansible .ssh]# ssh-copy-id root@192.168.126.12
'//将公钥推给被管理端'
[root@ansible .ssh]# ssh-copy-id root@192.168.126.13
'//切换至webserver端(192.168.126.12)'
[root@webserver ~]# cd .ssh/
[root@webserver .ssh]# ls
authorized_keys

四、ansible 命令格式及基本用法

----命令格式----
ansible [主机] [-m 模块] [-a args]

ansible-doc -l		'//列出所有已安装的模块(按q退出)'
ansible-doc -s yum	'//-s列出yum模块描述信息和操作动作'

----基本用法----
[root@ansible .ssh]# ansible webserver -m command -a 'date'		'//指定主机执行date命令'
Enter passphrase for key '/root/.ssh/id_rsa': 	'//输入密钥密码,之前设为123123'
192.168.126.12 | CHANGED | rc=0 >>
2021年 04月 02日 星期五 10:25:01 CST
[root@ansible .ssh]# ansible mysql -m command -a 'date'
Enter passphrase for key '/root/.ssh/id_rsa': 
192.168.126.13 | CHANGED | rc=0 >>
2021年 04月 02日 星期五 10:25:33 CST
'//每次执行该命令都要输入密钥密码,比较麻烦,我们可以通过免交互代理来避免'
[root@ansible .ssh]# ssh-agent bash
[root@ansible .ssh]# ssh-add 
Enter passphrase for /root/.ssh/id_rsa: 	'//输入密码'
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
'//再次尝试执行命令试试'
[root@ansible .ssh]# ansible 192.168.126.20-m command -a 'date'
192.168.126.20 | CHANGED | rc=0 >>
2021年 04月 02日 星期五 10:28:34 CST
'//这里除了别名也可以填IP地址,现在可以免交互执行命令了'

[root@ansible .ssh]#ansible 192.168.126.40 -m command -a 'ls /opt'
192.168.126.40 | CHANGED | rc=0 >>
rh

五、ansible 常用模块管理

环境:

主机名IP地址软件服务操作系统
ansible192.168.126.10ansibleCentOS7
node1192.168.126.20/CentOS7
node2192.168.126.40/CentOS7

1、command - 默认模块

命令格式:
ansible [主机] [-m 模块] [-a args]

例:
ansible-doc -l		'//列出所有已安装的模块(按q退出)'
ansible-doc -s yum	'//-s列出yum模块描述信息和操作动作(按q退出)'

[root@ansible ~]# ansible 192.168.126.20 -m command -a 'date'		'//指定ip执行date命令,这里上文已做过免交互'
192.168.126.20 | CHANGED | rc=0 >>
2021年 04月 06日 星期二 17:17:36 CST
[root@ansible ~]# ansible webserver -m command -a 'date'		'//主机名与ip地址同理'
192.168.126.20 | CHANGED | rc=0 >>
2021年 04月 06日 星期二 17:17:36 CST
[root@ansible ~]# ansible mysql -m command -a 'date'
192.168.126.40 | CHANGED | rc=0 >>
2021年 04月 06日 星期二 17:18:24 CST

[root@ansible ~]# ansible all -m command -a 'date'		'//所有hosts主机执行date命令'
192.168.126.40 | CHANGED | rc=0 >>
2021年 04月 06日 星期二 17:18:43 CST
192.168.126.20 | CHANGED | rc=0 >>
2021年 04月 06日 星期二 17:18:43 CST
[root@ansible ~]# ansible all -a 'ls /opt'		'//若不加-m模块,则默认运行command模块'192.168.126.40 | CHANGED | rc=0 >>
rh
192.168.126.20 | CHANGED | rc=0 >>
rh

2、cron - 定时任务模块

有两种状态(state):present表示添加,absent表示移除

例:
ansible-doc -s cron		'//-s查看cron模块信息'

[root@mysqlr .ssh]# which echo		'//在PATH变量指定的路径中搜索echo命令的位置'
/usr/bin/echo

[root@ansible ~]# ansible mysql -m cron -a 'minute="*/1" job="/usr/bin/echo hello" name="cw cron job"'
'//指定webserver主机,-m不可省略,否则默认执行command模块'
'//-a指定参数,每分钟执行(间隔频率);执行操作;指定计划性任务名称'
'//这里注意格式,单引号与双引号的使用'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "cw cron job"
    ]
}
[root@ansible ~]# ansible mysql -a 'crontab -l'		'//执行命令查看以下有无该计划性任务'
192.168.126.40 | CHANGED | rc=0 >>
#Ansible: cw cron job
*/1 * * * * /usr/bin/echo hello

[root@mysql .ssh]# crontab -l		'//切换至mysql查看以下'
#Ansible: cw cron job
*/1 * * * * /usr/bin/echo hello

[root@ansible ~]# ansible mysql -m cron -a 'name="cw cron job" state=absent'
'//移除计划性任务'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}
'//再切换至mysql查看,原先的计划性任务没了'
[root@mysql .ssh]# crontab -l

3、user - 用户模块

'该模块请求的是useradd,userdel,usermod三个指令'
'即创建/删除用户,设定用户所属组'

例:
ansible-doc -s user		'//-s查看user模块信息'

[root@ansible ~]# ansible mysql -m user -a 'name="zhangsan"'		'//在mysql主机中创建用户zhangsan'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1002, 
    "home": "/home/zhangsan", 
    "name": "zhangsan", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 1001
}
[root@node2 ~]# id zhangsan 
uid=1001(zhangsan) gid=1002(zhangsan) 组=1002(zhangsan)

#去到node2节点,可以看到zhangsan用户已经创好存在了

[root@ansible ~]# ansible mysql -m user -a 'name="zhangsan" state=absent'
'//删除该用户;absent使用频率较高'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "zhangsan", 
    "remove": false, 
    "state": "absent"
}

[root@node2 ~]# id zhangsan 
id: zhangsan: no such user

#切换到node2节点,可以看到zhangsan用户不存在了

4、group - 用户(组)模块

'该模块请求的是groupadd,groupdel,groupmod这三个指令(组)'

例:
ansible-doc -s group

[root@ansible ~]# ansible mysql -m group -a 'name=mysql gid=306 system=yes'
'//在mysql主机上创建组,组名为mysql;gid号为306(不指定也行,会自动生成);指定system'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 306, 
    "name": "mysql", 
    "state": "present", 
    "system": true
}

[root@node2 ~]# id mysql
uid=990(mysql) gid=306(mysql) 组=306(mysql)

[root@ansible ~]# ansible mysql -m user -a 'name=test02 uid=306 system=yes group=mysql'
'//创建用户,添加至mysql组,指定系统用户'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 306, 
    "home": "/home/cw", 
    "name": "cw", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": true, 
    "uid": 308
}
[root@ansible .ssh]#ansible mysql -a 'id cw'
192.168.126.40 | CHANGED | rc=0 >>
uid=308(cw) gid=306(mysql) 组=306(mysql)
'//注意一点,检查基本都是用-a,即command命令来检查的'

5、copy - 模块

例:
ansible-doc -s copy

[root@ansible ~]# ansible mysql -m copy -a 'src=/etc/fstab dest=/opt/fstab.bak owner=root mode=644'
'//src表示原文件; dest表示目标;即从哪复制到哪'
'//owner表示属主(所有者),mode表示权限'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "c2c0064d6bf5b2406fb8f0b0e1375c64dfb31bf9", 
    "dest": "/opt/fstab.bak", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "ff5317baec6e65db01351886774c36a6", 
    "mode": "0644", 
    "owner": "root", 
    "size": 595, 
    "src": "/root/.ansible/tmp/ansible-tmp-1617704881.31-40190-62239597790259/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible ~]# ansible mysql -a 'ls -l /opt'
192.168.126.13 | CHANGED | rc=0 >>
总用量 4
-rw-r--r--  1 root root 683 4月   2 12:08 fstab.bak
drwxr-xr-x. 2 root root   6 3月  26 2015 rh
[root@ansible ~]# ansible mysql -a 'cat /opt/fstab.bak'
'//查看复制文件的内容'
[root@ansible ~]# ansible mysql -m copy -a 'content="hello world" dest=/opt/fstab.bak2'
'//指定内容为hello world,重定向至该目录下(生成一个全新的文件)'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", 
    "dest": "/opt/fstab.bak2", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "5eb63bbbe01eeed093cb22bb8f5acdc3", 
    "mode": "0644", 
    "owner": "root", 
    "size": 11, 
    "src": "/root/.ansible/tmp/ansible-tmp-1617705515.51-40339-204544609892125/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible ~]# ansible mysql -a 'cat /opt/fstab.bak2'
'//再次查看'
192.168.126.40| CHANGED | rc=0 >>
hello world~
'//以上用法能够使用copy指定内容生成一个新文件'

6、file - 模块

实现创建/删除文件信息 对数据权限进行修改

例:
ansible-doc -s file

[root@ansible ~]# ansible mysql -m file -a 'path=/opt/fstab.bak owner=test02 group=mysql mode=666'
'//path指定路径;指定属主test02(需已存在);group指定mysql组;权限修改为666'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 306, 
    "group": "mysql", 
    "mode": "0700", 
    "owner": "zhangsan", 
    "path": "/opt/fstab.bak", 
    "size": 595, 
    "state": "file", 
    "uid": 1001
}
'//可切至mysql主机查看下'
[root@mysql opt]# ls -l		'//这是执行file模块之前的参数'
[root@node2 opt]# ls -l
总用量 8
-rwx------  1 zhangsan mysql 595 4月   6 18:28 fstab.bak
-rw-r--r--  1 root     root   11 4月   6 18:38 fstab.bak2
drwxr-xr-x. 2 root     root    6 3月  26 2015 rh
'//前后对比'
[root@mysql opt]# ls -l		'//执行file模块成功,提权,且修改了属组为zhangsan'

[root@ansible ~]# ansible mysql -m file -a 'src=/opt/fstab.bak path=/opt/fstab.bak.link state=link'
'//创建软链接'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/fstab.bak.link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 14, 
    "src": "/opt/fstab.bak", 
    "state": "link", 
    "uid": 0
}
[root@ansible ~]# ansible mysql -a 'ls -l /opt'
192.168.126.13 | CHANGED | rc=0 >>
192.168.126.40 | CHANGED | rc=0 >>
总用量 8
-rwx------  1 zhangsan mysql 595 4月   6 18:28 fstab.bak
-rw-r--r--  1 root     root   11 4月   6 18:38 fstab.bak2
lrwxrwxrwx  1 root     root   14 4月   6 18:55 fstab.bak.link -> /opt/fstab.bak
drwxr-xr-x. 2 root     root    6 3月  26 2015 rh

[root@ansible ~]# ansible mysql -m file -a "path=/opt/fstab.bak.link state=absent"
'//删除'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/opt/fstab.bak.link", 
    "state": "absent"
}
[root@ansible ~]# ansible mysql -a 'ls -l /opt'
192.168.126.40 | CHANGED | rc=0 >>
总用量 8
-rwx------  1 zhangsan mysql 595 4月   6 18:28 fstab.bak
-rw-r--r--  1 root     root   11 4月   6 18:38 fstab.bak2
drwxr-xr-x. 2 root     root    6 3月  26 2015 rh

[root@ansible ~]# ansible mysql -m file -a "path=/opt/test state=touch"
'//建立空文件'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt/cw", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
[root@ansible ~]# ansible mysql -a 'ls -l /opt'
192.168.126.40 | CHANGED | rc=0 >>
总用量 8
-rw-r--r--  1 root     root    0 4月   6 18:59 cw
-rwx------  1 zhangsan mysql 595 4月   6 18:28 fstab.bak
-rw-r--r--  1 root     root   11 4月   6 18:38 fstab.bak2
drwxr-xr-x. 2 root     root    6 3月  26 2015 rh
[root@ansible ~]# ansible mysql -a 'cat /opt/cw'
192.168.126.40 | CHANGED | rc=0 >>
'//确认为空文件'

7、ping - 模块

[root@ansible ~]# ansible all -m ping
'//测试被管理主机是否在线'
192.168.126.40 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.126.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

8、yum/service - 模块

service:用于管理服务运行状态

yum:使用yum软件包管理器安装,升级,降级,删除和列出软件包和组

ansible-doc -s service
ansible-doc -s yum

例:
[root@ansible ~]# ansible mysql -m yum -a 'name=httpd'
'//yum下载httpd服务;也可以使用all,让所有主机一起运行'
192.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ]
    }, 
    "msg": "", 
[root@node2 opt]# rpm -q httpd
httpd-2.4.6-97.el7.centos.x86_64
[root@node2 opt]# 		'//有了'
[root@ansible ~]# ansible mysql -m yum -a 'name=httpd state=absent'
'//卸载该软件包'
192\.168.126.40 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
[root@node2 opt]# rpm -q httpd
未安装软件包 httpd 
	'//卸载成功'

'//再次执行命令安装服务,之后使用service模块启动该服务'
[root@ansible ~]# ansible mysql -m yum -a 'name=httpd'
[root@ansible ~]# ansible mysql -m service -a 'name=httpd enabled=true state=started'
'//启动该服务并设置开机自启(生成内容较多)'
[root@ansible ~]# ansible mysql -a 'systemctl status httpd'
'//检查该服务是否正常开启'

9、shell/script - 模块

ansible-doc -s shell
ansible-doc -s script

例:
[root@ansible ~]# ansible webserver -m user -a 'name=sicong'
'//在webserver端建立一个用户,以作后续测试'
192.168.126.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1001, 
    "home": "/home/mm", 
    "name": "mm", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 1001
}
[root@ansible ~]# ansible webserver -m shell -a 'echo 123123|passwd --stdin sicong'
192.168.126.20 | CHANGED | rc=0 >>
更改用户 mm 的密码 。
passwd:所有的身份验证令牌已经成功更新。

[root@ansible ~]# vim /opt/test.sh
#!/bin/bash
'//这是一个测试脚本,生成一个测试文件到对方指定目录中去'
echo "echo "my name is cw"   > /opt/script.txt
chmod 666 /opt/script.txt		'//赋权'

[root@ansible ~]# ansible all -m script -a '/opt/test.sh'
'//使用script执行该脚本'
192.168.126.40 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.126.40 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.126.40 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
192.168.126.20 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.126.20 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.126.20 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
[root@ansible .ssh]#ansible all -a 'cat /opt/script.txt'
'//查看是否生成新文件,该测试脚本书否成功,这种方法可用于大批量创建用户等循环重复场景'

192.168.126.40 | CHANGED | rc=0 >>
my name is cw
192.168.126.20 | CHANGED | rc=0 >>
my name is cw

10、setup - 模块

ansible-doc -s setup

例:
[root@ansible ~]# ansible mysql -m setup
'//查看该主机详细信息,信息量巨大,建议配合grep使用'
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值