diff --git a/components/profile-controller/config/manager/kustomization.yaml b/components/profile-controller/config/manager/kustomization.yaml index f72d05bd2..db849d319 100644 --- a/components/profile-controller/config/manager/kustomization.yaml +++ b/components/profile-controller/config/manager/kustomization.yaml @@ -11,4 +11,8 @@ configMapGenerator: - ISTIO_INGRESS_GATEWAY_PRINCIPAL="cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account" - NOTEBOOK_CONTROLLER_PRINCIPAL="cluster.local/ns/kubeflow/sa/notebook-controller-service-account" - KFP_UI_PRINCIPAL="cluster.local/ns/kubeflow/sa/ml-pipeline-ui" + - SERVICE_MESH_MODE="istio-sidecar" + - WAYPOINT_NAME="waypoint" + - WAYPOINT_NAMESPACE="" + - CREATE_WAYPOINT="false" name: config diff --git a/components/profile-controller/config/manager/manager.yaml b/components/profile-controller/config/manager/manager.yaml index 5c9a4c584..c3b147332 100644 --- a/components/profile-controller/config/manager/manager.yaml +++ b/components/profile-controller/config/manager/manager.yaml @@ -25,6 +25,14 @@ spec: - $(USERID_PREFIX) - "-workload-identity" - $(WORKLOAD_IDENTITY) + - "-service-mesh-mode" + - $(SERVICE_MESH_MODE) + - "-waypoint-name" + - $(WAYPOINT_NAME) + - "-waypoint-namespace" + - $(WAYPOINT_NAMESPACE) + - "-create-waypoint" + - $(CREATE_WAYPOINT) envFrom: - configMapRef: name: config diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/authorizationpolicy.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/authorizationpolicy.yaml new file mode 100644 index 000000000..846f4ea53 --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/authorizationpolicy.yaml @@ -0,0 +1,14 @@ +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: profiles-kfam +spec: + action: ALLOW + rules: + - from: + - source: + principals: + - cluster.local/ns/kubeflow/sa/centraldashboard + selector: + matchLabels: + kustomize.component: profiles diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/httproute.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/httproute.yaml new file mode 100644 index 000000000..be434c78c --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/httproute.yaml @@ -0,0 +1,30 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: profiles-kfam +spec: + parentRefs: + - name: kubeflow-gateway + namespace: istio-system + hostnames: + - "kubeflow.local" + rules: + - matches: + - path: + type: PathPrefix + value: /kfam/ + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + add: + - name: x-forwarded-prefix + value: /kfam + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /kfam/ + backendRefs: + - name: profiles-kfam + namespace: kubeflow + port: 8081 \ No newline at end of file diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/kustomization.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/kustomization.yaml new file mode 100644 index 000000000..c6671f8d1 --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/kustomization.yaml @@ -0,0 +1,33 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: kubeflow +resources: +- ../../base +- service.yaml +- httproute.yaml +- authorizationpolicy.yaml + +commonLabels: + kustomize.component: profiles + +patchesStrategicMerge: +- patches/kfam.yaml +- patches/manager.yaml +- patches/remove-namespace.yaml + +configurations: +- params.yaml + +vars: +- name: PROFILES_NAMESPACE + fieldref: + fieldpath: metadata.namespace + objref: + name: profiles-kfam + kind: Service + apiVersion: v1 + +images: +- name: ghcr.io/kubeflow/kubeflow/kfam + newName: ghcr.io/kubeflow/kubeflow/kfam + newTag: latest \ No newline at end of file diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/params.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/params.yaml new file mode 100644 index 000000000..eea869e0d --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/params.yaml @@ -0,0 +1,3 @@ +varReference: +- path: spec/http/route/destination/host + kind: VirtualService diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/patches/kfam.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/patches/kfam.yaml new file mode 100644 index 000000000..9b17b23f5 --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/patches/kfam.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment +spec: + template: + metadata: + labels: + sidecar.istio.io/inject: "true" + spec: + securityContext: + seccompProfile: + type: RuntimeDefault + containers: + - command: + - /access-management + - "-cluster-admin" + - $(ADMIN) + - "-userid-header" + - $(USERID_HEADER) + - "-userid-prefix" + - $(USERID_PREFIX) + - "-service-mesh-mode" + - $(SERVICE_MESH_MODE) + envFrom: + - configMapRef: + name: config + image: ghcr.io/kubeflow/kubeflow/kfam + imagePullPolicy: IfNotPresent + name: kfam + livenessProbe: + httpGet: + path: /metrics + port: 8081 + initialDelaySeconds: 30 + periodSeconds: 30 + ports: + - containerPort: 8081 + name: kfam-http + protocol: TCP + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + capabilities: + drop: + - ALL + serviceAccountName: controller-service-account diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/patches/manager.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/patches/manager.yaml new file mode 100644 index 000000000..057b12040 --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/patches/manager.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment +spec: + template: + metadata: + labels: + sidecar.istio.io/inject: "false" + spec: + containers: + - name: manager + command: + - /manager + - -userid-header + - $(USERID_HEADER) + - -userid-prefix + - $(USERID_PREFIX) + - -workload-identity + - $(WORKLOAD_IDENTITY) + env: + - name: SERVICE_MESH_MODE + value: istio-ambient \ No newline at end of file diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/patches/remove-namespace.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/patches/remove-namespace.yaml new file mode 100644 index 000000000..4175e4c6d --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/patches/remove-namespace.yaml @@ -0,0 +1,5 @@ +$patch: delete +apiVersion: v1 +kind: Namespace +metadata: + name: system \ No newline at end of file diff --git a/components/profile-controller/config/overlays/kubeflow-ambient/service.yaml b/components/profile-controller/config/overlays/kubeflow-ambient/service.yaml new file mode 100644 index 000000000..5cea0f2b5 --- /dev/null +++ b/components/profile-controller/config/overlays/kubeflow-ambient/service.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Service +metadata: + name: profiles-kfam +spec: + ports: + - port: 8081 \ No newline at end of file diff --git a/components/profile-controller/controllers/profile_controller.go b/components/profile-controller/controllers/profile_controller.go index 8fb5d4cbf..c6b35a66a 100644 --- a/components/profile-controller/controllers/profile_controller.go +++ b/components/profile-controller/controllers/profile_controller.go @@ -46,6 +46,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" + gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) const AUTHZPOLICYISTIO = "ns-owner-access-istio" @@ -91,6 +92,10 @@ type ProfileReconciler struct { UserIdPrefix string WorkloadIdentity string DefaultNamespaceLabelsPath string + ServiceMeshMode string + WaypointName string + WaypointNamespace string + CreateWaypoint bool } // +kubebuilder:rbac:groups=core,resources=namespaces,verbs="*" @@ -127,14 +132,13 @@ func (r *ProfileReconciler) Reconcile(ctx context.Context, request ctrl.Request) ns := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{"owner": instance.Spec.Owner.Name}, - // inject istio sidecar to all pods in target namespace by default. - Labels: map[string]string{ - istioInjectionLabel: "enabled", - }, - Name: instance.Name, + Labels: map[string]string{}, + Name: instance.Name, }, } - setNamespaceLabels(ns, defaultKubeflowNamespaceLabels) + + // Set namespace labels and service mesh labels in one call + r.setNamespaceLabelsAndServiceMesh(ns, instance, defaultKubeflowNamespaceLabels) logger.Info("List of labels to be added to namespace", "labels", ns.Labels) if err := controllerutil.SetControllerReference(instance, ns, r.Scheme); err != nil { IncRequestErrorCounter("error setting ControllerReference", SEVERITY_MAJOR) @@ -178,8 +182,10 @@ func (r *ProfileReconciler) Reconcile(ctx context.Context, request ctrl.Request) for k, v := range foundNs.Labels { oldLabels[k] = v } - setNamespaceLabels(foundNs, defaultKubeflowNamespaceLabels) - logger.Info("List of labels to be added to found namespace", "labels", ns.Labels) + + // Apply namespace labels and service mesh mode labels to existing namespace + r.setNamespaceLabelsAndServiceMesh(foundNs, instance, defaultKubeflowNamespaceLabels) + logger.Info("List of labels to be added to found namespace", "labels", foundNs.Labels) if !reflect.DeepEqual(oldLabels, foundNs.Labels) { err = r.Update(ctx, foundNs) if err != nil { @@ -205,6 +211,23 @@ func (r *ProfileReconciler) Reconcile(ctx context.Context, request ctrl.Request) return reconcile.Result{}, err } + // Create waypoint and L4 AuthorizationPolicy in ambient mode + if r.ServiceMeshMode == "istio-ambient" { + if r.CreateWaypoint { + if err = r.createWaypoint(instance); err != nil { + logger.Error(err, "error creating waypoint", "namespace", instance.Name) + IncRequestErrorCounter("error creating waypoint", SEVERITY_MAJOR) + return reconcile.Result{}, err + } + } + + if err = r.updateL4AuthorizationPolicy(instance); err != nil { + logger.Error(err, "error updating L4 AuthorizationPolicy", "namespace", instance.Name) + IncRequestErrorCounter("error updating L4 AuthorizationPolicy", SEVERITY_MAJOR) + return reconcile.Result{}, err + } + } + // Update service accounts // Create service account "default-editor" in target namespace. // "default-editor" would have kubeflowEdit permission: edit all resources in target namespace except rbac. @@ -416,7 +439,7 @@ func (r *ProfileReconciler) SetupWithManager(mgr ctrl.Manager) error { return nil } -func (r *ProfileReconciler) getAuthorizationPolicy(profileIns *profilev1.Profile) istioSecurity.AuthorizationPolicy { +func (r *ProfileReconciler) getAuthorizationPolicy(profileIns *profilev1.Profile) *istioSecurity.AuthorizationPolicy { nbControllerPrincipal := GetEnvDefault( "NOTEBOOK_CONTROLLER_PRINCIPAL", "cluster.local/ns/kubeflow/sa/notebook-controller-service-account") @@ -429,7 +452,7 @@ func (r *ProfileReconciler) getAuthorizationPolicy(profileIns *profilev1.Profile "KFP_UI_PRINCIPAL", "cluster.local/ns/kubeflow/sa/ml-pipeline-ui") - return istioSecurity.AuthorizationPolicy{ + return &istioSecurity.AuthorizationPolicy{ Action: istioSecurity.AuthorizationPolicy_ALLOW, // Empty selector == match all workloads in namespace Selector: nil, @@ -515,7 +538,7 @@ func (r *ProfileReconciler) updateIstioAuthorizationPolicy(profileIns *profilev1 Name: AUTHZPOLICYISTIO, Namespace: profileIns.Name, }, - Spec: r.getAuthorizationPolicy(profileIns), + Spec: *r.getAuthorizationPolicy(profileIns), } if err := controllerutil.SetControllerReference(profileIns, istioAuth, r.Scheme); err != nil { @@ -751,12 +774,14 @@ func removeString(slice []string, s string) (result []string) { return } -func setNamespaceLabels(ns *corev1.Namespace, newLabels map[string]string) { +// setServiceMeshLabels sets the appropriate service mesh labels based on the mode +func (r *ProfileReconciler) setNamespaceLabelsAndServiceMesh(ns *corev1.Namespace, profileIns *profilev1.Profile, defaultLabels map[string]string) { if ns.Labels == nil { ns.Labels = make(map[string]string) } - for k, v := range newLabels { + // Apply default Kubeflow namespace labels first + for k, v := range defaultLabels { _, ok := ns.Labels[k] if len(v) == 0 { // When there is an empty value, k should be removed. @@ -770,8 +795,32 @@ func setNamespaceLabels(ns *corev1.Namespace, newLabels map[string]string) { } } } + + // Apply service mesh specific labels + if r.ServiceMeshMode == "istio-ambient" { + // In ambient mode, disable sidecar injection but enable ambient mesh + ns.Labels[istioInjectionLabel] = "disabled" + ns.Labels["istio.io/dataplane-mode"] = "ambient" + // Add waypoint labels for ambient mode + waypointNamespace := r.WaypointNamespace + if waypointNamespace == "" { + waypointNamespace = profileIns.Name + } + ns.Labels["istio.io/use-waypoint"] = r.WaypointName + ns.Labels["istio.io/use-waypoint-namespace"] = waypointNamespace + ns.Labels["istio.io/ingress-use-waypoint"] = "true" + } else { + // In sidecar mode (default), inject istio sidecar to all pods in target namespace + ns.Labels[istioInjectionLabel] = "enabled" + // Remove ambient mode labels if they exist + delete(ns.Labels, "istio.io/dataplane-mode") + delete(ns.Labels, "istio.io/use-waypoint") + delete(ns.Labels, "istio.io/use-waypoint-namespace") + delete(ns.Labels, "istio.io/ingress-use-waypoint") + } } + func (r *ProfileReconciler) readDefaultLabelsFromFile(path string) map[string]string { logger := r.Log.WithName("read-config-file").WithValues("path", path) dat, err := ioutil.ReadFile(path) @@ -789,6 +838,135 @@ func (r *ProfileReconciler) readDefaultLabelsFromFile(path string) map[string]st return labels } + +// createWaypoint creates a waypoint proxy in the profile namespace for ambient mode +func (r *ProfileReconciler) createWaypoint(profileIns *profilev1.Profile) error { + logger := r.Log.WithValues("profile", profileIns.Name) + + waypointNamespace := r.WaypointNamespace + if waypointNamespace == "" { + waypointNamespace = profileIns.Name + } + + // Create waypoint using Gateway API with waypoint gateway class + // This creates an Istio waypoint proxy that handles L7 policies in ambient mode + gatewayClassName := "istio-waypoint" + + waypoint := &gatewayv1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.WaypointName, + Namespace: waypointNamespace, + Labels: map[string]string{ + "gateway.istio.io/managed": "Istio", + }, + }, + Spec: gatewayv1beta1.GatewaySpec{ + GatewayClassName: gatewayv1beta1.ObjectName(gatewayClassName), + Listeners: []gatewayv1beta1.Listener{ + { + Name: "mesh", + Port: 15008, + Protocol: "HBONE", + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(profileIns, waypoint, r.Scheme); err != nil { + return err + } + + // Check if the waypoint already exists + foundWaypoint := &gatewayv1beta1.Gateway{} + err := r.Get(context.TODO(), types.NamespacedName{Name: waypoint.Name, Namespace: waypoint.Namespace}, foundWaypoint) + if err != nil { + if apierrors.IsNotFound(err) { + logger.Info("Creating waypoint", "waypoint", waypoint.Name, "namespace", waypoint.Namespace) + err = r.Create(context.TODO(), waypoint) + if err != nil { + return fmt.Errorf("failed to create waypoint: %w", err) + } + } else { + return fmt.Errorf("failed to get waypoint: %w", err) + } + } else { + // Waypoint already exists, check if update is needed + if !reflect.DeepEqual(waypoint.Spec, foundWaypoint.Spec) { + logger.Info("Updating waypoint", "waypoint", waypoint.Name, "namespace", waypoint.Namespace) + foundWaypoint.Spec = waypoint.Spec + err = r.Update(context.TODO(), foundWaypoint) + if err != nil { + return fmt.Errorf("failed to update waypoint: %w", err) + } + } + } + + logger.Info("Waypoint reconciled successfully", "waypoint", r.WaypointName, "namespace", waypointNamespace) + return nil +} + +// updateL4AuthorizationPolicy creates L4 AuthorizationPolicy to allow traffic from waypoint to services +func (r *ProfileReconciler) updateL4AuthorizationPolicy(profileIns *profilev1.Profile) error { + logger := r.Log.WithValues("profile", profileIns.Name) + + waypointNamespace := r.WaypointNamespace + if waypointNamespace == "" { + waypointNamespace = profileIns.Name + } + + waypointPrincipal := fmt.Sprintf("cluster.local/ns/%s/sa/%s", waypointNamespace, r.WaypointName) + + l4Policy := &istioSecurityClient.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "waypoint-l4-access", + Namespace: profileIns.Name, + }, + Spec: istioSecurity.AuthorizationPolicy{ + Action: istioSecurity.AuthorizationPolicy_ALLOW, + Selector: nil, // Match all workloads in namespace + Rules: []*istioSecurity.Rule{ + { + From: []*istioSecurity.Rule_From{ + { + Source: &istioSecurity.Source{ + Principals: []string{waypointPrincipal}, + }, + }, + }, + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(profileIns, l4Policy, r.Scheme); err != nil { + return err + } + + foundL4Policy := &istioSecurityClient.AuthorizationPolicy{} + err := r.Get(context.TODO(), types.NamespacedName{Name: l4Policy.Name, Namespace: l4Policy.Namespace}, foundL4Policy) + if err != nil { + if apierrors.IsNotFound(err) { + logger.Info("Creating L4 AuthorizationPolicy", "namespace", l4Policy.Namespace, "name", l4Policy.Name) + err = r.Create(context.TODO(), l4Policy) + if err != nil { + return err + } + } else { + return err + } + } else { + if !reflect.DeepEqual(*l4Policy.Spec.DeepCopy(), *foundL4Policy.Spec.DeepCopy()) { + foundL4Policy.Spec = *l4Policy.Spec.DeepCopy() + logger.Info("Updating L4 AuthorizationPolicy", "namespace", l4Policy.Namespace, "name", l4Policy.Name) + err = r.Update(context.TODO(), foundL4Policy) + if err != nil { + return err + } + } + } + return nil +} + func GetEnvDefault(variable string, defaultVal string) string { envVar := os.Getenv(variable) if len(envVar) == 0 { diff --git a/components/profile-controller/controllers/profile_controller_test.go b/components/profile-controller/controllers/profile_controller_test.go index f54206d2a..f8d5231fe 100644 --- a/components/profile-controller/controllers/profile_controller_test.go +++ b/components/profile-controller/controllers/profile_controller_test.go @@ -9,6 +9,7 @@ import ( profilev1 "github.com/kubeflow/kubeflow/components/profile-controller/api/v1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" @@ -22,6 +23,25 @@ type namespaceLabelSuite struct { func TestEnforceNamespaceLabelsFromConfig(t *testing.T) { name := "test-namespace" + + // Create a minimal ProfileReconciler for testing + reconciler := &ProfileReconciler{ + ServiceMeshMode: "istio-sidecar", // Test sidecar mode + } + + // Create a minimal profile for testing + profile := &profilev1.Profile{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: profilev1.ProfileSpec{ + Owner: rbacv1.Subject{ + Kind: "User", + Name: "test-user", + }, + }, + } + tests := []namespaceLabelSuite{ namespaceLabelSuite{ corev1.Namespace{ @@ -42,6 +62,7 @@ func TestEnforceNamespaceLabelsFromConfig(t *testing.T) { "serving.kubeflow.org/inferenceservice": "enabled", "pipelines.kubeflow.org/enabled": "true", "app.kubernetes.io/part-of": "kubeflow-profile", + "istio-injection": "enabled", // Added by service mesh logic }, Name: name, }, @@ -68,9 +89,10 @@ func TestEnforceNamespaceLabelsFromConfig(t *testing.T) { Labels: map[string]string{ "user-name": "Jim", "katib.kubeflow.org/metrics-collector-injection": "enabled", - "serving.kubeflow.org/inferenceservice": "disabled", + "serving.kubeflow.org/inferenceservice": "disabled", // Existing label preserved "pipelines.kubeflow.org/enabled": "true", "app.kubernetes.io/part-of": "kubeflow-profile", + "istio-injection": "enabled", // Added by service mesh logic }, Name: name, }, @@ -101,6 +123,8 @@ func TestEnforceNamespaceLabelsFromConfig(t *testing.T) { "serving.kubeflow.org/inferenceservice": "enabled", "pipelines.kubeflow.org/enabled": "true", "app.kubernetes.io/part-of": "kubeflow-profile", + "istio-injection": "enabled", // Added by service mesh logic + // "removal-label" should be removed due to empty value }, Name: name, }, @@ -108,7 +132,7 @@ func TestEnforceNamespaceLabelsFromConfig(t *testing.T) { }, } for _, test := range tests { - setNamespaceLabels(&test.current, test.labels) + reconciler.setNamespaceLabelsAndServiceMesh(&test.current, profile, test.labels) if !reflect.DeepEqual(&test.expected, &test.current) { t.Errorf("Expect:\n%v; Output:\n%v", &test.expected, &test.current) } diff --git a/components/profile-controller/go.mod b/components/profile-controller/go.mod index 83ce93399..08e00baf5 100644 --- a/components/profile-controller/go.mod +++ b/components/profile-controller/go.mod @@ -19,10 +19,11 @@ require ( gopkg.in/yaml.v2 v2.4.0 istio.io/api v0.0.0-20220525153140-e3c48c9ac324 istio.io/client-go v1.13.4 - k8s.io/api v0.24.0 - k8s.io/apimachinery v0.24.0 - k8s.io/client-go v0.24.0 + k8s.io/api v0.24.1 + k8s.io/apimachinery v0.24.1 + k8s.io/client-go v0.24.1 sigs.k8s.io/controller-runtime v0.12.1 + sigs.k8s.io/gateway-api v0.5.1 ) require ( @@ -50,7 +51,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.5 // indirect + github.com/google/go-cmp v0.5.6 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.1.2 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect @@ -89,8 +90,8 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiextensions-apiserver v0.24.0 // indirect - k8s.io/component-base v0.24.0 // indirect + k8s.io/apiextensions-apiserver v0.24.1 // indirect + k8s.io/component-base v0.24.1 // indirect k8s.io/klog/v2 v2.60.1 // indirect k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect diff --git a/components/profile-controller/go.sum b/components/profile-controller/go.sum index 490fd7bd1..79be7dd07 100644 --- a/components/profile-controller/go.sum +++ b/components/profile-controller/go.sum @@ -91,7 +91,6 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -240,8 +239,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -528,7 +528,6 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -980,21 +979,21 @@ istio.io/client-go v1.13.4/go.mod h1:kM3WH/HCojq7BhCD894SZuaAXUKMswT+VQRaEEhTGj0 istio.io/gogo-genproto v0.0.0-20211208193508-5ab4acc9eb1e/go.mod h1:vJDAniIqryf/z///fgZqVPKJ7N2lBk7Gg8DCTB7oCfU= k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg= k8s.io/api v0.23.1/go.mod h1:WfXnOnwSqNtG62Y1CdjoMxh7r7u9QXGCkA1u0na2jgo= -k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= -k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= -k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY= -k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM= +k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= +k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= +k8s.io/apiextensions-apiserver v0.24.1 h1:5yBh9+ueTq/kfnHQZa0MAo6uNcPrtxPMpNQgorBaKS0= +k8s.io/apiextensions-apiserver v0.24.1/go.mod h1:A6MHfaLDGfjOc/We2nM7uewD5Oa/FnEbZ6cD7g2ca4Q= k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFYc= k8s.io/apimachinery v0.23.1/go.mod h1:SADt2Kl8/sttJ62RRsi9MIV4o8f5S3coArm0Iu3fBno= -k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= -k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA= +k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= +k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apiserver v0.24.1/go.mod h1:dQWNMx15S8NqJMp0gpYfssyvhYnkilc1LpExd/dkLh0= k8s.io/client-go v0.23.1/go.mod h1:6QSI8fEuqD4zgFK0xbdwfB/PthBsIxCJMa3s17WlcO0= -k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= -k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.0 h1:h5jieHZQoHrY/lHG+HyrSbJeyfuitheBvqvKwKHVC0g= -k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= +k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E= +k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8= +k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/component-base v0.24.1 h1:APv6W/YmfOWZfo+XJ1mZwep/f7g7Tpwvdbo9CQLDuts= +k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= @@ -1007,7 +1006,6 @@ k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClC k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= @@ -1016,6 +1014,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI= sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0= +sigs.k8s.io/gateway-api v0.5.1 h1:EqzgOKhChzyve9rmeXXbceBYB6xiM50vDfq0kK5qpdw= +sigs.k8s.io/gateway-api v0.5.1/go.mod h1:x0AP6gugkFV8fC/oTlnOMU0pnmuzIR8LfIPRVUjxSqA= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= diff --git a/components/profile-controller/main.go b/components/profile-controller/main.go index 613a410ef..507113c17 100644 --- a/components/profile-controller/main.go +++ b/components/profile-controller/main.go @@ -31,6 +31,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + gwapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" profilev1 "github.com/kubeflow/kubeflow/components/profile-controller/api/v1" kubefloworgv1beta1 "github.com/kubeflow/kubeflow/components/profile-controller/api/v1beta1" @@ -42,6 +43,10 @@ const USERIDHEADER = "userid-header" const USERIDPREFIX = "userid-prefix" const WORKLOADIDENTITY = "workload-identity" const DEFAULTNAMESPACELABELSPATH = "namespace-labels-path" +const SERVICEMESHMODE = "service-mesh-mode" +const WAYPOINTNAME = "waypoint-name" +const WAYPOINTNAMESPACE = "waypoint-namespace" +const CREATEWAYPOINT = "create-waypoint" var ( scheme = runtime.NewScheme() @@ -54,6 +59,7 @@ func init() { utilruntime.Must(profilev1.AddToScheme(scheme)) utilruntime.Must(istioSecurityClient.AddToScheme(scheme)) utilruntime.Must(kubefloworgv1beta1.AddToScheme(scheme)) + utilruntime.Must(gwapiv1beta1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -65,6 +71,10 @@ func main() { var userIdPrefix string var workloadIdentity string var defaultNamespaceLabelsPath string + var serviceMeshMode string + var waypointName string + var waypointNamespace string + var createWaypoint bool flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":9876", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, @@ -76,6 +86,10 @@ func main() { flag.StringVar(&userIdPrefix, USERIDPREFIX, "accounts.google.com:", "Request header user id common prefix") flag.StringVar(&workloadIdentity, WORKLOADIDENTITY, "", "Default identity (GCP service account) for workload_identity plugin") flag.StringVar(&defaultNamespaceLabelsPath, DEFAULTNAMESPACELABELSPATH, "/etc/profile-controller/namespace-labels.yaml", "A YAML file with a map of labels to be set on every Profile namespace") + flag.StringVar(&serviceMeshMode, SERVICEMESHMODE, "istio-sidecar", "Service mesh mode: 'istio-sidecar' or 'istio-ambient' (default: istio-sidecar)") + flag.StringVar(&waypointName, WAYPOINTNAME, "waypoint", "Name of the waypoint proxy to use in ambient mode") + flag.StringVar(&waypointNamespace, WAYPOINTNAMESPACE, "", "Namespace of the waypoint (optional, defaults to profile namespace)") + flag.BoolVar(&createWaypoint, CREATEWAYPOINT, false, "Create waypoint proxy in profile namespace if it doesn't exist") opts := zap.Options{ Development: true, } @@ -104,6 +118,10 @@ func main() { UserIdPrefix: userIdPrefix, WorkloadIdentity: workloadIdentity, DefaultNamespaceLabelsPath: defaultNamespaceLabelsPath, + ServiceMeshMode: serviceMeshMode, + WaypointName: waypointName, + WaypointNamespace: waypointNamespace, + CreateWaypoint: createWaypoint, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Profile") os.Exit(1)