首页 > 其他分享 >k8s数据持久化

k8s数据持久化

时间:2023-12-13 15:45:30浏览次数:39  
标签:持久 name nfs mysql yuchaoit pod k8s 数据

前面的学习,我们已经基本完成了在k8s中部署一个web服务,运行pod、创建service、创建ingress对外提供域名的七层代理。

下一个环境就得去关注应用部署后的数据存储问题,容器化如何管理,k8s化如何管理。

1.什么是Volume

1.容器内部的存储数据,再容器生命周期中是很短暂的,伴随容器的销毁而删除,很不稳定。
2.并且在一个pod下同时运行多个容器,经常需要再多个容器之间共享文件。
3.因此k8s抽象了一个Volume存储卷来解决这些问题。
4.volume属于是pod的一部分,不能单独创建,只能在pod中定义(谨记)。
5.pod中的所有容器都可以访问Volume,且是挂载后使用,可以挂载到容器内任何目录。
6.k8s的volume不仅支持集群内部的资源类型,还支持第三方的存储类型。

 

2.Volume类型

Kubernetes的Volume有非常多的类型,在实际使用中使用最多的类型如下。

  • emptyDir:一种简单的空目录,主要用于临时存储。
  • hostPath:将主机某个目录挂载到容器中。
  • ConfigMap、Secret:特殊类型,将Kubernetes特定的对象类型挂载到Pod,在ConfigMapSecret章节介绍过如何将ConfigMap和Secret挂载到Volume中。
  • persistentVolumeClaim:Kubernetes的持久化存储类型,详细介绍请参考PV、PVC和StorageClass中会详细介绍。

2.1 EmptyDir类型

EmptyDir是最简单的一种Volume类型,根据名字就能看出,这个Volume挂载后就是一个空目录,应用程序可以在里面读写文件,emptyDir Volume的生命周期与Pod相同,Pod删除后Volume的数据也同时删除掉。

emptyDir配置示例如下。

  • Pod内的容器共享卷的数据
  • 存在于Pod的生命周期,Pod销毁,数据丢失
  • Pod内的容器自动重建后,数据不会丢失
