【Kubernetes 021】Python客户端自动创建和销毁Kubernetes资源详解

k8s client-java创建一个deployment yaml创建 参考 client-java创建 @Data public class DeploymentDTO { private String namespace; private String deploymentName; private Integer replicas; private String metadataLabelsApp; private String image; private String portName; priva 阅读详情

学会了k8s的基本使用,下面就可以开始一些进阶的学习了,例如二次开发。想象有一个网页管理工具,管理人员只需要点击一个按钮,后台就会自动按照预先设定好的参数创建资源。当资源使用完毕,又可以点击另一个按钮自动删除资源。这一节我们就一起来学习如何用python来完成这一目的。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

客户端

之前我们一直用的kubectl这个客户端去连接的API server,其通过~/.kube/config文件内的信息完成验证,进而进行API交互。所以其实理论上,只要有程序能获得同样的认证信息,就可以和kubectl一样完成这样的交互。于是官方用各种语言写了这样的一个客户端,并开源在了Github上,见这里。其中星标最多的当属python客户端了,于是我们就来试一试这款官方推出的python客户端。

对于用户config文件内容感兴趣的可以参考我的另一篇博客《【Kubernetes 018】cfssl创建证书并结合RBAC的RoleBinding配置新用户config文件操作详解》

操作思路

官方的Readme里面已经给出了各种代码示例,从这些示例里面大概能总结出操作的一些基本步骤,我这里按照我自己的理解总结如下

  1. 首先是获取认证信息,直接通过用户的config文件导入即可
  2. 查阅k8s的API Reference获取资源对应的API分支,例如deployment就是Deployment v1 apps,而对应到客户端的API类列表中的apps_v1_api.py。如果是service就是Service v1 core,对应到客户端的core_v1_api.py
  3. 然后对API的各个字段进行设置,可以单独设置,也可以直接用之前配置好的yaml文件
  4. 利用客户端类的各种方法去对资源进行创建更新或者删除

注意,因为k8s中的API分支多大几十种,在选择的时候要仔细点,不然会出现API版本不匹配的报错。

实际操作

我这里操作使用的环境如下

  • python 3.7.1
  • pycharm 2019.3 professional
  • kubernetes集群 1.15
  • kubernetes库 11.0.0

还是以创建《部署Rasa框架到Kubernetes集群并分配GPU资源》同样的资源来作为操作演示。

安装kubernetes库

直接利用pip安装即可,或者在pycharm里面安装,如下

1-package.png

之后就可以在项目中引入了

from kubernetes import client, config

获取认证信息

我这里创建了一个叫k8s_client的项目,然后将config文件拷贝到项目的根目录,用下面的方法从文件导入认证信息

BASE_URL = '/home/fuhx/python_projects/k8s/k8s_client/'
cf = config.load_kube_config(path.join(BASE_URL, 'config'))

创建API实例

如果要创建Deployment,创建一个apps_v1_api.py的API实例如下

apps_v1_api = client.AppsV1Api()

如果要创建Service,创建一个core_v1_api.py的API实例如下

core_v1_api = client.CoreV1Api()

导入yaml文件

我这里在项目根目录下创建了yaml目录,里面放了两个yaml文件rasa-deployment.yaml和rasa-service.yaml分别创建Deployment和Service。这里的两个文件是上一篇博客《部署Rasa框架到Kubernetes集群并分配GPU资源》中用到的文件,但是添加了一些字段,如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rasa-deployment-2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rasa-2
  template:
    metadata:
      labels:
        app: rasa-2
    spec:
      containers:
        - name: myrasa
          image: myrasa:v2
          ports:
            - containerPort: 5005
          command: ["/bin/sh","-c","rasa init --no-prompt;rasa run --enable-api"]
          livenessProbe:
            httpGet:
              port: 5005
              path: /
            initialDelaySeconds: 1
            periodSeconds: 3
          resources:
            limits:
              aliyun.com/gpu-mem: 1
          volumeMounts:
            - mountPath: /app
              name: rasa-app
            - mountPath: /tmp
              name: rasa-tmp
      volumes:
        - name: rasa-app
          emptyDir: {}
        - name: rasa-tmp
          emptyDir: {}

需要注意,这里除了修改了下名字以与现有资源不冲突以外,还添加了下面这一段

  selector:
    matchLabels:
      app: rasa-2

直接用kubectl的时候不用添加但是这里必须要添加,或许是因为这里的规范比较严格,不然在执行的时候会出现如下报错

...
...
kubernetes.client.rest.ApiException: (422)
Reason: Unprocessable Entity
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json', 'Date': 'Fri, 22 May 2020 08:04:23 GMT', 'Content-Length': '672'})
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Deployment.apps \"rasa-deployment-2\" is invalid: [spec.selector: Required value, spec.template.metadata.labels: Invalid value: map[string]string{\"app\":\"rasa-2\"}: `selector` does not match template `labels`]","reason":"Invalid","details":{"name":"rasa-deployment-2","group":"apps","kind":"Deployment","causes":[{"reason":"FieldValueRequired","message":"Required value","field":"spec.selector"},{"reason":"FieldValueInvalid","message":"Invalid value: map[string]string{\"app\":\"rasa-2\"}: `selector` does not match template `labels`","field":"spec.template.metadata.labels"}]},"code":422}



