作为一个久负盛名的容器编排平台,Kubernetes具有很多优势,其自动化能力尤其突出,具体体现在工作负载的发现、自愈和应用伸缩等方面。,然而,Kubernetes也在不断地进行升级,并不总是能开箱即用地用于生产环境。,本文提供了一系列应当重点考虑的Kubernetes最佳实践,用以提高您的 K8s 的安全性和性能,并控制成本。,,通常,应该始终将 K8s 升级到最新稳定版本,以应用最新的安全或性能的修复与改进,也会获得更多来自社区和供应商提供的支持,从而避免可能危及服务交付的安全和性能问题,以及成本方面的异常。,,可能你觉得 YAML 很难使用,那么不妨用一下 yamllint,它可以在一个文件中处理多个文档。,还有专门针对 Kubernetes 的 linter。比如,你可以使用 kube-score 来分析你的清单,从而遵循最佳实践。 Kubeval 也能用来分析你的清单,但是它只是检查有效性。Kubernetes 1.13 的 kubectl 提供的 dry-run 也可以用来检测清单而不实际应用它,所以,也可以使用这个特性来检查你为 K8s 准备的 YAML 文件。,,最好将 Deployment、Service 和 Ingress 等所有配置文件存储在版本控制系统中。Github 是最流行的开源分布式版本控制平台,也可以使用 Gitlab、BitBucket 和 SourceForge 等其它平台。,要在将代码推送到 Kubernetes 集群之前就对它们进行版本化管理,这样就可以跟踪代码的变更内容及变更人。这样做,你就可以快速回滚更改、重建或恢复集群,来确保稳定性和安全性。,,在 GitOps,或者是基于 Git 的工作流中,Git 是唯一的真实来源,因而是用于自动化包括 CI/CD 管道等所有任务的优秀模型。,而除了可以提升生产力,GitOps 还有助于加快部署和增强错误跟踪,并使 CI/CD 工作流程自动化,同时简化集群管理,加快应用开发。,应当编写声明性的 YAML 文件加上 kubectl apply 命令来将对象添加到集群,而不是直接使用 kubectl run 的命令性方式。声明式方法允许您指定所需达到的目标状态,剩下的交给 Kubernetes 自己来决定如何达到这个状态。,这样,所有的对象,就和代码一样,可以被保存在 YAML 文件中,并进行版本控制。一旦出现错误,就可以通过恢复之前的 YAML 文件并重新应用它们来轻松地回滚部署。而且,采用这个模式,可以确保团队能够看到集群的当前状态,以及随着时间的推移做出的所有更改。,,在为资源定义需求或上限时,Millicores 作为 CPU 的单位,而 MB 可用作内存的单位。如果资源需求超出了限制,那么容器将不会在吊舱中运行。,当资源稀缺时,如果没有配置资源需求和限制,生产集群就可能会失败。而资源充足时,多余的资源会被没有配置资源限制的 Pod 消耗掉,从而增加 Kubernetes 的使用成本。另外,如果 Pod 消耗了太多的 CPU 或内存,并且调度程序无法添加新的 Pod,则可能出现节点崩溃的情况。,,要尽可能避免使用裸露的豆荚,否则,在节点失败的情况下,将无法重新调度它们,仅仅因为它们没有被绑定到 Deployment 或 ReplicaSet。,Deployment 用于创建 ReplicaSet 来保持所需的 Pod 数量,并定义 Pod 替换策略,如 RollingUPdate。,除非有严格的重新启动策略,否则 Deployment 几乎总是比直接创建 Pod 更为有效。,,Label 是可以帮助您识别 Kubernetes 集群中特定资源的键值对,还可以用在 kubectl 命令上来过滤和选取对象,允许根据特定特征快速识别对象。,即使你觉得暂时不会用到它们,但用 Label 为你的对象打上标签绝对是个好主意。另外,要使用尽可能多的描述性标签来区分团队要使用的资源。比如可以按所有者、版本、实例、组件、管理者、项目、团队、机密级别等等来进行标记。,,活性探测器(Liveness probes)会定期检查长期存活 Pod 的健康状况,避免 Kubernetes 将流量导向不健康的 Pod。在默认情况下,Kubernetes 会重新启动未通过健康检查的 Pod,来确保应用程序的可用性。,探测器会向 Pod 发送一个 ping 信号,然后看是否可以接收到响应。如果没有响应,则表明应用程序没有在那个 Pod 中运行,导致探测器启动一个新 Pod,并在那里运行应用程序。,另外,必须首先运行启动探测器(startup probe),这是第三种探测器,当 Pod 的启动过程完成时,它会通知 Kubernetes。如果 Pod 的启动探测器不完整,活性探测器(Liveness probes)和就绪探测器(readiness probes)就不会起作用。,,命名空间可以在逻辑上将集群划分为子集群。当希望同时在多个项目或团队之间共享 Kubernetes 集群时,命名空间就非常有用。有了命名空间,开发、测试和生产团队就可以在同一个集群内协作,而不会覆盖或干扰彼此。,Kubernetes 自身提供了 default、kube-system 和 kube-public 三个命名空间。一个集群支持逻辑上独立但彼此可以通信的多个命名空间。,,无状态应用通常比有状态应用更容易管理,尽管这种情况正在随着 Kubernetes Operators 越来越受欢迎而改变。,无状态后端可以不再需要刚开始使用 Kubernetes 的团队来维护对伸缩性有限制的长连接。,无状态应用也使得按需迁移和扩展变得更为容易。,另外,保持工作负载的无状态还允许使用 Spot Instance(AWS、Azure 等云提供商的一种优惠计价方式)。,Spot Instance 的缺点在于,像 AWS 和 Azure 这样的提供商经常需要在短时间内回收廉价的计算资源,这样就会干扰工作负载,而使应用成为无状态,就可以避免这个问题。,,Kubernetes 的网络策略规定了哪些流量是允许的,哪些是不允许的。这类似于在 Kubernetes 集群的 Pod 之间设置防火墙。无论流量在 Pod 之间如何移动,只有在网络策略准许的情况下才被允许。,在创建网络策略之前,必须定义经过授权的连接并制定策略应该应用在哪些 Pod,由此过滤掉不符合标准的流量。,根据 Redhat 在2022年对300多名DevOps专业人士的调查,几乎所有被调查人(94%)在前一年至少发生过一次 Kubernetes 安全事件。,可以使用 RBAC 来制定哪些用户可以访问哪些 Kubernetes 资源,比如他们可以访问哪些集群,谁可以进行更改,以及可以在多大程度上进行更改。,RBAC 权限可以通过两种方式配置:,这是另一个重要的 Kubernetes 最佳安全实践。,除了要控制集群内部流量的网络策略之外,还要在集群前面设置一道防火墙,以限制访问 API 服务的外部请求。这可以使用常规或端口防火墙规则来实现。,另外,确保访问者 IP 地址在白名单中,并且服务器开放端口是受限的。,镜像需要是小而且分层的。镜像越小,其构建速度越快,所需的存储空间越少。镜像尺寸可以通过有效的分层来显著减小。,怎么做到?,如果需要许多不同的组件,可以在一个 Dockerfile 中使用多个 FROM 语句。安装程序将基于 FROM 命令从已部署的容器提取每一层。由此产生的 Docker 容器更小,因为它不再包含以前的层,而只包含需要的组件。
© 版权声明
文章版权归作者所有,未经允许请勿转载。