/
kubernetes.go
116 lines (101 loc) · 3.56 KB
/
kubernetes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plugin
import (
"context"
"fmt"
"strings"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"istio.io/istio/pkg/kube"
"istio.io/istio/pkg/log"
"istio.io/istio/pkg/util/sets"
)
type PodInfo struct {
Containers sets.String
Labels map[string]string
Annotations map[string]string
ProxyType string
ProxyEnvironments map[string]string
ProxyUID *int64
ProxyGID *int64
}
// newK8sClient returns a Kubernetes client
func newK8sClient(conf Config) (kubernetes.Interface, error) {
// Some config can be passed in a kubeconfig file
kubeconfig := conf.Kubernetes.Kubeconfig
config, err := kube.DefaultRestConfig(kubeconfig, "")
if err != nil {
log.Errorf("Failed setting up kubernetes client with kubeconfig %s", kubeconfig)
return nil, err
}
log.Debugf("istio-cni set up kubernetes client with kubeconfig %s", kubeconfig)
// Create the client
return kubernetes.NewForConfig(config)
}
// getK8sPodInfo returns information of a POD
func getK8sPodInfo(client kubernetes.Interface, podName, podNamespace string) (*PodInfo, error) {
pod, err := client.CoreV1().Pods(podNamespace).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
return nil, err
}
pi := ExtractPodInfo(pod)
log.Debugf("Pod %v/%v info: \n%+v", podNamespace, podName, pi)
return pi, nil
}
func ExtractPodInfo(pod *v1.Pod) *PodInfo {
pi := &PodInfo{
Containers: sets.New[string](),
Labels: pod.Labels,
Annotations: pod.Annotations,
ProxyEnvironments: make(map[string]string),
}
for _, c := range containers(pod) {
pi.Containers.Insert(c.Name)
if c.Name == ISTIOPROXY {
// don't include ports from istio-proxy in the redirect ports
// Get proxy container env variable, and extract out ProxyConfig from it.
for _, e := range c.Env {
pi.ProxyEnvironments[e.Name] = e.Value
}
if len(c.Args) >= 2 && c.Args[0] == "proxy" {
pi.ProxyType = c.Args[1]
}
if c.SecurityContext != nil {
pi.ProxyUID = c.SecurityContext.RunAsUser
pi.ProxyGID = c.SecurityContext.RunAsGroup
}
}
}
return pi
}
// containers fetches all containers in the pod.
// This is used to extract init containers (istio-init and istio-validation), and the sidecar.
// The sidecar can be a normal container or init in Kubernetes 1.28+
func containers(pod *v1.Pod) []v1.Container {
res := make([]v1.Container, 0, len(pod.Spec.Containers)+len(pod.Spec.InitContainers))
res = append(res, pod.Spec.InitContainers...)
res = append(res, pod.Spec.Containers...)
return res
}
func (pi PodInfo) String() string {
var b strings.Builder
b.WriteString(fmt.Sprintf(" Containers: %v\n", sets.SortedList(pi.Containers)))
b.WriteString(fmt.Sprintf(" Labels: %+v\n", pi.Labels))
b.WriteString(fmt.Sprintf(" Annotations: %+v\n", pi.Annotations))
b.WriteString(fmt.Sprintf(" Envs: %+v\n", pi.ProxyEnvironments))
b.WriteString(fmt.Sprintf(" ProxyConfig: %+v\n", pi.ProxyEnvironments))
return b.String()
}