早上好,
我对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启动时询问,而不在启动部署时询问?
提前谢谢。
2条答案
按热度按时间zrfyljdw1#
我拉了你的照片
ignasiet/aravomysql
试图找出哪里出了问题。事实证明,您的映像已经有一个初始化的mysql数据目录/var/lib/mysql
:但是,在安装
PersistentVolume
或者只是一个简单的docker卷/var/lib/mysql
,它最初是空的,因此脚本认为您的数据库未初始化。您可以通过以下方式复制此问题:如果需要运行一系列脚本来初始化数据库,则有两个选项:
基于
mysql
dockerfile,并将shell脚本或sql脚本添加到/docker-entrypoint-initdb.d
. 在“初始化一个新示例”下面有更多的细节。使用
initContainers
属性,类似于: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