首页 > 其他分享 >容器化最佳实践

容器化最佳实践

时间:2024-04-22 12:11:07浏览次数:12  
标签:容器 Kubernetes 映像 实践 最佳 构建 应用 Docker

容器构建最佳实践

1. 每个容器打包一个应用

重要性:高

  • 由于容器与其托管的应用具有相同的生命周期,因此每个容器应仅包含一个应用。当容器启动时,应用也应该启动,当应用停止时,容器也应该停止。
  • 如果一个容器中具有多个应用,则这些应用可能具有不同的生命周期或处于不同状态。例如,到最后可能出现容器在运行但其某个核心组件崩溃或无响应的情况。如果不进行额外的健康检查,则整个容器管理系统(Docker 或 Kubernetes)将无法判断该容器是否运行正常。对于 Kubernetes,这意味着,如果核心组件无响应,Kubernetes 不会自动重启容器。
    您可能会在公开映像中看到以下操作,但不要按照它们的示例进行操作:
  • 使用 Supervisor 等进程管理系统来管理容器中的一个或多个应用。
  • 使用 bash 脚本作为容器中的入口点,并使其生成多个应用作为后台作业。如需了解如何在容器中正确使用 bash 脚本,请参阅正确处理 PID 1、信号处理和僵尸进程。
    注意:您可能会看到有些知名供应商的官方映像并未实施这种最佳实践。供应商这样做的原因是他们需要多个组件正常工作,并且他们希望用户能够通过单个 docker run 命令来运行他们的软件。虽然此方法可用于测试和实验,但我们不建议在生产环境中运行这些映像。

2. 优化 Docker 构建缓存

重要性:高

Docker 构建缓存可以大幅度加速容器映像的构建。映像是逐层构建的,在 Dockerfile 中,每条指令都会在生成的映像中创建一层。在构建期间,如果可能,Docker 会重复使用先前构建中的层并跳过可能很昂贵的步骤。仅当所有先前的构建步骤都使用 Docker 的构建缓存时,Docker 才能使用该缓存。虽然此行为通常有助于加速构建,但您需要考虑一些情况。
例如,要充分利用 Docker 构建缓存,必须将经常更改的构建步骤置于 Dockerfile 底部。如果将它们放在顶部,则 Docker 无法将其构建缓存用于其他不经常更改的构建步骤。由于通常会为每个新版本的源代码构建一个新 Docker 映像,因此,请尽可能晚地向 Dockerfile 中的映像添加源代码。在下图中,您可以看到,如果更改 STEP 1,则 Docker 只能重复使用 FROM debian:11 步骤中的层。但是,如果更改 STEP 3,则 Docker 可以重复使用 STEP 1 和 STEP 2 的层。
image

图 . 如何使用 Docker 构建缓存的示例。 绿色表示可以重复使用的层。红色表示必须重新创建的层。
重复使用层还有另外一种结果:如果构建步骤依赖于存储在本地文件系统上的任何类型的缓存,则必须在同一构建步骤中生成此缓存。如果不生成此缓存,则构建步骤可能会通过来自先前构建的过期缓存执行。软件包管理器(如 apt 或 yum)中最常出现此行为:您必须在安装软件包的同一个 RUN 命令中更新代码库。
如果您在下面的 Dockerfile 中更改了第二个 RUN 步骤,则系统不会重新运行 apt-get update 命令,而是使用已过期的 apt 缓存。

FROM debian:11

RUN apt-get update
RUN apt-get install -y nginx
改为在单个 RUN 步骤中合并这两个命令:
FROM debian:11
RUN apt-get update &&  apt-get install -y nginx

3. 构建尽可能小的映像

构建较小的映像可以带来上传和下载速度更快等优点,这对于 Kubernetes 中 pod 的冷启动时间来说尤为重要:映像越小,节点下载映像的速度越快。但是,构建小映像可能很困难,因为您可能会在最终映像中无意间添加构建依赖项或未优化的层。
注意:如需了解特定于语言的示例,请参阅博文 为何及如何构建小型容器映像。
基础映像是 Dockerfile 的 FROM 指令中引用的映像。Dockerfile 中的每个其他指令都在此映像基础上构建。基础映像越小,生成的映像越小,下载速度也就越快。例如,alpine:3.17 映像比 ubuntu:22.04 映像小 23 MB。
您甚至可以使用scratch基础映像,它是一个空映像,您可以在该映像上构建自己的运行时环境。如果您的应用是静态链接的二进制文件,您可以使用 scratch 基础映像,如下所示:

