使用 mariadb-operator 在 Kubernetes 中运行和操作 MariaDB

mariadb-operator

StatefulSet 资源的引入是 Kubernetes 中运行有状态工作负载的重大变革,它引入了一系列特性,包括

  • 每个 Pod 的可预测 DNS 名称,允许在网络中单独寻址它们。
  • 每个 Pod 的稳定持久存储,确保每个 Pod 都绑定到同一个 PersistentVolumeClaim
  • 有序的优雅部署和自动滚动更新。

然而,这对于在 Kubernetes 中以可靠方式运行数据库来说还不够。我们缺少日间操作(Day 1 operations)和日常维护操作(Day 2 operations),例如配置高可用性和安排备份,这些是原生 Kubernetes 不管理的。通常,DBA(也就是人工操作员)是执行这些操作的指定人员,他们遵循操作手册并利用他们的专业知识,但归根结底他们是人类,能力有限,尤其是在维护大量数据库集群时。

为了解决这个问题,mariadb-operator 通过提供 MariaDB 自定义资源来扩展 Kubernetes API,该资源封装了在 Kubernetes 中轻松运行和操作 MariaDB 的操作专业知识。在这篇博客中,我们将安装 mariadb-operator 并配置它提供的一些自定义资源。

安装 mariadb-operator

您可以通过 Helm 轻松地在 Kubernetes 集群中安装 mariadb-operator。这将安装所需的自定义资源和操作符本身。

helm repo add mariadb-operator https://mariadb-operator.github.io/mariadb-operator
helm install mariadb-operator mariadb-operator/mariadb-operator

配置 MariaDB 服务器

首先,我们需要创建一个包含 root 凭据的 Kubernetes Secret

kubectl create secret generic mariadb --from-literal=root-password=mariadb 

然后,我们可以引用它并创建 MariaDB 资源

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: MariaDB
metadata:
  name: mariadb
spec:
  rootPasswordSecretKeyRef:
    name: mariadb
    key: root-password
  image:
    repository: mariadb
    tag: "10.11.3"
    pullPolicy: IfNotPresent
  port: 3306
  volumeClaimTemplate:
    resources:
      requests:
        storage: 100Mi
    accessModes:
      - ReadWriteOnce
  myCnf: |
    [mariadb]
    bind-address=0.0.0.0
    default_storage_engine=InnoDB
    binlog_format=row
    innodb_autoinc_lock_mode=2
    max_allowed_packet=256M
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 300m
      memory: 512Mi
EOF

操作符将监视 MariaDB 资源并最终将它们协调为 StatefulSets

kubectl get mariadbs
NAME      READY   STATUS    PRIMARY POD   AGE
mariadb   True    Running   mariadb-0     4m43s

kubectl get statefulsets
NAME      READY   AGE
mariadb   1/1     4m48s

kubectl get pods
NAME                                        READY   STATUS      RESTARTS   AGE
mariadb-0                                   1/1     Running     0          4m52s

配置数据库、用户和授权

MariaDB 实例成功部署并运行后,下一步是配置 Databases 并授予 Grant 权限给 Users

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Database
metadata:
  name: data-test
spec:
  mariaDbRef:
    name: mariadb
  characterSet: utf8mb4
  collate: uca1400_ai_ci
EOF
kubectl create secret generic user --from-literal=password=mariadb 
kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: User
metadata:
  name: user
spec:
  mariaDbRef:
    name: mariadb
  passwordSecretKeyRef:
    name: user
    key: password
  maxUserConnections: 20
EOF
kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Grant
metadata:
  name: grant
spec:
  mariaDbRef:
    name: mariadb
  privileges:
    - "CREATE"
    - "SELECT"
    - "INSERT"
    - "UPDATE"
  database: "*"
  table: "*"
  username: user
  grantOption: false
EOF

应用上述清单后,操作符将在 MariaDB 中创建相应的 SQL 资源

kubectl get databases
NAME        READY   STATUS    CHARSET   COLLATE           MARIADB   AGE
data-test   True    Created   utf8      utf8_general_ci   mariadb   45s

kubectl get users
NAME   READY   STATUS    MAXCONNS   MARIADB   AGE
user   True    Created   20         mariadb   25s

kubectl get grants
NAME    READY   STATUS    DATABASE   TABLE   USERNAME   GRANTOPT   MARIADB   AGE
grant   True    Created   *          *       user       true       mariadb   20s

为应用程序配置连接

在此阶段,我们可以声明式地创建 Connections,让应用程序只需挂载操作符创建的 Secret 即可无缝连接到 MariaDB

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Connection
metadata:
  name: connection
spec:
  mariaDbRef:
    name: mariadb
  username: user
  passwordSecretKeyRef:
    name: user
    key: password
  database: data-test
  secretName: connection
  secretTemplate:
    key: dsn
