实验环境:

在这里插入图片描述
按照图示部署好了K8s集群,一个Master,两个worker nodes。

DaemonSet(DS):

相比于deployment,daemonset不需要设置副本数,而是会自适应节点数,而是会自动在每个节点上创建一个pod。

应用场景:

  1. 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph;
  2. 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash;
  3. 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
    在这里插入图片描述
    创建daemonset:

可以根据deployment 的yaml文件来修改:

kubectl create deployment ds1 --image=nginx --dry-run=client -o yaml >ds1.yaml

修改其yaml文件:修改kind类型,删除掉replicas、strategy和status三个元素即可。同时可以添加terminationGracePeriodSeconds和imagePullPolicy。

[root@vms201 daemonset]# cat ds1.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: ds1
  name: ds1
spec:
  selector:
    matchLabels:
      app: ds1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: ds1
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}

创建ds,可以看到其分布在2个work nodes上:

[root@vms201 daemonset]# kubectl apply -f ds1.yaml
daemonset.apps/ds1 created
[root@vms201 daemonset]# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP              NODE             NOMINATED NODE   READINESS GATES
ds1-48x5f   1/1     Running   0          9s    10.244.58.212   vms202.rhce.cc   <none>           <none>
ds1-hn8q6   1/1     Running   0          9s    10.244.185.67   vms203.rhce.cc   <none>           <none>

如果控制ds仅在部分节点运行,可以通过如下方法实现:

首先给一个node打上标签:

[root@vms201 daemonset]# kubectl label nodes  vms202.rhce.cc disktype=ssd
node/vms202.rhce.cc labeled

修改daemonset的yaml文件,增加nodeSelector,用标签的方式指定调度在哪个node上:

[root@vms201 daemonset]# kubectl edit daemonsets.apps ds1
daemonset.apps/ds1 edited

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: ds1
  name: ds1
spec:
  selector:
    matchLabels:
      app: ds1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: ds1
    spec:
      terminationGracePeriodSeconds: 0
      nodeSelector:
        disktype: ssd
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}

查看ds是否修改成功:

[root@vms201 daemonset]# kubectl get ds ds1
NAME   DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ds1    1         1         1       1            1           disktype=ssd    58s

k8s组件中由daesonset创建的有如下的pod:

[root@vms201 daemonset]# kubectl get ds -n kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
calico-node   3         3         3       3            3           kubernetes.io/os=linux   6d12h
kube-proxy    3         3         3       3            3           kubernetes.io/os=linux   6d12h

二、ReplicationController(RC):

