您现在的位置是:首页 >技术教程 >k8s知识整理(继续整理中)网站首页技术教程

k8s知识整理(继续整理中)

跨行菜鸟运维 2023-04-26 11:55:08
简介k8s知识整理(继续整理中)


k8s知识整理

k8s组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R1JYC6Qv-1682407168072)(C:Users见智AppDataRoamingTypora	ypora-user-imagesimage-20230421162150862.png)]

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–>后端反向代理前端静态文件

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。