Kubernetes应用最佳实践

小白debug 2023-09-22 08:15

概述

本文从应用开发人员的角度,总结一下 Kubernetes 的业务开发中的最佳实践,本文不会展示任何相关的 kubelet 命令以及 yaml 格式文件,通过尽可能精简篇幅来提高读者阅读体验和效率。

面向开发人员的 Kubernetes 资源结构图

Namespace

Kubernetes 通过 Namespace 将资源进行逻辑上的隔离,默认情况下集群中有三个命名空间:default、kube-public 和 kube-system, 通常情况下,有一个非生产的 Kubernetes 集群用于特定环境 (开发、测试、集成),如果出于成本和业务服务独立性考虑,将生产和非生产环境混合到一个集群中, 则应该建立新的 Namespace 来进行业务服务区分与隔离,例如常见的 Namespace 是 testprod

此外,建立新的 Namespace 之后,应该为不同的 Namespace 来配置不同的资源配额和资源限制。例如给测试环境分配较少的资源额度,给生产环境分配较多的资源额度, 这样即使在测试环境对某个服务进行压测,也不会影响到生产环境。

阿里云 Kubernetes 集群命名空间与配额

使用 RBAC 进行访问控制

Kubernetes 中支持使用 RBAC 为集群中的用户和组定义细粒度的访问控制规则,例如可以将无状态应用、有状态应用、路由管理的功能开放给开发人员,将命名空间、资源配额与限制的功能开放给运维人员。

Pod

将 Pod 视为独立的机器,并将单个应用或者多个紧密耦合的应用放入单个 Pod 中。

对于多层应用,应该分散放到多个 Pod 中,典型的如 Web 应用,应该将前端页面、后端接口、缓存、数据库分别放入不同的 Pod 中。此外,不要将应用部署到单独的 Pod 中,在保持应用可以水平扩展的前提下:

  • 使用 Deployment 部署无状态应用
  • 使用 StatefulSet 部署有状态应用

如何判定单个 Pod 中是否应该放入多个容器?这里给出几个判断条件:

  • 多个应用需要一起运行还是相互独立运行?
  • 多个应用表示的是一个整体应用还是相互独立的组件?
  • 多个应用是否可以一起扩容还是需要独立进行?(例如多个生产者,单个消费者的应用场景)

组合大于继承

这条软件设计原则针对 Pod 依然适用,大多数情况下,单个应用容器都是最佳实践,对于某些多应用容器场景,可以通过将辅助容器中的应用使用子进程的方式运行,这样就可以将多个容器应用集成到一个容器应用中。


容器

每个容器中的应用都应该遵循单一职责,只负责一个功能或执行一项任务。如果应用内部发生不可恢复的错误,应该让它崩溃并自动退出,Kubernetes 会自动重启该容器。

避免以 root 身份运行

容器共享主机的内核,因此隔离程度无法到达虚拟机级别,安全的策略就是禁止使用 root 身份运行应用。

镜像优化

应该尽可能缩小镜像体积,因为当集群自动扩容添加新节点时,新节点必须下载容器镜像。容器的镜像体积越小,节点下载速度越快,应用的启动速度也就越快。

如果 CRI 容器使用的是 Docker,可以参考之前的 Docker 最佳实践[1]

镜像仓库

如果所在企业没有自己的基础设施团队,建议镜像仓库和云服务器的提供商保持一致,这样保证镜像仓库高可用的同时,可以节省带宽费用并提升镜像拉取速度 (因为走的是内网)。

镜像标签和拉取策略

网上大多数文章会提到 不要使用 latest 作为镜像标签,笔者不是特别认同,还是需要具体情况具体分析,笔者的建议是:

  1. 首先保证镜像仓库的高可用和访问速度,这是重中之重,如果这一点做到了,那么可以使用 latest 标签并将镜像拉取策略 imagePullPolicy 设置为 Always
  2. 对于测试环境,直接使用 latest 标签并将 imagePullPolicy 设置为 Always, 配置 CI 构建脚本在打包应用镜像时,除了 latest 标签镜像外,再额外打包一个以 git commit 哈希值作为标签的镜像 (回滚时专用镜像)
  3. 对于生产环境,使用应用迭代版本号作为镜像的标签

使用多维度而不是单维度的标签

维度名称
发布版本release"stable", "canary"
发布环境environment"dev", "qa", "production"
应用类型tier"frontend", "backend", "cache"

Deployment

对于无状态应用,直接使用 Deployment 部署。

阿里云 Kubernetes Deployment 滚动升级策略

下面主要说下几个重要的参数。

replicas

Pod 的副本数量。

maxUnavailable

