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