Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Source CRD instrumentation #2059

Open
wants to merge 12 commits into
base: feature/source-crd
Choose a base branch
from

Conversation

damemi
Copy link
Contributor

@damemi damemi commented Dec 23, 2024

This introduces the basic implementation for instrumenting/uninstrumenting via Source objects (#2037)

This does not remove current instrumentation with the odigos-instrumentation label, and does not do any checks to avoid conflicts etc. That work will follow. Right now this just drops in the basic workflow alongside the current label approach.

Changes:

  • Add a SourceReconciler to the startlangdetection Instrumentor controller.
    • Parse workload from Source object
    • If the Source is not being deleted, add 2 finalizers (one used for Source deletion, and another used by the deleteinstrumentedapplication controller), add workload labels to the Source for lookup, and continue with flow of creating an InstrumentationConfig by calling requestOdigletsToCalculateRuntimeDetails
    • If the Source is being deleted (determined by a DeletionTimestamp being present in an Update event, with the finalizer blocking deletion), remove the source finalizer and delete the InstrumentationConfig.
  • Add a function GetSourceListForWorkload everywhere we currently call workload.IsWorkloadInstrumentationEffectiveEnabled that returns any Source objects referencing the workload.
  • Add SourceReconciler to deleteinstrumentedapplication Instrumentor controller
    • When Source object is deleted, remove instrumented application finalizer and continue with reconciling the workload, which should trigger uninstrumentation based on the new checks for GetSourceListForWorkload throughout

I'm not a fan of using 2 finalizers and worry that we could end up with a deadlock/race. This is mostly due to InstrumentedApplication, and deprecating InstrumentedApplication should simplify the work required for this greatly.

Still needs:

  • Namespace instrumentation and exclusion
  • Switch odigos-instrumentation label to be shorthand for creating a Source on that workload/namespace
    • This includes removing current label checks with workload.IsWorkloadInstrumentationEffectiveEnabled
  • UI integration

@damemi damemi changed the title Source crd Implement Source CRD instrumentation Dec 23, 2024
@damemi damemi marked this pull request as ready for review December 23, 2024 21:20
@damemi damemi requested review from blumamir and RonFed December 23, 2024 21:22
// GetSourceListForWorkload returns a SourceList of all Sources that have matching
// workload name, namespace, and kind labels for an object. In theory, this should only
// ever return a list with 0 or 1 items, but due diligence should handle unexpected cases.
func GetSourceListForWorkload(ctx context.Context, kubeClient client.Client, obj client.Object) (*SourceList, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
func GetSourceListForWorkload(ctx context.Context, kubeClient client.Client, obj client.Object) (*SourceList, error) {
func GetSourceListForWorkload(ctx context.Context, kubeClient client.Client, obj client.Object) (SourceList, error) {

// Added by startlangdetection controller when Source is created
var instrumentedApplicationFinalizer = "odigos.io/source-instrumentedapplication-finalizer"

type SourceDeletedPredicate struct{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a utils package for predicates.
This one exists in k8sutils/pkg.predicate/deletion.go

source.Labels[workloadNamespaceLabel] = source.Spec.Workload.Namespace
source.Labels[workloadKindLabel] = string(source.Spec.Workload.Kind)

if err := r.Update(ctx, source); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it is possible here but since we are using Get modify Update we could get a conflict error if the update is on a stale object.
We have k8sutils/pkg/utils/retryconflict.go if it is relevant here.

// GetSourceListForWorkload returns a SourceList of all Sources that have matching
// workload name, namespace, and kind labels for an object. In theory, this should only
// ever return a list with 0 or 1 items, but due diligence should handle unexpected cases.
func GetSourceListForWorkload(ctx context.Context, kubeClient client.Client, obj client.Object) (*SourceList, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought: maybe we could wrap this function in another once returning a single source or an error.

Comment on lines +22 to +24
workloadNameLabel = "odigos.io/workload-name"
workloadNamespaceLabel = "odigos.io/workload-namespace"
workloadKindLabel = "odigos.io/workload-kind"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these consts will be used in other places as well, so maybe worth considering placing them in k8sutils/pkg/consts

@@ -74,5 +76,17 @@ func SetupWithManager(mgr ctrl.Manager) error {
return err
}

err = builder.
ControllerManagedBy(mgr).
Named("startlangdetection-source").
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add an event filter here to pass only Create events?

Comment on lines +63 to +70
// Check if a Source object exists for this workload
sourceList, err := v1alpha1.GetSourceListForWorkload(ctx, k8sClient, obj)
if err != nil {
return ctrl.Result{}, err
}
if len(sourceList.Items) == 0 {
return ctrl.Result{}, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which cases are handled here?

@@ -200,6 +200,11 @@ cli-install:
@echo "Installing odigos from source. version: $(ODIGOS_CLI_VERSION)"
cd ./cli ; go run -tags=embed_manifests . install --version $(ODIGOS_CLI_VERSION)

.PHONY: cli-uninstall
cli-uninstall:
@echo "Installing odigos from source. version: $(ODIGOS_CLI_VERSION)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
@echo "Installing odigos from source. version: $(ODIGOS_CLI_VERSION)"
@echo "Uninstalling odigos from source. version: $(ODIGOS_CLI_VERSION)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants