Kubernetes知识体系

运维技术栈-Kubernetes原理_kubernetes

k8s架构组成

运维技术栈-Kubernetes原理_kubernetes_02

运维技术栈-Kubernetes原理_kubernetes_03

etcd

运维技术栈-Kubernetes原理_kubernetes_04


  • 高可用键值数据库,B+tree形式存储,类似目录结构,父节点为目录,叶子节点存数据
  • 服务注册与发现功能,用户可以在etcd中注册服务,设定key TTL,保持心跳
  • 消息发布订阅,构建配置共享中心,etcd作为消息中心读取最新信息,并返回给订阅端
  • 基于Raft协议开发,分布式,自动leader选举
  • watch机制监控APISERVER等组件的消息
  • 操作指令:etcdctl
  • 通过内存和本地磁盘存储
  • TTL 给一个key设置一个有效期,到期后这个key就会被自动删掉
  • CAS 在对key进行赋值的时候,客户端需要提供一些条件,当这些条件满足后,才能赋值成功
  • prevExist:key当前赋值前是否存在
  • prevValue:key当前赋值前的值
  • prevIndex:key当前赋值前的Index

Raft协议

Raft协议基于quorum机制,即大多数同意原则,任何的变更都需超过半数的成员确认


​http://thesecretlivesofdata.com/raft/​

Raft 数据同步机制
  • leader选举机制

运维技术栈-Kubernetes原理_kubernetes_05


  1. 3个节点的情况下,初始状态都是follower角色,任期为0,
  2. 之后,node1发现没有leader,于是开始向node2和node3发起投票请求
  3. node2 和 node3 觉得node1没毛病,可以当leader,于是都投票给node1
  4. 此时,node1获得2票,满足大多数同意条件,成为leader


  • 数据同步机制


运维技术栈-Kubernetes原理_kubernetes_06


  1. 用户插入新数据,如SET key xxx;
  2. 此时,先由leader接收并执行该操作,但此时状态标记为uncommit,这时并没有真的保存到库中;
  3. leader开始将命令发送给其他节点,让它们也执行,同时开启watch监听,等待返回消息;
  4. 其他节点执行成功后,返回成功消息给leader;
  5. leader 判断如果大多数节点都返回完成消息了,才标记为commit状态;
  6. 之后,这条数据才真的保存到库中


Raft 故障恢复机制
  • Term机制
  1. 上面提到了Term表示任期,可以理解为一个阶段的标识,以下面场景举例
  2. node 1 在刚才突然因为网络故障下线了,此时,2和3发现node1的通信timeout超时了,
  3. 于是,由于节点变更,集群状态将Term更新为1,开始第二阶段的重新选举
  4. 之后,node2 和 node3 再开始进行选举流程
  5. 再往下走,node 1 故障处理掉,恢复正常
  6. 这时node 1起来了发现自己还处于Term 0任期
  7. 而node 2同步过来消息显示集群当前最新任期为Term 1
  8. 此时,node 1发现自己是旧的任期,就不会抢leader地位
  9. 而是主动去同步Term 1的最新数据。从而,集群恢复,数据保持最新状态
  10. 故,Term 可以理解为一个标识,表示集群数据是否最新


learner
  • 增加新节点时,新节点数据差异大,无法瞬时同步
  • learner负责接收数据,不参与投票,同时节点总数不变
  • 然后确定同步后,再更新到总节点数中


存储机制

运维技术栈-Kubernetes原理_kubernetes_07

存储分为两部分,一部分是内存中的索引(kvindex),另外一部分是后端存储

  • 可以对接多种存储,当前 etcd v3 使用 boltdb,是一个支持事物的kv存储
  • boltdb中存储的key是支持定义不同版本的(reversion),从而实现多版本控制

包括

  • main rev 每次事物为维度,每次事物加一
  • sub rev 同一个事物下的维度,同一事物每次操作加一


灾备


# 备份 从pod中获取证书信息
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \
snapshot save <backup-file-location>

# 恢复
ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 snapshot restore snapshotdb

# 恢复命令举例
etcdctl snapshot restore snapshot.db \
--name infra2 \
--data-dir=/tmp/etcd/infra2 \
--initial-cluster
infra0=http://127.0.0.1:3380,infra1=http://127.0.0.1:4380,infra2=http://127.0.0.1:5380 \
--initial-cluster-token etcd-cluster-1 \
--initial-advertise-peer-urls http://127.0.0.1:5380


容量管理

  • 单个对象不超过1.5m
  • 默认容量2G,不建议超过8G


etcd容量告警处理


• 设置etcd存储大小
$ etcd --quota-backend-bytes=$((16*1024*1024))
• 写爆磁盘
$ while [ 1 ]; do dd if=/dev/urandom bs=1024 count=1024 | ETCDCTL_API=3 etcdctl put key
|| break; done
• 查看endpoint状态
$ ETCDCTL_API=3 etcdctl --write-out=table endpoint status
• 查看alarm
$ ETCDCTL_API=3 etcdctl alarm list
• 清理碎片
$ ETCDCTL_API=3 etcdctl defrag
• 清理alarm
$ ETCDCTL_API=3 etcdctl alarm disarm

碎片整理

# keep one hour of history
$ etcd --auto-compaction-retention=1
# compact up to revision 3
$ etcdctl compact 3
$ etcdctl defrag
Finished defragmenting etcd member[127.0.0.1:2379]




etcd客户端工具

​etcdctl https://github.com/etcd-io/etcd/releases​


etcdctl常用命令

etcdctl member list --write-out=table --endpoints=localhost:12379

etcdctl --endpoints=localhost:12379 put /a b

etcdctl --endpoints=localhost:12379 get /a

etcdctl --endpoints=localhost:12379 get --prefix /

etcdctl --endpoints=localhost:12379 get --prefix / --keys-only --debug

