实验环境:
按照图示部署好了 K8s 集群,一个 Master,两个 worker nodes。
DaemonSet(DS):
相比于 deployment,daemonset 不需要设置副本数,而是会自适应节点数,而是会自动在每个节点上创建一个 pod。
应用场景:
- 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph;
- 在每个 Node 上运行日志收集 daemon,例如 fluentd、logstash;
- 在每个 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 的区别:
详细请参考:
blog.csdn.net/nickDaDa/ar…
实验测试:
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。
动态卷供应相关内容,请参考:blog.csdn.net/tushanpeipe…
创建 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 课程》
medium.com/stakater/k8…