Skip to content

Commit

Permalink
Enable webhook to oss (#1653)
Browse files Browse the repository at this point in the history
Co-authored-by: Tamir David <tamirdavid@Tamirs-MacBook-Pro.local>
  • Loading branch information
tamirdavid1 and Tamir David authored Oct 30, 2024
1 parent 89439b1 commit 509afdc
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 116 deletions.
59 changes: 9 additions & 50 deletions cli/cmd/resources/instrumentor.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
"github.com/odigos-io/odigos/k8sutils/pkg/consts"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -68,54 +69,6 @@ func NewInstrumentorLeaderElectionRoleBinding(ns string) *rbacv1.RoleBinding {
}
}

func NewInstrumentorRoleBinding(ns string) *rbacv1.RoleBinding {
return &rbacv1.RoleBinding{
TypeMeta: metav1.TypeMeta{
Kind: "RoleBinding",
APIVersion: "rbac.authorization.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "odigos-instrumentor",
Namespace: ns,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: "odigos-instrumentor",
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: "odigos-instrumentor",
},
}
}

func NewInstrumentorRole(ns string) *rbacv1.Role {
return &rbacv1.Role{
TypeMeta: metav1.TypeMeta{
Kind: "Role",
APIVersion: "rbac.authorization.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "odigos-instrumentor",
Namespace: ns,
},
Rules: []rbacv1.PolicyRule{
{
Verbs: []string{
"get",
},
APIGroups: []string{""},
Resources: []string{
"secrets",
},
},
},
}
}

func NewInstrumentorClusterRole() *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
TypeMeta: metav1.TypeMeta{
Expand Down Expand Up @@ -526,7 +479,15 @@ func NewInstrumentorDeployment(ns string, version string, telemetryEnabled bool,
},
},
},
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: consts.OdigosDeploymentConfigMapName,
},
},
},
},

