您现在的位置是:首页 >学无止境 >k8s知识整理(继续整理中)网站首页学无止境
k8s知识整理(继续整理中)
文章目录
k8s知识整理
k8s组件
master节点
kube-apiserver
- 整个集群的网关。提供了集群资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制。
kube-scheduler
- 负责资源的调度,按照预定的策略将Pod调度到相应的机器上。
kube-controller-manager
- 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等。
etcd
- 保存了整个集群的状态,并提供了监听(watch)机制,用于监听和向apiserver推送变更。
work节点
kube-proxy
- 负责未service提供cluster内部的服务发现和负载均衡
kubelet
- 负责维持容器的生命周期,同时也负责vloume(CVI)和网络(CNI)的管理
- 从apiserver接收关于pod对象的配置信息并确保它们处于期望的状态,并在apiserver上注册当前工作节点,定期向master汇报节点资源使用情况,并通过cadvisor监控容器和节点的资源占用情况
container runtime
- 负责镜像管理和Pod和容器的真正运行。默认的容器运行时为docker
add ons
CoreDNS
- 提供DNS服务,默认使用CoreDNS为集群提供服务注册和服务发现的动态名称解析服务
ingress controller
- 为集群外网访问提供方法
- nginx-ingress
- traefik-ingress
Pod常用控制器
##### Deployment
- 部署无状态应用
##### StatefullSet
- 部署有状态应用
##### Job
- 一次性的执行任务
##### Cronjob
- 周期性的执行任务
##### DaemonSet
- 一次部署,所有node节点都会部署
- fluentd
- prometheus node exporter
##### ReplicaSet
保证指定数量的pod运行,并提供pod数据变更、镜像版本变更
##### Horizontal Pod Autoscaler
自动扩缩容pod
k8s pod创建调度过程
1. 用户使用create yaml创建pod,请求给API Server,API Server将yaml中的属性信息(meta data)写入ETCD
2. API Server触发watch机制准备创建pod,信息转发给Scheduler,Scheduler使用调度算法选择node,Scheduler将node信息给APIServer,APIServer将绑定的node信息写入ETCD
3. API Server又通过watch机制,调用Kubelet,指定pod信息,触发docker run命 令创建容器
4. 创建完成之后反馈给Kubelet, Kubelet又将pod的状态信息给API Server,
5. API Server将pod的状态信息写入ETCD
k8s pod删除过程
1. Pod 被删除,状态变为 Terminating。从 API 层面看就是 Pod metadata 中的 deletionTimestamp 字段会被标记上删除时间。
2. kube-proxy watch 到了就开始更新转发规则,将 Pod 从 service 的 endpoint 列表中摘除掉,新的流量不再转发到该 Pod。
3. kubelet watch 到了就开始销毁 Pod。
3.1. 如果 Pod 中有 container 配置了 preStop Hook ,将会执行。
3.2. 发送 SIGTERM 信号给容器内主进程以通知容器进程开始优雅停止。
3.3. 等待 container 中的主进程完全停止,如果在 terminationGracePeriodSeconds 内 (默认 30s) 还未完全停止,就发送 SIGKILL信号将其强制杀死。
3.4. 所有容器进程终止,清理 Pod 资源。
3.5. 通知 APIServer Pod 销毁完成,完成 Pod 删除。
k8s 灰度发布(金丝雀部署)
-
ingress-nginx
-
基于Request Header的流量切分,适用于灰度发布以及AB测试场景。
-
基于Cookie的流量切分,适用于灰度发布以及AB测试场景。
-
基于Query Param的流量切分,适用于灰度发布以及AB测试场景。
-
基于服务权重的流量切分,适用于蓝绿发布场景。
-
Nginx Ingress Controller通过下列
canary-*
Annotation来支持应用服务的灰度发布机制。 -
不同灰度方式的优先级由高到低为:
canary-by-header`>`canary-by-cookie`>`canary-weight
Annotation 说明 适用的ACK Nginx Ingress Controller版本 nginx.ingress.kubernetes.io/canary 必须设置该Annotation值为 true
,否则其它规则将不会生效。取值:true
:启用canary
功能。false
:不启用canary
功能。≥v0.22.0 nginx.ingress.kubernetes.io/canary-by-header 表示基于请求头的名称进行灰度发布。请求头名称的特殊取值: always
:无论什么情况下,流量均会进入灰度服务。never
:无论什么情况下,流量均不会进入灰度服务。若没有指定请求头名称的值,则只要该头存在,都会进行流量转发。≥v0.22.0 nginx.ingress.kubernetes.io/canary-by-header-value 表示基于请求头的值进行灰度发布。需要与 canary-by-header
头配合使用。≥v0.30.0 nginx.ingress.kubernetes.io/canary-by-header-pattern 表示基于请求头的值进行灰度发布,并对请求头的值进行正则匹配。需要与 canary-by-header
头配合使用。取值为用于匹配请求头的值的正则表达式。≥v0.44.0 nginx.ingress.kubernetes.io/canary-by-cookie 表示基于Cookie进行灰度发布。例如, nginx.ingress.kubernetes.io/canary-by-cookie: foo
。Cookie内容的取值:always
:当foo=always
,流量会进入灰度服务。never
:当foo=never
,流量不会进入灰度服务。只有当Cookie存在,且值为always
时,才会进行流量转发。≥v0.22.0 nginx.ingress.kubernetes.io/canary-weight 表示基于权重进行灰度发布。取值范围:0~权重总值。若未设定总值,默认总值为100。 ≥v0.22.0 nginx.ingress.kubernetes.io/canary-weight-total 表示设定的权重总值。若未设定总值,默认总值为100。 ≥v1.1.2
-
-
kubectl rollout pause
- 待第一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一小部分新版本的应用,主体部分还是旧的版本。然后,再根据用户特征精心筛选出小部分用户的请求路由至新版本的Pod应用,并持续观察其是否能稳定地按期望的方式运行。
-
kubectl rollout resume
- 恢复暂停的Deployment,继续部署
k8s 蓝绿部署
- 蓝绿发布 新旧版共存,靠切换流量完成更新
k8s持久化
nfs
hostpath
cm
secret
empdir
cephfs
...
service的网络类型
clusterIP
- 默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP,适用于cluster内部网络访问Service。会自动分配一个IP地址赋予Service。
NodePort
- 在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过: NodePort来访问该服务。
LoadBalancer
-
在NodePort的基础上,借助Cloud Provider创建一个外部负载均衡器,并将请求转发到NodePort
-
默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP,适用于cluster内部网络访问Service。k8s会自动分配一个IP地址赋予Service。
pod常见状态
containcreating:
正在创建pod
ImagePullBackOff:
镜像拉取失败
pending:
调度失败
资源不足
pod 不满足node上有污点
不满足 nodeSelector 与 affinity
error:
至少有一个容器启动失败
cm、pvc等资源是否存在
running:
pod正常启动
crashloopbackoff:
pod创建失败,kubelet正在重启pod
Unschedulable:
Pod不能被调度,kube-scheduler没有匹配到合适的node节点。
PodScheduled:
pod正处于调度中,在kube-scheduler刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node。
Failed:
Pod中有容器启动失败而导致pod工作异常。
Unknown:
由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误。
Initialized:
所有pod中的初始化容器已经完成了
ContainerCreating:
正在创建
Running:
Pod内部的容器已经被创建并且启动。
Ready:
表示pod中的容器已经可以提供访问服务。
Completed::
运行完成
Error:
pod启动过程中发生错误
NodeLost:
Pod所在节点失联
Waiting:
Pod等待启动
Terminating:
Pod正在被销毁
CrashLoopBackOff:
pod创建失败,但是kubelet正在将它重启
ErrImagePull:
镜像拉取出错,超时或下载被强制终止
ImagePullBackOff:
Pod所在的node节点下载镜像失败
Pending:
正在创建Pod但是Pod中的容器还没有全部被创建完成=处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载等。
InvalidImageName:
node节点无法解析镜像名称导致的镜像无法下载
ImageInspectError:
无法校验镜像,镜像不完整导致
ErrImageNeverPull:
策略禁止拉取镜像,镜像中心权限是私有等
RegistryUnavailable:
镜像服务器不可用,网络原因或harbor宕机
CreateContainerConfigError:
不能创建kubelet使用的容器配置
CreateContainerError:
创建容器失败
RunContainerError:
pod运行失败,容器中没有初始化PID为1的守护进程等
ContainersNotInitialized:
pod没有初始化完毕
ContainersNotReady:
pod没有准备完毕
ContainerCreating:
pod正在创建中
PodInitializing:
pod正在初始化中
DockerDaemonNotReady:
node节点decker服务没有启动
NetworkPluginNotReady:
网络插件没有启动
...
pod的亲和性
Pod与Node的关系调度:
1、节点选择器调度: nodeSelector/nodeName
- 常规性调度方式,通过 pod.spec.nodeSelector 或 pod.spec.nodeName 来将 Pod 调度到指定的节点上。
2、节点亲和性调度:NodeAffinity
-
亲和性又分为 硬亲和性 和 软亲和性 这两种调度,通过 pod.spec.affinity.nodeAffinity 字段指定,作用是根据Node上的标签来约束Pod可以调度到哪些节点上。
-
requiredDuringSchedulingIgnoredDuringExecution:
-
硬亲和性,意思是将Pod调度至节点上时,挑选出来的Node,必须要满足这个字段定义的条件,如果集群中找不到满足这样条件的Node时,Pod会调度失败。
-
preferredDuringSchedulingIgnoredDuringExecution:
软亲和性,意思是将Pod调度至节点上时,会优先挑选出满足条件的Node,如果集群中找不到满足这样条件的Node时,也没关系,Pod仍然可以被调度出去。
POD与POD的关系调度:
1、Pod亲和性调度:PodAffinity
通过 pod.spec.affinity.podAffinity 字段指定:
-
requiredDuringSchedulingIgnoredDuringExecution:硬性要求,必须和某些POD调度在一起
-
preferredDuringSchedulingIgnoredDuringExecution:软性要求,优先和某些POD调度在一起
spec:
containers:
- name: myapp2
image: ikubernetes/myapp:v2
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: #选择与哪个POD具有亲和性
matchExpressions: #匹配表达式
- key: app
operator: In
values:
- podaffinity-myapp1 #表示这个pod要跟一个带有app:podaffinity-myapp1标签的pod放在同一个位置上
topologyKey: kubernetes.io/hostname #通过节点kubernetes.io/hostname标签来判断节点是否在同一个位置
2、Pod反亲和性调度:PodAntAffinity
通过 pod.spec.affinity.podAntiAffinity 字段指定:
-
requiredDuringSchedulingIgnoredDuringExecution:硬性要求,禁止和某些POD调度在一起
-
preferredDuringSchedulingIgnoredDuringExecution:软性要求,优先不跟某些POD调度在一起
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: #选择跟哪个POD不亲和
matchExpressions: #匹配表达式
- key: name
operator: In
values:
- podaffinity-myapp1 #与带有name:podaffinity-myapp1标签的pod具有反亲和性,不能放在同一个位置上
topologyKey: zone #通过节点的zone标签判断是否为同一个位置
Node污点容忍调度:
还有一种类型调度就是,通过给Node打一些标记,来限制Pod调度到某些Node上,这些标记被称为Taints(污点),通过node.spec.taints字段设置。
当Node被打上标记或污点后,除非这个Pod明确声明能够容忍这些污点,否则Pod是无法在这个有污点的node上运行的,这个容忍是通过pod.spec.tolerations字段定义的。
- 命令行操作
# 设置污点
kubectl taint nodes <node-name> key=value:effect
# 删除污点
kubectl taint nodes <node-name> key:effect-
# 为node1打上污点标签
kubectl taint nodes node1 k1=v1:NoSchedule
# 查看节点taint
kubectl describe nodes node1 | grep Taints
- 使用
apiVersion: v1
kind: Pod
metadata:
name: myweb
spec:
containers:
- name: myweb
image: nginx
tolerations:
- key: "k1"
operator: "Exists"
value: "v1"
effect: "NoSchedule"
- 解释
node.spec.taints: 给node设置污点,每个污点有一个key和value作为标签,其中value可以为空,effect描述污点的作用
key: 污点标签名称。The taint key to be applied to a node.
value: 污点标签对应的值
effect: 污点作用,有三个选项 NoSchedule, PreferNoSchedule, NoExecute
pod.spec.tolerations:
effect: 匹配taint effect,若为空表示匹配所有effect
key: 匹配taint key
operator: 有Exists与Equal两个值,Exists表示只要key在就可以调度,Equal(等值比较)必须是value也要相同。可以为空,匹配所有。
value: 匹配taint value。当operator为Exists时,value可以为空
effect:
NoSchedule: 表示不会将Pod调度到带有该污点的Node上, 但是已经存在的pod不会被驱逐
PreferNoSchedule: 表示尽量避免将Pod调度到带有该污点的Node上,但这不是必需的
NoExecute:表示不会将Pod调度到带有该污点的Node上,同时在该Node上已经存在的Pod,若没有对应的tolerations,也会被驱逐出去
pod的资源限制
limit:
cpu:
memory:
request:
cpu:
memory:
pod的健康监测
探针:
readinessProbe:
livenessProbe:
#探针是由 kubelet 对容器执行的定期诊断,以保证Pod的状态始终处于运行状态,要执行诊断,kubelet 调用由容器实现的Handler(处理程序),也称为Hook(钩子)。有三种类型的处理程序:
exec: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
tcpSocket: 对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
httpGet: 对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的
探针类型
startupProbe(启动探针): 使用启动探测器来了解应用容器何时启动。 如果配置了这类探测器,你就可以控制容器在启动成功后再进行存活性和就绪态检查, 确保这些存活、就绪探测器不会影响应用的启动。 如果启动探测失败,则kubelet将杀死容器,容器将按照重启策略进行下一步操作,如果容器没有提供启动探测,则默认状态为成功
livenessProbe(存活探针): 使用存活探测器来控制是否重启pod。检测容器是否正在运行,如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为 Success。
readinessProbe(就绪探针): 使用就绪探测器可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址,初始延迟之前的就绪状态默认为Failure(失败),如果容器不提供就绪探针,则默认状态为 Success,就绪探针用于控制pod是否添加至service。
探针通用配置参数
initialDelaySeconds: 初始化延迟时间,告诉kubelet在执行第一次探测前应该等待多少秒,默认是0秒,最小值是0
periodSeconds: 探测周期间隔时间,指定了kubelet应该每多少秒秒执行一次存活探测,默认是 10 秒。最小值是 1
timeoutSeconds: 单次探测超时时间,探测的超时后等待多少秒,默认值是1秒,最小值是1。
successThreshold: 从失败转为成功的重试次数,探测器在失败后被视为成功的最小连续成功数,默认值是1存活探测的这个值必须是1,最小值是 1。
failureThreshold: 从成功转为失败的重试次数,当Pod启动了并且探测到失败,Kubernetes的重试次数,存活探测情况下的放弃就意味着重新启动容器,就绪探测情况下的放弃Pod 会被打上未就绪的标签,默认值是3,最小值是1。
k8s集群外网访问过程
外部访问–>域名–>负载均衡–>ingress-controller–>ingress–>service–>pod–>nginx–>后端反向代理前端静态文件