API Server

  • 提供管理集群的REST API 接口,包括
  • 认证
  • 授权
  • 准入
  • 其他模块都通过API Server完成数据交互
  • 提供etcd数据缓存,提供读取服务,以减少etcd的压力


内部工作流程:

运维技术栈-Kubernetes原理_kubernetes_08

APIHandler:处理函数

AuthN: 认证

Rate Limit: 限流,防止请求过载

Auditing: 记录访问日志,用于审计

AuthZ: 鉴权 (如RBAC)

Aggregator: 聚合器

Mutating Webhook:准入控制器插件

Schema Validation:内置校验器

Validating Webhook:动态准入控制




认证 > 鉴权 > 准入 Mutating Validating Admission(限流)


认证

需要依照Kubernetes规范,构建认证服务,用来认证tokenreview request

认证插件

开启TLS

  • x509证书
  • 静态token文件
  • 引导token
  • 静态密码文件
  • ServiceAccount
  • OpenID
  • Webhook 令牌认证
  • 匿名请求

默认禁止


鉴权

授权

对集群资源的访问控制,通过检查请求包含的相关属性值,与相应的访问策略相比较。


允许的请求属性:

  • user,group,extra
  • API,请求方法和请求路径
  • 请求资源和子资源
  • Namespace
  • API Group


支持的授权插件:

  • ABAC
  • RBAC
  • Webhook
  • Node


RBAC

ABAC和RBAC相比,ABAC由于是通过SSH和文件系统权限实现,不便于管理,而RBAC可以直接通过API资源(可以简单理解为yaml文件)进行管理,不需接触节点,故方便许多。


运维技术栈-Kubernetes原理_kubernetes_09


RBAC 由 Role ClusterRole RoleBinding 几种类型对象结合使用,

  • 其中 Role 代表着定义一种角色,这个角色拥有哪些操作权限(get, watch, list, ...),只能绑定到一个namespace
  • ClusterRole 代表着用于对应多namespace的用户
  • RoleBinding 用于将定义好的角色应用于具体的用户、组或ServiceAccount,即把权限和用户绑定到一起,从而使得用户拥有操作权限
  • 与外部系统对接时,Group 代表授权的用户组
  • 对ServiceAccount授权时,Group 代表某个namespace下的所有ServiceAccount
  • User Account
  • 为人定义账户
  • 跨nampspace
  • Service Account
  • 为pod定义账户
  • 运行对象的身份,与namespace相关




准入控制

为资源增加自定义属性,在授权后对请求做进一步的验证或添加参数,认证鉴权只关注用户和涉及操作两方面,准入控制关注请求的内容的处理,同时,仅对创建、更新、删除、连接有效。


准入控制插件

可以同时开启多个插件,依次调用,形成准入控制链


  • AlwaysAdmit
  • AlwaysPullImages
  • DenyEscalatingExec
  • ImagePolicyWebhook
  • ServiceAccount
  • SecurityContextDeny
  • ResourceQuota
  • LimitRanger
  • InitialResources
  • NamespaceLifecycle
  • DefaultStorageClass
  • DefaultTolerationSeconds
  • PodSecurityPolicy
  • NodeRestriction


限流

由于Kubernetes所有的内部交互都要经由API Server,可想而知,APIServer是要面对大并发大流量场景的。在这种情况下,如果不管,必然会出现APIServer罢工的故障,因此,限流就是必要的手段了。


计数器固定窗口算法


运维技术栈-Kubernetes原理_kubernetes_10

对一端固定时间内的请求进行计数,如果请求数超过阈值,则舍弃超出的请求,如果没达到,则接受,且计数加1,当时间窗口结束时,重置计数器为0


计数器滑动窗口算法

运维技术栈-Kubernetes原理_kubernetes_11

  • 在固定窗口的基础上,将一个计时窗口分成了若干个小窗口,然后每个小窗口维护一个独立的计数器。
  • 当请求的时间大于当前窗口的最大时间时,则将计时窗口向前平移一个小窗口。
  • 平移时,将第一个小窗口的数据丢弃,然后将第二个小窗口设置为第一个小窗口,
  • 同时在最后面新增一个小窗口,将新的请求放在新增的小窗口中。
  • 同时要保证整个窗口中所有小窗口的请求数目之后不能超过设定的阈值。



漏斗算法

运维技术栈-Kubernetes原理_kubernetes_12

  • 漏斗算法的原理也很容易理解。请求来了之后会首先进到漏斗里,然后漏斗以恒定的速率将请求流出进行处理,从而起到平滑流量的作用。当请求的流量过大时,漏斗达到最大容量时会溢出,此时请求被丢弃。 在系统看来,请求永远是以平滑的传输速率过来,从而起到了保护系统的作用。



令牌桶算法

运维技术栈-Kubernetes原理_kubernetes_13

  • 令牌桶算法是对漏斗算法的一种改进,除了能够起到限流的作用外,还允许一定程度的流量突发。
  • 在令牌桶算法中,存在一个令牌桶,算法中存在一种机制以恒定的速率向令牌桶中放入令牌。令牌桶也有一定的容量,如果满了令牌就无法放进去了。 当请求来时,会首先到令牌桶中去拿令牌,如果拿到了令牌,则该请求会被处理,并消耗掉拿到的令牌; 如果令牌桶为空,则该请求会被丢弃。


APIServer中的限流配置
  • max-requests-inflight: 在给定时间内的最大 non-mutating 请求数
  • max-mutating-requests-inflight: 在给定时间内的最大 mutating 请求数,调整 apiserver 的流控 qos

运维技术栈-Kubernetes原理_kubernetes_14


API Priority and Fairness

1.18后 引入API Priority and Fairness

  • 更细粒度对请求分类和隔离
  • 空间有限的排队机制——短暂突发情况下,不会拒绝任何请求
  • 公平排队技术分发请求,确保平均分发到所有控制器
  • 多等级
  • 多队列


