kubernetes:使用mysql容器创建statefulset时出错

aiazj4mn  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(484)

早上好,
我对docker和kubernetes很陌生,我真的不知道从哪里开始寻求帮助。我用docker创建了一个数据库容器,我想用kubernetes来管理它和扩展它。我开始在我的机器上安装minikube,并尝试先创建一个部署,然后为数据库容器创建一个statefulset。但是在使用数据库(mariadb或mysql)创建pod时,statefulset有一个问题。当我使用一个部署时,吊舱被加载并且工作正常。但是,当在statefulset中使用相同的pod时,它们不起作用,返回请求mysql常量的错误。这是部署,我使用命令 kubectl create -f deployment.yaml :

apiVersion: apps/v1beta1
kind: Deployment
metadata:
 name: mydb-deployment
spec:
 template:
  metadata:
   labels: 
    name: mydb-pod
  spec:
   containers:
    - name: mydb
      image: ignasiet/aravomysql
      ports:
       - containerPort: 3306

在列出部署时: kubectl get Deployments :

NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
mydb-deployment    1         1         1            1           2m

以及豆荚: kubectl get pods :

NAME                                READY   STATUS    RESTARTS   AGE
mydb-deployment-59c867c49d-4rslh    1/1     Running   0          50s

但是由于我想创建一个持久数据库,所以我尝试用相同的容器和持久卷创建一个statefulset对象。因此,在创建以下statefulset时 kubectl create -f statefulset.yaml :

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
 name: statefulset-mydb
spec:
 serviceName: mydb-pod
 template:
  metadata:
   labels: 
    name: mydb-pod
  spec:
   containers:
    - name: aravo-database
      image: ignasiet/aravomysql
      ports:
       - containerPort: 3306
      volumeMounts:
       - name: volume-mydb
         mountPath: /var/lib/mysql
   volumes:
    - name: volume-mydb
      persistentVolumeClaim: 
       claimName: config-mydb

与服务 kubectl create -f service-db.yaml :

apiVersion: v1
kind: Service
metadata:
 name: mydb
spec:
 type: ClusterIP
 ports:
  - port: 3306
 selector:
  name: mydb-pod

以及权限文件 kubectl create -f permissions.yaml :

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: config-mydb
spec:
 accessModes: 
  - ReadWriteOnce
 resources:
  requests:
   storage: 3Gi

豆荚不起作用。他们给出了一个错误:

NAME                    READY   STATUS             RESTARTS   AGE
statefulset-mydb-0      0/1     CrashLoopBackOff   1          37s

在分析日志时,kubectl logs statefulset-mydb-0:

`error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD`

当容器已经有一个初始化脚本并且工作正常时,它怎么可能要求这些变量呢?为什么它只在作为statefulset启动时询问,而不在启动部署时询问?
提前谢谢。

zrfyljdw

zrfyljdw1#

我拉了你的照片 ignasiet/aravomysql 试图找出哪里出了问题。事实证明,您的映像已经有一个初始化的mysql数据目录 /var/lib/mysql :

$ docker run -it --rm --entrypoint=sh ignasiet/aravomysql:latest

# ls -al /var/lib/mysql

total 110616
drwxr-xr-x 1 mysql mysql      240 Nov  7 13:19 .
drwxr-xr-x 1 root  root        52 Oct 29 18:19 ..
-rw-rw---- 1 root  root     16384 Oct 29 18:18 aria_log.00000001
-rw-rw---- 1 root  root        52 Oct 29 18:18 aria_log_control
-rw-rw---- 1 root  root      1014 Oct 29 18:18 ib_buffer_pool
-rw-rw---- 1 root  root  50331648 Oct 29 18:18 ib_logfile0
-rw-rw---- 1 root  root  50331648 Oct 29 18:18 ib_logfile1
-rw-rw---- 1 root  root  12582912 Oct 29 18:18 ibdata1
-rw-rw---- 1 root  root         0 Oct 29 18:18 multi-master.info
drwx------ 1 root  root      2696 Nov  7 13:19 mysql
drwx------ 1 root  root        12 Nov  7 13:19 performance_schema
drwx------ 1 root  root        48 Nov  7 13:19 yypy

但是,在安装 PersistentVolume 或者只是一个简单的docker卷 /var/lib/mysql ,它最初是空的,因此脚本认为您的数据库未初始化。您可以通过以下方式复制此问题:

$ docker run -it --rm --mount type=tmpfs,destination=/var/lib/mysql ignasiet/aravomysql:latest
error: database is uninitialized and password option is not specified 
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

如果需要运行一系列脚本来初始化数据库,则有两个选项:
基于 mysql dockerfile,并将shell脚本或sql脚本添加到 /docker-entrypoint-initdb.d . 在“初始化一个新示例”下面有更多的细节。
使用 initContainers 属性,类似于:

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: statefulset-mydb
spec:
  serviceName: mydb-pod
  template:
  metadata:
    labels: 
    name: mydb-pod
  spec:
    containers:
    - name: aravo-database
      image: ignasiet/aravomysql
      ports:
        - containerPort: 3306
      volumeMounts:
        - name: volume-mydb
          mountPath: /var/lib/mysql
    initContainers:
    - name: aravo-database-init
      command:
        - /script/to/initialize/database
      image: ignasiet/aravomysql
      volumeMounts:
        - name: volume-mydb
          mountPath: /var/lib/mysql
    volumes:
    - name: volume-mydb
      persistentVolumeClaim: 
        claimName: config-mydb
t1rydlwq

t1rydlwq2#

您所面临的问题并不特定于statefulset。这是因为持久的卷。如果在没有持久卷的情况下使用statefulset,则不会遇到此问题。或者,如果将部署与持久卷一起使用,您将面临这个问题。
为什么?好吧,让我解释一下。
设置其中一个环境变量 MYSQL_ROOT_PASSWORD , MYSQL_ALLOW_EMPTY_PASSWORD 或者 MYSQL_RANDOM_ROOT_PASSWORD 对于创建新数据库是必需的。阅读这里的环境变量部分。
但是,如果您从脚本初始化数据库,则不需要提供它。看这条线 docker-entrypont.sh 在这里。它检查是否已经有一个数据库 /var/lib/mysql 目录。如果没有,它将尝试创建一个。如果您没有提供任何指定的环境变量,那么它将给出您得到的错误。但是,如果它在那里已经找到一个数据库,它将不会尝试创建一个数据库,并且您也不会看到错误。
现在,问题是,您已经初始化了数据库,那么为什么它仍然抱怨环境变量呢?
在这里,持续的音量开始发挥作用。因为您已经在安装了持久卷 /var/lib/mysql 目录,现在这个目录指向当前为空的持久卷。所以,当你的容器 docker-entrypoint.sh 脚本,它在上找不到任何数据库 /var/lib/mysql 目录,因为它现在指向的是持久卷而不是原始卷 /var/lib/mysql 已在此目录上初始化数据库的docker映像的目录。所以,它会尝试创建一个新的数据库,并会抱怨你没有提供 MYSQL_ROOT_PASSWORD 环境变量。
当您不使用任何持久卷时 /var/lib/mysql 目录指向包含初始化数据库的原始目录。所以,你没有看到错误。
那么,如何正确初始化mysql数据库呢?
为了从脚本初始化mysql,您只需要将脚本放入 /docker-entrypoint-initdb.d . 只需使用一个香草mysql映像,将初始化脚本放入一个卷中,然后在 /docker-entrypoint-initdb.d 目录。mysql将被初始化。
有关如何从脚本初始化的详细信息,请检查此答案:https://stackoverflow.com/a/45682775/7695859

相关问题