Process finished with exit code 1

Service需要注意修改端口避免跟现有资源冲突

apiVersion: v1
kind: Service
metadata:
  name: rasa-service-2
spec:
  type: NodePort
  selector:
    app: rasa-2
  ports:
    - name: http
      port: 5005
      targetPort: 5005
      nodePort: 31112

这里因为两个资源属于不同API分支,要用不同的类实例去创建,所以不能放在同一个文件用用---隔开。

之后就可以分别导入备用了

with open(path.join(BASE_URL, 'yaml/rasa_deployment.yaml')) as f:
    dep = yaml.safe_load(f)
with open(path.join(BASE_URL, 'yaml/rasa_service.yaml')) as f:
    svc = yaml.safe_load(f)

yaml和json一样用直接load进来变为字典格式,不过yaml为了安全起见有一个safe_load命令,只会去解析一些基本yaml语法,一般情况下用safe得就可以了

创建和删除

分别调用API实例得方法即可,这里单独创建了4个函数用来处理

def create_deployment(api_instance, body):
    api_response = api_instance.create_namespaced_deployment(
        body=body,
        namespace='default')
    print(api_response)
    # print("Deployment created. status='%s'" % str(api_response.status))


def delete_deployment(api_instance, name):
    api_response = api_instance.delete_namespaced_deployment(
        name=name,
        namespace='default'
    )
    print(api_response)


def create_service(api_instance, body):
    api_response = api_instance.create_namespaced_service(
        body=body,
        namespace='default'
    )
    print(api_response)


def delete_service(api_instance, name):
    api_response = api_instance.delete_namespaced_service(
        name=name,
        namespace='default'
    )
    print(api_response)

最后在main函数中去调用即可,我这里就不写复杂得逻辑判断了

BASE_URL = '/home/fuhx/python_projects/k8s/k8s_client/'
cf = config.load_kube_config(path.join(BASE_URL, 'config'))
core_v1_api = client.CoreV1Api()
apps_v1_api = client.AppsV1Api()
with open(path.join(BASE_URL, 'yaml/rasa_deployment.yaml')) as f:
	dep = yaml.safe_load(f)
with open(path.join(BASE_URL, 'yaml/rasa_service.yaml')) as f:
	svc = yaml.safe_load(f)
create_deployment(apps_v1_api, dep)
# create_service(core_v1_api, svc)
# delete_deployment(apps_v1_api, 'rasa-deployment-2')
# delete_service(core_v1_api, 'rasa-service-2')

