Kubeadm安装部署k8s集群、踩坑日常

背景

​ Docker是一个非常流行的容器化平台,它可以让我们方便构建、打包、发布和运行容器化应用程序。但是,在生产环境中,我们可能需要处理成百上千个容器,需要更好的管理这些容器,这就是Kubernetes(K8S)的用武之地。

​ K8S是一个开源容器编排系统,它可以管理和部署容器化应用程序,自动化容器部署、扩展和故障恢复。K8S可以让我们更好管理容器与容器相关的资源和服务,同时提供了许多强大的功能,如:负载均衡、自动扩展、滚动更新、健康检查等。

​ K8S的安装方法有很多,但官方推荐的只包括Kubeadm和二进制安装。因为Kubeadm和二进制安装可以提供更加稳定、更适合生产环境的K8S。本章介绍下如何使用Kubeadm安装K8S集群。

​ 先了解下,两种安装方式(Kubeadm和二进制)的适用场景。Kubeadm是官方提供的开源工具,用于快速搭建K8S集群,也是比较方便和推荐的方式。其中的kubeadm initkubeadm join这两个命令可以快速创建K8S集群。Kubeadm可以初始化K8S,且所有的组件都以Pod形式运行,具有故障自恢复能力。

​ Kubeadm相当于使用程序脚本帮助我们自动完成集群安装,简化部署操作,证书、组件资源清单文件都是自动创建的。自动部署屏蔽了很多细节,使用者对各个模块的了解较少,遇到问题比较难排错。因此,Kubeadm适合需要经常部署K8S或对自动化要求比较高的场景使用。二进制安装就是手动安装,步骤繁琐,对K8S理解的更加全面。

环境准备

服务器

​ 生产环境的K8S需要在服务器上安装,这样表现会更加稳定,若没有生产环境服务器,可以使用虚拟机方式创建3个CentOS7的虚拟机,网络使用桥接或NAT模式都可以。

网络规划

K8S网络规划:

  • podSubnet(Pod网段) 10.244.0.0/16:在K8s中,每个Pod都有一个唯一的IP地址,这个IP地址是在Pod启动时动态分配的。这些Pod IP地址属于一个特定的IP地址段,称为Pod网络。Pod网络是在k8s网络模型中实现的,它允许不同的Pod相互通信,同时允许集群中其他部分与Pod进行通信。

  • serviceSubnet(Service网段) 10.96.0.0/12:在k8s集群中,Service是一种资源对象,用于提供稳定的服务访问入口。它是一组具有相同标签的Pod的抽象,可以通过一个虚拟IP地址和端口暴露出来。

  • 物理机网段192.168.153.0/24:表示IP从192.168.153.1192.168.153.254这个范围内的所有地址都可以在该网络内分配使用

    Tips:Pod和Service的网段不能和物理网段一致,这是因为它们是在集群内部使用的虚拟网络,需要避免和物理机上的网络地址冲突,防止出现不必要的问题。另外,使用不同网段也有助于更好的隔离容器和宿主机之间的网络。因此建议,在部署K8s集群时,将Pod和Service的网段分别设置为独立网段,与物理机网段区分。

K8s集群机器部署组件清单

集群角色IP主机名组件
控制节点192.168.153.180xiaolumaster1apiserver、controller-manager、schedule、kubelet、etcd、kube-proxy、容器运行时、calico、kubeadm
工作节点192.168.153.181xiaolunode1kube-proxy、calico、coredns、容器运行时、kubelet、kubeadm
工作节点192.168.153.182xiaolunode2kube-proxy、calico、coredns、容器运行时、kubelet、kubeadm

安装K8s的机器必须进行相应的初始化设置,否则Kubeadm安装K8s预检查会失败,导致无法继续。下面搞一搞初始化操作。

机器初始化

配置静态IP

​ 服务器或虚拟机的IP地址默认都是DHCP动态分配的,这样重启机器IP地址就会变化,为让IP固定不变,需设置静态IP。

编辑文件:

vim /etc/sysconfig/network-scripts/ifcfg-ens32
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
IPADDR="192.168.153.180"
NETMASK="255.255.255.0"
GATEWAY="192.168.153.2"
DNS1="192.168.153.2"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens32"
UUID="cfcc634b-f183-4e48-a16a-9d3dfd8f8ddb"
DEVICE="ens32"
ONBOOT="yes"
  • BOOTPROTO=“static”:使用静态地址
  • IPADDR=“192.168.153.180” IP地址,需要和自己计算机所在的网段一致
  • NETMASK=“255.255.255.0” 子网掩码,需要和自己计算机所在的网段一致
  • GATEWAY=“192.168.153.2” 网关,可以使用route -n查看自己电脑网关地址
  • ONBOOT=“yes” 开机启动网络,必须yes