FROM scratch
COPY mybinary /mybinary
CMD [ "/mybinary" ]

4. 尝试创建具有通用层的映像

如果必须下载 Docker 映像,Docker 首先会检查您是否已具有映像中的某些层。如果您具有这些层,则不会下载它们。如果您之前下载的另一映像与您当前正在下载的映像具有相同的基础,则可能会出现此情况。 结果是第二个映像的已下载数据量要少得多。
在组织级别,您可以为开发者提供一组通用的标准基础映像,从而利用这一规律减少下载量。您的系统下载各基础映像的次数必须仅为一次。初始下载后,仅需要使每个映像具有唯一性的层。实际上,映像的共同点越多,下载速度就越快。
image

5. 使用语义版本控制进行标记

发布软件的常用方法是使用版本号“标记”(如 git tag 命令中所示)特定版本的源代码。语义版本控制规范提供了一种用于处理版本号的简便方法。在此系统中,您的软件版本号由三部分组成:X.Y.Z,其中:

  • X 是主要版本号,仅在发布不兼容的 API 更改时递增。
  • Y 是次要版本号,在发布新功能时递增。
  • Z 是补丁程序版本,在发布 bug 修复时递增。
    次要版本号或补丁程序版本号的每次递增都必须针对向后兼容的更改。
    如果您使用此系统或类似系统,请根据以下政策标记您的映像:
  • latest 标记始终表示最新(可能处于稳定状态)的映像。创建新映像后,此标记会立即移动。
  • X.Y.Z 标记表示软件的某个特定版本。请勿将其移动至其他映像。
  • X.Y 标记表示软件的 X.Y 次要分支的最新补丁程序版本。在有新的补丁程序版本发布后,此标记会移动。
  • X 标记表示 X 主要分支的最新次要版本的最新补丁程序版本。在有新的补丁程序版本或新的次要版本发布时,系统会移动此标记。
    通过使用此政策,用户可以灵活选择要使用的软件版本。他们可以选择特定的 X.Y.Z 版本,并可确保该映像永远不会更改,也可以选择一个不太具体的标记,自动获取更新。

容器运维最佳实践

1. 确保容器无状态且不可变

重要性:高

如果您第一次尝试使用容器,请不要将其视为传统服务器。例如,不要正在运行的容器内更新应用,或者在出现漏洞时修补正在运行的容器。从根本上说,容器不是以这种方式运行的,容器被设计为无状态且不可变。
无状态
无状态意味着任何状态(任何类型的持久性数据)均存储在容器之外。这种外部存储可以采取多种形式,具体取决于您的需求:

  • 如需存储文件,建议使用远程存储。
  • 如需存储用户会话等信息,建议使用外部低延时键值存储,例如 Redis 或 Memcached。
  • 如果需要块级存储(例如对于数据库),则可以使用挂接到容器的外部磁盘。
    通过使用这些选项,您可以从容器本身移除数据,这意味着可以随时彻底关闭和销毁容器,而不必担心数据丢失。如果创建了一个新容器来替换旧容器,只需将新容器连接到同一数据存储区或绑定到同一磁盘即可。
    不变性
    不可变意味着容器在其生命周期内不会被修改,即没有更新、没有补丁程序,也没有配置更改。如果必须更新应用代码或应用补丁程序,则需要构建新映像并重新部署。 不变性使部署更安全、更可重复。
    如果需要回滚,只需重新部署旧映像即可。此方法允许您在每个环境中部署同一容器映像,使它们尽可能相同。
    如需在不同环境中使用同一容器映像,我们建议您外部化容器配置(侦听端口、运行时选项等)。
    容器通常配置有装载在特定路径上的环境变量或配置文件。在 Kubernetes 中,您可以使用 Secrets 和 ConfigMaps 将容器中的配置作为环境变量或文件注入。
    如果需要更新配置,请使用更新后的配置部署一个新容器(基于同一映像)。
    image

