Skip to content

Commit

Permalink
add proposal about resize asts pvc
Browse files Browse the repository at this point in the history
Signed-off-by: Abner-1 <yuanyuxing.yyx@alibaba-inc.com>
  • Loading branch information
ABNER-1 committed Jul 16, 2024
1 parent 8ae13b1 commit f02893f
Show file tree
Hide file tree
Showing 3 changed files with 477 additions and 0 deletions.
Binary file added docs/img/asts-resize-pvc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
236 changes: 236 additions & 0 deletions docs/proposals/20240626-asts-volume-resize-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
---
title: AdvancedStatefulSetVolumeResize
authors:
- "@Abner-1"
reviewers:
- "@furykerry"
- "@zmberg"
creation-date: 2024-06-26
last-updated: 2024-06-26
status:
---


# Advanced StatefulSet 支持卷变配

## 目录
* [Advanced StatefulSet 支持卷变配](#advanced-statefulset-支持卷变配)
* [目录](#目录)
* [Motivation](#motivation)
* [用户场景](#用户场景)
* [用户失败恢复场景](#用户失败恢复场景)
* [本质问题](#本质问题)
* [目标](#目标)
* [非目标](#非目标)
* [Proposal](#proposal)
* [API Definition](#api-definition)
* [增加 webhook 校验](#增加-webhook-校验)
* [PVC 调谐过程修改](#pvc-调谐过程修改)
* [原地变配 pvc 更新失败后怎么办?](#原地变配-pvc-更新失败后怎么办)
* [为什么选择延续 KEP-661 的不追踪 vct 的历史版本](#为什么选择延续-kep-661-的不追踪-vct-的历史版本)
* [Implementation](#implementation)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
➜ kruise git:(add-proposal-resize-asts-pvc) ✗ gh-md-toc docs/proposals/20240626-asts-volume-resize-zh.md

Table of Contents
=================

* [Advanced StatefulSet 支持卷变配](#advanced-statefulset-支持卷变配)
* [目录](#目录)
* [Motivation](#motivation)
* [用户场景](#用户场景)
* [用户失败恢复场景](#用户失败恢复场景)
* [本质问题](#本质问题)
* [目标](#目标)
* [非目标](#非目标)
* [Proposal](#proposal)
* [API Definition](#api-definition)
* [增加 webhook 校验](#增加-webhook-校验)
* [PVC 调谐过程修改](#pvc-调谐过程修改)
* [原地变配 pvc 更新失败后怎么办?](#原地变配-pvc-更新失败后怎么办)
* [Implementation](#implementation)
* [为什么选择延续 KEP-661 的不追踪 vct 的历史版本?](#为什么选择延续-kep-661-的不追踪-vct-的历史版本)
* [为什么需要增加 KEP-4650 提议的两个字段,而不是完全参照 KEP-661?](#为什么需要增加-kep-4650-提议的两个字段而不是完全参照-kep-661)

## Motivation
目前已经支持了 CloneSet Volume Claim Templates 变动时触发 pod 重建,使 pvc 重新 reconcile 达成变配。
但是对于有状态应用这样的策略过于激进,需要完善 advanced Stateful Set 对于 Volume Claim Templates 变动的更新策略。
asts 现状是对 Volume Claim Templates 变动时完全不关注,只对新的 pod 进行 reconcile,

### 用户场景

1. **[H]** 对可支持变配的 StorageClass 的场景, 可以直接 edit pvc storage 字段增加规格大小(不支持减少)
2. 对不支持变配的 StorageClass 的场景,需要确保已有 pvc 内容不再需要后可(手动/自动)删除 pvc 和 pod,新 reconcile 出来的 pvc 和 pod 就可以使用最新的配置 (完善用户场景, 该场景理论上是需要)
a. 部分消费类场景,使用一段时间后磁盘会有一部分碎片,有时候会在消费完成后 recreate 以提高性能 (sts删除后重建是不是也可以)
3. 对需要更改 StorageClass 的场景,操作和场景 2 类似
a. 更改 ssd -> essd / 迁移上云等

### 用户失败恢复场景

在场景 1 的操作过程中可能遇到一些意外情况,如修改 Volume Claim Templates 因为各种情况在某个 pod 操作失败了。此时用户会有这几种恢复期望:
1. 完全回滚到配置修改之前,如同时修改镜像和卷规格,但新镜像有问题,想完全回滚(KEP-661不解决)
2. **[H]** 部分回滚到配置修改之前,如同时修改镜像和卷规格,但新镜像有问题,想回滚到旧镜像,但使用新的卷规格 (KEP-661解决)
3. 不回滚配置,解决异常 pod 的失败问题
a. 如变配符合预期但在某个节点存储 quota 不足,与管理员沟通后增加 quota
b. 如变配符合预期但在某个节点底层资源存储不足,希望漂移到资源充足的节点上
4. 重新修改配置,如修改卷规格10G -> 100G,因为存储 quota 不足,希望改成 10G -> 20G: (假设10个更新到第5个实例失败)前4个 pod 需要 100G -> 20G, 后6个需要10G -> 20G (KEP-1790)

### 本质问题

1. 如何识别不能原地变配的场景 (KEP661)

2. 有没有可能设计一种机制来识别pvc已无数据安全问题,从而让删除 pvc 的过程自动化,进而将自动化 pvc 重建的过程(KEP 4650 定义的机制更侧重将错误处理交由上层用户/平台)

1. 如果有这样一种机制,和 delete pvc 的区别在哪?
- delete pvc 是一个和 api 做交互的接口,有权限要求;这种机制可以是某个组件识别到 pvc 状态/pod 内存储状态后打标,是一个实况上报的功能,权限要求较低
- sts 控制器可以结合并发度和调谐进度来做 delete pvc 的实际决策

3. 用户想要的迁移 PVC 的机制究竟是什么样的?一个灵活的机制(KEP4650)还是受限但通用的解决方案?

### 目标
1. 希望在 sc 支持容量扩展的前提下扩展 Volume Claim Templates 规格可以自动化操作
2. 【Nice to have】在 sc 不支持容量扩展的前提下,由用户已自行确保原有云盘内数据不需要保存后调整 Volume Claim Templates 配置 + 显式指定 pvc 更新方式,可自动删除重建
- 如何区分是因为更新导致的重建,而不是异常场景驱逐后的重建 -- 参考 clone set 在delete pod 里处理
- 既然用户知道,理论上可以等待手动删除后重建(OnDelete)
3. 确保用户可以知道 pvc 的变配是否完成或发生错误
4. 不阻碍用户尝试从异常情况下进行恢复
5. 在打开 RecoverVolumeExpansionFailure feature gate 的集群中,允许用户达成恢复期望4

### 非目标

1. 不实现 kep 1790
2. 不实现 volume claim 的版本管理和跟踪,详细影响[为什么选择延续 KEP-661 的不追踪 vct 的历史版本](#为什么选择延续-kep-661-的不追踪-vct-的历史版本)
3. 不实现和标识pvc可删除联动的调谐机制


## Proposal

### API Definition
增加字段

1. 在StatefulSet spec中引入一个新字段:`volumeClaimUpdateStrategy`
来指定如何协调PVC和Pod的更新。可能的值有:
- `OnDelete`:默认值,仅在旧PVC被删除时更新PVC。
- `InPlace`:就地更新PVC。失败后退化到 OnDelete。
- `ReCreate` (可整合目前 cloneset 的 pvc 行为,sts 暂不支持,看社区场景)
- 和 pod OnDelete 的结合可能有点问题:无法区分是在滚动更新场景中更新pvc和pod还是日常想保留pvc但重建异常 pod。
- 可以禁止这种结合,已经用 OnDelete 方式来决定更新 pod了,让上层自行决定是否 delete pvc 也合理。

2.`StatefulSet spec.updateStrategy.rollingUpdate`中引入一个新字段:`volumeClaimSyncStrategy`
来指定如何更新PVC和Pod。可能的值有:
- Async:默认值,保持当前行为,只有 volumeClaimUpdateStrategy OnDelete 时可以设置
- LockStep:首先更新PVC,然后更新Pod。详见下文。

> 为什么我们需要增加这两个字段? link todo
A:asts 对 vct 的修改一直是放过的,如果完全参照 661 来做,其实会降低 api 的灵活性,导致现在用户的一些场景不可用。为了实现向前兼容的方式有两种:“增加这两个字段增加 vct 调谐的灵活性” 和“使用 feature gate 全局管理 webhook拦截和调谐步骤 ”
两种方式的论证可以见附件,暂定为“增加这两个字段增加 vct 调谐的灵活性”

3. **Introduction of `volumeClaimTemplates` in StatefulSet `status`**:
- **`status.volumeClaimTemplates[x].templateName`**: 显示追踪的 `spec.volumeClaimTemplates` 的 pvc (template)name,这个在 vcts 一定唯一,方便用户排查问题
- **Note**: indexId 不是很直观且 vcts 允许删减,不是很好追踪。
- **`status.volumeClaimTemplates[x].compatibleReplicas`**: 是当前 vct 已兼容/已更新的副本数
- **`status.volumeClaimTemplates[x].compatibleReadyReplicas`**: 是当前 vct 已兼容/已成功更新的副本数
- **`status.volumeClaimTemplates[x].finishedReconciliationGeneration`**: 显示 pvc 已经完成调谐的 generation,如上述两个 vct,
- 第一个因为所有副本还没有全部ready,所以还是2;
- 第二个所有副本已经ready,已经追踪上了 sts 现有 generation



```yaml
spec:
volumeClaimUpdateStrategy: OnDelete
# OnDelete:Default value. PVCs are updated only when the old PVC is deleted.
# InPlace:Updates the PVC in place. Also includes the behavior of OnDelete.
# ReCreate (May integrate the current behavior of PVCs in CloneSet)

updateStrategy:
rollingUpdate:
volumeClaimSyncStrategy: Async
# Async:Default value. Maintains current behavior. Only configurable when volumeClaimUpdateStrategy is set to OnDelete.
# LockStep:PVCs are updated first, followed by Pods. More details provided below.

status:
availableReplicas: 3
collisionCount: 0
currentReplicas: 3
currentRevision: ex1-54c5bd476c
observedGeneration: 3
readyReplicas: 3
replicas: 3
updateRevision: ex1-54c5bd476c
updatedReplicas: 3
volumeClaimTemplates: # new field
- finishedReconciliationGeneration: 2
updatedReadyReplics: 1 # resize 状态成功的副本数
updatedReplicas: 2 # 下发 resize 的副本数
templateName: vol1
# 当 updatedReadyReplics == spec.replicas时,
# 调整 finishedReconciliationGeneration 为 sts 的 generation
- finishedReconciliationGeneration: 3
updatedReadyReplics: 3
updatedReplicas: 3
templateName: vol2
```
### 增加 webhook 校验
可以通过 storageclass 中 `allowVolumeExpansion` 字段进行判断是否支持扩展 pvc,但这个字段并不一定和 CSI 实际的能力匹配。

1. Update Strategy为 inplace 时, 如果对应 sc 支持扩展,且 vct 不变或只是大小扩展,则通过。否则拒绝。
- Q:如果先改成 OnDelete 的同时改 vct,后面再改成 inplace?
- A:会在滚动更新过程中卡住,走异常更新流程即可

2. Update Strategy为 OnDelete 时,直接放过


### PVC 调谐过程修改

1. 监听 pvc 的变动: 但不根据 owner reference(已经被用来实现 pvc 自动删除),而是在 annotation 上记录 sts 对象
2. update status 中增加对 pvc 的检验/版本管理
3. rolling update 里面在更新 pod 之前更新 pvc
1. expand 的时候更新 pvc
2. 识别 expand 回滚的情况
- 1790 不开的时候不卡
- 1790 开启的时候下发 resize



### 原地变配 pvc 更新失败后怎么办?

理论上 inplace + lock step 失败后需要用户进行介入,此时一般是必须要重建 pvc (同时也意味着 pod 一定要重建)
理想预期中会降级到 ondelete + lock step 链路,即:
以三副本场景举例,在原地变配 pvc2 失败,
1. 删除 pod2, 同时给 pvc2 打上标签
2. 识别到 pvc2 上的标签时不会进行新 pod2 的创建
3. 等待 pvc2 兼容 且标签消除(可在识别到 pvc 兼容后自动去除)
1. 此时用户介入预期会有几种情况
- pvc2 数据不需要,delete pvc2
- 下发一个新 job 挂载 pvc2,进行备份/快照,成功后 delete pvc2
4. (3.5)此时如果删除 pod0,会触发 pod0的重建,不会因为 pvc0 不兼容而卡住
5. 兼容后再次创建 pod2,等待 pod2 ready 后更新下一个序号



### Implementation
主体修改位于 `rollingUpdateStatefulsetPods` 函数
![asts-resize-pvc](../img/asts-resize-pvc.png)


### 为什么选择延续 KEP-661 的不追踪 vct 的历史版本?
现在 asts/cloneset 不在 controller revision 追踪 volumeClaimTemplates 的历史信息,只关注当前值,延续当前行为的主要原因:
1. 将 vct 的信息加入 controller revision,意味着**如果只存在 vct 的改动也会触发 asts 的版本变动**
1. 目前没有收集到相关的需求
2. 对现有控制器流程影响比较大,涉及改动多,风险比较大

2. 直接回滚的操作可以通过上层重新下发配置解决,预想中的大部分场景是可以不回滚pvc配置(或不紧急)
- 相较 expand pvc 的需求优先级较低,如有必要,可以后续演进

3. 加入历史版本跟踪,可以在尚未更新到某 pvc 时,即使 pvc 被删除也会被拉起到历史版本, 而非最新版本
- pvc 数据还是没法恢复的,此时用户 delete 某个 pvc 的目的是为了拉起旧版本的 pvc 配置吗? 貌似没啥区别。

现在没有具体需求场景的情况下,没想明白可持久化存储在数据丢失的情况下,回到历史版本的pvc配置相较最新版本的pvc配置的核心优势是什么?

### 为什么需要增加 KEP-4650 提议的两个字段,而不是完全参照 KEP-661?
1. sts 之前不允许修改 vct 任何字段,661 实现的是功能增强
2. asts 之前允许修改 vct 任何字段,可用来实现类似 OnDelete + async 的方式,实现 661 如果在webhook 中检验只允许修改 size,无法保证以前的用户场景兼容
Loading

0 comments on commit f02893f

Please sign in to comment.