指定滚动更新过程中不可用的 Pod 数量上限,数值可以是绝对数字,也可以是百分比 (最终会转换成数字),例如 Pod 数量为 10, maxUnavailable 值的 30%, 那么在滚动升级过程中,始终保证可用的 Pod 数量为 7 。

maxSurge

指定可以创建超出 replicas 的 Pod 数量,数值可以是绝对数字,也可以是百分比 (最终会转换成数字),例如 Pod 数量为 10, maxSurge 值为 30%, 那么在滚动升级过程中,始终 Pod 最大数量不超过 13 。

在滚动升级期间设置合理的 maxUnavailable 和 maxSurge 值,在资源消耗和保证服务可用性之间取得平衡。

minReadySeconds

指定新创建的 Pod 的最小就绪时间,只有超过这个时间 Pod 才会被认为可用,使用该参数更好掌握升级部署过程,避免 Pod 中的进程启动后立即接受流量导致错误,同时减缓滚动升级的速率。

通常情况下需要根据业务场景计算出应用的初始化时间上限,同时还要考虑到应用的就绪时间条件,通过两者的综合考量,将 minReadySeconds 值设置地尽量高一些。

progressDeadlineSeconds

默认情况下, 10 分钟内无法完成滚动升级将被判定为失败,对于大多数无状态应用来说这个时间太长了,可以更新 spec.progressDeadlineSeconds 来自定义超时时间。

Recreate 策略

Deployment 的默认策略是 RollingUpdate, 也就是滚动升级。

此外还可以将策略设置为 Recreate, Recreate 策略首先终止当前版本中的所有 Pod,然后创建并启动新 Pod, 两个过程之间会有一定的服务不可用空窗期, 该策略的应用场景是: 无法接受应用在滚动升级策略中同时存在的两个版本,并且可以接受一定的服务不可用空窗期 (例如金融相关业务),可以在业务低峰期采用这种策略,并在用户界面给出对应的维护公告。

DaemonSet

将所有由 systemd 管理的进程使用 DaemonSet 管理

ConfigMap

针对不同的环境单独配置 ConfigMap, 可以将多个小的配置文件合并到一个大的配置文件中,参考 这个示例[2]

配置热更新

热更新 ConfigMap 会导致应用重新加载新的配置,但不会触发应用程序重启。

  1. 创建一个 ConfigMap 对象,包含应用的配置数据
  2. 在 Pod 配置中,将 ConfigMap 挂载为一个卷(Volume), 应用可以直接从卷中读取配置数据
  3. 当配置数据需要更新时,修改 ConfigMap
  4. 修改 ConfigMap 后,Kubernetes 会自动触发相关的事件,通知 Pod 更新其挂载的卷
  5. Pod 接收到更新事件,重新加载卷中的配置文件,从而实现配置热更新

图片来源: https://www.manning.com/books/kubernetes-in-action-second-edition

Secret

确保采用 Secret 的方式存储敏感数据,禁止使用环境变量、自定义加密方式等毫无意义的奇技淫巧。同时限制特定容器集合才能访问 Secret, 读取 Secret 之后保持只读状态,避免以明文存储 Secret 数据或将 Secret 传输给第三方。

注意: Secrets 默认情况下采用 base64 编码存储非加密的形式存储在 etcd 中,需要配置为静态加密方式


Job

正常情况下,Job 会在 Pod 中运行直到完成,但是,如果节点发生故障,或者当 Pod 在运行时被驱逐出节点时,调度器会将 Job 放在一个新的节点上重新运行。所以 Job 要保证幂等性 (例如创建数据表时的 IF NOT EXISTS 判断语句),并且在状态为失败时自动停止,不再重新启动 (将 Restart Policy 配置为 Never)。对于涉及到网络请求的 Job, 笔者的建议是 将请求重试等策略放在应用代码中,而不是通过配置 Job 的 Restart Policy 来完成

比较重要的两个声明字段:

  • spec.completions: 指定 Job 需要运行的次数
  • spec.parallelism: 指定 Job 并行数量

CronJob

将周期性的自动化任务通过 CronJob 来执行,例如数据备份、回归测试、日志分析、运营数据邮件、已有 Cron 任务的迁移等。

注意: 因为工作节点本身受到资源使用和调度的限制,所以可能发生 Job 运行时间延时的情况 (和在应用层使用的定时任务组件延时情况类似),如果 Job 本身有较高的时间敏感度, 可以通过指定 startingDeadlineSeconds 字段来指定 Job 运行截止日期,这样的话,如果 Job 运行时会检测,如果运行时间大于截止日期,Job 将不再运行并且直接标记状态为失败。

此外,不应该将 Job 的运行时间作为业务时间序列属性,对于多副本运行的 Job 要保证幂等性