运维技术栈-Kubernetes原理_kubernetes_15


  • APF 的实现依赖两个非常重要的资源 FlowSchema, PriorityLevelConfiguration
  • APF 对请求进行更细粒度的分类,每一个请求分类对应一个 FlowSchema (FS)
  • FS 内的请求又会根据 distinguisher 进一步划分为不同的 Flow.
  • FS 会设置一个优先级 (Priority Level, PL),不同优先级的并发资源是隔离的。所以不同优先级的资源不会相互排挤。特定优先级的请求可以被高优处理。
  • 一个 PL 可以对应多个 FS,PL 中维护了一个 QueueSet,用于缓存不能及时处理的请求,请求不会因为超出 PL 的并发限制而被丢弃。
  • FS 中的每个 Flow 通过 shuffle sharding 算法从 QueueSet 选取特定的 queues 缓存请求。
  • 每次从 QueueSet 中取请求执行时,会先应用 fair queuing 算法从 QueueSet 中选中一个 queue,然后从这个 queue 中取出 oldest 请求执行。所以即使是同一个 PL 内的请求,也不会出现一个 Flow 内的请求一直占用资源的不公平现象。


APF概念
  • 传入的请求通过FlowSchema按照其属性分类,并分配优先级
  • 每个优先级维护自定义的并发限制,加强了隔离度,这样不同优先级的请求,就不会相互饿死
  • 在同一个优先级内,公平算法可以防止来自不同flow的请求相互饿死
  • 该算法将请求排队,通过排队机制,防止在平均负载较低时,通信量突增而导致请求失败


优先级
  • 如果未启用APF,API的整体并发量将受到参数max-requests-inflight和max-requests-inflight 的限制
  • 启用APF后,将对这些参数定义的并发限制数值进行求和,然后分配到一组可配置的优先级中。每个传入的请求都会分配一个优先级。
  • 每个优先级都可以进行配置,设定并发请求数限制。


排队

即使是同一优先级内,也可能存在大量不同的流量源,这就有可能导致一个疯狂传入的请求流堵死其他正常请求流


公平排队算法解决了上述问题

  • 每个请求会分配到某个流,由与其对应FlowSchema的名字+FlowDistinguisher来标识
  • FlowDistinguisher(流区分项)可以由请求发送者、目标资源的名称空间或其他无意义的字符串来标识
  • 系统尝试为不同流中具有相同优先级的请求赋予近似相等的权重
  • 将请求划分到流中之后,APF 功能将请求分配到队列中。
  • 分配时使用一种称为 混洗分片(Shuffle-Sharding) 的技术。 该技术可以相对有效地利用队列隔离低强度流与高强度流。
  • 排队算法的细节可针对每个优先等级进行调整,并允许管理员在内存占用、公平性(当总流量超标时,各个独立的流将都会取得进展)、突发流量的容忍度以及排队引发的额外延迟之间进行权衡。


豁免请求

针对某些特殊请求可以做豁免处理,实现不受任何限制


默认配置


  • system
  • leader-election
  • workload-high
  • workload-low
  • global-default
  • exempt
  • catch-all


PriorityLevelConfiguration


apiVersion: 
flowcontrol.apiserver.k8s.io/v1beta1
kind: PriorityLevelConfiguration
metadata:
name: global-default
spec:
limited:
assuredConcurrencyShares: 20
limitResponse:
queuing:
handSize: 6
queueLengthLimit: 50
queues: 128
type: Queue
type: Limited


controller manager

控制管理器

  • 集群的大脑,确保整个集群动起来
  • 确保kubernetes遵循声明式系统规范,确保系统的真实状态与用户定义的期望状态一致
  • 是多个控制器的集合,每个都是一个loop,负责侦听其监控的对象,当对象发生变更时完成配置
  • 自动重试机制,以确保最终一致性


工作流程


运维技术栈-Kubernetes原理_kubernetes_16

通用Controller


  • Job Controller 处理job
  • Pod AutoScaler 自动扩缩容
  • ReplicaSet
  • Service Controller
  • StatefulSet Controller
  • Name 固定
  • hostname.subdomain.svc.cluster.local -> localhost
  • pvc template
  • Volume Controller
  • Resource quota Controller
  • Namespace Controller namespace删除时同时删除包含的资源
  • Replication Controller 创建RC后,负责创建Pod
  • Daemon Controller


controllerRevision 记录不同类型Spec版本信息,确保配置与用户期望一致性


delete --cascade=orphan


保护controller 的 kubeconfig,避免被外部看到获取权限


Controller 和 scheduler的高可用


通过锁,确定leader,每15秒一次确认锁对象


Informer的内部机制

运维技术栈-Kubernetes原理_kubernetes_17




控制器的协同工作原理

运维技术栈-Kubernetes原理_kubernetes_18

用户创建DM < DC监听 > 建立RS > APIServer

APIServer < RC监听 > 创建Pod > APIServer < kubelet监听 > scheduler > Pod to node < node-kubelet



kube-Scheduler

负责分配pods到节点上,它监听APIServer,查询还未分配node的pod,然后根据调度策略、节点资源状况等因素去分配这些pod


具体因素包括

  • 公平调度
  • 资源高效利用
  • QoS
  • affinity 和anti-affinity
  • 数据本地化
  • 内部负载干扰
  • deadlines

运维技术栈-Kubernetes原理_kubernetes_19

