kubernetes组件 Controller manager深刻认知
- Controller manager
- 常见的controller
- Controller manager的工作流程
- informer的内部机制
- 控制器的协同工作原理
- ReplicaSet controller 是如何被管理的?
- statefuleset 和deployment controller是如何控制滚动升级的
- statefuleset的滚动升级策略
- deployment 的滚动升级策略
- 一个经典的金丝雀发布请求监控图
- Controller 如何为statefuleset 设置DNS规则
- deployment 为什么需要三级对象才能实现rollingupdate? 而daemonset、statefuleset 为何可以呢?
- deploy 和daemonset 的toleration有何区别?
- namespace controller
- garbage controller
- 如何解除ownerReferences 的父子关系图?
- 来自生产的经验
- 高可用
- 高可用-leader election
Controller manager
Controller manager是真正负责资源管理的组件,它主要负责容器的副本数管理、节点状态维护、节点网段分配等。
它由众多控制器组成是Kubernetes负责实现生命式API和控制器模式的核心。
常见的controller
Controller manager的工作流程
informer的内部机制
控制器的协同工作原理
ReplicaSet controller 是如何被管理的?
以ReplicaSet为例,它会周期地检测理想的“目标容器数”和真实的“当前容器数”是否相同。如果不相等,则会将实际的容器数调整到目标容器数。
当设置一个ReplicaSet的副本数为10的时候,如果实际的容器数小于10,则会执行调用Apiserver创建Pod。如果当前容器数大于10,则会执行删除Pod操作。ReplicaSet检测过程如图
statefuleset 和deployment controller是如何控制滚动升级的
statefuleset的滚动升级策略
statefuleset的rollingupdate每次只升级一个partition,也就是有状态副本集的一个实例,例如mysql实例升级版本, 待确认0没问题之后。 再升级1. 需要人手动改。 无状态的滚动升级则不需要人介入。
template:
metadata:
annotations:
kubectl.kubernetes.io/restartedAt: "2022-09-22T14:41:17+08:00"
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: 10.50.10.185/harbortest/nginx:1.7.1
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
name: web
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/share/nginx/html
name: www
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
deployment 的滚动升级策略
maxSurge: 每次最多升级多少个pod.
maxUnavailable:每次不可用pod的数量。
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx-pod
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
一个经典的金丝雀发布请求监控图
Controller 如何为statefuleset 设置DNS规则
POD ip变了没关系,因为有DNS 记录,别的用户调用的是域名。域名永远会指向新的podip。
deployment 为什么需要三级对象才能实现rollingupdate? 而daemonset、statefuleset 为何可以呢?
使用了同一的版本管理controllerrevision 对象 。
这是statefuleset的controllerrevision, 也是通过hash值的变化确定其名称,和deployment相比较少了一层rs。
这是因为deploy这个对象出现的早,后面的对象设计演进更加先进了。
k get controllerrevision -n dev
NAME CONTROLLER REVISION AGE
web-58968dc4b7 statefulset.apps/web 2 64d
web-5d6c5f6975 statefulset.apps/web 1 150d
controllerrevision 的内容
⚡ root@master1 /etc/kubernetes k get controllerrevision web-58968dc4b7 -n dev -oyaml
apiVersion: apps/v1
data:
spec:
template:
$patch: replace
metadata:
annotations:
kubectl.kubernetes.io/restartedAt: "2022-09-22T14:41:17+08:00"
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: 10.50.10.185/harbortest/nginx:1.7.1
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
name: web
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/share/nginx/html
name: www
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
kind: ControllerRevision
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"StatefulSet","metadata":{"annotations":{},"name":"web","namespace":"dev"},"spec":{"replicas":2,"selector":{"matchLabels":{"app":"nginx"}},"serviceName":"nginx","template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"10.50.10.185/harbortest/nginx:1.7.1","name":"nginx","ports":[{"containerPort":80,"name":"web"}],"volumeMounts":[{"mountPath":"/usr/share/nginx/html","name":"www"}]}]}},"volumeClaimTemplates":[{"metadata":{"name":"www"},"spec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"1Gi"}}}}]}}
creationTimestamp: "2022-09-22T06:41:17Z"
labels:
app: nginx
controller.kubernetes.io/hash: 58968dc4b7
name: web-58968dc4b7
namespace: dev
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: StatefulSet
name: web
uid: f85c72ef-4c47-4ccd-bf37-ff074aecb666
resourceVersion: "20488479"
uid: f7659ffe-5d5d-4db3-aecd-f868312b7a9a
revision: 2
deploy 和daemonset 的toleration有何区别?
daemon set
和节点比较亲密不容易被驱逐,一般都没有tolerationseconds,会一直赖着不走直到条件满足,
注意看这个promtail的pod yaml,这个组件是用来收集日志的.
apiVersion: v1
kind: Pod
labels:
controller-revision-hash: 7d4595d8
k8s.kuboard.cn/layer: monitor
k8s.kuboard.cn/name: kuboard-promtail
pod-template-generation: "1"
name: kuboard-promtail-2d8ws
namespace: kuboard
...
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/disk-pressure
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/memory-pressure
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/pid-pressure
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/unschedulable
operator: Exists
volumes:
- configMap:
defaultMode: 420
name: kuboard-promtail-configmap
name: config
- hostPath:
deployment
和节点关系不大,总结来说就是 “不行我就走”。
namespace controller
删除一个ns时会级联删除该ns下的所有对象。这是如何做到的呢?
通过uid属性
ns的删除机制?
ns是标记删除,finalizer 为空则真正删除。
garbage controller
ownerReferences 表明这个pod来自哪里?是sts、deploy、daemon 哪个对象呢? 他们之间都是通过ownerReferences来进行关联的。
这就构建出了父子关系图。
graphbuilder. 扫描这些对象,构建这个关系图。
同样删除的时候,会通过这个父子关系图进行级联删除。
如何解除ownerReferences 的父子关系图?
应用场景是啥呢?
删除的时候通过传入 --cascade=orphan 来完成
# --cascade='background': Must be "background", "orphan", or "foreground". Selects the deletion cascading strategy
来自生产的经验
高可用
Leader Election
Kubenetes 提供基于 configmap 和 endpoint 的 leader election 类库
Kubernetes 采用leader election 模式启动 component 后』会创建对应 endpoint, leader 信息 annotate 至U endponit 上。
高可用-leader election
现在一般都不使用EP,使用新的对象lease
这类似于一个文件所,k8s 通过lease 来确保唯一一个controller运行。
# k get lease kube-controller-manager -oyaml -n kube-system
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
creationTimestamp: "2022-06-26T07:04:24Z"
name: kube-controller-manager
namespace: kube-system
resourceVersion: "37461454"
uid: d9e4245d-4e88-4f6b-900c-ac473bbe3201
spec:
acquireTime: "2022-10-19T06:54:48.349009Z"
holderIdentity: master2_5099ba2c-f421-43e6-8f3a-7b09363610d1
leaseDurationSeconds: 15
leaseTransitions: 9
renewTime: "2022-11-25T08:22:57.622771Z"
可以看到mster2 抢到了锁. 来控制controller manager