From 067b84a9b0ef12ebff9d88d339ff6d4ac1d603a8 Mon Sep 17 00:00:00 2001 From: Michi Mutsuzaki Date: Tue, 19 Sep 2023 00:03:35 +0000 Subject: [PATCH] podinfo: Populate workload info - Add WorkloadType and WorkloadObject fields to PodInfo. - Export workload.GetWorkloadMetaFromPod() function so that the operator can call it to set WorkloadType and WorkloadObject fields. - Update equal() function to take these fields into account. I opted for defining a new WorkloadObjectMeta type instead of using metav1.ObjectMeta to avoid generating unnecessary "unknown field" log messages. See [1] for additional context. [1]: https://github.com/kubernetes-sigs/controller-tools/issues/448 Signed-off-by: Michi Mutsuzaki --- operator/podinfo/podinfo_controller.go | 9 ++++++- operator/podinfo/podinfo_controller_test.go | 22 ++++++++++++++++ .../crds/v1alpha1/cilium.io_podinfo.yaml | 26 +++++++++++++++++++ pkg/k8s/apis/cilium.io/v1alpha1/types.go | 16 ++++++++++++ pkg/k8s/apis/cilium.io/v1alpha1/version.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 18 +++++++++++++ pkg/process/workload.go | 15 ++++++----- .../crds/v1alpha1/cilium.io_podinfo.yaml | 26 +++++++++++++++++++ .../pkg/k8s/apis/cilium.io/v1alpha1/types.go | 16 ++++++++++++ .../k8s/apis/cilium.io/v1alpha1/version.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 18 +++++++++++++ 11 files changed, 160 insertions(+), 10 deletions(-) diff --git a/operator/podinfo/podinfo_controller.go b/operator/podinfo/podinfo_controller.go index 5e6e53ed91..da3a831c3a 100644 --- a/operator/podinfo/podinfo_controller.go +++ b/operator/podinfo/podinfo_controller.go @@ -8,6 +8,7 @@ import ( "reflect" ciliumiov1alpha1 "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" + "github.com/cilium/tetragon/pkg/process" "golang.org/x/exp/maps" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -87,13 +88,16 @@ func equal(pod *corev1.Pod, podInfo *ciliumiov1alpha1.PodInfo) bool { Controller: &controller, BlockOwnerDeletion: &blockOwnerDeletion, } + workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod) return pod.Name == podInfo.Name && pod.Namespace == podInfo.Namespace && pod.Status.PodIP == podInfo.Status.PodIP && maps.Equal(pod.Annotations, podInfo.Annotations) && maps.Equal(pod.Labels, podInfo.Labels) && len(podInfo.OwnerReferences) == 1 && - reflect.DeepEqual(podInfo.OwnerReferences[0], expectedOwnerReference) + reflect.DeepEqual(podInfo.OwnerReferences[0], expectedOwnerReference) && + reflect.DeepEqual(podInfo.WorkloadObject, workloadObject) && + reflect.DeepEqual(podInfo.WorkloadType, workloadType) } // hasAllRequiredFields checks if the necessary pod fields are available. @@ -112,6 +116,7 @@ func generatePodInfo(pod *corev1.Pod) *ciliumiov1alpha1.PodInfo { for _, podIP := range pod.Status.PodIPs { podIPs = append(podIPs, ciliumiov1alpha1.PodIP{IP: podIP.IP}) } + workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod) controller := true blockOwnerDeletion := true return &ciliumiov1alpha1.PodInfo{ @@ -136,6 +141,8 @@ func generatePodInfo(pod *corev1.Pod) *ciliumiov1alpha1.PodInfo { PodIP: pod.Status.PodIP, PodIPs: podIPs, }, + WorkloadType: workloadType, + WorkloadObject: workloadObject, } } diff --git a/operator/podinfo/podinfo_controller_test.go b/operator/podinfo/podinfo_controller_test.go index 73c15c4631..b91f307478 100644 --- a/operator/podinfo/podinfo_controller_test.go +++ b/operator/podinfo/podinfo_controller_test.go @@ -11,6 +11,7 @@ import ( "testing" ciliumv1alpha1 "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" + "github.com/cilium/tetragon/pkg/process" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -113,6 +114,7 @@ func TestGeneratePod(t *testing.T) { for _, podIP := range pod.Status.PodIPs { podIPs = append(podIPs, ciliumv1alpha1.PodIP{IP: podIP.IP}) } + workloadObject, workloadType := process.GetWorkloadMetaFromPod(pod) expectedPodInfo := &ciliumv1alpha1.PodInfo{ ObjectMeta: metav1.ObjectMeta{ Name: pod.Name, @@ -134,6 +136,8 @@ func TestGeneratePod(t *testing.T) { PodIP: pod.Status.PodIP, PodIPs: podIPs, }, + WorkloadType: workloadType, + WorkloadObject: workloadObject, } generatedPodInfo := generatePodInfo(pod) assert.Equal(t, expectedPodInfo, generatedPodInfo, "Generated incorrect PodInfo corresponding to the pod") @@ -244,5 +248,23 @@ func TestEqual(t *testing.T) { pod.Annotations = getRandMap() assert.False(t, equal(pod, podInfo), "Pod Annotations changed, still returning pod not changed") }) + + t.Run("Pod owner references changed", func(t *testing.T) { + pod := randomPodGenerator() + controller, blockOwnerDeletion := true, true + podInfo := generatePodInfo(pod) + pod.GenerateName = "tetragon-" + pod.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "apps/v1", + Kind: "DaemonSet", + Name: "tetragon", + UID: "00000000-0000-0000-0000-000000000000", + Controller: &controller, + BlockOwnerDeletion: &blockOwnerDeletion, + }, + } + assert.False(t, equal(pod, podInfo), "Pod owner references changed, still returning pod not changed") + }) }) } diff --git a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml index 801433d0e3..84ae826017 100644 --- a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml +++ b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml @@ -59,6 +59,32 @@ spec: type: object type: array type: object + workloadObject: + description: Workload that created this pod. + properties: + name: + description: Name of the object. + type: string + namespace: + description: Namespace of this object. + type: string + type: object + workloadType: + description: Workload type (e.g. "Deployment", "Daemonset") that created + this pod. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + type: object type: object served: true storage: true diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/types.go b/pkg/k8s/apis/cilium.io/v1alpha1/types.go index 560f5a5f9d..73f2e03ed5 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/types.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/types.go @@ -271,6 +271,17 @@ type PodIP struct { IP string `json:"IP,omitempty"` } +// WorkloadObjectMeta is metadata associated with workloads that create pods. +type WorkloadObjectMeta struct { + // Name of the object. + // +optional + Name string `json:"name,omitempty"` + + // Namespace of this object. + // +optional + Namespace string `json:"namespace,omitempty"` +} + // +genclient // +kubebuilder:object:root=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -283,6 +294,11 @@ type PodInfo struct { Spec PodInfoSpec `json:"spec,omitempty"` Status PodInfoStatus `json:"status,omitempty"` + + // Workload type (e.g. "Deployment", "Daemonset") that created this pod. + WorkloadType metav1.TypeMeta `json:"workloadType,omitempty"` + // Workload that created this pod. + WorkloadObject WorkloadObjectMeta `json:"workloadObject,omitempty"` } // +kubebuilder:object:root=true diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/version.go b/pkg/k8s/apis/cilium.io/v1alpha1/version.go index 2a7a08370c..9102afb649 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/version.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/version.go @@ -7,4 +7,4 @@ package v1alpha1 // Used to determine if CRD needs to be updated in cluster // // Developers: Bump patch for each change in the CRD schema. -const CustomResourceDefinitionSchemaVersion = "0.12.3" +const CustomResourceDefinitionSchemaVersion = "0.12.4" diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go b/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go index f73ef2d741..4a397c1be5 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go @@ -330,6 +330,8 @@ func (in *PodInfo) DeepCopyInto(out *PodInfo) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) + out.WorkloadType = in.WorkloadType + out.WorkloadObject = in.WorkloadObject return } @@ -640,3 +642,19 @@ func (in *UProbeSpec) DeepCopy() *UProbeSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadObjectMeta) DeepCopyInto(out *WorkloadObjectMeta) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadObjectMeta. +func (in *WorkloadObjectMeta) DeepCopy() *WorkloadObjectMeta { + if in == nil { + return nil + } + out := new(WorkloadObjectMeta) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/process/workload.go b/pkg/process/workload.go index fa82b0509f..b55a520bad 100644 --- a/pkg/process/workload.go +++ b/pkg/process/workload.go @@ -11,6 +11,7 @@ import ( "regexp" "strings" + "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -18,15 +19,16 @@ import ( var cronJobNameRegexp = regexp.MustCompile(`(.+)-\d{8,10}$`) // GetWorkloadMetaFromPod heuristically derives workload metadata from the pod spec. -func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta) { +func GetWorkloadMetaFromPod(pod *corev1.Pod) (v1alpha1.WorkloadObjectMeta, metav1.TypeMeta) { if pod == nil { - return metav1.ObjectMeta{}, metav1.TypeMeta{} + return v1alpha1.WorkloadObjectMeta{}, metav1.TypeMeta{} } // try to capture more useful namespace/name info for deployments, etc. // TODO(dougreid): expand to enable lookup of OWNERs recursively a la kubernetesenv - deployMeta := pod.ObjectMeta - deployMeta.ManagedFields = nil - deployMeta.OwnerReferences = nil + deployMeta := v1alpha1.WorkloadObjectMeta{ + Name: pod.GetObjectMeta().GetName(), + Namespace: pod.GetObjectMeta().GetNamespace(), + } typeMetadata := metav1.TypeMeta{ Kind: "Pod", @@ -65,7 +67,6 @@ func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta // https://github.com/openshift/library-go/blob/7a65fdb398e28782ee1650959a5e0419121e97ae/pkg/apps/appsutil/const.go#L25 deployMeta.Name = pod.Labels["deploymentconfig"] typeMetadata.Kind = "DeploymentConfig" - delete(deployMeta.Labels, "deploymentconfig") } else if typeMetadata.Kind == "Job" { // If job name suffixed with `-`, where the length of digit timestamp is 8~10, // trim the suffix and set kind to cron job. @@ -89,6 +90,6 @@ func getWorkloadMetaFromPod(pod *corev1.Pod) (metav1.ObjectMeta, metav1.TypeMeta } func getWorkloadNameFromPod(pod *corev1.Pod) string { - objMeta, _ := getWorkloadMetaFromPod(pod) + objMeta, _ := GetWorkloadMetaFromPod(pod) return objMeta.Name } diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml index 801433d0e3..84ae826017 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml @@ -59,6 +59,32 @@ spec: type: object type: array type: object + workloadObject: + description: Workload that created this pod. + properties: + name: + description: Name of the object. + type: string + namespace: + description: Namespace of this object. + type: string + type: object + workloadType: + description: Workload type (e.g. "Deployment", "Daemonset") that created + this pod. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + type: object type: object served: true storage: true diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go index 560f5a5f9d..73f2e03ed5 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go @@ -271,6 +271,17 @@ type PodIP struct { IP string `json:"IP,omitempty"` } +// WorkloadObjectMeta is metadata associated with workloads that create pods. +type WorkloadObjectMeta struct { + // Name of the object. + // +optional + Name string `json:"name,omitempty"` + + // Namespace of this object. + // +optional + Namespace string `json:"namespace,omitempty"` +} + // +genclient // +kubebuilder:object:root=true // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -283,6 +294,11 @@ type PodInfo struct { Spec PodInfoSpec `json:"spec,omitempty"` Status PodInfoStatus `json:"status,omitempty"` + + // Workload type (e.g. "Deployment", "Daemonset") that created this pod. + WorkloadType metav1.TypeMeta `json:"workloadType,omitempty"` + // Workload that created this pod. + WorkloadObject WorkloadObjectMeta `json:"workloadObject,omitempty"` } // +kubebuilder:object:root=true diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/version.go b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/version.go index 2a7a08370c..9102afb649 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/version.go +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/version.go @@ -7,4 +7,4 @@ package v1alpha1 // Used to determine if CRD needs to be updated in cluster // // Developers: Bump patch for each change in the CRD schema. -const CustomResourceDefinitionSchemaVersion = "0.12.3" +const CustomResourceDefinitionSchemaVersion = "0.12.4" diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go index f73ef2d741..4a397c1be5 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go @@ -330,6 +330,8 @@ func (in *PodInfo) DeepCopyInto(out *PodInfo) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) + out.WorkloadType = in.WorkloadType + out.WorkloadObject = in.WorkloadObject return } @@ -640,3 +642,19 @@ func (in *UProbeSpec) DeepCopy() *UProbeSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadObjectMeta) DeepCopyInto(out *WorkloadObjectMeta) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadObjectMeta. +func (in *WorkloadObjectMeta) DeepCopy() *WorkloadObjectMeta { + if in == nil { + return nil + } + out := new(WorkloadObjectMeta) + in.DeepCopyInto(out) + return out +}