k8s使用statefulset部署mysql一主多从集群

部署原理

在这里插入图片描述

1、准备环境

服务器2核4G
139.198.38.94
139.198.41.101
139.198.31.125

需要提前准备好NFS挂载,此处用的是静态nfs

#所有机器安装
yum install -y nfs-utils

主节点

#nfs主节点
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports

mkdir -p /nfs/data
systemctl enable rpcbind --now
systemctl enable nfs-server --now
#配置生效
exportfs -r

从节点

showmount -e 139.198.38.94

#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir -p /nfs/data

mount -t nfs 139.198.38.94:/nfs/data /nfs/data

静态pv池

#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03

二、部署MySQL

(1)从以下的 YAML 配置文件创建 ConfigMap

configmap(作用配置文件和镜像解藕)

[root@master mysql]# cat cm.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  master.cnf: |
    [mysqld]
    log-bin     # 主mysql激活二进制日志
  slave.cnf: |
    [mysqld]
    super-read-only     # 从mysql上面设置为只读

这个 ConfigMap 提供 my.cnf 覆盖,使您可以独立控制 MySQL 主服务器和从服务器的配置。 在这种情况下,您希望主服务器能够将复制日志提供给从服务器,并且希望从服务器拒绝任何不是通过复制进行的写操作。

ConfigMap 本身没有什么特别之处,它可以使不同部分应用于不同的 Pod。 每个 Pod 都会决定在初始化时要看基于 StatefulSet 控制器提供的信息。

(2)从以下 YAML 配置文件创建服务

[root@master mysql]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql      
spec:
  ports:
  - name: mysql   # 负责写
    port: 3306
  clusterIP: None
  selector:
    app: mysql
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-read     #只读
  labels:
    app: mysql
spec:
  ports:
  - name: mysql
    port: 3306
  selector:
    app: mysql

Headless Service 给 StatefulSet 控制器为集合中每个 Pod 创建的 DNS 条目提供了一个宿主。因为 Headless Service 名为 mysql,所以可以通过在同一 Kubernetes 集群和 namespace 中的任何其他 Pod 内解析 .mysql来访问 Pod。

客户端 Service 称为 mysql-read,是一种常规 Service,具有其自己的群集 IP,该群集 IP 在报告为就绪的所有MySQL Pod 中分配连接。可能端点的集合包括 MySQL 主节点和所有从节点。

请注意,只有读取查询才能使用负载平衡的客户端 Service。因为只有一个 MySQL 主服务器,所以客户端应直接连接到 MySQL 主服务器 Pod (通过其在 Headless Service 中的 DNS 条目)以执行写入操作。

(3)从以下 YAML 配置文件创建PV

[root@master mysql]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-mysql01
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  nfs:
    path: /nfs/data/01
    server: 192.168.10.11
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-mysql02
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  nfs:
    path: /nfs/data/02
    server: 192.168.10.11
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-mysql03
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  nfs:
    path: /nfs/data/03
    server: 192.168.10.11

master写,slave读。NFS映射mysql文件到本地,删除或重启pod或容器不会删除文件。

(4)最后,从以下 YAML 配置文件创建 StatefulSet pod

