Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
Kubernetes Operator×î¼Ñʵ¼ù
 
×÷Õߣº whole
  2518  次浏览      31
 2020-7-3
 
±à¼­ÍƼö:
±¾ÎĽéÉÜÁËʵ¼ùÉæ¼°Éè¼ÆKubernetes Operatorʱ×î³£¼ûµÄÎÊÌ⣬ϣÍû¶ÔÄúµÄѧϰÓÐËù°ïÖú¡£
±¾ÎÄÀ´×ÔÓÚKubernetes£¬ÓÉ»ðÁú¹ûÈí¼þAlice±à¼­¡¢ÍƼö¡£

½éÉÜ

Kubernetes OperatorÊÇÁ¬½Óµ½Ö÷API²¢¼àÊÓʼþµÄ½ø³Ì£¬Í¨³£ÊÇ¼à¿ØÓÐÏÞÊýÁ¿µÄ×ÊÔ´ÀàÐÍ¡£

µ±·¢ÉúÏà¹ØÊ¼þʱ£¬Operator»á×ö³ö·´Ó¦²¢Ö´ÐÐÌØ¶¨²Ù×÷¡£Õâ¿ÉÄܽöÏÞÓÚÓëÖ÷API½»»¥£¬µ«Í¨³£Éæ¼°ÔÚijЩÆäËûϵͳÉÏÖ´ÐÐijЩ²Ù×÷£¨¿ÉÄÜÔÚȺ¼¯ÄÚ»òȺ¼¯ÍâµÄ×ÊÔ´ÖУ©¡£

OperatorʵÏÖΪ¿ØÖÆÆ÷µÄ¼¯ºÏ£¬ÆäÖÐÿ¸ö¿ØÖÆÆ÷¼àÊÓÌØ¶¨µÄ×ÊÔ´ÀàÐÍ¡£µ±ÔÚ¹Û²ìµÄ×ÊÔ´ÉÏ·¢ÉúÏà¹ØÊ¼þʱ£¬Æô¶¯Ð­µ÷Ñ­»·¡£

ÔÚЭµ÷ÖÜÆÚÄÚ£¬¿ØÖÆÆ÷ÓÐÔðÈμì²éµ±Ç°×´Ì¬ÊÇ·ñÓë¼àÊÓ×ÊÔ´ÃèÊöµÄÆÚÍû״̬ƥÅä¡£ÓÐȤµÄÊÇÉè¼ÆÉÏ£¬Ê¼þ²»»á´«µÝ¸øÐ­µ÷ÖÜÆÚ£¬Ð­µ÷ÖÜÆÚ±»Ç¿ÖÆÉè¼ÆÎª¹Ø×¢Ê¼þËùÔÚʵÀýµÄÕû¸ö״̬¡£

ÕâÖÖ·½·¨±»³ÆÎª»ùÓڲ㼶µÄÉè¼Æ£¬¶ø²»ÊÇ»ùÓÚ±ßÔµµÄ¡£»ùÓڲ㼶µÄ´¥·¢Ô´×ÔÓÚµç×Óµç·Éè¼Æ£¬Éè¼ÆÀíÄîÊǽÓÊÕʼþ£¨ÀýÈçÖжϣ©ºÍ¶Ô״̬×÷³ö·´Ó¦£¬¶ø»ùÓÚ±ßÔµ´¥·¢µÄÀíÄîÊǽÓÊÕʼþ²¢¶Ô״̬±ä»¯×÷³ö·´Ó¦¡£

»ùÓڲ㼶µÄ´¥·¢ËäȻЧÂʽϵͣ¬µ«ÓÉÓÚËüÇ¿ÖÆÖØÐÂÆÀ¹ÀÕû¸ö״̬¶ø²»ÊÇÖ»¹Ø×¢¸Ä±äµÄ״̬£¬Òò´Ë±»ÈÏΪ¸üÊʺÏÓÚ¸´ÔÓÇÒ²»¿É¿¿µÄ»·¾³£¬ÔÚÕâÖÖÇé¿öÏÂÐźſÉÄܻᶪʧ»òÖØ¸´¶à´Î¡£

ÕâÖÖÉè¼ÆÑ¡Ôñ»áÓ°ÏìÎÒÃDZàд¿ØÖÆÆ÷´úÂëµÄ·½Ê½¡£

Óë´ËÌÖÂÛÏà¹ØµÄ»¹ÓжÔAPIÇëÇóÉúÃüÖÜÆÚµÄÀí½â¡£ÏÂͼÌṩÁËÒ»¸ö¸ÅÒª×ܽ᣺

µ±ÏòAPI·þÎñÆ÷·¢³öÇëÇóʱ£¬ÌرðÊǶÔÓÚ´´½¨ºÍɾ³ýÇëÇó£¬ÇëÇ󽫾­ÀúÉÏÊö½×¶Î¡£Çë×¢Ò⣬¿ÉÒÔÖ¸¶¨webhooksÀ´Ö´Ðл¥³âºÍУÑé¡£Èç¹ûOperatorÒýÈëÁËеÄ×Ô¶¨Òå×ÊÔ´¶¨Ò壨 custom resource definition£¬CRD£©£¬ÎÒÃÇ¿ÉÄÜ»¹±ØÐ붨ÒåÕâЩwebhook¡£Í¨³££¬Operator½ø³ÌÒ²»áͨ¹ýÕìÌý¶Ë¿ÚÀ´ÊµÏÖwebhook¶Ëµã¡£