阶段为:

  • Predict: 过滤不满足条件节点
  • PodFitsHostPorts: 检查是否有Host Ports 冲突
  • PodFitsPorts: 同PodFitsHostPorts
  • PodFitsResources: 检查Node的资源是否充足,包括允许的Pod数量,CPU,内存,GPU个数以及其他的OpaqueIntResources
  • Hostname: 检查pod.Spec.NodeName是否与候选节点一致
  • MatchNodeSelector: 检查候选节点的pod.Spec.NodeSelector是否匹配
  • NoVolumeZoneConflict: 检查volume zone是否冲突
  • MatchInterPodAffinity: 检查是否匹配Pod的亲和性要求
  • NoDiskConflict: 检查是否存在Volume冲突,仅限于GCE PD、AWS EBS、Ceph RBD以及iSCSI
  • PodToleratesNodeTaints: 检查Pod是否容忍Node Taints
  • CheckNodeMemoryPressure: 检查Pod是否可以调度到MemoryPressure的节点上
  • CheckNodeDiskPressure: 检查Pod是否可以调度到DiskPressure的节点上
  • NoVolumeNodeConflict:检查节点是否满足Pod所引用的Volume的条件
  • 还有很多其他的策略,也可以编写自己的策略
  • Priority: 筛选最佳节点
  • SelectorSpreadPriority: 优先减少节点上属于同一个Service或ReplicationController的Pod数量
  • InterPodAffinityPriority:优先将Pod调度到相同的拓扑上(如同一个节点、Rack、Zone等)
  • LeastRequestPriority:优先调度到请求资源少的节点上
  • BalancedResourceAllocation:优先平衡各节点的资源使用
  • NodePreferAvoidPodsPriority:alpha.kubernetes.io/preferAvoidPods字段判断,权重为10000,避免其他优先级策略的影响
  • NodeAffinityPriority:优先调度到匹配NodeAffinity的节点上
  • TaintTolerationPriority:优先调度到匹配TaintToleration的节点上
  • ServiceSpreadingPriority:尽量将同一个service的pod分布到不同的节点上,已经被SelectorSpreadPriority替代
  • EqualPriority:将所有节点的优先级设置为1
  • ImageLocalityPriority:尽量将使用大镜像的容器调度到已经下拉了该镜像的节点上
  • MostRequestedPriority:尽量调度到已经使用过的Node上,特别适用于cluster-autoscaler
  • Bind: pod绑定到该节点


Resource 控制

  • CPU
  • requests

调度时,判断当前节点正在运行的Pod的CPU Request的总和,再加上待调度的Pod的Request,得出的总和判断是否超出节点CPU可分配资源。

  • limits

配置Cgroups以限制资源上限


​调度时只是看request的资源量,不看limit。这就可能导致节点资源较少的情况下,调度pod时资源量满足条件,于是调度到该节点上了,但是该pod运行一段时间后资源占用持续增高,最后导致该节点资源被占满。​

​CPU如果占满,超出limit限制,不会导致pod进程crash,只会导致pod变慢​

​其他的硬的资源占满,则会触发OOM killer​


  • 内存
  • requests

判断节点剩余内存是否满足Pod需求

  • limits

配置Cgroups以限制内存资源上限



  • 磁盘资源

容器临时存储(ephemeral-storage)包含日志和可写层数据,可以通过定义pod spec中的limits.ephemeral-storage和requests.ephemeral-storage来申请

Pod调度完成后,计算节点对临时存储的限制不是基于Cgroups的,而是由kubelet定时获取容器的日志和容器可写层的磁盘使用情况,如果超过限制,则会对Pod进行驱逐

  • InitContainer的资源需求

当scheduler调度带有多个init容器的Pod时,只计算cpu.request最多的init容器,而不是计算所有的init的总和

由于init容器执行完会立即退出,即便是多个,也是依次退出,所以只需要考虑request需求最高的那个init是否满足就可以了

scheduler在后续调度时计算该节点资源,init容器的资源需求依然会被纳入计算。因为init容器在特定情况下可能会再次执行。


把Pod调度到指定Node上

  • nodeSelector
  • nodeAffinity
  • podAffinity
  • Taints
  • tolerations


nodeSelector用法


kubectl label nodes node-1 disktype=ssd # 将节点"node-1"打上"disktype=ssd"的标签,其中disktype为key,ssd为

之后,编辑工作负载的yaml


spec:
nodeSelector:
disktype:ssd


Node Affinity(节点亲和)
  • require 强亲和性,必须调度到哪些节点
  • prefer 弱亲和性,尽量调度,优选条件


  • 让pod 只会被调度到必须具有 disktype=ssd 标签的节点
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent


  • pod首选具有 disktype=ssd 标签的节点
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent


pod 间亲和性与反亲和性

基于已经在节点上运行的 Pod 的标签 来约束 Pod 可以调度到的节点,而不是基于节点上的标签,支持podAffinity和PodAntiAffinity。


apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity: # 配置pod亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security # 匹配标签key为security
operator: In
values:
- S1 # 匹配标签value为S1
topologyKey: topology.kubernetes.io/zone # 同时,该节点需满足该标签
podAntiAffinity: # 配置pod反亲和性
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security # 匹配标签key为security
operator: In
values:
- S2 # 匹配标签value为S2
topologyKey: topology.kubernetes.io/zone # 同时,该节点需满足该标签
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0


  • 华为云关于调度策略工作负载调度的解释,只是基于pod的亲和性调度策略,不考虑可用区

基于工作负载可以设置多条调度策略,但多条策略中设置的标签必须同时出现在一个工作负载中。例如亲和(反亲和)工作负载app1和app2,则实际亲和(反亲和)的是同时包含app1和app2标签的工作负载


Taints和tolerations

用于保证不被调度到不合适的node上,其中taints用于node,tolerations用于pod

Taint类型:

  • NoSchedule: 给节点打污点,保证新的Pod不被调度到该节点
  • PreferNoSchedule:尽量不调度到该节点
  • NoExcecute: 不调度新Pod,同时删除已在运行的pod。可以加上tolerationSeconds作为时间条件,过后才删除。


kubectl taint nodes node1 key1=value1:NoSchedule


移除撤销污点

kubectl taint nodes node1 key1=value1:NoSchedule-


若要在已打上污点的节点上,运行新的Pod,需要修改Pod的yaml文件如下

tolerations:
- key: "key1"
operator: "Equal" # 表示= ; Equal是默认值
value: "value1"
effect: "NoSchedule" # =

tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"