检查效果

如果API方法没有报错就可以认为资源的操作没有问题,这时候就可以去集群内部检查下资源状况,当然安装了ELK或者Prometheus的就直接图形界面查看了。

root@control-plane-1:~# kubectl get pod -o wide
NAME                                 READY   STATUS    RESTARTS   AGE    IP            NODE       NOMINATED NODE   READINESS GATES
curl-6bf6db5c4f-fr2xv                1/1     Running   0          2d3h   10.244.2.2    gpu-node   <none>           <none>
nvidia-deployment-5f4bbd9457-2rj7r   1/1     Running   1          2d3h   10.244.2.4    gpu-node   <none>           <none>
nvidia-deployment-5f4bbd9457-hfxqh   1/1     Running   1          2d3h   10.244.2.3    gpu-node   <none>           <none>
rasa-deployment-2-6446bc5d4d-dp229   1/1     Running   0          19s    10.244.2.12   gpu-node   <none>           <none>
rasa-deployment-586ff4666-hf6xm      1/1     Running   0          2d2h   10.244.2.8    gpu-node   <none>           <none>
root@control-plane-1:~# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP          2d23h
rasa-service     NodePort    10.108.95.50     <none>        5005:31111/TCP   43h
rasa-service-2   NodePort    10.102.214.112   <none>        5005:31112/TCP   31s

从另外一台机器上试一下Service的端口服务

[root@ai-asterisk ~]# curl -X POST 172.29.57.202:31112/webhooks/rest/webhook -d '{"sender":"xiaofu","message":"How are you?"}'
[{"recipient_id":"xiaofu","text":"I am a bot, powered by Rasa."}]

总结

这里只是抛砖引玉,简单找了两个资源尝试了一下添加和删除,更多的API等着我们在实际项目中慢慢探索。有了python客户端我们就可以将k8s的自动化操作融入到一些运维平台中了,如果有机会我们以后再分享更多这方面的内容。

Agent Runtime 层的消亡与重生:从上下文牢笼到事件溯源架构 Agent 系统的本质挑战并非模型能力,而是状态管理的工程极限——当上下文窗口成为不可靠的记忆载体,系统便陷入静默崩溃。这引向一个基础技术命题:如何构建可回溯、可恢复、可审计的 agent 执行环境?其核心原理在于将‘会话’从 transient context 解耦为持久化事件流(event log),辅以无状态执行器(harness)与隔离式沙箱(sandbox),形成类操作系统的 runtime 基础设施。该架构显著提升 AI 应用的稳定性、安全性和可观测性,支撑金融风控、医疗推理、供应链协同等高可靠 阅读详情

相关推荐

Agent Runtime 正在成为AI时代的操作系统层

Agent 运行时(Runtime)是支撑大模型智能体可靠执行的核心基础设施,其本质是将非确定性AI行为转化为可追溯、可审计、可重放的结构化事件流。它融合了事件日志(event log)、沙箱隔离(sandbox)、无状态执行器(harness)等关键原理,技术价值在于保障业务连续性、降低调试成本、满足合规审计要求。典型应用场景包括金融合规审查、电商智能工单分派、跨系统自动化对账等高可靠性需求领域。随着 AWS、Google、Microsoft 等云厂商加速推出标准化 Agent Runtime 服务,该层

weixin_33885676的博客 520

K8S学习之helm

helm 是tiller的客户端,tiller是守护进程,helm 请求,tiller接收,与api交互完成创建 helm 包管理工具,下载chart图表, chart部署实例release,chart里有个values.yaml,定义值进行模板安装,其参数可以修改 helm吧k8s的资源打包到图表中 Helm相当于linux环境下的yum包管理工具。 helm是一k8s中的一个命令行客户端工具,helm是tiller的客户端,tiller是一个守护进程,接收helm的请求,helm把请求交给ti

weixin_60092693的博客 8787