±¾Îĵµ½éÉÜÁËʹÓÃOperator SDKÉè¼ÆºÍ¿ª·¢OperatorʱҪ¼ÇסµÄÒ»×é×î¼Ñʵ¼ù¡£

Èç¹ûÄãµÄOperatorÒýÈëÁËеÄCRD£¬Operator SDK½«Ð­Öú¹¹½¨Ëü¡£ÒªÈ·±£ÄãµÄCRD·ûºÏKubernetesÀ©Õ¹APIµÄ×î¼Ñʵ¼ù£¬Çë×ñÑ­ÕâЩԼ¶¨¡£

±¾ÎÄÖÐÌáµ½µÄËùÓÐ×î¼Ñʵ¼ù¶¼ÔÚoperator-utils²Ö¿âÖÐÌṩµÄʾÀýÖнøÐÐÁËÃèÊö¡£¸Ã²Ö¿âÊä³öÊÇÒ»¸ö¿É±»ÒÀÀµµÄ¿â°ü£¬Äã¿ÉÒÔÔÚOperatorÖе¼Èë¸Ã¿â£¬ÎªÄã±àд×Ô¼ºµÄOperatorÌṩһЩÓÐÓõŤ¾ß¡£

×îºó£¬ÕâÌ×±àдOperatorµÄ×î¼Ñʵ¼ù´ú±íÁËÎÒ¸öÈ˵Ĺ۵㣬²»Ó¦±»ÊÓΪºìñ×î¼Ñʵ¼ùµÄÕýʽÁÐ±í¡£

´´½¨¼àÊÓ

ÕýÈçÎÒÃÇËù˵£¬¿ØÖÆÆ÷ÔÚ×ÊÔ´ÉϹ۲ìʼþ¡£ÕâÊÇͨ¹ý³éÏóµÄ¼à¿ØÀ´Íê³É¡£

¼àÊÓÊÇÒ»ÖÖ½ÓÊÕÌØ¶¨ÀàÐÍ£¨ºËÐÄÀàÐÍ»òCRD£©Ê¼þµÄ»úÖÆ¡£Í¨³£Í¨¹ýÖ¸¶¨ÒÔÏÂÄÚÈÝÀ´´´½¨¼àÊÓ£º

1.Òª¼àÊÓµÄ×ÊÔ´ÀàÐÍ¡£

2.´¦Àí³ÌÐò¡£´¦Àí³ÌÐò½«¼àÊÓÀàÐÍÉϵÄʼþÓ³Éäµ½µ÷ÓÃЭµ÷ÖÜÆÚµÄÒ»¸ö»ò¶à¸öʵÀý£¬¼àÊÓµÄÀàÐͺÍʵÀýÀàÐͲ»±ØÏàͬ¡£

3.Ò»¸öPredicate¡£Predicate¿ÉÒÔÊÇÒ»×麯Êý£¬¿ÉÒÔ×Ô¶¨Ò壬½öÓÃÀ´¹ýÂËÎÒÃǸÐÐËȤµÄʼþ¡£

ÏÂͼÃèÊöÁËÕû¸ö¹ý³Ì£º

ͨ³££¬´ò¿ªÍ¬Ò»ÖÖÀàµÄ¶à¸ö¼àÊÓÊÇ¿ÉÒÔ½ÓÊܵģ¬ÒòΪ¼àÊÓÊǶà·¸´Óõġ£

Ä㻹Ӧ³¢ÊÔ¾¡¿ÉÄܹýÂËʼþ¡£ÀýÈ磬ÕâÀïÊÇÒ»¸ö¹ýÂËÃØÃÜʼþµÄÃèÊö¡£ÕâÀïÎÒÃÇÖ»¶ÔÓÐÌØ¶¨µÄ×¢½âµÄkubernetes.io/tlsÀàÐ͵ÄÃÜԿʼþ¸ÐÐËȤ£º

isAnnotatedSecret := predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
oldSecret, ok := e.ObjectOld.(*corev1.Secret)
if !ok {
return false
}
newSecret, ok := e.ObjectNew.(*corev1.Secret)
if !ok {
return false
}
if newSecret.Type != util.TLSSecret {
return false
}
oldValue, _ := e.MetaOld.GetAnnotations()[certInfoAnnotation]
newValue, _ := e.MetaNew.GetAnnotations()[certInfoAnnotation]
old := oldValue == "true"
new := newValue == "true"
// if the content has changed we trigger if the annotation is there
if !reflect.DeepEqual(newSecret.Data[util.Cert], oldSecret.Data[util.Cert]) ||
!reflect.DeepEqual(newSecret.Data[util.CA], oldSecret.Data[util.CA]) {
return new
}
// otherwise we trigger if the annotation has changed
return old != new
},
CreateFunc: func(e event.CreateEvent) bool {
secret, ok := e.Object.(*corev1.Secret)
if !ok {
return false
}
if secret.Type != util.TLSSecret {
return false
}
value, _ := e.Meta.GetAnnotations()[certInfoAnnotation]
return value == "true"
},
}

Ò»¸ö·Ç³£³£¼ûµÄģʽÊǹ۲ìÎÒÃÇ´´½¨£¨ºÍÎÒÃÇÓµÓУ©×ÊÔ´ÉϵÄʼþ£¬²¢ÔÚÓµÓÐÕâЩ×ÊÔ´µÄCRÉϰ²ÅÅЭµ÷ÖÜÆÚ£¬ÕâÑù×ö¿ÉÒÔʹÓÃEnqueueRequestForOwner´¦Àí³ÌÐò¡£Õâ¿ÉÒÔ°´ÈçÏ·½Ê½Íê³É£º

