干货 | 京东云托管Kubernetes集成镜像仓库并部署原生DashBoard

干货 | 京东云托管Kubernetes集成镜像仓库并部署原生DashBoard

原创:   成晨   京东云开发者社区    昨天

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


在上一篇“Cloud Native 实操系列”文章中,我们为大家介绍了 如何通过京东云原生容器实现Eureka的部署 (? 可点击查看原文内容 )。今天,我们将为大家介绍京东云托管Kubernetes集成镜像仓库并部署原生DashBoard。


随着Docker技术的发展和广泛流行,云原生应用和容器调度管理系统爆之也成为IT领域大热的词汇。事实上,云原生应用的思想,在Docker技术火前,已经由云计算技术的领导者和分布式系统架构的推广者广泛传播,例如云原生应用的12要素早在2011年就由Heroku的工程师提出了;只不过以虚拟机技术作为云原生应用的基础实施,由于虚拟机镜像大、镜像标准不统一以及打包流程和工具不统一,无法业界广泛接受的云原生应用标准,限制了云原生应用的流行。而Docker的出现正好解决了这些限制云原生应用构建、交付和运行的瓶颈,使得构建云原生应用成为了使用Docker的开发者自然而然的选择。


单机的Docker引擎和单一的容器镜像只能解决单一服务的打包和测试问题。而要运行生产级的企业级应用,就需要容器调度管理系统。在这里面,Docker技术就仿佛运送系统零件的集装箱,把云原生应用的各个标准化零件交付到各个企业的不同码头,而容器调度管理系统就是企业应用的运行车间,把不同的零件组装、运行、维护起来。



1. 京东云Kubernetes介绍

Kubernetes是为生产环境而设计的容器调度管理系统,对于负载均衡、服务发现、高可用、滚动升级、自动伸缩等容器云平台的功能要求有原生支持。由于Kubernetes在K和s间有8个字母,因此常简称K8s。事实上,随着对K8s系统架构与设计理念的了解深入,我们会发现K8s系统正是处处为运行云原生应用而设计考虑;同时,随着对K8s系统使用的加深和加广,也会有越来越多有关云原生应用的设计模式产生出来,使得基于K8s系统设计和开发生产级的复杂云原生应用变得像启动一个单机版容器服务那样简单易用。


根据CNCF在2018年8月进行的第六次测量容器管理市场的温度,83%的受访者更喜欢Kubernetes的容器管理工具,58%的受访者在生产中使用Kubernetes,42%的受访者正在进行评估以备将来使用,40%的企业(员工规模在5000+)正在使用Kubernetes。Kubernetes在开发人员中已经变得非常流行。

京东云Kubernetes集群采用管理节点全托管的方式,为用户提供简单易用、高可靠、功能强大的容器管理服务。该产品完全兼容标准Kubernetes API ,集成京东云网络、存储等插件。Kubernetes集群服务简化了Kubernetes部署、管理,降低了Kubernetes使用门槛,增强应用的可靠性,提升开发的效率,减少资源投入成本。

1.1 产品优势

相较于传统自建Kubernetes集群,京东云Kubernetes集群服务有如下优势:

  • 易用性:在控制台一键式创建Kubernetes集群服务;管理节点采用全托管的方式,免除繁琐的部署、运维、升级等工作;提供工作节点定制镜像,预置集群工作节点所需的各种组件。

  • 可靠性:同地域下,集群的管理、工作节点可跨可用区部署,支持单集群至少运行三台云主机作为管理节点,同时基于京东云高可用组隔离故障域,进一步增强了可靠性。

  • 功能性:基于京东云SDN网络,提供CNI网络插件,依托京东云私有网络的高可用及可靠性,轻松适应不同规模生产环境的网络需求;提供CRI存储插件,集成京东云云硬盘,提供安全可靠的持久化存储;集成京东云负载均衡服务,提供安全、可靠的网络访问。

  • 性价比:京东云Kubernetes集群服务本身暂时免费,目前您只需为集群中创建的云主机、公网IP、云硬盘等云资源按需付费。


1.2 京东云Kubernetes部署架构

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

k8s培训

下面会演示京东云Kubernetes集成京东云镜像仓库,构建原生dashboard的最佳实践,希望能起到抛砖引玉的作用。