​operator​​​ 的默认值是 ​​Equal​​。

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:

  • 如果 ​​operator​​​ 是 ​​Exists​​​ (此时容忍度不能指定 ​​value​​),或者
  • 如果 ​​operator​​​ 是 ​​Equal​​​ ,则它们的 ​​value​​ 应该相等


说明:

存在两种特殊情况:

如果一个容忍度的 ​​key​​​ 为空且 operator 为 ​​Exists​​, 表示这个容忍度与任意的 key 、value 和 effect 都匹配,即这个容忍度能容忍任意 taint。

如果 ​​effect​​​ 为空,则可以与所有键名 ​​key1​​ 的效果相匹配。


优先级调度

v1.8开始,增加了定义pod的优先级,保证高优先级的pod优先调度

apiserver配置 --feature-gates=PodPriority=true 和 --runtime-config=scheduling.k8s.io/v1alpha1=true

scheduler配置 --feature-gates=PodPriority=true


1.先定义一个Priority Class

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "此优先级类应仅用于 XYZ 服务 Pod。"


2.配置Pod的yaml,增加优先级字段

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority


多调度器

如果默认的调度器不满足要求,还可以部署自定义的调度器,同时,整个集群可以同时运行多个调度器,通过podSpec.schedulerName来选择调度器。default-scheduler




kubelet

k8s的初始化系统 init system

  • 获取pod清单,并按需启停
  • 汇报节点资源信息和健康状态
  • Pod的健康检查和状态汇报


kubelet管理Pod的核心流程

运维技术栈-Kubernetes原理_kubernetes_20

APIServer file http 获取pod发布消息,生成清单

syncLoop 获取清单信息,开始执行

computePodActions 比对当前pod运行状态,对容器进行相应操作

PLEG 监控pod状态,上报给syncLoop


CRI

一组gRPC服务。kubelet作为客户端,与容器运行时通信,通信基于gPRC框架再通过Socket实现。

包括两类服务

  • 镜像服务(Image Service)

下载、检查和删除镜像

  • 运行时服务(Runtime Service)
  • 管理容器生命周期
  • 与容器交互的调用

“docker-shim”,“containerd”,“CRI-O”,都是遵循CRI的容器运行时,称其为高层级运行时

高层级运行时会下载一个OCI镜像,解压成文件系统包,再在其中运行容器程序。同时,运行时规范会定义相关配置(namespace\cgroups\volumemount等等),以及生命周期。这个称为低层级运行时。低层级运行时的实现包括runC、kata、gVisor等。


性能比较

运维技术栈-Kubernetes原理_kubernetes_21

containerd 比dockershim流程更简洁,同时性能上高于cri-o,所以是目前最优的方案。


docker 切换 containerd
  • 创建config
  • 修改config /etc/containerd/config.toml 替换pause镜像源和SystemdCgroup
  • 编辑kubeadm.conf 修改环境变量为containerd的相关参数
  • 重启进程



网络原理


CNI

kubernetes的网络模型设计原则:

  • 所有的Pod不需要通过NAT就能访问
  • 所有的节点不需要通过NAT就能访问
  • 容器内IP地址和外部组件看到的IP地址是一样的


Pod内所有容器共享一个共同的网络命名空间,实现通过localhost:port就能连接其他容器。

运行时通过CNI调用网络插件实现容器网络设置。

运行时从CNI的目录中读取Json格式的配置文件,如果目录中包含多个文件,一般默认读取名字排序的第一个。文件后缀可为".conf"、".conflist"、".json"


service

  • 应用服务的抽象
  • 基于labels绑定应用
  • service selector
  • Pod对象定义了label进行标记,之后service selector指定pod标签,便形成了绑定关系,从而实现了与应用的绑定
  • ports
  • 定义服务的端口、目标应用的端口,以及协议等信息
  • 为应用提供负载均衡和服务发现
  • endpoints = ip : port
  • endpoint controller 侦听Service的创建,并创建同名的Endpoint对象
  • 关联service 和每个pod之间关系,通过container_ip: container_port的方式组成endpoints
  • addresses属性以列表的形式记录其所关联的后端所有已就绪(ready)pod的ip
  • notReadyAddresses 反映未就绪的Pod的IP,以实现屏蔽流量的转发
  • 通过 publishNotReadyAddresses: true ,不管pod是否就绪, 直接映射到address
  • EndpointSlice 用于将数目过大的pod导致的ep地址列表过长进行切片
  • Service selector 不定义的service
  • 不会自动创建endpoint
  • 用户手动创建endpoint
  • 用户可设置任意IP到address列表中
  • 访问该服务,可转发至用户手动设置的地址
  • 实现为集群外的endpoint创建服务
  • kube-proxy 负责将n个应用映射到endpoints
  • 自动分配 DNS + cluster IP (集群内访问方式)
  • service 类型
  • cluster IP
  • 查看kube-apiserver.conf,找到--service-cluster-ip-range=10.255.0.0/16参数,该参数即为为service分配的ip范围
  • nodePort
  • LoadBalancer
  • 需要云厂商负载均衡设备配合使用
  • 对于不同厂商,有对应的Controller支持
  • ExternalName
  • 为外部域名创建别名
  • Headless Service
  • Cluster IP 定义为 None,外部无法访问调用

EndpointSlice


当某个service对应的backend Pod较多时,ep对象会因为保存的地址过多而变得非常庞大

endpointslice可将endpoint切片


apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: example-abc
labels:
kubernetes.io/service-name: example
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.1.2.3"
conditions:
ready: true
hostname: pod-1
nodeName: node-1
zone: us-west2-a


