Files
alibabacloud-eci/_bmad-output/implementation-artifacts/1-1-spot-strategy-annotation.md
D8D Developer b5df40b865 feat(eci): 实现抢占式实例注解支持并更新开发状态
- 在 eci.go 中添加 `AnnotationECISpotInstance` 常量定义
- 实现注解解析逻辑,通过 `k8s.aliyun.com/eci-spot-instance: "true"` 启用抢占式实例
- 添加完整的单元测试覆盖各种注解值场景(true、false、未设置、无效值、大小写变体)
- 修复 eci.go 中预存在的类型转换错误(int → string)
- 更新 docs/eci.md 文档,添加简化注解使用说明
- 将开发状态从 ready-for-dev 更新为 review

🔧 chore(claude): 扩展本地设置允许的命令

- 在 .claude/settings.local.json 中添加 go build、go test 和 make 命令的 Bash 执行权限
2026-01-01 09:27:33 +00:00

6.9 KiB
Raw Blame History

Story 1.1: 抢占式实例开关注解支持

Status: review

Story

作为集群管理员, 我想要通过 Pod 注解控制是否使用抢占式实例, 以便为核心服务使用稳定实例,为批处理任务使用低成本抢占式实例。

Acceptance Criteria

AC-001: 启用抢占式实例

Given Pod 设置了注解 k8s.aliyun.com/eci-spot-instance: "true" When Pod 被调度到 Virtual Kubelet Then ECI 实例使用抢占式实例创建 And SpotStrategy 设置为 SpotAsPriceGo

AC-002: 禁用抢占式实例

Given Pod 设置了注解 k8s.aliyun.com/eci-spot-instance: "false" When Pod 被调度到 Virtual Kubelet Then ECI 实例使用按量实例创建 And 不设置 SpotStrategy 字段

AC-003: 默认行为(未设置注解)

Given Pod 未设置 k8s.aliyun.com/eci-spot-instance 注解 When Pod 被调度到 Virtual Kubelet Then ECI 实例使用按量实例创建(默认行为) And 不设置 SpotStrategy 字段

Tasks / Subtasks

  • T-001: 定义注解名称常量 (AC: 全部)

    • 在 eci.go 顶部添加 AnnotationECISpotInstance 常量
    • 确保与其他注解常量命名风格一致
  • T-002: 实现注解解析逻辑 (AC: 001, 002, 003)

    • 修改 eci.go 第 211-213 行的硬编码逻辑
    • 添加注解检查:pod.Annotations["k8s.aliyun.com/eci-spot-instance"]
    • 实现字符串比较逻辑(不区分大小写)
    • 仅当值为 "true" 时设置 SpotStrategy
  • T-003: 添加单元测试 (AC: 001, 002, 003)

    • 测试注解值为 "true" → 设置 SpotStrategy
    • 测试注解值为 "false" → 不设置 SpotStrategy
    • 测试注解未设置 → 不设置 SpotStrategy
    • 测试注解值为其他值 → 不设置 SpotStrategy
  • T-004: 代码审查与提交 (AC: 全部)

    • 运行 make vet 检查代码质量
    • 运行 make test 验证测试通过
    • 更新相关文档

Dev Notes

问题背景

当前 vk-eci 项目中,抢占式实例策略(SpotStrategy)在 eci.go:212 被硬编码启用,所有 Pod 都会使用抢占式实例。这导致核心服务可能被抢占中断,影响服务稳定性。

修改位置

主要文件: eci.go 第 211-213 行

当前代码:

// 添加抢占式实例策略配置
request.SpotStrategy = "SpotAsPriceGo"  // 设置抢占式实例策略为按价格竞价
//request.SpotDuration = 0                // 设置抢占式实例持续时间为0非定时抢占

实现方案

1. 定义注解常量

在 eci.go 顶部的常量定义区域(约第 32-36 行附近)添加:

const (
    serviceAccountSecretMountPath = "/var/run/secrets/kubernetes.io/serviceaccount"
    podTagTimeFormat              = "2006-01-02T15-04-05Z"
    timeFormat                    = "2006-01-02T15:04:05Z"

    // Pod 注解常量
    AnnotationECISpotInstance  = "k8s.aliyun.com/eci-spot-instance"
    AnnotationECIEipInstanceId  = "k8s.aliyun.com/eci-eip-instanceid"
    AnnotationECIUseSpecs       = "k8s.aliyun.com/eci-use-specs"
    AnnotationECIWithEip        = "k8s.aliyun.com/eci-with-eip"
)

2. 修改 SpotStrategy 设置逻辑

将第 211-213 行的硬编码逻辑替换为:

// 抢占式实例配置 - 支持通过注解控制是否启用
if spotInstance, exists := pod.Annotations["k8s.aliyun.com/eci-spot-instance"]; exists {
    if strings.ToLower(spotInstance) == "true" {
        request.SpotStrategy = "SpotAsPriceGo"  // 启用抢占式实例,使用按价格竞价策略
    }
    // false 时不设置 SpotStrategy使用按量实例
}
// 默认行为:不设置 SpotStrategy使用按量实例

现有注解模式参考

项目已有类似的注解处理模式,请保持一致:

EIP 自动创建注解 (eci.go:195-209):

if withEip, exists := pod.Annotations["k8s.aliyun.com/eci-with-eip"]; exists {
    if withEip == "true" {
        request.AutoCreateEip = requests.Boolean(strconv.FormatBool(true))
    }
}
if eipInstanceId, exists := pod.Annotations["k8s.aliyun.com/eci-eip-instanceid"]; exists {
    request.EipInstanceId = eipInstanceId
}

ECS 规格注解 (eci.go:190-193):

if specs, exists := pod.Annotations["k8s.aliyun.com/eci-use-specs"]; exists {
    request.InstanceType = specs
}

Project Structure Notes

项目路径结构:

/mnt/code/vk-eci/
├── eci.go                          # 主文件 - 需要修改
├── eci/                            # ECI API 客户端包
├── cmd/virtual-kubelet/            # CLI 入口
├── docs/                           # 项目文档
└── _bmad-output/                   # BMAD 工作流输出

代码风格对齐:

  • 遵循 Go 标准命名规范
  • 注解值比较使用 strings.ToLower() 不区分大小写
  • 布尔值字符串比较使用 == "true" 模式(与现有 EIP 注解一致)
  • 保持与其他注解处理相同的代码结构

References

Dev Agent Record

Agent Model Used

BMad Dev Agent (dev) - Story Implementation

Debug Log References

无审查继续状态,全新实现。

Completion Notes List

实现完成日期: 2026-01-01

已实现功能:

  1. T-001: 定义注解常量 AnnotationECISpotInstance (eci.go:40)
  2. T-002: 实现注解解析逻辑,替换硬编码的 SpotStrategy (eci.go:216-223)
    • 支持通过 k8s.aliyun.com/eci-spot-instance: "true" 启用抢占式实例
    • 默认行为(未设置或 false使用按量实例
    • 注解值比较不区分大小写
  3. T-003: 添加单元测试覆盖 (eci_test.go)
    • 测试注解常量定义
    • 测试各种注解值场景 (true, false, 未设置, 无效值, 大小写变体)
  4. T-004: 代码质量检查和文档更新
    • 修复预存在的构建错误 (eci.go:329)
    • 更新 docs/eci.md 添加新注解文档

额外修复:

  • 修复 eci.go:329 预存在的类型转换错误 (int → string)

测试结果:

  • make vet: 通过 ✓
  • make test: 所有测试通过 ✓ (8个测试用例)

File List

新增文件:

  • eci_test.go

修改文件:

  • eci.go (添加注解常量, 实现注解逻辑, 修复构建错误)
  • docs/eci.md (添加 vk-eci 简化注解文档)

Change Log

  • 2026-01-01: Story 1.1 实现完成
    • 添加 k8s.aliyun.com/eci-spot-instance 注解支持
    • 移除硬编码的 SpotStrategy 设置
    • 添加单元测试覆盖
    • 更新文档
    • 修复预存在的构建错误