修改配置文件之后,需要重启网络才能使配置生效,命令:

service network restart

看下ip地址已经改变了。

在这里插入图片描述

另外两台机器(工作节点),同样的方式设置好,同上的机器部署清单中,将ip先设置好。

配置机器主机名

​ 在K8s集群中,每个节点都需要一个唯一的名称标识自己,这个名称需要在加入集群时使用。若设置主机名,管理员可以更轻松管理容器,方便通过主机名识别和访问每个节点。

  • 192.168.153.180设置为xiaolumaster1
hostnamectl set-hostname xiaolumaster1 && bash
  • 192.168.153.181设置为xiaolunode1
hostnamectl set-hostname xiaolunode1 && bash
  • 192.168.153.182设置为xiaolunode2
hostnamectl set-hostname xiaolunode2 && bash

配置hosts文件

​ 配置hosts文件让每个k8s节点通过主机名互相通信,不需要记ip地址了,修改每台机器的/etc/hosts文件,增加3行

192.168.153.180	xiaolumaster1
192.168.153.181	xiaolunode1
192.168.153.182	xiaolunode2

配置控制节点到工作节点免密登录

​ 在k8s集群中,控制节点需要能通过SSH链接到工作节点中,以执行各种命令和任务,如管理Pod、检查节点状态等。每次都输入密码登录,非常麻烦,建议配置ssh免密登录,提高工作效率。

​ 在控制节点生成ssh密钥

[root@xiaolumaster1 ~]# ssh-keygen

选项直接回车,默认即可。

在这里插入图片描述

​ 可以看到密钥文件生成在root目录下的.ssh目录中。默认情况下,生成一个id_rsa私钥文件和id_rsa.pub公钥文件,私钥应该保持安全,只有持有私钥的用户才能对它进行身份验证。公钥文件交给其他计算机上的授权用户,以便将它添加到本地计算机的授权列表,进而允许该用户在本地计算机上进行ssh连接。

​ 接下来执行命令,将公钥文件发送给各个k8s节点服务器:

[root@xiaolumaster1 ~]# ssh-copy-id xiaolumaster1
[root@xiaolumaster1 ~]# ssh-copy-id xiaolunode1
[root@xiaolumaster1 ~]# ssh-copy-id xiaolunode2

以上命令分别将当前用户的公钥文件(默认~/.ssh/id_rsa.pub)复制到三个节点中,便于用户ssh免密登录。

ssh-copy-id工具会自动使用SSH协议进行连接,在目标计算机建立.ssh目录(若不存在),并将当前用户的公钥追加到目标计算机的~/.ssh/authorized_keys文件中。

关闭交换区

​ Linux中交换分区(Swap)类似于Windows的虚拟内存,就是当内存不足时,把一部分硬盘空间虚拟成内存使用,解决内存容量不足的问题。

​ 在k8s集群中,关闭交换分区可以确保内存不被交换出去,避免内存不足导致应用程序崩溃和节点异常。因为k8s在每个节点部署多个容器,若节点上的应用程序的内存超过了可用内存,操作系统就会将部分的内存换出到硬盘,降低了容器的性能和稳定性。所以在部署k8s集群时,需要关闭交换分区。

两种关闭方式,一种临时,一种永久

1.临时方案

[root@xiaolumaster1 ~]# swapoff -a
[root@xiaolunode1 ~]# swapoff -a
[root@xiaolunode2 ~]# swapoff -a

2.永久性

vim打开/etc/fstab文件,直接注释掉挂载交换分区即可。三台机器都注释掉。

#/dev/mapper/centos-swap swap                    swap    defaults        0 0

fstab全称(File System Table),系统启动时,会读取这个文件的数据,并根据其中的信息自动挂载文件系统。

所以最好重启下机器,重新读取一下fstab文件,或者再执行下临时方案就行了。

修改内核参数

1.加载br_netfilter模块

​ br_netfilter叫透明防火墙,又称桥接模式防火墙。就是在网桥设备中增加防火墙功能。开启ip6tables和iptables需要加载透明防火墙。

