我们从社区和客户那里收到的一个很常见的要求是提供一种使用 Operators 来管理数据库用户的方法——MongoDB 和 MySQL。尽管我们认为这是一项有趣的任务,但我们的 Operator 主要是一种工具,用于简化我们在 Kubernetes 上的软件部署和管理。我们的目标是提供准备好托管关键任务应用程序并部署了最佳实践的数据库集群。
为什么要使用 Operator 来管理用户?
有几个用例:
- 简化 CICD 管道。应用单个清单比在数据库准备好后运行多个命令来创建用户更简单。
- 将 DB 用户的控制权交给开发人员或应用程序,但不提供对数据库的直接访问。
- 有一种观点认为 Kubernetes 将从容器编排器过渡到控制平面来管理一切。对于一些公司来说,这是一种策略。
我们希望拥有为用户提供 Operator 的功能,但为每个 Operator 单独执行此操作似乎不是正确的解决方案。好像可以统一。
如果我们将其提升到另一个层次并创建一种通过 Kubernetes 控制平面在任何数据库上配置用户的方法会怎样?用户已经通过控制平面在公有云上创建了MySQL实例,那么为什么不以同样的方式创建数据库用户呢?
Crossplane.io – 一个 Kubernetes 插件,使用户能够通过 k8s 控制平面声明性地描述和配置基础设施。根据设计,它可以通过“提供者”进行扩展。其中之一 – provider-sql – 支持通过 CRD 管理 MySQL 和 PostgreSQL 用户(甚至数据库)的功能。让我们看看如何让它与Percona XtraDB Cluster Operator 一起工作。
开始吧
先决条件:
- Kubernetes集群
- 使用 Operator 部署的 Percona XtraDB 集群(请参阅此处的文档)
目标是通过Kubernetes API创建自定义资源(CR)对象来触发crossplane.io在PXC集群上创建用户。作为总结,它看起来像这样:

