k8s基础原创
# apiVersion
kubectl api-versions
alpha 名称中带有alpha的API版本是进入Kubernetes的新功能的早期候选版本。这些可能包含错误,并且不保证将来可以使用。
beta API版本名称中的beta表示测试已经超过了alpha级别,并且该功能最终将包含在Kubernetes中。 虽然它的工作方式可能会改变,并且对象的定义方式可能会完全改变,但该特征本身很可能以某种形式将其变为Kubernetes。
stable 稳定的apiVersion这些名称中不包含alpha或beta。 它们可以安全使用。
v1 这是Kubernetes API的第一个稳定版本。 它包含许多核心对象。
apps/v1 apps是Kubernetes中最常见的API组,其中包含许多核心对象和v1。 它包括与在Kubernetes上运行应用程序相关的功能,如Deployments,RollingUpdates和ReplicaSets。
autoscaling/v1 此API版本允许根据不同的资源使用指标自动调整容器。此稳定版本仅支持CPU扩展,但未来的alpha和beta版本将允许您根据内存使用情况和自定义指标进行扩展。
batch/v1 batchAPI组包含与批处理和类似作业的任务相关的对象(而不是像应用程序一样的任务,如无限期地运行Web服务器)。 这个apiVersion是这些API对象的第一个稳定版本。
batch/v1beta1 Kubernetes中批处理对象的新功能测试版,特别是包括允许您在特定时间或周期运行作业的CronJobs。
certificates.k8s.io/v1beta1 此API版本添加了验证网络证书的功能,以便在群集中进行安全通信。 您可以在官方文档上阅读更多内容。
extensions/v1beta1 此版本的API包含许多新的常用Kubernetes功能。 部署,DaemonSets,ReplicaSet和Ingresses都在此版本中收到了重大更改。
policy/v1beta1 此apiVersion增加了设置pod中断预算和pod安全性新规则的功能
rbac.authorization.k8s.io/v1 此apiVersion包含Kubernetes基于角色的访问控制的额外功能。这有助于您保护群集
# resourceVersion
这个版本号是一个 K8s 的内部机制,用户不应该假设它是一个数字或者通过比较两个版本号大小来确定资源对象的新旧,唯一能做的就是通过比较版本号相等来确定对象是否是同一个版本(即是否发生了变化)。而 resourceVersion 一个重要的用处,就是来做 update 请求的版本控制。 kube-apiserver 会校验用户 update 请求提交对象中的 resourceVersion 一定要和当前 K8s 中这个对象最新的 resourceVersion 一致,才能接受本次 update。否则,K8s 会拒绝请求,并告诉用户发生了版本冲突(Conflict)。
# Patch 机制
json patch 在 json patch 中我们要指定操作类型,比如 add 新增还是 replace 替换,另外在修改 containers 列表时要通过元素序号来指定容器。
merge patch(默认) merge patch 无法单独更新一个列表中的某个元素,因此不管我们是要在 containers 里新增容器、还是修改已有容器的 image、env 等字段,都要用整个 containers 列表来提交 patch:
strategic merge patch 在我们 patch 更新 containers 不再需要指定下标序号了,而是指定 name 来修改,K8s 会把 name 作为 key 来计算 merge。 目前 strategic 策略只能用于原生 K8s 资源以及 Aggregated API 方式的自定义资源,对于 CRD 定义的资源对象,是无法使用的。
# externalTrafficPolicy,跳过SNAT
对于Service, 如果指定类型为 NodePort, 那么这个端口会在集群的所有 Node 上打开,即使这个Node 上面没有这个pod
Kube-proxy转发时会保留源IP。即:容器收到的报文,看到源IP地址还是用户的。
缺点是负载均衡可能不是很好,因为一旦容器实例分布在多个节点上,它只转发给本机,不跨节点转发流量。当然,少了一次转发,性能会相对好一丢丢。
注:这种模式下的Service类型只能为外部流量,即:LoadBalancer 或者 NodePort 两种,否则会报错
# 存储空间资源限制ephemeral-storage
在每个Kubernetes的节点上,kubelet的根目录(默认是/var/lib/kubelet)和日志目录(/var/log)保存在节点的主分区上,这个分区同时也会被Pod的EmptyDir类型的volume、容器日志、镜像的层、容器的可写层所占用。
resources:
requests:
cpu: 1
memory: 2048Mi
ephemeral-storage: 2Gi
limits:
cpu: 2
memory: 2048Mi
ephemeral-storage: 5Gi
2
3
4
5
6
7
8
9
# 使用限制:
- 只要Root Dir和kubelet --root-dir在一个分区,就能起作用
- 如果运行时指定了别的独立的分区,比如修改了docker的镜像层和容器可写层的存储位置(默认是/var/lib/docker)所在的分区,将不再将其计入ephemeral-storage的消耗。
# 效果
在容器写入超过存储限制时就会被驱逐掉 teststorage 0/1 Evicted 0 1m
# Qos 服务质量等级
Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。 Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。 BestEffort:容器必须没有任何内存或者 CPU 的限制或请求。
三个级别的优先级从低到高的顺序是: BestEffort pods -> Burstable pods -> Guaranteed pods
可压缩资源:如CPU,即使cpu 超配,也可以划分时间片运行,只是运行变慢,进程不会挂。 不可压缩资源:Memory/Storage,内存不同于CPU,系统内存不足时,会触发 OOM杀死进程,按照oom score 来确定先kill谁,oom_score_adj值越高,被kill 的优先级越高。
# ResourceVersion
绝大部分情况下,apiserver 直接从本地缓存提供服务(因为它缓存了集群全量数据); 某些特殊情况,例如, 客户端明确要求从 etcd 读数据(追求最高的数据准确性) apiserver 本地缓存还没建好 对于非结构化的数据存储系统来说,LIST操作通常都是非常重量级的,不仅占用大量的 磁盘 IO、网络带宽和 CPU。K8s的LIST请求大部分都应该被apiserver挡住,从它的本地缓存提供服务,但如果使用不当,就会跳过缓存直接到达 etcd,有很大的稳定性风险。
Get请求:GetOptions{}与ListOption{}一样,不设置ResourceVersion=0会导致 apiserver去etcd拿数据,应该尽量避免。
When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history.
When specified for list:
2
- if unset, then the result is returned from remote storage based on quorum-read flag;
- if it's 0, then we simply return what we currently have in cache, no guarantee;
- if set to non zero, then the result is at least as fresh as given rv. 未指定ResourceVersion,获取最新数据;ApiServer收到这个类型的读请求后,会向Etcd发出线性读请求获取etcd最新数据 ResourceVersion=“0”,获取ApiServer的缓存数据,有可能是过期数据。 ResouceVersion为非0的字符串,获取不小于该version的数据。 默认是未指定ResouceVersion。 如果客户端没传ListOption,则初始化一个默认值,其中的ResourceVersion设置为空字符串, 这将使apiserver从etcd拉取数据来返回给客户端,而不使用本地缓存(除非本地缓存还没有建好)。 resourceVersion=0将导致limit被忽略,也就是说, 虽然指定了limit,但请求会返回全量数据。 从 v1.19 版本开始,Kubernetes API 服务器支持 list 请求的 resourceVersionMatch 参数
# 调优建议
List 请求默认设置 ResourceVersion=0 优先使用 namespaced API 通过label/field selector做过滤
http://arthurchiao.art/blog/k8s-reliability-list-data-zh https://www.pudn.com/news/62c14ac49f2d63494a8b7887.html https://kubernetes.io/zh-cn/docs/reference/_print/
# 主机网络hostNetwork
- Pod使用主机网络只需要在配置中添加hostNetwork: true即可
- 部署后可以看到Pod的IP与节点的IP相同,说明Pod直接使用了主机网络。
- Pod直接使用主机的网络会占用宿主机的端口,Pod的IP就是宿主机的IP,使用时需要考虑是否与主机上的端口冲突
- 由于占用主机端口,使用Deployment部署hostNetwork类型Pod时,要注意Pod的副本数不要超过节点数量,否则会导致一个节点上调度了多个Pod,Pod启动时端口冲突无法创建
# pod的重启策略
Always:但凡pod对象终止就重启,此为默认策略。
OnFailure:仅在pod对象出现错误时才重启
# 删除一个Pod会发生什么事情?
Kube-apiserver会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;
关闭流程如下: 1、 pod从service的endpoint列表中被移除; 2、 如果该pod定义了一个停止前的钩子,其会在pod内部被调用,停止钩子一般定义了如何优雅的结束进程; 3、 进程被发送TERM信号(kill -14) 4、 当超过优雅退出的时间后,Pod中的所有进程都会被发送SIGKILL信号(kill -9)。
# 镜像拉取策略 ImagePullPolicy
Always:不管镜像是否存在都会进行一次拉取 Never:不管镜像是否存在都不会进行拉取 IfNotPresent:只有镜像不存在时,才会进行镜像拉取
# 为容器配置hosts
# 配置在二级ipsec下,和cointariners同级
spec:
...
spec:
hostAliases:
- ip: "172.16.0.12"
hostnames:
- "api.cc.pro"
containers:
- name: cc-x
2
3
4
5
6
7
8
9
# 容器修改hostname
spec:
hostname: busybox-1
subdomain: busybox-subdomain
2
3
因为pod的访问域名是hostname.custom-subdomain.default.svc.cluster.local
所以该 Pod 的域名是 busybox-1.busybox-subdomain.default.svc.cluster.local。
# kubernetes 指定节点nodeName与NodeSelector
Pod.spec.nodeName用于强制约束将Pod调度到指定的Node节点上,这里说是“调度”,但其实指定了nodeName的Pod会直接跳过Scheduler的调度逻辑,直接写入PodList列表,该匹配规则是强制匹配。 Pod.spec.nodeSelector是通过kubernetes的label-selector机制进行节点选择,由scheduler调度策略MatchNodeSelector进行label匹配,调度pod到目标节点,该匹配规则是强制约束。启用节点选择器的步骤为:Node添加label标记>Pod定义中添加nodeSelector