github.phpd.cn/cilium/cilium@v1.6.12/pkg/k8s/annotate.go (about)

     1  // Copyright 2016-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package k8s
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"fmt"
    21  	"net"
    22  
    23  	"github.com/cilium/cilium/pkg/annotation"
    24  	"github.com/cilium/cilium/pkg/cidr"
    25  	"github.com/cilium/cilium/pkg/controller"
    26  	clientset "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned"
    27  	"github.com/cilium/cilium/pkg/logging/logfields"
    28  
    29  	"github.com/sirupsen/logrus"
    30  	"k8s.io/apimachinery/pkg/types"
    31  	"k8s.io/client-go/kubernetes"
    32  )
    33  
    34  // K8sClient is a wrapper around kubernetes.Interface.
    35  type K8sClient struct {
    36  	// kubernetes.Interface is the object through which interactions with
    37  	// Kubernetes are performed.
    38  	kubernetes.Interface
    39  }
    40  
    41  // K8sCiliumClient is a wrapper around clientset.Interface.
    42  type K8sCiliumClient struct {
    43  	clientset.Interface
    44  }
    45  
    46  func updateNodeAnnotation(c kubernetes.Interface, nodeName string, v4CIDR, v6CIDR *cidr.CIDR, v4HealthIP, v6HealthIP, v4CiliumHostIP, v6CiliumHostIP net.IP) error {
    47  	annotations := map[string]string{}
    48  
    49  	if v4CIDR != nil {
    50  		annotations[annotation.V4CIDRName] = v4CIDR.String()
    51  	}
    52  	if v6CIDR != nil {
    53  		annotations[annotation.V6CIDRName] = v6CIDR.String()
    54  	}
    55  
    56  	if v4HealthIP != nil {
    57  		annotations[annotation.V4HealthName] = v4HealthIP.String()
    58  	}
    59  	if v6HealthIP != nil {
    60  		annotations[annotation.V6HealthName] = v6HealthIP.String()
    61  	}
    62  
    63  	if v4CiliumHostIP != nil {
    64  		annotations[annotation.CiliumHostIP] = v4CiliumHostIP.String()
    65  	}
    66  
    67  	if v6CiliumHostIP != nil {
    68  		annotations[annotation.CiliumHostIPv6] = v6CiliumHostIP.String()
    69  	}
    70  
    71  	if len(annotations) == 0 {
    72  		return nil
    73  	}
    74  
    75  	raw, err := json.Marshal(annotations)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	patch := []byte(fmt.Sprintf(`{"metadata":{"annotations":%s}}`, raw))
    80  
    81  	_, err = c.CoreV1().Nodes().Patch(nodeName, types.StrategicMergePatchType, patch)
    82  
    83  	return err
    84  }
    85  
    86  // AnnotateNode writes v4 and v6 CIDRs and health IPs in the given k8s node name.
    87  // In case of failure while updating the node, this function while spawn a go
    88  // routine to retry the node update indefinitely.
    89  func (k8sCli K8sClient) AnnotateNode(nodeName string, v4CIDR, v6CIDR *cidr.CIDR, v4HealthIP, v6HealthIP, v4CiliumHostIP, v6CiliumHostIP net.IP) error {
    90  	scopedLog := log.WithFields(logrus.Fields{
    91  		logfields.NodeName:       nodeName,
    92  		logfields.V4Prefix:       v4CIDR,
    93  		logfields.V6Prefix:       v6CIDR,
    94  		logfields.V4HealthIP:     v4HealthIP,
    95  		logfields.V6HealthIP:     v6HealthIP,
    96  		logfields.V4CiliumHostIP: v4CiliumHostIP,
    97  		logfields.V6CiliumHostIP: v6CiliumHostIP,
    98  	})
    99  	scopedLog.Debug("Updating node annotations with node CIDRs")
   100  
   101  	controller.NewManager().UpdateController("update-k8s-node-annotations",
   102  		controller.ControllerParams{
   103  			DoFunc: func(_ context.Context) error {
   104  				err := updateNodeAnnotation(k8sCli, nodeName, v4CIDR, v6CIDR, v4HealthIP, v6HealthIP, v4CiliumHostIP, v6CiliumHostIP)
   105  				if err != nil {
   106  					scopedLog.WithFields(logrus.Fields{}).WithError(err).Warn("Unable to patch node resource with annotation")
   107  				}
   108  				return err
   109  			},
   110  		})
   111  
   112  	return nil
   113  }