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

     1  // Copyright 2018 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  	"regexp"
    19  
    20  	k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
    21  	"github.com/cilium/cilium/pkg/logging/logfields"
    22  	"github.com/cilium/cilium/pkg/option"
    23  	"github.com/cilium/cilium/pkg/policy"
    24  
    25  	"github.com/sirupsen/logrus"
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  )
    29  
    30  const (
    31  	// AnnotationIstioSidecarStatus is the annotation added by Istio into a pod
    32  	// when it is injected with a sidecar proxy.
    33  	// Since Istio 0.5.0, the value of this annotation is a serialized JSON object
    34  	// with the following structure ("imagePullSecrets" was added in Istio 0.8.0):
    35  	//
    36  	//     {
    37  	//         "version": "0213afe1274259d2f23feb4820ad2f8eb8609b84a5538e5f51f711545b6bde88",
    38  	//         "initContainers": ["sleep", "istio-init"],
    39  	//         "containers": ["istio-proxy"],
    40  	//         "volumes": ["cilium-unix-sock-dir", "istio-envoy", "istio-certs"],
    41  	//         "imagePullSecrets": null
    42  	//     }
    43  	AnnotationIstioSidecarStatus = "sidecar.istio.io/status"
    44  
    45  	// DefaultSidecarIstioProxyImageRegexp is the default regexp compiled into
    46  	// SidecarIstioProxyImageRegexp.
    47  	DefaultSidecarIstioProxyImageRegexp = "cilium/istio_proxy"
    48  )
    49  
    50  var (
    51  	// SidecarIstioProxyImageRegexp is the regular expression matching
    52  	// compatible Istio sidecar istio-proxy container image names.
    53  	// This is set by the "sidecar-istio-proxy-image" configuration flag.
    54  	SidecarIstioProxyImageRegexp = regexp.MustCompile(DefaultSidecarIstioProxyImageRegexp)
    55  )
    56  
    57  // isInjectedWithIstioSidecarProxy returns whether the given pod has been
    58  // injected by Istio with a sidecar proxy that is compatible with Cilium.
    59  func isInjectedWithIstioSidecarProxy(scopedLog *logrus.Entry, pod *corev1.Pod) bool {
    60  	istioStatusString, ok := pod.GetAnnotations()[AnnotationIstioSidecarStatus]
    61  	if !ok {
    62  		// Istio's injection annotation was not found.
    63  		scopedLog.Debugf("No %s annotation", AnnotationIstioSidecarStatus)
    64  		return false
    65  	}
    66  
    67  	scopedLog.Debugf("Found %s annotation with value: %s",
    68  		AnnotationIstioSidecarStatus, istioStatusString)
    69  
    70  	// Check that there's an "istio-proxy" container that uses an image
    71  	// compatible with Cilium.
    72  	for _, container := range pod.Spec.Containers {
    73  		if container.Name != "istio-proxy" {
    74  			continue
    75  		}
    76  		scopedLog.Debug("Found istio-proxy container in pod")
    77  
    78  		if !SidecarIstioProxyImageRegexp.MatchString(container.Image) {
    79  			continue
    80  		}
    81  		scopedLog.Debugf("istio-proxy container runs Cilium-compatible image: %s", container.Image)
    82  
    83  		for _, mount := range container.VolumeMounts {
    84  			if mount.MountPath != "/var/run/cilium" {
    85  				continue
    86  			}
    87  			scopedLog.Debug("istio-proxy container has volume mounted into /var/run/cilium")
    88  
    89  			return true
    90  		}
    91  	}
    92  
    93  	scopedLog.Debug("No Cilium-compatible istio-proxy container found")
    94  	return false
    95  }
    96  
    97  // GetPodLabels returns the labels of a pod
    98  func GetPodLabels(namespace, podName string) (map[string]string, error) {
    99  	scopedLog := log.WithFields(logrus.Fields{
   100  		logfields.K8sNamespace: namespace,
   101  		logfields.K8sPodName:   podName,
   102  	})
   103  	scopedLog.Debug("Connecting to k8s apiserver to retrieve labels for pod")
   104  
   105  	result, err := Client().CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{})
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	// Also get all labels from the namespace where the pod is running
   111  	k8sNs, err := Client().CoreV1().Namespaces().Get(namespace, metav1.GetOptions{})
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	k8sLabels := result.GetLabels()
   117  	if k8sLabels == nil {
   118  		k8sLabels = map[string]string{}
   119  	}
   120  	for k, v := range k8sNs.GetLabels() {
   121  		k8sLabels[policy.JoinPath(k8sConst.PodNamespaceMetaLabels, k)] = v
   122  	}
   123  	k8sLabels[k8sConst.PodNamespaceLabel] = namespace
   124  
   125  	if result.Spec.ServiceAccountName != "" {
   126  		k8sLabels[k8sConst.PolicyLabelServiceAccount] = result.Spec.ServiceAccountName
   127  	} else {
   128  		delete(k8sLabels, k8sConst.PolicyLabelServiceAccount)
   129  	}
   130  
   131  	// If the pod has been injected with an Istio sidecar proxy compatible with
   132  	// Cilium, add a label to notify that.
   133  	// If the pod already contains that label to explicitly enable or disable
   134  	// the sidecar proxy mode, keep it as is.
   135  	if _, ok := k8sLabels[k8sConst.PolicyLabelIstioSidecarProxy]; !ok &&
   136  		isInjectedWithIstioSidecarProxy(scopedLog, result) {
   137  		k8sLabels[k8sConst.PolicyLabelIstioSidecarProxy] = "true"
   138  	}
   139  
   140  	k8sLabels[k8sConst.PolicyLabelCluster] = option.Config.ClusterName
   141  
   142  	return k8sLabels, nil
   143  }