err = c.Watch(&source.Kind{Type: &examplev1alpha1.MyControlledType{}}, &handler.EnqueueRe

²»Ì«³£¼ûµÄÇé¿öÊÇʼþ±»×é²¥µ½¶à¸öÄ¿±ê×ÊÔ´¡£¿¼ÂÇ»ùÓÚ×¢Êͽ«TLSÃÜÔ¿×¢È뵽·ÓɵĿØÖÆÆ÷Çé¿öÖС£Í¬Ò»ÃüÃû¿Õ¼äÖеĶà¸ö·ÓÉ¿ÉÒÔÖ¸ÏòÏàͬµÄÃÜÔ¿¡£Èç¹ûÃÜÔ¿¸Ä±ä£¬ÎÒÃÇÐèÒª¸üÐÂËùÓзÓÉ¡£Òò´Ë£¬ÎÒÃÇÐèÒªÔÚÃÜÔ¿ÀàÐÍÉÏ´´½¨Ò»¸ö¼àÊÓÆ÷£¬´¦Àí³ÌÐò½«ÈçÏÂËùʾ£º

type enqueueRequestForReferecingRoutes struct {
client.Client
}

// trigger a router reconcile event for those routes that reference this secret
func (e *enqueueRequestForReferecingRoutes) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
routes, _ := matchSecret(e.Client, types.NamespacedName{
Name: evt.Meta.GetName(),
Namespace: evt.Meta.GetNamespace(),
})
for _, route := range routes {
q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
Namespace: route.GetNamespace(),
Name: route.GetName(),
}})
}
}

// Update implements EventHandler
// trigger a router reconcile event for those routes that reference this secret
func (e *enqueueRequestForReferecingRoutes) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
routes, _ := matchSecret(e.Client, types.NamespacedName{
Name: evt.MetaNew.GetName(),
Namespace: evt.MetaNew.GetNamespace(),
})
for _, route := range routes {
q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
Namespace: route.GetNamespace(),
Name: route.GetName(),
}})
}
}

×ÊԴЭµ÷ÖÜÆÚ

Эµ÷ÖÜÆÚÊǼàÊÓ²úÉúʼþÉÏ´«ºó£¬¿ò¼Ü¸øÎÒÃÇÖØÐ¿ØÖƵĵط½¡£ÈçǰËùÊö£¬´ËʱÎÒÃÇûÓйØÓÚʼþÀàÐ͵ÄÐÅÏ¢£¬ÒòΪÎÒÃÇÕýÔÚ´¦Àí»ùÓÚ²ã±ðµÄ´¥·¢Æ÷¡£

ÏÂÃæÊǹÜÀíCRDµÄ¿ØÖÆÆ÷µÄ³£¼ûЭµ÷ÖÜÆÚµÄÄ£ÐÍ¡£Óëÿ¸öÄ£ÐÍÒ»Ñù£¬Õâ²¢²»ÄÜÍêÈ«·´Ó³ÈκÎÌØ¶¨µÄÓÃÀý£¬µ«ÎÒÏ£ÍûÊÇÓÐÓõ쬵±ÄãÔÚ±àдÔËËã·û¿¼Âǽâ¾öÎÊÌâµÄʱºò¡£

´ÓͼÖпÉÒÔ¿´³ö£¬Ö÷Òª²½ÖèÊÇ£º

1.¼ìË÷¸ÐÐËȤµÄCRʵÀý¡£

2.¹ÜÀíʵÀýÓÐЧÐÔ¡£ÎÒÃǶԲ»´øÓÐЧֵµÄʵÀý²»Ö´ÐÐÈκβÙ×÷¡£

3.¹ÜÀíʵÀý³õʼ»¯¡£Èç¹ûδ³õʼ»¯ÊµÀýµÄijЩֵ£¬Ôò±¾½Ú½«¸ºÔð´¦Àí¡£

4.¹ÜÀíʵÀýɾ³ý¡£Èç¹ûʵÀý±»É¾³ý£¬ÎÒÃÇÐèÒª½øÐÐÒ»Ð©ÌØ¶¨µÄÇåÀí£¬Õâ¾ÍÊÇÎÒÃǹÜÀíËüµÄµØ·½¡£

5.¹ÜÀí¿ØÖÆÆ÷ÒµÎñÂß¼­¡£Èç¹ûÉÏÊö²½ÖèÈ«²¿Í¨¹ý£¬ÎÒÃÇ×îÖÕ¿ÉÒÔ¹ÜÀíºÍÖ´ÐдËÌØ¶¨ÊµÀýµÄЭµ÷Âß¼­¡£Õâ¸ú¿ØÖÆÆ÷·Ç³£Ïà¹ØµÄ¡£

ÔÚ±¾½ÚµÄÆäÓಿ·ÖÖУ¬Äã¿ÉÒÔÔÚÿ¸ö²½ÖèÖÐÕÒµ½¸üÉîÈëµÄ¿¼ÂÇÒòËØ¡£

×ÊÔ´ÑéÖ¤

´æÔÚÁ½ÖÖÀàÐ͵ÄÑéÖ¤£ºÓï·¨ÑéÖ¤ºÍÓïÒåÑéÖ¤¡£

Óï·¨ÑéÖ¤£ºÍ¨¹ý¶¨ÒåOpenAPIÑéÖ¤¹æÔòÀ´½øÐÐÓï·¨ÑéÖ¤¡£

ÓïÒåÑéÖ¤£ºÍ¨¹ý´´½¨ValidatingAdmissionConfigurationÀ´Íê³ÉÓïÒåÑéÖ¤¡£

