istio.io/istio@v0.0.0-20240520182934-d79c90f27776/cni/pkg/plugin/kubernetes.go (about)

     1  // Copyright Istio Authors
     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 plugin
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"strings"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/client-go/kubernetes"
    25  
    26  	"istio.io/istio/pkg/kube"
    27  	"istio.io/istio/pkg/log"
    28  	"istio.io/istio/pkg/util/sets"
    29  )
    30  
    31  type PodInfo struct {
    32  	Containers        sets.String
    33  	Labels            map[string]string
    34  	Annotations       map[string]string
    35  	ProxyType         string
    36  	ProxyEnvironments map[string]string
    37  	ProxyUID          *int64
    38  	ProxyGID          *int64
    39  }
    40  
    41  // newK8sClient returns a Kubernetes client
    42  func newK8sClient(conf Config) (kubernetes.Interface, error) {
    43  	// Some config can be passed in a kubeconfig file
    44  	kubeconfig := conf.Kubernetes.Kubeconfig
    45  
    46  	config, err := kube.DefaultRestConfig(kubeconfig, "")
    47  	if err != nil {
    48  		log.Errorf("Failed setting up kubernetes client with kubeconfig %s", kubeconfig)
    49  		return nil, err
    50  	}
    51  
    52  	log.Debugf("istio-cni set up kubernetes client with kubeconfig %s", kubeconfig)
    53  
    54  	// Create the client
    55  	return kubernetes.NewForConfig(config)
    56  }
    57  
    58  // getK8sPodInfo returns information of a POD
    59  func getK8sPodInfo(client kubernetes.Interface, podName, podNamespace string) (*PodInfo, error) {
    60  	pod, err := client.CoreV1().Pods(podNamespace).Get(context.TODO(), podName, metav1.GetOptions{})
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	pi := ExtractPodInfo(pod)
    66  	log.Debugf("Pod %v/%v info: \n%+v", podNamespace, podName, pi)
    67  
    68  	return pi, nil
    69  }
    70  
    71  func ExtractPodInfo(pod *v1.Pod) *PodInfo {
    72  	pi := &PodInfo{
    73  		Containers:        sets.New[string](),
    74  		Labels:            pod.Labels,
    75  		Annotations:       pod.Annotations,
    76  		ProxyEnvironments: make(map[string]string),
    77  	}
    78  	for _, c := range containers(pod) {
    79  		pi.Containers.Insert(c.Name)
    80  		if c.Name == ISTIOPROXY {
    81  			// don't include ports from istio-proxy in the redirect ports
    82  			// Get proxy container env variable, and extract out ProxyConfig from it.
    83  			for _, e := range c.Env {
    84  				pi.ProxyEnvironments[e.Name] = e.Value
    85  			}
    86  			if len(c.Args) >= 2 && c.Args[0] == "proxy" {
    87  				pi.ProxyType = c.Args[1]
    88  			}
    89  			if c.SecurityContext != nil {
    90  				pi.ProxyUID = c.SecurityContext.RunAsUser
    91  				pi.ProxyGID = c.SecurityContext.RunAsGroup
    92  			}
    93  		}
    94  	}
    95  	return pi
    96  }
    97  
    98  // containers fetches all containers in the pod.
    99  // This is used to extract init containers (istio-init and istio-validation), and the sidecar.
   100  // The sidecar can be a normal container or init in Kubernetes 1.28+
   101  func containers(pod *v1.Pod) []v1.Container {
   102  	res := make([]v1.Container, 0, len(pod.Spec.Containers)+len(pod.Spec.InitContainers))
   103  	res = append(res, pod.Spec.InitContainers...)
   104  	res = append(res, pod.Spec.Containers...)
   105  	return res
   106  }
   107  
   108  func (pi PodInfo) String() string {
   109  	var b strings.Builder
   110  	b.WriteString(fmt.Sprintf("  Containers: %v\n", sets.SortedList(pi.Containers)))
   111  	b.WriteString(fmt.Sprintf("  Labels: %+v\n", pi.Labels))
   112  	b.WriteString(fmt.Sprintf("  Annotations: %+v\n", pi.Annotations))
   113  	b.WriteString(fmt.Sprintf("  Envs: %+v\n", pi.ProxyEnvironments))
   114  	b.WriteString(fmt.Sprintf("  ProxyConfig: %+v\n", pi.ProxyEnvironments))
   115  	return b.String()
   116  }