Use patch for robust pod metadata update in poolmgr (#1509)

Use "Patch" to update pod metadata instead of "Update" to avoid 
dropping fields that the old client-go doesn't support.
This commit is contained in:
Ta-Ching Chen
2020-01-28 00:04:22 +08:00
committed by GitHub
parent e651433727
commit 8f8afaf139
+27 -6
View File
@@ -18,6 +18,7 @@ package poolmgr
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
@@ -244,20 +245,41 @@ func (gp *GenericPool) _choosePod(newLabels map[string]string) (*apiv1.Pod, erro
// Relabel. If the pod already got picked and // Relabel. If the pod already got picked and
// modified, this should fail; in that case just // modified, this should fail; in that case just
// retry. // retry.
chosenPod.ObjectMeta.Labels = newLabels labelPatch, _ := json.Marshal(newLabels)
// Append executor instance id to pod annotations to // Append executor instance id to pod annotations to
// indicate this pod is managed by this executor. // indicate this pod is managed by this executor.
chosenPod.ObjectMeta.Annotations = gp.getDeployAnnotations() annotations := gp.getDeployAnnotations()
annotationPatch, _ := json.Marshal(annotations)
_, err = gp.kubernetesClient.CoreV1().Pods(gp.namespace).Update(chosenPod) patch := fmt.Sprintf(`{"metadata":{"annotations":%v, "labels":%v}}`, string(annotationPatch), string(labelPatch))
gp.logger.Info("relabel pod", zap.String("pod", patch))
newPod, err := gp.kubernetesClient.CoreV1().Pods(chosenPod.Namespace).Patch(chosenPod.Name, k8sTypes.StrategicMergePatchType, []byte(patch))
if err != nil { if err != nil {
gp.logger.Error("failed to relabel pod", zap.Error(err), zap.String("pod", chosenPod.ObjectMeta.Name)) gp.logger.Error("failed to relabel pod", zap.Error(err), zap.String("pod", chosenPod.Name))
continue continue
} }
// With StrategicMergePatchType, the client-go sometimes return
// nil error and the labels & annotations remain the same.
// So we have to check both of them to ensure the patch success.
for k, v := range newLabels {
if newPod.Labels[k] != v {
return nil, errors.Errorf("value of necessary labels '%v' mismatch: want '%v', get '%v'",
k, v, newPod.Labels[k])
}
}
for k, v := range annotations {
if newPod.Annotations[k] != v {
return nil, errors.Errorf("value of necessary annotations '%v' mismatch: want '%v', get '%v'",
k, v, newPod.Annotations[k])
}
}
} }
gp.logger.Info("chose pod", zap.Any("labels", newLabels), gp.logger.Info("chose pod", zap.Any("labels", newLabels),
zap.String("pod", chosenPod.ObjectMeta.Name), zap.Duration("elapsed_time", time.Since(startTime))) zap.String("pod", chosenPod.Name), zap.Duration("elapsed_time", time.Since(startTime)))
return chosenPod, nil return chosenPod, nil
} }
} }
@@ -269,7 +291,6 @@ func (gp *GenericPool) labelsForFunction(metadata *metav1.ObjectMeta) map[string
label[fv1.FUNCTION_NAMESPACE] = metadata.Namespace // function CRD must stay within same namespace of environment CRD label[fv1.FUNCTION_NAMESPACE] = metadata.Namespace // function CRD must stay within same namespace of environment CRD
label["managed"] = "false" // this allows us to easily find pods not managed by the deployment label["managed"] = "false" // this allows us to easily find pods not managed by the deployment
return label return label
} }
func (gp *GenericPool) scheduleDeletePod(name string) { func (gp *GenericPool) scheduleDeletePod(name string) {