×¢Ò⣺ÎÞ·¨ÔÚ¿ØÖÆÆ÷ÖÐÑéÖ¤CR¡£Ò»µ©CR·þÎñÆ÷½ÓÊÜCR£¬Ëü½«´æ´¢ÔÚetcdÖС£Ò»µ©ËüÔÚetcdÖУ¬ÓµÓÐËüµÄ¿ØÖÆÆ÷¾ÍÎÞ·¨¾Ü¾øËü£¬Èç¹ûCRÎÞЧ£¬³¢ÊÔʹÓÃ/´¦ÀíËü½«µ¼Ö´íÎó¡£

½¨Ò飺ÒòΪÎÒÃDz»Äܱ£Ö¤½«´´½¨ºÍ/»òÔËÐÐValidatingAdmissionConfiguration£¬ÎÒÃÇ»¹Ó¦¸Ã´Ó¿ØÖÆÆ÷ÄÚÑéÖ¤CR£¬Èç¹ûËüÃÇÎÞЧÔò±ÜÃâ´´½¨ÎÞÏÞ´íÎóÑ­»·£¨ÁíÇë²ÎÔÄ£º´íÎó¹ÜÀí£©¡£

Óï·¨ÑéÖ¤

¿ÉÒÔ°´ÕÕ´Ë´¦ËùÊöÌí¼ÓOpenAPIÑéÖ¤¹æÔò¡£

½¨Ò飺¾¡¿ÉÄÜ¶àµØÎª×Ô¶¨Òå×ÊÔ´½¨Ä£×÷ΪÓï·¨ÑéÖ¤µÄÑéÖ¤¡£Óï·¨ÑéÖ¤Ïà¶Ô¼òµ¥£¬¿É·ÀÖ¹¸ñʽ´íÎóµÄCR´æ´¢ÔÚetcdÖУ¬Òò´ËÓ¦¾¡¿ÉÄÜʹÓÃËü¡£

ÓïÒåÑéÖ¤

ÓïÒåÑéÖ¤ÊǹØÓÚÈ·±£×ֶξßÓкÏÀíµÄÖµ²¢ÇÒÕû¸ö×ÊÔ´¼Ç??¼ÊÇÓÐÒâÒåµÄ¡£ÓïÒåÑéÖ¤ÒµÎñÂß¼­È¡¾öÓÚCR±íʾµÄ¸ÅÄ±ØÐëÓÉOperatir¿ª·¢ÈËÔ±±àÂë¡£

Èç¹û¸ø¶¨CRÐèÒªÓïÒåÑéÖ¤£¬ÔòOperatorÓ¦¹«¿ªwebhook£¬²¢ÇÒÓ¦ÔÚOperator²¿ÊðÖд´½¨ValidatingAdmissionConfiguration¡£

Ŀǰ´æÔÚÒÔÏÂÏÞÖÆ£º

ÔÚOpenShift 3.11ÖУ¬ValidatingAdmissionConfigurations´¦ÓÚ¼¼ÊõÔ¤ÀÀÖУ¨´Ó4.1¿ªÊ¼Ö§³ÖËüÃÇ£©¡£

Operator SDK²»Ö§³Ö½ÅÊÖ¼Üwebhooks¡£Õâ¿ÉÒÔʹÓÃkubebuilderÀ´½â¾ö£¬ÀýÈ磺

kubebuilder webhook -group crew -version v1 -kind FirstMate -t??ype = mutating -operations = create£¬update

ÑéÖ¤¿ØÖÆÆ÷ÖеÄ×ÊÔ´

×îºÃ¾Ü¾øÎÞЧµÄCR£¬¶ø²»ÊÇÔÚetcdÖнÓÊÜËü£¬È»ºó¹ÜÀí´íÎóÌõ¼þ¡£Ò²¾ÍÊÇ˵£¬¿ÉÄÜ´æÔÚδ²¿Êð»ò¸ù±¾²»¿ÉÓõÄValidatingAdmissionConfigurationµÄÇé¿ö¡£ÎÒÈÏΪÔÚ¿ØÖÆÆ÷´úÂëÖнøÐÐÓïÒåÑéÖ¤ÈÔÈ»ÊÇÒ»¸öºÃϰ¹ß¡£´úÂëµÄ½á¹¹Ó¦Ê¹Äã¿ÉÒÔÔÚValidatingAdmissionConfigurationºÍ¿ØÖÆÆ÷Ö®¼ä¹²ÏíÏàͬµÄÑéÖ¤Àý³Ì¡£

µ÷ÓÃÑéÖ¤·½·¨µÄ¿ØÖÆÆ÷´úÂëÓ¦ÈçÏÂËùʾ£º

if ok, err := r.IsValid(instance); !ok {
return r.ManageError(instance, err)
}

Çë×¢Ò⣬Èç¹ûÑé֤ʧ°Ü£¬ÎÒÃǻᰴÕÕ´íÎó¹ÜÀí²¿·ÖÖеÄ˵Ã÷¹ÜÀí´Ë´íÎó¡£

IsValidµÄº¯ÊýÀàËÆÓÚ£º

func (r *ReconcileMyCRD) IsValid(obj metav1.Object) (bool, error) {
mycrd, ok := obj.(*examplev1alpha1.MyCRD)
// validation logic
}
Resource Initialization