2. 环境准备

2.1 创建AK、SK

登陆京东云控制台后,点击账号下拉菜单,选择 Access Key 管理。

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

点击 创建 ,并输入相关手机号码。

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1


至此AK、SK创建成功。
640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

2.2 容器镜像仓库准备

选择容器镜像仓库:

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

镜像仓库模板为: registry-URL/repository:tag ,所以我们创建顺序为:

  1. 创建注册表

  2. 创建仓库

2.2.1 创建注册表

点击 创建 按钮,后输入注册表名称,本例中的名称为: pocexam .

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

2.2.2 创建镜像仓库

由于Kubernetes 官方dashboard 镜像 kubernetes-dashboard-amd64 为国外资源,国内无法pull,所以我们需要先从Google镜像仓库push到本地后再上传到镜像仓库。

此处创建镜像仓库时的名称为: kubernetes-dashboard-amd64

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1
2.2.3 上传Kubernetes-dashboard镜像

此处需要创建一台Linux云主机(建议使用Ubuntu镜像),并安装Docker。此处不再赘述。通过ssh工具连接,执行如下命令安装Docker工具:



1

apt-

get

 install -y docker.io

由于国内网络原因,Google官方镜像 k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 无法pull,所以我们需要从docker.io仓库的Google容器镜像进行拉取:



1


docker

 pull mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.

10

.

1


然后执行 docker images 会看到拉取到的镜像。

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

上传至京东云镜像仓库之前,需要有上传权限,可以通过临时令牌的方式登录并上传镜像。
获取临时令牌方法为: 京东云控制台-->容器镜像仓库-->注册表 ,选择之前创建的registry,右侧点击获取临时令牌:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

设置有效期:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

确认后,可以获得多种格式的登陆方式,本次操作使用 Docker客户端登录命令 ,点击复制按钮,并在Linux云主机中执行。

需要注意:完全复制粘贴到Linux shell 命令中即可,无需修改任何参数。

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 修改为 $registry-URL/kubernetes-dashboard-amd64:v1.10.1 ,此处的registry-URL变量需要替换为你所创建的registry的值,或者可以在控制台获取到:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

比如本次操作的值为 pocexam-cn-north-1.jcr.service.jdcloud.com/kubernetes-dashboard-amd64 ,那么操作命令如下:



1


docker

 tag mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.

10

.

1

 pocexam-cn-north-

1

.jcr.service.jdcloud.com/kubernetes-dashboard-amd64:v1.

10

.

1

 && docker push !$

修改tag并成功上传至京东云镜像仓库的截图如下:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

在控制台可以验证到已成功上传:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

2.3 创建Kubernetes集群

2.3.1 创建Kubernetes所需的基础网络

首先创建VPC: 控制台-->网络-->私有网络(VPC)

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

划分子网: 控制台-->网络-->子网

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

创建Kubernetes集群, 控制台-->弹性计算-->Kubernetes集群

注意需要选择AK,修改node节点的CIDR,避免与集群中的service、pod冲突。

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1 640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

点击确认后,等待若干分钟,集群创建成功,目前支持的版本为1.12.3。


2.4 云主机Kubernetes客户端配置

在Linux云主机上,执行如下shell命令:



1

wget https://pocexam.s3.cn-north-1.jdcloud-oss.com/kubernetes-client-linux-amd64.tar.gz

2 tar zxvf kubernetes-client-linux-amd64.tar.gz &&  cd  kubernetes/client/bin/
3 chmod +x kubectl && sudo mv ./kubectl /usr/ local /bin/kubectl


2.5 配置集群凭证

在Linux云主机执行如下shell命令,创建相关配置文件,并将Kubernetes的连接信息写入config文件,保存退出:



1

mkdir -p ~

/.kube && vi ~/

.kube/config

连接信息获取方式为: 控制台-->弹性计算-->Kubernetes集群 ,点击创建的Kubernetes集群名称。

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1 640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

将文本框中的内容保存至 ~/.kube/config 文件中。然后执行 kubectl version 命令,显示如下信息表示连接成功:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


3. Kubernetes集群集成京东云镜像仓库

参考帮助文档链接:https://docs.jdcloud.com/cn/jcs-for-kubernetes/deploy-container-registry

