深入剖析Kubernetes--第五章:Kubernetes编排原理_控制器_StatefulSet(1)

StatefulSet(一)

​ Deployment 假设了一个应用的所有Pod都是一样的,他们之间没有顺序。但在实际场景中,多个实例之间通常会存在依赖关系,例如分布式应用中存在主从、主备关系;数据存储类应用,它的多个实例,往往都会在本地磁盘上保存一份数据。而这些实例一旦被杀掉,即便重建出来,实例与数据之间的对应关系也已经丢失,从而导致应用失败。

​ 当实例之间有不对等关系时,以及实例对外部数据有依赖关系时,被称为“有状态应用”(Stateful Application)

StatefulSet将应用状态抽象为两种:

(1)拓扑状态(顺序)

(2)存储状态

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

Headless Service

Service 是 Kubernetes 项目中用来将一组 Pod 暴露给外界访问的一种机制,访问Service 即可访问到具体的Pod。

有两种访问方式:

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

二:就是以 Service 的 DNS 方式。比如:访问“my-svc.my-namespace.svc.cluster.local”这条 DNS 记录,就可以访问到名叫 my-svc 的 Service 所代理的某一个 Pod。

在第二个方式下,又可以分为两种处理方法:

第一,Normal Service。访问“my-svc.my-namespace.svc.cluster.local”解析到的,是 my-svc 这个 Service 的 VIP,后面的流程就跟 VIP 方式一致。

第二,正是 Headless Service。访问“my-svc.my-namespace.svc.cluster.local”解析到的,直接就是 my-svc 代理的某一个 Pod 的 IP 地址。区别在于,Headless Service 不需要分配一个 VIP,而是可以直接以 DNS 记录的方式解析出被代理 Pod 的 IP 地址。

例: Headless Service 对应的 YAML 文件

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

Headless Service,其实仍是一个标准 Service 的 YAML 文件。只不过,它的 clusterIP 字段的值是:None,即:这个 Service,没有一个 VIP 作为“头”。这也就是 Headless 的含义。所以,这个 Service 被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod。所代理的 Pod,通过Label Selector 机制选择。

按照这样的方式创建了一个 Headless Service 之后,它所代理的所有 Pod 的 IP 地址,都会被绑定一个这样格式的 DNS 记录

...svc.cluster.local

这个 DNS 记录,正是 Kubernetes 项目为 Pod 分配的唯一的“可解析身份”(Resolvable Identity)

StatefulSet 是如何使用这个 DNS 记录来维持 Pod 的拓扑状态的呢

例: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

这个 YAML 文件,和前面文章中用到的 nginx-deployment 的唯一区别,就是多了一个 serviceName=nginx 字段。

这个字段的作用,就是告诉 StatefulSet 控制器,在执行控制循环(Control Loop)的时候,请使用nginx 这个 Headless Service 来保证 Pod 的“可解析身份”。

kubectl create -f svc.yaml
kubectl get service nginx
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None                 80/TCP    109s

kubectl create -f statefulset.yaml
kubectl get statefulset web
NAME   READY   AGE
web    2/2     2m19s

这些 Pod 的创建,也是严格按照编号顺序进行的。比如,在 web-0 进入到 Running 状态、并且细分状态(Conditions)成为 Ready 之前,web-1 会一直处于 Pending 状态。

当这两个 Pod 都进入了 Running 状态之后,你就可以查看到它们各自唯一的“网络身份”了。

使用 kubectl exec 命令进入到容器中查看它们的 hostname:

kubectl exec web-0 -- sh -c 'hostname'
web-0
kubectl exec web-1 -- sh -c 'hostname'
web-1

这两个 Pod 的 hostname 与 Pod 名字是一致的,都被分配了对应的编号。

以 DNS 的方式,访问一下这个 Headless Service:

kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh 

这条命令,启动了一个一次性的 Pod,因为–rm 意味着 Pod 退出后就会被删除掉。然后,在这个 Pod 的容器里面,尝试用 nslookup 命令,解析一下 Pod 对应的 Headless Service:

//nslookup命令 是常用域名查询工具,就是查DNS信息用的命令。

$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
$ nslookup web-0.nginx
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
 
Name:      web-0.nginx
Address 1: 10.244.1.7
 
$ nslookup web-1.nginx
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
 
Name:      web-1.nginx
Address 1: 10.244.2.7 

你可能感兴趣的:(kubernetes)