github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/controller/kube/index.go (about) 1 package kube 2 3 import ( 4 appsv1 "k8s.io/api/apps/v1" 5 corev1 "k8s.io/api/core/v1" 6 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 "k8s.io/apimachinery/pkg/labels" 8 "k8s.io/apimachinery/pkg/types" 9 ) 10 11 func NewIndex() *Index { 12 return &Index{ 13 podsInfoByIP: make(map[string]IPInfo), 14 replicaSets: make(map[types.UID]metav1.ObjectMeta), 15 jobs: make(map[types.UID]metav1.ObjectMeta), 16 deployments: make(map[types.UID]*appsv1.Deployment), 17 pods: make(map[types.UID]*corev1.Pod), 18 nodesByName: make(map[string]*corev1.Node), 19 } 20 } 21 22 type Index struct { 23 podsInfoByIP map[string]IPInfo 24 replicaSets map[types.UID]metav1.ObjectMeta 25 jobs map[types.UID]metav1.ObjectMeta 26 deployments map[types.UID]*appsv1.Deployment 27 pods map[types.UID]*corev1.Pod 28 nodesByName map[string]*corev1.Node 29 } 30 31 func (i *Index) addFromPod(pod *corev1.Pod) { 32 i.pods[pod.UID] = pod 33 if !pod.Spec.HostNetwork { 34 ipInfo := IPInfo{ 35 Pod: pod, 36 Node: i.nodesByName[pod.Spec.NodeName], 37 } 38 owner := i.getPodOwner(pod) 39 if owner.UID != pod.UID { 40 ipInfo.Owner = &owner 41 } 42 i.podsInfoByIP[pod.Status.PodIP] = ipInfo 43 } 44 } 45 46 func (i *Index) addFromEndpoints(v *corev1.Endpoints) { 47 for _, subset := range v.Subsets { 48 for _, address := range subset.Addresses { 49 // Skip adding entries if target info exists. Will be added by pods. 50 if address.TargetRef != nil { 51 continue 52 } 53 54 i.podsInfoByIP[address.IP] = IPInfo{Endpoint: &IPEndpoint{ 55 ID: string(v.UID), 56 Name: v.Name, 57 Namespace: v.Namespace, 58 Labels: v.Labels, 59 }} 60 } 61 } 62 } 63 64 func (i *Index) addFromService(v *corev1.Service) { 65 ips := getServiceIPs(v) 66 if len(ips) == 0 { 67 return 68 } 69 70 for _, ip := range ips { 71 i.podsInfoByIP[ip] = IPInfo{Service: v} 72 } 73 } 74 75 func (i *Index) addFromNode(v *corev1.Node) { 76 i.nodesByName[v.Name] = v 77 78 for _, address := range v.Status.Addresses { 79 if address.Type == corev1.NodeInternalIP { 80 i.podsInfoByIP[address.Address] = IPInfo{Node: v} 81 return 82 } 83 } 84 } 85 86 func (i *Index) deleteFromPod(v *corev1.Pod) { 87 delete(i.pods, v.UID) 88 89 if !v.Spec.HostNetwork { 90 delete(i.podsInfoByIP, v.Status.PodIP) 91 } 92 } 93 94 func (i *Index) deleteFromEndpoints(v *corev1.Endpoints) { 95 for _, subset := range v.Subsets { 96 for _, address := range subset.Addresses { 97 if address.TargetRef != nil { 98 continue 99 } 100 101 delete(i.podsInfoByIP, address.IP) 102 } 103 } 104 } 105 106 func (i *Index) deleteFromService(v *corev1.Service) { 107 ips := getServiceIPs(v) 108 if len(ips) == 0 { 109 return 110 } 111 112 for _, ip := range ips { 113 delete(i.podsInfoByIP, ip) 114 } 115 } 116 117 func (i *Index) deleteByNode(v *corev1.Node) { 118 delete(i.nodesByName, v.Name) 119 120 for _, address := range v.Status.Addresses { 121 if address.Type == corev1.NodeInternalIP { 122 delete(i.podsInfoByIP, address.Address) 123 } 124 } 125 } 126 127 func (i *Index) getPodOwner(pod *corev1.Pod) metav1.OwnerReference { 128 if len(pod.OwnerReferences) == 0 { 129 return metav1.OwnerReference{ 130 Kind: "Pod", 131 Name: pod.Name, 132 UID: pod.UID, 133 } 134 } 135 owner := pod.OwnerReferences[0] 136 switch owner.Kind { 137 case "ReplicaSet": 138 if rs, found := i.replicaSets[owner.UID]; found { 139 owner = findOwner(owner, rs.OwnerReferences) 140 if owner.Kind != "Deployment" { 141 if dep, found := findDeploymentByPodSelector(i.deployments, pod); found { 142 return metav1.OwnerReference{ 143 Kind: dep.Kind, 144 Name: dep.Name, 145 UID: dep.UID, 146 } 147 } 148 } 149 return owner 150 } 151 case "Job": 152 if rs, found := i.jobs[owner.UID]; found { 153 return findOwner(owner, rs.OwnerReferences) 154 } 155 } 156 return owner 157 } 158 159 func findDeploymentByPodSelector(deployments map[types.UID]*appsv1.Deployment, pod *corev1.Pod) (*appsv1.Deployment, bool) { 160 for _, w := range deployments { 161 sel, err := metav1.LabelSelectorAsSelector(w.Spec.Selector) 162 if err != nil { 163 continue 164 } 165 if sel.Matches(labels.Set(pod.Labels)) { 166 return w, true 167 } 168 } 169 return nil, false 170 } 171 172 func findOwner(ref metav1.OwnerReference, refs []metav1.OwnerReference) metav1.OwnerReference { 173 if len(refs) > 0 { 174 return refs[0] 175 } 176 return ref 177 } 178 179 func getServiceIPs(svc *corev1.Service) []string { 180 switch svc.Spec.Type { //nolint:exhaustive 181 case corev1.ServiceTypeClusterIP, corev1.ServiceTypeNodePort: 182 if svc.Spec.ClusterIP == corev1.ClusterIPNone { 183 return nil 184 } 185 return []string{svc.Spec.ClusterIP} 186 case corev1.ServiceTypeLoadBalancer: 187 for _, ingress := range svc.Status.LoadBalancer.Ingress { 188 if ip := ingress.IP; ip != "" { 189 return []string{ip} 190 } 191 } 192 } 193 return svc.Spec.ExternalIPs 194 } 195 196 type IPEndpoint struct { 197 ID string 198 Name string 199 Namespace string 200 Labels map[string]string 201 } 202 203 type IPInfo struct { 204 IP string 205 Pod *corev1.Pod 206 Service *corev1.Service 207 Node *corev1.Node 208 Endpoint *IPEndpoint 209 Owner *metav1.OwnerReference 210 }