[root@xiaolumaster1 ~]# modprobe br_netfilter
[root@xiaolunode1 ~]# modprobe br_netfilter
[root@xiaolunode2 ~]# modprobe br_netfilter

2.启动相关内核参数

​ 在安装配置k8s集群时,需要开启一些内核参数以确保网络功能的正常运行。

  • net.bridge.bridge-nf-call-ip6tables=1 允许iptables对IPV6数据包进行处理
  • net.bridge.bridge-nf-call-iptables=1 允许iptables对桥接数据包进行处理,这是容器间通信必须的
  • net.ipv4.ip_forward=1 linux中允许IP转发功能,使得数据包在不同网络间进行路由

三台机器都需执行

cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
EOF

sysctl -p /etc/sysctl.d/k8s.conf

关闭防火墙

​ 在安装k8s集群时,关闭Firewalld防火墙可以避免由于防火墙造成的k8s集群组件无法正常通信的问题。k8s需要使用大量的网络端口进行通信,包括etcd、kubelet、kube-proxy等组件都需要开放对应的端口才能工作。

​ 在关闭防火墙前,确保已经采取了安全措施,如安全组来保护节点安全问性。

​ 三台机器都执行。

systemctl stop firewalld; systemctl disable firewalld

关闭SELinux

​ 安装k8s集群,通常关闭SELinux,默认情况下,SELinux可能会阻止k8s某些操作,如挂载卷和访问容器日志等。可能使k8s无法正常工作。

​ 1.三台机器关闭SELinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

​ 2.重启服务器

​ 3.验证是否已经关闭

getenforce

显示Disabled,那么说明已经关闭了。

配置安装Docker和Containerd需要的阿里云在线yum源

配置阿里yum源可以提高下载速度,三台机器都执行

sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

配置安装k8s组件需要的阿里云yum源

​ k8s命令包在本地源是不存在的,需要配置阿里云yum源安装k8s命令工具。直接在主节点中配置好,然后通过scp命令拷给其他两个节点即可。

vim /etc/yum.repos.d/kubernetes.repo

