±à¼ÍƼö: |
±¾ÎĽéÉÜÁËʵ¼ùÉæ¼°Éè¼Æ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¡£
|