不管是传统的 Linux Cron 任务,还是通过守护进程 + 定时器组件模式,亦或是 Kubernetes 中的 Job, 这些都只是具体的运行时载体,最重要的是保证业务代码的健壮性。

日志

将 Pod 内应用日志输出到文件或标准输出,然后通过日志采集组件,最后将日志数据发送到自建日志仓库或云服务商提供的日志聚合服务。

防火墙和网络策略

大多数情况下,使用云服务商提供的默认配置就可以满足需求,如果需要自定义网络策略,可以参考 官方文档[3]

监控集群

监控 Kubernetes 集群对于确保应用程序的运行状况和性能至关重要,使用 Prometheus、Grafana 等工具或云服务商提供的原生监控解决方案,来收集和分析集群中的指标, 例如 CPU 使用率、内存使用率和网络流量等,同时设置警报和主动通知方式,保证集群出现任何问题时收到通知。

集群伸缩

集群伸缩可以自动添加或者删除工作节点,需要主要的是: 如果遇到业务在某个时刻流量突增的场景,则最好提前手动添加节点,毕竟新节点从启动到加入到集群并开始接收流量也需要时间,提前增加节点可以避免突增的流量造成负载过大甚至宕机。

升级到稳定的新版本

新的版本除了引入新功能之外,还包括漏洞和安全修复,可以定期升级到最新的稳定版本,享受官方升级带来的红利。担心已有组件和新版本不兼容?主流云服务商都有兼容性自动检测功能,直接使用即可。

小结

随着微服务架构的普及,实现一个简单的服务都需要对云原生中涉及到的分布式技术栈和容器编排基础知识有较深入的理解。因此,开发人员必须精通现代编程语言来实现业务功能,并且同时精通云原生技术来解决非功能性需求。

