使用 Kubernetes 最容易犯的 10 个错误!

标签: kubernetes 云原生-cloud-native | 发表时间:2020-07-09 10:22 | 作者:K8SMeetup社区
出处:https://segmentfault.com/blogs
作者: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...

相关 [kubernetes 错误] 推荐:

最全Kubernetes加固指南:12个最佳实践,防止Kubernetes配置错误

- - DockOne.io
在容器环境中,Kubernetes管理着拥有数个、数百个甚至数千个节点的容器集群,其配置的重要性不可忽略. Kubernetes的配置选项很复杂,一些安全功能并非默认开启,这加大了安全管理难度. 如何有效地使用包括Pod安全策略、网络策略、API服务器、Kubelet及其他Kubernetes组件和功能策略建立安全的Kubernetes环境.

使用 Kubernetes 最容易犯的 10 个错误!

- - SegmentFault 最新的文章
作者:Tj Blogumas 翻译: Bach( 才云). 校对: 星空下的文仔( 才云)、 bot( 才云). 在多年使用 Kubernetes 的过程中,我们接触了相当多的 K8s 集群,同样也犯了许多错误. 本文就介绍了那些最容易也最常犯的 10 个错误,并讨论了要如何解决.

Kubernetes & Microservice

- - 午夜咖啡
这是前一段时间在一个微服务的 meetup 上的分享,整理成文章发布出来. 谈微服务之前,先澄清一下概念. 微服务这个词的准确定义很难,不同的人有不同的人的看法. 比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界.

Kubernetes学习(Kubernetes踩坑记)

- - Z.S.K.'s Records
记录在使用Kubernetes中遇到的各种问题及解决方案, 好记性不如烂笔头. prometheus提示 /metrics/resource/v1alpha1 404. 原因: 这是因为[/metrics/resource/v1alpha1]是在v1.14中才新增的特性,而当前kubelet版本为1.13.

kubernetes移除Docker?

- -
两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时. 这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用. 看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定.

Kubernetes 完全教程

- - 午夜咖啡
经过一个阶段的准备,视频版本的 《Kubernetes 完全教程》出炉了. 课程一共分为七节,另外有一节 Docker 预备课,每节课大约一个多小时. 目标是让从没接触过 Kubernetes 的同学也能通过这个课程掌握 Kubernetes. 为什么要学习 Kubernetes. 在介绍课程之前,先说说为什么要学习 Kubernetes 以及什么人需要学习 Kubernetes.

Kubernetes 监控详解

- - DockOne.io
【编者的话】监控 Kubernetes 并不是件容易的事. 本文介绍了监控 Kubernetes 的难点、用例以及有关工具,希望可以帮助大家进一步了解监控 Kubernetes. 如果想要监控 Kubernetes,包括基础架构平台和正在运行的工作负载,传统的监控工具和流程可能还不够用. 就目前而言,监控 Kubernetes 并不是件容易的事.

Kubernetes 切换到 Containerd

- - bleem
由于 Kubernetes 新版本 Service 实现切换到 IPVS,所以需要确保内核加载了 IPVS modules;以下命令将设置系统启动自动加载 IPVS 相关模块,执行完成后需要重启. 重启完成后务必检查相关 module 加载以及内核参数设置:. 1.2、安装 Containerd. Containerd 在 Ubuntu 20 中已经在默认官方仓库中包含,所以只需要 apt 安装即可:.

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

喜大普奔:Spark on kubernetes

- - Zlatan Eevee
两个星期前(08/15/2017),spark社区提了一个新的SPIP(Spark Project Improvement Proposals): Spark on Kubernetes: Kubernetes as A Native Cluster Manager,即用k8s管理spark集群. 经过社区2个星期的投票,看上去很快要能合入了.