zoukankan      html  css  js  c++  java
  • k8s存储数据卷

    k8s存储

    • 在容器中的磁盘文件是短暂的,当容器挂掉时候,k8s会将它重启,而重启后容器文件会丢失,并且有的pod会有多容器进行文件交互。为了解决这个问题,k8s引入数据卷概念。
    • k8s中Volume提供在容器中挂在外部存储的能力。
    • Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume
    • 常用数据卷:
    本地:hostPath, emptyDir
    网络:NFS, Ceph, GlusterFS
    公有云:AWS EBS
    k8s资源: configmap, secret
    

    1.存储数据卷

    1.1emptyDir

    • 是一个临时存储卷。与pod生命周期绑定一起,如果pod删除卷也会被删除

    • 主要应用:pod中容器之间数据共享(比如一个容器负责写,一个容器负责读的场景)。

    • 示例:

      # 在pod 中启动2个容器一个读一个写
      apiVersion: v1
      kind: Pod
      metadata:
        name: volume1
      spec:
        containers:
        - name: write
          image: centos
          command: ["bash", "-c", "for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
          volumeMounts:
            - name: data
              mountPath: /data
        - name: read
          image: centos
          command: ["bash", "-c", "tail -f /data/hello"]
          volumeMounts:
            - name: data
              mountPath: /data
        volumes:
        - name: data
          emptyDir: {}
      # 如有启动异常可执行
      [root@k8s-master ~]# kubectl logs <pod name> -c <容器name>
      # 通过exec在容器执行shell命令,查看写的执行状态
      kubectl exec volume1 -c write -- tail /data/hello
      # 通过如下命令可以查看刚才部署的pod跑在哪个节点上
      kubectl get pods -o wide
      # 到相应节点过滤查看容器
      docker ps | grep volume1
      #刚才设置数据共享目录在宿主机
      /var/lib/kubelet/pods/<NAME 的ID>/volumes/kubernetes.io~empty-dir/data/hello 
      

    1.2Hostpath

    • 挂载node文件系统(pod所在节点)上文件或者目录到pod中的容器。

    • 应用场景:pod中容器需要访问宿主机文件(比如应用程序读取宿主机的物理资源,日志)

    • 示例:

      apiVersion: v1
      kind: Pod
      metadata:
        name: pod-hostpath
      spec:
        containers:
        - name: busybox
          image: busybox
          args:
          - /bin/sh
          - -c
          - sleep: 36000
          volumeMounts:
          - name: data
            mountPath: /data# 挂载容器中/data下
        volumes:
        - name: data
          hostPath:
            path: /tmp# 挂载宿主机的/tmp下
            type: Directory
      
      # 进入容器往容器/data下新增文件
      kubectl exec -it pod-hostpath -- sh
      touch hahat.txt
      # 查看pod运行的节点
      kubectl get pods -o wide
      # 在node01节点上查看/tmp目录下,可以查看新创建的haha.txt
      

    1.3NFS

    • 网络存储卷,NFS提供对NFS挂载支持,可以自动将NFS共享路径挂载到Pod中。

    • 准备一台服务器安装NFS,注意:每个Node上都要安装nfs-utils:需要让节点pod挂载共享目录,需要linux支持nfs内部协议的模块

      yum install -y nfs-utils
      
      vi /etc/exports
      	/ifs/kubernetes *(rw,no_root_squash)
      	# /ifs/kubernetes 指定暴漏目录
      	# * 表示暴漏的网段为所有,也可以设置
      	# rw,no_root_squash 表示权限
      # 创建文件夹
      	mkdir -p /ifs/kubernetes
      # 启动
      	
      	systemctl start nfs
      	systemctl enable nfs
      # 测试nfs是否能用,另一台机器
      mount -t nfs 172.16.215.141:/ifs/kubernetes /mnt
      cd /mnt
      
      
      mount -t nfs 172.16.215.141:/ifs/kubernetes /mnt
      cd /mnt
      touch 111.txt
      # 查看nfs服务器/ifs/kubernetes下是否存在111.txt
      
      # 卸载nfs命令: mount /mnt/
      

    1.4 ConfigMap

    • 创建ConfigMap后,数据实际会存储在k8s中etcd,然后通过创建pod时引用该数据。

    • 应用场景:应用程序配置文件

    • pod使用configmap数据有两种方式:

      1.变量注入
      2.数据卷挂载
      
    • 示例:

      [root@k8s-master ~]# vi configmap.yaml
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: configmap-demo
      data:# 定义键值方式变量
        a: "123"
        b: "456"
        # 定义多行变量
        redis.properties: | 
          port: 6379
          host: 192.168.31.10
      # 将configmap保存到k8中etcd中
      [root@k8s-master ~]# kubectl apply -f configmap
      
      [root@k8s-master ~]# kubectl get configmap
      NAME               DATA   AGE
      configmap-demo     3      7s
      
      
      # 定义一个pod
      
      apiVersion: v1
      kind: Pod
      metadata: 
        name: configmap-demo-map
      spec:
        containers:
          - name: demo
            image: nginx
            # 变量注入
            env:
              - name: ZZZ# 自定义变量
                value: "zzz"
              - name: ABCD# 变量名字
                valueFrom:
                  configMapKeyRef:
                    name: configmap-demo# 来自于configmap
                    key: a
              - name: CDEF
                valueFrom: 
                  configMapKeyRef:
                    name: configmap-demo
                    key: b
            # 数据卷挂载
            volumeMounts:
            - name: config
              mountPath: "/config"# 存放容器中/config目录下
              readOnly: true
        volumes:
          - name: config
            configMap:
              name: configmap-demo
              items:
              - key: "redis.properties"# key与对应configmap.yaml对应
                path: "redis.properties"# 保存在容器中路径
      # 执行pod
      [root@k8s-master ~]# kubectl apply -f pod-configmap.yaml
      # 进入容器
      [root@k8s-master ~]# kubectl exec -it configmap-demo-map -- bash
      
      # 验证数据卷挂载
      root@configmap-demo-map:/# cat config/redis.properties
      port: 6379
      host: 192.168.31.10
      
      # 验证变量注入
      root@configmap-demo-map:/# echo $CDEF
      456
      

    1.5 Secret

    • 与ConfigMap类似,区别于Secret主要存储敏感数据,所有数据要经过base64编码。
    • 应用场景:凭据
    • kubectl create secret 支持三种数据类型
    docker-registry: 存储镜像仓库认证信息
    generic:从文件,目录或者字符串创建,例如存储用户名,密码
    tls:存储证书,例如HTTPS证书
    
    • 示例
    [root@k8s-master ~]# echo -n 'admin' | base64
    [root@k8s-master ~]# echo -n '1f2d1e2e67df' | base64
    [root@k8s-master ~]# vi secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-user-pass
    type: Opaque
    data:
      username: YWRtaW4=
      password: MWYyZDFlMmU2N2Rm
    
    # 应用
    [root@k8s-master ~]# kubectl apply -f secret.yaml 
    # 查看secret
    [root@k8s-master ~]# kubectl get secret
    NAME                                 TYPE                                  DATA   AGE
    db-user-pass                         Opaque                                2      12s
    # 创建一个pod
    [root@k8s-master ~]# vi pod-secret.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: secret-demo-pod
    spec:
      containers:
        - name: demo
          image: nginx
          # 变量注入
          env:
            - name: USER
              valueFrom:
                secretKeyRef:
                  name: db-user-pass
                  key: username
            - name: PASS
              valueFrom:
                secretKeyRef:
                  name: db-user-pass
                  key: password
          # 数据卷方式
          volumeMounts:
          - name: config
            mountPath: "/config"
            readOnly: true
      volumes:
        - name: config
          secret:
            secretName: db-user-pass
            items:
            - key: username
              path: my-username
    # 应用:
    [root@k8s-master ~]# kubectl apply -f pod-secret.yaml 
    # 进入pod中
    [root@k8s-master ~]# kubectl exec -it secret-demo-pod -- bash
    # 变量注入方式验证
    root@secret-demo-pod:/# echo $USER
    admin
    root@secret-demo-pod:/# echo $PASS
    1f2d1e2e67df
    # 数据卷方式验证
    root@secret-demo-pod:/# cat /config/my-username
    admin
    

    2.pv和pvc管理存储

    • PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理。

    • PersistentVolumeClaim(PVC): 让用户不需要关系具体的Volume实现细节。

    • 示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: deply-pvc
      name: deploy-pvc
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: deploy-pvc
      strategy: {}
      template:
        metadata:
          labels:
            app: deploy-pvc
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
            volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
          volumes:
          - name: data
            persistentVolumeClaim:# 卷资源pvc
              claimName: my-pvc# 申请空间pvc名字
    ---
    # pvc分配的存储资源
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
    # 此时创建pod处于Pending状态 查看pod详情
    kubectl describe pod deploy-pvc-6994b7ff4b-k8wgb
    # Events报错:
    Warning  FailedScheduling  7m27s  default-scheduler  0/2 nodes are available: 2 pod has unbound immediate PersistentVolumeClaims.
    # 表示PVC没有绑定PV,需要创建一个PV
    # 创建的PV,指定存储的资源
    vi pv.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv00001
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /ifs/kubernetes
        server: 172.16.215.141
    # 应用:挂载存储
    kubectl apply -f pv.yaml
    # 此时刚才创建的pvc开始创建,运行。如何查看pv与pvc绑定
    kubectl get pv,pvc
    
    NAME                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
    persistentvolume/pv00001   1Gi        RWX            Retain           Bound    default/my-pvc                           96s
    
    NAME                           STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    persistentvolumeclaim/my-pvc   Bound    pv00001   1Gi        RWX                           15m
    
    # 可以看到pv与pvc已经进行绑定
    
    • 当创建多个pv为保证多个pv之间数据隔离,会在nfs上创建多个目录
    /ifs/
    └── kubernetes
        ├── pv00001
        ├── pv00002
        └── pv00003
    
    • 此时pv.yaml应该如下定义多个yaml块
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv00001
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /ifs/kubernetes/pv00001
        server: 172.16.215.141
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv00002
    spec:
      capacity:
        storage: 2Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /ifs/kubernetes/pv00002
        server: 172.16.215.141
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv00003
    spec:
      capacity:
        storage: 3Gi
      accessModes:
        - ReadWriteMany
      nfs:
        path: /ifs/kubernetes/pv00003
        server: 172.16.215.141
    
    • 当又创建一个应用。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: deply-pvc
      name: deploy-pvc2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: deploy-pvc
      strategy: {}
      template:
        metadata:
          labels:
            app: deploy-pvc
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
            volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
          volumes:
          - name: data
            persistentVolumeClaim:
              claimName: my-pvc2
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc2
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1.5Gi
    
    • 此时通过kubectl get pvc
    [root@k8s-master ~]# kubectl get pvc
    NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    my-pvc    Bound    pv00001   1Gi        RWX                           32m
    my-pvc2   Bound    pv00002   2Gi        RWX                           2m12s
    # 可以看到创建第一个和第二个应用分别绑定了pv00001和pv00002
    
    • PV生命周期
    accessModes:访问模式
    	AccessModes是用来对PV进行访问模式的设置,用于描述用户应用对存储资源访问权限,访问权限包括下面几种。
    		ReadWriteOnce(RWO): 读写权限,但是只能被单个节点挂载
    		ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载
    		ReadWriteMany(RWX): 读写权限,可以被多个节点挂载
    RECLAIM POLICY(回收策略)
    	通过 kubectl get pv 命令,查看RECLAIM POLICY列,目前有3种策略
    		Retain(保留):保留数据,需要管理员手工清理数据
    		Recycle(回收):清除PV中的数据,效果相当于rm -rf
    		Delete(删除): 与PV相连后端存储同时删除
    STATUS 状态
    	表示一个PV生命周期状态。
    		Available(可用): 表示可用状态,还未被任何PVC绑定
    		Bound(已绑定): 表示PV已经被PVC绑定
    		Released(已释放): PVC被删除,但是资源还未被集群重新声明
    		Failed(失败): 表示该PV的自动回收失败
    
    • PV与PVC常见问题
    1.PV与PVC之间关系?
    	一个PV对应一个PVC
    2.PV与PVC怎么匹配?
    	根据存储空间,访问模式进行匹配
    3.容器匹配策略是什么样的?
    	匹配最接近的PV容量,如果满足不了Pod会处于pending状态
    4. 存储空间(1Gi,2Gi,...)字段限制使用容量?
    	这个字段主要用于做匹配,实际的使用限制取决于后端存储。
    
    • 现在我们在使用PV为静态供给,需要k8s工程师创建一大堆PV供开发者使用。PV静态供给维护成本过高,通过StorageClass动态进行PV供给可减少维护成本。

    3.PV动态供给(StorageClass)

    • 基于NFS实现PV动态供给流程图

    • NFS外部资源调配

    • GitHub复制文件class.yaml,deployment.yaml,rbac.yamlyaml文件下载地址

      • class.yaml 用于存储类
      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
        name: managed-nfs-storage
      provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
      parameters:
        archiveOnDelete: "false"
      
      • deployment.yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nfs-client-provisioner
        labels:
          app: nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
      spec:
        replicas: 1
        strategy:
          type: Recreate
        selector:
          matchLabels:
            app: nfs-client-provisioner
        template:
          metadata:
            labels:
              app: nfs-client-provisioner
          spec:
            serviceAccountName: nfs-client-provisioner
            containers:
              - name: nfs-client-provisioner
                image: lizhenliang/nfs-subdir-external-provisioner:v4.0.1
                volumeMounts:
                  - name: nfs-client-root
                    mountPath: /persistentvolumes
                env:
                  - name: PROVISIONER_NAME
                    value: k8s-sigs.io/nfs-subdir-external-provisioner
                  - name: NFS_SERVER
                    value: 172.16.215.141# NFS服务器IP
                  - name: NFS_PATH
                    value: /ifs/kubernetes# 共享目录
            volumes:
              - name: nfs-client-root
                nfs:
                  server: 172.16.215.141# NFS服务器IP
                  path: /ifs/kubernetes# 挂载容器的目录
      
      • rbac.yaml为了连接k8s的api进行授权
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
      ---
      kind: ClusterRole
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: nfs-client-provisioner-runner
      rules:
        - apiGroups: [""]
          resources: ["nodes"]
          verbs: ["get", "list", "watch"]
        - apiGroups: [""]
          resources: ["persistentvolumes"]
          verbs: ["get", "list", "watch", "create", "delete"]
        - apiGroups: [""]
          resources: ["persistentvolumeclaims"]
          verbs: ["get", "list", "watch", "update"]
        - apiGroups: ["storage.k8s.io"]
          resources: ["storageclasses"]
          verbs: ["get", "list", "watch"]
        - apiGroups: [""]
          resources: ["events"]
          verbs: ["create", "update", "patch"]
      ---
      kind: ClusterRoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: run-nfs-client-provisioner
      subjects:
        - kind: ServiceAccount
          name: nfs-client-provisioner
          # replace with namespace where provisioner is deployed
          namespace: default
      roleRef:
        kind: ClusterRole
        name: nfs-client-provisioner-runner
        apiGroup: rbac.authorization.k8s.io
      ---
      kind: Role
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: leader-locking-nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
      rules:
        - apiGroups: [""]
          resources: ["endpoints"]
          verbs: ["get", "list", "watch", "create", "update", "patch"]
      ---
      kind: RoleBinding
      apiVersion: rbac.authorization.k8s.io/v1
      metadata:
        name: leader-locking-nfs-client-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
      subjects:
        - kind: ServiceAccount
          name: nfs-client-provisioner
          # replace with namespace where provisioner is deployed
          namespace: default
      roleRef:
        kind: Role
        name: leader-locking-nfs-client-provisioner
        apiGroup: rbac.authorization.k8s.io
      
    • 目录结构

      nfs-external-rpovisioner/
      ├── class.yaml
      ├── deployment.yaml
      └── rbac.yaml
      
    • 应用

      kubectl apply -f .
      
    • 查看存储类

      [root@k8s-master nfs-external-rpovisioner]# kubectl get sc
      NAME                  PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
      managed-nfs-storage   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  10s
      
    • 查看pod

      [root@k8s-master nfs-external-rpovisioner]# kubectl get pods
      NAME                                      READY   STATUS              RESTARTS   AGE
      nfs-client-provisioner-6f5bf84fc9-srrf8   0/1     Running   0          50s
      
    • 创建一个deployment看是否能动态供给

      # storageClassName 设置存储类名字,通过 kubectl get sc 获取存储类的名字。
      vi deploy-storageclass.yaml 
      
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: deply-pvc
        name: deploy-storageclass
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: deploy-pvc
        strategy: {}
        template:
          metadata:
            labels:
              app: deploy-pvc
          spec:
            containers:
            - image: nginx
              name: nginx
              resources: {}
              volumeMounts:
              - name: data
                mountPath: /usr/share/nginx/html
            volumes:
            - name: data
              persistentVolumeClaim:
                claimName: my-sc
      ---
      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: my-sc
      spec:
        storageClassName: "managed-nfs-storage"
        accessModes:
          - ReadWriteMany
        resources:
          requests:
            storage: 1.5Gi
      
    • 创建pod

      [root@k8s-master ~]# kubectl apply -f deploy-storageclass.yaml 
      
      
    • 在NFS服务器172.16.215.141可以看到/ifs/kubernetes目录下有default-my-sc-pvc-d94fb9a6-d6ed-4511-9077-18487bfd1985可以知道自动创建一个目录,这个目录就是PV动态供给创建目录

    • 我们进入一个容器内

      kubectl exec -it deploy-storageclass-7584589f8c-ltqg4 bash
      
      cd /usr/share/nginx/html/
      # 创建一个文件
      touch 1.txt
      # 此时查看NFS服务器上的default-my-sc-pvc-d94fb9a6-d6ed-4511-9077-18487bfd1985目录下也多了一个文件1.txt
      
    • 动态供给分配的存储资源,是看你pod要求分配的是多少存储资源。

    • 需要知道是动态存储的类不是一对一关系,可以重复使用,它就好像提供一个接口一样,重复调用。

    4.有状态应用部署:StatefulSet控制器

    • Deployment控制器设计原则:管理所有pod一模一样,提供同一个服务,不需要考虑多副本之间的关系是否有独立存储,也不考虑在哪台Node运行,可随意扩容和缩容,这种应用称为‘无状态’,例如web服务。

    • 在实际场景中,这并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往往有依赖关系,例如:主从关系,主备关系,这种应用称为‘有状态’,例如MySQL主从,Etcd集群。

    • StatefulSet

      • 用于部署有状态应用

      • 解决pod独立生命周期,保持pod启动顺序和唯一性。

        1.稳定,唯一网络标识符,持久存储
        2.有序, 优雅的部署和扩展,删除和终止。
        3.有序,滚动更新
        
      • 应用场景:分布式应用,数据库集群

    • 稳定的网络ID

      • 使用Headless Service (相比普通Service只是将spec.clusterIP定义为None)来维护Pod网络身份。并且添加ServiceName字段指定StatefulSet控制器要使用这个Headless Service。DNS解析名称:. , .svc.cluster.local
    • 稳定的存储

      • StatefulSet存储卷使用VolumeClaimTemplate创建,称为卷申请模版,当StatefulSet使用VolumeClaimTemplate创建一个PV(PersistentVolume)时,同样也会为每个pod分配并创建一个编号的PVC
    • 如部署一个MySQL主从:

      • 主从实例启动顺序
      • 主从实例数据目录唯一
      • 从连接主实例需要指定IP或主机名
    • 这里拿nginx做实例,部署statefulSet

    # 新增一个statefulSet的基本模版yaml文件
    [root@k8s-master ~]# kubectl create deployment sts --image=nginx --dry-run=client -o yaml > sts.yaml
    
    # 暴漏一个service
    [root@k8s-master ~]# kubectl expose deployment deploy-pvc --port=80 --target-port=80 --dry-run=client -o yaml > svc.yaml
    
    # 编写demployment的service为StatefulSet
    
    
    
    
    
    
    # vi sts.yaml
    apiVersion: apps/v1
    kind: StatefulSet#设置StatefulSet控制器
    metadata:
      labels:
        app: sts
      name: sts
    spec:
      serviceName: "sts"# 指定serviceName,用户指定Headless Service
      replicas: 2
      selector:
        matchLabels:
          app: sts
      template:
        metadata:
          labels:
            app: sts
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
            volumeMounts:# 定义挂载目录
            - name: www
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:# volumeClaimTemplates 为每个pod分配独立pv。只支持StatefulSet
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]#单pod读写模式,一个pvc只能被一个pod独享,
          storageClassName: "managed-nfs-storage"# 存储类,为上面提前设置好的。
          resources:
            requests:
              storage: 1Gi
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: sts
      name: sts
    spec:
      clusterIP: None# Headless Service是将clusterIP置为None,因为是一个有状态的service。
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app: sts
    
    
    # 应用
    kubectl apply -f sts.yaml
    
    # kubectl get pods 可以看到,pod进行有序的启动(部署)
    sts-0                                    1/1     Running   0          10m
    sts-1                                    1/1     Running   0          9m53s
    
    # 为每个pod分配稳定身份
    [root@k8s-master ~]# kubectl get ep
    NAME                                          ENDPOINTS                                                        AGE
    sts                                           10.244.85.204:80,10.244.85.205:80                                25m
    
    
    [root@k8s-master ~]# kubectl get svc
    NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
    sts          ClusterIP   None           <none>        80/TCP         27m
    
    
    
    # 创建一个沙箱
    [root@k8s-master ~]# kubectl run -it --rm --image=busybox:1.28.4 -- sh
    # deploy-nfs 通过 CLUSTER-IP 进行解析
    / # nslookup deploy-nfs
    Server:    10.96.0.10
    Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
    # 而sts并没有 CLUSTER-IP 通过pod IP进行解析
    / # nslookup sts
    Server:    10.96.0.10
    Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      sts
    Address 1: 10.244.85.205 sts-0.sts.default.svc.cluster.local
    Address 2: 10.244.85.204 sts-1.sts.default.svc.cluster.local
    
    • 当我们对sts.yaml进行升级时候比如nginx版本升级更高版本
    # 重新apply
    kubectl apply -f sts.yaml
    # 升级的顺序是从后向前升级,也就是先sts-1再sts-0
    
    • StatefulSet和Deployment区别
    主要是身份区别:
    	域名
    	主机名
    	存储(PVC)
    
    • 总结
    1如果是不需额外数据依赖或者状态维护的部署,或者replicas是1,优先考虑使用Deployment;
    2如果单纯的要做数据持久化,防止pod宕掉重启数据丢失,那么使用pv/pvc就可以了;
    3如果要打通app之间的通信,而又不需要对外暴露,使用headlessService即可;
    4如果需要使用service的负载均衡,不要使用StatefulSet,尽量使用clusterIP类型,用serviceName做转发;
    5如果是有多replicas,且需要挂载多个pv且每个pv的数据是不同的,因为pod和pv之间是 一 一对应的,如果某个pod挂6掉再重启,还需要连接之前的pv,不能连到别的pv上,考虑使用StatefulSet
    6能不用StatefulSet,就不要用
    
  • 相关阅读:
    负margin实现div的左右排版
    一起来灭掉IE6!
    javac编译多个带package文件
    iis express感觉还不错
    关于sqlite使用entity framework的布署问题
    远程服务器返回了错误 NOTFOUND
    userAgent string detection in javascript
    a crossbroswer solution for parse xml fragment
    event related object in javascript
    several way to implement inheritance in javascript
  • 原文地址:https://www.cnblogs.com/xujunkai/p/14851666.html
Copyright © 2011-2022 走看看