3.1 创建具有时效性的secret

在Linux云主机shell中操作:



1

kubectl create secret docker-registry 

my

-secret -n kube-

system

 --docker-server=pocexam-cn-north-

1

.jcr.service.jdcloud.com --docker-username=jdcloud --docker-password=z7G4sQTHMaNG0GRN --docker-email=chengchen3@jd.com

需要注意如下参数的值:

  • docker-server:你创建的镜像仓库的注册表URL。

  • docker-username:默认jdcloud,无需修改。

  • docker-password:在临时令牌中获取,详情参考下图(获取secret所需的临时密码)。

  • docker-email:用户自定义邮箱。

  • -n 参数,默认为 default  namespace,本次部署绑定到kube-system。 未来yaml配置文件中,你要创建pod或者deployment所在的namesapce,必须与本次创建的secret所在的namesapce保证一直,否则会出现ErrImagePullw的问题


3.1.1 获取secret所需的临时密码

在镜像仓库中选择注册表,点击 获取临时令牌:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

红框中标识的内容即临时密码。

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

3.2 自动定期获取临时令牌,长期有效

shell中执行如下命令:



1


#创建相关基于角色的访问控制(RBAC)


2 kubectl  apply -f https://pocexam.s3.cn-north-1.jdcloud-oss.com/jcr-credential-rbac.yaml

下载 jcr-credential-cron.yaml 文件,设定每一个小时获取临时令牌,请使用时添加JDCLOUD_ACCESS_KEY和JDCLOUD_SECRET_KEY内容。



1


cd

 

~

2 wget
 https://pocexam.s3.cn-north-1.jdcloud-oss.com/jcr-credential-cron.yaml

修改部分变量的值:



 1

apiVersion: batch/v1beta1

2 kind: CronJob
3 metadata:
4   name: jdcloud-jcr-credential-cron
5 spec:
6   schedule:  "0 */1 * * *"   # 0代表每小时的整点,您可以根据需要修改时间,如改成15代表每小时的第15分钟获取临时令牌。
7   successfulJobsHistoryLimit: 2
8   failedJobsHistoryLimit: 2  
9   jobTemplate:
10     spec:
11       backoffLimit: 4
12       template:
13         spec:
14           serviceAccountName: default
15           terminationGracePeriodSeconds: 0
16           restartPolicy: Never
17           hostNetwork:  true
18           containers:
19           - name: jcr-token-refresher
20             imagePullPolicy: Always
21             image: jdcloudcli/jdcloud-cli:latest
22              command :
23             -  "/bin/sh"
24             -  "-c"
25             - |
26                ##REGISTRY_NAME变量需要修改为你的的镜像仓库注册表的名称
27               REGISTRY_NAME=XXX
28                ##JCR_REGION变量需要修改为你的镜像仓库所在的region
29               JCR_REGION=cn-north-1
30               DOCKER_REGISTRY_SERVER=https:// ${REGISTRY_NAME} - ${JCR_REGION} .jcr.service.jdcloud.com
31               DOCKER_USER=jdcloud
32                ##JDCLOUD_ACCESS_KEY和JDCLOUD_SECRET_KEY需要修改为你的pin的AK、SK的值
33               JDCLOUD_ACCESS_KEY=xxxxxxxxxxxxxx
34               JDCLOUD_SECRET_KEY=xxxxxxxxxxxxx
35               jdc configure add --profile  ${DOCKER_USER}  --access-key  ${JDCLOUD_ACCESS_KEY}  --secret-key  ${JDCLOUD_SECRET_KEY}
36               PRECHECK=`jdc cr get-authorization-token --region-id  ${JCR_REGION}  --registry-name  ${REGISTRY_NAME}  |jq .result.authorizationToken`
37                if  [  'null'  =  " $PRECHECK "  ];  then
38                    echo   "jdc cr call failed no valid content"  
39                    exit  0 
40                else
41                    echo   "jdc cr call return authentication string"
42                fi ;
43               DOCKER_PASSWORD=` echo   ${PRECHECK}  | base64 -d |cut  -d   ':'  -f2`
44               kubectl delete secret my-secret ||  true
45                echo   "0:" $PRECHECK
46                echo   "1:" $DOCKER_REGISTRY_SERVER
47                echo   "2:" $DOCKER_USER
48                echo   "3:" $DOCKER_PASSWORD46 /15555780261891.jpg)
49
50
51
52
53
54
55
56
57
58               kubectl create secret docker-registry my-secret \
59               --docker-server= $DOCKER_REGISTRY_SERVER  \
60               --docker-username= $DOCKER_USER  \
61               --docker-password= $DOCKER_PASSWORD  \
62                ##docker-email修改为你的邮箱地址
63               --docker-email=xxxx@jd.com
64               kubectl patch serviceaccount default  -p  '{"imagePullSecrets":[{"name":"my-secret"}]}'   # kubectl patch  $SERVICEACCOUNT xxxxx  -n $NAMESPACEOFSERVICEACCOUNT

