yum list kubelet --showduplicates | sort -r
第一章, 第二章
1. HPA 与之前的 RC,Deployment 一样, 也属于一种 Kubernetes 资源对象. 通过追踪分析指定 RC 控制的所有目标 Pod 的负载变化情况, 来确定是否需要有针对性地调整目标 Pod 的副本数量, 这是 HPA 的实现原理. HPA 有以下两种方式作为 Pod 负载的度量指标: CPUUtilizationPercentage 应用程序自定义的度量指标, 比如服务在每秒内的相应请求数(TPS 或 QPS).CPUUtilizationPercentage 是一个算术平均值, 即目标 Pod 所有副本自 身的 CPU 利用率的平均值. 一个 Pod 自身的 CPU 利用率是该 Pod 当前 CPU 的使用量除以它的 Pod Request 的值, 比如定义一个 Pod 的 Pod Request 为 0.4, 而当前 Pod 的 CPU 使用量为 0.2, 则它的 CPU 使用率为 50%, 这样就 可以算出一个 RC 控制的所有 Pod 副本的 CPU 利用率的算术平均值了. 在 CPUUtilizationPercentage 计算过程中使用到的 Pod 的 CPU 使用量通常是 1min 内的平均值
2. StatefulSet 特性: StatefulSet 里的每个 Pod 都有稳定, 唯一的网络标识, 可以用来 发现集群内的其他成员. StatefulSet 控制的 Pod 副本的启停顺序是受控的, 操作第 n 个 Pod 时, 前 n-1 个 Pod 已经是运行且准备好的状态. StatefulSet 里的 Pod 采用稳定的持久化存储卷, 通过 PV 或 PVC 来 实现, 删除 Pod 时默认不会删除与 StatefulSet 相关的存储卷(为了保证数 据的安全)StatefulSet 除了要与 PV 卷捆绑使用以存储 Pod 的状态数据, 还要与 Headless Service 配合使用, 即在每个 StatefulSet 定义中都要声明它属于 哪个 Headless Service.Headless Service 与普通 Service 的关键区别在于, 它没有 Cluster IP, 如果解析 Headless Service 的 DNS 域名, 则返回的是该 Service 对应的全部 Pod 的 Endpoint 列表. StatefulSet 在 Headless Service 的 基础上又为 StatefulSet 控制的每个 Pod 实例都创建了一个 DNS 域名: podname.headless.service name
3. PV: accessModes 属性, 目前有以下类型: ReadWriteOnce: 读写权限, 并且只能被单个 Node 挂载 ReadOnlyMany: 只读权限, 允许被多个 Node 挂载 ReadWriteMany: 读写权限, 允许被多个 Node 挂载
PV 是有状态的对象, 它的状态有以下几种: Available: 空闲状态. Bound: 已经绑定到某个 PVC 上. Released: 对应的 PVC 已经被删除, 但资源还没有被集群收 回. Failed:PV 自动回收失败. Reclaiming: 用户删除 PVC 释放对 PV 的占用后, 系统根据 PV 的 "reclaim policy" 决定对 PV 执行何种回收操作. 目前,"reclaim policy" 有三种方式: Retained,Recycled,Deleted.Retained: 保护被 PVC 释放的 PV 及其上数据, 并将 PV 状态改成 "released", 不将被其它 PVC 绑定. 集群管理员手动通过如下步骤释放存储资源: 手动删除 PV, 但与其相关的后端存储资源如 (AWS EBS, GCE PD, Azure Disk, or Cinder volume) 仍然存在. 手动清空后端存储 volume 上的数据. 手动删除后端存储 volume, 或者重复使用后端 volume, 为其创建新的 PV Delete: 删除被 PVC 释放的 PV 及其后端存储 volume. 对于动态 PV 其 "reclaim policy" 继承自其 "storage class", 默认是 Delete. 集群管理员负责将 "storage class" 的 "reclaim policy" 设置成用户期望的形式, 否则需要用户手动为创建后的动态 PV 编辑 "reclaim policy"
4. kubelet 的职责在于通过 RPC 管理容器的生命周期, 实现容器生命周 期的钩子, 存活和健康监测, 以及执行 Pod 的重启策略等
5. 目前还有一个潜在问题是, kubelet 处理所有的请求连接, 使其有成 为 Node 通信瓶颈的可能. 在设计 CRI 时, 要让容器运行时能够跳过中间 过程. 容器运行时可以启动一个单独的流式服务来处理请求(还能对 Pod 的资源使用情况进行记录), 并将服务地址返回给 kubelet. 这样 kubelet 就能反馈信息给 API Server, 使之可以直接连接到容器运行时提 供的服务, 并连接到客户端
6. 目前已经有多款开源 CRI 项目可用于 Kubernetes:Docker,CRI-O, Containerd,frakti(基于 Hypervisor 的容器运行时), 各 CRI 运行时的安 装手册可参考官网 https://kubernetes.io/docs/setup/cri / 的说明
第三章
1. kubelet 只支持可以被 API Server 管理的 Pod 使用 ConfigMap. kubelet 在本 Node 上通过 --manifest-url 或 --config 自动创建的静态 Pod 将无 法引用 ConfigMap
2. 在 Pod 对 ConfigMap 进行挂载 (volumeMount) 操作时, 在容器 内部只能挂载为 "目录", 无法挂载为 "文件". 在挂载到容器内部后, 在 目录下将包含 ConfigMap 定义的每个 item, 如果在该目录下原来还有其 他文件, 则容器内的该目录将被挂载的 ConfigMap 覆盖
3. 将 Pod 信息注入为环境变量:
- apiVersion: v1
- kind: pod
- metadata:
- name: {{ template "module.name" . }}
- namespace: {{ $.Release.Namespace }}
- spec:
- containers:
- - name: {{ .Chart.Name }}
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
- env:
- - name: MY_POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
- - name: MY_POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- - name: MY_POD_IP
- valueFrom:
- fieldPath: matadata.podIP
4. 将容器资源信息注入为环 境变量
- apiVersion: v1
- kind: pod
- metadata:
- name: {{ template "module.name" . }}
- namespace: {{ $.Release.Namespace }}
- spec:
- containers:
- - name: {{ .Chart.Name }}
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
- resources:
- requests:
- memory: "32Mi"
- CPU: "125m"
- limits:
- memory: "64Mi"
- CPU: "250m"
- env:
- - name: MY_CPU_REQUEST
- valueFrom:
- resourceFieldRef:
- containerName: test-container
- resource: request.CPU
5. 通过 Downward API 将 Pod 的 Label,Annotation 列表通过 Volume 挂载为容器中的一个文件
- apiVersion: v1
- kind: pod
- metadata:
- name: {{ template "module.name" . }}
- namespace: {{ $.Release.Namespace }}
- labels:
- zone: us-est-coast
- cluster: test-cluster1
- Rack: Rack-22
- annotations:
- build: two
- builder: john-doe
- spec:
- containers:
- - name: {{ .Chart.Name }}
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
- resources:
- requests:
- memory: "32Mi"
- CPU: "125m"
- limits:
- memory: "64Mi"
- CPU: "250m"
- volumeMounts:
- - name: pidinfo
- mountPath: /etc
- readOnly: false
- volumes:
- - name: podinfo
- downloadAPI:
- items:
- - path: "labels"
- fieldRef:
- fieldPath: metadata.labels
- - path: "annotations"
- fieldRef:
- fieldPath: metadata.annotations
这里要注意 "volumes" 字段中 downwardAPI 的特殊语法, 通过 items 的设置, 系统会根据 path 的名称生成文件. 根据上例的设置, 系统将在 容器内生成 / etc/labels 和 / etc/annotations 两个文件. Downward API 的价值. 在某些集群中, 集群中的每个节点都需要将自身的标识 (ID) 及进程绑定的 IP 地址等信息事先写入配置文件中, 进程在启动时会读取这些 信息, 然后将这些信息发布到某个类似服务注册中心的地方, 以实现集 群节点的自动发现功能
6. pod 的生命周期: kubelet 重启失效容器的时间间隔以 sync-frequency 乘以 2n 来计算, 例 如 1,2,4,8 倍等, 最长延时 5min, 并且在成功重启后的 10min 后重置该时间.
7. NodeAffinity:Node 亲和性调度 NodeAffinity 意为 Node 亲和性的调度策略, 是用于替换 NodeSelector 的全新调度策略. 目前有两种节点亲和性表达:◎ RequiredDuringSchedulingIgnoredDuringExecution: 必须满足指定的规则才可以调度 Pod 到 Node 上 (功能与 nodeSelector 很像, 但是使用 的是不同的语法), 相当于硬限制 ◎ PreferredDuringSchedulingIgnoredDuringExecution: 强调优先满足指定规则, 调度器会尝试调度 Pod 到 Node 上, 但并不强求, 相当于软 限制. 多个优先级规则还可以设置权重(weight) 值, 以定义执行的先 后顺序. IgnoredDuringExecution 的意思是: 如果一个 Pod 所在的节点在 Pod 运 行期间标签发生了变更, 不再符合该 Pod 的节点亲和性需求, 则系统将 忽略 Node 上 Label 的变化, 该 Pod 能继续在该节点运行
8. PodAffinity:Pod 亲和与互斥调度策略. Pod 间的亲和与互斥从 Kubernetes 1.4 版本开始引入. 这一功能让用 户从另一个角度来限制 Pod 所能运行的节点: 根据在节点上正在运行的 Pod 的标签而不是节点的标签进行判断和调度, 要求对节点和 Pod 两个条 件进行匹配. 这种规则可以描述为: 如果在具有标签 X 的 Node 上运行了 一个或者多个符合条件 Y 的 Pod, 那么 Pod 应该 (如果是互斥的情况, 那么就变成拒绝) 运行在这个 Node 上
9. Pod 的互斥性调度
10. Taints 和 Tolerations(污点和容忍)Taint 需要和 Toleration 配合使用, 让 Pod 避开那些不合适的 Node. 在 Node 上设置一个或多个 Taint 之后, 除非 Pod 明确声明能够容忍这些污 点, 否则无法在这些 Node 上运行. Toleration 是 Pod 的属性, 让 Pod 能够 (注意, 只是能够, 而非必须)运行在标注了 Taint 的 Node 上 可以用 kubectl taint 命令为 Node 设置 Taint 信息: kubectl taint nodes node1 key=value:NoSchedule 这个设置为 node1 加上了一个 Taint. 该 Taint 的键为 key, 值为 value,Taint 的效果是 NoSchedule. 这意味着除非 Pod 明确声明可以容忍 这个 Taint, 否则就不会被调度到 node1 上. 然后, 需要在 Pod 上声明 Toleration. 下面的两个 Toleration 都被设置 为可以容忍 (Tolerate) 具有该 Taint 的 Node, 使得 Pod 能够被调度到 node1 上
- tolerations:
- - key: "key"
- operator: "Equal"
- value: value
- effect: "NoSchedule"
或者
- tolerations:
- - key: "key"
- operator: "Exists"
- effect: "NoSchedule"
Pod 的 Toleration 声明中的 key 和 effect 需要与 Taint 的设置保持一致, 并且满足以下条件之一.◎ operator 的值是 Exists(无须指定 value).◎ operator 的值是 Equal 并且 value 相等. 如果不指定 operator, 则默认值为 Equal. 另外, 有如下两个特例.◎ 空的 key 配合 Exists 操作符能够匹配所有的键和值.◎ 空的 effect 匹配所有的 effect. 在上面的例子中, effect 的取值为 NoSchedule, 还可以取值为 PreferNoSchedule, 这个值的意思是优先, 也可以算作 NoSchedule 的软 限制版本 - 一个 Pod 如果没有声明容忍这个 Taint, 则系统会尽量避免把 这个 Pod 调度到这一节点上, 但不是强制的系统允许在同一个 Node 上设置多个 Taint, 也可以在 Pod 上设置多个 Toleration.Kubernetes 调度器处理多个 Taint 和 Toleration 的逻辑顺序为: 首先列出节点中所有的 Taint, 然后忽略 Pod 的 Toleration 能够匹配的部 分, 剩下的没有忽略的 Taint 就是对 Pod 的效果了. 下面是几种特殊情◎ 如果在剩余的 Taint 中没有 NoSchedule 效果, 但是有 PreferNoSchedule 效果, 则调度器会尝试不把这个 Pod 指派给这个节点.◎ 如果在剩余的 Taint 中存在 effect=NoSchedule, 则调度器不会把 该 Pod 调度到这一节点上.◎ 如果在剩余的 Taint 中有 NoExecute 效果, 并且这个 Pod 已经在该节点上运行, 则会被驱逐; 如果没有在该节点上运行, 则也不会再被调 度到该节点上.
11. Pod Priority Preemption:Pod 优先级调度. 在 Kubernetes 1.8 版本之前, 当集群的可用资源不足时, 在用户提交 新的 Pod 创建请求后, 该 Pod 会一直处于 Pending 状态, 即使这个 Pod 是一 个很重要 (很有身份) 的 Pod, 也只能被动等待其他 Pod 被删除并释放资 源, 才能有机会被调度成功. Kubernetes 1.8 版本引入了基于 Pod 优先级 抢占 (Pod Priority Preemption) 的调度策略, 此时 Kubernetes 会尝试释 放目标节点上低优先级的 Pod, 以腾出空间 (资源) 安置高优先级的 Pod, 这种调度方式被称为 "抢占式调度". 在 Kubernetes 1.11 版本中, 该 特性升级为 Beta 版本, 默认开启, 在后继的 Kubernetes 1.14 版本中正式 Release. 如何声明一个负载相对其他负载 "更重要"? 我们可以通过以下 几个维度来定义:◎ Priority, 优先级;◎ QoS, 服务质量等级;◎ 系统定义的其他度量指标. 优先级抢占调度策略的核心行为分别是驱逐 (Eviction) 与抢占 (Preemption), 这两种行为的使用场景不同, 效果相同. Eviction 是 kubelet 进程的行为, 即当一个 Node 发生资源不足 (under resource pressure) 的情况时, 该节点上的 kubelet 进程会执行驱逐动作, 此时 Kubelet 会综合考虑 Pod 的优先级, 资源申请量与实际使用量等信息来计 算哪些 Pod 需要被驱逐; 当同样优先级的 Pod 需要被驱逐时, 实际使用的 资源量超过申请量最大倍数的高耗能 Pod 会被首先驱逐. 对于 QoS 等级 为 "Best Effort" 的 Pod 来说, 由于没有定义资源申请 (CPU/Memory Request), 所以它们实际使用的资源可能非常大. Preemption 则是 Scheduler 执行的行为, 当一个新的 Pod 因为资源无法满足而不能被调度 时, Scheduler 可能(有权决定) 选择驱逐部分低优先级的 Pod 实例来满 足此 Pod 的调度目标, 这就是 Preemption 机制. 需要注意的是, Scheduler 可能会驱逐 Node A 上的一个 Pod 以满足 Node B 上的一个新 Pod 的调度任务
12. deployment 更新. 当更新 Deployment 时, 系统创建了一个新的 ReplicaSet(nginx-deployment-3599678771), 并将其副本数量扩展到 1, 然后将旧的 ReplicaSet 缩减为 2. 之后, 系统继续按照相同的更新策 略对新旧两个 ReplicaSet 进行逐个调整. 最后, 新的 ReplicaSet 运行了 3 个 新版本 Pod 副本, 旧的 ReplicaSet 副本数量则缩减为 0
13. 自动扩缩容机制. Kubernetes 中的某个 Metrics Server(Heapster 或自定义 Metrics Server)持续采集所有 Pod 副本的指标数据. HPA 控制器通过 Metrics Server 的 API(Heapster 的 API 或聚合 API)获取这些数据, 基于用户定义 的扩缩容规则进行计算, 得到目标 Pod 副本数量. 当目标 Pod 副本数量与 当前副本数量不同时, HPA 控制器就向 Pod 的副本控制器 (Deployment,RC 或 ReplicaSet)发起 scale 操作, 调整 Pod 的副本数量, 完成扩缩容操作
14. 指标的类型 Master 的 kube-controller-manager 服务持续监测目标 Pod 的某种性能 指标, 以计算是否需要调整副本数量. 目前 Kubernetes 支持的指标类型 如下:◎ Pod 资源使用率: Pod 级别的性能指标, 通常是一个比率值, 例 如 CPU 使用率. ◎ Pod 自定义指标: Pod 级别的性能指标, 通常是一个数值, 例如接收的请数量.◎ Object 自定义指标或外部自定义指标: 通常是一个数值, 需要 容器应用以某种方式提供, 例如通过 HTTP URL"/metrics" 提供, 或者使 用外部服务提供的指标采集 URL.Kubernetes 从 1.11 版本开始, 弃用基于 Heapster 组件完成 Pod 的 CPU 使用率采集的机制, 全面转向基于 Metrics Server 完成数据采集. Metrics Server 将采集到的 Pod 性能指标数据通过聚合 API(Aggregated API)如 metrics.k8s.io,custom.metrics.k8s.io 和 external.metrics.k8s.io 提供给 HPA 控制器进行查询
15. 扩缩容算法详解 Autoscaler 控制器从聚合 API 获取到 Pod 性能指标数据之后, 基于下 面的算法计算出目标 Pod 副本数量, 与当前运行的 Pod 副本数量进行对 比, 决定是否需要进行扩缩容操作:
即当前副本数 *(当前指标值 / 期望的指标值), 将结果向上取整. 当计算结果与 1 非常接近时, 可以设置一个容忍度让系统不做扩缩 容操作. 容忍度通过 kube-controller-manager 服务的启动参数 --horizontal- pod-autoscaler-tolerance 进行设置, 默认值为 0.1(即 10%), 表示基于上 述算法得到的结果在 [-10%- 10%] 区间内, 即 [0.9-1.1], 控制器都不会进行扩缩容操作. 也可以将期望指标值(desiredMetricValue) 设置为指标的平均值类 型, 例如 targetAverageValue 或 targetAverageUtilization, 此时当前指标值 (currentMetricValue)的算法为所有 Pod 副本当前指标值的总和除以 Pod 副本数量得到的平均值. 此外, 存在几种 Pod 异常的情况, 如下所述:◎ Pod 正在被删除 (设置了删除时间戳): 将不会计入目标 Pod 副本数量.◎ Pod 的当前指标值无法获得: 本次探测不会将这个 Pod 纳入目标 Pod 副本数量, 后续的探测会被重新纳入计算范围.◎ 如果指标类型是 CPU 使用率, 则对于正在启动但是还未达到 Ready 状态的 Pod, 也暂时不会纳入目标副本数量范围. 可以通过 kube- controller-manager 服务的启动参数 --horizontal-pod-autoscaler-initial- readiness-delay 设置首次探测 Pod 是否 Ready 的延时时间, 默认值为 30s. 另一个启动参数 --horizontal-pod-autoscaler-cpuinitialization-period 设置首 次采集 Pod 的 CPU 使用率的延时时间. 如果在 HorizontalPodAutoscaler 中设置了多个指标, 系统就会对每个 指标都执行上面的算法, 在全部结果中以期望副本数的最大值为最终结 果. 如果这些指标中的任意一个都无法转换为期望的副本数(例如无法 获取指标的值), 系统就会跳过扩缩容操作. 最后, 在 HPA 控制器执行扩缩容操作之前, 系统会记录扩缩容建议 信息(Scale Recommendation). 控制器会在操作时间窗口(时间范围 可以配置) 中考虑所有的建议信息, 并从中选择得分最高的建议. 这个 值可通过 kube-controller-manager 服务的启动参数 --horizontal-pod- autoscaler-downscale-stabilization-Windows 进行配置, 默认值为 5min. 这 个配置可以让系统更为平滑地进行缩容操作, 从而消除短时间内指标值 快速波动产生的影响
16. HorizontalPodAutoscaler 配置详解 .HorizontalPodAutoscaler 资源对象处于 Kubernetes 的 API 组 "autoscaling" 中, 目前包括 v1 和 v2 两个版本. 其中 autoscaling/v1 仅支 持基于 CPU 使用率的自动扩缩容, autoscaling/v2 则用于支持基于任意指 标的自动扩缩容配置, 包括基于资源使用率, Pod 指标, 其他指标等类 型的指标数据, 当前版本为 autoscaling/v2beta2
- apiVersion: autoscaling/v1
- kind: HorizontalPodAutoscalee
- metadata:
- name: PHP-apache
- spec:
- scaleTargetRef:
- apiVersion: apps/v1
- kind: Deployment
- name: PHP-apache
- minReplicas: 1
- maxReplicas: 10
- targetCPUUtilizationPercentage: 50
◎ scaleTargetRef: 目标作用对象, 可以是 Deployment, ReplicationController 或 ReplicaSet.◎ targetCPUUtilizationPercentage: 期望每个 Pod 的 CPU 使用率都 为 50%, 该使用率基于 Pod 设置的 CPU Request 值进行计算, 例如该值为 200m, 那么系统将维持 Pod 的实际 CPU 使用值为 100m.◎ minReplicas 和 maxReplicas:Pod 副本数量的最小值和最大值, 系统将在这个范围内进行自动扩缩容操作, 并维持每个 Pod 的 CPU 使用 率为 50%.
17. 基于 autoscaling/v2beta2 的 HorizontalPodAutoscaler 配置
- apiVersion: autoscaling/v2beta2
- kind: HorizontalPodAutoscaler
- metadata:
- name: PHP-apache
- spec:
- scaleTargetRef:
- apiVersion: apps/v1
- kind: Deployment
- name: PHP-apache
- minReplicas: 1
- maxReplicas: 10
- metrics:
- - type: Resource
- resource:
- name: CPU
- target:
- type: Utilization
- averageUtilization: 50
◎ scaleTargetRef: 目标作用对象, 可以是 Deployment, ReplicationController 或 ReplicaSet.◎ minReplicas 和 maxReplicas:Pod 副本数量的最小值和最大值, 系统将在这个范围内进行自动扩缩容操作, 并维持每个 Pod 的 CPU 使用 率为 50%.◎ metrics: 目标指标值. 在 metrics 中通过参数 type 定义指标的类 型; 通过参数 target 定义相应的指标目标值, 系统将在指标数据达到目标值时 (考虑容忍度的区间, 见前面算法部分的说明) 触发扩缩容操 作.
来源: http://www.bubuko.com/infodetail-3475004.html