[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0

​ 通过远程复制发送到其他两个节点上。

scp /etc/yum.repos.d/kubernetes.repo xiaolunode1:/etc/yum.repos.d/
scp /etc/yum.repos.d/kubernetes.repo xiaolunode2:/etc/yum.repos.d/

配置时间同步

​ 在k8s集群中,时间同步很重要,因为k8s各个组件之间需要通过时间戳确定事件的先后顺序,若各个节点的时间不同步,会导致k8s出现各种问题。三台机器都执行。

yum -y install ntpdate # 安装软件
ntpdate cn.pool.ntp.org # 同步网络时间

crontab -e
* * * * * /usr/sbin/ntpdate cn.pool.ntp.org		# 定时任务同步时间,每分钟执行一次

重启定时任务
service crond restart

安装Docker-CE和Containerd服务

​ K8s是一个容器编排和管理系统,它的任务是在集群中部署、运行和管理容器化应用程序。因此,Kubernetes需要一个容器运行时来管理容器,以便能够将容器化的应用程序部署和运行在集群中。Docker和Containerd都是常用的容器运行时,因此在安装Kubernetes前需要安装其一。

​ 从k8s1.20版本开始,k8s官方将默认的容器运行时从Docker改为了Containerd。在1.24版本后,Docker作为容器运行时已经被弃用,Containerd成为唯一推荐的容器运行时,所有节点均安装,安装步骤如下:

1.安装Containerd

yum install -y containerd.io-1.6.6	# 安装containerd

# 生成containerd配置文件
containerd config default > /etc/containerd/config.toml

vim /etc/containerd/config.toml
# 修改/etc/containerd/config.toml,只需改动一下内容
SystemdCgroup = true
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"
  • SystemdCgroup = true 代表Containerd驱动用Systemd,在k8s中,容器运行时需要与宿主机的Cgroup和Namespace进行交互,管理容器资源。
  • sandbox_image = “registry.aliyuncs.com/google_containers/pause:3.7”,设置为阿里云镜像仓库中的pause:3.7。

2.创建/etc/crictl.yaml文件

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

这个文件是crictl工具的配置文件,用于指定与Containerd交互的相关设置。

指定unix:///run/containerd/containerd.sock是为了告诉crictl使用UNIX套接字的方式来连接Containerd的API。Containerd提供了一个Socket文件unix:///run/containerd/containerd.sock,crictl通过连接这个Socket文件可以与Containerd进行通信,实现管理容器和镜像等操作。

3.配置Containerd镜像加速器

编辑/etc/containerd/config.toml文件

vim /etc/containerd/config.toml

config_path = "/etc/containerd/certs.d" #指定containerd的证书存放目录

创建证书等目录文件

# 创建目录
mkdir /etc/containerd/certs.d/docker.io/ -p

vim /etc/containerd/certs.d/docker.io/hosts.toml		# 创建文件

# 内容如下
[host."https://6yqx5sih.mirror.aliyuncs.com",host."https://registry.docker-cn.com"]
capabilities = ["pull","push"]

4.重启Containerd来使配置生效

systemctl restart containerd

5.安装Docker,配置Docker镜像加速

yum install -y docker-ce
systemctl enable docker

vim /etc/docker/daemon.json

{
    "registry-mirrors":[
        "https://6yqx5sih.mirror.aliyuncs.com",
        "https://registry.docker-cn.com",
        "https://docker.mirrors.ustc.edu.cn",
        "http://hub-mirror.c.163.com"
    ]
}

systemctl restart docker

安装部署Kubernetes集群

安装Kubernetes集群需要的包

所有节点都需要执行。

yum install -y kubelet-1.27.0 kubeadm-1.27.0 kubectl-1.27.0
  • kubelet:k8s的一个核心组件,负责在每个节点上运行Pod并管理声明周期,它通过容器运行时(Docker或Containerd)来运行容器。kubelet负责监控容器状态、资源使用情况和网络连接情况,将这些信息报告给k8s其他组件,以便它们协调容器在集群中的运行。
  • Kubeadm:用于启动k8s集群的命令工具。
  • Kubectl:k8s的命令行工具,管理k8s集群的各个方面,包括创建、部署、管理和监控应用程序、服务和资源。Kubectl可以和K8s API服务器交互,管理集群。
#开机自启
systemctl enable kubelet

Kubeadm初始化Kubernetes集群

这里只需要controller控制节点来初始化即可,然后其他work节点join进来。

kubeadm config print init-defaults > kubeadm.ymal

kubeadm config print init-defaults:是Kubeadm的命令,用于打印默认的Kubernetes初始化配置内容,并且输出到一个文件中。之后使用kubeadm init初始化k8s集群,可以使用这个文件作为输入,而不是手动输入。添加并修改相应的配置,如下

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.153.180	# ip地址
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  name: xiaolumaster1	# 主机
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers	# 阿里云镜像仓库
kind: ClusterConfiguration
kubernetesVersion: 1.27.0
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16	# pod网段
  serviceSubnet: 10.96.0.0/12	# service网段
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd

kubeadm初始化Kubenetes集群

kubeadm init --config=kubeadm.ymal --ignore-preflight-errors=SystemVerification

在这里插入图片描述

如图,说明已经安装完成。

重置k8s集群

​ 我们执行完毕kubeadm init后发现不想把这台机器作为controller来使用了,那么我们可以使用kubeadm reset命令将k8s集群进行重置。

kubeadm reset

配置Kubectl配置文件config

​ 默认安装K8s后,Kubectl是无权限访问K8s的API的,所以需要一个config文件,相当于是对kubectl进行授权,这样Kubectl命令可以使用config文件中的用户和证书对k8s集群进行管理。

​ 主目录创建一个.kube目录,存放全局config文件

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # 将config拷过来更名

sudo chown $(id -u):$(id -g) $HOME/.kube/config # 设置权限
  • 查看k8s集群
kubectl get nodes

在这里插入图片描述

有一个名为xiaolumaster1的控制节点名称,集群状态NotReady,因为没有安装网络插件。

扩容Kubernets集群

​ 通过前面的安装步骤,是单节点的Kubernetes,即整个集群只有一个controller控制节点。在k8s中,控制节点是有污点的,不允许Pod调度,控制节点是不希望有业务Pod运行的,所以需要扩容增加工作节点。

在controller(控制节点,以下内容中,控制节点统称controller,工作节点称为work)上,创建加入节点的命令行:

kubeadm token create --print-join-command
kubeadm join 192.168.153.180:6443 --token mqp4fj.6q9n6fglby7d7c1z --discovery-token-ca-cert-hash sha256:2e16927670268b431886daca133777d82072c9b87864dbbe6092de7bbda55a29

work节点需要执行上面的kubeadm join命令以加入到节点中,执行后,结果如下

在这里插入图片描述

在这里插入图片描述

​ 可以看到,集群中又增加了两位小伙伴,它们的角色现在都是None,通常来讲我们是将另外两个none角色的节点称之为工作节点,在controller中将它们两个设置为worker即可

kubectl label node xiaolunode1 node-role.kubernetes.io/worker=worker
kubectl label node xiaolunode2 node-role.kubernetes.io/worker=worker

在这里插入图片描述

ok了,集群中状态都是NotReady状态,我们安装完网络插件就好了。

安装网络插件Calico

上传calico.yaml文件到controller上,使用ymal文件安装Calico。

kubectl apply -f calico.yaml

使用kubectl部署k8s网络插件calico。

  • kubectl apply : 用于通过yml文件来创建或更新Kubernetes资源
  • -f calico.yaml 将指定的yml文件应用于当前的k8s环境

安装完毕后,再次查看k8s集群状态。

kubectl get nodes

在这里插入图片描述

温馨Tips:若发现经过此步骤一直有节点NotReady,可以将所有机器进行kubeadm reset,重启kubelet命令systemctl restart kubelet,然后重新执行一遍上面的初始化集群步骤,然后先安装完毕calico之后,再重新加入两个节点即可。

网络测试&DNS测试

测试网络

测试下k8s中创建的Pod能否正常访问网络。

kubectl run busybox4 --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # ping www.baidu.com

在这里插入图片描述

在k8s集群上创建了一个名为busybox4的Pod,然后在此Pod内运行了一个BusyBox容器。

最后在/的工作目录中,ping了一下www.baidu.com,然后显示IP地址、数据字节等。可以看到,在k8s中创建的Pod能访问,说明Calico网络插件已经正常安装了,可以访问网络。

测试CoreDNS是否正常

​ CoreDNS是一个Kubernetes集群中非常重要的DNS服务器,它通过提供命名服务简化服务间 通信和DNS解析的管理和维护。

​ 在K8s中,每个Pod有一个唯一的DNS名称,如pod-name.namespace-name.svc.cluster-domain.tld,其中cluster-domain.tld是集群中使用的域名后缀。每个服务都有一个DNS名称,pod-name.namespace-name.svc.cluster-domain.tld,它将解析为该服务的集群IP地址。

​ CoreDNS使用插件来支持各种DNS记录类型,例如A、CNAME、SRV等。它可以与k8s的API服务器进行交互,以了解k8s中运行的应用程序和服务状态。

kubectl run busybox4 --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # nslookup kubernetes.default.svc.cluster.local

在这里插入图片描述

  • nslookup kubernetes.default.svc.cluster.local:用于解析k8s中的apiserver这个Pod前面的代理service域名,内部service的名称是通过coreDNS解析的,10.96.0.10就是coreDNS的clusterIP,说明coreDNS已经配置好了。

延长证书

Kubeadm安装的k8s默认证书有效一年,过了一年API Server就会禁止连接,所以需要将证书延长。

查看下证书的有效时间:

openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text | grep Not
Not Before: May 25 08:16:52 2024 GMT
Not After : May 23 08:16:52 2034 GMT

我这里是10年有效期,实现的步骤还是梳理下:

需要将update-kubeadm-cert.sh文件上传到controller节点,然后赋权限,执行即可。

chmod +x update-kubeadm-cert.sh
./update-kubeadm-cert.sh all

执行完毕后,查看下Pod是否正常,若能查询出数据,那么证书签发完成。

kubectl get pods -n kube-system

在这里插入图片描述

  • 查看证书时长
openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text | grep Not

Not Before: May 25 08:16:52 2024 GMT
Not After : May 23 08:16:52 2034 GMT
  • apiserver证书
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not

Not Before: May 25 08:16:52 2024 GMT
Not After : May 23 08:16:52 2034 GMT
  • etcd证书
openssl x509 -in /etc/kubernetes/pki/apiserver-etcd-client.crt -noout -text | grep Not

Not Before: May 25 08:16:52 2024 GMT
Not After : May 23 08:16:52 2034 GMT
  • proxy证书
openssl x509 -in /etc/kubernetes/pki/front-proxy-ca.crt -noout -text | grep Not

Not Before: May 25 08:16:52 2024 GMT
Not After : May 23 08:16:52 2034 GMT
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值