K8s: 控制器之StatefulSets对象

发布于:2024-04-28 ⋅ 阅读:(27) ⋅ 点赞:(0)

StatefulSet


1 ) 概述

  • Stateful,也就是有状态应用,微服务无状态是一个理想的这么一个环境
  • 有些应用是有状态的,比如这个web服务器,它只能运行在一台server上
  • 因为它要访问一些持久化的存储
  • 比如说 mysql 它就是一个典型的有状态的应用,不希望应用随时漂移到别的节点上,然后数据发生变化
  • 为什么说它有状态?
    • 就是因为它的数据是落在这个磁盘上的
    • 虽然云原生应用里面,尽量的把一些服务都变成云原生的应用
    • 在实际生活中,在实际企业开发中,很多应用它是有状态的
  • 那什么是无状态的呢?
    • 比如一个博客应用,它是无状态的,它不依赖于你底层的数据库服务地址
    • 这个应用可以部署多个
  • 在这个mysql服务器,它是有状态的应用,K8s为了应对,提出了 StatefulSets 的概念
  • StatefulSets 它是用来管理Deployment和扩展一组Pod,并且为这个pod提供序号唯一性的保证
  • 所以它和Deployment的不同是在于
    • 它管理了一组相同容器定义的pod, 它为每个Pod维护了一个固定的ID
    • 在Deployment,它的ID是一个Pod名称加后面随机字母的组合,它的名称是动态拼出来的
    • 但是,StatefulSet的pod, 它的容器名称有一个永久不变的ID, 如果建3个,就会变成 -0, -1, -2 这样的不变ID
  • StatefulSets 会定义你期望的一个状态,比如说你有3个副本,它会给你创建3个副本
  • StatefulSets 的使用场景
    • 有稳定唯一的网络标识符
    • 有一个稳定的持久化的存储,可以有序的去缩放,有序的去更新扩容
      • 有序的是指更新是从012345…按顺序更新,而不是随机的去更新
    • 这样的应用更适合 StatefulSets 来管理,而不是Deployment
  • StatefulSets 的限制
    • 必须有这个挂载 PersistentVolume 挂载卷,可以是本地,也可以是对象存储
    • 需要有一个外部的持久化化存储,基于 storage class来匹配,那么这里面有一点很重要
    • 注意,如果说删掉 StatefulSets 中的pod并不会删除它的关联的存储
    • 这样是保证数据的安全,而在Deployment里删除pod, 其创建的临时数据文件都会消失
    • 对于 StatefulSets 它其实更着重的是这些数据
  • 所以 K8s 它设计的时候,存储这个对象和 StatefulSets,是两个隔离的对象
  • 另外,StatefulSets 需要用 headless 服务来创建pod标识
  • headless叫无头服务
    • 就是我的请求, 有时候不想走负载均衡,直接想通过IP链接到后端
    • 这个时候在 K8s 中,它就提供这个headless这个服务
    • 在HTTP发请求的时候发一个post请求之前,会发一个head请求,这个headless请求会做一些事情
    • 比如说对方后端的这个IP地址是哪里?做一些 session 的认证
    • headless请求, 就是直接能够不发这个head请求,直接和后端的服务进行一个交互,直接进行CRUD的操作
    • 在这种情况下, 需要要把这个 clusterip 设成为 none
    • 就是 StatefulSets 里面的 pod 在容器里面不用固定的IP