Kubernetes×ÊÔ´µÄÒ»¸öºÜºÃµÄ´«Í³ÌØÐÔÊÇ£¬Ö»ÓÐ×ÊÔ´µÄËùÐè×Ö¶ÎÓÉÓû§³õʼ»¯£¬ÆäËû×ֶοÉÒÔÊ¡ÂÔ¡£ÕâÊÇ´ÓÓû§½Ç¶È¿´µ½µÄ£¬µ«ÊÇ´Ó±àÂëÕߺ͵÷ÊÔ×ÊÔ´·¢ÉúµÄÊÂÇéµÄ½Ç¶ÈÀ´¿´£¬Êµ¼ÊÉϸüºÃµØÑ¡ÔñÊdzõʼ»¯ËùÓÐ×ֶΡ£ ÕâÔÊÐí±àд´úÂë¹ý³ÌÖÐÎÞÐèʼÖÕ¼ì²é×Ö¶ÎÊÇ·ñÒѶ¨Ò壬²¢ÔÊÐíÇáËÉÅųý´íÎóÇé¿ö¡£ ΪÁ˳õʼ»¯×ÊÔ´£¬ÓÐÁ½ÖÖÑ¡Ôñ£º

ÔÚ¿ØÖÆÆ÷Öж¨Òå³õʼ»¯·½·¨¡£

¶¨ÒåMutatingAdmissionConfiguration£¨¸Ã¹ý³ÌÀàËÆÓÚValidatingAdmissionConfiguration£©

½¨Ò飺ÔÚ¿ØÖÆÆ÷Öж¨Òå³õʼ»¯·½·¨¡£´úÂëÓ¦ÈçÏÂËùʾ£º

if ok := r.IsInitialized(instance); !ok {
err := r.GetClient().Update(context.TODO(), instance)
if err != nil {
log.Error(err, "unable to update instance", "instance", instance)
return r.ManageError(instance, err)
}
return reconcile.Result{}, nil
}

Çë×¢Ò⣬Èç¹û½á¹ûΪtrue£¬ÎÒÃǸüÐÂʵÀýÈ»ºó·µ»Ø¡£Õ⽫´¥·¢ÁíÒ»¸öÁ¢¼´Ð­µ÷ÖÜÆÚ¡£µÚ¶þ´Î³õʼ»¯·½·¨½«·µ»Øfalse£¬Âß¼­½«¼ÌÐøµ½ÏÂÒ»½×¶Î¡£

×ÊÔ´»ØÊÕ

Èç¹û×ÊÔ´²»ÊÇÓÉOperator¿ØÖƵÄCRÓµÓУ¬µ«ÔÚɾ³ýCRʱÐèÒª²ÉÈ¡´ëÊ©£¬Ôò±ØÐëʹÓûØÊÕÆ÷¡£

»ØÊÕÆ÷ÌṩÁËÒ»ÖÖ»úÖÆ£¬Í¨ÖªKubernetes¿ØÖÆÃæ°åÔÚÖ´Ðбê×¼KubernetesÀ¬»øÊÕ¼¯Âß¼­Ö®Ç°ÐèÒªÖ´ÐÐÏà¹Ø²Ù×÷¡£

¿ÉÒÔÔÚ×ÊÔ´ÉÏÉèÖÃÒ»¸ö»ò¶à¸öÖÕ½áÆ÷¡£Ã¿¸ö¿ØÖÆÆ÷Ó¦¹ÜÀí×Ô¼ºµÄ»ØÊÕÆ÷£¬Èç¹û´æÔÚÔòºöÂÔÆäËû»ØÊÕÆ÷¡£

ÕâÊǹÜÀí»ØÊÕÆ÷µÄα´úÂëËã·¨£º

Èç¹ûÐèÒª£¬ÔÚ³õʼ»¯·½·¨ÆÚ¼äÌí¼Ó»ØÊÕÆ÷¡£

Èç¹ûÕýÔÚɾ³ý×ÊÔ´£¬Çë¼ì²é´Ë¿ØÖÆÆ÷ÓµÓеĻØÊÕÆ÷ÊÇ·ñ´æÔÚ¡£

Èç¹ûûÓУ¬Çë·µ»Ø

Èç¹ûÊÇ£¬ÇëÖ´ÐÐÇåÀíÂß¼­

1. Èç¹û³É¹¦£¬Çëͨ¹ýɾ³ý»ØÊÕÆ÷À´¸üÐÂCR

2. Èç¹ûʧ°Ü¾ö¶¨ÊÇ·ñÖØÊÔ»ò·ÅÆú²¢¿ÉÄÜÁôÏÂÀ¬»ø£¨ÔÚijЩÇé¿öÏÂÕâÊÇ¿ÉÒÔ½ÓÊܵģ©

Èç¹ûÇåÀíÂß¼­ÐèÒª´´½¨ÆäËû×ÊÔ´£¬Çë¼Çס£¬ÎÞ·¨ÔÚҪɾ³ýµÄÃüÃû¿Õ¼äÖд´½¨ÆäËû×ÊÔ´¡£ÒªÉ¾³ýµÄÃüÃû¿Õ¼ä½«´¥·¢°üº¬CRºÍ»ØÊÕÆ÷ÔÚÄÚµÄËùÓÐÄÚÈݵÄɾ³ý¡£

ÇëÔÚ´Ë´¦²é¿´´úÂëʾÀý£º

if util.IsBeingDeleted(instance) {
if !util.HasFinalizer(instance, controllerName) {
return reconcile.Result{}, nil
}
err := r.manageCleanUpLogic(instance)
if err != nil {
log.Error(err, "unable to delete instance", "instance", instance)
return r.ManageError(instance, err)
}
util.RemoveFinalizer(instance, controllerName)
err = r.GetClient().Update(context.TODO(), instance)
if err != nil {
log.Error(err, "unable to update instance", "instance", instance)
return r.ManageError(instance, err)
}
return reconcile.Result{}, nil
}

