feat(epic): 新增抢占式实例注解支持史诗文档

- 创建史诗文档 `epic-001-spot-strategy-annotation.md`,用于规划抢占式实例注解功能
- 详细描述问题陈述、业务价值、需求分解、用户故事和技术实现要点
- 提供使用示例,展示如何通过 Pod 注解控制是否启用抢占式实例
- 定义功能需求与非功能需求,确保功能灵活性与向后兼容性
This commit is contained in:
D8D Developer
2026-01-01 09:11:22 +00:00
parent 76e1ccfd5c
commit c964594cf9

View File

@@ -0,0 +1,207 @@
# Epic 001: 抢占式实例注解支持
**状态**: 📋 待规划
**优先级**: P1 - 高优先级
**创建日期**: 2026-01-01
---
## 概述
当前 vk-eci 项目中,抢占式实例策略(`SpotStrategy`)被硬编码启用,所有 Pod 都会使用抢占式实例。本史诗旨在通过 Pod 注解Annotation让用户**自主选择是否启用抢占式实例**,提升灵活性和可用性控制。
---
## 问题陈述
### 当前问题
在 [eci.go:212](../../eci.go#L212) 中:
```go
request.SpotStrategy = "SpotAsPriceGo" // 硬编码启用抢占式实例
```
**影响**
- 所有 Pod 都强制使用抢占式实例
- 抢占式实例可能被回收,导致核心服务中断
- 无法为不同工作负载选择合适的实例类型
- 缺乏对服务稳定性的控制能力
### 用户痛点
| 用户角色 | 痛点描述 |
|---------|---------|
| 集群管理员 | 核心服务(如 API、数据库不应该使用可中断的抢占式实例 |
| DevOps 工程师 | 批处理任务希望用抢占式实例降成本,但在线服务需要稳定实例 |
| 开发团队 | 无法控制自己服务的实例类型,影响服务 SLA |
---
## 业务价值
### 预期收益
- **稳定性提升**:核心服务可使用按量实例,避免被抢占中断
- **成本优化**非关键任务批处理、CI/CD可选用抢占式实例节省成本
- **灵活性**:用户根据业务需求自主选择实例类型
- **向后兼容**:可配置默认行为,保持现有体验
---
## 需求分解
### 功能需求
| ID | 需求描述 |
|----|---------|
| FR-001-1 | 支持通过 Pod 注解 `k8s.aliyun.com/eci-spot-instance` 控制是否启用抢占式实例 |
| FR-001-2 | 注解值为 `"true"` 时启用抢占式实例,使用 `SpotAsPriceGo` 策略 |
| FR-001-3 | 注解值为 `"false"` 或未设置时,不设置 `SpotStrategy`(使用按量实例) |
| FR-001-4 | 支持配置全局默认行为(可选,通过 Provider Config |
### 非功能需求
| ID | 需求描述 |
|----|---------|
| NFR-001-1 | 注解解析不应影响 Pod 创建性能 |
| NFR-001-2 | 保持与现有 EIP 注解、ECS 规格注解的一致性风格 |
---
## 用户故事
### Story 001.1: 抢占式实例开关注解支持
**作为** 集群管理员,
**我想要** 通过 Pod 注解控制是否使用抢占式实例,
**以便** 为核心服务使用稳定实例,为批处理任务使用低成本抢占式实例。
**验收标准**
---
**Given** Pod 设置了注解 `k8s.aliyun.com/eci-spot-instance: "true"`
**When** Pod 被调度到 Virtual Kubelet
**Then** ECI 实例使用抢占式实例创建
**And** `SpotStrategy` 设置为 `SpotAsPriceGo`
---
**Given** Pod 设置了注解 `k8s.aliyun.com/eci-spot-instance: "false"`
**When** Pod 被调度到 Virtual Kubelet
**Then** ECI 实例使用按量实例创建
**And** 不设置 `SpotStrategy` 字段
---
**Given** Pod 未设置 `k8s.aliyun.com/eci-spot-instance` 注解
**When** Pod 被调度到 Virtual Kubelet
**Then** ECI 实例使用按量实例创建(默认行为)
**And** 不设置 `SpotStrategy` 字段
---
## 技术实现要点
### 修改位置
**文件**: [eci.go](../../eci.go) 第 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使用按量实例
```
### 字符串常量定义
建议在 [eci.go](../../eci.go) 顶部定义注解名称常量,保持一致性:
```go
const (
AnnotationECISpotInstance = "k8s.aliyun.com/eci-spot-instance"
AnnotationECIEipInstanceId = "k8s.aliyun.com/eci-eip-instanceid"
// ... 其他注解常量
)
```
### 添加测试
- 单元测试验证注解解析逻辑true/false/未设置/非法值)
- 集成测试:验证 ECI API 调用参数正确传递
---
## 使用示例
### 启用抢占式实例(批处理任务)
```yaml
apiVersion: v1
kind: Pod
metadata:
name: batch-job
annotations:
k8s.aliyun.com/eci-spot-instance: "true"
spec:
containers:
- name: worker
image: nginx
```
### 使用按量实例(核心服务)
```yaml
apiVersion: v1
kind: Pod
metadata:
name: api-server
annotations:
k8s.aliyun.com/eci-spot-instance: "false"
spec:
containers:
- name: api
image: api-server:v1
```
### 默认行为(不设置注解)
```yaml
apiVersion: v1
kind: Pod
metadata:
name: default-pod
spec:
containers:
- name: app
image: nginx
# 不设置注解,使用按量实例
```
---
## 相关文档
- [产品概览](../../docs/product-brief-vk-eci-2025-11-06.md)
- [ECI 抢占式实例文档](../../docs/eci.md)
- [阿里云 ECI Spot 实例文档](https://help.aliyun.com/document_detail/87980.html)
---
## 变更历史
| 日期 | 版本 | 变更内容 | 作者 |
|------|------|---------|------|
| 2026-01-01 | 0.1 | 初始版本(复杂设计) | Amelia |
| 2026-01-01 | 0.2 | 简化为布尔开关设计 | Amelia |
---
_下一步创建 Story 001.1 详细文档并进入开发。_