Service Topology

  • 服务拓扑(Service Topology)可以让一个服务基于集群的 Node 拓扑进行流量路由
  • 对于 ClusterIP 服务,无法完成同节点优先的路由,你也无法配置集群优选路由到同一可用区中的端点。
  • 通过在 Service 上配置topologyKeys,你可以基于来源节点和目标节点的标签来定义流量路由策略。
  • 从而实现根据同一节点、同一机架、同一可用区、同一数据中心等不同维度做特定的流量路由策略
  • 如果 Service 没有匹配的后端 Node,那么第二个标签会被使用做匹配, 以此类推,直到没有标签。
  • 如果没有匹配到任何节点,流量会被拒绝


  • 只定向到同一个 Node 上的端点
  • ["kubernetes.io/hostname"]
  • 做法:优先node端点,其次同一可用区端点,再次同一地区端点,最后集群范围端点
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
topologyKeys:
- "kubernetes.io/hostname"
- "topology.kubernetes.io/zone"
- "topology.kubernetes.io/region"
- "*"


kube-proxy

节点的网络,请求转发,针对pods做负载均衡。

  • 监控发布的服务,及完成负载均衡配置
  • 各节点负载均衡策略保持一致,确保服务发现分布式,服务调用无需额外跳转
  • 基于不同插件实现
  • userspace
  • 早期方案,在用户空间监听一个端口,所有服务通过iptables转发到这个端口,然后在其内部负载均衡到实际的Pod
  • 该方式效率低,性能瓶颈明显
  • iptables
  • iptables通过表、链区分规则的维度,将请求依次匹配不同的规则,并依次执行相应的动作,最终实现到目标端的转发
  • iptables的概率算法实现简单的负载均衡
  • 服务多的时候iptables规则多,大规模下性能问题明显
  • ipvs
  • ipvs通过一种realserver-server的模型结合多种灵活的算法实现负载均衡
  • 解决了iptables的性能问题
  • winuserspace
  • 仅工作在windows上


CoreDNS

  • CoreDNS 是推荐的 DNS 服务器,取代了 kube-dns,实现DNS解析
  • 监听Service和Endpoint的变化并生成DNS配置
  • 用户通过访问DNS提供的域名即可访问到后端对应的Pod,不需要了解具体的cluster ip
  • 域名范式:
  • 普通service:servicename.namespace.svc.clusterdomain
  • headless:podname.servicename.namespace.svc.clusterdomain
  • External:该service创建新域名映射原域名,CoreDNS会为该svc创建CName记录
  • 可在 kubelet 中使用 --cluster-domain=<默认本地域名> 标志配置本地域名
  • DNS 服务器支持正向查找(A 和 AAAA 记录)、端口发现(SRV 记录)、反向 IP 地址发现(PTR 记录)等
  • 可以通过修改 ConfigMap 来更改默认的 CoreDNS 行为
  • 通过DNSPolicy更改解析策略

Ingress

  • 基于7层的负载均衡,负责将流量转发到后端Service
  • 可以作为一种SLB方案在有限的程度上代替HLB,节省money和资源
  • 功能简单,弊端明显,仅支持80和443端口,7层上也只是做到了支持TLS,并不支持自定义的http方法,基于正则表达式的url匹配也没有简单的解决方案

API对象

  • 管理操作单元
  • 有四大类属性

***通用属性***

  • TypeMeta // kubernetes对象的最基本定义,通过引入GKV(Group,Kind,Version)模型定义了一个对象的类型
  • Group // 将对象根据功能范围归入不同分组,使得可维护性、可理解性更高
  • Kind // 定义一个对象的基本类型,Node\Pod\Deployment\...
  • Version // kubernetes版本
  • MetaData // 规定Namespace和Name
  • Label //标签,形式是键值对(key<=63bytes,value<=253)定义属性,用于API匹配过滤。
  • Annotation //作为属性扩展,注释
  • Finalizer //资源锁,如为空,则删除时只做逻辑删除,只是更新对象的metadata.deletionTimestamp字段
  • ResourceVersion //乐观锁,用于比对即将要创建的对象状态是否最新,如不是最新则通知控制器重新获取对象最新状态,从而提升系统效率

***私有属性***

  • Spec // 用户期望的状态
  • Status // 对象的实际状态



常用kubernetes对象及其分组

运维技术栈-Kubernetes原理_kubernetes_22


工作负载原理

Pod


Pod 启动流程

运维技术栈-Kubernetes原理_kubernetes_23


Pod的生命周期

Pod phase


kubectl get pod 返回的状态

Pod Phase 

Conditions

Completed

Succeeded


ContainerCreating

Pending


CrashLoopBackOff

Running

Container exits

CreateContainerConfigError

Pending

configmap/secret "name" not found

ErrImagePull

ImagePullBackOff

Init:ImagePullBackOff

InvalidImageName

Pending

Back-off pulling image

Error

Failed

restartPolicy:Never

container exits with Error(not 0)

Evicted

Failed

message: "Usage of EmptyDir volume "myworkdir" exceeds the limits "40Gi"."

reason:Evicted

Init:0/1

Pending

Init Containers don't exit

Init:CrashLoopBackOff

Init:Error

Pending

Init container crashed (exit with not 1)

OOMkilled

Running

Containers are OOMkilled

StartError

Running

Containers cannot be started

Unknown

Running

Node NotReady

OutOfCpu/OutOfMemory

Failed

Scheduled,but if cannot pass kubelet admit


QoS分类

Guaranteed, Burstable and BestEffort



High

Guaranteed

Pod的每个容器都设置了资源CPU和内存需求

Limits和requests的值完全一致

to

Burstable

至少一个容器制定了CPU或内存request

Pod的资源需求不符合Guaranteed Qos的条件,也就是requests和limits不一致

Low

BestEffort

Pod中的所有容器都未指定CPU或内存资源需求requests


  • 定义Guaranteed类型的资源需求来保护重要Pod
  • 合理设置limit和resource



spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed


spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable


spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort


还记得我们上面章节中提到的pod服务质量吗?有Guaranteed,Burstable和BestEffort 3种服务质量。

