美文网首页
k8s使用nfs持久存储mysql数据的一次踩坑

k8s使用nfs持久存储mysql数据的一次踩坑

作者: PENG先森_晓宇 | 来源:发表于2020-07-27 08:51 被阅读0次

    准备

    首先确保nfs服务端搭建成功。由于资源限制,我们的nfs服务器和k8s集群不在同一局域网内,所以k8s中pv使用公网ip连接nfs,且nfs服务器的带宽为10M。

    • 创建nfs pv
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-nfs
    spec:
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Recycle
      nfs:
        path: /mysql-data
        server: 39.105.232.177
    
    • 创建pvc
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: mysql-pvc
      namespace: laravel
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
    
    • 查看pv和pvc的状态

    pv属于bound状态

    NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
    mysql-nfs   10Gi       RWO            Recycle          Bound    laravel/mysql-pvc                           16d
    
    

    pvc也属于bound状态

    NAME        STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    mysql-pvc   Bound    mysql-nfs   10Gi       RWO                           16d
    

    如果没有使用storageclass,pv和pvc通过相同的storage存储大小和accessModes访问策略俩个元素来实现自动绑定。可以看到图中pv和pvc已经自动绑定。

    • 创建mysql的deployment
      使用的 harbor.maigengduo.com/laravel/mysql5.7镜像是基于docker官方的mysql:5.7镜像build的,mysql的data目录为/var/lib/mysql。
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: mysql
      namespace: laravel
      labels:
        name: mysql
      annotations:
        reloader.stakater.com/auto: "true"
    spec:
      replicas: 1
      selector:
        matchLabels:
          name: mysql
      template:
        metadata:
          labels:
            name: mysql
        spec:
          containers:
            - name: mysql
              image: harbor.maigengduo.com/laravel/mysql5.7:202007071543
              ports:
                - name: mysql-port
                  containerPort: 3306
                  protocol: TCP
              imagePullPolicy: Always
              env:
              - name: MYSQL_ROOT_PASSWORD
                value: root
              volumeMounts:
                - name: mysql-pvc
                  mountPath: "/var/lib/mysql"
          restartPolicy: Always
          volumes:
            - name: mysql-pvc
              persistentVolumeClaim:
                claimName: mysql-pvc
    

    部署完之后我开始认为,容器内的/var/lib/mysql目录下的数据会‘直接同步’到nfs服务端的/mysql-data目录下,注意:这里是我认为的,后面会验证我还是年轻啊,哈哈

    但是发现,容器内的数据文件并没有同步到nfs服务端,nfs服务端的共享目录只看到俩个文件,分别为ibdata1和ib_logfile0,而且导致mysql服务不可用,最严重的时候直接导致了整个k8s的pod都处于pendding状态了。

    为了确定问题,我将容器内别的目录(目录大小比较小)重新挂载到nfs上,发现是可以正常同步的,证明是/var/lib/mysql目录特殊,特殊点有俩个,第一个该目录的用户和所属组都是mysql,第二点是该目录比较大

    root@mysql-85bc98b4d9-gg4q2:/var/lib# ls -l
    total 32
    drwxr-xr-x 1 root  root  4096 Aug 14  2019 apt
    drwxr-xr-x 1 root  root  4096 Aug 14  2019 dpkg
    drwxr-xr-x 2 root  root  4096 Mar 28  2019 misc
    drwxr-xr-x 6 mysql mysql 4096 Jul 24 01:10 mysql
    drwxrwx--- 2 mysql mysql 4096 Aug 14  2019 mysql-files
    drwxr-x--- 2 mysql mysql 4096 Aug 14  2019 mysql-keyring
    drwxr-xr-x 2 root  root  4096 Aug 12  2019 pam
    drwxr-xr-x 1 root  root  4096 Aug 12  2019 systemd
    
    root@mysql-85bc98b4d9-gg4q2:/var/lib/mysql# du -sh
    422M    .
    .
    

    于是这里提出有几个问题

    1. nfs服务端为什么只同步过俩个文件?
    2. 为什么mysql服务会不可用?为什么严重时整个k8s中的pod都处于pendding状态了呢?

    带着上面的俩个问题,多次实验首先发现了下面这个问题

    nfs服务端共享文件夹权限问题

    现象:nfs服务端的共享目录/mysql-data原本的用户和所属组都是root,如下

    [root@iZ2zebwwgp62jma838rfc4Z /]# ls -l
    drwxr-xr-x   6 root root  4096 Jul 24 09:10 mysql-data
    

    但是当部署deployment后,也就是客户端挂载后,服务端的共享目录/mysql-data的用户变为了polkitd,用户组变成了input,如下

    [root@iZ2zebwwgp62jma838rfc4Z /]# ls -l
    drwxr-xr-x   6 polkitd input  4096 Jul 24 09:10 mysql-data
    

    为什么呢?感觉有点不正常。

    • 首先查看容器内的/var/lib/mysql目录的权限,看到该目录所属用户和用户组都为mysql
    root@mysql-85bc98b4d9-gg4q2:/var/lib# ls -l
    total 32
    drwxr-xr-x 1 root  root  4096 Aug 14  2019 apt
    drwxr-xr-x 1 root  root  4096 Aug 14  2019 dpkg
    drwxr-xr-x 2 root  root  4096 Mar 28  2019 misc
    drwxr-xr-x 6 mysql mysql 4096 Jul 24 01:10 mysql
    

    然后查看用户为mysql的相关信息,发现用户myql所属id为999,所属组id也为999

    root@mysql-85bc98b4d9-gg4q2:/var/lib# cat /etc/passwd | grep mysql
    mysql:x:999:999::/home/mysql:
    
    • 查看宿主机上用户id为999的信息,发现用户id为999的用户为polkitd。
    [root@iZ2zebwwgp62jma838rfc4Z /]# cat /etc/passwd | grep 999
    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    

    继续查看用户组id为999的组名,发现用户组id为999的组名为input。

    [root@iZ2zebwwgp62jma838rfc4Z /]# cat /etc/group | grep 999
    input:x:999:
    

    到这里你肯定明白了宿主机上共享目录的权限怎么变成用户为polkitd,用户组变成了input。

    • 总结

    宿主机使用volume映射到容器内时,宿主机和容器内的文件或文件夹的权限是相同的,准备的说是用户id和用户组id是相同的。

    解决

    似乎上面那个现象对我们上面提的俩问题并没有什么帮助,但是上面那个现象是真实存在的,我们必须搞清楚。接下来进入正题。。。

    • nfs服务端为什么只同步过俩个文件?

    刚开始时这个问题真的很棘手,后来静下来想想,这个目录大小将近500M,是不是目录太大的问题,同步需要时间呢?所以并不是只同步过来俩个文件,而是正在同步中,接下来验证这个猜想。

    首先在宿主机的共享目录下查看文件夹大小,发现为100M

    [root@iZ2zebwwgp62jma838rfc4Z mysql-data]# du -sh
    100M    .
    

    在过2秒查看一遍,发现大小变为101M

    [root@iZ2zebwwgp62jma838rfc4Z mysql-data]# du -sh
    101M    .
    

    此时真的验证了我们的猜想,nfs服务端的数据是正在同步中,只是nfs的写速度真的很慢,让我们以为就同步过来俩个文件,被表象所迷惑。
    同步速度慢主要有几个原因,首先io同步就是耗时的,其次nfs服务器和k8s不在一个局域网内,然后nfs服务器的带宽也很低,最主要的还是nfs服务写速度真的很慢。

    • 为什么mysql服务会不可用?为什么严重时整个k8s中的pod都处于pendding状态了呢?

    写io是很耗cpu的,更何况这种大量复制。既然服务不可用了,我们使用top命令查看下k8s worker节点机器的各项性能,如下图。发现nfs在同步过程有一个nginx的command的进程cpu竟然达到了99%,us的cpu达到了23.5%,sy的cpu达到了48.6%,很显然,io同步时消耗了大量的cpu,导致mysql服务不可用了,而k8s的pod都会占用宿主机的cpu的资源的,如果宿主机的cpu资源不够pod所申明的cpu,pod将会重新构建,进而进入pod的生命周期中的pendding状态,所有pod都在争抢宿主机cpu的资源。

    image.png

    总结:写io是很耗cpu资源,为了k8s集群服务的可用性,我们需要将k8s的node节点的cpu调大点。

    如果你了解k8s resource,你就会知道,只有当节点拥有足够满足 Pod 内存请求的内存和cpu请求的cpu时,才会将 Pod 调度至节点上运行,显然上面这种情况消耗了大量的cpu,导致pod都调度不到节点上,以至于处于pendding状态。

    可以看到我们上面的mysql deployment中并没有设置resource相关cpu和memory配置,pod默认limit为节点的所有cpu个memory。当nfs数据复制时,将大量消耗pod内的cpu,以至于node节点的cpu被消耗完,这是出现这个问题的根本原因,体现了pod设置resource资源的重要性,不然某个pod类似我们的这种情况将会消耗光节点的所有资源。

    上面俩个问题解决后,等到mysql的数据文件全部同步到nfs上时,理应mysql服务和其他服务都能正常访问了,但是并没有预期的那么好,又出现了下面这个问题。。

    mysql connection is not allowed

    在集群外连接mysql时报以下错误。

    rHost '172-17-208-115.calico-typha.kube-system.svc.cluster.local' is 
    not allowed to connect to this MySQL serverConnection closed by foreign host.
    
    • 解决

    这个原因是因为索要链接的mysql数据库只允许其所在的服务器连接,需要在mysql服务器上设置一下允许的ip权限

    grant all privileges on *.* to 'root'@'%' identified by 'root';
    flush privileges;
    

    相关文章

      网友评论

          本文标题:k8s使用nfs持久存储mysql数据的一次踩坑

          本文链接:https://www.haomeiwen.com/subject/icadlktx.html