用 shell 做一个调谐循环
目标
用Shell脚本直接实现读取CR的明细,调整下游资源,将结果写回status的调整循环,并用对象版本证明第二次运行什么都没有改变。
为什么重要
在这个练习中制作的不是控制器二进制文件,而是 重新初始化函数的本质。 在实际的控制器中,重新初始化传递给的不是对象,而是键,也不会告知发生了什么变化。 因此,重新初始化总是从“现在想要的状态是什么,实际是什么”中重新开始。 这个设计所强制的就是 等效性。 在已经正确的情况下重新编写时,会产生新的 watch 事件,该事件会再次调用重新初始化,无限次触发自己。 因此,等效性的真正判断标准不是“没有发生错误”,而是 “子对象的 resourceVersion 保持不变”。 另一个重要的区分是错误和重启。 依赖对象尚未准备就绪的情况不是失败,因此不能返回错误。 错误会累积指数重置并污染日志,使该对象的重试间隔变长,真正出现问题时响应会变慢。 最后,最终化器是打破“删除 = 即刻消失”直觉的装置。 删除请求只是记录删除时间,而重新初始化调用的那一刻是清理外部资源的最后机会。
阶段
开始前准备:练习板每次练习都会重新生成,所以前一次练习的群集状态不会保留。kubectl get crd webservices.apps.labhub.io如果空着的话,请重新填写CRD后再应用。kubectl create ns crd-lab也做吧。在这个实习中subresources.status哇properties.status下面replicas·observedGeneration·conditions必须要有正义,spec里面有image(required),replicas(default 1),tier需要(default dev)。
- 首先
crd-lab在WebServicecheckout请制作spec.image: nginx:1.27,spec.replicas: 3,spec.tier: dev). 然后/root/op/reconcile/reconcile.sh制作并chmod +x请做。这个脚本是kubectl getCR的spec(desired)和子ConfigMapcheckout-desired读(actual)/root/op/reconcile/out/observe.json在{"desired": {...}, "actual": {...}}必须以形状保存,desired.image是CR的spec.image和必须完全相同。 - 第一次执行的判断
/root/op/reconcile/out/decision-1.json请保存到。action银create,reason写下为什么做出那样判断的字符串,target是关于什么的判断(例如:configmap/checkout-desired)包含。 - 请让脚本按照判断执行。
crd-labConfigMapcheckout-desired制作data.image是CR的spec.image应该有价值,metadata.ownerReferences[0].uid是checkout的实际uid,metadata.labels在app.kubernetes.io/managed-by: webservice-controller必须去。 kubectl get cm checkout-desired -n crd-lab -o jsonpath='{.metadata.resourceVersion}'价格/root/op/reconcile/out/rv-before.txt保存到,再执行一次脚本后,将相同的值/root/op/reconcile/out/rv-after.txt请保存到。两个值必须相同,第二个判断是/root/op/reconcile/out/decision-2.json在action这个noop必须进入。- 请让脚本重写status。
checkout的status.conditions在type: Ready,status: "True"输入条件,status.observedGeneration乙metadata.generation和一样,status.replicas的spec.replicas请制作成像这样。脚本中包含--subresource=status字符串必须实际包含。 /root/op/reconcile/out/requeue.json请制作。action银requeue,after_seconds是大于0的整数,is_error是false是。还有/root/op/reconcile/out/backoff-note.txt请分别用一个句子以上写出两点——为什么需要指数级地增加重试间隔的backoff,以及如果全部将“还没有准备好”处理为错误的话,错误日志会暴走,导致一个对象被排队饿死的问题。crd-lab在WebServiceephemeral制作并metadata.finalizers在webservice.labhub.io/cleanup请放入。以3号相同的方式子ConfigMapephemeral-desired也制作。然后kubectl delete webservice ephemeral -n crd-lab --wait=false请求删除,紧接着的整个对象/root/op/reconcile/out/terminating.json请保存到(此文件中包含metadata.deletionTimestamp哇metadata.finalizers都必须显示出来)。然后子ConfigMapephemeral-desired删除了什么,整理了什么/root/op/reconcile/out/cleanup.txt写在后面的话,请移除最终处理器。ephemeral请让它实际消失。crd-lab在WebServicebilling科search另外创建(分别拥有image和replicas),作为reconcilercheckout·billing·search三个都绕了一圈后/root/op/reconcile/out/reconcile-report.json请制作。items是各元素name科action(create/update/noop/requeue拥有其中一个)的数组,summary.noop没有做任何事情的次数,converged在true包含。三个CR都status.observedGeneration这个metadata.generation应该和一样。
参考
- 练习板每次练习都会重新生成,所以前一个练习的聚类状态不会保留下来。但如果把声明留作文件,无论在哪个练习板上,都可以重新建立相同的状态——这就是声明型的实际优势。
- 删除最终化器:
kubectl patch webservice ephemeral -n crd-lab --type=merge -p '{"metadata":{"finalizers":null}}' - 价格相同的内容
kubectl apply这样做的话,服务器会处理为没有变更。resourceVersion不会上升。但是,只要把每次不同的值(时间戳等)放在annotation里,就会破坏其性质。 - status 用patch写:
kubectl patch webservice checkout -n crd-lab --subresource=status --type=merge -p '{"status":{...}}' - 常见的错误1:第4次脚本每次都
kubectl replace我kubectl create --dry-run后强制应用。即使内容相同,版本升级后也会失败在等级判断上。 - 常见的错误2:在6次中
is_error的true写为。还没有依赖对象不是错误,而是等待状态。 - 常见错误3:在7号中等待删除命令结束。如果附带终结器,命令将无法返回,因此必须使用不等待的选项才能观察删除中状态。
读取想要的状态和实际状态
首先crd-lab在WebServicecheckout请制作spec.image: nginx:1.27,spec.replicas: 3,spec.tier: dev). 然后/root/op/reconcile/reconcile.sh制作并chmod +x请做。这个脚本是kubectl getCR的spec(desired)和子ConfigMapcheckout-desired读(actual)/root/op/reconcile/out/observe.json在{"desired": {...}, "actual": {...}}必须以形状保存,desired.image是CR的spec.image和必须完全相同。
Recon Sale的第一步不是判断,而是阅读。CR的spec是desired,子对象是actual。如果没有子对象,actual是空的也是正常的,脚本需要执行权限。
通过比较做出调整判断
第一次执行的判断/root/op/reconcile/out/decision-1.json请保存到。action银create,reason写下为什么做出那样判断的字符串,target是关于什么的判断(例如:configmap/checkout-desired)包含。
判断不能只以action结束。要留下为什么做出这样的判断以及是对什么做出判断,这样以后才能只看日志进行追踪。
根据判断制作子资源
请让脚本按照判断执行。crd-labConfigMapcheckout-desired制作data.image是CR的spec.image应该有价值,metadata.ownerReferences[0].uid是checkout的实际uid,metadata.labels在app.kubernetes.io/managed-by: webservice-controller必须去。
不要用手抄写价格,请在CR中输入。需要与父母的联系和表示是我制作的标记标签。
防止第二次运行不改变任何东西
kubectl get cm checkout-desired -n crd-lab -o jsonpath='{.metadata.resourceVersion}'价格/root/op/reconcile/out/rv-before.txt保存到,再执行一次脚本后,将相同的值/root/op/reconcile/out/rv-after.txt请保存到。两个值必须相同,第二个判断是/root/op/reconcile/out/decision-2.json在action这个noop必须进入。
差异性的证据不是日志,而是对象的版本。在第二次运行前后分别记录下子对象的resourceVersion,然后比较一下。内容相同的话,服务器不会重新写入。
将调整结果重新写入status
请让脚本重写status。checkout的status.conditions在type: Ready,status: "True"输入条件,status.observedGeneration乙metadata.generation和一样,status.replicas的spec.replicas请制作成像这样。脚本中包含--subresource=status字符串必须实际包含。
status以与spec不同的路径写入。指定该路径的字符串必须实际存在于脚本中。请同时匹配处理的世代编号和观测的副本。
整理杰奎的判断和白开水
/root/op/reconcile/out/requeue.json请制作。action银requeue,after_seconds是大于0的整数,is_error是false是。还有/root/op/reconcile/out/backoff-note.txt请分别用一个句子以上写出两点——为什么需要指数级地增加重试间隔的backoff,以及如果全部将“还没有准备好”处理为错误的话,错误日志会暴走,导致一个对象被排队饿死的问题。
还没有依赖对象并不意味着失败。请按秒记录下何时再次查看,并明确说明这不是错误。备忘录中必须分别写下重新尝试间隔增加的原因和全部被处理为错误时出现的问题。
用最终整理器整理后删除
crd-lab在WebServiceephemeral制作并metadata.finalizers在webservice.labhub.io/cleanup请放入。以3号相同的方式子ConfigMapephemeral-desired也制作。然后kubectl delete webservice ephemeral -n crd-lab --wait=false请求删除,紧接着的整个对象/root/op/reconcile/out/terminating.json请保存到(此文件中包含metadata.deletionTimestamp哇metadata.finalizers都必须显示出来)。然后子ConfigMapephemeral-desired删除了什么,整理了什么/root/op/reconcile/out/cleanup.txt写在后面的话,请移除最终处理器。ephemeral请让它实际消失。
删除请求不是立即删除。首先保存拍下删除时间点的瞬间,整理完毕后才能移除最终化程序,对象才会消失。有不等待的删除选项。
做了一圈多个CR,然后制作报告
crd-lab在WebServicebilling科search另外创建(分别拥有image和replicas),作为reconcilercheckout·billing·search三个都绕了一圈后/root/op/reconcile/out/reconcile-report.json请制作。items是各元素name科action(create/update/noop/requeue拥有其中一个)的数组,summary.noop没有做任何事情的次数,converged在true包含。三个CR都status.observedGeneration这个metadata.generation应该和一样。
Recon Slayer不是特定CR专用的。一边照顾多个对象一边收集各自的判断,用一行总结是否都达到了想要的状态。所有对象的世代编号必须正确才能收敛。