[root@master mysql]# cat sts.yaml 
# statefulset.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  serviceName: mysql
  replicas: 3
  template:
    metadata:
      labels:
        app: mysql
    spec:
      initContainers:
      - name: init-mysql
        image: mysql:5.7
        command:
        - bash
        - "-c"
        - |
          set -ex
          # Generate mysql server-id from pod ordinal index.
          [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
          ordinal=${BASH_REMATCH[1]}
          echo [mysqld] > /mnt/conf.d/server-id.cnf
          # Add an offset to avoid reserved server-id=0 value.
          echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
          # Copy appropriate conf.d files from config-map to emptyDir.
          if [[ $ordinal -eq 0 ]]; then
            cp /mnt/config-map/master.cnf /mnt/conf.d/
          else
            cp /mnt/config-map/slave.cnf /mnt/conf.d/
          fi          
        volumeMounts:
        - name: conf
          mountPath: /mnt/conf.d
        - name: config-map
          mountPath: /mnt/config-map
      - name: clone-mysql
        image: ist0ne/xtrabackup   #此处镜像我做了修改
        command:
        - bash
        - "-c"
        - |
          set -ex
          # Skip the clone if data already exists.
          [[ -d /var/lib/mysql/mysql ]] && exit 0
          # Skip the clone on master (ordinal index 0).
          [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
          ordinal=${BASH_REMATCH[1]}
          [[ $ordinal -eq 0 ]] && exit 0
          # Clone data from previous peer.
          ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
          # Prepare the backup.
          xtrabackup --prepare --target-dir=/var/lib/mysql          
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ALLOW_EMPTY_PASSWORD
          value: "1"
        ports:
        - name: mysql
          containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping"]
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            # Check we can execute queries over TCP (skip-networking is off).
            command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
          initialDelaySeconds: 5
          periodSeconds: 2
          timeoutSeconds: 1      
      - name: xtrabackup
        image: ist0ne/xtrabackup  #此处镜像我做了修改
        ports:
        - name: xtrabackup
          containerPort: 3307
        command:
        - bash
        - "-c"
        - |
          set -ex
          cd /var/lib/mysql

          # Determine binlog position of cloned data, if any.
          if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
            # XtraBackup already generated a partial "CHANGE MASTER TO" query
            # because we're cloning from an existing slave. (Need to remove the tailing semicolon!)
            cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
            # Ignore xtrabackup_binlog_info in this case (it's useless).
            rm -f xtrabackup_slave_info xtrabackup_binlog_info
          elif [[ -f xtrabackup_binlog_info ]]; then
            # We're cloning directly from master. Parse binlog position.
            [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
            rm -f xtrabackup_binlog_info xtrabackup_slave_info
            echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
                  MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
          fi

          # Check if we need to complete a clone by starting replication.
          if [[ -f change_master_to.sql.in ]]; then
            echo "Waiting for mysqld to be ready (accepting connections)"
            until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done

            echo "Initializing replication from clone position"
            mysql -h 127.0.0.1 \
                  -e "$(<change_master_to.sql.in), \
                          MASTER_HOST='mysql-0.mysql', \
                          MASTER_USER='root', \
                          MASTER_PASSWORD='', \
                          MASTER_CONNECT_RETRY=10; \
                        START SLAVE;" || exit 1
            # In case of container restart, attempt this at-most-once.
            mv change_master_to.sql.in change_master_to.sql.orig
          fi

          # Start a server to send backups when requested by peers.
          exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
            "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root"          
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          subPath: mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
      volumes:
      - name: conf
        emptyDir: {}
      - name: config-map
        configMap:
          name: mysql
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 5Gi
      storageClassName: slow
生成配置

在启动 Pod 规约中的任何容器之前,Pod 首先按顺序运行所有的 Init 容器。

第一个名为 init-mysql 的 Init 容器根据序号索引生成特殊的 MySQL 配置文件。

该脚本通过从 Pod 名称的末尾提取索引来确定自己的序号索引,而 Pod 名称由 hostname 命令返回。 然后将序数(带有数字偏移量以避免保留值)保存到 MySQL conf.d 目录中的文件 server-id.cnf。 这一操作将 StatefulSet 所提供的唯一、稳定的标识转换为 MySQL 服务器的 ID, 而这些 ID 也是需要唯一性、稳定性保证的。

通过将内容复制到 conf.d 中,init-mysql 容器中的脚本也可以应用 ConfigMap 中的 primary.cnf 或 replica.cnf。 由于示例部署结构由单个 MySQL 主节点和任意数量的副本节点组成, 因此脚本仅将序数 0 指定为主节点,而将其他所有节点指定为副本节点。

克隆现有数据

通常,当新 Pod 作为副本节点加入集合时,必须假定 MySQL 主节点可能已经有数据。 还必须假设复制日志可能不会一直追溯到时间的开始。

这些保守的假设是允许正在运行的 StatefulSet 随时间扩大和缩小而不是固定在其初始大小的关键。

第二个名为 clone-mysql 的 Init 容器,第一次在带有空 PersistentVolume 的副本 Pod 上启动时,会在从属 Pod 上执行克隆操作。 这意味着它将从另一个运行中的 Pod 复制所有现有数据,使此其本地状态足够一致, 从而可以开始从主服务器复制。

MySQL 本身不提供执行此操作的机制,因此本示例使用了一种流行的开源工具 Percona XtraBackup。 在克隆期间,源 MySQL 服务器性能可能会受到影响。 为了最大程度地减少对 MySQL 主服务器的影响,该脚本指示每个 Pod 从序号较低的 Pod 中克隆。 可以这样做的原因是 StatefulSet 控制器始终确保在启动 Pod N + 1 之前 Pod N 已准备就绪。

开始复制

Init 容器成功完成后,应用容器将运行。 MySQL Pod 由运行实际 mysqld 服务的 mysql 容器和充当 辅助工具 的 xtrabackup 容器组成。

xtrabackup sidecar 容器查看克隆的数据文件,并确定是否有必要在副本服务器上初始化 MySQL 复制。 如果是这样,它将等待 mysqld 准备就绪,然后使用从 XtraBackup 克隆文件中提取的复制参数 执行 CHANGE MASTER TO 和 START SLAVE 命令。

一旦副本服务器开始复制后,它会记住其 MySQL 主服务器,并且如果服务器重新启动或 连接中断也会自动重新连接。 另外,因为副本服务器会以其稳定的 DNS 名称查找主服务器(mysql-0.mysql), 即使由于重新调度而获得新的 Pod IP,它们也会自动找到主服务器。

最后,开始复制后,xtrabackup 容器监听来自其他 Pod 的连接,处理其数据克隆请求。 如果 StatefulSet 扩大规模,或者下一个 Pod 失去其 PersistentVolumeClaim 并需要重新克隆, 则此服务器将无限期保持运行。

一段时间后,您应该看到所有3个 Pod 都开始运行

[root@master mysql]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
mysql-0   2/2     Running   0          7m32s
mysql-1   2/2     Running   0          5m25s
mysql-2   2/2     Running   0          34s

查看pv,pvc的绑定情况

[root@master mysql]# kubectl get pvc,pv
NAME                                 STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-mysql-0   Bound    pv-nfs-mysql01   5Gi        RWO            slow           9m9s
persistentvolumeclaim/data-mysql-1   Bound    pv-nfs-mysql02   5Gi        RWO            slow           7m2s
persistentvolumeclaim/data-mysql-2   Bound    pv-nfs-mysql03   5Gi        RWO            slow           2m11s

NAME                              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE
persistentvolume/pv-nfs-mysql01   5Gi        RWO            Retain           Bound    default/data-mysql-0   slow                    9m27s
persistentvolume/pv-nfs-mysql02   5Gi        RWO            Retain           Bound    default/data-mysql-1   slow                    9m27s
persistentvolume/pv-nfs-mysql03   5Gi        RWO            Retain           Bound    default/data-mysql-2   slow                    9m27s

查看service

[root@master mysql]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    19h
mysql        ClusterIP   None          <none>        3306/TCP   13h
mysql-read   ClusterIP   10.96.35.19   <none>        3306/TCP   13h

测试

测试用例:

#登录主的mysql
mysql -h mysql-0.mysql  
[root@master mysql]# kubectl run test --image=mysql:5.7 -it -- bash
If you don't see a command prompt, try pressing enter.
root@test:/# mysql -h mysql-0.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 955
Server version: 5.7.36-log MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| xtrabackup_backupfiles |
+------------------------+
5 rows in set (0.01 sec)

创建创建数据库

mysql> create database testdb;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.00 sec)

分别查看两个从的mysql,都自动复制了testdb数据库

root@test:/# mysql -h mysql-1.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1248
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.00 sec)
root@test:/# mysql -h mysql-2.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1244
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.01 sec)
[root@master mysql]# kubectl get pod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP                NODE    NOMINATED NODE   READINESS GATES
mysql-0   2/2     Running   0          44m   192.168.166.147   node1   <none>           <none>
mysql-1   2/2     Running   0          41m   192.168.104.22    node2   <none>           <none>
mysql-2   2/2     Running   0          37m   192.168.104.23    node2   <none>           <none>
test      1/1     Running   2          16m   192.168.166.148   node1   <none>           <none>