无状态和不变性的组合是基于容器的基础架构的卖点之一。这种组合允许您自动化部署并提高其频率和可靠性。

2. 避免使用特权容器

虚拟机或裸机服务器中,您避免以 root 用户身份运行应用。原因很简单,如果应用遭到破解,攻击者就可以拥有对服务器的完整访问权限。出于同样的原因,请避免使用特权容器。特权容器是一种可以访问主机的所有设备的容器,它几乎可以绕过容器的所有安全功能。
如果您认为需要使用特权容器,请考虑以下备选方案:

  • 通过 Kubernetes 的 securityContext 选项或 Docker 的 --cap-add 标志为容器提供特定功能。Docker 文档列出了默认启用的功能和必须明确启用的功能。
  • 如果您的应用必须修改主机设置才能运行,请在辅助信息文件容器或 init 容器中修改这些设置。 与您的应用不同,这些容器不需要向内部或外部流量公开,因此隔离性更高。
  • 如果需要在 Kubernetes 中修改 sysctl,请使用专用注释。

使应用易于监控
重要性:高
与日志记录一样,监控是应用管理不可或缺的一部分。在许多方面,监控容器化应用与监控非容器化应用遵循相同的原则。但是,由于容器化基础架构往往具有高度动态性,其所含的容器会频繁创建或删除,您无法在每次发生这种情况时都重新配置监控系统。
指标 HTTP 端点
指标 HTTP 端点的运作方式与后文公开应用的运行状况中提到的端点类似。它通常在 /metrics URI 上公开应用的内部指标。 响应如下:
http_requests_total{method="post",code="200"} 1027
http_requests_total{method="post",code="400"} 3
http_requests_total{method="get",code="200"} 10892
http_requests_total{method="get",code="400"} 97
在此示例中,http_requests_total 是指标,method 和 code 是标签,最右侧的数字是这些标签的指标值。在本例中,自启动以来,应用对 HTTP GET 请求已返回 400 错误代码 97 次。
通过 Prometheus 客户端库(提供多种语言)可以轻松生成此 HTTP 端点。 OpenCensus 还可以使用此格式(以及许多其他功能)导出指标。但请注意,切勿将此端点公开给公共互联网。
Prometheus 官方文档详细介绍了该主题。如需详细了解白盒(和黑盒)监控,请阅读《站点可靠性工程》的第 6 章。

3. 公开应用的运行状况

重要性:高
为了便于在生产环境中进行管理,应用必须将其状态传达给整个系统,包括应用是否正在运行?运行状况是否良好?是否已准备好接收流量?应用表现如何?
Kubernetes 有两种类型的健康检查,包括活动性探测和就绪性探测。 每种类型都有特定用途,本部分会详细介绍。您可以通过多种方式(包括在容器内运行命令或检查 TCP 端口)实现这两种类型的探测,但首选方法是使用此最佳实践中介绍的 HTTP 端点。如需详细了解此主题,请参阅 Kubernetes 文档。
活跃性探测
健康检查的关键探针
实现活动性探测的推荐方法是让应用公开 /healthz HTTP 端点。在此端点上收到请求后,如果认为运行状况良好,应用应发送“200 OK”响应。在 Kubernetes 中,运行状况良好意味着容器不需要终止或重启。运行状况良好的条件因应用而异,但通常意味着以下情况:

  • 该应用正在运行。
  • 其主要依赖性得到满足(例如,它可以访问其数据库)。
    就绪性探测
    滚动更新的关键探针,
    实现就绪性探测的推荐方法是让应用公开 /ready HTTP 端点。当应用在此端点上收到请求时,如果其已准备好接收流量,则应发送“200 OK”响应。准备好接收流量意味着以下情况:
  • 该应用运行状况良好。
  • 任何潜在的初始化步骤均已完成。
  • 发送到应用的任何有效请求都不会导致错误。
    Kubernetes 使用就绪性探测来编排应用的部署。如果更新部署,Kubernetes 将对属于该部署的 pod 进行滚动更新。 默认更新政策是一次更新一个 pod,即 Kubernetes 会在更新下一个 pod 之前等待新 pod 准备就绪(由就绪性探测指明)。