变量修改完成后,shell中执行如下命令,创建Kubernetes的计划任务:

1kubectl apply -f jcr-credential-cron.yaml


4. 部署dashboard

在Linux云主机中执行如下命令,下载dashboard相关yaml配置文件:



1


wget

 https://pocexam.s3.cn-north-1.jdcloud-oss.com/db.yml

需要修改镜像地址为之前上传的Kubernetes-dashboard地址:



  1


# Copyright 2017 The Kubernetes Authors.


 2 #
 3 # Licensed under the Apache License, Version 2.0 (the "License");
 4 # you may not use this file except in compliance with the License.
 5 # You may obtain a copy of the License at
 6 #
 7 #     http://www.apache.org/licenses/LICENSE-2.0
 8 #
 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # ------------------- Dashboard Secret ------------------- #
16
17 apiVersion: v1
18 kind: Secret
19 metadata:
20   labels:
21     k8s-app: kubernetes-dashboard
22   name: kubernetes-dashboard-certs
23   namespace: kube-system
24 type: Opaque
25
26 ---
27 # ------------------- Dashboard Service Account ------------------- #
28
29 apiVersion: v1
30 kind: ServiceAccount
31 metadata:
32   labels:
33     k8s-app: kubernetes-dashboard
34   name: kubernetes-dashboard
35   namespace: kube-system
36
37 ---
38 # ------------------- Dashboard Role & Role Binding ------------------- #
39
40 kind: Role
41 apiVersion: rbac.authorization.k8s.io/v1
42 metadata:
43   name: kubernetes-dashboard-minimal
44   namespace: kube-system
45 rules:
46    # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
47 - apiGroups: [ "" ]
48   resources: [ "secrets" ]
49   verbs: [ "create" ]
50    # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
51 - apiGroups: [ "" ]
52   resources: [ "configmaps" ]
53   verbs: [ "create" ]
54    # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
55 - apiGroups: [ "" ]
56   resources: [ "secrets" ]
57   resourceNames: [ "kubernetes-dashboard-key-holder" "kubernetes-dashboard-certs" ]
58   verbs: [ "get" "update" "delete" ]
59    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
60 - apiGroups: [ "" ]
61   resources: [ "configmaps" ]
62   resourceNames: [ "kubernetes-dashboard-settings" ]
63   verbs: [ "get" "update" ]
64    # Allow Dashboard to get metrics from heapster.
65 - apiGroups: [ "" ]
66   resources: [ "services" ]
67   resourceNames: [ "heapster" ]
68   verbs: [ "proxy" ]
69 - apiGroups: [ "" ]
70   resources: [ "services/proxy" ]
71   resourceNames: [ "heapster" "http:heapster:" "https:heapster:" ]
72   verbs: [ "get" ]
73
74 ---
75 apiVersion: rbac.authorization.k8s.io/v1
76 kind: RoleBinding
77 metadata:
78   name: kubernetes-dashboard-minimal
79   namespace: kube-system
80 roleRef:
81   apiGroup: rbac.authorization.k8s.io
82   kind: Role
83   name: kubernetes-dashboard-minimal
84 subjects:
85 - kind: ServiceAccount
86   name: kubernetes-dashboard
87   namespace: kube-system
88
89 ---
90 # ------------------- Dashboard Deployment ------------------- #
91
92 kind: Deployment
93 apiVersion: apps/v1
94 metadata:
95   labels:
96     k8s-app: kubernetes-dashboard
97   name: kubernetes-dashboard
98   namespace: kube-system
99 spec:
100   replicas: 1
101   revisionHistoryLimit: 10
102   selector:
103     matchLabels:
104       k8s-app: kubernetes-dashboard
105   template:
106     metadata:
107       labels:
108         k8s-app: kubernetes-dashboard
109     spec:
110       containers:
111       - name: kubernetes-dashboard
112          ##此处修改为你之前上传到镜像仓库的dashboard地址
113         image: Myregistry-cn-north-1.jcr.service.jdcloud.com/kubernetes-dashboard-amd64:v1.10.1
114         ports:
115         - containerPort: 8443
116           protocol: TCP
117         args:
118           - --auto-generate-certificates
119            # Uncomment the following line to manually specify Kubernetes API server Host
120            # If not specified, Dashboard will attempt to auto discover the API server and connect
121            # to it. Uncomment only if the default does not work.
122            # - --apiserver-host=http://my-address:port
123         volumeMounts:
124         - name: kubernetes-dashboard-certs
125           mountPath: /certs
126            # Create on-disk volume to store exec logs
127         - mountPath: /tmp
128           name: tmp-volume
129         livenessProbe:
130           httpGet:
131             scheme: HTTPS
132             path: /
133             port: 8443
134           initialDelaySeconds: 30
135           timeoutSeconds: 30
136       volumes:
137       - name: kubernetes-dashboard-certs
138         secret:
139           secretName: kubernetes-dashboard-certs
140       - name: tmp-volume
141         emptyDir: {}
142       serviceAccountName: kubernetes-dashboard
143       imagePullSecrets:
144         - name: my-secret
145        # Comment the following tolerations if Dashboard must not be deployed on master
146       tolerations:
147       - key: node-role.kubernetes.io/master
148         effect: NoSchedule
149
150 ---
151 # ------------------- Dashboard Service ------------------- #
152 # ------------------- 此处设置在京东云自动创建LB并绑定带宽为10Mbps的公网IP------------------- #
153 kind: Service
154 apiVersion: v1
155 metadata:
156   name: dashboard-lb
157   namespace: kube-system
158   labels:
159     k8s-app: kubernetes-dashboard
160 spec:
161   ports:
162     - protocol: TCP
163       port: 9443
164       targetPort: 8443
165       nodePort: 30063
166   type: LoadBalancer
167   selector:
168      k8s-app: kubernetes-dashboard