在主mysql中插入数据进行测试

[root@master mysql]# kubectl attach test -it
Defaulting container name to test.
Use 'kubectl describe pod/test -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
root@test:/# mysql -h mysql-0.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2096
Server version: 5.7.36-log MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.01 sec)

mysql> use testdb
Database changed

mysql> create table people(id int,name varchar(255),age int);
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| people           |
+------------------+
1 row in set (0.01 sec)

mysql> insert into people value (1,"linda",26);
Query OK, 1 row affected (0.01 sec)

mysql> select * from people;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | linda |   26 |
+------+-------+------+
1 row in set (0.00 sec)

分别查看两个从的mysql,看其是否复制过来数据

root@test:/# mysql -h mysql-1.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2158
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.01 sec)

mysql> use testdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| people           |
+------------------+
1 row in set (0.00 sec)

mysql> select * from people;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | linda |   26 |
+------+-------+------+
1 row in set (0.00 sec)

root@test:/# mysql -h mysql-2.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2171
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.01 sec)

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| people           |
+------------------+
1 row in set (0.01 sec)

mysql> select * from people
    -> ^C
mysql> select * from people;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | linda |   26 |
+------+-------+------+
1 row in set (0.00 sec)

查看挂在的目录内容

[root@master ~]# cd /nfs/data/
[root@master data]# ll
total 4
drwxr-xr-x 3 root root 19 May 20 10:27 01
drwxr-xr-x 3 root root 19 May 20 10:32 02
drwxr-xr-x 3 root root 19 May 20 10:32 03
-rw-r--r-- 1 root root 56 May 19 20:57 a.txt
[root@master data]# cd 01/
[root@master 01]# ll
total 4
drwxr-xr-x 7 polkitd root 4096 May 20 10:58 mysql
[root@master 01]# cd mysql/
[root@master mysql]# ll
total 191508
-rw-r----- 1 polkitd input       56 May 20 10:27 auto.cnf
-rw------- 1 polkitd input     1680 May 20 10:27 ca-key.pem
-rw-r--r-- 1 polkitd input     1112 May 20 10:27 ca.pem
-rw-r--r-- 1 polkitd input     1112 May 20 10:27 client-cert.pem
-rw------- 1 polkitd input     1680 May 20 10:27 client-key.pem
-rw-r----- 1 polkitd input     1370 May 20 10:27 ib_buffer_pool
-rw-r----- 1 polkitd input 79691776 May 20 11:30 ibdata1
-rw-r----- 1 polkitd input 50331648 May 20 11:30 ib_logfile0
-rw-r----- 1 polkitd input 50331648 May 20 10:27 ib_logfile1
-rw-r----- 1 polkitd input 12582912 May 20 10:28 ibtmp1
drwxr-x--- 2 polkitd input     4096 May 20 10:27 mysql
-rw-r----- 1 polkitd input      177 May 20 10:27 mysql-0-bin.000001
-rw-r----- 1 polkitd input  3084237 May 20 10:27 mysql-0-bin.000002
-rw-r----- 1 polkitd input      790 May 20 11:30 mysql-0-bin.000003
-rw-r----- 1 polkitd input       63 May 20 10:27 mysql-0-bin.index
drwxr-x--- 2 polkitd input     8192 May 20 10:27 performance_schema
-rw------- 1 polkitd input     1680 May 20 10:27 private_key.pem
-rw-r--r-- 1 polkitd input      452 May 20 10:27 public_key.pem
-rw-r--r-- 1 polkitd input     1112 May 20 10:27 server-cert.pem
-rw------- 1 polkitd input     1680 May 20 10:27 server-key.pem
drwxr-x--- 2 polkitd input     8192 May 20 10:27 sys
drwxr-x--- 2 polkitd input       56 May 20 11:29 testdb
drwxr-x--- 2 root    root         6 May 20 10:32 xtrabackup_backupfiles
[root@master mysql]# cd testdb/
[root@master testdb]# ll
total 112
-rw-r----- 1 polkitd input    65 May 20 10:58 db.opt
-rw-r----- 1 polkitd input  8614 May 20 11:29 people.frm
-rw-r----- 1 polkitd input 98304 May 20 11:30 people.ibd