EOF
kubectl get connections
NAME         READY   STATUS    SECRET       MARIADB   AGE
connection   True    Healthy   connection   mariadb   6s

kubectl get secret connection -o jsonpath="{.data.dsn}" | base64 -d
user:mariadb@tcp(mariadb.default.svc.cluster.local:3306)/data-test

编排和调度 SQL 脚本

既然应用程序可以成功建立连接,下一个考虑因素是数据库模式的管理。 SqlJob 资源允许在 Kubernetes Jobs 中执行 SQL 脚本。通过利用此资源,您可以通过执行 SQL 脚本来灵活地定义数据库模式或执行迁移。

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: SqlJob
metadata:
  name: 01-users
spec:
  mariaDbRef:
    name: mariadb
  username: user
  passwordSecretKeyRef:
    name: user
    key: password
  database: data-test
  sql: |
    CREATE TABLE IF NOT EXISTS users (
      id bigint PRIMARY KEY AUTO_INCREMENT,
      username varchar(255) NOT NULL,
      UNIQUE KEY name__unique_idx (username)
    );
    INSERT INTO users(username) VALUES('mmontes11');
EOF
kubectl get sqljobs
NAME       COMPLETE   STATUS    MARIADB   AGE
01-users   True       Success   mariadb   42s

kubectl get jobs
NAME       COMPLETIONS   DURATION   AGE
01-users   1/1           10s        49s

kubectl exec -it mariadb-0 -- mariadb -u user -pmariadb -D data-test -e "SELECT * FROM users;"
+----+-----------+
| id | username  |
+----+-----------+
|  1 | mmontes11 |
+----+-----------+

备份和恢复

数据库初始化后,定期安排备份以防止数据丢失至关重要。您可以通过创建 Backup 资源来做到这一点。

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Backup
metadata:
  name: backup-scheduled
spec:
  mariaDbRef:
    name: mariadb
  schedule:
    cron: "*/5 * * * *"
  maxRetentionDays: 30
  storage:
    persistentVolumeClaim:
      resources:
        requests:
          storage: 100Mi
      accessModes:
        - ReadWriteOnce
EOF

此资源将被协调为 CronJob,它会定期调度 Jobs 来执行备份。

kubectl get backups
NAME               COMPLETE   STATUS    MARIADB   AGE
backup-scheduled   True       Success   mariadb   24s

kubectl get cronjobs
NAME               SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
backup-scheduled   */5 * * * *   False     0        28s             29s

类似地,我们可以创建 Restore 资源来恢复 Backup

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Restore
metadata:
  name: restore
spec:
  mariaDbRef:
    name: mariadb
  backupRef:
    name: backup-scheduled
EOF
kubectl get restores
NAME      COMPLETE   STATUS    MARIADB   AGE
restore   True       Success   mariadb   11s

kubectl get jobs
NAME                        COMPLETIONS   DURATION   AGE
restore                     1/1           10s        23s

从备份启动新的 MariaDB 实例

为了方便起见,可以从现有的 Backup 创建一个新的 MariaDB 实例。通过利用此功能,您可以根据需要启动新实例并快速从备份中恢复数据。操作符将在新实例准备就绪后立即执行恢复操作来处理此过程。

kubectl apply -f - <<EOF
apiVersion: mariadb.mmontes.io/v1alpha1
kind: MariaDB
metadata:
  name: mariadb-from-backup
spec:
  bootstrapFrom:
    backupRef:
      name: backup-scheduled
  rootPasswordSecretKeyRef:
    name: mariadb
    key: root-password
  image:
    repository: mariadb
    tag: "10.11.3"
    pullPolicy: IfNotPresent
  port: 3306
  volumeClaimTemplate:
    resources:
      requests:
        storage: 100Mi
    accessModes:
      - ReadWriteOnce
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 300m
      memory: 512Mi
EOF
kubectl get mariadbs
NAME                  READY   STATUS    PRIMARY POD             AGE
mariadb-from-backup   True    Running   mariadb-from-backup-0   1m

kubectl get pods
NAME                                        READY   STATUS      RESTARTS   AGE
mariadb-from-backup-0                       1/1     Running     0          1m

kubectl exec -it mariadb-from-backup-0 -- mariadb -u root -pmariadb -D data-test  -e "SELECT * FROM users;"
+----+-----------+
| id | username  |
+----+-----------+
|  1 | mmontes11 |
+----+-----------+

总结

本博客演示了如何有效利用 mariadb-operator 通过自定义资源管理 Kubernetes 中的 MariaDB 实例,推广了声明式方法,而不是依赖于命令式命令。欢迎查看文档,如有任何疑问,请加入 mariadb-operator Slack 频道!

资源