shell中创建Kubernetes deployment:



1


kubectl

 

apply

 

-f

 

db


.yml


查看集群中所有的service:



1


kubectl

 get svc --

all

-namespaces

可以看到正在创建LB对应的公网IP:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


稍等1分钟左右再查看,可以看到LB已绑定公网IP:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

查看所有namespace的pod,可以看到已成功pull:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


5. 访问dashboard

使用Chrome或者Firefox浏览器访问service所绑定的公网IP以及对应端口,本次实验中访问:https://192.168.125.165:9443,会看到如下信息:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

本次访问我们使用令牌访问全部权限。 认证时的账号必须为ServiceAccount,被dashboard的pod拿来由kubernetes进行认证

5.1 创建ServiceAccount



1

kubectl 

create

 serviceaccount dashboard-

admin

 -n kube-

system



5.2 绑定相关Role

1kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

相关参数:

  • clusterrole :指定使用的集群角色,系统默认自带很多,建议指定。

  • serviceaccount :指定认证使用的ServiceAccount,由上一步创建。


5.3 获取Secret

1kubectl describe sa dashboard-admin -n kube-system

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

由此可知,本例中 dashboard-admin-token-wf2tj 为使用的Secret。


5.4 获取Token

执行shell命令查看对应secret相关信息:



1

kubectl 

describe

 secrets -n kube-

system

 dashboard-

admin

-token-wf2tj

下图中获取到的token即访问凭证。

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1

将其复制粘贴到浏览器中即可登录成功:

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1 640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1


点击“ 阅读原文 ”,了解更多京东云K8s产品信息



640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1



福利预警


京东云开发者社区用户专属福利!

参加沙龙活动,免费得CNCF大会门票!

???

640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1



阅读原文
 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69912185/viewspace-2645293/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/69912185/viewspace-2645293/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值