[root@master data]# cd 02/
[root@master 02]# ll
total 4
drwxr-xr-x 7 polkitd root 4096 May 20 10:58 mysql
[root@master 02]# cd mysql/
[root@master mysql]# ll
total 196716
-rw-r----- 1 polkitd input       56 May 20 10:32 auto.cnf
-rw-r----- 1 polkitd root       427 May 20 10:32 backup-my.cnf
-rw------- 1 polkitd input     1676 May 20 10:32 ca-key.pem
-rw-r--r-- 1 polkitd input     1112 May 20 10:32 ca.pem
-rw-r--r-- 1 root    root        81 May 20 10:32 change_master_to.sql.orig
-rw-r--r-- 1 polkitd input     1112 May 20 10:32 client-cert.pem
-rw------- 1 polkitd input     1680 May 20 10:32 client-key.pem
-rw-r----- 1 polkitd root      1370 May 20 10:32 ib_buffer_pool
-rw-r----- 1 polkitd root  79691776 May 20 11:30 ibdata1
-rw-r----- 1 polkitd root  50331648 May 20 11:30 ib_logfile0
-rw-r----- 1 polkitd root  50331648 May 20 10:32 ib_logfile1
-rw-r----- 1 polkitd input 12582912 May 20 10:32 ibtmp1
-rw-r----- 1 polkitd input      122 May 20 11:35 master.info
drwxr-x--- 2 polkitd root      4096 May 20 10:32 mysql
-rw-r----- 1 polkitd input      209 May 20 10:32 mysql-1-relay-bin.000001
-rw-r----- 1 polkitd input      958 May 20 11:30 mysql-1-relay-bin.000002
-rw-r----- 1 polkitd input       54 May 20 10:32 mysql-1-relay-bin.index
drwxr-x--- 2 polkitd root      8192 May 20 10:32 performance_schema
-rw------- 1 polkitd input     1680 May 20 10:32 private_key.pem
-rw-r--r-- 1 polkitd input      452 May 20 10:32 public_key.pem
-rw-r----- 1 polkitd input       63 May 20 11:30 relay-log.info
-rw-r--r-- 1 polkitd input     1112 May 20 10:32 server-cert.pem
-rw------- 1 polkitd input     1680 May 20 10:32 server-key.pem
drwxr-x--- 2 polkitd root      8192 May 20 10:32 sys
drwxr-x--- 2 polkitd input       56 May 20 11:29 testdb
drwxr-x--- 2 polkitd root        20 May 20 10:32 xtrabackup_backupfiles
-rw-r--r-- 1 polkitd root        27 May 20 10:32 xtrabackup_binlog_pos_innodb
-rw-r----- 1 polkitd root       115 May 20 10:32 xtrabackup_checkpoints
-rw-r----- 1 polkitd root       502 May 20 10:32 xtrabackup_info
-rw-r----- 1 polkitd root   8388608 May 20 10:32 xtrabackup_logfile
[root@master mysql]# cd testdb/
[root@master testdb]# ll
total 112
-rw-r----- 1 polkitd input    65 May 20 10:58 db.opt
-rw-r----- 1 polkitd input  8614 May 20 11:29 people.frm
-rw-r----- 1 polkitd input 98304 May 20 11:30 people.ibd

