运维自动化----Ansible

学习目标:

掌握ansible的架构、搭建和实操

学习内容:

1、ansible软件架构介绍

ansible是一个同时管理多个远程主机的软件,必须是任意可以通过ssh登录的机器,因此ansible可以管理的机器如:

  • 远程虚拟机
  • 物理机
  • 也可以直接管理本机机器
    ansible通过ssh协议实现了管理节点(老板,安装了ansible服务的机器),被管理节点(员工,被管理的机器节点)的通信,只能是通过ssh协议登录的主机,就可以完成ansible自动化的部署,可实现:
  • 批量文件分发;数据复制、修改、删除
  • 批量自动化安装软件服务、服务部署、服务启停
    ansible特点
    ansible的编排引擎可以出色的完成各种任务配置管理,ansible在流程控制,资源部署等方面很强大,且ansible无需安装客户端软件,管理简洁,使用yaml配置文件语法,功能强大,便于维护
    ansible是基于python语言开发的,主要由python的两个ssh处理模块,paramiko,以及PyYAML模块
  • 安装部署简单
  • 管理主机便捷,支持多台主机并行管理
  • 无需安装被管理节点的客户端(no agent),且无需占用客户端的其他端口,仅仅使用ssh服务即可
  • 不用root用户也可执行,降低系统权限

2、 ansible原理架构图在这里插入图片描述

3、ansible实践部署

准备好3台云服务器ECS,处于同一个VPC或局域网内
zabbix_server 172.28.102.129 管理机器(安装ansible服务端)
zabbix_proxy 172.28.102.131 被管理机器(配置好ssh,关闭防火墙)
zabbix_agent2 172.28.102.130 被管理机器
先准备ansible管理机器

  1. 选择yum源自动化安装,阿里云yum,epel源,前提记得配置好
yum install -y epel-release
yum install -y ansible libseliunx-python
  1. 检查ansible软件安装情况,查询配置文件、可执行命令
[root@zabbix_server ~]# rpm -ql ansible |grep -E '^/etc|^/usr/bin'
/etc/ansible
/etc/ansible/ansible.cfg     #配置文件
/etc/ansible/hosts  		 #主机列表文件
/etc/ansible/roles
/usr/bin/ansible			 #命令的可执行文件
/usr/bin/ansible-2
/usr/bin/ansible-2.7
/usr/bin/ansible-config
/usr/bin/ansible-connection
/usr/bin/ansible-console
/usr/bin/ansible-console-2
/usr/bin/ansible-console-2.7
/usr/bin/ansible-doc
/usr/bin/ansible-doc-2
/usr/bin/ansible-doc-2.7
/usr/bin/ansible-galaxy
/usr/bin/ansible-galaxy-2
/usr/bin/ansible-galaxy-2.7
/usr/bin/ansible-inventory
/usr/bin/ansible-playbook
/usr/bin/ansible-playbook-2
/usr/bin/ansible-playbook-2.7
/usr/bin/ansible-pull
/usr/bin/ansible-pull-2
/usr/bin/ansible-pull-2.7
/usr/bin/ansible-vault
/usr/bin/ansible-vault-2
/usr/bin/ansible-vault-2.7
  1. 检查ansible版本
[root@zabbix_server ~]# 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, Jul 13 2018, 13:06:57) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]

在准备ansible被管理机器
安装ansible所需的系统模块

yum install -y libselinux-python epel-release

ansible管理方式
ansible批量管理主机的方式有两种:

  • 传统的输入ssh密码验证
  • 密钥
    配置好ansible的配置文件,添加被管理机器的ip地址或主机名
    1.备份现有的配置文件
[root@zabbix_server ansible]# cp /etc/ansible/hosts{,.bak}
[root@zabbix_server ansible]# ll
total 32
-rw-r--r-- 1 root root 19985 Jan 16 05:55 ansible.cfg
-rw-r--r-- 1 root root  1016 Jan 16 05:55 hosts
-rw-r--r-- 1 root root  1016 Apr 27 11:24 hosts.bak
drwxr-xr-x 2 root root  4096 Jan 16 05:55 roles

2.添加ansible需要管理的机器地址,添加如下信息

[root@zabbix_server ansible]# tail -3 hosts
[LYP]
172.28.102.130
172.28.102.131