k8s Python API

主要使用https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/这个说明, 一般主要是创建pod 和svc,以及更新pod,直接上代码如下: from kubernetes import client, config from kubernetes.client.rest import ApiException def main(): #可以用以下命令把token 放到一个 文件中 # Token.

dz45693的专栏 3089

前端react axios 发送post请求fastapi响应报错422 (Unprocessable Entity)

也有小伙伴会出现发送接送数据出现422,如果你理解了数据不对应的错误原理,那么你就应该分析道,你的json数据是什么格式的?很多时候到这里我们就开始搜索百度、csdn等寻找答案,大多都说是header设置有问题格式不对等等,后来我查寻了官方的文档,发现这个错误其实解决起来很简单的,只要。好像明白了哪里出问题,后端没定义接收数据的类型.因为前端发来的是一个str,我们修改一下后的s的类型试试.,前后端的数据类型一致就可以了,不用什么header设置,不用改这改那的就可以完美解决422的错误问题.

J_Sky:编程爱好者,又菜又爱玩. 2万+

【信息科学与工程学】【安全领域】第一百四十二篇 零信任网络解决方案中的算法04

对于节点 i, 有功和无功功率平衡方程为: Pi​=Vi​∑j=1N​Vj​(Gij​cosθij​+Bij​sinθij​), Qi​=Vi​∑j=1N​Vj​(Gij​sinθij​−Bij​cosθij​)。下风向某点 (x,y,z)的浓度 C为: C=2πuσy​σz​Q​exp(−2σy2​y2​)[exp(−2σz2​(z−H)2​)+exp(−2σz2​(z+H)2​)], 其中 Q是源强, u是风速, H是有效源高, σy​,σz​是水平和垂直扩散参数。

weixin_49199313的博客 1408

解决fetch_california_housing数据集403错误的3种实用方法(附手动下载地址)

本文针对机器学习中常见的fetch_california_housing数据集403 Forbidden错误,提供了三种实用的解决方案。从理解HTTP 403错误的根源出发,详细介绍了修改源码路径、使用国内镜像源以及手动下载并配置数据文件这三种方法,并附带了可靠的手动下载地址,帮助开发者彻底解决数据加载障碍,确保机器学习项目顺利进行。

weixin_29062963的博客 558

2022学习0420【熟悉helm】

1.先下载helm并从阿里源上pull下来一个mysql,我下的是helm-v3.7.1-linux-amd64.tar.gz。 https://blog.51cto.com/u_13760351/2898442 2.尝试helm install mysql --generate-name,报错如下,另外版本要换成apps/v1 问题1:不知道为什么源没有selector [root@VM-0-36-centos helm]# helm install mysql --generate-name Error

qq_43264065的博客 1608

FDTD Solutions-入射波长模式