[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox-empty
  namespace: yuchaoit
spec:
  containers:
  - image: busybox
    name: test-busybox
    volumeMounts:
    - mountPath: /data/busybox/
      name: cache-busybox
    command: ["/bin/sh","-c","while true;do echo $(date) >> /data/busybox/www.yuchaoit.cn.log;sleep 2;done"]
  volumes:
  - name: cache-busybox
    emptyDir: {}

emptyDir实际是将Volume的内容写在Pod所在节点的磁盘上

创建资源

[root@k8s-master-10 ~/test-volumes]#kubectl create -f busybox-volume.yml 

[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po busybox-empty -owide
NAME            READY   STATUS    RESTARTS   AGE     IP          NODE          NOMINATED NODE   READINESS GATES
busybox-empty   1/1     Running   0          2m18s   10.2.1.48   k8s-node-11   <none>           <none>

查看目标机器的Volume情况

# 1. docker inspect查看容器挂载信息

# 2. 查看宿主机挂载目录
[root@k8s-node-11 ~]#tail -f   /var/lib/kubelet/pods/e631e809-d3e7-4bcf-8d13-3364a4e4add2/volumes/kubernetes.io~empty-dir/cache-busybox/*
Mon Sep 12 08:44:03 UTC 2022
Mon Sep 12 08:44:05 UTC 2022
Mon Sep 12 08:44:07 UTC 2022
Mon Sep 12 08:44:09 UTC 2022
Mon Sep 12 08:44:11 UTC 2022
Mon Sep 12 08:44:13 UTC 2022
Mon Sep 12 08:44:15 UTC 2022
Mon Sep 12 08:44:17 UTC 2022
Mon Sep 12 08:44:19 UTC 2022

干掉pod

[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit delete po busybox-empty 
pod "busybox-empty" deleted

查看Volume状态
随之也被清空了

2.2 HostPath类型

https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/

Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。

问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态重启。

第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。

阅读本文前建议你熟悉一下 Pod

1.HostPath是一种持久化存储,emptyDir里面的内容会随着Pod的删除而消失,但HostPath不会
2.如果对应的Pod删除,HostPath Volume里面的内容依然存在于节点的目录中,如果后续重新创建Pod并调度到同一个节点,挂载后依然可以读取到之前Pod写的内容。

3.HostPath存储的内容与节点相关,所以它不适合像数据库这类的应用,想象下如果数据库的Pod被调度到别的节点了,那读取的内容就完全不一样了。

4.记住永远不要使用HostPath存储跨Pod的数据,一定要把HostPath的使用范围限制在读取节点文件上,这是因为Pod被重建后不确定会调度哪个节点上,写文件可能会导致前后不一致。

yaml

[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox-hostpath
  namespace: yuchaoit
spec:
  volumes:
  - name: hostpath-busybox
    hostPath:
      path: /data/hostpath-busybox # 宿主机映射点
      type: DirectoryOrCreate # 目录不存在自动创建


  containers:
  - image: busybox
    name: test-busybox
    volumeMounts:  # 容器数据挂到Volume里
    - mountPath: /data/busybox/ # 容器内挂载点
      name: hostpath-busybox    # 容器内挂载点,挂到哪个卷
    command: ["/bin/sh","-c","while true;do echo $(date) 超哥带你学k8s >> /data/busybox/www.yuchaoit.cn.log;sleep 2;done"]

创建结果

[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po busybox-hostpath -owide
NAME               READY   STATUS    RESTARTS   AGE   IP          NODE          NOMINATED NODE   READINESS GATES
busybox-hostpath   1/1     Running   0          42s   10.2.1.49   k8s-node-11   <none>           <none>

查看宿主机日志挂载

 

删除pod,查看hostPath数据

 

2.3 NFS 类型

https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#nfs

很明显,这种不一致的数据持久化,必然是不可取的,我们可以采用共享式存储文件系统,NFS就是个代表。

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。

不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

注意: 在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。

# 变化的只有关于Volume设置参数
# 查看应该用什么字段
# [root@k8s-master-10 ~/test-volumes]#kubectl explain pod.spec.volumes.nfs
# 提前准备好一个NFS服务器即可。
 # yum install nfs-utils rpcbind -y
 # /nfsShare *(insecure,rw,sync,root_squash)

具体yaml

[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-volume-nfs
  namespace: yuchaoit
spec:
  volumes:
  - name: nfs-data
    nfs:
      server: 10.0.0.11
      path: /nfsShare


  containers:
  - image: nginx:1.14.1
    name: nginx-volume-nfs
    ports:
      - name: http
        containerPort: 80
    volumeMounts:  # 容器数据挂到Volume里
    - mountPath: /usr/share/nginx/html/ # 容器内挂载点
      name: nfs-data    # 容器内挂载点,挂到哪个卷

创建pod查看nfs共享数据

[root@k8s-master-10 ~/test-volumes]#kubectl create -f nfs-volume.yml 
pod/nginx-volume-nfs created
[root@k8s-master-10 ~/test-volumes]#
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po -owide
NAME                                READY   STATUS    RESTARTS   AGE   IP          NODE          NOMINATED NODE   READINESS GATES
nginx-deployment-6f7886b6db-pvjd5   1/1     Running   0          6h    10.2.2.60   k8s-node-12   <none>           <none>
nginx-deployment-6f7886b6db-xsj8n   1/1     Running   0          6h    10.2.1.47   k8s-node-11   <none>           <none>
nginx-volume-nfs                    1/1     Running   0          6s    10.2.1.50   k8s-node-11   <none>           <none>
[root@k8s-master-10 ~/test-volumes]#
[root@k8s-master-10 ~/test-volumes]#curl 10.2.1.50
<meta charset=utf-8>超哥带你学k8s www.yuchaoit.cn

思考

这只是给pod单个的添加Volume字段,如果一组pod控制器需要使用nfs,该如何配置?

volume支持的种类众多(参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes )
每种对应不同的存储后端实现,因此为了屏蔽后端存储的细节,同时使得Pod在使用存储的时候更加简洁和规范,k8s引入了两个新的资源类型,PV和PVC。


PersistentVolume(持久化卷),是对底层的存储的一种抽象,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。
如使用PV对接NFS存储。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity: 
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfsShare
    server: 10.0.0.11

2.4 实践持久化mysql数据

学习点

1.基于节点选择器指定运行mysql的Node
2.使用Deployment管理mysql
3.使用hostPath持久化mysql数据

yaml

apiVersion: apps/v1      # 注意这里与Pod的区别,Deployment是apps/v1而不是v1
kind: Deployment         # 资源类型为Deployment
metadata:
  name: mysql-deploy         # Deployment的名称
  namespace: yuchaoit
spec:
  selector:      # 要和pod的label对应上
    matchLabels:
      app: mysql  
  replicas: 1             # Pod的数量,Deployment会确保一直有1个Pod运行         

  template:               # Pod的定义,用于创建Pod,也称为Pod template
    metadata:             # pod的信息
      labels:             # pod打上标签
        app: mysql 
    spec:                 # pod具体字段属性,如容器信息,存储卷,pod部署节点等
      volumes:
        - name: mysql-volume # 卷名
          hostPath: # 卷类型
            path: /www.yuchaoit.cn/mysql # 宿主机目录
            type: DirectoryOrCreate
      nodeSelector: # pod部署节点选择器
        diskType: ssd # label的key-value
      containers: # pod内容器信息
      - image: mysql:5.7 # 镜像下载地址
        name: mysql-pod # 容器名
        imagePullPolicy: IfNotPresent # 镜像下载策略
        ports: # 容器内暴露端口
          - name: mysql-port 
            containerPort: 3306 # 指明容器内要暴露的端口
        env: # 给容器设置运行环境变量
          - name: MYSQL_ROOT_PASSWORD
            value: "www.yuchaoit.cn"
        volumeMounts:
          - mountPath: /var/lib/mysql # 容器内挂载点
            name: mysql-volume # 挂载的设备,卷的名字

创建mysql-pod

[root@k8s-master-10 ~/test-volumes]#kubectl create -f mysql-deploy.yml 
deployment.apps/mysql-deploy created


[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po
NAME                                READY   STATUS    RESTARTS   AGE
mysql-deploy-569f9d64fc-86mpq       0/1     Pending   0          10s

# 查看事件,为什么pending
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit describe pod mysql-deploy-569f9d64fc-86mpq 


# 经典的事件报错
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  41s   default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
  Warning  FailedScheduling  41s   default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.


# 给Node打上标签
[root@k8s-master-10 ~/test-volumes]#kubectl label nodes k8s-node-12 diskType=ssd
node/k8s-node-12 labeled


# 此时会发现pod动态已自动更新了
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po mysql-deploy-569f9d64fc-86mpq  -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP          NODE          NOMINATED NODE   READINESS GATES
mysql-deploy-569f9d64fc-86mpq   1/1     Running   0          2m47s   10.2.2.61   k8s-node-12   <none>           <none>

图解mysql-pod数据持久化

1.检查mysql节点的持久化数据
[root@k8s-node-12 /www.yuchaoit.cn/mysql]#ls
auto.cnf  ca-key.pem  ca.pem  chaoge666  client-cert.pem  client-key.pem  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ibtmp1  mysql  performance_schema  private_key.pem  public_key.pem  server-cert.pem  server-key.pem  sys
[root@k8s-node-12 /www.yuchaoit.cn/mysql]#

2.尝试连接集群内pod的mysql
# 这里临时运行一个新pod,去登录mysql-pod。

 

创建pod远程连接mysql-pod

[root@k8s-master-10 ~/test-volumes]#kubectl run client-mysql -it --image=mysql:5.7 --  bash -c 'mysql -uroot -pwww.yuchaoit.cn -h10.2.2.61 -P3306'
If you don't see a command prompt, try pressing enter.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.7.36, for Linux (x86_64) using  EditLine wrapper

Connection id:        6
Current database:    
Current user:        [email protected]
SSL:            Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
Current pager:        stdout
Using outfile:        ''
Using delimiter:    ;
Server version:        5.7.36 MySQL Community Server (GPL)
Protocol version:    10
Connection:        10.2.2.61 via TCP/IP
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    latin1
Conn.  characterset:    latin1
TCP port:        3306
Uptime:            8 min 39 sec

Threads: 1  Questions: 15  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.028
--------------

mysql>

2.5 综合练习 k8s运行wordpress

以目前所有所学知识点,完成wordpress在k8s下的运行,并且可以通过域名

1. wordpress.yuchaoit.cn 访问博客集群入口
2. 用deployment控制器单独管理mysql(副本数1)、单独管理wordpress(副本数2)
3. 创建Service代理mysql,以及wordpress
4. 创建wordpress访问集群入口

实践

nfs共享存储

选用随便一个机器,如11机器。

yum install nfs-utils -y 
cat >/etc/exports <<'EOF'
/nfs-volume/blog/ *(rw,sync,no_root_squash)
EOF

mkdir -p /nfs-volume/blog/

systemctl restart nfs

1. mydel-deployment.yml

yaml所有字段,不要求你去记住,会看、会修改、确保业务运行即可。

面试官问你,k8s中遇见不认识的字段,你是怎么处理的?

答。基于kubectl explain查阅资料,以及官网。

apiVersion: apps/v1      # 注意这里与Pod的区别,Deployment是apps/v1而不是v1
kind: Deployment         # 资源类型为Deployment
metadata:
  name: mysql-deploy            # Deployment的名称
  namespace: yuchaoit
  labels:
    app: mysql
spec:
  selector:       # RS控制器基于label匹配pod,确保副本数
    matchLabels:
      app: mysql

  template:              # Pod的定义,用于创建Pod,也称为Pod template
    metadata:
      labels:           # pod打上标签
        app: mysql  # 必须和selector一样
    spec:
      volumes:
        - name: db
          hostPath:
            path: /data/mysql
      nodeSelector:
        diskType: ssd

      containers:
      - image: mysql:5.7
        name: mysql-blog
        imagePullPolicy: IfNotPresent
        args:                               # 容器运行参数
        - --default_authentication_plugin=mysql_native_password
        - --character-set-server=utf8mb4
        - --collation-server=utf8mb4_unicode_ci

        ports:            
          - name: dbport   
            containerPort: 3306 # 指明容器内要暴露的端口
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: www.yuchaoit.cn
        - name: MYSQL_DATABASE
          value: wordpress
        - name: MYSQL_USER
          value: wordpress
        - name: MYSQL_PASSWORD
          value: www.yuchaoit.cn
        volumeMounts:
          - name: db
            mountPath: /var/lib/mysql/

创建结果

[root@k8s-master-10 ~]#kubectl -n yuchaoit get po -owide
NAME                           READY   STATUS    RESTARTS   AGE   IP          NODE          NOMINATED NODE   READINESS GATES
mysql-deploy-75f47f87c-l7t8f   1/1     Running   0          6s    10.2.2.64   k8s-node-12   <none>           <none>

2. mysql-svc.yml

给mysql服务,进行服务发现(选择pod 带有app: mysql)

apiVersion: v1
kind: Service
metadata:
  name: mysql        # Service的名称,服务发现名称
  namespace: yuchaoit
spec:
  selector:          # Label Selector,选择包含app=nginx标签的Pod
    app: mysql
  ports:
  - name: mysql-port
    targetPort: dbport   # 直接基于mysql-pod暴露的端口名即可对应
    port: 3306         # Service对外暴露的端口,也就是ClusterIP的port
    protocol: TCP    # 转发协议类型,支持TCP和UDP

查看svc

[root@k8s-master-10 ~]#kubectl -n yuchaoit get svc mysql -owide
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE    SELECTOR
mysql   ClusterIP   10.1.225.170   <none>        3306/TCP   103s   app=mysql


# 确认svc可用
[root@k8s-master-10 ~]#docker run mysql:5.7.25 bash -c 'mysql -uroot -pwww.yuchaoit.cn -h10.1.225.170 -P3306 -e "status;"'
mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
mysql  Ver 14.14 Distrib 5.7.25, for Linux (x86_64) using  EditLine wrapper

Connection id:        3
Current database:    
Current user:        [email protected]
SSL:            Cipher in use is DHE-RSA-AES256-SHA
Current pager:        stdout
Using outfile:        ''
Using delimiter:    ;
Server version:        5.7.36 MySQL Community Server (GPL)
Protocol version:    10
Connection:        10.1.225.170 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    latin1
Conn.  characterset:    latin1
TCP port:        3306
Uptime:            9 min 46 sec

Threads: 1  Questions: 10  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.017
--------------

3. wordpress-deploy.yml

于超老师强烈建议,纯手敲,前期别偷懒,挨个的理解字段的作用。

你可能会遇见N个错误,但是你也有了N个成长。

[root@k8s-master-10 ~]#cat deploy-wordpress.yml 
apiVersion: apps/v1      # 注意这里与Pod的区别,Deployment是apps/v1而不是v1
kind: Deployment         # 资源类型为Deployment
metadata:
  name: wordpress-deploy            # Deployment的名称
  namespace: yuchaoit
  labels:
    app: wordpress
spec:
  replicas: 2 # pod副本数
  selector:       # RS控制器基于label匹配pod,确保副本数
    matchLabels:
      app: wordpress
  minReadySeconds: 5 # 新创建的 pod 应准备就绪的最小秒数
  strategy: # 设置Deployment滚动更新pod的策略
    type: RollingUpdate # 默认就是滚动更新
    rollingUpdate:
      maxSurge: 1 # 最大调度1个pod
      maxUnavailable: 1 # 最多不可用1个
  template:              # Pod的定义,用于创建Pod,也称为Pod template
    metadata:
      labels:           # pod打上标签
        app: wordpress 
    spec:
      volumes:
        - name: nfs-data # 定义pod的数据卷,给容器使用
          nfs:
            server: 10.0.0.11
            path: /nfs-volume/blog/ # 使用nfs的什么共享目录
      initContainers:  # 初始化容器,启动wordpress前,至少确认呢mysql是连通的,否则没意义
        - name: init-db
          image: busybox
          command: ['sh','-c','until nslookup mysql;do echo waiting for mysql service done....www.yuchaoit.cn...;sleep 1;done;']


      containers:
      - image: wordpress
        name: wordpress-blog
        imagePullPolicy: IfNotPresent
        ports:
          - name: wordpressport # 容器暴露端口,对应的名字,便于其他服务调用
            containerPort: 80


        env: # 根据wordpress镜像要求的环境变量,传入参数
        - name: WORDPRESS_DB_HOST
          value: mysql:3306 # 传入的是Service名字,以及端口
        - name: WORDPRESS_DB_USER
          value: wordpress
        - name: WORDPRESS_DB_PASSWORD
          value: www.yuchaoit.cn

        readinessProbe: # 就绪探针
          tcpSocket:
            port: 80
          initialDelaySeconds: 5 #5秒后开始探测
          periodSeconds: 10 # 10S探测一次
        resources:
          requests: # 节点所需的最小资源
            memory: 256Mi
            cpu: 200m
          limits:   # 限制pod最大资源使用量
            memory: 256Mi
            cpu: 200m
        volumeMounts: # 容器使用卷
          - name: nfs-data
            mountPath: /var/www/html/wp-content # 容器内挂载点

# 这是一个经典的应用部署yaml,对于基础所需的deployment,部署应用,需要考虑到的pod字段,都用上了,作为学习pod部署样本。
#
[root@k8s-master-10 ~]#

创建wordpress应用pod,过程估计得有1分钟,有一个下载时间,可以提前先准备好镜像。

查看pod运行结果
[root@k8s-master-10 ~]#kubectl -n yuchaoit get po -owide -l app=wordpress
NAME                               READY   STATUS     RESTARTS   AGE    IP          NODE          NOMINATED NODE   READINESS GATES
wordpress-deploy-c4df856c7-4p4bt   0/1     Init:0/1   0          5m8s   <none>      k8s-node-12   <none>           <none>
wordpress-deploy-c4df856c7-qncj2   1/1     Running    0          5m8s   10.2.1.51   k8s-node-11   <none>           <none>


# 熟练用describe去看资源状态
[root@k8s-master-10 ~]#kubectl -n yuchaoit describe pod wordpress-deploy-c4df856c7-

踩坑记录,客户端主机,不支持nfs插件

       In some cases useful info is found in syslog - try
       dmesg | tail or so.
  Warning  FailedMount  88s (x4 over 7m34s)  kubelet  (combined from similar events): MountVolume.SetUp failed for volume "nfs-data" : mount failed: exit status 32
Mounting command: systemd-run
Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/ae9fd074-e367-4b0b-a84a-8a2132e265ff/volumes/kubernetes.io~nfs/nfs-data --scope -- mount -t nfs 10.0.0.11:/nfs-volume/blog/ /var/lib/kubelet/pods/ae9fd074-e367-4b0b-a84a-8a2132e265ff/volumes/kubernetes.io~nfs/nfs-data
Output: Running scope as unit run-116975.scope.
mount: wrong fs type, bad option, bad superblock on 10.0.0.11:/nfs-volume/blog/,
       missing codepage or helper program, or other error
       (for several filesystems (e.g. nfs, cifs) you might
       need a /sbin/mount.<type> helper program)

       In some cases useful info is found in syslog - try
       dmesg | tail or so.
  Warning  FailedMount  49s (x4 over 7m39s)  kubelet  Unable to attach or mount volumes: unmounted volumes=[nfs-data], unattached volumes=[default-token-nkzpq nfs-data]: timed out waiting for the condition
[root@k8s-master-10 ~]#

# 给客户端机器,安装nfs套件即可。
[root@k8s-node-12 ~]#yum install nfs-utils -y

# 重建pod查看结果
[root@k8s-master-10 ~]#kubectl -n yuchaoit delete po -l app=wordpress

# 提示:可以去看目标机器的init容器运行结果


# 等待片刻后,通信没问题了
[root@k8s-master-10 ~]#kubectl -n yuchaoit get po -owide -l app=wordpress 
NAME                               READY   STATUS    RESTARTS   AGE     IP          NODE          NOMINATED NODE   READINESS GATES
wordpress-deploy-c4df856c7-qjs68   1/1     Running   0          6m51s   10.2.1.52   k8s-node-11   <none>           <none>
wordpress-deploy-c4df856c7-x8gm9   1/1     Running   0          6m51s   10.2.2.66   k8s-node-12   <none>           <none>

4.wordpress-svc.yml

apiVersion: v1
kind: Service
metadata:
  name: wordpress        # Service的名称,服务发现名称
  namespace: yuchaoit
spec:
  selector:          # Label Selector,选择包含app=nginx标签的Pod
    app: wordpress
  ports:
  - name: wordpress-port
    targetPort: wordpressport   # 直接基于wordpress-pod暴露的端口名即可对应
    port: 80         # Service对外暴露的端口,也就是ClusterIP的port
    protocol: TCP    # 转发协议类型,支持TCP和UDP

查看svc

[root@k8s-master-10 ~]#kubectl -n yuchaoit get svc wordpress -owide 
NAME        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE   SELECTOR
wordpress   ClusterIP   10.1.49.131   <none>        80/TCP    60s   app=wordpress

5.wordpress-ingress.yml

支持集群内配置就完毕了,提供一个外部访问入口吧。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wordpress
  namespace: yuchaoit
spec:
  rules:                                 # 转发规则
  - host: "wordpress.yuchaoit.cn"            # 填入你们的业务域名
    http:                                # 基于http协议解析
      paths:                            # 基于url路径匹配
      - pathType: Prefix                 #要设置路径类型,否则不合法,
        path: "/"                     # 以 / 分割的URL路径前缀匹配,区分大小写,这里表默认所有路径。
        backend:                      # 后端Service信息的组合
          service:                    
            name: wordpress    # 代理到名字是service1的ClusterIP
            port:                    # 代理到的Service的端口号。
              number: 80

查看结果

[root@k8s-master-10 ~]#kubectl -n yuchaoit get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME           CLASS    HOSTS                   ADDRESS   PORTS   AGE
test-ingress   <none>   www.yuchaoit.cn                   80      32h
wordpress      <none>   wordpress.yuchaoit.cn             80      4s

# 可以去ingress控制器里看nginx规则

6.访问试试!!

hosts解析来一波
10.0.0.10      www.yuchaoit.cn wordpress.yuchaoit.cn


[root@k8s-master-10 ~]#kubectl --namespace=nginx-ingress  logs -f  nginx-ingress-75c88594dc-klfqc

 

3.PV(PersistentVolume) 持久化存储卷

前面介绍的是针对pod资源设置Volume的三种玩法

EmptyDir,非持久化
hostPath,属于持久化,但只限在具体Node,只适合读的场景。
nfs,属于持久化。

如果要求pod在重新被调度后,依然能保留,使用之前读写后的数据,就必须用网络存储;

网络存储有很多主流的方案,块存储、文件存储、对象存储等。

开源技术
cephFS 
GlusterFS
NFS

生产环境下的公有云厂商提供的
-对象存储
-云硬盘
-弹性文件系统

k8s为了解适配诸多的存储技术,抽象了PV、PVC两个资源,让运维不用关心具体的存储基础设施来源,只需要关心使用存储资源,声明好自己要用多少资源即可。

图解生产下的k8s存储架构

 

PV是什么

PersistentVolume

PV描述的是持久化存储卷,主要定义的是一个持久化存储在宿主机上的目录,比如一个NFS的挂载目录。

PVC是什么

PersistentVolumeClaim

PVC描述的是Pod所希望使用的持久化存储的属性,比如,Volume存储的大小、可读写权限等等。

PVC绑定PV

 

1. pv是对底层网络共享存储的抽象,将共享存储定义为一种"资源"
2. PV由管理员先创建和配置
3. PVC则是用户对存储资源的一种 `申请`
4.对比理解的话
Pod的运行会消耗Node的资源、PVC会消耗PV的资源。
5.PVC的申请,有特定的存储空间,以及访问方式。

PV、PVC关系、与使用流程

 

nfs与mysql数据共享持久化

1.准备NFS

yum install nfs-utils -y
mkdir /nfs-volume/mysql/ -p
cat > /etc/exports <<'EOF'
/nfs-volume/mysql/ 10.0.0.0/24(rw,async,no_root_squash,no_all_squash)
EOF


systemctl restart nfs rpcbind 
systemctl enable nfs rpcbind

showmount -e 127.0.0.1

2.node安装nfs套件

yum install nfs-utils -y

showmount -e 10.0.0.10

3.管理员准备NFS-PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv # pv资源名
  # namespace: yuchaoit 
spec:
  capacity: 
    storage: 10Gi  # 存储10Gi资源
  accessModes:
  - ReadWriteMany  # 多个节点可以读写PV
  persistentVolumeReclaimPolicy: Retain # PV回收策略,保留数据,需要管理员手工删除
  nfs:  # 对接存储类型
    path: /nfs-volume/mysql/
    server: 10.0.0.10

创建pv

[root@k8s-master-10 /all-k8s-yml]#kubectl create -f mysql-nfs-pv.yml 
persistentvolume/nfs-pv created


[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get pv -owide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
nfs-pv   10Gi       RWX            Retain           Available                                   9s    Filesystem


一个 PV 的生命周期中,可能会处于4中不同的阶段:

Available(可用):表示可用状态,还未被任何 PVC 绑定
Bound(已绑定):表示 PV 已经被 PVC 绑定
Released(已释放):PVC 被删除,但是资源还未被集群重新声明
Failed(失败): 表示该 PV 的自动回收失败

pv资源字段解释

capacity,存储能力, 目前只支持存储空间的设置, 就是我们这里的 storage=1Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。

accessModes,访问模式, 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
ReadWriteMany(RWX):读写权限,可以被多个节点挂载

persistentVolumeReclaimPolicy,pv的回收策略, 目前只有 NFS 和 HostPath 两种类型支持回收策略
Retain(保留)- 保留数据,需要管理员手工清理数据
Recycle(回收)- 清除 PV 中的数据,效果相当于执行 rm -rf /volume_yuchaoit.cn/*
Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 ASW EBS。
目前只有NFS、HostPath两个类型的PV支持Recycle,直接删除。

PV不属于集群资源

因为PV是直接对接底层存储的,就像集群中的Node可以为Pod提供计算资源(CPU和内存)一样,PV可以为Pod提供存储资源。

因此PV不是namespaced的资源,属于集群层面可用的资源。

Pod如果想使用该PV,需要通过创建PVC挂载到Pod中。

当PV进入Released状态备注

若PVC被删除,PV会进入Released状态,PVC也无法重新绑定,PVC只能和Availabel状态的PV绑定。

生产做法是
1. 备份PV数据,迁移走
2.  修改PV状态,删除对PVC的引用记录,此时k8s的PV控制器watch到PV变化,更新PV状态,恢复Availabel状态。

 

claimRef该字段记录PV、PVC的双向绑定记录

[root@k8s-master-10 /all-k8s-yml]#kubectl edit pv nfs-pv 
persistentvolume/nfs-pv edited


[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get pv -owide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
nfs-pv   10Gi       RWX            Retain           Available                                   24m   Filesystem
[root@k8s-master-10 /all-k8s-yml]#

4.用户创建mysql-pvc

PVC全写是PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,创建完成后,可以和PV实现一对一绑定。

对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: yuchaoit # pvc属于ns下的资源
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi # 声明PVC用多少存储
  volumeName: nfs-pv # PVC绑定PV 
  # 也可以不填,
  #PersistentVolumeController会不断地循环去查看每一个 PVC,是不是已经处于 Bound(已绑定)状态。
  # 如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与未绑定的 PVC 进行绑定
  # 这样,Kubernetes 就可以保证用户提交的每一个 PVC,只要有合适的 PV 出现,它就能够很快进入绑定状态。
  # 而所谓将一个 PV 与 PVC 进行“绑定”,其实就是将这个 PV 对象的名字,填在了 PVC 对象的 spec.volumeName 字段上。

创建pvc,绑定PV

[root@k8s-master-10 /all-k8s-yml]#kubectl create -f mysql-nfs-pvc.yml 
persistentvolumeclaim/nfs-pvc created



[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get pvc -owide
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
nfs-pvc   Bound    nfs-pv   10Gi       RWX                           7m43s   Filesystem


[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get pv -owide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE   VOLUMEMODE
nfs-pv   10Gi       RWX            Retain           Bound    yuchaoit/nfs-pvc                           25m   Filesystem

5.storageClass实现动态挂载

上面于超老师讲的PV、PVC、创建pv及pvc过程是手动,且pv与pvc一一对应,手动创建很繁琐。

k8s提供了一个更简单的方法,能动态自动创建PV。

通过storageClass + provisioner的方式来实现通过PVC自动创建并绑定PV。

这里作为高阶存储玩法,以后再补充。

6.创建mysql-deployment控制器

apiVersion: apps/v1      # 注意这里与Pod的区别,Deployment是apps/v1而不是v1
kind: Deployment         # 资源类型为Deployment
metadata:
  name: mysql-deploy            # Deployment的名称
  namespace: yuchaoit
  labels:
    app: mysql
spec:
  selector:       # RS控制器基于label匹配pod,确保副本数
    matchLabels:
      app: mysql

  template:              # Pod的定义,用于创建Pod,也称为Pod template
    metadata:
      labels:           # pod打上标签
        app: mysql  # 必须和selector一样

    spec:
      volumes: # 给pod内定义2个卷
        - name: mysql-pvc
          persistentVolumeClaim: # pod引用PVC
            claimName: mysql-pvc
        - name: mysql-log 
          hostPath:
            path: /var/log/mysql

      nodeSelector: # pod部署节点选择器
        diskType: SSD

      containers:
      - image: mysql:5.7
        name: mysql
        imagePullPolicy: IfNotPresent

        ports:            
          - name: dbport   
            containerPort: 3306 # 指明容器内要暴露的端口
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "www.yuchaoit.cn"

        volumeMounts:
          - name: mysql-pvc # 容器内挂载pvc
            mountPath: /var/lib/mysql # 挂载点
          - name: mysql-log 
            mountPath: /var/log/mysql

运行

[root@k8s-master-10 /all-k8s-yml]#kubectl create -f mysql-deploy.yml 

起不来?看看问题
[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit describe   pod mysql-deploy-98b786585-p9b9g 

加上label
[root@k8s-master-10 /all-k8s-yml]#kubectl label nodes k8s-node-12 diskType=SSD
error: 'diskType' already has a value (ssd), and --overwrite is false
[root@k8s-master-10 /all-k8s-yml]#kubectl label nodes k8s-node-12 diskType=SSD --overwrite 
node/k8s-node-12 labeled

查看结果
[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get po -owide 
NAME                           READY   STATUS    RESTARTS   AGE     IP          NODE          NOMINATED NODE   READINESS GATES
mysql-deploy-98b786585-p9b9g   1/1     Running   0          2m12s   10.2.2.74   k8s-node-12   <none>           <none>

7.结果测试

按如下流程测试即可
1.查看PV里的数据
[root@k8s-master-10 /nfs-volume/mysql]#ls
auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem


2.加一个数据试试
mysql> create database yuchao_k8s;
Query OK, 1 row affected (0.01 sec)


3.删除pod,查看数据能回来吗?(deployment保障了pod的副本数)

 

标签:持久,name,nfs,mysql,yuchaoit,pod,k8s,数据
From: https://www.cnblogs.com/sxy-blog/p/17899179.html

相关文章

  • k8s配置文件管理
    1.为什么要用configMapConfigMap是一种用于存储应用所需配置信息的资源类型,用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。通过ConfigMap可以方便的做到配置解耦,使得不同环境有不同的配置。考虑真实的使用场景,像数据库这类中间件,是作为公共资源,为多个......
  • 搭建grafana,接入prometheus展示数据
    搭建grafana,接入prometheus展示数据一、搭建grafana1、下载grafana二进制包wgethttps://dl.grafana.com/enterprise/release/grafana-enterprise-10.2.0.linux-amd64.tar.gz 2、解压到/opt目录,配置软连接tarzxfgrafana-enterprise-10.2.0.linux-amd64.tar.gz......
  • NineData慢查询分析功能:为DBA提供全面的数据库性能解决方案
    对于一个DBA来说,从公司数据库系统的稳定程度可以看出他的能力几何,一个优秀的DBA不仅要保证数据库的稳定运行,还需要有能力有效处理数据库的各种突发性能问题,而最常见的性能问题,就是慢查询。我们公司规模比较大,大大小小的项目加起来超过100个数据库实例,而保证这些数据库的稳......
  • 数据资产入表,从数据产权三权分置说起
    数据资产在会计上入表的前提,必须是企业的数据才能入表。数据的确权需要通过数据产权结构性分置来确定,明确具体什么人对什么数据拥有什么权利。其实数据产权的结构分制不是什么新话题,实际上是有土地产权分制,当时提出土地的产权分制就是想激活土地的这个价值,同样数据产权的结构分制也......
  • k8s资源清单
    k8s资源清单再安装好k8s之后,本章开始学习k8s的具体使用玩法。重点介绍如何使用Workload管理业务应用的生命周期,实现服务不中断的滚动更新,通过服务发现和集群内负载均衡来实现集群内部的服务间访问,并通过ingress实现外部使用域名访问集群内部的服务。学习过程中会逐步对Djang......
  • 数据类型一些相关问题
    如何取出整型的每一位我们可以定义四个uint8_t的变量,然后将int类型变量每8位每8位的取出1intmain()2{3OLED_Init();4intnum=261;5uint8_tnum1;6uint8_tnum2;7uint8_tnum3;8uint8_tnum4;9num1=(0xff000000&num)>>2......
  • 兼容性复制功能/自定义mock数据/通用hook
    *****自定义mockconstresourceList=computed(()=>Array.from({length:20},(_,index)=>index).map((v,i)=>{return{id:i,joinList:Array.from({length:i},(_,index1)=>index1).map((v,......
  • k8s介绍
    k8s容器编排系统k8S是谷歌几十年来研发的一套系统,更新了运维领域的玩法。内容很多,先快速练习玩法,知道是什么就行。具体【为什么】再花时间慢慢学吧!0.参考资料1.k8s能干什么https://kubernetes.io/zh-cn/docs/concepts/overview/#why-you-need-kubernetes-and-what-can-i......
  • dremio 的虚拟数据集市
    实际上术语来自dremio的一篇博客,实际上官方也提供了如何创建自服务语义层的实践博客中玩法的简单说明官方的说明是参考如下流程创建业务单元 基于文件夹的玩法数据源鸡好吃呢个以及视图创建 实际上就是基于数据源进行vds的处理访问控制以及权限处理用户数据管理以及data......
  • 教你使用Prometheus-Operator进行K8s集群监控
    本文分享自华为云社区《Promethues-operator入门使用指导》,作者:可以交个朋友。一、背景在非operator配置的普罗中我们监控k8s集群都是通过配置configmap进行服务发现和指标拉取。切换到prometheus-operator难免会有些使用问题。不少用户已经习惯底层配置自动发现的方式。当过渡......