ssh密码认证方式管理机器
ansible是直接利用linux本地的ssh服务,以及一些远程的ssh操作,一般情况下客户端的ssh服务默认是开启的,无需额外管理
1.在管理机器zabbix_server上执行如下命令
-m 指定功能模块(默认就是command模块)
-a 告诉模块需要执行的参数
-k 询问密码验证
-u 指定运行的用户
在zabbix_server机器上,告诉其他被管理机器,你要执行什么命令,以及用什么用户去执行
ansible 主机列表 -m command -a ‘hostname’ -k -u root
2.如上操作,一般默认情况下会有如下错误提示,需要执行如下动作,只需要手动ssh对主机进行一次连接,既可以使用ansible命令操作了,原因是手动连接之后你的~/.ssh/known_hosts文件里面就会有记录记载

[root@zabbix_server ansible]# ansible LYP -m command -a 'hostname' -k -u root
SSH password: 
172.28.102.131 | FAILED | rc=-1 >>
Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host.
172.28.102.130 | CHANGED | rc=0 >>
zabbix_agent2
[root@zabbix_server ansible]# cat ~/.ssh/known_hosts 
172.28.102.130 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPw7q96uIhanENEG0PuxDPcJjpu4FW8+6KP7cARoGzI8kdX8C4/UFZhQBeMClRjb4ihdR0QeVbuvXxhfgwqOwEs=
[root@zabbix_server ansible]# ssh root@172.28.102.131
The authenticity of host '172.28.102.131 (172.28.102.131)' can't be established.
ECDSA key fingerprint is SHA256:FzivlLsvu8+STA1zfHMVdrdriI3M2XM4BPHrpvWOZzY.
ECDSA key fingerprint is MD5:50:1f:cb:1f:5b:39:9d:c3:17:b7:9d:7e:e2:af:98:5a.
Are you sure you want to continue connecting (yes/no)? y
Please type 'yes' or 'no': yes
Warning: Permanently added '172.28.102.131' (ECDSA) to the list of known hosts.
root@172.28.102.131's password: 
Last login: Wed Apr 27 10:50:08 2022 from 47.96.60.109

Welcome to Alibaba Cloud Elastic Compute Service !
[root@zabbix_server ansible]# cat ~/.ssh/known_hosts 
172.28.102.130 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPw7q96uIhanENEG0PuxDPcJjpu4FW8+6KP7cARoGzI8kdX8C4/UFZhQBeMClRjb4ihdR0QeVbuvXxhfgwqOwEs=
172.28.102.131 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE3HZuKff3Mk2wqHjevuDCib74jj9yc/i4f/uchPx2lyaCfxahbF0o0y+IvordQAO6/3dT/PBEkllc8Wy7RB9lg=

3.此时可以再次执行ansible命令,在zabbix_server管理机器上,让这2个被管理的机器执行我们想要的结果

[root@zabbix_server ansible]# ansible LYP -m command -a 'hostname' -k -u root
SSH password: 
172.28.102.130 | CHANGED | rc=0 >>
zabbix_agent2
172.28.102.131 | CHANGED | rc=0 >>
zabbix_proxy

配置免密登录
每次执行ansible命令的时候,都需要输入ssh的认证密码,也就是root的密码,如果不同的主机密码不一致,那你还得输入多次才行,因此我们可以配置如下的快捷登录方式

  1. ansible自带的密码认证参数
    可以在/etc/ansible/hosts文件中,定义好密码即可。即可实现快速的认证,远程管理主机
    参数:
    ansible_host 主机地址
    ansible_port 端口(默认是22端口)
    ansible_user 认证的用户
    ansible_ssh_pass 用户认证的密码
    使用hosts文件的参数,来实现ssh认证,修改hosts文件,改为如下:
[root@zabbix_server ~]# tail -3 /etc/ansible/hosts
[LYP]
172.28.102.130 ansible_user=root ansible_ssh_pass=Cm146688!
172.28.102.131 ansible_user=root ansible_ssh_pass=Cm146688!

修改成次配置后,此时可以不需要输入密码,即可ssh自动验证通过,但是存在一个问题就是密码以明文的方式记录在管理机器上面,不安全:

[root@zabbix_server ~]# ansible LYP -m command -a 'hostname' 
172.28.102.130 | CHANGED | rc=0 >>
zabbix_agent2
172.28.102.131 | CHANGED | rc=0 >>
zabbix_proxy

ssh密钥方式批量管理主机
这个方式比起hosts文件的密码参数来的更安全放心

  1. 在管理机器zabbix_server上创建ssh密钥对,生成后并检查公私钥文件
[root@zabbix_server .ssh]# ssh-keygen -f ~/.ssh/id_rsa -P "" >/dev/null 2>&1
[root@zabbix_server .ssh]# ll
total 12
-rw------- 1 root root    0 Apr 20 09:00 authorized_keys
-rw------- 1 root root 1679 Apr 27 14:49 id_rsa
-rw-r--r-- 1 root root  400 Apr 27 14:49 id_rsa.pub
-rw-r--r-- 1 root root  352 Apr 27 11:47 known_hosts
  1. 编写公钥分发脚本