标签:容器,Kubernetes,映像,实践,最佳,构建,应用,Docker
From: https://www.cnblogs.com/canghai-xudong/p/18150386

相关文章

  • springboot 嵌入式的web容器的的选择
    springboot默认内置tomcat可以替换undertow、jetty、nettytomcattomcat默认200最大线程完整实现了JEE容器和serlet规范tomcat6以后支持Jdk1.4的NIO用于完整支持了javaee因此比较笨重和重量级很多高并发会替换成undertowundertow这个是红帽2012开源出来的一个......
  • 实践展示openEuler部署Kubernetes 1.29.4版本集群
    本文分享自华为云社区《openEuler部署Kubernetes1.29.4版本集群》,作者:江晚正愁余。一、Kubernetes集群节点准备1.1主机操作系统说明序号操作系统及版本备注1CentOS7u9或OpenEuler22031.2主机硬件配置说明需求CPU内存硬盘角色主机名值8C8G1024GBmasterk8s-ma......
  • 【用户案例】数字化转型中的新质生产力:东风日产的RPA实践与启示
    在数字化时代的浪潮中,企业数字化转型已成为不可逆转的趋势。面对工效联动和数字化转型的双重挑战,传统汽车行业急需寻找新的突破点。东风日产,作为一家拥有 1.9万名员工的汽车企业,为我们展示了如何成功实现内部转型东风日产是东风汽车有限公司旗下的重要乘用车板块,致力于以先进......
  • list容器
    list是一种双向链表。list的设计更加复杂一点,好处是每次插入或删除一个元素,就配置或释放一个元素,list对于空间的运用有绝对的精准,一点也不浪费。而且对于任何位置的元素插入或删除,list永远是常数空间。list源码分成了两个部分,一个部分是list结构,另一部分是list节点的结......
  • vcetor容器
    1.基本数据结构template<classT,classAlloc=alloc>classvector{public:typedefTvalue_type;typedefvalue_type*pointer;typedefconstvalue_type*const_pointer; //定义迭代器,这里就只是一个普通的指针typedefvalue_type*iter......
  • 第6章 工程实践——真实场景大不同
    第6章工程实践——真实场景大不同  通过前面章节的学习,相信读者应该已经具备了一定NLP算法应用开发能力,虽然需要借助大语言模型,但这也是一种能力,毕竟用户并不关心产品后面用了什么技术。一款产品或应用开发完成后,接下来就是要面向市场和客户了,这中间有非常多的工作要做,即便我......
  • 快速理解Laravel容器(IOC、DI、Provider、Contract)
    源码理解思维的提升分享一些个人见解。Laravel里面的某些概念,就像魔术一样,看起来很厉害,当知道魔术怎么变的,就会认为也不过如此。所以不必感觉Laravel里有些概念难以理解。应当抛除被框架约束思维的枷锁,用PHP设计的角度去思考,关注大概,而不是在在框架层面逐行磨叽。毕竟源码那么......
  • 32天【代码随想录算法训练营34期】第八章 贪心算法 part02 (● 122.买卖股票的最佳时
    122.买卖股票的最佳时机IIclassSolution:defmaxProfit(self,prices:List[int])->int:result=0foriinrange(len(prices)-1):ifprices[i+1]-prices[i]>0:result+=prices[i+1]-prices[i]return......
  • RocketMQ实践
    RocketMQ的安装下载安装ApacheRocketMQ​这里以在Linux环境为例,介绍RocketMQ安装过程。解压下载的源码包并编译构建二进制可执行文件$mvn-Prelease-all-DskipTests-Dspotbugs.skip=truecleaninstall-U$cddistribution/target/rocketmq-4.9.4/rocketmq-4.9.4启动N......
  • 在Linux中,如何实现虚拟机和容器之间的互操作性?
    在Linux中,实现虚拟机和容器之间的互操作性是一个涉及多个步骤的过程。以下是一些关键的步骤和考虑因素:选择适合的虚拟化技术和容器技术:虚拟化技术:常见的虚拟化技术有VMware、VirtualBox等。它们允许你在一个物理机上创建和运行多个虚拟机,每个虚拟机都有自己的操作系统和应用程......