Ports: []corev1.ContainerPort{
{
Name: "webhook-server",
Expand Down Expand Up @@ -630,8 +591,6 @@ func (a *instrumentorResourceManager) InstallFromScratch(ctx context.Context) er
certManagerInstalled := isCertManagerInstalled(ctx, a.client)
resources := []client.Object{
NewInstrumentorServiceAccount(a.ns),
NewInstrumentorRole(a.ns),
NewInstrumentorRoleBinding(a.ns),
NewInstrumentorLeaderElectionRoleBinding(a.ns),
NewInstrumentorClusterRole(),
NewInstrumentorClusterRoleBinding(a.ns),
Expand Down
5 changes: 3 additions & 2 deletions cli/cmd/resources/odigosdeployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

func NewOdigosDeploymentConfigMap(ns string, odigosVersion string) *corev1.ConfigMap {
func NewOdigosDeploymentConfigMap(ns string, odigosVersion string, odigosTier string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: v1.TypeMeta{
Kind: "ConfigMap",
Expand All @@ -27,6 +27,7 @@ func NewOdigosDeploymentConfigMap(ns string, odigosVersion string) *corev1.Confi
},
Data: map[string]string{
"ODIGOS_VERSION": odigosVersion,
"ODIGOS_TIER": odigosTier,
},
}
}
Expand Down Expand Up @@ -104,7 +105,7 @@ func (a *odigosDeploymentResourceManager) Name() string { return "OdigosDeployme

func (a *odigosDeploymentResourceManager) InstallFromScratch(ctx context.Context) error {
resources := []client.Object{
NewOdigosDeploymentConfigMap(a.ns, a.odigosVersion),
NewOdigosDeploymentConfigMap(a.ns, a.odigosVersion, string(a.odigosTier)),
NewLeaderElectionRole(a.ns),
}

Expand Down
4 changes: 4 additions & 0 deletions helm/odigos/templates/cleanup/cleanup-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ rules:
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["list", "get", "patch", "delete"]
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
verbs: ["get", "list", "delete"]

12 changes: 0 additions & 12 deletions helm/odigos/templates/instrumentor/role.yaml

This file was deleted.

13 changes: 0 additions & 13 deletions helm/odigos/templates/instrumentor/rolebinding.yaml

This file was deleted.

1 change: 1 addition & 0 deletions helm/odigos/templates/odigos-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ metadata:
namespace: {{ .Release.Namespace }}
data:
ODIGOS_VERSION: {{ .Values.image.tag | default .Chart.AppVersion }}
ODIGOS_TIER: "{{- if .Values.onPremToken }}onprem{{- else }}community{{- end }}"
17 changes: 16 additions & 1 deletion instrumentor/controllers/instrumentationdevice/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,23 @@ func addInstrumentationDeviceToWorkload(ctx context.Context, kubeClient client.C
}

result, err := controllerutil.CreateOrPatch(ctx, kubeClient, obj, func() error {

podSpec, err := getPodSpecFromObject(obj)
if err != nil {
return err
}

return instrumentation.ApplyInstrumentationDevicesToPodTemplate(podSpec, runtimeDetails, otelSdkToUse, obj)
err, deviceApplied := instrumentation.ApplyInstrumentationDevicesToPodTemplate(podSpec, runtimeDetails, otelSdkToUse, obj)
if err != nil {
return err
}

// If instrumentation device is applied successfully, add odigos.io/inject-instrumentation label to enable the webhook
if deviceApplied {
instrumentation.SetInjectInstrumentationLabel(podSpec)
}

return nil
})

if err != nil {
Expand Down Expand Up @@ -162,12 +173,16 @@ func removeInstrumentationDeviceFromWorkload(ctx context.Context, kubeClient cli
if err != nil {
return err
}
// If instrumentation device is removed successfully, remove odigos.io/inject-instrumentation label to disable the webhook
instrumentation.RemoveInjectInstrumentationLabel(podSpec)

instrumentation.RevertInstrumentationDevices(podSpec)

err = instrumentation.RevertEnvOverwrites(workloadObj, podSpec)
if err != nil {
return err
}

return nil
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@ func (p *PodsWebhook) Default(ctx context.Context, obj runtime.Object) error {
}

func injectOdigosEnvVars(pod *corev1.Pod) {
namespace := pod.Namespace

// Common environment variables that do not change across containers
commonEnvVars := []corev1.EnvVar{
{
Name: EnvVarNamespace,
Value: namespace,
Name: EnvVarNamespace,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
{
Name: EnvVarPodName,
Expand Down
39 changes: 32 additions & 7 deletions instrumentor/instrumentation/instrumentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import (
"fmt"
"strings"

odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"
"github.com/odigos-io/odigos/common/envOverwrite"
"sigs.k8s.io/controller-runtime/pkg/client"

odigosv1 "github.com/odigos-io/odigos/api/odigos/v1alpha1"
"github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/k8sutils/pkg/env"
"github.com/odigos-io/odigos/k8sutils/pkg/envoverwrite"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
Expand All @@ -20,15 +21,17 @@ var (
ErrPatchEnvVars = errors.New("failed to patch env vars")
)

func ApplyInstrumentationDevicesToPodTemplate(original *corev1.PodTemplateSpec, runtimeDetails *odigosv1.InstrumentedApplication, defaultSdks map[common.ProgrammingLanguage]common.OtelSdk, targetObj client.Object) error {
func ApplyInstrumentationDevicesToPodTemplate(original *corev1.PodTemplateSpec, runtimeDetails *odigosv1.InstrumentedApplication, defaultSdks map[common.ProgrammingLanguage]common.OtelSdk, targetObj client.Object) (error, bool) {
// delete any existing instrumentation devices.
// this is necessary for example when migrating from community to enterprise,
// and we need to cleanup the community device before adding the enterprise one.
RevertInstrumentationDevices(original)

deviceApplied := false

manifestEnvOriginal, err := envoverwrite.NewOrigWorkloadEnvValues(targetObj.GetAnnotations())
if err != nil {
return err
return err, deviceApplied
}

var modifiedContainers []corev1.Container
Expand All @@ -39,15 +42,15 @@ func ApplyInstrumentationDevicesToPodTemplate(original *corev1.PodTemplateSpec,
// this is necessary to sync the existing envs with the missing language if changed for any reason.
err = patchEnvVarsForContainer(runtimeDetails, &container, nil, *containerLanguage, manifestEnvOriginal)
if err != nil {
return fmt.Errorf("%w: %v", ErrPatchEnvVars, err)
return fmt.Errorf("%w: %v", ErrPatchEnvVars, err), deviceApplied
}
modifiedContainers = append(modifiedContainers, container)
continue
}

otelSdk, found := defaultSdks[*containerLanguage]
if !found {
return fmt.Errorf("%w for language: %s, container:%s", ErrNoDefaultSDK, *containerLanguage, container.Name)
return fmt.Errorf("%w for language: %s, container:%s", ErrNoDefaultSDK, *containerLanguage, container.Name), deviceApplied
}

instrumentationDeviceName := common.InstrumentationDeviceName(*containerLanguage, otelSdk)
Expand All @@ -57,19 +60,22 @@ func ApplyInstrumentationDevicesToPodTemplate(original *corev1.PodTemplateSpec,
}
container.Resources.Limits[corev1.ResourceName(instrumentationDeviceName)] = resource.MustParse("1")

deviceApplied = true

err = patchEnvVarsForContainer(runtimeDetails, &container, &otelSdk, *containerLanguage, manifestEnvOriginal)
if err != nil {
return fmt.Errorf("%w: %v", ErrPatchEnvVars, err)
return fmt.Errorf("%w: %v", ErrPatchEnvVars, err), deviceApplied
}

modifiedContainers = append(modifiedContainers, container)

}

original.Spec.Containers = modifiedContainers

// persist the original values if changed
manifestEnvOriginal.SerializeToAnnotation(targetObj)
return nil
return nil, deviceApplied
}

// this function restores a workload manifest env vars to their original values.
Expand Down Expand Up @@ -218,3 +224,22 @@ func patchEnvVarsForContainer(runtimeDetails *odigosv1.InstrumentedApplication,

return nil
}

func SetInjectInstrumentationLabel(original *corev1.PodTemplateSpec) {
odigosTier := env.GetOdigosTierFromEnv()

// inject the instrumentation annotation for oss tier only
if odigosTier == common.CommunityOdigosTier {
if original.Labels == nil {
original.Labels = make(map[string]string)
}
original.Labels["odigos.io/inject-instrumentation"] = "true"
}
}

// RemoveInjectInstrumentationLabel removes the "odigos.io/inject-instrumentation" label if it exists.
func RemoveInjectInstrumentationLabel(original *corev1.PodTemplateSpec) {
if original.Labels != nil {
delete(original.Labels, "odigos.io/inject-instrumentation")
}
}
27 changes: 10 additions & 17 deletions instrumentor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,11 @@ import (

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/rest"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
ctrlzap "sigs.k8s.io/controller-runtime/pkg/log/zap"
Expand Down Expand Up @@ -131,8 +129,14 @@ func main() {
UID: deployment.UID,
},
Status: deployment.Status,
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: deployment.Spec.Template.Labels,
},
},
},
}

newDep.Spec.Template.Spec = deployment.Spec.Template.Spec
return newDep, nil
},
Expand Down Expand Up @@ -202,21 +206,10 @@ func main() {
os.Exit(1)
}

// Init Kubernetes API client
cfg, err := rest.InClusterConfig()
if err != nil {
setupLog.Error(err, "Failed to init Kubernetes API client")
os.Exit(-1)
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
setupLog.Error(err, "Failed to init Kubernetes API client")
os.Exit(-1)
}

ctx := signals.SetupSignalHandler()

err = sdks.SetDefaultSDKs(ctx, clientset)
err = sdks.SetDefaultSDKs(ctx)

if err != nil {
setupLog.Error(err, "Failed to set default SDKs")
os.Exit(-1)
Expand Down
9 changes: 2 additions & 7 deletions instrumentor/sdks/sdks.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (

"github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/k8sutils/pkg/env"
k8sutils "github.com/odigos-io/odigos/k8sutils/pkg/utils"
"k8s.io/client-go/kubernetes"
)

var defaultOtelSdkPerLanguage = map[common.ProgrammingLanguage]common.OtelSdk{}
Expand Down Expand Up @@ -43,11 +41,8 @@ func otelSdkConfigOnPrem() map[common.ProgrammingLanguage]common.OtelSdk {
}
}

func SetDefaultSDKs(ctx context.Context, clientset *kubernetes.Clientset) error {
odigosTier, err := k8sutils.GetCurrentOdigosTier(ctx, env.GetCurrentNamespace(), clientset)
if err != nil {
return err
}
func SetDefaultSDKs(ctx context.Context) error {
odigosTier := env.GetOdigosTierFromEnv()

switch odigosTier {
case common.CommunityOdigosTier:
Expand Down
Loading

0 comments on commit 509afdc

Please sign in to comment.