kubernets之StatefulSet

1 StatefulSet解决的问题

对于kubernetes中的应用,如果同一个deployment中的pod存在依赖,或者对于数据存储应用往往有多个实例,但每个实例都会在本地保存一份数据,如果应用实例重建,
那么实例与本地数据的对应关系会丢失。这种实例的不对等关系以及对外部数据有依赖的应用,我们称之为“有状态的应用”。
对于这种“有状态的应用”如何管理,StatefulSet为这个问题提供了解决办法。

2 StatefulSet功能

StatefulSet把“有状态的应用”抽象为了两种情况:

  • 拓扑状态,应用之间不对等,启动有先后顺序
  • 存储状态,一个数据库应用的多个实例

StatefulSet核心功能就是通过某种方式记录这些状态,然后在 Pod 被重新创建时,能够为新 Pod 恢复这些状态。

3 StatefulSet之拓扑状态

3.1 原理

Service 将一组Pod 暴露给外界访问,那么Service又改如何被访问呢?

  • 以 Service 的 VIP(Virtual IP,即:虚拟 IP)方式

  • 以 Service 的 DNS 方式。比如:这时候,只要我访问“my-svc.my-namespace.svc.cluster.local”这条 DNS 记录,就可以访问到名叫 my-svc 的 Service 所代理的某一个 Pod。可以分为两种处理方法:

    • 一是 Normal Service。这种情况下,你访问“my-svc.my-namespacece.svc.cluster.local”解析到的,正是 my-svc 这个 Service 的 VIP,后面的流程就跟 VIP 方式一致了。

    • 二是 Headless Service。这种情况下,你访问“my-svc.my-namespace.svc.cluster.local”解析到的,直接就是my-svc 代理的某一个 Pod 的 IP 地址。

    Normal Service和Headless Service 的区别是,后者不需要分配一个 VIP,可以直接以 DNS 记录的方式解析出被代理 Pod 的 IP 地址。

Headless Service,其实仍是一个标准Service的YAML文件。只不过,它的 clusterIP 字段的值是:None,没有VIP。

3.2 实例

statefulset.yaml 文件如下

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

执行操作:

kubectl create -f statefulset.yaml -n cfd
# 查看过程
kubectl get pod -w -l app=nginx -n cfd

# 创建一个pod,用于访问web pod
kubectl run -i --tty --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh -n cfd 

# 查看dns是否正常
nslookup web-0.nginx
nslookup web-1.nginx

# 删除pod,查看启动过程
kubectl delete pod -l app=nginx -n cfd
kubectl get pod -w -l app=nginx -n cfd

4 StatefulSet之存储状态

StatefulSet对存储状态的管理,主要使用的是Persistent Volume Claim的功能,同时也避免了用户名、授权文件位置等信息的暴露。

对于一个pvc对象,Kubernetes会自动为它绑定一个符合条件的Volume,这个Volume一般由运维人员维护。对于PVC和PV的设计,类似于“接口”和“实现”的思想。

4.1 实例

PV的YAML文件如下:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv-volume
  labels:
    type: local
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  rbd:
    monitors:
    - '10.16.154.78:6789'
    - '10.16.154.82:6789'
    - '10.16.154.83:6789'
    pool: kube
    image: foo
    fsType: ext4
    readOnly: true
    user: admin
    keyring: /etc/ceph/keyring
    imageformat: "2"
    imagefeatures: "layering"

使用PVC的StatefulSet的YAML文件如下:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

执行的操作:

kubectl create -f statefulset.yaml
# pvc 以“pvc名字-statefulset名字-编号”的方式命名
kubectl get pvc -l app=nginx
  NAME        STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
  www-web-0   Bound     pvc-15c268c7-b507-11e6-932f-42010a800002   1Gi        RWO           48s
  www-web-1   Bound     pvc-15c79307-b507-11e6-932f-42010a800002   1Gi        RWO           48s

# 在volume中写入index.html文件
for i in 0 1; do kubectl exec web-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'; done
# 访问nginx服务器,返回index.html的内容
for i in 0 1; do kubectl exec -it web-$i -- curl localhost; done
  hello web-0
  hello web-1

# 删除pod
kubectl delete pod -l app=nginx

# 在被重新创建出来的 Pod 容器里访问 http://localhost
$ kubectl exec -it web-0 -- curl localhost
  hello web-0

4.2 原理

根据以上的实例发现,在pod删除时,并没有删除Pod对应的PVC和PV,而Volume写入的数据也依然保存在远程存储服务中。
基于以上的现象,我们得出StatefulSet管理存储状态的原理如下所示:

    1. StatefulSet的控制器直接管理的是Pod,StatefulSet会在每个Pod实例后加一个编号,用于区分实例的不同;
    1. Kubernetes通过Headless Service,为这些有编号的Pod,在DNS服务器中生成带同样编号的DNS记录;
    1. StatefulSet为每个pod创建一个同样编号的PVC,这样Kubernetes通过PV机制为每个PVC绑定上对应的PV,保证每一个Pod一直拥有同一个独立的Volume。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值