评论
  • 本文继续介绍Linux系统查看硬件配置及常用调试命令,方便开发者快速了解开发板硬件信息及进行相关调试。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。查看系统版本信息查看操作系统版本信息root@ido:/# cat /etc/*releaseDISTRIB_ID=UbuntuDISTRIB_RELEASE=20.04DISTRIB_CODENAME=focalDIS
    Industio_触觉智能 2025-01-03 11:37 137浏览
  • 前言近年来,随着汽车工业的快速发展,尤其是新能源汽车与智能汽车领域的崛起,汽车安全标准和认证要求日益严格,应用范围愈加广泛。ISO 26262和ISO 21448作为两个重要的汽车安全标准,它们在“系统安全”中扮演的角色各自不同,但又有一定交集。在智能网联汽车的高级辅助驾驶系统(ADAS)应用中,理解这两个标准的区别及其相互关系,对于保障车辆的安全性至关重要。ISO 26262:汽车功能安全的基石如图2.1所示,ISO 26262对“功能安全”的定义解释为:不存在由于电子/电气系统失效引起的危害
    广电计量 2025-01-02 17:18 218浏览
  • 在快速发展的能源领域,发电厂是发电的支柱,效率和安全性至关重要。在这种背景下,国产数字隔离器已成为现代化和优化发电厂运营的重要组成部分。本文探讨了这些设备在提高性能方面的重要性,同时展示了中国在生产可靠且具有成本效益的数字隔离器方面的进步。什么是数字隔离器?数字隔离器充当屏障,在电气上将系统的不同部分隔离开来,同时允许无缝数据传输。在发电厂中,它们保护敏感的控制电路免受高压尖峰的影响,确保准确的信号处理,并在恶劣条件下保持系统完整性。中国国产数字隔离器经历了重大创新,在许多方面达到甚至超过了全球
    克里雅半导体科技 2025-01-03 16:10 117浏览
  • 光耦合器,也称为光隔离器,是一种利用光在两个隔离电路之间传输电信号的组件。在医疗领域,确保患者安全和设备可靠性至关重要。在众多有助于医疗设备安全性和效率的组件中,光耦合器起着至关重要的作用。这些紧凑型设备经常被忽视,但对于隔离高压和防止敏感医疗设备中的电气危害却是必不可少的。本文深入探讨了光耦合器的功能、其在医疗应用中的重要性以及其实际使用示例。什么是光耦合器?它通常由以下部分组成:LED(发光二极管):将电信号转换为光。光电探测器(例如光电晶体管):检测光并将其转换回电信号。这种布置确保输入和
    腾恩科技-彭工 2025-01-03 16:27 155浏览
  • 在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容,修改源码再编译很费时。今天为大家介绍一个便捷的方法,让OpenHarmony通过挂载镜像来修改镜像内容!触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器,树莓派卡片电脑设计,支持开源鸿蒙OpenHarmony3.2-5.0系统,适合鸿蒙开发入门学习。挂载镜像首先,将要修改内容的镜像传入虚拟机当中,并创建一个要挂载镜像的文件夹,如下图:之后通过挂载命令将system.img镜像挂载到sys
    Industio_触觉智能 2025-01-03 11:39 112浏览
  • 影像质量应用于多个不同领域,无论是在娱乐、医疗或工业应用中,高质量的影像都是决策的关键基础。清晰的影像不仅能提升观看体验,还能保证关键细节的准确传达,例如:在医学影像中,它对诊断结果有着直接的影响!不仅如此,影像质量还影响了:▶ 压缩技术▶ 存储需求▶ 传输效率随着技术进步,影像质量的标准不断提高,对于研究与开发领域,理解并提升影像质量已成为不可忽视的重要课题。在图像处理的过程中,硬件与软件除了各自扮演着不可或缺的基础角色,有效地协作能够确保图像处理过程既高效又具有优异的质量。软硬件各扮演了什么
    百佳泰测试实验室 2025-01-03 10:39 132浏览
  • 自动化已成为现代制造业的基石,而驱动隔离器作为关键组件,在提升效率、精度和可靠性方面起到了不可或缺的作用。随着工业技术不断革新,驱动隔离器正助力自动化生产设备适应新兴趋势,并推动行业未来的发展。本文将探讨自动化的核心趋势及驱动隔离器在其中的重要角色。自动化领域的新兴趋势智能工厂的崛起智能工厂已成为自动化生产的新标杆。通过结合物联网(IoT)、人工智能(AI)和机器学习(ML),智能工厂实现了实时监控和动态决策。驱动隔离器在其中至关重要,它确保了传感器、执行器和控制单元之间的信号完整性,同时提供高
    腾恩科技-彭工 2025-01-03 16:28 159浏览
  • 物联网(IoT)的快速发展彻底改变了从智能家居到工业自动化等各个行业。由于物联网系统需要高效、可靠且紧凑的组件来处理众多传感器、执行器和通信设备,国产固态继电器(SSR)已成为满足中国这些需求的关键解决方案。本文探讨了国产SSR如何满足物联网应用的需求,重点介绍了它们的优势、技术能力以及在现实场景中的应用。了解物联网中的固态继电器固态继电器是一种电子开关设备,它使用半导体而不是机械触点来控制负载。与传统的机械继电器不同,固态继电器具有以下优势:快速切换:确保精确快速的响应,这对于实时物联网系统至
    克里雅半导体科技 2025-01-03 16:11 160浏览
  • Matter加持:新世代串流装置如何改变智能家居体验?随着现在智能家庭快速成长,串流装置(Streaming Device,以下简称Streaming Device)除了提供更卓越的影音体验,越来越多厂商开始推出支持Matter标准的串流产品,使其能作为智能家庭中枢,连结多种智能家电。消费者可以透过Matter的功能执行多样化功能,例如:开关灯、控制窗帘、对讲机开门,以及操作所有支持Matter的智能家电。此外,再搭配语音遥控器与语音助理,打造出一个更加智能、便捷的居家生活。支持Matter协议
    百佳泰测试实验室 2025-01-03 10:29 136浏览
  • 车身域是指负责管理和控制汽车车身相关功能的一个功能域,在汽车域控系统中起着至关重要的作用。它涵盖了车门、车窗、车灯、雨刮器等各种与车身相关的功能模块。与汽车电子电气架构升级相一致,车身域发展亦可以划分为三个阶段,功能集成愈加丰富:第一阶段为分布式架构:对应BCM车身控制模块,包含灯光、雨刮、门窗等传统车身控制功能。第二阶段为域集中架构:对应BDC/CEM域控制器,在BCM基础上集成网关、PEPS等。第三阶段为SOA理念下的中央集中架构:VIU/ZCU区域控制器,在BDC/CEM基础上集成VCU、
    北汇信息 2025-01-03 16:01 170浏览
  • 【工程师故事】+半年的经历依然忧伤,带着焦虑和绝望  对于一个企业来说,赚钱才是第一位的,对于一个人来说,赚钱也是第一位的。因为企业要活下去,因为个人也要活下去。企业打不了倒闭。个人还是要吃饭的。企业倒闭了,打不了从头再来。个人失业了,面对的不仅是房贷车贷和教育,还有找工作的焦虑。企业说,一个公司倒闭了,说明不了什么,这是正常的一个现象。个人说,一个中年男人失业了,面对的压力太大了,焦虑会摧毁你的一切。企业说,是个公司倒闭了,也不是什么大的问题,只不过是这些公司经营有问题吧。
    curton 2025-01-02 23:08 289浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