×ÊÔ´ËùÓÐȨ

×ÊÔ´ËùÓÐȨÊÇKubernetesÖеÄÒ»¸ö±¾µØ¸ÅÄÓÃÓÚÈ·¶¨ÈçºÎɾ³ý×ÊÔ´¡£µ±É¾³ý×ÊÔ´¼°¸Ã×ÊÔ´ÓµÓÐµÄÆäËû×ÊԴʱ£¬Ä¬ÈÏÇé¿öÏÂÒ²»áɾ³ý×Ó×ÊÔ´£¨Äú¿ÉÒÔͨ¹ýÉèÖÃcascade = falseÀ´½ûÓôËÐÐΪ£©¡£

´ËÐÐΪÓÐÖúÓÚÈ·±£ÕýÈ·µÄ×ÊÔ´À¬»øÊÕ¼¯£¬ÓÈÆäÊǵ±×ÊÔ´¿ØÖƶ༶²ã´Î½á¹¹ÖÐµÄÆäËû×ÊԴʱ£¨Ç뿼ÂÇDeployment-> Repilcaset-> Pod£©¡£

½¨Ò飺Èç¹ûÄãµÄ¿ØÖÆÆ÷´´½¨×ÊÔ´²¢ÇÒÕâЩ×ÊÔ´µÄÉúÃüÖÜÆÚÓë×ÊÔ´£¨ºËÐÄ»òCR£©Ïà¹ØÁª£¬ÄÇôÄãÓ¦¸Ã½«´Ë×ÊÔ´ÉèÖÃΪÕâЩ×ÊÔ´µÄËùÓÐÕß¡£Õâ¿ÉÒÔ°´ÈçÏ·½Ê½Íê³É£º

controllerutil.SetControllerReference(owner, obj, r.GetScheme())1

ËùÓÐȨµÄÆäËûһЩ¹æÔòÈçÏ£º

owner¶ÔÏó±ØÐëÓëÓµÓжÔÏóλÓÚͬһÃû³Æ¿Õ¼äÖС£

ÃüÃû¿Õ¼ä×ÊÔ´¿ÉÒÔÓµÓÐȺ¼¯¼¶×ÊÔ´¡£ÎÒÃÇÔÚÕâÀïҪСÐÄ¡£¶ÔÏó¿ÉÒÔÓÐһϵÁÐËùÓÐÕß¡£Èç¹û¶à¸öÃüÃû¿Õ¼ä¶ÔÏóÓµÓÐÏàͬµÄ¼¯Èº¼¶¶ÔÏó£¬Ôòÿ¸ö¶ÔÏó¶¼Ó¦ÉùÃ÷ËùÓÐȨ¶ø²»Ó¦¸Ã¸²¸ÇÆäËûÈ˵ÄËùÓÐȨ£¨ÉÏÊöAPI¸ºÔðÕâÒ»µã£©¡£

¼¯Èº¼¶×ÊÔ´²»ÄÜÓµÓÐÃüÃû¿Õ¼ä×ÊÔ´¡£

¼¯Èº¼¶±ð¶ÔÏó¿ÉÒÔÓµÓÐÁíÒ»¸ö¼¯Èº¼¶±ð¶ÔÏó¡£

¹ÜÀí״̬

StatusÊÇ×ÊÔ´µÄ±ê×¼²¿·Ö¡£StatusÏÔÈ»ÓÃÓÚ±¨¸æ×ÊÔ´µÄ״̬¡£ÔÚ±¾ÎĵµÖУ¬ÎÒÃǽ«Ê¹ÓÃStatusÀ´±¨¸æÉÏ´ÎÖ´ÐÐЭµ÷ÖÜÆÚµÄ½á¹û¡£Äã¿ÉÒÔʹÓÃ״̬Ìí¼Ó¸ü¶àÐÅÏ¢¡£

ÔÚÕý³£Çé¿öÏ£¬Èç¹ûÎÒÃÇÿ´ÎÖ´ÐÐЭµ÷ÖÜÆÚʱ¶¼ÔÚ¸üÐÂ×ÊÔ´£¬Õ⽫´¥·¢¸üÐÂʼþ£¬¶øÊ¼þÓÖ»áÔÚÎÞÏÞÑ­»·Öд¥·¢Ð­µ÷ÖÜÆÚ¡£

³öÓÚÕâ¸öÔ­Òò£¬StatusÓ¦¸Ã½¨Ä£ÎªÒ»¸ö×Ó×ÊÔ´£¬ÈçÕâÀïËù½âÊ͵ġ£

ÕâÑù£¬ÎÒÃÇ¿ÉÒÔÔÚ²»Ôö¼ÓResourceGenerationÔªÊý¾Ý×ֶεÄÇé¿öϸüÐÂ×ÊԴ״̬¡£ÎÒÃÇ¿ÉÒÔʹÓÃÒÔÏÂÃüÁî¸üÐÂ״̬£º

err = r.Status().Update(context.Background(), instance)

ÏÖÔÚÎÒÃÇÐèҪΪÎÒÃǵļàÊÓ±àдһ¸öÃèÊö£¨Çë²ÎÔÄÓйØÕâЩ¸ÅÄîµÄ¸ü¶àÏêϸÐÅÏ¢µÄ¼àÊÓ²¿·Ö£©£¬ÕâЩÃèÊö½«ºöÂÔ²»Ôö¼ÓResourceGenerationµÄ¸üУ¬Õâ¿ÉÒÔʹÓÃGenerationChangePredicateÀ´Íê³É¡£

