尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Podman `--no-healthcheck` 选项完全指南:在 create / run / update 中禁用容器健康检查

Podman `--no-healthcheck` 选项完全指南:在 create / run / update 中禁用容器健康检查 Podman--no-healthcheck选项完全指南在 create / run / update 中禁用容器健康检查【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址: https://gitcode.com/gh_mirrors/po/podman导读--no-healthcheck是 Podman 提供给podman create、podman run、podman update三个命令的通用布尔选项用于完全禁用容器定义的健康检查Healthcheck。本文将以 options/no-healthcheck.md 为骨架结合 Podman 源码命令行参数解析、specgen 生成、libpod 运行时健康检查逻辑与端到端测试用例讲透该选项的语义、用法、底层实现机制Test: [NONE]哨兵值、与其他健康检查选项的互斥关系以及禁用后的可观察行为。选项语义一行文档背后的完整含义原文档 no-healthcheck.md 对--no-healthcheck的定义只有一句话Disable any defined healthchecks for container.禁用容器上任何已定义的健康检查。但这句话实际包含两层含义需要结合源码理解覆盖镜像自带健康检查很多基础镜像例如 nginx、postgres 等在其HEALTHCHECK指令中定义了默认健康检查。使用--no-healthcheck创建容器后镜像中的健康检查会被彻底屏蔽容器不会再周期性地执行任何检查命令。覆盖显式指定的健康检查如果在命令行同时传入了--health-cmd等选项--no-healthcheck与它们是互斥的详见下文“互斥关系”一节Podman 会直接报错拒绝执行。该选项是一个布尔开关默认false且该选项文件被三个命令共用——文件头部的注释明确标注了这一点#### This option file is used in: #### podman create, run, update因此本选项在podman create、podman run、podman update三个命令中拥有完全一致的语义。在 create / run 时禁用健康检查命令行用法创建容器时禁用健康检查的最简单方式# 基于自带 HEALTHCHECK 的镜像创建容器但完全禁用其健康检查 podman create --no-healthcheck --name myweb nginx:latest # 或者直接运行 podman run -d --no-healthcheck --name myweb -p 8080:80 nginx:latest在命令行参数层面该选项在 cmd/podman/common/create.go 中被注册且仅在CreateModecreate和UpdateModeupdate两种模式下生效if mode entities.CreateMode || mode entities.UpdateMode { createFlags.BoolVar( cf.NoHealthCheck, no-healthcheck, false, Disable healthchecks on container, ) }注意该选项没有短选项不像-e之于--env只能以--no-healthcheck全称形式书写。与 --health-cmd 的互斥校验当用户在同一个命令行中既指定--no-healthcheck又指定--health-cmd时Podman 会拒绝执行。该校验位于 specgen 生成阶段见 pkg/specgenutil/specgen.goif len(c.HealthCmd) 0 { if c.NoHealthCheck { return errors.New(cannot specify both --no-healthcheck and --health-cmd) } s.HealthConfig, err MakeHealthCheckFromCli(...) ... }同理--no-healthcheck与启动期健康检查命令--health-startup-cmd也是互斥的见 pkg/specgenutil/specgen.goif c.StartupHCCmd ! { if c.NoHealthCheck { return errors.New(cannot specify both --no-healthcheck and --health-startup-cmd) } ... }这两处互斥校验在源码注释与错误信息中表达得非常直白用户在拼写命令时应避免同时传入。用 podman update 动态禁用健康检查--no-healthcheck的另一个重要使用场景是对运行中的容器动态禁用健康检查无需重建容器# 先创建一个带健康检查的容器 podman run -d --name app \ --health-cmd curl -f http://localhost/ || exit 1 \ --health-interval 10s \ --health-retries 3 \ myapp:latest # 事后禁用该容器的健康检查 podman update app --no-healthcheckpodman update在 cmd/podman/containers/update.go 中通过cmd.Flags().Changed(no-healthcheck)感知用户是否显式指定了该选项并将其写入updateHealthCheckConfig.NoHealthCheckif cmd.Flags().Changed(no-healthcheck) { updateHealthCheckConfig.NoHealthCheck vals.NoHealthCheck }随后libpod 层在 libpod/healthcheck_config.go 中处理该配置noHealthCheck : false if updateHealthCheckConfig.NoHealthCheck ! nil { noHealthCheck *updateHealthCheckConfig.NoHealthCheck } changed : originalHealthCheckConfig.SetNewHealthCheckOptions(updateHealthCheckConfig, healthCheckOptions) if noHealthCheck changed { return nil, false, errors.New(cannot specify both --no-healthcheck and other HealthCheck flags) } if noHealthCheck { if originalHealthCheckConfig.IsStartup() { return StartupHealthCheckConfig{StartupHealthCheck: nil}, true, nil } return HealthCheckConfig{Schema2HealthConfig: manifest.Schema2HealthConfig{Test: []string{NONE}}}, true, nil }这里有两点值得注意动态更新时的互斥如果podman update同时传入了其他健康检查相关 flag如--health-interval、--health-retries等会触发cannot specify both --no-healthcheck and other HealthCheck flags错误。启动期健康检查一并清除如果容器原本配置了启动期健康检查startup healthcheck--no-healthcheck会将其一并置空。Podman 系统级测试 test/system/280-update.bats 完整覆盖了这一场景——先创建带健康检查的容器执行podman update $ctrname --no-healthcheck再用podman inspect断言Config.Healthcheck.Test等于[NONE]test podman update - --no-healthcheck { local msghealthmsg-$(random_string) local ctrnamec-h-$(safename) run_podman run -d --name $ctrname \ --health-cmd echo $msg \ --health-startup-cmd echo startup$msg \ $IMAGE /home/podman/pause cid$output run_podman update $ctrname --no-healthcheck run_podman inspect $ctrname --format {{.Config.Healthcheck.Test}} assert $output [NONE] HealthCheck command is disabled }底层实现Test: [NONE]哨兵机制--no-healthcheck在容器配置中的落点是 OCI 镜像规范manifest.Schema2HealthConfig的Test字段。当--no-healthcheck生效时Podman 并不删除健康检查配置对象而是把Test字段设置为特殊的哨兵值[NONE]注意是包含单个字符串NONE的切片见 pkg/specgenutil/specgen.go} else if c.NoHealthCheck { s.HealthConfig manifest.Schema2HealthConfig{ Test: []string{NONE}, } }设置成NONE而非直接置空是为了显式覆盖镜像自带的 HEALTHCHECK——镜像的默认健康检查在生成容器配置时会被这里的Test: [NONE]整体替换掉保证“禁用”是确定性的、可被 inspect 观察到的。在 libpod 运行层libpod/container.go 的HasHealthCheck()方法对[NONE]哨兵做了专门判定——只要Test为空切片或等于NONE就认为容器“没有定义健康检查”// HasHealthCheck returns bool as to whether there is a health check // defined for the container func (c *Container) HasHealthCheck() bool { // Consider a healthcheck present only when a HealthCheckConfig exists // and the Test field contains a meaningful command. Treat an empty // Test slice or the special [NONE] sentinel as no healthcheck. if c.config.HealthCheckConfig nil { return false } test : c.config.HealthCheckConfig.Test if len(test) 0 { return false } if len(test) 1 strings.ToUpper(test[0]) define.HealthConfigTestNone { return false } return true }因此从容器健康状态机libpod/healthcheck.go的角度看一个被--no-healthcheck禁用的容器其Runtime.HealthCheck()会走到if !container.HasHealthCheck() { return define.HealthCheckNotDefined, fmt.Errorf(container %s has no defined healthcheck, container.ID()) }也就是说健康检查 timer 根本不会被创建也不会有任何周期性检查动作发生。禁用后的可观察行为podman healthcheck run 直接报错端到端测试 test/e2e/healthcheck_run_test.go 验证了这一点——用--no-healthcheck创建容器后手动执行健康检查会以错误退出It(podman disable healthcheck with --no-healthcheck on valid container, func() { SkipIfNotAMD64() // https://github.com/containers/podman/issues/28269 session : podmanTest.Podman([]string{run, -dt, --no-healthcheck, --name, hc, HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) hc : podmanTest.Podman([]string{healthcheck, run, hc}) hc.WaitWithDefaultTimeout() Expect(hc).Should(ExitWithError(125, has no defined healthcheck)) })对应到podman healthcheck run命令的输出大概是Error: container hc has no defined healthcheck容器状态中不再出现健康信息同一测试文件 test/e2e/healthcheck_run_test.go 还验证了禁用健康检查后podman container inspect --format {{.State.Health}}的输出不会包含健康状态不会出现starting/healthy/unhealthy等阶段因为健康检查状态机从未启动。通过 inspect 确认配置已禁用这是最直接的验证方式podman inspect myweb --format {{.Config.Healthcheck.Test}} # 输出: [NONE]另一种“禁用”思路--health-intervaldisable除--no-healthcheck外Podman 还允许通过--health-intervaldisable在不改动检查命令的前提下暂停周期性执行相关行为在 test/e2e/healthcheck_run_test.go 中有测试覆盖。两者适用场景不同--no-healthcheck彻底清除健康检查语义podman healthcheck run会报“未定义”State.Health无内容--health-intervaldisable保留健康检查配置与日志但不再按周期调度执行适合临时暂停、日后恢复的场景。相关命令与更多资料由于该选项文件被三处 man page 引用读者可以在仓库文档中继续深挖上下文podman-create.1.md.in创建容器的完整选项表--no-healthcheck与--health-cmd、--health-interval、--health-retries、--health-timeout、--health-start-period、--health-startup-cmd等选项共同构成健康检查配置族podman-run.1.md.in运行容器的完整选项表podman-update.1.md.in动态更新容器配置支持在容器运行期追加禁用健康检查podman-healthcheck.1.md手动触发健康检查的命令podman healthcheck run与本文的禁用行为直接相关。小结--no-healthcheck虽在文档中只有一句话其背后却是一套完整的实现链路命令行参数解析cmd/podman/common/create.go→ 互斥校验与 specgen 生成pkg/specgenutil/specgen.go→ libpod 动态更新libpod/healthcheck_config.go→ 运行时的[NONE]哨兵判定libpod/container.go。无论你是在创建容器时屏蔽镜像自带的健康检查、用podman update对运行中的容器动态停用健康检查还是排查“为什么我的容器没有健康状态”理解--no-healthcheck的语义与实现都能帮助你更精准地掌控 Podman 容器的健康检查行为。【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址: https://gitcode.com/gh_mirrors/po/podman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表