- 云原生
- 后端
- 前端
- 运维
- 可观测性
- 开发工具
【免费下载链接】octant
Highly extensible platform for developers to better understand the complexity of Kubernetes clusters.
Octant 是一个面向开发者的 Kubernetes 集群可视化与操作平台。本文以 changelogs/CHANGELOG-0.24.md 为主线,结合当前仓库源码,系统解读 v0.24.0(2021-08-09 发布)的两大核心亮点——为 Pod 新增容器镜像 Manifest 查看能力、为 Go 插件引入自动重载机制,以及三项 Bug 修复与五项常规改进。读完本文,你将掌握这些新特性的使用方式、底层实现原理与对应的源码验证路径,可用于排查 Octant 插件运行问题或二次开发。
版本概览:v0.24.0 发布时间与交付内容
| 项目 | 内容 |
|---|---|
| 版本号 | v0.24.0 |
| 发布日期 | 2021-08-09 |
| 核心亮点 | Pod 容器镜像 Manifest(#156);Go 插件自动重载(#178) |
| 缺陷修复 | 3 项(#1688 / #2143 / #2809) |
| 常规改进 | 5 项(#1422 / #2774 / #2775 / #2776 / #2795) |
v0.24.0 的安装包通过官方发布渠道提供。该版本同时服务于 Go 插件与 JavaScript 插件两条扩展生态:前者由 pkg/plugin/manager.go 中的插件管理器负责进程级生命周期管理,后者由 pkg/plugin/javascript.go 基于 goja 事件循环在 Octant 进程内运行(通过path.Ext(pluginName) == ".js"判定是否为 JS 插件,见 pkg/plugin/javascript.go)。
亮点一:为 Pod 增加容器镜像 Manifest 查看能力
功能入口与动作路由
v0.24.0 起,开发者可以直接在 Octant 中查看 Pod 所使用容器镜像的 manifest 与配置信息。该功能通过 Octant 的前端动作(Action)机制暴露:
- 动作名称常量定义在 internal/octant/actions.go,值为
action.octant.dev/manifest; - 动作分发器实现在 internal/octant/manifest.go,
Manifest结构体实现了action.Dispatcher接口,ActionName()返回ActionGetManifest; - 动作处理器从
payload中读取两个关键参数:image(镜像名)与host(目标操作系统),随后调用manifest.ManifestManager.GetImageManifest(ctx, hostOS, image)完成拉取。
因此,前端发起请求时只需要提供镜像名与宿主 OS 两个字段,例如:
{ "image": "docker://nginx:1.16.1", "host": "linux" }底层实现:基于 containers/image 的 Manifest 拉取
核心逻辑位于 internal/manifest/manifest.go,这里可以拆解为四个关键设计:
1. 镜像名归一化(parseName):如果镜像名不含://协议前缀,默认按 Docker Hub 镜像处理,自动补充docker://前缀(见 internal/manifest/manifest.go)。也就是说nginx:1.16.1与docker://nginx:1.16.1等价。
2. 多平台选择(OSChoice):通过&types.SystemContext{OSChoice: hostOS}指定目标操作系统,再调用srcRef.NewImageSource(ctx, systemCtx)拉取对应平台的 manifest。对于多架构镜像列表(manifest list),这一步会依据 hostOS 挑选合适的镜像实例。
3. 双输出结构(ImageManifest):GetImageManifest返回两个字符串——Manifest(原始 manifest JSON)与Configuration(镜像 OCI 配置 blob,经json.MarshalIndent美化缩进),数据结构定义见 internal/manifest/manifest.go。
4. 进程内缓存(imageCache + 互斥锁):ManifestConfiguration以map[ImageEntry]ImageManifest缓存已拉取结果,ImageEntry由镜像名与 hostOS 构成;命中缓存直接返回,未命中时先加锁再拉取,避免并发重复请求(见 internal/manifest/manifest.go 与GetImageManifest的缓存判断逻辑)。
测试用例与预期行为验证
测试文件 internal/manifest/manifest_test.go 给出了非常清晰的预期行为,可直接作为功能验证依据:
| 用例 | 输入 | hostOS | 预期结果 |
|---|---|---|---|
| alpine | docker://alpine:3.14.0 | linux | 成功,比对 testdata/alpine_manifest.json 与 testdata/alpine_config.json |
| nginx | docker://nginx:1.16.1 | linux | 成功,比对 testdata/nginx_manifest.json 与 testdata/nginx_config.json |
| 无协议前缀 | nginx:1.16.1 | linux | 与显式docker://结果一致(验证 parseName) |
| 平台不匹配 | docker://alpine:3.14.0 | windows | 报错:no image found in manifest list for architecture amd64, variant "", OS windows |
其中 testdata/nginx_manifest.json 展示了典型的 manifest list 结构:包含 amd64、arm/v7、arm64、386、ppc64le、s390x 等平台条目,印证了 hostOS 参数在多架构场景下的实际作用。注意测试在 CI 环境下会被跳过(t.Skip("Skipping test in CI to avoid rate limits")),以避免对镜像仓库的频繁拉取触发限流。
亮点二:Go 插件自动重载
使用方式:改完即生效,无需重启 Octant
v0.24.0 之前,修改 Go 插件代码后必须重启 Octant 才能加载新版本;该版本引入自动重载后,插件目录中的文件一旦发生变化,Octant 会自动卸载并重新注册插件,开发体验与热更新对齐。
插件目录的解析逻辑见 pkg/plugin/loader.go:
- macOS / Linux 默认目录:
~/.config/octant/plugins; - Windows 或设置了
xdg-config-home时:~/octant/plugins; - 可通过
--plugin-path配置项追加额外的插件目录(多个路径用系统路径分隔符拼接)。
底层实现:fsnotify 监听 + 事件去抖
自动重载的核心是Manager.watchPluginFiles(pkg/plugin/manager.go),流程如下:
- 用
fsnotify.NewWatcher()监听所有插件目录; - 忽略纯
Chmod事件,对Remove/Rename事件执行Unload卸载; - 对
Write/Create事件先写入writeEventsmap 暂存; - 每 1 秒(
time.After(1 * time.Second))统一处理一次暂存事件,调用updatePlugin完成重载——该去抖机制避免了编辑器保存时多次 Write 事件导致的重复重载; updatePlugin内部先Unload,再根据 pkg/plugin/javascript.go 的判定分发:JS 插件走registerJSPlugin,Go 插件走m.Load(name)+m.start(ctx, config)。
此外,pkg/plugin/manager.go 中的goPluginPingPong提供了进程级兜底:每 5 秒对已注册的 Go 插件客户端执行一次Ping(),若 Ping 失败(例如插件进程异常退出),会自动重启该插件进程。自动重载 + 心跳重启共同保证了插件生态的健壮性。
缺陷修复:三项体验问题
1. 修复文本与链接组件的状态指示器(#1688)
此前文本(text)与链接(link)组件在特定状态下无法正确显示状态指示器。该修复涉及 Octant 前端组件渲染层,使这两类组件在对象详情页的状态呈现与表格、按钮等组件保持一致。
2. 修复 Windows 下 Go 插件拉起终端的问题(#2143)
Go 插件在 Windows 平台启动子进程时,会因终端窗口闪现等问题影响运行。仓库中通过构建约束区分了平台实现:
- Unix 平台(pkg/plugin/plugincmd_unix.go):直接
exec.Command(cmd); - Windows 平台(pkg/plugin/plugincmd_windows.go):设置
SysProcAttr = &syscall.SysProcAttr{HideWindow: true},隐藏插件进程的控制台窗口。
HideWindow: true正是本次针对 Windows 的修复点:避免 Go 插件进程在桌面环境弹出多余窗口,同时保证终端类功能(如容器 exec 会话)在 Windows 下正常建立。
3. 修复插件提供的活动 Tab 未正确选中(#2809)
Octant 允许插件通过SupportsTab能力声明为特定 GVK 追加详情页 Tab。相关接口定义见 pkg/plugin/client.go(SupportsTab与HasTabSupport),以及 pkg/plugin/dashboard/dashboard.proto 中的PrintTab消息(name+layout)。
此前当插件返回多个 Tab 时,默认选中的活动 Tab 可能与预期不符(例如插件指定的首个 Tab 未被激活)。本次修复确保插件提供的 Tab 在详情页加载后能被正确选中,使PrintTabs(pkg/plugin/dashboard/dashboard.proto)返回的 Tab 集合与前端激活状态保持一致。
常规改进:五项增强
1. 支持自定义 SVG 图标(#1422)
导航条目现在可以使用自定义 SVG 图标。实现层面:
- pkg/navigation/navigation.go 的
SetNavigationIcon会将图标名以internal:前缀注入导航条目(IconName: fmt.Sprintf("internal:%s", name)); - gRPC 协议层面,pkg/plugin/dashboard/dashboard.proto 的
Navigation消息包含icon_name、icon_source、custom_svg三个字段,插件可携带自定义 SVG 内容; - 内置导航图标名称集中在 pkg/icon/icon.go,均为 Clarity 图标体系的命名(如
application、network-globe、storage等)。
这意味着插件开发者既可以复用 Clarity 内置图标,也可以直接注入自定义 SVG,让插件模块在导航栏拥有专属视觉标识。
2. 移除对pb.Timestamp的废弃用法(#2774)
该改动清理了 gRPC 定义中对pb.Timestamp的已废弃引用,将协议定义(pkg/plugin/dashboard/dashboard.proto)与生成的dashboard.pb.go、dashboard_grpc.pb.go统一到新的 protobuf 用法,减少因依赖升级带来的编译告警与兼容性隐患。
3. 启用 Go 插件应用 YAML 的能力(#2775)
Go 插件现在可以通过动作action.octant.dev/apply(常量定义见 pkg/action/actions.go)向集群应用 YAML 资源。实现位于 internal/octant/apply_yaml.go:
- 请求结构
applyYamlRequest包含namespace与update两个必填字段(internal/octant/apply_yaml.go),Validate()会拒绝空值; Handle调用objectStore.CreateOrUpdateFromYAML将 YAML 应用到集群,并根据结果数量发送不同类型的提醒(pkg/action/manager.go 定义了ERROR/WARNING/INFO/SUCCESS四种AlertType,默认提醒过期时间为 10 秒,见 pkg/action/manager.go):- 1 个资源:发送 INFO 消息;
- 多个资源:发送
Applied N resources汇总消息; - 失败:发送 ERROR 消息,同时仍返回部分结果给客户端。
配套测试 internal/octant/apply_yaml_test.go 验证了命名空间级 ConfigMap 的创建流程(资源不存在时先Get命中 NotFound,再调用Create)。
4. 为 JS 插件监听器提供更清晰的错误信息(#2776)
JS 插件(.js文件)同样纳入自动重载体系(pkg/plugin/manager.go)。本次改进聚焦于 JS 插件 watcher 的错误处理:当监听目录不可用、文件解析失败或重载注册出错时,日志会以更明确的方式输出失败原因(例如reloading: JavaScript plugin: %w携带具体错误),便于开发者快速定位是脚本语法错误、插件元数据缺失还是动作注册冲突。
5. 插件日志更细粒度化(#2795)
插件管理器的日志从笼统的输出改为带上下文的细粒度记录。以 pkg/plugin/manager.go 为例:
pluginLogger := log.From(ctx).With("plugin-name", pluginPath) pluginLogger.With("cmd", pluginPath, "metadata", metadata). Infof("registered plugin %q", metadata.Name)每条日志都携带plugin-name标签,并区分注册、动作注册、模块注册、重载、心跳等不同阶段,配合Debugf级别的 payload 输出,能够在排查多插件共存环境时快速定位到具体插件的具体环节。
结语与升级建议
v0.24.0 的两个亮点分别补强了 Octant 的两大方向:面向普通用户的集群可观测性(Pod 镜像 Manifest 一目了然)与面向插件开发者的开发体验(Go 插件热重载 + 更友好的错误与日志)。若你正在维护 Go 插件,建议升级后重点验证:
- 修改插件源码保存后,观察日志中是否出现
reloading: Go plugin: <name>,确认自动重载生效; - 在 Windows 上确认插件进程不再闪现控制台窗口(对应 #2143 修复);
- 若插件为对象详情页提供多个 Tab,确认默认激活的 Tab 符合预期(对应 #2809 修复);
- 如插件需要向集群下发资源,可直接复用
action.octant.dev/apply动作(对应 #2775 能力)。
对镜像 Manifest 功能感兴趣的话,可直接阅读 internal/manifest/manifest.go 与 internal/manifest/manifest_test.go 中的测试用例,它们是最权威的功能行为说明。
- 云原生
- 后端
- 前端
- 运维
- 可观测性
- 开发工具
【免费下载链接】octant
Highly extensible platform for developers to better understand the complexity of Kubernetes clusters.
相关推荐
kOps 1.7 版本深度解读:Manifest 重写、Calico Pod CIDR 修复与 CVE-2017-14491 安全更新
kOps 1.7 版本深度解读:Manifest 重写、Calico Pod CIDR 修复与 CVE 2017 14491 安全更新 导读 本文基于仓库中的
云原生集群管理运维IaC3分钟搞定Windows和Office永久激活:KMS智能激活脚本终极指南
3分钟搞定Windows和Office永久激活:KMS智能激活脚本终极指南 还在为Windows系统频繁弹出的激活提醒而烦恼吗?Office突然变成只读模式让你
运维buildah manifest inspect 命令详解:查看 OCI 镜像索引与多架构 manifest list 的完整指南
buildah manifest inspect 命令详解:查看 OCI 镜像索引与多架构 manifest list 的完整指南 导读 buildah man
云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考