feat(spot-strategy): 新增抢占式实例注解支持

- 添加故事 1.1 的实现工件文档,定义抢占式实例开关注解功能
- 更新 sprint 状态文件,将故事标记为 ready-for-dev 并开始 epic-1 的开发
This commit is contained in:
D8D Developer
2026-01-01 09:18:25 +00:00
parent c964594cf9
commit 0cb22c1f7c
2 changed files with 166 additions and 9 deletions

View File

@@ -0,0 +1,162 @@
# Story 1.1: 抢占式实例开关注解支持
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## 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](../../eci.go#L212) 被硬编码启用,所有 Pod 都会使用抢占式实例。这导致核心服务可能被抢占中断,影响服务稳定性。
### 修改位置
**主要文件**: [eci.go](../../eci.go) 第 211-213 行
**当前代码**:
```go
// 添加抢占式实例策略配置
request.SpotStrategy = "SpotAsPriceGo" // 设置抢占式实例策略为按价格竞价
//request.SpotDuration = 0 // 设置抢占式实例持续时间为0非定时抢占
```
### 实现方案
#### 1. 定义注解常量
在 eci.go 顶部的常量定义区域(约第 32-36 行附近)添加:
```go
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 行的硬编码逻辑替换为:
```go
// 抢占式实例配置 - 支持通过注解控制是否启用
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):
```go
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):
```go
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
- [Epic 001: 抢占式实例注解支持](../planning-artifacts/epics/epic-001-spot-strategy-annotation.md)
- [eci.go:212 - 当前硬编码位置](../../eci.go#L212)
- [eci.go:190-209 - 现有注解处理模式](../../eci.go#L190-L209)
- [ECI 抢占式实例文档](../../docs/eci.md)
- [项目概览](../../docs/project-overview.md)
## Dev Agent Record
### Agent Model Used
BMad Scrum Master (sm) - YOLO Mode
### Debug Log References
### Completion Notes List
### File List

View File

@@ -5,15 +5,10 @@ generated: "2025-11-26"
project: "vk-eci"
sprint: "Sprint-1"
stories:
- id: "STORY-001"
title: "实现 ECI 抢占式实例 SpotToBeReleased 事件处理"
file: "docs/stories/spot-instance-event-handling.md"
status: "TODO"
priority: "高"
effort: "中等"
assignee: ""
created: "2025-11-26"
# BMAD 故事状态跟踪
development_status:
"1-1-spot-strategy-annotation": "ready-for-dev"
"epic-1": "in-progress"
# 故事状态定义
# TODO - 待开始