- 用户使用所需的用户创建 CR 并授予
- Crossplane 检测到它
- provider-sql(Crossplane 提供者)是通过一个 Secret 对象配置的,该对象具有 PXC 端点和根凭据
- provider-sql 连接到 PXC 并创建用户
我已将这篇文章的所有文件连同仅列出所有步骤的精简 Runbook 一起放入公共 github 存储库中。你可以在这里找到这一切。
安装横板
最简单的方法是通过 helm 来完成:
kubectl create namespace crossplane
helm repo add crossplane-alpha https://charts.crossplane.io/alpha
helm install crossplane --namespace crossplane crossplane-alpha/crossplane
其他安装方法可以在crossplane.io 文档中找到。
安装提供者-sql
Crossplane中的Provider是一个类似于Terraform 的 provider的概念。crossplane 中的一切都是通过 Kubernetes API 完成的,其中包括 Providers 的安装:
$ cat crossplane-provider-sql.yaml apiVersion: pkg.crossplane.io/v1beta1 kind: Provider metadata: name: provider-sql spec: package: "crossplane/provider-sql:master" $ kubectl apply -f crossplane-provider-sql.yaml
这将为 provider-sql 安装自定义资源定义,它将用于管理我们 PXC 集群上的 MySQL 用户。可以在此处找到 provider-sql 的完整文档,但它们不是很详细。
差不多好了
一切都已安装,需要最后一次配置。
创建一个secret ,provider-sql 将使用它来连接到 MySQL 数据库。我在 pxc 命名空间中部署了 cluster1 Percona XtraDB 集群,相应的秘密将如下所示:
$ cat crossplane-secret.yaml apiVersion: v1 kind: Secret metadata: name: crossplane-secret namespace: pxc stringData: username: root password: <root password> endpoint: cluster1-haproxy.pxc.svc.cluster.local port: "3306" type: Opaque
您可以从通过 Operator 部署 PXC 时创建的 secret 中获取 root 密码。快速获取方法是这样的:
$ kubectl get secret -n pxc my-cluster-secrets -o yaml | awk '/root:/ {print $2}' | base64 --decode && echo
<root password>
Crossplane 将使用端点和端口作为 MySQL 连接字符串,以及连接到它的用户名和密码。配置 provider-sql 以从 secret 中获取信息:
$ cat crossplane-mysql-config.yaml apiVersion: mysql.sql.crossplane.io/v1alpha1 kind: ProviderConfig metadata: name: cluster1-pxc spec: credentials: source: MySQLConnectionSecret connectionSecretRef: namespace: pxc name: crossplane-secret $ kubectl apply -f crossplane-mysql-config.yaml
让我们验证配置是否到位:
$ kubectl get providerconfig.mysql.sql.crossplane.io NAME AGE cluster1-pxc 14s
做吧
可以了,好了。Crossplane 现在可以连接到数据库并创建用户。从 Kubernetes 和用户的角度来看,它只是通过控制平面 API 创建自定义资源。
数据库创建
$ cat crossplane-db.yaml apiVersion: mysql.sql.crossplane.io/v1alpha1 kind: Database metadata: name: my-db spec: providerConfigRef: name: cluster1-pxc $ kubectl apply -f crossplane-db.yaml database.mysql.sql.crossplane.io/my-db created $ kubectl get database.mysql.sql.crossplane.io NAME READY SYNCED AGE my-db True True 14s
这在我的 Percona XtraDB 集群上创建了数据库:
$ mysql -u root -p -h cluster1-haproxy
Server version: 8.0.22-13.1 Percona XtraDB Cluster (GPL), Release rel13, Revision a48e6d5, WSREP version 26.4.3
...
mysql> show databases like 'my-db';
+------------------+
| Database (my-db) |
+------------------+
| my-db |
+------------------+
1 row in set (0.01 sec)
DB 也可以通过 Kubernetes API 删除 - 只需删除相应的 数据库.mysql .sql .crossplane .io 对象。
用户创建
用户需要密码。密码永远不应该以纯文本形式存储,所以让我们将其放入 Secret 中:
$ cat user-secret.yaml apiVersion: v1 kind: Secret metadata: name: my-user-secret stringData: password: mysuperpass type: Opaque
我们现在可以创建用户:
$ cat crossplane-user.yaml apiVersion: mysql.sql.crossplane.io/v1alpha1 kind: User metadata: name: my-user spec: providerConfigRef: name: cluster1-pxc forProvider: passwordSecretRef: name: my-user-secret namespace: default key: password writeConnectionSecretToRef: name: connection-secret namespace: default $ kubectl apply -f crossplane-user.yaml user.mysql.sql.crossplane.io/my-user created $ kubectl get user.mysql.sql.crossplane.io NAME READY SYNCED AGE my-user True True 11s
$ cat crossplane-grants.yaml
apiVersion: mysql.sql.crossplane.io/v1alpha1
kind: Grant
metadata:
name: my-grant
spec:
providerConfigRef:
name: cluster1-pxc
forProvider:
privileges:
- DROP
- CREATE ROUTINE
- EVENT
userRef:
name: my-user
databaseRef:
name: my-db
$ kubectl apply -f crossplane-grants.yaml
grant.mysql.sql.crossplane.io/my-grant created
$ kubectl get grant.mysql.sql.crossplane.io
NAME READY SYNCED AGE ROLE DATABASE PRIVILEGES
my-grant True True 7s my-user my-db [DROP CREATE ROUTINE EVENT]
验证用户是否在那里:
mysql> show grants for 'my-user';
+-----------------------------------------------------------------+
| Grants for my-user@% |
+-----------------------------------------------------------------+
| GRANT USAGE ON *.* TO `my-user`@`%` |
| GRANT DROP, CREATE ROUTINE, EVENT ON `my-db`.* TO `my-user`@`%` |
+-----------------------------------------------------------------+
2 rows in set (0.00 sec)
保持状态
Kubernetes 是声明性的,它的控制器总是尽最大努力保持声明的配置和实际状态同步。这意味着如果您要从数据库中手动删除用户(而不是通过 Kubernetes API),在协调循环的下一次传递中,Crossplane 将同步状态并重新创建用户并再次授予。
结论
一个数据库引擎中的某些功能与另一个有很大不同,但有时存在一种模式。用户创建是可以跨多个数据库引擎统一的模式之一。幸运的是,Cloud Native Foundation 环境非常庞大,由许多构建块组成,这些构建块一起使用可以提供出色的基础设施或应用程序。
原文地址:https://www.percona.com/blog/2021/05/20/manage-mysql-users-with-kubernetes/?xzs