Èç¹ûÄ㻹¼ÇµÃ£¬Èç¹ûÎÒÃÇʹÓûØÊÕÆ÷£¬ÔòÓ¦ÔÚ³õʼ»¯Ê±ÉèÖûØÊÕÆ÷¡£Èç¹û»ØÊÕÆ÷ÊÇΨһÕýÔÚ³õʼ»¯µÄ£¬ÒòΪËüÊÇÔªÊý¾Ý×ֶεÄÒ»²¿·Ö£¬ResourceGeneration½«²»»áµÝÔö¡£ÎªÁ˽âÊ͸ÃÓÃÀý£¬ÒÔÏÂÊÇpredicateµÄÐ޸İ汾£º

type resourceGenerationOrFinalizerChangedPredicate struct {
predicate.Funcs
}

// Update implements default UpdateEvent filter
for validating resource version change
func (resourceGenerationOrFinalizerChangedPredicate) Update(e event.UpdateEvent) bool {
if e.MetaNew.GetGeneration() == e.MetaOld.GetGeneration()
&& reflect.DeepEqual
(e.MetaNew.GetFinalizers(), e.MetaOld.GetFinalizers()) {
return false
}
return true
}
Now assuming your status is as follows:

type MyCRStatus struct {
// +kubebuilder:validation:Enum=Success,Failure
Status string `json:"status,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Reason string `json:"reason,omitempty"`
}
You can write a function to manage the successful
execution of a reconciliation cycle:
func (r *ReconcilerBase) ManageSuccess(obj metav1.Object)
(reconcile.Result, error) {
runtimeObj, ok := (obj).(runtime.Object)
if !ok {
log.Error(errors.New("not a runtime.Object"), "passed object was not a runtime.Object", "object", obj)
return reconcile.Result{}, nil
}
if reconcileStatusAware, updateStatus := (obj).
(apis.ReconcileStatusAware); updateStatus {
status := apis.ReconcileStatus{
LastUpdate: metav1.Now(),
Reason: "",
Status: "Success",
}
reconcileStatusAware.SetReconcileStatus(status)
err := r.GetClient().Status().Update(context.Background(), runtimeObj)
if err != nil {
log.Error(err, "unable to update status")
return reconcile.Result{
RequeueAfter: time.Second,
Requeue: true,
}, nil
}
} else {
log.Info("object is not RecocileStatusAware, not setting status")
}
return reconcile.Result{}, nil
}

¹ÜÀí´íÎó

Èç¹û¿ØÖÆÆ÷½øÈë´íÎó״̬²¢ÔÚЭµ÷·½·¨Öзµ»Ø´íÎó£¬ÔòOperator½«´íÎó¼Ç¼µ½±ê×¼Êä³ö£¬²¢Á¢¼´ÖØÐµ÷¶ÈЭµ÷ʼþ£¨Ä¬Èϵ÷¶È³ÌÐòӦʵ¼Ê¼ì²âÊÇ·ñ·´¸´³öÏÖÏàͬµÄ´íÎ󣬲¢Ôö¼Óµ÷¶Èʱ¼ä£¬µ«¸ù¾ÝÎҵľ­Ñ飬Õâ²»»á·¢Éú£©¡£Èç¹û´íÎóÌõ¼þÊÇÓÀ¾ÃÐԵģ¬Ôò»á²úÉúÓÀ¾Ã´íÎóÑ­»·Çé¿ö¡£´ËÍ⣬Óû§²»»á¿´µ½´Ë´íÎóÇé¿ö¡£

ÓÐÁ½ÖÖ·½·¨¿ÉÒÔ֪ͨÓû§´íÎ󣬲¢ÇÒ¿ÉÒÔͬʱʹÓÃËüÃÇ£º

·µ»Ø¶ÔÏó״̬ÖеĴíÎó¡£

Éú³ÉÃèÊö´íÎóµÄʼþ¡£

´ËÍ⣬Èç¹ûÄãÈÏΪ´íÎó¿ÉÄÜ»á×ÔÐнâ¾ö£¬ÔòÓ¦ÔÚÒ»¶Îʱ¼äºóÖØÐ°²ÅÅЭµ÷ÖÜÆÚ¡£Í¨³££¬¸Ãʱ¼ä¶ÎÒÔÖ¸Êý·½Ê½Ôö¼Ó£¬ÒÔ±ãÔÚÿ´Îµü´úʱ£¬½«ÔÚδÀ´½øÒ»²½°²ÅÅЭµ÷ʼþ£¨ÀýÈ磬ÿ´ÎµÄʱ¼äÁ¿µÄÁ½±¶£©¡£

ÎÒÃǽ«ÔÚ״̬¹ÜÀíµÄ»ù´¡ÉϹ¹½¨´¦Àí´íÎóÇé¿ö£º

func (r *ReconcilerBase) ManageError(obj metav1.
Object, issue error) (reconcile.Result, error) {
runtimeObj, ok := (obj).(runtime.Object)
if !ok {
log.Error(errors.New("not a runtime.Object"),
"passed object was not a runtime.Object", "object", obj)
return reconcile.Result{}, nil
}
var retryInterval time.Duration
r.GetRecorder().Event(runtimeObj, "Warning", "ProcessingError",
issue.Error())
if reconcileStatusAware, updateStatus := (obj).
(apis.ReconcileStatusAware); updateStatus {
lastUpdate := reconcileStatusAware.GetReconcileStatus().
LastUpdate.Time
lastStatus := reconcileStatusAware.GetReconcileStatus().Status
status := apis.ReconcileStatus{
LastUpdate: metav1.Now(),
Reason: issue.Error(),
Status: "Failure",
}
reconcileStatusAware.SetReconcileStatus(status)
err := r.GetClient().Status().Update
(context.Background(), runtimeObj)
if err != nil {
log.Error(err, "unable to update status")
return reconcile.Result{
RequeueAfter: time.Second,
Requeue: true,
}, nil
}
if lastUpdate.IsZero() || lastStatus == "Success" {
retryInterval = time.Second
} else {
retryInterval = status.LastUpdate.Sub(lastUpdate).
Round(time.Second)
}
} else {
log.Info("object is not RecocileStatusAware, not setting status")
retryInterval = time.Second
}
return reconcile.Result{
RequeueAfter: time.Duration(math.Min(float64
(retryInterval.Nanoseconds()*2), float64
(time.Hour.Nanoseconds()*6))),
Requeue: true,
}, nil
}

Çë×¢Ò⣬´Ëº¯Êý»áÁ¢¼´·¢ËÍʼþ£¬È»ºóʹÓôíÎóÌõ¼þ¸üÐÂ״̬¡£×îºó£¬¼ÆËãºÎÊ±ÖØÐ°²ÅÅÏÂÒ»´Î³¢ÊÔ¡£¸ÃËã·¨³¢ÊÔ½«Ã¿¸öÑ­»·µÄʱ¼ä¼Ó±¶£¬×î¶à¿É´ïÁù¸öСʱ¡£

ÁùСʱÊÇÒ»¸öºÜºÃµÄÉÏÏÞ£¬ÒòΪʼþ³ÖÐø´óÔ¼Áù¸öСʱ£¬ËùÒÔÕâÓ¦¸ÃÈ·±£Ê¼ÖÕ´æÔÚÃèÊöµ±Ç°´íÎóÇé¿öµÄ»î¶¯Ê¼þ¡£

½áÂÛ

±¾²©¿ÍÖнéÉÜÁËʵ¼ùÉæ¼°Éè¼ÆKubernetes Operatorsʱ×î³£¼ûµÄÎÊÌ⣬²¢ÇÒÓ¦¸ÃÔÊÐíÄú±àдһ¸öÓÐÐÅÐÄͶÈëÉú²úµÄOperator¡£ºÜ¿ÉÄÜ£¬ÕâÖ»ÊÇÒ»¸ö¿ªÊ¼£¬½«À´»áÓиü¶àµÄ¿ò¼ÜºÍ¹¤¾ß½«»á³öÏÖ£¬ÒÔ°ïÖú±àдOperator¡£

 

   
2518 ´Îä¯ÀÀ       31
Ïà¹ØÎÄÕÂ

ÔÆ¼ÆËãµÄ¼Ü¹¹
¶ÔÔÆ¼ÆËã·þÎñÄ£ÐÍ
ÔÆ¼ÆËãºËÐļ¼ÊõÆÊÎö
Á˽âÔÆ¼ÆËãµÄ©¶´
Ïà¹ØÎĵµ

ÔÆ¼ÆËã¼ò½é
ÔÆ¼ÆËã¼ò½éÓëÔÆ°²È«
ÏÂÒ»´úÍøÂç¼ÆËã--ÔÆ¼ÆËã
ÈídzÎöÔÆ¼ÆËã
Ïà¹Ø¿Î³Ì

ÔÆ¼ÆËãÔ­ÀíÓëÓ¦ÓÃ
ÔÆ¼ÆËãÓ¦ÓÃÓ뿪·¢
CMMIÌåϵÓëʵ¼ù
»ùÓÚCMMI±ê×¼µÄÈí¼þÖÊÁ¿±£Ö¤
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]
 
×îÐÂÎÄÕÂ
ÔÆÔ­Éú¼Ü¹¹¸ÅÊö
K8S¸ß¿ÉÓü¯Èº¼Ü¹¹ÊµÏÖ
ÈÝÆ÷ÔÆ¹ÜÀíÖ®K8S¼¯Èº¸ÅÊö
k8s-ÕûÌå¸ÅÊöºÍ¼Ü¹¹
Ê®·ÖÖÓѧ»áÓÃdocker²¿Êð΢·þÎñ
×îпγÌ
ÔÆ¼ÆË㡢΢·þÎñÓë·Ö²¼Ê½¼Ü¹¹
Æóҵ˽ÓÐÔÆÔ­ÀíÓë¹¹½¨
»ùÓÚKubernetesµÄDevOpsʵ¼ù
ÔÆÆ½Ì¨¼Ü¹¹ÓëÓ¦Ó㨰¢ÀïÔÆ£©
Docker²¿Êð±»²âϵͳÓë×Ô¶¯»¯¿ò¼Üʵ¼ù
³É¹¦°¸Àý
±±¾© ÔÆÆ½Ì¨Óë΢·þÎñ¼Ü¹¹Éè¼Æ
ͨÓù«Ë¾GE DockerÔ­ÀíÓëʵ¼ùÅàѵ
ij¾ü¹¤Ñо¿µ¥Î» MDA£¨Ä£ÐÍÇý¶¯¼Ü¹¹£©
ÖªÃûÏû·Ñ½ðÈÚ¹«Ë¾ ÁìÓòÇý¶¯Éè¼Æ
ÉîÛÚijÆû³µÆóÒµ Ä£ÐÍÇý¶¯µÄ·ÖÎöÉè¼Æ