从的mysql只能读数据,而不能写入数据

[root@master ~]# kubectl attach test -it
Defaulting container name to test.
Use 'kubectl describe pod/test -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
root@test:/# mysql -h mysql-1.mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2381
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.01 sec)

mysql> use testdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into value(2,"jacson",22);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2,"jacson",22)' at line 1
[root@master mysql]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    19h
mysql        ClusterIP   None          <none>        3306/TCP   13h
mysql-read   ClusterIP   10.96.35.19   <none>        3306/TCP   13h

可通过mysql -h 10.96.35.19或者mysql -h mysql-read进入任意一个mysql中,其是随机选择一个mysql来进行操作。

验证这一说法:

[root@master mysql]# kubectl run mysql-client-loop --image=mysql:5.7 -i -t --rm --restart=Never --\
>   bash -ic "while sleep 1; do mysql -h mysql-read -e 'SELECT @@server_id,NOW()'; done"
If you don't see a command prompt, try pressing enter.
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         100 | 2022-05-20 15:36:00 |
+-------------+---------------------+
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         102 | 2022-05-20 15:36:01 |
+-------------+---------------------+
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         101 | 2022-05-20 15:36:02 |
+-------------+---------------------+
^C
pod "mysql-client-loop" deleted
pod default/mysql-client-loop terminated (Error)

随机选取到mysql-1,因此不发完成插入数据操作

[root@master ~]# kubectl attach test -it
Defaulting container name to test.
Use 'kubectl describe pod/test -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
root@test:/# mysql -h mysql-read
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 52148
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
|         101 |
+-------------+
1 row in set (0.00 sec)

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into table people value(4,"lili",28);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'table people value(4,"lili",28)' at line 1

[root@master mysql]# kubectl attach test -it
Defaulting container name to test.
Use 'kubectl describe pod/test -n default' to see all of the containers in this pod.
If you don't see a command prompt, try pressing enter.
root@test:/# mysql -h 10.96.35.19
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1131
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| mysql                  |
| performance_schema     |
| sys                    |
| testdb                 |
| xtrabackup_backupfiles |
+------------------------+
6 rows in set (0.00 sec)
[root@master mysql]# kubectl run mysql-client --image=mysql:5.7 -i -t --rm --restart=Never --  mysql -h mysql-read -e "SELECT * FROM testdb.people"
+------+--------+------+
| id   | name   | age  |
+------+--------+------+
|    1 | linda  |   26 |
|    2 | jacson |   22 |
|    3 | admin  |   24 |
+------+--------+------+
pod "mysql-client" deleted
模拟 Pod 和 Node 的宕机时间
破坏就绪态探测

为了证明从副本节点缓存而不是单个服务器读取数据的可用性提高,请在使 Pod 退出 Ready 状态时,保持上述 SELECT @@server_id 循环一直运行。

迫使就绪态探测失败的一种方法就是中止该命令:

kubectl exec mysql-2 -c mysql -- mv /usr/bin/mysql /usr/bin/mysql.off

此命令会进入 Pod mysql-2 的实际容器文件系统,重命名 mysql 命令,导致就绪态探测无法找到它。 几秒钟后, Pod 会报告其中一个容器未就绪。你可以通过运行以下命令进行检查:

此时,你应该会看到 SELECT @@server_id 循环继续运行,尽管它不再报告 102。 回想一下,init-mysql 脚本将 server-id 定义为 100 + $ordinal, 因此服务器 ID 102 对应于 Pod mysql-2。

