GKE Kubernetes MySQL输入/输出错误Ext4Error

我在Kubernetes分区集群上部署了一个MySQL数据库(状态集),在Google Cloud平台上作为服务(GKE)运行。

分区群集由类型为e2-Medium的3个实例组成。

由于以下错误,MySQL容器无法启动。

kubectl logs mysql-statefulset-0
2022-02-07 05:55:38+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.35-1debian10 started.
find: '/var/lib/mysql/': Input/output error

上次查看的事件。

4m57s   Warning   Ext4Error   gke-cluster-default-pool-rnfh   kernel-monitor, gke-cluster-default-pool-rnfh   EXT4-fs error (device sdb): __ext4_find_entry:1532: inode #2: comm mysqld: reading directory lblock 0   40d   8062   gke-cluster-default-pool-rnfh
3m22s   Warning   BackOff     pod/mysql-statefulset-0   spec.containers{mysql}   kubelet, gke-cluster-default-pool-rnfh   Back-off restarting failed container

节点。

kubectl get node -owide
gke-cluster-default-pool-ayqo   Ready    <none>   54d   v1.21.5-gke.1302   So.Me.I.P   So.Me.I.P    Container-Optimized OS from Google   5.4.144+         containerd://1.4.8
gke-cluster-default-pool-rnfh   Ready    <none>   54d   v1.21.5-gke.1302   So.Me.I.P   So.Me.I.P   Container-Optimized OS from Google   5.4.144+         containerd://1.4.8
gke-cluster-default-pool-sc3p   Ready    <none>   54d   v1.21.5-gke.1302   So.Me.I.P   So.Me.I.P     Container-Optimized OS from Google   5.4.144+         containerd://1.4.8

我还注意到rnfh节点内存不足。

kubectl top node
NAME                            CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
gke-cluster-default-pool-ayqo   117m         12%    992Mi           35%
gke-cluster-default-pool-rnfh   180m         19%    2953Mi          104%
gke-cluster-default-pool-sc3p   179m         19%    1488Mi          52%

MySQL Mainfest

# HEADLESS SERVICE
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless-service
  labels:
    kind: mysql-headless-service
spec:
  clusterIP: None
  selector:
    tier: mysql-db
  ports:
    - name: 'mysql-http'
      protocol: 'TCP'
      port: 3306
---
# STATEFUL SET
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-statefulset
spec:
  selector:
    matchLabels:
      tier: mysql-db
  serviceName: mysql-statefulset
  replicas: 1
  template:
    metadata:
      labels:
        tier: mysql-db
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: my-mysql
          image: my-mysql:latest
          imagePullPolicy: Always
          args:
            - "--ignore-db-dir=lost+found"
          ports:
            - name: 'http'
              protocol: 'TCP'
              containerPort: 3306
          volumeMounts:
            - name: mysql-pvc
              mountPath: /var/lib/mysql
          env:
            - name: MYSQL_ROOT_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-root-username
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-root-password
            - name: MYSQL_USER
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-username
            - name: MYSQL_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-password
            - name: MYSQL_DATABASE
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-database
  volumeClaimTemplates:
    - metadata:
        name: mysql-pvc
      spec:
        storageClassName: 'mysql-fast'
        resources:
          requests:
            storage: 120Gi
        accessModes:
          - ReadWriteOnce
          - ReadOnlyMany

MySQL存储类清单:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: mysql-fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate

为什么Kubernetes尝试将Pod调度到内存不足的节点?

更新

我已向MySQL清单添加了请求和限制,以改进Qos Class。现在Qos ClassGuaranteed

遗憾的是,Kubernetes仍在尝试调度到内存不足rnfh节点。

kubectl describe po mysql-statefulset-0 | grep node -i
Node: gke-cluster-default-pool-rnfh/So.Me.I.P

kubectl describe po mysql-statefulset-0 | grep qos -i
QoS Class: Guaranteed

解决方案

我又运行了几个测试,但无法复制。

要正确回答这个问题,我们需要更多的日志。不确定你是否还留着它们。如果我能猜到哪个是这个问题的根本原因,我会说它与PersistentVolume有关。

在其中一个Github issue - Volume was remounted as read only after error #752中,我发现其行为与OP的行为非常相似。

您已经为您的MySQL创建了special存储类。您已设置reclaimPolicy: Retain,因此未删除PV。当StatefulsetPod(具有相同后缀-0)重新创建(由于连接错误、数据库上的一些问题而重新启动,很难说)时,它会尝试重新认领此卷。在提到的Github问题中,用户也有非常相似的情况。也有inode #262147: comm mysqld: reading directory lblock问题,但在下面也有条目[ +0.003695] EXT4-fs (sda): Remounting filesystem read-only。可能在重新装载时更改了权限?

您的volumeClaimTemplates包含的另一件事

        accessModes:
          - ReadWriteOnce
          - ReadOnlyMany
因此,一个PersistentVolume可以被一个节点用作ReadWriteOnce,也可以被多个节点仅用作ReadOnlyMany。有可能使用Read-Only评估模式在不同节点中重新创建POD。

[ +35.912075] EXT4-fs warning (device sda): htree_dirblock_to_tree:977: inode #2: lblock 0: comm mysqld: error -5 reading directory block
[  +6.294232] EXT4-fs error (device sda): ext4_find_entry:1436: inode #262147: comm mysqld: reading directory lblock ...
[  +0.005226] EXT4-fs error (device sda): ext4_find_entry:1436: inode #2: comm mysqld: reading directory lblock 0
[  +1.666039] EXT4-fs error (device sda): ext4_journal_check_start:61: Detected aborted journal
[ +0.003695] EXT4-fs (sda): Remounting filesystem read-only

它适合OP的评论:

两天前,由于我不知道的原因,Kubernetes重新启动了容器,并一直尝试在rnfa机器上运行它。容器可能已从另一个节点逐出。

另外,可能会更新节点或群集(取决于是否打开了自动更新选项),这可能会强制重新启动Pod。

'/var/lib/mysql/': Input/output error问题可能指向数据库损坏,如前面提到的here。

通常,该问题已由cordoning受影响的节点解决。有关cordondrain之间差异的其他信息,请参阅here。

与添加一样,要将实例分配给特定节点或具有指定标签的节点,可以使用Affinity

相关文章