Docker Mysql 官方镜像没有在 kubernetes 中创建用户

Docker Mysql official image not creating user in kubernetes

我正在尝试使用来自 DockerHub 的官方 Mysql 图像通过 StatefulSet 在 k8s 中部署一个 mysql 实例。我正在关注 DockerHub 的图像文档并提供 MYSQL_ROOT_PASSWORDMYSQL_USERMYSQL_PASSWORD 环境变量,因此应该自动创建用户,但事实并非如此。我在容器日志中看到的错误是 root 用户在创建 MYSQL_USER 中提供的用户时无法连接。

2021-09-14 17:28:20+00:00 [Note] [Entrypoint]: Creating user foo_user
2021-09-14T17:28:20.860763Z 5 [Note] Access denied for user 'root'@'localhost' (using password: YES)
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

经过一些调查,我注意到当环境变量的值取自 k8s 机密时会出现问题,但如果我在 StatefulSet 的清单中对它们的值进行硬编码,它就可以正常工作。您可以在下面看到我当前的代码:

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  serviceName: mysql-svc
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: "mysql:latest"
        env:
        - name: MYSQL_DATABASE
          value: 'foo_db'
        - name: MYSQL_USER
          value: 'foo_user'
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-sec
              key: MYSQL_PASSWORD
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-sec
              key: MYSQL_ROOT_PASSWORD
        ports:
        - containerPort: 3306
          protocol: TCP
        volumeMounts:
        - name: mysql-db
          mountPath: /var/lib/mysql
          subPath: mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-db
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 4Gi

secrets.yml 文件:

apiVersion: v1
kind: Secret
metadata:
  name: mysql-sec
  labels:
    app: mysql
type: Opaque
data:
  MYSQL_PASSWORD: ***************************
  MYSQL_ROOT_PASSWORD: ***************************

我也尝试先创建密文以确保密文在 pod 启动时已经存在,但没有成功。

有什么想法吗?

我终于找到了问题的根本原因,它与机密无关...问题与为密码选择的值的“复杂性”有关。我选择了一个由在线工具自动生成的强密码,类似于 !6Y*]q~x+xG{9HQ~,并且出于某种未知原因,此谷使 mysql docker 图像的 /entrypoint.sh 脚本失败出现上述错误 Access denied for user 'root'@'localhost' (using password: YES)。然而,即使脚本失败,容器和 mysql 服务器已启动&运行,我能够潜入并成功执行 mysql -u root --password="$MYSQL_ROOT_PASSWORD",所以我很清楚错误位于此脚本及其扩展和使用此环境变量值的方式中。在用一个“不太复杂”的密码值交换密码值后,它就像一个魅力。

这可能取决于您创建 Secret 的准确程度。事实上,如果您在创建 Secret.

时使用单引号,那么包含某些特殊字符的密码应该不是问题

我相信 official kubernetes documentation 的这个片段应该可以回答您的问题:

Note:

Special characters such as $, \, *, =, and ! will be interpreted by your shell and require escaping. In most shells, the easiest way to escape the password is to surround it with single quotes ('). For example, if your actual password is S!B\*d$zDsb=, you should execute the command this way:

kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb='

You do not need to escape special characters in passwords from files (--from-file).

请注意存储在 Secret 中的值,例如如下片段所示:

    type: Opaque
    data:
      MYSQL_PASSWORD: ***************************
      MYSQL_ROOT_PASSWORD: ***************************

base64 编码的字符串。因此,如果您在将它们放入 secret.yaml:

之前正确编码它们
echo '!6Y*]q~x+xG{9HQ~' | base64

你不应该 运行 遇到任何问题。