2 )应用

  • 在这里面,我们会先创建一个Service,然后再创建这个StatefulSets

  • 新建 sfs-demo1.yaml

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mongodb
    spec:
      serviceName: mongodb  #必须配置 和service名字统一起来
      replicas: 2
      selector:
        matchLabels:
          app: mongodb
      template:
        metadata:
          labels:
            app: mongodb
        spec:
          containers:
            - name: mongo
              image: mongo:4.4          
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: mongodb
    spec:
      selector:
        app: mongodb
      type: ClusterIP
      # HeadLess  
      clusterIP: None
      ports:
        - port: 27017    #本 Service 的端口
          targetPort: 27017  #容器的端口
    
  • $ kubectl apply -f sfs-demo1.yaml

    statefulset.apps/mongodb created
    service/mongodb created
    
  • $ kubectl get all

    NAME            READY   STATUS    RESTARTS   AGE
    pod/mongodb-0   1/1     Running   0          20s
    pod/mongodb-1   1/1     Running   0          19s
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
    service/kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP     6d2h
    service/mongodb      ClusterIP   None         <none>        27017/TCP   20s
    
    NAME                       READY   AGE
    statefulset.apps/mongodb   2/2     20s
    
  • $ kubectl rollout restart statefulset mongodb 重启

  • $ kubectl scale statefulset mongodb --replicas=5 扩容

  • $ kubectl get all

    NAME            READY   STATUS    RESTARTS   AGE
    pod/mongodb-0   1/1     Running   0          3m31s
    pod/mongodb-1   1/1     Running   0          3m33s
    pod/mongodb-2   1/1     Running   0          2m33s
    pod/mongodb-3   1/1     Running   0          21s
    pod/mongodb-4   1/1     Running   0          20s
    
    NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
    service/kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP     6d2h
    service/mongodb      ClusterIP   None         <none>        27017/TCP   6m49s
    
    NAME                       READY   AGE
    statefulset.apps/mongodb   5/5     6m49s
    
  • $ kubectl get svc

    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
    kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP     6d2h
    mongodb      ClusterIP   None         <none>        27017/TCP   8m49s
    
  • $ kubectl get endpoints mongodb -o yaml

    apiVersion: v1
    kind: Endpoints
    metadata:
      annotations:
        endpoints.kubernetes.io/last-change-trigger-time: "2024-04-23T06:21:28Z"
      creationTimestamp: "2024-04-23T06:14:58Z"
      labels:
        service.kubernetes.io/headless: ""
      name: mongodb
      namespace: default
      resourceVersion: "292772"
      uid: e600cd76-37e9-48c1-90f8-fae2b31bbbd4
    subsets:
    - addresses:
      - hostname: mongodb-1
        ip: 10.244.1.107
        nodeName: node1.k8s
        targetRef:
          kind: Pod
          name: mongodb-1
          namespace: default
          resourceVersion: "292407"
          uid: 654c1164-9a0d-46c0-8148-61f71a6e7224
      - hostname: mongodb-0
        ip: 10.244.1.108
        nodeName: node1.k8s
        targetRef:
          kind: Pod
          name: mongodb-0
          namespace: default
          resourceVersion: "292437"
          uid: cef974da-f02d-4d93-bb00-0c74d534c866
      - hostname: mongodb-3
        ip: 10.244.1.109
        nodeName: node1.k8s
        targetRef:
          kind: Pod
          name: mongodb-3
          namespace: default
          resourceVersion: "292757"
          uid: caf43581-9e7c-48db-a761-1cb74e0ea871
      - hostname: mongodb-2
        ip: 10.244.2.67
        nodeName: node2.k8s
        targetRef:
          kind: Pod
          name: mongodb-2
          namespace: default
          resourceVersion: "292743"
          uid: 1eeba1cb-0e50-45fa-81d2-f4022dbd8b63
      - hostname: mongodb-4
        ip: 10.244.2.68
        nodeName: node2.k8s
        targetRef:
          kind: Pod
          name: mongodb-4
          namespace: default
          resourceVersion: "292770"
          uid: 4e3dc9f3-4f28-4802-af9a-705c12404ae5
      ports:
      - port: 27017
        protocol: TCP
    
  • $ kubectl exec -ti mongodb-0 -- mongo 测试数据存储

    MongoDB shell version v4.4.29
    connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
    Implicit session: session { "id" : UUID("74389cfe-1776-43ef-a37a-61cf5a7a9d82") }
    MongoDB server version: 4.4.29
    Welcome to the MongoDB shell.
    For interactive help, type "help".
    For more comprehensive documentation, see
      https://docs.mongodb.com/
    Questions? Try the MongoDB Developer Community Forums
      https://community.mongodb.com
    ---
    The server generated these startup warnings when booting:
            2024-04-23T06:18:17.563+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
            2024-04-23T06:18:17.563+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
    ---
    >
    
  • $ exit 退出

    bye
    
  • $ run mongodb-client --rm --tty -i --restart='Never' --image mongo:4.4 --command -- bash 连接数据库测试

    If you don't see a command prompt, try pressing enter.
    root@mongodb-client:/#
    
  • $ mongo --host mongodb-0.mongodb

    MongoDB shell version v4.4.29
    connecting to: mongodb://mongodb-0.mongodb:27017/?compressors=disabled&gssapiServiceName=mongodb
    Implicit session: session { "id" : UUID("83892098-096c-4521-acf4-54aa13312392") }
    MongoDB server version: 4.4.29
    Welcome to the MongoDB shell.
    For interactive help, type "help".
    For more comprehensive documentation, see
      https://docs.mongodb.com/
    Questions? Try the MongoDB Developer Community Forums
      https://community.mongodb.com
    ---
    The server generated these startup warnings when booting:
            2024-04-23T06:18:17.563+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
            2024-04-23T06:18:17.563+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
    ---
    >
    

关于run相关参数

  • $ kubectl run nginx --image=nginx
    • 启动一个 Nginx 实例
  • $ kubectl run hazelcast --image=hazelcast --port=5701
    • 启动一个 hazelcast 单个实例,并开放容器的5701端口
  • $ kubectl run hazelcast --image=hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default"
    • 运行一个 hazelcast 单个实例,并设置容器的环境变量"DNS_DOMAIN=cluster" and “POD_NAMESPACE=default”
  • $ kubectl run nginx --image=nginx --replicas=5
    • 启动一个 replicated 实例去复制 nginx
  • $ kubectl run nginx --image=nginx --dry-run
    • 试运行,不创建他们的情况下,打印出所有相关的 API 对象
  • $ kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }'
    • 用可解析的 JSON 来覆盖加载 deploymentspec,来运行一个 nginx 单个实例
    • 替换 … 为具体key, value
  • $ kubectl run -i --tty busybox --image=busybox --restart=Never
    • 运行一个在前台运行的 busybox 单个实例,如果退出不会重启

网站公告

今日签到

点亮在社区的每一天
去签到