[root@master mysql]# kubectl exec mysql-2 -c mysql -- mv /usr/bin/mysql /usr/bin/mysql.off
[root@master mysql]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
mysql-0   2/2     Running   0          13h
mysql-1   2/2     Running   0          13h
mysql-2   1/2     Running   0          13h
test      1/1     Running   6          12h
[root@master mysql]# kubectl run mysql-client-loop --image=mysql:5.7 -i -t --rm --restart=Never --\
>   bash -ic "while sleep 1; do mysql -h mysql-read -e 'SELECT @@server_id,NOW()'; done"
If you don't see a command prompt, try pressing enter.
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         100 | 2022-05-20 15:51:58 |
+-------------+---------------------+
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         100 | 2022-05-20 15:51:59 |
+-------------+---------------------+
+-------------+---------------------+
| @@server_id | NOW()               |
+-------------+---------------------+
|         101 | 2022-05-20 15:52:00 |
+-------------+---------------------+

现在修复 Pod,几秒钟后它应该重新出现在循环输出中:

kubectl exec mysql-2 -c mysql -- mv /usr/bin/mysql.off /usr/bin/mysql
删除 Pods

如果删除了 Pod,则 StatefulSet 还会重新创建 Pod,类似于 ReplicaSet 对无状态 Pod 所做的操作。

kubectl delete pod mysql-2

StatefulSet 控制器注意到不再存在 mysql-2 Pod,于是创建一个具有相同名称并链接到相同 PersistentVolumeClaim 的新 Pod。 你应该看到服务器 ID 102 从循环输出中消失了一段时间,然后又自行出现。

