Skip to content

Commit 3c1de72

Browse files
authored
feat: add istio virtualservice reconciliation to controller (#500)
* setup virtualservice to route traffic for workspaces - Update the helper func with CopyDeepVirtualService - set istio env var as config across controller - make controller manifest consistent with frontend/backend - fix the configmap name in manager_istio_patch.yaml Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * add e2e test to verify workspace connection Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * fixed controller config with istio component Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * restructure the virtual service httproute configuration Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * Remove the extend e2e test of portforward gateway Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * remove the reference of istio overlays Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * set service name with available service for e2e test Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> * Fix the naming convention and e2e changes Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com> --------- Signed-off-by: Harshad Reddy Nalla <hnalla@redhat.com>
1 parent 07ee02f commit 3c1de72

File tree

19 files changed

+492
-61
lines changed

19 files changed

+492
-61
lines changed

workspaces/backend/internal/models/workspaces/funcs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ func buildServices(ws *kubefloworgv1beta1.Workspace, wskPodTemplatePorts map[kub
359359
case kubefloworgv1beta1.ImagePortProtocolHTTP:
360360
services[i].HttpService = &HttpService{
361361
DisplayName: ptr.Deref(port.DisplayName, wskPort.DefaultDisplayName),
362-
HttpPath: fmt.Sprintf("/workspace/%s/%s/%s/", ws.Namespace, ws.Name, port.Id),
362+
HttpPath: fmt.Sprintf("/workspace/connect/%s/%s/%s/", ws.Namespace, ws.Name, port.Id),
363363
}
364364
}
365365
}

workspaces/controller/api/v1beta1/workspacekind_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ type WorkspaceKindVolumeMounts struct {
279279

280280
type HTTPProxy struct {
281281
// if the path prefix is stripped from incoming HTTP requests
282-
// - if true, the '/workspace/{profile_name}/{workspace_name}/' path prefix
282+
// - if true, the '/workspace/connect/{profile_name}/{workspace_name}/' path prefix
283283
// is stripped from incoming requests, the application sees the request
284284
// as if it was made to '/...'
285285
// - this only works if the application serves RELATIVE URLs for its assets
@@ -291,7 +291,7 @@ type HTTPProxy struct {
291291
// - sets the `spec.http[].headers.request` of the Istio VirtualService
292292
// https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers-HeaderOperations
293293
// - the following string templates are available:
294-
// - `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/{profile_name}/{workspace_name}/')
294+
// - `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/connect/{profile_name}/{workspace_name}/')
295295
// +kubebuilder:validation:Optional
296296
RequestHeaders *IstioHeaderOperations `json:"requestHeaders,omitempty"`
297297
}

workspaces/controller/cmd/main.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ import (
2020
"crypto/tls"
2121
"flag"
2222
"os"
23+
"strconv"
2324

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

29+
istiov1 "istio.io/client-go/pkg/apis/networking/v1"
2830
"k8s.io/apimachinery/pkg/runtime"
2931
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3032
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -36,6 +38,7 @@ import (
3638
"sigs.k8s.io/controller-runtime/pkg/webhook"
3739

3840
kubefloworgv1beta1 "github.com/kubeflow/notebooks/workspaces/controller/api/v1beta1"
41+
"github.com/kubeflow/notebooks/workspaces/controller/internal/config"
3942
controllerInternal "github.com/kubeflow/notebooks/workspaces/controller/internal/controller"
4043
"github.com/kubeflow/notebooks/workspaces/controller/internal/helper"
4144
webhookInternal "github.com/kubeflow/notebooks/workspaces/controller/internal/webhook"
@@ -50,6 +53,8 @@ var (
5053
func init() {
5154
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
5255

56+
utilruntime.Must(istiov1.AddToScheme(scheme))
57+
5358
utilruntime.Must(kubefloworgv1beta1.AddToScheme(scheme))
5459
// +kubebuilder:scaffold:scheme
5560
}
@@ -60,6 +65,10 @@ func main() {
6065
var probeAddr string
6166
var secureMetrics bool
6267
var enableHTTP2 bool
68+
69+
// Define command line flags
70+
cfg := &config.EnvConfig{}
71+
6372
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
6473
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
6574
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
@@ -69,6 +78,15 @@ func main() {
6978
"If set the metrics endpoint is served securely")
7079
flag.BoolVar(&enableHTTP2, "enable-http2", false,
7180
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
81+
flag.StringVar(&cfg.IstioGateway, "istio-gateway", getEnvAsStr("ISTIO_GATEWAY", ""),
82+
"The name of the Istio gateway to use")
83+
flag.StringVar(&cfg.IstioHosts, "istio-hosts", getEnvAsStr("ISTIO_HOSTS", "*"),
84+
"The hosts to use for the Istio VirtualService")
85+
flag.StringVar(&cfg.ClusterDomain, "cluster-domain", getEnvAsStr("CLUSTER_DOMAIN", "cluster.local"),
86+
"The domain to use for the Istio VirtualService")
87+
flag.BoolVar(&cfg.UseIstio, "use-istio", getEnvAsBool("USE_ISTIO", false),
88+
"If set, Istio will be used")
89+
7290
opts := zap.Options{
7391
Development: true,
7492
}
@@ -129,14 +147,15 @@ func main() {
129147

130148
// setup field indexers on the manager cache. we use these indexes to efficiently
131149
// query the cache for things like which Workspaces are using a particular WorkspaceKind
132-
if err := helper.SetupManagerFieldIndexers(mgr); err != nil {
150+
if err := helper.SetupManagerFieldIndexers(mgr, cfg); err != nil {
133151
setupLog.Error(err, "unable to setup field indexers")
134152
os.Exit(1)
135153
}
136154

137155
if err = (&controllerInternal.WorkspaceReconciler{
138156
Client: mgr.GetClient(),
139157
Scheme: mgr.GetScheme(),
158+
Config: cfg,
140159
}).SetupWithManager(mgr, controller.Options{
141160
RateLimiter: helper.BuildRateLimiter(),
142161
}); err != nil {
@@ -188,3 +207,19 @@ func main() {
188207
os.Exit(1)
189208
}
190209
}
210+
211+
func getEnvAsStr(name string, defaultVal string) string {
212+
if value, exists := os.LookupEnv(name); exists {
213+
return value
214+
}
215+
return defaultVal
216+
}
217+
218+
func getEnvAsBool(name string, defaultVal bool) bool {
219+
if value, exists := os.LookupEnv(name); exists {
220+
if boolValue, err := strconv.ParseBool(value); err == nil {
221+
return boolValue
222+
}
223+
}
224+
return defaultVal
225+
}

workspaces/controller/config/crd/bases/kubeflow.org_workspacekinds.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3699,7 +3699,7 @@ spec:
36993699
default: false
37003700
description: |-
37013701
if the path prefix is stripped from incoming HTTP requests
3702-
- if true, the '/workspace/{profile_name}/{workspace_name}/' path prefix
3702+
- if true, the '/workspace/connect/{profile_name}/{workspace_name}/' path prefix
37033703
is stripped from incoming requests, the application sees the request
37043704
as if it was made to '/...'
37053705
- this only works if the application serves RELATIVE URLs for its assets
@@ -3710,7 +3710,7 @@ spec:
37103710
- sets the `spec.http[].headers.request` of the Istio VirtualService
37113711
https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers-HeaderOperations
37123712
- the following string templates are available:
3713-
- `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/{profile_name}/{workspace_name}/')
3713+
- `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/connect/{profile_name}/{workspace_name}/')
37143714
properties:
37153715
add:
37163716
additionalProperties:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: kustomize.config.k8s.io/v1alpha1
2+
kind: Component
3+
4+
configMapGenerator:
5+
- envs:
6+
- params.env
7+
name: kubeflow-workspaces-istio-config
8+
9+
patches:
10+
- path: manager_istio_patch.yaml
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: workspaces-controller
5+
spec:
6+
template:
7+
spec:
8+
containers:
9+
- name: manager
10+
env:
11+
- name: USE_ISTIO
12+
valueFrom:
13+
configMapKeyRef:
14+
name: kubeflow-workspaces-istio-config
15+
key: USE_ISTIO
16+
- name: ISTIO_GATEWAY
17+
valueFrom:
18+
configMapKeyRef:
19+
name: kubeflow-workspaces-istio-config
20+
key: ISTIO_GATEWAY
21+
- name: ISTIO_HOST
22+
valueFrom:
23+
configMapKeyRef:
24+
name: kubeflow-workspaces-istio-config
25+
key: ISTIO_HOST
26+
- name: CLUSTER_DOMAIN
27+
valueFrom:
28+
configMapKeyRef:
29+
name: kubeflow-workspaces-istio-config
30+
key: CLUSTER_DOMAIN
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
USE_ISTIO=true
2+
ISTIO_GATEWAY=kubeflow/kubeflow-gateway
3+
ISTIO_HOST=*
4+
CLUSTER_DOMAIN=cluster.local

workspaces/controller/config/default/kustomization.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ resources:
1515

1616
components:
1717
- components/common
18+
- components/istio
1819

1920
patches:
2021
# [METRICS] The following patch will enable the metrics endpoint. Ensure that you also protect this endpoint.

workspaces/controller/config/samples/jupyterlab_v1beta1_workspacekind.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ spec:
153153
httpProxy:
154154

155155
## if the path prefix is stripped from incoming HTTP requests
156-
## - if true, the '/workspace/{profile_name}/{workspace_name}/' path prefix
156+
## - if true, the '/workspace/connect/{profile_name}/{workspace_name}/' path prefix
157157
## is stripped from incoming requests, the application sees the request
158158
## as if it was made to '/...'
159159
## - this only works if the application serves RELATIVE URLs for its assets
@@ -164,7 +164,7 @@ spec:
164164
## - sets the `spec.http[].headers.request` of the Istio VirtualService
165165
## https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers-HeaderOperations
166166
## - the following string templates are available:
167-
## - `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/{profile_name}/{workspace_name}/')
167+
## - `.PathPrefix`: the path prefix of the Workspace (e.g. '/workspace/connect/{profile_name}/{workspace_name}/')
168168
##
169169
requestHeaders: {}
170170
#set: { "X-RStudio-Root-Path": "{{ .PathPrefix }}" } # for RStudio

workspaces/controller/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ require (
77
github.com/onsi/ginkgo/v2 v2.19.0
88
github.com/onsi/gomega v1.33.1
99
golang.org/x/time v0.3.0
10+
istio.io/api v1.22.8
11+
istio.io/client-go v1.22.8
1012
k8s.io/api v0.31.0
1113
k8s.io/apimachinery v0.31.0
1214
k8s.io/client-go v0.31.0
@@ -59,6 +61,7 @@ require (
5961
golang.org/x/text v0.16.0 // indirect
6062
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
6163
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
64+
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
6265
google.golang.org/protobuf v1.34.2 // indirect
6366
gopkg.in/inf.v0 v0.9.1 // indirect
6467
gopkg.in/yaml.v2 v2.4.0 // indirect

0 commit comments

Comments
 (0)