update set能回滚吗_k8s pvc在挂载状态下被删除,状态变为Terminating并无法回滚的问题排查和总结...

k8s在1.14版本开始,GA支持本地存储[1],这对于我们来说,是个非常好的消息,因为我们现在的虚机环境,就是采用的本地存储,如果k8s能够较好的支持本地存储的分配策略,对我们的迁移工作,将是非常大的一个帮助,这里要感谢k8s,GA的真是时候。

但是在使用本地存储的时候,还是发现了一个问题,我个人认为在设计上有待考量,即如标题所说,k8s的pvc(PersistentVolumeClaim)在被Pod挂载的状态下,如果对其执行删除动作,将会变为Terminating状态,且这是一个几乎不可逆的过程,完全无法回滚(后面我会细讲为什么),只能够等待Pod被删除的时候,这个pvc会跟着一起删除。大家理解我的意思吧,也就是一旦pvc被执行了删除动作,那么它的死期就已经被定了下来,那就是挂载它的那个Pod被删除的时候,这个设计逻辑,不是很有意思吗?一个Persistent Volume Claim,永远无法再Persistent了,只能等着跟Pod一起被干掉,实在是让人有点无法理解,但是经过本文记录的一系列查证之后发现,原来k8s就是这么设计的(详见issue评论[2]liggitt应该是k8s pv相关设计的leader吧,直接就把这位仁兄提的issue给close了),顿时无语,只能上知乎吐槽一下了。

宣泄完情绪,回归主题,先把问题复现一下:

//首先创建了本地存储的pv和使用本地存储pv的statefulset,如下:【这块创建工作略过,本文的问题与pv是何种类型无关】
# kubectl get pods
NAME                                              READY   STATUS    RESTARTS   AGE
web-0                                             1/1     Running   0          4d14h
web-1                                             1/1     Running   0          10d
web-2                                             1/1     Running   0          10d
# kubectl get pvc
NAME                                               STATUS        VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0                                          Terminating   local-pv-40faed3c   5584Gi     RWO            local-disks    4d14h
www-web-1                                          Bound         local-pv-310d5bcb   5584Gi     RWO            local-disks    10d
www-web-2                                          Bound         local-pv-a23634e8   4467Gi     RWO            local-disks    10d
//对于www-web-0,在之前执行了kubectl delete pvc www-web-0的操作,所以状态从Bound变成了Terminating。然后这个状态就再不能通过任何方式回滚了,
//只有等web-0被删除以后,www-web-0与其一同被删除。
//【而且删除web-0之后,web-0的重建会失败,报错www-web-0 not found,只有再次删除web-0,新的pvc才会被创建出来,
//详见https://github.com/kubernetes/kubernetes/issues/74374,主要是因为删除pod和删除pvc是两个go程在做的,存在一个先后冲突问题。这个不是本文重点,就不多说了。

因为试图回滚,也看了一下pvc在正常Bound状态下和Terminating状态下的区别:

分别kubectl get pvc [pvc] -o yaml了一下,发现唯一的区别就是Terminating状态下pvc的metadata多了如下内容:
  deletionGracePeriodSeconds: 0
  deletionTimestamp: "2019-06-06T10:44:44Z"

看来这就是Terminating的原因,第一反应就是是否可以修改或者删除deletionTimestamp这个值呢?试了一下用kubectl patch修改成“”或者很久以后的某个时间,发现不能,没反应。

# kubectl patch pvc www-web-0 -p '{"metadata":{"deletionTimestamp":""}}'
Error from server: parsing time "" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "2006"
# kubectl patch pvc www-web-0 -p '{"metadata":{"deletionTimestamp":"2019-07-06T10:44:44Z"}}'
persistentvolumeclaim/www-web-0 patched (no change)
时间还是原来的,没改变

然后想看看是否可以直接删掉,同样。

# kubectl patch pvc www-web-0 --type=json -p='[{"op": "remove", "path": "/metadata/deletionTimestamp"}]'
persistentvolumeclaim/www-web-0 patched (no change)
依旧没有反映。

这就奇怪了,其他的内容,都可以通过patch修改和删除,只有deletionTimestamp和deletionGracePeriodSeconds不能,我在想,难道是代码层做了限制?话说,中途,我还想通过etcd直接修改value值,但是因为etcd里存的value是protobuf协议编码[3],还得转换写入,实在麻烦,但这个方式最后看来,是唯一可以回滚的途径了=_=!!。

接下来,看代码,从patch的api开始跟,发现这么一段【代码是v1.14.2版本】:

efe8018b6a0f69b56f77c5a3547e26e9.png
D:rrxgosrck8s.iokubernetesvendork8s.ioapiserverpkgregistryrestupdate.go

这回清楚了,为什么怎么改都改不了?因为代码写死了,不让改。好吧,那为什么不让改呢?看看blame吧,发现这次提交就是Jordan Liggitt提交的。

9a6e4144971a7d9c8864f823ac13b480.png

找到对应的Merge PR。

8830bbc9b2b75c4b7ca29c824df2d02d.png

看PR[4]里面全部commit的内容,应该只是把原来的限制,挪了一下位置,从很早之前就一直有。

5bb0ba21c37366ac6edcf0d622770cce.png

好吧,代码还是不继续跟了,看看issue,搜一下"deletionTimestamp pvc undo"试试,果然搜到一个关键issue,所以英文好还是很重要啊,之前搜没加"undo"这个词,就没搜出什么正相关的issue。

6359d07f19fd2b44fdc1d1d094dc51ea.png

这个也就是文章最开始提到的那个issue[2]

1a8491ea9ba35d75a9f86c14ffea7eed.png

得出结论了,看回复原文吧,人家就是不想让你undo回滚,连workaround的机会都不给你。好吧,这回死心了。

结论:

1、原生k8s不允许执行删除后的回滚动作。——所以删除任何东西前,要想好,k8s的最终一致性可是原则,虽然我认为这个原则不应该在这个管理层面上强制执行的。

2、如果真的删除了,想挽留,在不改k8s原生代码的前提下,只能有以下两种方式挽回:

1)将pvc的persistentVolumeReclaimPolicy从Delete改为Retain,这样起码删除pod之后,pvc即使被删除,底层数据也不会被删。

2)通过修改etcd里面的value值,删除deletionTimestamp和deletionGracePeriodSeconds两个key。(需要有protobuf协议到yaml的相互转换,还没试过)

3、还有一个比较简单的方式,就是修改k8s的代码,将上面截图的那部分限制代码删掉,允许kubectl patch删除deletionTimestamp和deletionGracePeriodSeconds这两个key,个人感觉,这个可以有。

附注参考:

https://stackoverflow.com/questions/tagged/kubernetes【有些求助类问题,比搜github issue靠谱,类似本文的问题,搜pvc terminating,就查到一个相关的提问Cancel or undo deletion of Persistent Volumes in kubernetes cluster】

https://stackoverflow.com/questions/45744534/etcd-v3-cant-read-encoded-values

kubectl patcth用法:

https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md

参考

  1. ^本地存储provider https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner
  2. ^abUndelete/lazy delete resources https://github.com/kubernetes/kubernetes/issues/69980#issuecomment-431035255
  3. ^etcdctl v3: k8s changes its internal format to proto, and the etcdctl result is unreadable. #44670 https://github.com/kubernetes/kubernetes/issues/44670
  4. ^Deprecate repair-malformed-updates flag, move object meta mutation into BeforeCreate #61455 https://github.com/kubernetes/kubernetes/pull/61455
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值