共计 4169 个字符,预计需要花费 11 分钟才能阅读完成。
作者:Tj Blogumas
翻译:Bach(才云)
校对:星空下的文仔(才云)、bot(才云)
在多年应用 Kubernetes 的过程中,咱们接触了相当多的 K8s 集群,同样也犯了许多谬误。本文就介绍了那些最容易也最常犯的 10 个谬误,并探讨了要如何解决。
资源申请和限度
这相对是犯错榜单的第一名。 设置 CPU 申请有两种常见谬误:不设置或者设置的很低。 尽管这样能够在每个节点上包容更多的 Pod,但会导致节点的适度应用。在高需要期间,节点的 CPU 会被齐全占用,工作负载取得的申请资源会受到 CPU 限度,从而导致应用程序提早、超时等状况。
不设置 CPU 申请的配置:
resources: {}
CPU 申请设置很低的配置:
resources:
另一方面,即便节点的 CPU 没有充分利用,如果设置了不必要的 CPU 限度同样会限度 Pod,这也会导致提早减少。
内存的适量应用一样会带来许多问题。 达到 CPU 限度值会导致提早,而达到内存限度值,Pod 会被间接杀死,这就像是 OOMkill,一个内存不足时会主动杀死过程的机制。如果不想产生这样的事件,就不要适度应用内存,而应该应用 Guaranteed QoS,设置内存申请值等于限度值。
Burstable QoS 下的资源设置:
resources:
Guaranteed QoS 下的资源设置:
resources:
在设置资源时,咱们能够应用 metrics-server 查看容器以后 CPU 和内存的应用状况。如果它曾经在服务器端运行,能够运行以下命令:
kubectl top pods
通过显示的以后应用状况,咱们就能够大抵理解资源状况了。如果想要及时查看状况指标,例如峰值,昨天晚上的 CPU 应用状况等,咱们能够应用 Prometheus、DataDog 等。它们会从 metrics-server 中获取指标并进行存储,而后咱们就能够查问或绘制图形。另外,VerticalPodAutoscaler 工具能够帮忙咱们自动化地查看 CPU、内存的应用状况,并依据状况从新设置新的申请值和限度。
liveness 和 readiness 探针的设置
默认状况下,零碎不会设置 liveness 和 readiness 探针。K8s 弱小的自愈能力有时候能够让容器始终工作上来。但如果呈现不可复原的谬误时,服务要如何重新启动?负载均衡器如何判断 Pod 是否能够开始解决流量,是否能够持续解决更多流量?
很多人不晓得 liveness 和 readiness 探针之间的区别:
- 如果对 Pod 的 liveness 探测失败,会重新启动该 Pod
- 如果对 Pod 的 readiness 探测失败,会将 Pod 和 Kubernetes 断开连接(能够应用 kubectl get endpoints 进行查看),并且在下次探测胜利之前,都不会发送流量
留神,这两种探针要在 Pod 整个生命周期中运行。
很多人只晓得 readiness 的一个利用场景:readiness 探针在容器启动时运行,以告知 K8s 服务 Pod 何时就绪,能够开始为流量提供服务。
它的另一个利用场景是通知用户,在 Pod 的生命周期内,Pod 有没有因为太“热”而无奈解决过多的流量,须要缩小工作“沉着”一下。直到 readiness 探测胜利时,咱们再持续给 Pod 发送更多流量。 在这种状况下,readiness 探测失败就会事与愿违,因为咱们不须要重新启动这个运行状况良好的 Pod。
有时候,不配置任何探针会比配置谬误探针要好。就像下面说的,如果将 liveness 探针配置成和 readiness 探针一样,那么会导致很多问题。一开始倡议仅配置 readiness 探针,因为 liveness 探针很危险。
如果有一个和其余 Pod 有共享依赖项的 Pod 被敞开,咱们就要保障这个 Pod 的任何一个探针都不能失败,否则将导致所有 Pod 的级联生效,这就像是搬起石头砸本人的脚。
HTTP 服务的负载均衡器
咱们可能在集群中有更多的 HTTP 服务,并对外开放。如果将 Kubernetes 服务设置为 type: LoadBalancer
,那么其控制器将提供并配置一个内部负载均衡器(不肯定是 L7 负载均衡器,有可能是 L4 负载均衡器),并且这些资源(内部动态 IPv4 地址、计算硬件等)可能会变得很贵,因为创立了很多这样的服务。
在这种状况下,咱们将内部拜访形式设置为 type: NodePort
,并共享一个内部负载均衡器会更好。另外,还有一个其余不错的办法是部署一个相似 Nginx-ingress-controller(或 traefik)的货色作为裸露给内部负载均衡器的单个 NodePort endpoint,并依据 Kubernetes ingress resource 配置在集群中调配路由流量。
集群内的(微)服务能够通过 ClusterIP 服务和 DNS Service Discovery 进行通信。留神不要应用公共 DNS/IP,这会影响提早并减少云老本。
无 K8s 感知的集群主动伸缩
在集群中增加节点或从集群中删除节点时,不应只思考节点 CPU 使用率等简略指标。在调度 Pod 时,咱们须要依据许多调度束缚(例如 Pod 和节点的亲和力、taints、tolerations、资源申请、QoS 等)来决定。
假如有一个新的 Pod 要调度,然而所有可用的 CPU 都被占用,并且 Pod 处于 Pending 状态。内部主动伸缩器看到以后应用的 CPU 均匀使用率十分高,就不会扩大(不会将 Pod 增加为节点),也就是说该 Pod 不会被调度。
扩大(从集群中删除节点)总是会更加艰难。假如有一个有状态的 Pod 已连贯长久卷,因为长久卷通常属于特定的可用性区域,并且不能在该区域中复制,因而自定义主动伸缩器删除带有该 Pod 的节点时,调度程序会无奈将其调度到另一个节点上,因为它受到长久卷惟一可用性区域的限度,Pod 会再次卡在 Pending 状态。
K8s 社区宽泛应用集群主动伸缩器,它运行在集群中,并与大多数次要私有云供应商的 API 集成,能够了解这些限度,并且在上述情况下进行扩大。另外,它还会确定是否能够在不影响设置的状况下失常扩大,以节俭计算成本。
不应用 IAM、RBAC 的性能
不要将具备永恒 secret 的 IAM User 用于机器和应用程序,而应该应用角色(role)和服务帐号(service account)生成的长期 secret。
咱们常常看到这种状况:在应用程序配置中对拜访权限和密钥进行硬编码,应用 Cloud IAM 时就永远不轮换 secret。咱们应该在适当的中央应用 IAM Roles 和服务帐户代替 IAM User。
跳过 kube2iam,间接应用服务帐户的 IAM Roles。
apiVersion: v1
另外,在不是必要时,千万不要将 admin 和 cluster-admin 的权限给予服务帐户或实例配置文件。
Pod 亲和性
运行某个部署的 3 个 Pod 正本时,如果该节点下线,所有正本都将会随之下线。咱们不能指望 Kubernetes 调度器对 Pod 强加亲和性设置,而要本人明确定义它们。
// omitted for brevity
这样能够确保将 Pod 调度在不同的节点上(仅在调度工夫,而不是在执行工夫进行查看,因而要设置 requiredDuringSchedulingIgnoredDuringExecution
)。
没有 PodDisruptionBudget
在 Kubernetes 上运行生产工作负载时,节点和集群必须不断地降级或停用。PodDisruptionBudget(PDB)是一种 API,为集群管理员和集群用户提供服务保障。
确保创立 PDB 以防止因为节点停用而造成不必要的服务中断。
apiVersion: policy/v1beta1
作为集群用户,咱们就能够通知集群管理员:“嘿,我这里有个 zookeeper 服务,无论要做什么,都至多要有 2 个正本始终可用。”
共享集群中太多租户或环境
Kubernetes 命名空间不提供任何强隔离。 大家通常认为,如果将非生产工作负载拆散到一个命名空间,而后再将生产工作负载拆散到另一个命名空间,那么二者就永远不会相互影响,这样就能够实现某种程度的偏心调配,比方资源的申请和限度、配额、优先级等,并实现隔离(比方 affinities、tolerations、taints 或 nodeselectors),进而“物理地”拆散数据立体上的负载,但这种拆散是相当简单的。
如果须要在同一集群中同时应用两种类型的工作负载,咱们就必须承当这种复杂性。如果不须要这样,并且再用一个集群老本更低时(例如在私有云中),那么最好将其放在另一个集群中以实现更高的隔离级别。
externalTrafficPolicy:Cluster
咱们常常看到这种状况,所有流量都在集群内路由到 NodePort 服务上,该服务默认 externalTrafficPolicy: Cluster
,这意味着集群中的每个节点都关上了 NodePort,这样能够应用任何一个与所需的服务(一组 Pod)进行通信。
通常,NodePort 服务为针对的 Pod 仅运行在那些节点的子集上。这意味着,如果与未运行 Pod 的节点通信,它会将流量转发到另一个节点,从而导致额定的网络跳转并减少提早。
在 Kubernetes 服务上设置 externalTrafficPolicy: Local
后就不会在每个节点上关上 NodePort,只会在理论运行 Pod 的节点上关上。如果应用内部负载均衡器对其终端节点进行查看,它会仅将流量发送到应该去往的那些节点,能够改善提早并缩小计算开销和进口老本。
把集群当宠物,管制立体压力大
大家有没有这样的经验:给服务器取一些奇怪的名字;给节点随机生成 ID;亦或者因为一开始用 Kubernetes 做验证,所以给集群取名“testing”,后果到生产环境还在应用“testing”名字。
把集群当宠物可不是开玩笑的,咱们须要不断地删除集群,演练劫难复原,并管理控制立体。另一方面,过多地应用管制立体也不是一件坏事。随着工夫的流逝,管制立体变慢了,很可能就是咱们创立了很多对象但没有轮换它们。
总结
不要指望所有都会主动解决,Kubernetes 并不是万能的。即便在 Kubernetes 上,蹩脚的利用一样是蹩脚的利用,一不小心,就可能会导致很多简单问题。心愿本文总结的十个常见谬误,能够对你带来帮忙。
https://medium.com/devops-dud…