✨ feat(epic): 新增抢占式实例注解支持史诗文档
- 创建史诗文档 `epic-001-spot-strategy-annotation.md`,用于规划抢占式实例注解功能 - 详细描述问题陈述、业务价值、需求分解、用户故事和技术实现要点 - 提供使用示例,展示如何通过 Pod 注解控制是否启用抢占式实例 - 定义功能需求与非功能需求,确保功能灵活性与向后兼容性
This commit is contained in:
@@ -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 详细文档并进入开发。_
|
||||
Reference in New Issue
Block a user