经常在文献中看到仿真光源使用TM/TE模式,这个确定是十分必要的,决定了仿真结果。 但是也不能局限于选择TM/TE,因为不同领域、不同软件之间的使用习惯和命名可能不同。并且在现代光波导器件中,几乎全部 都是混合模式,或者称之为quasi-TE(准TE模式)和quasi-TM(准TM模式),多数情况下都简称为TE模式和TM模式。要知道 到底是TE模式还是TM模式,需要查看其电场的主分量(即振幅...

HECHUANWANG的博客 1万+

Kubernetes Python Client 初体验之Deployment

Kubernetes官方推荐我们使用各种Controller来管理Pod的生命周期,今天写一个最常用的Deployment的操作例子。 首先是创建Deployment with open(path.join(path.dirname(__file__), "lede_test1.yml")) as f: dep = yaml.safe_load(f) resp = self.a...

Think Different. 2538

ComfyUI工作流换脸节点报错ReActorFaceSwap

找到自己ComfyUI安装目录的custom_nodes下是否有这个comfyui-reactor-node-main。大家在借鉴别人工作流进行AI换脸的时候,如果遇到ReActorFaceSwap报错提示,莫慌,看我的,两步解决问题。这里千万注意不要嵌套文件夹,保证点击去这个文件就可以看到内置的配置文件!找到自己ComfyUI安装目录的facerestore_models。如果有这个文件,直接跳过,去下一步。如果没有,可以去Git官网下载。

qq_70810809的博客 9015

耕地质量评价软件实操指南:如何用Excel+ArcGIS一键生成土壤普查报告(附避坑技巧)

本文提供了一套融合Excel数据处理与ArcGIS空间分析的耕地质量评价实战工作流。详细讲解了从数据规范化预处理、高效数据桥接,到在ArcGIS中实现指标评分、综合指数计算与等级划分的全流程,旨在帮助土壤普查工作者大幅提升报告生成效率与准确性,并分享了关键的避坑技巧。

weixin_28455801的博客 489

GrpConf 2025 笔记(二)

本节课中我们一起学习了 gRPC Rust 的全面介绍。我们从 Rust 语言的基础开始,了解了其因安全性、性能和便利性而流行的原因,以及所有权和生命周期等核心概念。接着,我们探讨了构建 gRPC Rust 的必要性,即满足社区需求并与 gRPC 的安全可靠理念契合。然后,我们深入了解了当前基于 Tonic 的实现、其存在的局限性以及改进方向,包括安全、性能和功能完整性。最后,我们分析了将 gRPC 异步架构适配到 Rust 时遇到的技术挑战(如状态管理的同步访问),并了解了项目的当前进展和未来发布计划。

龙哥盟 59

Mac用户必看:Parallels Desktop 18.1.1最新破解版安装与优化全攻略(附资源)

本文为Mac用户提供Parallels Desktop 18.1.1的详细安装与优化指南,涵盖虚拟化技术选型、专业级配置流程及性能调优技巧。重点解析Parallels Desktop在图形加速、系统资源调度方面的核心优势,并分享生产力增强技巧与典型应用场景实战方案,帮助用户最大化利用这一高效虚拟化工具。

weixin_29240343的博客 816

使用ServiceAccount解决pod自动读取k8s凭证时的错误总结

问题描述:分析:看到User “system:serviceaccount:xxxx” ,起码可以判断出service account已生效。从后面的报错来判断可能是权限不够,在ClusterRole的rules中先赋予全部权限进行测试解决方案:问题解决!但权限的控制需要解决项目来做控制。

shuozhuqiu6452的博客 638

结构力学程序算法理论基础(一)————虚功原理

1.约束 定义约束:限制质点或者质点系运动的条件称为约束,表示这些限制条件的数学方程称为约束方程。 (1)几何约束 限制质点或者质点系在空间的几何位置的条件称为几何约束.如单摆,其中质点M可绕固定点O在平面Oxy内摆动,摆长为l.这时摆杆对质点的限制条件是:质点M必须在以点O为圆心,以l为半径的圆周上运动.其约束方程为: 又质点M在固定的曲面上运动,那么曲面方程就是质点M的约束方程,即 上...

l93919861的博客 4510

本地部署DeepSeek并搭建量化交易系统:完整指南

本地部署DeepSeek并搭建量化交易系统指南 本文提供了一套完整的本地部署DeepSeek大语言模型并构建量化交易系统的技术方案。系统包含以下核心组件: 环境配置:详细说明Ubuntu系统、NVIDIA显卡驱动、CUDA和Python环境的安装要求,推荐使用conda管理依赖 DeepSeek部署: 通过HuggingFace下载7B或13B量化版本模型 使用4-bit量化技术降低显存需求 封装为FastAPI服务提供推理接口 量化系统架构: 模块化设计,各组件通过Redis解耦 包含数据获取、因子计算、

huanghm88的专栏 476

Python开发运维:Python调用K8S API实现资源管理

(3) 操作pod: nginx-deployment-7848d4b86f-57rvf ,将pod镜像nginx修改为busybox。读取pod: nginx-deployment-7848d4b86f-57rvf 信息。(2)编写deployment文件: nginx-deploy.yaml。(1) 编写代码:python-api-deploy.py。(1)编写代码:api-delete-k8s.py。写代码:python-k8s-api.py。写代码:api-read-k8s.py。

cronaldo91的博客 3801

OpenCV实现物体尺寸的测量

物体尺寸测量的思路是找一个确定尺寸的物体作为参照物,根据已知的计算未知物体尺寸。如下图所示,绿色的板子尺寸为220*300(单位:毫米),通过程序计算白色纸片的长度。

qq_53545309的博客 9156

关于 deployment 的 spec.selector 是否必选验证

2、为什么会问出这个问题?是什么妨碍了你写这个字段吗?1、在我的环境上,必选。

看,未来的博客 1147

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

记一次创建deployment资源报错

记一次创建deployment资源报错

soliso 2220

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

2020-12-27

Kubernetes API使用API是什么?K8s APIK8s认证方式示例Python客户端库HTTP API API是什么? API(Application Programming Interface,应用程序接口): 是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。 K8s API K8s也提供API接口,提供这个接口的是管理节点的apiserver组件,ap

qq_28119019的博客 282

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

3、pod 的创建与销毁

1、为什么一个pod要包含多个容器,不是包含一个容器(更好发挥服务器性能,类似与一个pod是一个虚拟机)12、pod的对应列表展示yaml文件中对应列 (-L列出列表,不做选择)7、根据pod 查看yaml 的json格式。16、pod 部署执行的标签的node节点。14、pod标签选择器(-l 选择)4、检查现有pod的yaml的文件。18、pod的命名空间(隔离资源,6、根据yaml文件创建pod。8、查看pod的日志请求。10、pod 标签的作用。2、pod间的网络通讯。11、pod指定标签。

qq_38788128的博客 930

deployment标签(labels)匹配相关知识:spec.selector.matchLables与spec.template.metadata.lables

deployment标签(labels)匹配相关知识:spec.selector.matchLables与spec.template.metadata.lables 1. spec.selector.matchLables实验 1.1 正确的Deployment书写方式,是要让spec.selector.matchLabels值和spec.template.metadata.lables值完全匹配,这样才不会报错。 apiVersion: apps/v1 kind: Deployment me.

梦想起飞的地方......... 1万+

Kubernetes API响应说明

API Server响应用户请求时附带一个状态码,该状态码符合HTTP规范。表3.1列出了API Server可能返回的状态码。 状态码 编码 描述 200 ok 表明请求完成 201 Created 表明创建类的请求完全成功 204 NoContent 表明请求完全成功,同时HTTP响应不包含响应体。 在响应OPTIONS方法的...

qingdao666666的博客 4054

java 调用k8s创建 pod

这里使用的包是 <dependency> <groupId>io.kubernetes</groupId> <artifactId>client-java</artifactId> <version>9.0.0</version> </dependency> <dependency> <groupId>io.kubernetes</groupId&

liaoxiaolin520的博客 3148

python 简单操作k8s

需要注意的是,重启 Pod 操作将会杀死该 Pod 中的容器,并重新启动一个新的容器。因此,在执行重启操作之前,请确保你已经备份了相关数据,并且已经确认该操作不会对应用程序产生不良影响。方法创建 Kubernetes API 客户端。接着,指定要重启的 Pod 的命名空间和名称,并使用。中指定要重启的容器名称和重启次数,以确保重启操作能够正确执行。方法加载 Kubernetes 配置文件,然后使用。方法来重启该 Pod。

weixin_42562106的博客 5548
上一篇: 部署Rasa框架到Kubernetes集群并分配GPU资源
下一篇: python中__file__变量和path模块的配合使用
T型人小付
博客等级 码龄7年 433粉丝 210原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值