平时的 web服务主要用的是RC和Deployment这种对象资源的使用,还有在特定场合下使用的控制器:DaemonSet与StatefulSet。
通过该控制器的名称我们可以看出它的用法:Daemon,就是用来部署守护进程的,DaemonSet用于在每个Kubernetes节点中将守护进程的副本作为后台进程运行,说白了就是在每个节点部署一个Pod副本,当节点加入到Kubernetes集群中,Pod会被调度到该节点上运行,当节点从集群只能够被移除后,该节点上的这个Pod也会被移除,当然,如果我们删除DaemonSet,所有和这个对象相关的Pods都会被删除。
在哪种情况下我们会需要用到这种业务场景呢?其实这种场景还是比较普通的,比如:
集群存储守护程序,如glusterd、ceph要部署在每个节点上以提供持久性存储;
节点监视守护进程,如Prometheus监控集群,可以在每个节点上运行一个node-exporter进程来收集监控节点的信息;
日志收集守护程序,如fluentd或logstash,在每个节点上运行以收集容器的日志
这里需要特别说明的一个就是关于DaemonSet运行的Pod的调度问题,正常情况下,Pod运行在哪个节点上是由Kubernetes的调度器策略来决定的,然而,由DaemonSet控制器创建的Pod实际上提前已经确定了在哪个节点上了(Pod创建时指定了.spec.nodeName),所以:
DaemonSet并不关心一个节点的unshedulable字段
DaemonSet可以创建Pod,即使调度器还没有启动,这点非常重要。
下面直接使用一个示例来演示下,在每个节点上部署一个Nginx Pod:(nginx-ds.yaml)
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: nginx-ds
labels:
k8s-app: nginx
spec:
selector:
matchLabels:
k8s-app: nginx
template:
metadata:
labels:
k8s-app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- name: http
containerPort: 80
然后直接创建即可:
$ kubectl create -f nginx-ds.yaml
然后我们可以观察下Pod是否被分布到了每个节点上:
$ kubectl get nodes
$ kubectl get pods -o wide
认识StatefulSet这种控制器之前,得先弄明白一个概念:什么是有状态服务?什么是无状态服务?
无状态服务(Stateless Service):该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的,比如前面我们讲解的WordPress实例,我们是不是可以同时启动多个实例,但是我们访问任意一个实例得到的结果都是一样的吧?因为他唯一需要持久化的数据是存储在MySQL数据库中的,所以我们可以说WordPress这个应用是无状态服务,但是MySQL数据库就不是了,因为他需要把数据持久化到本地。
有状态服务(Stateful Service):就和上面的概念是对立的了,该服务运行的实例需要在本地存储持久化数据,比如上面的MySQL数据库,你现在运行在节点A,那么他的数据就存储在节点A上面的,如果这个时候你把该服务迁移到节点B去的话,那么就没有之前的数据了,因为他需要去对应的数据目录里面恢复数据,而此时没有任何数据。
比如我们常见的 WEB 应用,是通过session来保持用户的登录状态的,如果我们将session持久化到节点上,那么该应用就是一个有状态的服务了,因为我现在登录进来你把我的session持久化到节点A上了,下次我登录的时候可能会将请求路由到节点B上去了,但是节点B上根本就没有我当前的session数据,就会被认为是未登录状态了,这样就导致我前后两次请求得到的结果不一致了。所以一般为了横向扩展,我们都会把这类 WEB 应用改成无状态的服务,怎么改?将session数据存入一个公共的地方,比如redis里面,是不是就可以了,对于一些客户端请求API的情况,我们就不使用session来保持用户状态,改成用token也是可以的。
无状态服务利用我们前面的Deployment或者RC都可以很好的控制,对应有状态服务,需要考虑的细节就要多很多了,容器化应用程序最困难的任务之一,就是设计有状态分布式组件的部署体系结构。由于无状态组件可能没有预定义的启动顺序、集群要求、点对点 TCP 连接、唯一的网络标识符、正常的启动和终止要求等,因此可以很容易地进行容器化。诸如数据库,大数据分析系统,分布式 key/value 存储和 message brokers 可能有复杂的分布式体系结构,都可能会用到上述功能。为此,Kubernetes引入了StatefulSet资源来支持这种复杂的需求。
StatefulSet类似于ReplicaSet,但是它可以处理Pod的启动顺序,为保留每个Pod的状态设置唯一标识,同时具有以下功能:
稳定的、唯一的网络标识符
稳定的、持久化的存储
有序的、优雅的部署和缩放
有序的、优雅的删除和终止
有序的、自动滚动更新