管理访问控制列表用户

Valkey 访问控制列表(ACL)用户由 valkey.buf.red/v1alpha1 中的 User 资源表示。每个自定义用户都会引用与该实例位于同一命名空间中的一个或多个 Kubernetes Secret。

要求

  • 在创建 User 资源之前,先创建 Valkey 实例。
  • 密码必须为 8–32 个字符,并存储在 Secret 键 password 下。
  • 为了兼容 Operator 的 username helper,请使用非空名称,且仅包含字母、数字和连字符,最大长度为 31 个字符。在所检查的基线中,User admission webhook 不会应用该 helper 检查,因此不兼容的名称可能会被接受,并在该账户应用到 Valkey 时失败。
  • 自定义用户不能获得 ACL 命令。webhook 会移除或拒绝 ACL 管理权限,以防止权限提升。

Operator 还会为一个实例维护 defaultoperator 账户。operator 账户保留用于调谐,不能被原生应用使用,也不得手动修改。在所检查的基线中,default 账户在生成时不包含密码,其 ACL 规则会禁止 aclflushallflushdbkeys 命令。需要这些被禁止的数据命令之一的原生应用必须使用一个授予该命令的自定义用户;不能授予 ACL 管理本身。

webhook 接受 Operator 定义的 Valkey 访问控制列表(ACL)规则语法和命令类别的子集。请针对每条规则执行 server-side dry-run,然后在所选 server 版本上测试允许和拒绝的命令;schema 通过并不意味着该规则实现了预期的最小权限。

列出用户

mutating webhook 会使用所属实例名称为 User 资源添加标签:

kubectl -n default get user -l buf.red/name=valkey-cluster
kubectl -n default get user -l buf.red/name=valkey-cluster \
  -o custom-columns='RESOURCE:.metadata.name,TYPE:.spec.accountType,USERNAME:.spec.username,PHASE:.status.phase,MESSAGE:.status.message'

Ready 表示控制器已将该账户应用到处于就绪状态的 Valkey 节点。Pending 表示调谐仍在进行中,或者实例尚未就绪。Fail 需要检查 .status.message、Events 和节点日志。

创建密码 Secret

准备一个仅包含密码的本地文件,限制其权限,并在不将密码写入清单的情况下创建 Secret:

chmod 600 /secure/path/app-password
kubectl -n default create secret generic valkey-app-password \
  --from-file=password=/secure/path/app-password

创建用户

arch 设置为所属实例的架构,并将 instanceName 设置为其名称:

kubectl apply -f - <<'EOF'
apiVersion: valkey.buf.red/v1alpha1
kind: User
metadata:
  name: valkey-app
  namespace: default
spec:
  accountType: custom
  arch: cluster
  username: app
  passwordSecrets:
    - valkey-app-password
  aclRules: "+@read +@write -@dangerous ~app:* &app:*"
  instanceName: valkey-cluster
EOF

验证调谐结果:

kubectl -n default get user valkey-app
kubectl -n default get user valkey-app -o jsonpath='{.status.phase}{"\n"}'
kubectl -n default describe user valkey-app

预期的阶段是 ReadyPending 表示控制器仍在应用该账户,而 Fail 则需要检查 .status.message 和 Events。

检查 webhook 写入的规范化 ACL 规则:

kubectl -n default get user valkey-app \
  -o jsonpath='{.spec.aclRules}{"\n"}{.status.aclRules}{"\n"}'

测试认证

使用交互式密码输入,以便密码不会出现在命令行或环境变量中:

valkey-cli -h <service-host> -p 6379 --user app --askpass PING

对于 Cluster 架构,请添加 -c,以便客户端跟随 slot 重定向:

valkey-cli -c -h <service-host> -p 6379 --user app --askpass PING

轮换密码

  1. 使用新密码创建第二个 Secret。
  2. 在保留旧 Secret 的同时,将新 Secret 添加到 spec.passwordSecrets
  3. 等待 User 阶段返回 Ready,然后更新客户端。
  4. spec.passwordSecrets 中移除旧 Secret 名称。
  5. 等待 Ready,测试新密码,然后删除旧 Secret。

使用以下命令编辑资源:

kubectl -n default edit user valkey-app

多 Secret 迁移提供了一个重叠窗口,在此期间两个密码都会生效。在该窗口内验证两个凭据;调谐按节点逐个进行,并非跨 Cluster 的原子事务。

更改权限

应用应用所需的最小权限。此示例将规则替换为仅限 app:* 键和通道的读写访问:

kubectl -n default patch user valkey-app --type=merge \
  -p '{"spec":{"aclRules":"+@read +@write -@dangerous ~app:* &app:*"}}'
kubectl -n default get user valkey-app -w

等待 Ready,测试一个允许的操作和一个被拒绝的操作,并检查规范化的 status 规则。不要授予 +@all+@admin 或其他会隐式启用 ACL 命令的类别,除非该规则同时显式移除了该命令并且 webhook 接受了结果。

删除自定义用户

kubectl -n default delete user valkey-app

Operator 会从处于就绪状态的 Valkey 节点中移除该账户。只要其实例仍然存在,内置的 defaultoperator 用户就不能删除。

故障处理

kubectl -n default describe user valkey-app
kubectl -n default get events --sort-by=.lastTimestamp
kubectl -n default get secret valkey-app-password \
  -o go-template='{{.metadata.name}}{{"\t"}}{{if index .data "password"}}password key present{{else}}password key missing{{end}}{{"\n"}}'

最后一条命令仅检查 key 是否存在,不会打印其值。不要在支持案例中打印、解码、记录或附加 Secret 数据。如果某个用户一直处于 Fail,请收集已省略 Secret 值的 User 资源、所属的 Valkey 状态、Events,以及相关的 Operator 日志。

有关 server 端 ACL 语义,请参阅官方 ACL 文档ACL SETUSER 命令参考