这篇文章主要介绍了kubernetes核心原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇kubernetes核心原理是什么文章都会有所收获,下面我们一起来看看吧。
控制器逻辑中包括controller, sensor 和system 三个逻辑组件,通过修改spec中相关的字段来触发事件,controller通过比较当前状态和期望状态,来触发对系统的具体操作。
sensor中则包括reflector, informer, indexer 三个组件,
reflector通过list&watch apiserver 来获取资源的数据,
list 用来在controller重启或者watch中断的情况下,对资源进行全量的更新。
watch则在多次list之间进行增量的更新。
reflector会在获取资源信息之后,会在delta queue中加入一个包括资源信息本身和资源对象事件类型的delta数据,delta队列可以保证同一个对象在队列中仅有一条记录,从而避免在reflector list&watch的时候产生重复的记录。
informer组件不断从delta队列中弹出delta记录,一方面把资源对象交给资源回调函数,同时又把资源对象交给indexer, indexer默认将资源对象记录在缓存中,通 过namespace作为其索引值,并且能被controller-manager的多个controller进行资源共享。
控制循环的控制器函数,主要由事件处理函数
和worker组成。
事件处理函数,会监听资源的新增、更新、删除事件,并根据控制器的逻辑,决定是否需要处理。
对于需要处理的事件,会把事件关联资源的命名空间,以及资源的名字塞入一个工作队列中,并且由worker池中的一个worker进行处理。
工作队列会对存储的事件进行去重,从而避免多个worker处理同一个资源的情况。
worker在处理资源对象时,一般会根据其名字来获取最新的数据,用来创建/更新资源对象,或调用其他外部服务。
worker处理失败的时候,会把资源事件重新加入工作队列中,方便之后重试。
控制器模式总结:
声明式api驱动- 对k8s资源对象的修改
控制器异步控制系统向终态趋近
使系统的自动化和无人值守成为可能
自定义资源和控制器(operator)便于系统扩展
定义一组pod的期望数量,controller会维持pod数量与期望数量一致。
配置pod发布方式,controller会按照给定的策略更新pod,保证更新过程中不可用的pod数量在限定范围内。
如果发布有问题,支持“一键”回滚。
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
kubectl rollout history deployment.v1.apps/nginx-deployment
Deployment只负责管理不同版本的ReplicaSet, 由ReplicaSet管理Pod副本数。每个ReplicaSe对应Deployment template的一个版本,一个RS下的pod都是相同版本。
checkpaused: 检查dp是否需要禁止新的发布,
dp的控制器实际上做了一些更复杂的事情,包括版本管理,而将具体版本下的数量维持工作交给replicaset来做。
扩容-发布-回滚
MinReadySeconds: 判断Pod available的最小ready时间
RevisionHistoryLimit: 保留历史revision(replicaset)的数量,默认值为10
paused: 标识deployment制作数量维持,不做新的发布
progressDealineSeconds: 判断dp status condition 为failed的最大时间。(dp处于processing最大多长时间,则认为dp status 为failed.)
MaxUnavailable: 滚动过程中最多有多少个pod不可用。
MaxSurge: 滚动过程最多存在多少个pod超过期望replicas数量。
maxunavailable 和 max surge不能同时为0?
因为,当maxsurge=0时,就必须先删一个pod再创建一个新pod,因为新扩出来一个pod,会导致rs超过期望数量。
maxsurge保证不能新扩pod,maxunavailable保证不能有pod不可用。
创建一个或多个pod确保指定数量的pod可以成功地运行终止。
跟踪pod状态,根据配置及时重试失败的pod。
确定依赖关系,保证上一个任务运行完毕后再运行下一个任务。
控制任务并行度,并根据配置确保pod队列大小。
completions: 代表本pod队列执行次数,这里8代表这个任务将被执行8次。
parallelism: 代表并行执行个数,这里的2代表并行执行的pod数量,也就是会有2个pod同时运行。
schedule: crontab时间格式相同
startingDeadlineSeconds: job最长启动时间
concurrencyPolicy: 是否允许并行运行
successfulJobsHistoryLimit: 允许留存历史job个数
Job controller 负责根据配置创建pod
job controller跟踪job状态,根据配置及时重试pod或者继续创建
job controller会自动添加label,来跟踪对应pod,并根据配置并行或串行创建pod
所有的job都是一个controller,它会去watch kube-apiserver,我们每次提交一个yaml,会经过apiserver存到etcd里,然后job controller 会注册几个handler,每次我们有添加/更新/删除等操作时,他会通过一个消息队列发送到job controller里,job controller检查当前存在的active pod, ……
保证集群内每一个(或者一些)节点都运行一组相同的pod
跟踪集群节点状态,保证新加入的节点自动创建对应的pod
跟踪集群节点状态,保证移除的节点删除对应的pod
跟踪pod状态,保证每个节点pod处于运行状态
RollingUpdate: DaemonSet默认更新策略,当更新Daemonset模板后,老的pod会被先删除,然后再去创建新的pod,可以配合健康检查做滚动更新。
OnDelete: 当DaemonSet模板更新后,只有手动的删除某一个对应的pod,此节点Pod才会被更新。
DaemonSet Controller负责根据配置创建Pod
DaemonSet Controller跟踪pod状态,根据配置及其重试pod或者继续创建
DaemonSet Controller会自动添加affinity&label来跟踪对应的pod,并根据配置在每个节点或者适合的部分节点创建pod
pod的配置管理包括:
可变配置(configmap),
敏感信息(secret),
身份认证(serviceAccount),
资源配置(spec.containers[].Resources.limits/requests),
安全管控(spec.containers[].securitycontext),
前置校验(spec.Initcontainers)。
主要管理容器运行所需的配置文件,环境变量,命令行参数等可变配置。用于解耦容器镜像和可变配置,从而保障工作负载(pod)的可移植性。
kubectl create configmap kube-flannel-cfg --from-file=configure-pod-container/configmap/cni-conf.json -n kube-system kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
configmap文件大小限制: 1MB (etcd要求)
pod只能引用相同namespace中的configmap
pod引用的configmap不存在时,pod无法创建成功。即pod创建前需要先创建好configmap.
使用envFrom从configmap来配置环境变量时,如果configmap中的某些key认为无效(比如key中带有数字),该环境变量将不会注入容器,但是pod可以正常创建。
只有通过k8s api创建的pod才能使用configmap, 其他方式创建的pod(如manifest创建的static pod)不能使用configmap.
在集群中用于存储密码,token等敏感信息用的资源对象。其中敏感数据采用base-64编码保存,相比存储在明文的configmap中更规范和安全。
kubectl create secret generic myregistrykey --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret文件大小限制: 1MB
secret虽然采用base-64编码,但可以简单解码查看原始信息。对secret加密有较强需求,可以考虑结合k8s+vault来解决敏感信息的加密和权限管理。
secret最佳实践:因为list/watch的一般处理将获取到namespace下所有的secret,因此不建议采取list/watch的方式获取secret信息,而推荐使用GET,从而减少更多secret暴露的可能性。
主要用于解决pod在集群中的身份认证问题。其中认证使用的授权信息,则利用前面讲到的secret(type=kubernetes.io/service-account-token)进行管理。
实现原理:
pod创建时admission controller会根据指定的service account(默认为default)把对应的secret挂载到容器中固定的目录下(/var/run/secrets/kubernetes.io/serviceaccount).
当pod访问集群时,可以默认利用secret其中的token文件来认证pod的身份。
默认token的认证信息为:
Group: system:serviceaccounts:[namespaces-name]
User: system:serviceaccount:[namespace-name]:[pod-name]
如果一个pod中某一个容器异常退出,被kubelet拉起如何保证之前产生的重要数据不丢?
同一个pod的多个容器如何共享数据?
k8s volume类型:
1)本地存储: emptydir/hostpath
2)网络存储:
in-tree: awsEBS/gcePersistentDisk/nfs...
out-tree: flexvolume/csi volume plugin
3)projected volume: secret/configmap/downwardAPI/serviceAccountToken
4)pvc、pv
pod中声明的volume的生命周期与pod相同,以下常见场景:
pod销毁重建(dp管理的pod镜像升级)
宿主机故障迁移(statefulset管理的pod带远程volume迁移)
多pod共享同一个数据volume
数据volume快照,resize等功能的扩展实现
一个PV可以设置多个访问策略,PVC与PV bound时,PV controller会优先找到AccessModes列表最短并且匹配的PVC Acessmodes列表的pv集合,然后从集合中找到capacity最小且符合pvc size需求的pv对象。
职责分离,PVC中只用声明自己需要的存储size、access mode(单node独占还是多node共享?只读还是读写访问?)等业务真正关心的存储需求(不用关心存储实现细节),PV和其对应的后端存储信息则由交给集群管理员统一运维和管控,安全访问策略更容易控制。
PVC简化了用户对存储的需求,pv才是存储的实际信息承载体。通过kube-controller-manager中的PersisentVolumeController将PVC与合适的pv bound到一起,从而满足用户对存储的实际需求。
PVC像是面向对象编程中抽象出来的接口,PV是接口对应的实现。
前者需要集群管理员提前规划或预测存储需求,后者可以通过stroageclass创建不同的PV模板,user无需关心这些PV的细节,k8s结合PVC和storageclasss两者动态创建PV对象。
StorageClassName:
pvc 可通过该字段找到相同值的PV(静态provisioning)
也可通过该字段对应的storageclass从而动态provisioning新PV对象。
说明:到达released状态的PV无法根据reclaim policy回到available状态而再次bound新的PVC。
此时,如果想复用原来PV对应的存储中的数据,只有两种方式:
复用old pv中记录的存储信息,新建pv对象。
直接从pvc对象复用,即不unbound pvc和pv。(即:statefulset处理存储状态的原理)
用户创建一个pvc对象,会被csi-provisioner watch到,结合pvc对象以及在其中声明的storageclass,通过grpc调用csi plugin. 会请求云存储服务并实际申请pv存储。
之后pvcontroller 会将pvc和申请到的pv做bound,之后这块pv就可被使用了。
当用户创建pod对象,通过kube-scheduler调度到具体的node节点后,通过csi-node-server将申请的pvmount到pod可以使用的路径,然后再create/start container.
create /attach/ mount 三个阶段:
本质问题
PV在Binding或者Dynamic Provisioning时,并不知道使用它的pod会被调度到哪些Node上?但PV本身的访问对node的“位置”(拓扑)有限制。
流程改进
Binding/Dynamic Provisioning PV的操作Delay到Pod调度结果确定之后做,好处:
对于pre-provisioned的含有node affinity的pv对象,可以在pod运行的node确认之后,根据node找到合适的pv对象,然后与pod中使用的pvc binding,保证pod运行的node满足pv对访问“位置”的要求。
对于dynamic provisioning PV场景,在pod运行的node确认之后,可以结合node的“位置”信息创建可被该node访问的pv对象。
k8s相关组件改进
PV controller: 支持延迟binding操作
dynamic pv provisioner: 动态创建pv时要结合pod待运行的node的“位置”信息
scheduler: 选择node时要考虑pod的pvc binding需求,也就是要结合pre-provisioned 的PV 的node affinity以及dynamic provisioning时 pvc指定的storageclass.allowedTopologies的限制
当该PVC对象被创建之后由于对应StorageClass的BindingMode为 WaitForFirstConsumer并不会马上动态生成PV对象,而是要等到使用该PVC对象的第一个pod调度出结果之后,而且kube-scheduler在调度pod的时候会去选择满足storageclass.allowedTopologies中指定的拓扑限制的nodes.
用户创建一个包含pvc的pod(使用动态存储卷);
PV controller发现这个pvc处于待绑定状态,调用volume plugin(in-tree 或 out-of-tree)创建存储卷,并创建PV对象;并将创建的PV与pvc绑定。
Scheduler根据pod配置、节点状态、pv配置等信息,把pod调度到某个node节点上。
AD controller发现pod和pvc处于待挂载状态,调用volume plugin(in-tree 或 out-of-tree)实现设备挂载到目标节点(/dev/vdb);
在node节点上,kubelet(volume manager)等待设备挂载完成,通过volume plugin将设备挂载到指定目录:/var/lib/kubelet/pods/646154cf-xxx-xxx-xxx/volumes/alicloud~disk/pv-disk
kubelet在被告知挂载目录准备好后,启动pod中的containers,用docker -v方式(bind mount)将已经挂载到本地的卷映射到容器中。
主要概念:
PersistentVolume: 持久化存储卷,详细定义预挂载存储空间的各项参数;无namespace限制,一般由集群管理员创建维护PV;
PersistentVolumeClaim: 持久化存储卷声明,用户使用的存储接口,对存储细节无感知,属于某namespace.
StorageClass: 存储类,创建PV存储的模板类,即系统会按照StorageClass定义的存储模板创建存储卷(包括真实存储空间和PV对象);
主要任务:
PV、PVC声明周期管理:创建、删除PV对象;负责PV、PVC的状态迁移;
绑定PVC、PV对象:一个pvc必须与一个PV绑定后才能被应用使用;pv-controller会根据绑定条件和对象状态对pv、pvc进行bound、unbound操作。
ClaimWorker:
实现PVC的状态迁移;
通过系统标签“pv.kubernetes.io/bind-completed"来标识一个pvc是为bound状态;
当pvc为unbound时,触发PV筛选逻辑,如果找到合适的PV则bound,如果找不到则触发provision。(如果不是in-tree provisioner则等待)
VolumeWorker:
实现PV的状态迁移;
通过ClaimRef来判断PV是bound还是released,pv状态为released时,若reclaim为delete,则执行删除逻辑。
AD controller负责将数据卷挂载/卸载到特定节点上;
核心对象:DesiredStateOfWorld, ActualStateOfWorld
核心逻辑:Reconcile, desiredStateOfWorldPopulator
DesiredStateOfWorld: 集群中预期要达到的数据卷挂载状态
ActualStateOfWorld:集群中实际存在的数据卷挂载状态
desiredStateOfWorldPopulator:根据卷挂载状态,更新DSW,ASW数据;
reconcile: 根据DSW, ASW对象状态,轮询执行attach, detach操作。
它是kubelet中的一个manager,调用本节点Volume的attach/detach/mount/umount操作;
volumeManager实时扫描本节点的pod状态,对需要更新状态的volume通过调用volume plugin执行相应操作。
volumeManager根据存储类型需要还会执行一些公共操作,例如:块设备的格式化、挂载块设备到公共目录等。
数据结构:
VolumePluginMgr:管理本节点上in-tree/out-of-tree的插件列表;
desiredStateOfWorld: 记录节点上数据卷的期望挂载状态;
actualStateOfWorld:记录节点上数据卷的实际挂载状态;
核心逻辑:
desiredStateOfWorldPopulator:同步包含数据卷的pod状态;
Reconciler:循环执行attach/detach/mount/unmount, 具体操作通过调用volume plugin实现的接口完成。
AD controller还是volume manager做attach/detach操作?
通过--enable-controller-attach-detach来控制
根据不同的存储类型提供数据卷Provision, Delete, Attach, Detach, Mount, Unmount具体操作实现,是多种具体存储类型的功能抽象接口。
关于“kubernetes核心原理是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“kubernetes核心原理是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。