​驱逐pod的顺序就是根据pod的服务质量来排序的​​,大致顺序如下,这是我理解的:


  • 找出​​BestEffort​​​类型的pod和​​Burstable​​​类型​​超过出请求​​​的pod,这类pod按照​​优先级​​排序,优先级低的优先被驱逐,以此类推,直至满足驱逐信号。如果pod未设置的优先级则默认为0,驱逐顺序如下(当前所有pod的优先级都为0)

  • 先驱逐​​BestEffort​​类型的pod,驱逐顺序为pod请求内存从高到低依次逐出。
  • 如果逐出所有BestEffort类型的pod还没有满足,则开始逐出​​Burstable​​类型超出请求的pod,逐出顺序同样为请求从高到低。

  • 剩下的都是Guaranteed和 Burstable类型且其使用率低于请求的pod,​​正常低于请求值的pod是不会被驱逐的​​​。但是有一种特殊情况:如果系统守护进程(例如 kubelet、docker、和 journald)消耗的资源多于通过 system-reserved 或 kube-reserved 分配保留的资源时,为保持节点的稳定性并限制意外消耗对其他 pod 的影响,此时节点就会驱逐这些低于请求的pod,驱逐顺序为​​优先级​​由低到高。



作者:PENG先森_晓宇

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。





健康检查

健康检查探针类型分为

  1. livenessProbe
  1. 探活, 当检查失败时,意味着该应用进程已经无法正常提供服务,kubelet会终止该容器进程并按照restartPolicy决定是否重启
  1. readinessProbe
  1. 就绪状态检查,当检查失败时,意味着应用进程正常运行,但因为某些原因不能提供服务,Pod状态会被标记为NotReady
  1. startupProbe
  1. 在初始化阶段(Ready之前)进行的检查,避免过于高频的监测影响应用正常启动


探测方法:

  • ExecAction --运行命令,返回码为0判定成功
  • 运行一个容器,探测容器中某个文件是否一直存在,如该文件不存在了,就会触发重启
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5


  • TcpSocketAction --基于TCP检测IP:Port是否可达


apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
  • HTTPGetAction --针对服务URL发起Get请求,返回码200-400之间为成功
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3


区别理解:

  • LivenessProbe 基于应用进程是否启动判断应用是否正常,不正常重新启动
  • ReadnessProbe 基于应用能否提供服务判断是否就绪,不就绪不接受k8s的流量

定义就绪探测器

有时候,应用程序会暂时性的不能提供通信服务。 例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用程序,也不想给它发送请求。 Kubernetes 提供了就绪探测器来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。


说明: 就绪探测器在容器的整个生命周期中保持运行状态。

注意: 活跃性探测器 不等待 就绪性探测器成功。 如果要在执行活跃性探测器之前等待,应该使用 initialDelaySeconds 或 startupProbe。


readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5


  • startupProbe 在进程成功运行前规定一个等待时间,在这段时间内,liveness不激活,以避免liveness触发重启
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080

livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10

startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30 //失败次数超过30次后触发重启
periodSeconds: 10 //10s探测一次


initialDelaySeconds和StartupProbe的区别理解


initialDelaySeconds定义一个在执行liveness之前固定的等待时间, 这个时间是严格的,这段时间过后探测器才会激活

场景一:pod设定initialDelaySeconds 60s,而容器进程实际上3s就启动好了,就会导致60s秒内这段时间没法提供服务;

场景二:pod设定initialDelaySeconds 5s,而容器实际上需要花30s才能启动,那5s之后就会开始频繁探测;


而通过配置StartupProbe,就可以避免上述尴尬场景,StartupProbe是一个单独维度的监测机制,会独立于liveness去判断容器进程是否成功启动,这样liveness就只需要关注进程成功启动后的服务过程中,是否时刻处于正常状态;使用了Startup也不需要配置Delay等待,Startup会按照固定的频率自行判断是否启动成功了,这样就比Delay更加灵活.


探针属性


探针属性

描述

initialDelaySeconds

Defaults to 0 seconds.Minium value is 0

periodSeconds

Defaults to 10 seconds. Minium is 1

timeoutSeconds

Defaults to 1 second. Minium is 1

successThreshold

Defaults to 1.Must be 1 for liveness.Minium value is 1

failureThreshold

Defaults to 3. Minium is 1.


ReadinessGates


扩展属性, 可以通过指定外部的控制器来判断pod是否就绪, 从而实现一些特定的就绪检查判断


kind: Pod
...
spec:
readinessGates:
- conditionType: "www.example.com/feature-1"
status:
conditions:
- type: Ready # 内置的 Pod 状况
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
- type: "www.example.com/feature-1" # 额外的 Pod 状况
status: "False"
lastProbeTime: null
lastTransitionTime: 2018-01-01T00:00:00Z
containerStatuses:
- containerID: docker://abcd...
ready: true
...



Post-start 和 Pre-Stop Hook


apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]



Pres-Stop >>> kill -SIGTERM >>> kill -SIGKILL 从而实现优雅终止容器


  • bash 会忽略SIGTERM信号量, 因此kill -SIGTERM会永远超时, 若bash 作为 EntryPoint, 则应避免 grace period 过长





ReplicaSet(副本集)

副本集,把多个Pod作为副本集合到一起,确保副本数与用户期望一致

  • pod只是单个应用实例的抽象,而replica构建多个同样的应用副本,形成分布式高可用
  • 定义pod副本数
  • 这些pod之间是无状态的
  • 自动创建新副本,以满足用户定义的副本数
  • 通过调整副本数,进行便捷的扩缩容


Deployment(部署)

  • 表示对kubernetes集群的一次更新操作
  • 创建一个服务,更新一个服务,滚动升级一个服务
  • 滚动升级的逻辑就是依次更新多个旧副本
  • 与replicaset解耦,负责副本集以外的逻辑处理