ReplicationController (RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的pod来替代;而异常多出来的容器也会自动回收。

修改RC的yaml文件:

[root@vms201 daemonset]# cat rc1.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: myrc
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

创建RC并查看:

[root@vms201 daemonset]# kubectl apply -f rc1.yaml
replicationcontroller/myrc created

[root@vms201 daemonset]# kubectl get rc myrc -o wide
NAME   DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES   SELECTOR
myrc   3         3         3       58s   nginx        nginx    app=nginx

伸缩副本数:

[root@vms201 daemonset]# kubectl scale rc myrc --replicas=2
replicationcontroller/myrc scaled
[root@vms201 daemonset]# kubectl get rc
NAME   DESIRED   CURRENT   READY   AGE
myrc   2         2         2       4m38s

删除掉RC:

[root@vms201 daemonset]# kubectl delete -f rc1.yaml
replicationcontroller "myrc" deleted

三、ReplicaSet (RS)

在新版的Kubernetes中建议使用ReplicaSet (RS)来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不同,只是名字不一样,但ReplicaSet支持集合式selector。

虽然 ReplicaSets 可以独立使用,但如今它主要被Deployments 用作协调 Pod 的创建、删除和更新的机制。当使用 Deployment 时,你不必担心还要管理它们创建的 ReplicaSet,Deployment 会拥有并管理它们的ReplicaSet。所以说Deployment本质上是通过管理RS来管理pod的。

修改RS的yaml文件:

[root@vms201 daemonset]# cat rs1.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myrs
  labels:
    app: guestbook
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent

创建并查看RS:

[root@vms201 daemonset]# kubectl apply -f rs1.yaml
replicaset.apps/myrs created
[root@vms201 daemonset]# kubectl get rs  -o wide
NAME   DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES   SELECTOR
myrs   3         3         3       88s   nginx        nginx    tier=frontend

修改副本数:

[root@vms201 daemonset]# kubectl scale rs myrs --replicas=2
replicaset.apps/myrs scaled
[root@vms201 daemonset]# kubectl get rs  -o wide
NAME   DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES   SELECTOR
myrs   2         2         2       2m37s   nginx        nginx    tier=frontend

删除RS:

[root@vms201 daemonset]# kubectl delete -f rs1.yaml
replicaset.apps "myrs" deleted

四、StatefulSet(STS):

概述:
StatefulSet(k8s v1.9 中的stable-GA)是一种用于管理有状态应用程序的 Kubernetes 资源。它管理一组 Pod 的部署和扩展,并为这些 Pod 的排序和唯一性提供保证。

StatefulSet 也是一个 Controller,但与 Deployments 不同,它不会创建 ReplicaSet,而是自己创建具有唯一命名约定的 Pod。例如,如果用户创建一个名称为counter的 StatefulSet ,它将创建一个名称为counter-0的 pod ,对于一个 statefulset 的多个副本,它们的名称将像counter-0、counter-1、counter-2 等一样递增。

有状态集的每个副本都有自己的状态,每个 Pod 都将创建自己的 PVC(持久卷声明)。因此,具有 3 个副本的 statefulset 将创建 3 个 pod,每个 pod 都有自己的 Volume,因此总共 3 个 PVC。

相比于Deployments,StatefulSet能做到每一个容器的有自己的存储卷(数据不同),但是无法做到负载分担。

什么时候考虑使用StatefulSet:

一些应用,只适用于内部,并不行对外提供服务,且每个pod需要有自己的存储,且个pod挂掉再重启,还需要连接之前的pv,不能连到别的pv上,考虑使用StatefulSet。

sts和deploy的区别:
在这里插入图片描述
详细请参考:
https://blog.csdn.net/nickDaDa/article/details/90401635

实验测试:
sts不能直接创建,可以在K8s官网上找到对应的模板,然后进行修改:

[root@vms201 sts]# cat sts1.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteMany" ]
      storageClassName: "mysc"
      resources:
        requests:
          storage: 500Mi

仅创建一个Nginx的pod。其中 volumeClaimTemplates,每设置一个副本都会创建一个pvc。这里pvc通过指定的sc生成pv。
动态卷供应相关内容,请参考:https://blog.csdn.net/tushanpeipei/article/details/118493324?spm=1001.2014.3001.5501

创建sts服务后查看:可以看到已经自己已经生成了PVC,连接到了SC上,最终挂载到了远端NFS存储上。

[root@vms201 sts]# kubectl apply -f sts1.yaml
statefulset.apps/web created
[root@vms201 sts]# kubectl get pod web-0
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          17s
[root@vms201 sts]# kubectl get pvc
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pvc-a6928573-5d1d-4895-b36f-943658d1c11f   500Mi      RWX            mysc           3h30m

扩展副本数后可以发现,命名为web-1,序号依次增加:

[root@vms201 sts]# kubectl scale statefulset web --replicas=2
statefulset.apps/web scaled
[root@vms201 sts]# kubectl get pods | grep web
web-0                                    1/1     Running       0          9m13s
web-1                                    1/1     Running       0          68s

可以在NFS数据卷中找到数据信息:可以看到两个pod的信息是分别存储的。

[root@nfs cc]# ls
sts-www-web-0-pvc-a6928573-5d1d-4895-b36f-943658d1c11f  sts-www-web-1-pvc-310b70de-71a6-48fc-b8de-d769d572328e

修改pod的主页,以做区别:

[root@vms201 sts]# kubectl exec -it web-0 -- sh -c "echo 111 > /usr/share/nginx/html/index.html"
[root@vms201 sts]# kubectl exec -it web-1 -- sh -c "echo 222 > /usr/share/nginx/html/index.html"

然后将副本数清空后重新增加:

[root@vms201 sts]# kubectl scale statefulset web --replicas=0
statefulset.apps/web scaled
[root@vms201 sts]# kubectl scale statefulset web --replicas=2
statefulset.apps/web scaled
[root@vms201 sts]# kubectl get pods | grep web
web-0                                    1/1     Running       0          30s
web-1                                    1/1     Running       0          29s

可以看到名称没有改变,然后再去查看每个pod中的数据,可以发现依然和副本关闭前一致(存储不会错乱):

[root@vms201 sts]# kubectl exec -it web-0 -- sh -c "cat /usr/share/nginx/html/index.html"
111
[root@vms201 sts]# kubectl exec -it web-1 -- sh -c "cat /usr/share/nginx/html/index.html"
222

主要注意的是,重新创建的pod名称和存储的信息都和之前保持一致,但是IP地址不同。

headless service:

由于每个pod中保存的信息不同,如果使用svc负载的方式将流量负载到不同的pod中,会导致访问到的内容不同。而直接访问pod,由于同一个pod删除,重新创建后,IP地址不同,也是一个问题。所以这个时候就可以实验headless service(无头服务)来解决问题。

可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。对于STS的无头无法不能直接创建,我看可以在SVC的yaml文件中修改:

[root@vms201 sts]# cat headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx

应用并查看服务信息,这里的CLUSTER-IP为None:

[root@vms201 sts]# kubectl apply -f headless.yaml
service/nginx created
[root@vms201 sts]# kubectl get svc -o wide
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx   ClusterIP   None         <none>        80/TCP    39s   app=nginx

访问headless服务下的pod:访问格式: 容器名.服务名,这里也就是web-0.nginx和web-1.nginx。

[root@vms201 sts]# kubectl run -it testpod --image=yauritux/busybox-curl --rm --image-pull-policy=IfNotPresent -- sh
If you don't see a command prompt, try pressing enter.
/home # curl web-0.nginx
111
/home # curl web-1.nginx
222

参考资料:
《老段CKA课程》
https://medium.com/stakater/k8s-deployments-vs-statefulsets-vs-daemonsets-60582f0c62d4

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