Deployment 应用于无状态的应用,即它认为所有 Pod 是完全一样的。所以它们之间没有顺序。但对于一些应用,尤其是分布式应用, 它的多个实例之间有依赖关系。比如:主从关系。这种实例之间有不对等关系(拓扑状态),以及实例对外部数据有依赖关系(存储状态)的应用,就称为有状态的应用。
Service 是 Kubernetes 项目中用来将一组 Pod 暴露给外界访问的一种机制。这个 Service 的访问方式有以下3种:
(1) 虚拟IP(VIP)的方式。
(2)NDS 方式。比如: 只要访问 my-svc.my-namespace.svc.cluster.local 就可以访问名叫 my-svc 所代理的某一个 pod。具体又分为两种处理方法
(a) Normal Service 。 此种方式,当访问 my-svc.my-namespace.svc.cluster.local 时,其实就是访问 my-svc 这个 service 的 VIP。
(b) Headless Service。 当访问 my-svc.my-namespace.svc.cluster.local 时,解析到的直接就是 my-svc 某一个 Pod 的 IP 地址。区别在于,Headless Service 不需要分配一个 VIP,而是可以直接以 DNS 记录的方式解析出被代理 Pod 的 IP 地址。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None # 表明是 headless Service
selector:
app: nginx
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
这里的 serviceName=nginx 的作用就是告诉 StatefulSet 控制器,在执行控制循环时请使用 Nginx 这个 Headless Service 来保证 Pod 可解析。先创建上面的 headless service,然后再创建 statefulSet。运行如下的命令:
kubectl get pods -w -l app=nginx
上面的命令输入够快的话,可以看到 web-0 的容器变为 ready 之前, web-1 会一直处于 Pending 状态(有些版本可能都看不到 web-1)。我们进入容器,可以看到 pod 的 hostname 就是 pod 的名字
kubectl exec web-0 -- sh -c 'hostname'
我们用下面的命令把这两个 Pod 删除后,kubernetes 会按照原先的编号的顺序重新创建出两个 Pod,并且分配了与原来相同的网络身份。
kubectl delete pod -l app=nginx
这种严格的对应规则,StatefulSet 就保证了 Pod 网络标识的稳定性。