StatefulSet(有状态服务集)


  • 需要根据某种数据同步状态信息到最新
  • 存储的形式下,启动新pod需要挂载源存储,读取上一次的数据,从而提供连续的服务
  • 适用于数据库、zookeeper、etcd等集群化服务
  • 概括说就是把pod和其依赖的存储关联到一起,以提供状态连续的服务
  • 会为pod编号,编号从0开始
  • yaml中定义volumeClaimTemplates
  • 升级策略
  • onDelete
  • 滚动升级
  • 分片升级


Job

  • 临时启动一批任务,任务执行完成后自动退出
  • spec.completions
  • 单个pod成功执行就标识完成
  • 定义x个任务成功执行则完成
  • 根据应用确认的全局成功则完成


DaemonSet

  • 支撑型服务
  • 保证每个node至少有一个此类Pod在运行
  • 典型场景
  • 存储
  • 日志
  • 监控


存储原理

PV

  • Persistent Volume(PV),持久化存储数据卷。这个 API 对象主要定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。
  • 通常情况下,PV 对象是由运维人员事先创建在 Kubernetes 集群里待用的。比如,运维人员可以定义这样一个 NFS 类型的 PV,如下所示
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.244.1.4
path: "/"

PVC(Persistent VolumeClaim)

  • PVC 描述的,则是 Pod 所希望使用的持久化存储的属性。比如,Volume 存储的大小、可读写权限等等。
  • PVC 对象通常由开发人员创建;或者以 PVC 模板的方式成为 StatefulSet 的一部分,然后由 StatefulSet 控制器负责创建带编号的 PVC。
  • 比如,开发人员可以声明一个 1 GiB 大小的 PVC,如下所示:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: manual
resources:
requests:
storage: 1Gi

storageclass

  • 批量创建一套PV的模板
  • 解放繁琐的手工操作

PV、PVC、StorageClass协同

  • 用户提交请求创建pod,Kubernetes发现这个pod声明使用了PVC,那就靠PersistentVolumeController帮它找一个PV配对。
  • 没有现成的PV,就去找对应的StorageClass,帮它新创建一个PV,然后和PVC完成绑定。
  • 新创建的PV,还只是一个API 对象,需要经过“两阶段处理”变成宿主机上的“持久化 Volume”才真正有用:
  • 第一阶段由运行在master上的AttachDetachController负责,为这个PV完成 Attach 操作,为宿主机挂载远程磁盘;
  • 第二阶段是运行在每个节点上kubelet组件的内部,把第一步attach的远程磁盘 mount 到宿主机目录。这个控制循环叫VolumeManagerReconciler,运行在独立的Goroutine,不会阻塞kubelet主循环。
  • 完成这两步,PV对应的“持久化 Volume”就准备好了,POD可以正常启动,将“持久化 Volume”挂载在容器内指定的路径。

ceph

glusterfs

secret

  • 存放密码、密钥、认证凭证
  • 避免写在配置文件

configmap

  • 存储为键值对
  • 作为pod的环境变量
  • 作为pod的命令行参数
  • 作为存储卷中的配置文件

configmap创建方式


  • 基于目录或文件创建,可以同时指定多个文件
kubectl create configmap nginx-config --from-file=/home/nginx/nginx.conf --from-file=/home/nginx/conf.d/ -n test


  • 基于命令行指定各个key-value方式
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm


  • yaml方式
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm


configmap使用方式


  • 作为环境变量方式
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never


  • 作为配置文件方式---nginx.conf 的使用
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:1.9
ports:
- containerPort: 8081
volumeMounts: --就是这一段使用configMap配置
- mountPath: /etc/nginx/conf.d --将配置文件挂载到哪里
name: config
- mountPath: /html --指定数据目录
name: data
volumes:
- name: data --指定数据目录创建
emptyDir: {}
- name: config --指定config使用configMap
configMap:
name: nginx-config --指定使用configMap中的nginx-config配置
items: --注:也可不指定items,那默认是nginx-config里的所有值都挂载
- key: nginx.conf --使用nginx-config配置的nginx.conf键里的内容
path: nginx.conf
-----------------------------------
©著作权归作者所有:来自51CTO博客作者文尔的原创作品,如需转载,请注明出处,否则将追究法律责任
kubernetes的配置中心configmap
https://blog.51cto.com/passed/2348256




CRD(CustomResourceDefinition)


  • 允许用户自定义Schema
  • 控制器开发
  • 对象开发

常用命令

kubectl exec 

打开debug日志
kubectl get xxx -v 9

# 查看对象yaml文件
kubectl get xxx -o yaml

# 查看对象及扩展信息,如IP,所在节点等
kubectl get xxx -o wide

# 监视变化
-w watch

# 查看对象详细状态信息描述
kubectl describe

# 查看对象日志
kubectl logs

# 类似docker run的方式启动容器
kubectl run --image=nginx:alpine nginx-app --port=80

# 端口映射,创建对外服务
kubectl expose deployment nginx-app --port=80 --target-port=80

kubectl describe svc

# 查看所有的endpoints
kubectl describe ep

# 级联删除

常见发布故障

运维技术栈-Kubernetes原理_kubernetes_24


运维技术栈-Kubernetes原理_kubernetes_25


Metrics

部署metrics组件后,通过kubectl top pods pod_name 可以获取到容器的资源使用情况,进行监控

实现的原理

  • kubeapiserver 捕获 kubectl top 命令,转给 metrics组件执行,
  • metrics 组件访问以下url就可以获取到资源使用信息
  • 这个url还可以通过以下命令获取

 #  kubectl get --raw "/api/v1/nodes/<node_Name>/proxy/metrics/resource"


HPA

算法原理

期望副本数 = ceil[当前副本数*(当前指标/期望指标)]


参数

--horizontal-pod-autoscaler-downscale-stabilization 设置扩容冷却时间窗口长度


扩展功能-平滑扩容

behavior:
scaleDown:
policies:
- type: Pods
value: 4
periodSeconds: 60
- type: Percent
value: 10
periodSeconds: 60