k8s——pod控制器
- Pod控制器介绍
-
- Pod控制器及其功能
- pod控制器有多种类型
- Pod与控制器的关系
- Pod控制器类型及yaml格式
-
- Deployment
- StatefulSet
- DaemonSet
- Job
- CronJob
Pod控制器介绍
Pod控制器及其功能
Pod控制器又称工作负载(workload),用于实现管理pod保证中间层pod资源符合预期状态,pod当资源出现故障时,将尝试重启。当重启策略无效时,将重建pod的资源。
pod控制器有多种类型
- ReplicaSet: 代用户创建指定数量的代用户pod保证副本的数量pod副本数量符合预期状态,并支持滚动自动扩容和缩容功能。 ReplicaSet三个由三个组件组成: (1)用户期望pod副本数量 (2)判断哪个标签选择器pod归自己管理 (3)当现存的pod数量不足,会根据pod新建资源模板 帮助用户管理无状态的用户pod然而,资源准确地反映了用户定义的目标数量,RelicaSet不是直接使用的控制器,而是使用Deployment
- Deployment:工作在ReplicaSet目前最好的控制器是管理无状态应用。支持滚动更新和回滚功能,并提供声明配置。 ReplicaSet 与Deployment 这两个资源对象在之前逐渐被替换RC的作用。
- DaemonSet:确保集群中的每个节点只运行特定的节点pod副本通常用于实现系统级后台任务。ELK服务 特点:服务无状态 服务必须是守护过程
- StatefulSet:管理有状态应用
- Job:完成后立即退出,无需重启或重建
- Cronjob:周期性任务控制不需要在后台连续运行
Pod与控制器的关系
- controllers:在集群上管理和运行容器 pod 对象,pod通过label-selector 相关联。
- Pod应用的操作和维护,如伸缩、升级等。
Pod控制器类型及yaml格式
Deployment
部署无状态应用 管理Pod和ReplicaSet 具有在线部署、副本设置、滚动升级、回滚等功能 提供声明更新,例如只更新一个新的image 应用场景:web服务 //示例: vim nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.15.4 ports: - containerPort: 80 kubectl create -f nginx-deployment.yaml kubectl get pods,deploy,rs ///检查控制器配置 kubectl edit deployment/nginx-deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" creationTimestamp: "2021-04-19T08:13:50Z" generation: 1 labels: app: nginx #Deployment资源的标签 name: nginx-deployment namespace: default resourceVersion: "167208" selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-deployment uid: d9d3fef9-20d2-4196-95fb-0e21e65af24a spec: progressDeadlineSeconds: 600 replicas: 3 #期望的pod数量,默认是1 revisionHistoryLimit: 10 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 25% #升级过程中会先启动新的Pod数量不超过预期Pod数量的25%,也可以是绝对值 maxUnavailable: 25% #在新的升级过程中Pod启动好后销毁的旧Pod数量不超过预期Pod数量的25%,也可以是绝对值 type: RollingUpdate #滚动升级 template: metadata: creationTimestamp: null labels: app: nginx #Pod副本相关标签 spec: containers: - image: nginx:1.15.4 #镜像名称 imagePullPolicy: IfNotPresent #镜像拉取策略 name: nginx ports: - containerPort: 80 ##容器暴露的监控端口 protocol: TCP resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always #容器重启策略 schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 ... ///查看历史版本 kubectl rollout history deployment/nginx-deployment deployment.extensions/nginx-deployment REVISION CHANGE-CAUSE 1 <none>
StatefulSet
有状态应用部署 稳定的持久存储,即Pod基于相同的持久数据,重新调度后仍可访问PVC来实现 网络标志稳定,即Pod重新调度后PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现 有序部署,有序扩展,即Pod是有序的,在部署或扩展时应按定义的顺序进行(即从0到N-1,在下一个Pod运行前的一切Pod必须都是Running和Ready状态),基于init containers来实现 有序收缩,有序删除(即从N-1到0) 常见的应用场景:数据库 https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
==========================================================
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:
●Headless Service(无头服务):用于为Pod资源标识符生成可解析的DNS记录。
●volumeClaimTemplates(存储卷申请模板):基于静态或动态PV供给方式为Pod资源提供专有的固定存储。
●StatefulSet:用于管控Pod资源。
==========================================================
为什么要有headless?
在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。
为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
==========================================================
为什么要有volumeClainTemplate?
大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在 deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。
==========================================================
服务发现:就是应用服务之间相互定位的过程。
应用场景:
●动态性强:Pod会飘到别的node节点
●更新发布频繁:互联网思维小步快跑,先实现再优化,老板永远是先上线再慢慢优化,先把idea变成产品挣到钱然后再慢慢一点一点优化
●支持自动伸缩:一来大促,肯定是要扩容多个副本
K8S里服务发现的方式---DNS,使K8S集群能够自动关联Service资源的“名称”和“CLUSTER-IP”,从而达到服务被集群自动发现的目的。
实现K8S里DNS功能的插件:
●skyDNS:Kubernetes 1.3之前的版本
●kubeDNS:Kubernetes 1.3至Kubernetes 1.11
●CoreDNS:Kubernetes 1.11开始至今
==========================================================
//安装CoreDNS,仅二进制部署环境需要安装CoreDNS
方法一:
下载链接:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base
vim transforms2sed.sed
s/__DNS__SERVER__/10.0.0.2/g
s/__DNS__DOMAIN__/cluster.local/g
s/__DNS__MEMORY__LIMIT__/170Mi/g
s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: coredns.yaml.base/g
sed -f transforms2sed.sed coredns.yaml.base > coredns.yaml
方法二:上传 coredns.yaml 文件
kubectl create -f coredns.yaml
kubectl get pods -n kube-system
==========================================================
vim nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx
kubectl create -f nginx-service.yaml
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d19h
nginx-service NodePort 10.96.173.115 <none> 80:31756/TCP 10s
=========================================================
vim pod6.yaml
apiVersion: v1
kind: Pod
metadata:
name: dns-test
spec:
containers:
- name: busybox
image: busybox:1.28.4
args:
- /bin/sh
- -c
- sleep 36000
restartPolicy: Never
kubectl create -f pod6.yaml
//解析kubernetes和nginx-service名称
kubectl exec -it dns-test sh
/ # nslookup kubernetes
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
/ # nslookup nginx-service
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: nginx-service
Address 1: 10.96.173.115 nginx-service.default.svc.cluster.local
==========================================================
//查看statefulset的定义
kubectl explain statefulset
KIND: StatefulSet
VERSION: apps/v1
DESCRIPTION:
StatefulSet represents a set of pods with consistent identities. Identities
are defined as: - Network: A single stable DNS and hostname. - Storage: As
many VolumeClaims as requested. The StatefulSet guarantees that a given
network identity will always map to the same storage identity.
FIELDS:
apiVersion <string>
kind <string>
metadata <Object>
spec <Object>
status <Object>
kubectl explain statefulset.spec
KIND: StatefulSet
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Spec defines the desired identities of pods in this set.
A StatefulSetSpec is the specification of a StatefulSet.
FIELDS:
podManagementPolicy <string> #Pod管理策略
replicas <integer> #副本数量
revisionHistoryLimit <integer> #历史版本限制
selector <Object> -required- #选择器,必选项
serviceName <string> -required- #服务名称,必选项
template <Object> -required- #模板,必选项
updateStrategy <Object> #更新策略
volumeClaimTemplates <[]Object> #存储卷申请模板,必选项
=========================================================
//清单定义StatefulSet
如上所述,一个完整的 StatefulSet 控制器由一个 Headless Service、一个 StatefulSet 和一个 volumeClaimTemplate 组成。如下资源清单中的定义:
vim stateful-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
labels:
app: myapp-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp-svc
replicas: 3
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
annotations: #动态PV创建时,使用annotations在PVC里声明一个StorageClass对象的标识进行关联
volume.beta.kubernetes.io/storage-class: nfs-client-storageclass
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
解析上例:由于 StatefulSet 资源依赖于一个实现存在的 Headless 类型的 Service 资源,所以需要先定义一个名为 myapp-svc 的 Headless Service 资源,用于为关联到每个 Pod 资源创建 DNS 资源记录。接着定义了一个名为 myapp 的 StatefulSet 资源,它通过 Pod 模板创建了 3 个 Pod 资源副本,并基于 volumeClaimTemplates 向前面创建的PV进行了请求大小为 2Gi 的专用存储卷。
==========================================================
//创建pv
//stor01节点
mkdir -p /data/volumes/v{
1,2,3,4,5}
vim /etc/exports
/data/volumes/v1 192.168.80.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.80.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.80.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.80.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.80.0/24(rw,no_root_squash)
systemctl restart rpcbind
systemctl restart nfs
exportfs -arv
showmount -e
//定义PV
vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: stor01
accessModes: ["ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/volumes/v4
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/volumes/v5
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
kubectl apply -f pv-demo.yaml
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 7s
pv002 2Gi RWO Retain Available 7s
pv003 2Gi RWO,RWX Retain Available 7s
pv004 2Gi RWO,RWX Retain Available 7s
pv005 2Gi RWO,RWX Retain Available 7s
//创建statefulset
kubectl apply -f stateful-demo.yaml
kubectl get svc #查看创建的无头服务myapp-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 50d
myapp-svc ClusterIP None <none> 80/TCP 38s
kubectl get sts #查看statefulset
NAME DESIRED CURRENT AGE
myapp 3 3 55s
kubectl get pvc #查看pvc绑定
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 2Gi RWO 1m
myappdata-myapp-1 Bound pv003 2Gi RWO,RWX 1m
myappdata-myapp-2 Bound pv004 2Gi RWO,RWX 1m
kubectl get pv #查看pv绑定
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 6m
pv002 2Gi RWO Retain Bound default/myappdata-myapp-0 6m
pv003 2Gi RWO,RWX Retain Bound default/myappdata-myapp-1 6m
pv004 2Gi RWO,RWX Retain Bound default/myappdata-myapp-2 6m
pv005 2Gi RWO,RWX Retain Available 6m
kubectl get pods #查看Pod信息
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 2m
myapp-1 1/1 Running 0 2m
myapp-2 1/1 Running 0 2m
kubectl delete -f stateful-demo.yaml
//当删除的时候是从myapp-2开始进行删除的,关闭是逆向关闭
kubectl get pods -w
//此时PVC依旧存在的,再重新创建pod时,依旧会重新去绑定原来的pvc
kubectl apply -f stateful-demo.yaml
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 2Gi RWO 5m
myappdata-myapp-1 Bound pv003 2Gi RWO,RWX 5m
myappdata-myapp-2 Bound pv004 2Gi RWO,RWX
//滚动更新
//StatefulSet 控制器将在 StatefulSet 中删除并重新创建每个 Pod。它将以与 Pod 终止相同的顺序进行(从最大的序数到最小的序数),每次更新一个 Pod。在更新其前身之前,它将等待正在更新的 Pod 状态变成正在运行并就绪。如下操作的滚动更新是按照2-0的顺序更新。
vim stateful-demo.yaml #修改image版本为v2
.....
image: ikubernetes/myapp:v2
....
kubectl apply -f stateful-demo.yaml
kubectl get pods -w #查看滚动更新的过程
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 29s
myapp-1 1/1 Running 0 27s
myapp-2 0/1 Terminating 0 26s
myapp-2 0/1 Terminating 0 30s
myapp-2 0/1 Terminating 0 30s
myapp-2 0/1 Pending 0 0s
myapp-2 0/1 Pending 0 0s
myapp-2 0/1 ContainerCreating 0 0s
myapp-2 1/1 Runnin