栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

k8s 控制器-Statefulset

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

k8s 控制器-Statefulset

  • StatefulSet 是为了管理有状态服务的问题而设计
  • 扩展:有状态服务?
    StatefulSet 是有状态的集合,管理有状态的服务,它所管理的 Pod 的名称不能随意变化。数据持久化的目录也是不一样,每一个 Pod 都有自己独有的数据持久化存储目录。比如 MySQL 主从、redis集群等。
     
  • Deployment 管理 pod,pod 名字怎么组成?
    replicaset-随机数
    无状态服务?
    RS、Deployment、DaemonSet 都是管理无状态的服务,它们所管理的 Pod 的 IP、名字,启停顺序等都是随机的。个体对整体无影响,所有 pod 都是共用一个数据卷的,部署的 tomcat 就是无状态的服务,tomcat 被删除,在启动一个新的 tomcat,加入到集群即可,跟 tomcat 的名字无关。
     
  • StatefulSet 由以下几个部分组成:

    1. Headless Service(没有 ip 的 service):用来定义 pod 网路标识,生成可解析的 DNS 记录service ip 存在哪?iptables 或者 ipvs 规则中

    2. volumeClaimTemplates:存储卷申请模板,创建 pvc,指定 pvc 名称大小,自动创建 pvc,且 pvc 由存储类供应。

    3. StatefulSet:管理 pod 的
     
  • 扩展:什么是 Headless service?
    Headless service 不分配 clusterIP,headless service 可以通过解析 service 的 DNS,返回所有Pod 的 dns 和 ip 地址 (statefulSet 部署的 Pod 才有 DNS),普通的 service,只能通过解析 service 的DNS 返回 service 的 ClusterIP。
  • 为什么要用 headless service(没有 service ip 的 service)?
  • 在使用 Deployment 时,创建的 Pod 名称是没有顺序的,是随机字符串

    用 statefulset 管理pod 时要求 pod 名称必须是有序的 ,每一个 pod 不能被随意取代,pod 重建后 pod 名称还是一样

    因为 pod IP 是变化的,所以要用 Pod 名称来识别。pod 名称是 pod 唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个 Pod 一个唯一的名称。
  • 1.headless service 会为 service 分配一个域名 .$.svc.cluster.local

    K8s 中资源的全局 FQDN 格式:
     Service_NAME.NameSpace_NAME.Domain.LTD. Domain.LTD.=svc.cluster.local. #这是默认 k8s 集群的域名。

    FQDN 全称 Fully Qualified Domain Name 即全限定域名:同时带有主机名和域名的名称
    FQDN = Hostname + DomainName

    如 主机名是 GF
    域名是 beyond.com
    FQDN= GF.beyond.com


    2.StatefulSet 会为关联的 Pod 保持一个不变的 Pod Name
    statefulset 中 Pod 的名字格式为$(StatefulSet name)-$(pod 序号)


    3.StatefulSet 会为关联的 Pod 分配一个 dnsName
    $.$.$.svc.cluster.local

     
  • 为什么要用 volumeClaimTemplate?

    对于有状态应用都会用到持久化存储,比如 mysql 主从,由于主从数据库的数据是不能存放在一个目录下的,每个 mysql 节点都需要有自己独立的存储空间。

    而在 deployment 中创建的存储卷是一个共享的存储卷,多个 pod 使用同一个存储卷,它们数据是同步的,而 statefulset 定义中的每一个 pod 都不能使用同一个存储卷,这就需要使用 volumeClaimTemplate

    当在使用 statefulset 创建 pod 时,volumeClaimTemplate 会自动生成一个 PVC,从而请求绑定一个 PV,每一个 pod 都有自己专用的存储卷。

    Pod、PVC 和 PV 对应的关系图如下:


  •  Statefulset 资源清单文件编写技巧
  • #查看定义 Statefulset 资源需要的字段

  • [~]# kubectl explain statefulset
    KIND: StatefulSet
    VERSION: apps/v1
    DEscriptION:
     StatefulSet represents a set of pods with consistent identities. Identities
     are defined as:
     - Network: A single stable DNS and hostname.
     - Storage: As many VolumeClaims as requested. The StatefulSet guarantees
     that a given network identity will always map to the same storage identity.
    FIELDS:
     apiVersion #定义 statefulset 资源需要使用的 api 版本
     kind #定义的资源类型
     metadata #元数据
     spec #定义容器相关的信息

    #查看 statefulset.spec 字段如何定义?
    [~]# kubectl explain statefulset.spec
    KIND: StatefulSet
    VERSION: apps/v1
    RESOURCE: spec
    DEscriptION:
     Spec defines the desired identities of pods in this set.
     A StatefulSetSpec is the specification of a StatefulSet.
    FIELDS:
     podManagementPolicy #pod 管理策略
     replicas #副本数
     revisionHistoryLimit #保留的历史版本
     selector -required- #标签选择器,选择它所关联的 pod
     serviceName -required- #headless service 的名字
     template -required- #生成 pod 的模板
     updateStrategy #更新策略
     volumeClaimTemplates <[]Object> #存储卷申请模板


    #查看 statefulset 的 spec.template 字段如何定义?
    #对于 template 而言,其内部定义的就是 pod,pod 模板是一个独立的对象

    [~]# kubectl explain statefulset.spec.template
    KIND: StatefulSet
    VERSION: apps/v1
    RESOURCE: template
    DEscriptION:

    FIELDS:
     metadata
     spec #定义容器属性

    通过上面可以看到,statefulset 资源中有两个 spec 字段。

    第一个 spec 声明的是 statefulset 定义多少个 Pod 副本(默认将仅部署 1 个 Pod)、匹配 Pod 标签的选择器、创建 pod 的模板、存储卷申请模板

    第二个 spec 是 spec.template.spec:主要用于 Pod 里的容器属性等配置。

    tatefulset.spec.template 里的内容是声明 Pod 对象时要定义的各种属性,所以这部分也叫做 PodTemplate(Pod 模板)。

    还有一个值得注意的地方是:在tatefulset.spec.selector 中定义的标签选择器必须能够匹配到spec.template.metadata.labels 里定义的 Pod 标签,否则 Kubernetes 将不允许创建 statefulset。
     


  • Statefulset 使用案例-部署 web 站点
  • 1、创建运行 nfs-provisioner 需要的 sa 账号
    vim serviceaccount.yaml 2、对 sa 授权
    kubectl create clusterrolebinding nfs-provisioner --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner 
  •  3、安装 nfs-provisioner 程序
    # mkdir /data/nfs_pro -p
    #把/data/nfs_pro 变成 nfs 共享的目录
    vim /etc/exports

    vim nfs-deployment.yaml
     provisioner 相当于一个 pod,必须正常运行才可以
    • 4、#创建存储类
      # vim class-web.yaml

       
      vim statefulset.yaml

       #通过上面可以看到创建的 pod 是有序的 web-[ ]
    • #使用 kubectl run 运行一个提供 nslookup 命令的容器的,改命令来自于 dnsutils 包,通过对pod 主机名执行 nslookup,可以检查它们在集群内部的 DNS 地址:

      kubectl exec -it web-0 -- /bin/bash
      apt update
      apt install dnsutils -y
      nslookup web-0.nginx.default.svc.cluster.local

      #statefulset 创建的 pod 也是有 dns 记录的

      Server:        10.96.0.10
      Address:    10.96.0.10#53

      Name:    nginx.default.svc.cluster.local
      Address: 10.244.61.198
      Name:    nginx.default.svc.cluster.local
      Address: 10.244.179.6

       资源清单详细解读:

      apiVersion: v1 #定义 api 版本
      kind: Service #定义要创建的资源:service
      metadata: 
       name: nginx #定义 service 的名字
       labels:
       app: nginx #service 的标签
      spec:
       ports:
       - port: 80
       name: web
       clusterIP: None #创建一个没有 ip 的 service
       selector:
       app: nginx #选择拥有 app=nginx 标签的 pod
      ---
      apiVersion: apps/v1
      kind: StatefulSet
      metadata: 
       name: web
      spec:
       selector:
       matchLabels:
       app: nginx
       serviceName: "nginx" # 上面定义的 headless service 的名字
       replicas: 2 #副本数
       template: #定义 pod 的模板
       metadata: 
       labels:
       app: nginx
       spec: 
       containers:
       - name: nginx
       image: nginx
       ports:
       - containerPort: 80
       name: web
       volumeMounts:
       - name: www
       mountPath: /usr/share/nginx/html
       volumeClaimTemplates: #存储卷申请模板
         - metadata:
           name: www
        spec:
           accessModes: ["ReadWriteOnce"]
           storageClassName: "nfs-web" #指定从哪个存储类申请 pv
           resources:
             requests: 
               storage: 1Gi #需要 1G 的 pvc,会自动跟符合条件的 pv 绑定

    • Statefulset 管理 pod-扩容、缩容、更新
    • Statefulset 实现 pod 的动态扩容
       
    • 如果觉得两个副本太少了,想要增加,只需要修改配置文件 statefulset.yaml 里的 replicas 的值即可,原来 replicas: 2,现在变成 replicaset: 3,修改之后,执行更新:

       也可以直接编辑控制器实现扩容,这个是把请求提交给了 apiserver,实时修改
       Statefulset 实现 pod 的动态缩容
      如果觉得 4 个 Pod 副本太多了,想要减少,只需要修改配置文件 statefulset.yaml 里的replicas 的值即可,把 replicaset:4 变成 replicas: 2,修改之后,执行更新:
       #Statefulset 实现 pod 里面容器 的更新
      kubectl edit statefulsets.apps web
      #修改镜像 nginx 变成- image: ikubernetes/myapp:v2,修改之后保存退出

       

    • k8s 配置管理中心-Configmap
    •  
    • Configmap 概述
    • 什么是 Configmap?
      Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value 键值对的形式保存,也可通过文件的形式保存。
    • Configmap 能解决哪些问题?
      在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache 等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。

      所以,k8s 中引入了 Configmap资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。
    • 1、Configmap 是 k8s 中的资源, 相当于配置管理中心,可以有一个或者多个 Configmap;
      2、Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
    • Configmap 应用场景
      1、使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用性,因为一个 configMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。configmap 注入方式有两种,一种将configMap 做为存储卷,一种是将 configMap 通过 env 中 onfigMapKeyRef 注入到容器中。

      2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用 configmap 可以友好的进行配置共享。

      局限性
      ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB。
      如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。

    • Configmap 创建方法
    • 编写 configmap 资源清单 YAML 文件

      # vim mysql-configmap.yaml

       使用 Configmap,把 configmap 做成 volume,挂载到 pod
      vim mysql-pod-volume.yaml

       

    转载请注明:文章转载自 www.mshxw.com
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号