Skip to content

Commit

Permalink
podinfo: Populate workload info
Browse files Browse the repository at this point in the history
- 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]: kubernetes-sigs/controller-tools#448

Signed-off-by: Michi Mutsuzaki <michi@isovalent.com>
  • Loading branch information
michi-covalent committed Sep 20, 2023
1 parent 5b25a7c commit 067b84a
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 10 deletions.
9 changes: 8 additions & 1 deletion operator/podinfo/podinfo_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand All @@ -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{
Expand All @@ -136,6 +141,8 @@ func generatePodInfo(pod *corev1.Pod) *ciliumiov1alpha1.PodInfo {
PodIP: pod.Status.PodIP,
PodIPs: podIPs,
},
WorkloadType: workloadType,
WorkloadObject: workloadObject,
}
}

Expand Down
22 changes: 22 additions & 0 deletions operator/podinfo/podinfo_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand All @@ -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")
Expand Down Expand Up @@ -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")
})
})
}
26 changes: 26 additions & 0 deletions pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_podinfo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pkg/k8s/apis/cilium.io/v1alpha1/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
18 changes: 18 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions pkg/process/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,24 @@ 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"
)

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",
Expand Down Expand Up @@ -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 `-<digit-timestamp>`, where the length of digit timestamp is 8~10,
// trim the suffix and set kind to cron job.
Expand All @@ -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
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 067b84a

Please sign in to comment.