[root@zabbix_server lyp]# cat ssh_key_send.sh
#!/bin/bash
CURRENT_PATH=`cd $(dirname $0);pwd`
SCRIPT_NAME=$(echo ${0##*/})
#echo $CURRENT_PATH
#exit 2
rm -rf ~/.ssh/id_rsa*
ssh-keygen -f ~/.ssh/id_rsa -P "" >/dev/null 2>&1
SSH_PASS=Cm146688!
KEY_PATH=~/.ssh/id_rsa.pub
for ip in 130 131
do
        sshpass -p$SSH_PASS ssh-copy-id -i $KEY_PATH -o "StrictHostKeyChecking=no" 172.28.102.$ip | tee -a ${CURRENT_PATH}/${SCRIPT_NAME}.log
done
[root@zabbix_server lyp]# sh ssh_key_send.sh 
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' '172.28.102.130'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' '172.28.102.131'"
and check to make sure that only the key(s) you wanted were added.

执行完脚本之后,此时就可以在管理机器zabbix_server上再连接客户端,就无需输入账号密码了,并且可以尝试使用ansible命令连接,如下所示:

[root@zabbix_server lyp]# ssh -o 'StrictHostKeyChecking=no' '172.28.102.130'
Last login: Wed Apr 27 14:29:23 2022 from 172.28.102.129

Welcome to Alibaba Cloud Elastic Compute Service !

[root@zabbix_agent2 ~]# exit
[root@zabbix_server ansible]# tail -5 hosts
[LYP]
#172.28.102.130 ansible_user=root ansible_ssh_pass=Cm146688!
#172.28.102.131 ansible_user=root ansible_ssh_pass=Cm146688!
172.28.102.130
172.28.102.131
[root@zabbix_server ansible]# ansible LYP -m command -a 'df -h'
172.28.102.131 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.1G   36G   6% /
devtmpfs        909M     0  909M   0% /dev
tmpfs           920M     0  920M   0% /dev/shm
tmpfs           920M  496K  919M   1% /run
tmpfs           920M     0  920M   0% /sys/fs/cgroup
tmpfs           184M     0  184M   0% /run/user/0
172.28.102.130 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.0G   36G   6% /
devtmpfs        909M     0  909M   0% /dev
tmpfs           920M     0  920M   0% /dev/shm
tmpfs           920M  468K  919M   1% /run
tmpfs           920M     0  920M   0% /sys/fs/cgroup
tmpfs           184M     0  184M   0% /run/user/0

4、ansible模式与命令

ansible实现批量化主机管理的模式,主要有两种:

  • 利用ansible的纯命令行实现的批量管理,ad-hoc模式—好比简单的shell命令管理

  • 利用ansible的playbook剧本来实现批量管理,playbook剧本模式—好比复杂的shell脚本管理
    ad-hoc模式
    ansible的ad-hoc模式是ansible命令行的形式,也就是处理一些临时的、简单的任务,可以直接使用ansible的命令行来操作,比如:

    • 临时批量查看被管理机器的内存情况、CPU负载情况,网络情况
    • 比如临时的分发配置文件等等

    playbook模式
    ansible的playbook模式是针对比较具体,且具有较大的任务,那么你就得实现写好剧本,应用场景:

    • 一键部署rsync备份服务器
    • 一键部署LNMP环境
  • ansible的ad-hoc命令行解析
    让被管理机器返回主机名

[root@zabbix_server ansible]# ansible LYP -m command -a 'hostname'
172.28.102.130 | CHANGED | rc=0 >>
zabbix_agent2
172.28.102.131 | CHANGED | rc=0 >>
zabbix_prox

ad-hoc命令解释:

  • ansible —自带提供的命令操作
  • LYP —/etc/ansible/hosts文件中定义的主机组,还可以写主机ip地址,以及通配符*
  • -m command —ansible的指定模块的参数,以及指定了command的参数
  • -a —指定给command模块什么参数,hostname、uname -a等等
    ansible-doc命令
    列出所有的ansible支持的模块
ansible-doc -l
查看某个模块的具体使用方法
[root@zabbix_server ~]# ansible-doc -s command
 - name: Execute commands on targets
  command:
      argv:                  # Passes the command as a list rather than a string. Use `argv' to avoid quoting values that would otherwise be interpreted incorrectly (for example "user name"). Only the
                               string or the list form can be provided, not both.  One or the other must be provided.
      chdir:                 # Change into this directory before running the command.
      cmd:                   # The command to run.
      creates:               # A filename or (since 2.0) glob pattern. If it already exists, this step *won't* be run.
      free_form:             # The command module takes a free form command to run. There is no actual parameter named 'free form'.
      removes:               # A filename or (since 2.0) glob pattern. If it already exists, this step *will* be run.
      stdin:                 # Set the stdin of the command directly to the specified value.
      stdin_add_newline:     # If set to `yes', append a newline to stdin data.
      strip_empty_ends:      # Strip empty lines from the end of stdout/stderr in result.
      warn:                  # Enable or disable task warnings.

5、ansible模块精讲

ansible-doc -l
command模块
作用:在远程节点上执行一个命令

  • chdir 在执行命令之前,先通过cd命令进入该参数执行的目录
  • creates 在创建一个文件之前,判断该文件是否存在,如果存在了则跳过前面的动作,如果不存在则执行前面的动作
  • free_form 该参数可以输入任何的系统命令参数,实现远程执行和管理
  • removes 定义一个文件是否存在,如果存在就执行前面的动作,如果不存在则跳过动作

command模块是ansible的默认模块,也可以省略不写,但是要注意如下的坑:

  • 使用command模块,不得出现shell变量$name,也不可以出现特殊符号> < | ; & 这些符号command模块都不认识,你如果要使用这些前面指定的变量,特殊符号,请使用shell模块。

command模块案列
1、获取所有被管理机器的负载信息

[root@zabbix_server ~]# ansible LYP -m command -a 'pwd chdir=/tmp' 
172.28.102.130 | CHANGED | rc=0 >>
/tmp
172.28.102.131 | CHANGED | rc=0 >>
/tmp

2、 让客户端机器,先切换到/tmp目录下,然后打印当前的工作目录

[root@zabbix_server ~]# ansible LYP -m command -a 'uptime' 
172.28.102.130 | CHANGED | rc=0 >>
 16:25:17 up 6 days,  5:55,  1 user,  load average: 0.48, 0.11, 0.08
172.28.102.131 | CHANGED | rc=0 >>
 16:25:17 up 2 days,  1:52,  2 users,  load average: 0.10, 0.11, 0.09

3、练习creates参数
该参数作用是判断文件是否存在,存在则跳过,不存在这执行

[root@zabbix_server ~]# ansible LYP -m command -a 'pwd creates=/home' 
172.28.102.130 | SUCCESS | rc=0 >>
skipped, since /home exists
172.28.102.131 | SUCCESS | rc=0 >>
skipped, since /home exists
[root@zabbix_server ~]# ansible LYP -m command -a 'pwd creates=/home/111' 
172.28.102.130 | CHANGED | rc=0 >>
/root
172.28.102.131 | CHANGED | rc=0 >>
/root

4、参数removes实践,存在则执行,不存在则跳过

[root@zabbix_server ~]# ansible LYP -m command -a 'ls /opt removes=/home/111' 
172.28.102.130 | SUCCESS | rc=0 >>
skipped, since /home/111 does not exist
172.28.102.131 | SUCCESS | rc=0 >>
skipped, since /home/111 does not exist
[root@zabbix_server home]# ansible LYP -m command -a 'ls /tmp removes=/tmp' 
172.28.102.130 | CHANGED | rc=0 >>
agent.sock
AliyunAssistClientSingleLock.lock
ansible_command_payload_hXgi8h
CmsGoAgent.pid
systemd-private-82dde605792a4ee883a4d2802381b5ac-chronyd.service-Uhaa9b
172.28.102.131 | CHANGED | rc=0 >>
AliyunAssistClientSingleLock.lock
ansible_command_payload_1r1p0a
argus.sock
systemd-private-bd0d675d43e74a248ffb8ba3f07fe61e-chronyd.service-ABpqJ8
systemd-private-bd0d675d43e74a248ffb8ba3f07fe61e-mariadb.service-s8bz9c

5、warn参数,是否提供告警信息
#执行命令,且忽略信息

[root@zabbix_server ~]# ansible LYP -m command -a 'chmod 644 /etc/hosts warn=false'
172.28.102.130 | CHANGED | rc=0 >>

172.28.102.131 | CHANGED | rc=0 >>

shell模块
作用:在远程主机上执行命令(复杂的命令)
了解模块用法的渠道:

  • linux命令行里面通过ansible-doc -s 模块名称
  • ansible官网查看帮助信息https://docs.ansible.com/ansible/2.9/modules/shell_module.html

shell模块支持的参数和解释

  • chdir 在执行命令之前,通过cd进入该参数的目录
  • creates 定义一个文件是否存在,如果存在则不执行该命令,如果不存在则执行该命令
  • free_form 参数信息中可以输入任何的系统指令,实现远程管理
  • removes 定义一个文件是否存在,如果存在该文件,则执行命令,不存在则跳过

shell模块案列

  • 批量查询进程信息
[root@zabbix_server ~]# ansible LYP -m shell -a "ps -ef |grep ssh |grep -v grep"
172.28.102.130 | CHANGED | rc=0 >>
root      1026     1  0 Apr21 ?        00:00:01 /usr/sbin/sshd -D
root     26999  1026  0 17:32 ?        00:00:00 sshd: root@pts/0
root     27046  1026  1 17:33 ?        00:00:00 sshd: root@pts/1
172.28.102.131 | CHANGED | rc=0 >>
root      1098     1  0 Apr25 ?        00:00:00 /usr/sbin/sshd -D
root     28504  1098  0 17:00 ?        00:00:00 sshd: root@pts/0
root     30572  1098  1 17:33 ?        00:00:00 sshd: root@pts/1
  • 批量在客户端机器,创建写入文件信息
[root@zabbix_server ~]# ansible LYP -m shell -a "echo 你真棒!>/home/heihei.txt"
172.28.102.130 | CHANGED | rc=0 >>

172.28.102.131 | CHANGED | rc=0 >>
  • 批量执行脚本
    该需要执行的脚本,必须要在客户端上存在,否则会把报错文件不存在,这是shell模块的特点,是因为还有一个专门执行脚本的script模块,注意这个脚本必须在客户端机器上存在才行
    1.创建文件夹
    2.创建sh脚本文件
    3.赋予脚本可执行权限
    4.执行脚本
    5.忽略warning信息
    思路分析:
    最好所有的操作都是在管理机器上进行远程操作,批量化操作
ansible LYP -m shell -a "mkdir /home/myscripts/;echo 'hostname' > /home/myscripts/hostname.sh;chmod +x /home/myscripts/hostname.sh;sh /home/myscripts/hostname.sh warn=false"
172.28.102.130 | CHANGED | rc=0 >>
zabbix_agent2
172.28.102.131 | CHANGED | rc=0 >>
zabbix_proxy

script模块
功能:把管理机器上面的脚本远程的传输到被管理节点上去执行
比起shell模块,script模块的功能更强大,在管理机器上面本地有一份脚本,就可以在所有被管理机器上面去运行

script模块支持的参数和解释

  • chdir 在执行命令之前,通过cd进入该参数的目录
  • creates 定义一个文件是否存在,如果存在则不执行该命令,如果不存在则执行该命令
  • free_form 参数信息中可以输入任何的系统指令,实现远程管理
  • removes 定义一个文件是否存在,如果存在该文件,则执行命令,不存在则跳过

应用案例:
1、在管理节点上创建脚本

total 0
[root@zabbix_server myscripts]# echo -e 'pwd\nhostname' > local_host.sh
[root@zabbix_server myscripts]# ll
total 4
-rw-r--r-- 1 root root 13 Apr 27 18:46 local_host.sh
[root@zabbix_server myscripts]# cat local_host.sh 
pwd
hostname

2、赋予执行权限

chmod +x local_host.sh 

3、远程的批量执行脚本,且在客户端上不需要存在该脚本

}
[root@zabbix_server myscripts]# ansible LYP -m script -a "/home/myscripts/local_host.sh"
172.28.102.130 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 172.28.102.130 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 172.28.102.130 closed."
    ], 
    "stdout": "/root\r\nzabbix_agent2\r\n", 
    "stdout_lines": [
        "/root", 
        "zabbix_agent2"
    ]
}
172.28.102.131 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 172.28.102.131 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 172.28.102.131 closed."
    ], 
    "stdout": "/root\r\nzabbix_proxy\r\n", 
    "stdout_lines": [
        "/root", 
        "zabbix_proxy"
    ]
}
[root@zabbix_server myscripts]# pwd
/home/myscripts

学习总结

  1. 在生产环境中,ansible的连接方式,二选一即可,最好是配置ssh公私钥免密登录
  2. 如果生产环境的要求更高,可以用普通用户去执行,再提权操作,sudo
  3. 学习视频链接:https://www.bilibili.com/video/BV1CP4y1M7Fd?p=37
  4. ansible官方模块解释查阅文档链接:https://docs.ansible.com/ansible/2.9/modules/shell_module.html
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值