本实例参考官方文档:链接

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
产品名字 版本 centos 7.5 kubernetes 1.13 docker 18.09.5 JDK 1.8_131 SSH 7.4 etcd 3.3.10(API version:2) flannel 0.10.0 TOMCAT 8 Mysql 5.6 Ambari 2.7 HDP 3.0 ElasticSearch 6.5.1 Kibana 6.5.1 Logstash 6.5.1 Neo4j 3.4 esxi 6.5 MAVEN 3.6 ElasticSearch 6.5.1 Kibana 6.5.1 Logstash 6.5.1 目录: 1. ESXI6.5创建centos虚拟机 10 1.1. 准备工作 10 1.2. 创建新的虚拟机 10 2. ESXI虚拟机克隆 13 2.1. 创建文件夹 13 2.2. 复制文件 13 2.3. 注册现有虚拟机 14 2.4. 为克隆的虚拟机添加硬盘 15 3. HPE服务器Centos7.5安装 16 3.1. 服务器(DL388 Gen10)加载镜像文件 16 3.2. 系统安装、配置 18 3.2.1. 选中【install centos7】 18 3.2.2. 语言 18 3.2.3. 其他配置 18 3.2.4. 时区 18 3.2.5. 软件包安装 19 3.2.6. 磁盘分区 19 3.2.7. root用户密码配置 20 3.2.8. 完成安装 20 3.3. IP地址、主机名设置 20 3.4. 磁盘挂载并开机自动挂载 22 3.4.1. 磁盘挂载(如果超过2T的挂载则看超过2T的挂载章节) 22 3.4.2. 设置开机时自动挂载 23 3.4.3. 超过2T的挂载 23 3.5. 磁盘分区扩容 25 3.5.1. 根目录 25 3.5.2. 普通目录 26 3.6. Vim命令安装 26 3.7. Wget命令安装 26 3.8. 查看端口占用命令 26 3.9. 新建用户、用户组并设置root权限 26 4. SSH免密 27 4.1. 查看SSH是否安装,需要客户端与服务都安装,centos7自带ssh服务,一般可以跳过安装步骤 27 4.2. 安装命令 27 4.3. service sshd restart 启动、重启SSH服务; 27 4.4. 开机启动。 27 4.5. 退出SSH命令 27 4.6. SSH免密登录 27 5. 同步系统时间,(分布式系统各个节点需要同步时间) 27 5.1. 安装NTP插件 27 5.2. 同步时间: 27 6. JDK 28 7. Maven 28 8. Tomcat 29 8.1. 配置tomcat的环境变量和内存设置 29 8.2. 服务自启动 30 9. Mysql 30 9.1. 离线安装 30 9.2. 在线安装 30 9.2.1. 检测系统是否自带安装mysql 30 9.2.2. 下载yum包 30 9.2.3. 安装mysql 30 9.2.4. 启动服务 30 9.2.5. 设置root密码 30 9.2.6. 设置开机自启 31 9.2.7. mysql安全设置 31 9.2.8. 创建数据库 31 9.2.9. 创建用户 31 9.2.10. 更改数据存储路径 31 9.2.11. 开启binlog日志 32 9.2.12. 修改mysql配置文件 32 9.3. 问题整理 33 10. Apache Http文件服务器 33 10.1. 安装http 33 10.2. 修改Http服务器根路径 33 10.3. 中文乱码 33 10.3.1. 文件内容中文乱码 33 10.3.2. 文件名字中文乱码 33 10.4. 修改目录文件名不要被截断 33 11. Ambari 33 11.1. 安装相关服务 33 11.2. 同步所有节点时间 34 11.3. IP与主机名映射 34 11.4. SSH免密 34 11.5. JDK安装(建议1.8) 34 11.6. 关闭防火墙、selinux、THP 34 11.7. 最大打开文件要求 34 11.8. mysql配置(server机器操作) 34 11.8.1. 创建数据库 34 11.8.2. 下载mysql-connection-java 34 11.9. 部署本地库(镜像服务器)(server机器操作) 35 11.9.1. 下载HortWorks官网上的4个库到本地(也可以在线下载,但是速度会很慢) 35 11.9.2. 创建本地yum源 35 11.9.3. 上传文件 35 11.9.4. 解压文件 35 11.9.5. 新建一个httpd资源库文件夹 35 11.9.6. 修改本地源地址 35 11.10. Ambari-server端安装部署(server机器操作) 36 11.10.1. 安装Ambari-server 36 11.10.2. 配置Ambari-server 36 11.10.3. 查看并启动Ambari-server 37 11.10.4. Ambari登陆 38 11.11. Ambari集群搭建(所有agent节点机器操作) 38 11.11.1. 安装agent 38 11.11.2. 部署Agent 39 11.11.3. 创建集群: 39 11.11.4. 存储库地址配置: 40 11.11.5. 节点配置: 40 11.11.6. 节点验证: 41 11.11.7. 选择需要安装的服务: 41 11.11.8. 主服务节点配置,尽量均匀分布: 42 11.11.9. 从服务、客户端节点配置: 42 11.11.10. 密码配置: 42 11.11.11. 数据库配置 42 11.11.12. 修改服务存储、日志路径: 44 11.11.13. 用户名配置 44 11.11.14. 配置文件更改 45 11.11.15. 部署 45 11.12. Ambari 卸载服务 48 11.13. 登陆地址 48 11.14. 异常处理 48 11.15. 警告 50 11.15.1. Ambari Metrics ,Hbase rootdir路径问题 50 11.15.2. Atlas 51 12. Ambari集成ElasticSearch6.x 51 12.1. 通过SSH把源码传到centos机器上 51 12.2. 复制源码到Ambari 51 12.3. 编辑metainfo.xml文件 51 12.4. 启动/重启Ambari 51 12.5. 添加服务 51 13. ElasticSearch集群搭建 54 13.1. 解压文件:必须使用非root用户安装和启动 54 13.2. 创建目录 54 13.3. 配置文件 55 13.4. 系统配置文件 55 13.5. 启动服务 56 13.6. 添加系统服务自启动 56 13.7. Head安装 57 13.8. 登陆地址 57 13.9. ES跨域访问配置 57 13.10. IK分词器安装 57 13.11. Cerebro配置 57 13.12. 集群使用经验 58 13.13. 问题整理 58 14. Elasticsearch与reactivesearch快速构建搜索项目 58 15. kibana 59 15.1. 配置kibana配置文件 59 15.2. 启动、停止服务 59 15.3. 登陆地址 59 15.4. 汉化 59 16. Neo4j 59 16.1. 下载地址: 59 16.2. 解压缩: 59 16.3. SSH复制文件到其他节点: 60 16.4. 启动服务: 60 16.5. 登陆地址 60 16.6. 账号密码: 60 16.7. neo4服务自启动 60 16.8. 配置文件解释 61 17. 安装logstash插件同步ES-mysql数据 65 17.1. 下载logstash(版本需与ES一致) 65 17.2. 安装logstash-input-jdbc插件步骤: 65 17.3. 启动logstash 66 18. HDFS 67 18.1. 退出安全模式: 67 19. Kafka 67 19.1. 优化 67 20. Spark2.x 68 20.1. 示例执行 68 21. YARN 68 21.1. 错误处理 68 22. Docker安装 68 22.1. 在线安装 68 22.1.1. 使用国内docker源 68 22.1.2. Docker安装 68 22.1.3. 启动进程 68 22.2. RPM安装方式 68 22.2.1. 安装libtool-ltdl 68 22.2.2. 关闭selinux和内存交换 69 22.2.3. 安装docker-ce-selinuxdocker-ce 69 22.3. 二进制文件安装方式 69 22.3.1. 下载地址 69 22.3.2. 安装配置 69 23. Kubernetes集群搭建准备 70 23.1. 机器规划: 70 23.2. 所有节点添加环境变量 70 23.3. 下载地址 70 23.4. 解压文件 70 23.5. Server节点CA证书创建分发 70 23.5.1. 安装cfssl 70 23.5.2. 创建用来生成 CA 文件的 JSON 配置文件 71 23.5.3. 创建用来生成 CA 证书签名请求(CSR)的 JSON 配置文件 71 23.5.4. 生成CA证书(ca.pem)和密钥(ca-key.pem) 71 23.5.5. 分发证书 72 24. ETCD数据库集群搭建 72 24.1. 创建etcd证书签名请求 72 24.2. 生成证书和私钥 73 24.3. 创建配置文件 73 24.4. 创建服务文件 74 24.5. 拷贝etcd.conf和etcd.service文件到其他2个节点 74 24.6. 启动服务 74 24.7. 测试集群 75 24.8. 注意事项 75 25. Kubernetes集群安装部署 75 25.1. Master节点部署 75 25.1.1. 复制文件 75 25.1.2. 部署kube-apiserver服务 75 25.1.3. 部署kube-controller-manager服务 78 25.1.4. 部署kube-scheduler服务 79 25.1.5. 部署kubectl 命令行工具 79 25.2. Node节点部署 81 25.2.1. 复制文件 81 25.2.2. 部署kubelet 81 25.2.3. 部署Kube-proxy服务 84 25.3. Flannel网络配置 86 25.3.1. 下载地址 86 25.3.2. 解压文件 86 25.3.3. 复制文件 86 25.3.4. 生成ca配置文件与证书 86 25.3.5. 分发证书 87 25.3.6. 配置文件 87 25.3.7. Flannel CNI集成 88 25.3.8. 启动服务 88 25.3.9. 配置Docker使用Flannel 89 25.4. coredns安装 89 25.4.1. 编辑配置文件 89 25.4.2. 创建coredns 93 25.4.3. 查看coredns服务 93 25.4.4. Pod容器中进行域名解析测试 93 25.5. kubernetes-dashboard部署 93 26. GlusterFS分布式文件系统部署 95 26.1. 在kubernetes部署 95 26.1.1. 安装: 95 26.1.2. 创建Heketi服务: 97 26.1.3. 为Heketi设置GlusterFS集群 99 26.2. yum部署 99 26.3. 创建分布式卷 99 27. SpringBoot 100 28. SpringCloud 100
网盘文件永久链接 目录: 1ocker三剑客名词介绍mp4 2 ckermachine与 dockercompose个绍mp4 3 ockercompose使用的三步mp4 4 ockercompose语法讲解 5 ockercompose语法讲解2av,mP 6 ockercompose案例1.mp4 7 ockercompose案例2.mp4 8 ockercompose案例3,mp4 9 dockerswarm简介与集群环境佳备mp4 10 dockerswarm集群搭建,mp4 11harbor准备两个版本的ngn镜像,mp4 12发布服务路由网格mp4 13负载均衡扩展与裁减mp4 14版本更新版本回退滚动间隔更新mp4 15本地存储着与网络存储卷mp4 16服务互联与服务发现mp4 17小结mp4 18容器认识1mp4 19容器认识2.mp4 20ocker个绍版本,mp4 21ocker容器使用的内核技术介绍mp4 22 ocker安装,mp4 23ocker客户端与服务端分离mp4 24程 docker操作演示还原环境mp4 25像容器仓库概念mp4 26找镜像下载镜像删除镜食m 27配置镜像加速器mp4 28镜像导出与导入方法mp4 29镜像仓库分美公网仓库创建与量作演示,mp4 30habo个绍hbo安装过程1.mp4 31 harbor安装过程2.mp4 32hbor上传下载mp4 33镜像小结imP4 34容器常见操作1mp4 35容器常见操作2mp4 36 ocker命令回顾 commit提交镜像_mp4 37 ockerexed操作,mp4 38 ocker常见操作总结重点mp4 39时复制和用时分配技术讲解mp4 40合文件系统介绍auts介绍mp4 41ufs过渡到 overlay . mp4 42过操作来理解 overlay, mp4 43 ocker存储驱动小结mp4 44器跑httpd案例1mp4 45自定义httpd容器并提交为镜像dockerrun启动应用详解mp4 46 docker数据卷mp4 47docker数据卷小结官方htpd镜像运行容器mp4 48docker跑mariadb或mysql应用mp4 49 docker跑应用补充与小结,mp4 50 ockerfile个绍参数讲解1mp4 51 ockerfile参数讲解2mp4 52ockerfile构建httpd镜像,mp4 53ockerfile构建httpd镜像2mp4 54 ockerfile构建 tomcat镜像mp4 55 ockerfile构建 tomcat多种方法之间的比较mp4 56 ockerfilel构建 mariadb镜像,mp4 57 ockert构建 mariadb镜像2小结mp4 58 ocker单宿主机容器互联mp 59 docker本地网络 bridge模式mp4 60 docker本地网络 hostnonecontainer模式,mp4 61跨 dockery网络方案ame价绍mp4 62 lanned网络搭建过程mp4 63 anned网络测试与网络小结mp4 64 docker的web管理平台小结mp4 ...............................................

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值