Skip to content

Commit 44120d0

Browse files
authored
Add mounts VW example (#24)
* Add mounts VW example * update gitignore * add index
1 parent e54d737 commit 44120d0

File tree

178 files changed

+20501
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+20501
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hack/tools/*
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
GO_INSTALL = ./hack/go-install.sh
3+
4+
TOOLS_DIR=hack/tools
5+
TOOLS_GOBIN_DIR := $(abspath $(TOOLS_DIR))
6+
GOBIN_DIR=$(abspath ./bin)
7+
PATH := $(GOBIN_DIR):$(TOOLS_GOBIN_DIR):$(PATH)
8+
TMPDIR := $(shell mktemp -d)
9+
KIND_CLUSTER_NAME ?= kind
10+
11+
CONTROLLER_GEN_VER := v0.16.1
12+
CONTROLLER_GEN_BIN := controller-gen
13+
CONTROLLER_GEN := $(TOOLS_DIR)/$(CONTROLLER_GEN_BIN)-$(CONTROLLER_GEN_VER)
14+
export CONTROLLER_GEN # so hack scripts can use it
15+
16+
17+
CODE_GENERATOR_VER := v2.1.0
18+
CODE_GENERATOR_BIN := code-generator
19+
CODE_GENERATOR := $(TOOLS_GOBIN_DIR)/$(CODE_GENERATOR_BIN)-$(CODE_GENERATOR_VER)
20+
export CODE_GENERATOR # so hack scripts can use it
21+
22+
KCP_APIGEN_VER := v0.26.0
23+
KCP_APIGEN_BIN := apigen
24+
KCP_APIGEN_GEN := $(TOOLS_DIR)/$(KCP_APIGEN_BIN)-$(KCP_APIGEN_VER)
25+
export KCP_APIGEN_GEN # so hack scripts can use it
26+
27+
OPENSHIFT_GOIMPORTS_VER := c72f1dc2e3aacfa00aece3391d938c9bc734e791
28+
OPENSHIFT_GOIMPORTS_BIN := openshift-goimports
29+
OPENSHIFT_GOIMPORTS := $(TOOLS_DIR)/$(OPENSHIFT_GOIMPORTS_BIN)-$(OPENSHIFT_GOIMPORTS_VER)
30+
export OPENSHIFT_GOIMPORTS # so hack scripts can use it
31+
32+
VERSION ?= $(shell git describe --tags --always --dirty)
33+
34+
LDFLAGS= -s -w \
35+
-extldflags '-static'
36+
37+
all: build
38+
.PHONY: all
39+
40+
ldflags:
41+
@echo $(LDFLAGS)
42+
43+
tools: $(CONTROLLER_GEN) $(KCP_APIGEN_GEN) $ $(CODE_GENERATOR) $(OPENSHIFT_GOIMPORTS) ## Install tools
44+
.PHONY: tools
45+
46+
$(CONTROLLER_GEN):
47+
GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) sigs.k8s.io/controller-tools/cmd/controller-gen $(CONTROLLER_GEN_BIN) $(CONTROLLER_GEN_VER)
48+
49+
$(CODE_GENERATOR):
50+
GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/kcp-dev/code-generator/v2 $(CODE_GENERATOR_BIN) $(CODE_GENERATOR_VER)
51+
52+
$(KCP_APIGEN_GEN):
53+
GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/kcp-dev/kcp/sdk/cmd/apigen $(KCP_APIGEN_BIN) $(KCP_APIGEN_VER)
54+
55+
$(OPENSHIFT_GOIMPORTS):
56+
GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/openshift-eng/openshift-goimports $(OPENSHIFT_GOIMPORTS_BIN) $(OPENSHIFT_GOIMPORTS_VER)
57+
58+
.PHONY: require-%
59+
require-%:
60+
@if ! command -v $* 1> /dev/null 2>&1; then echo "$* not found in ${PATH}"; exit 1; fi
61+
62+
.PHONY: verify-go-versions
63+
verify-go-versions: ## Verify go versions
64+
hack/verify-go-versions.sh
65+
66+
build: WHAT ?= ./cmd/...
67+
build: require-jq require-go require-git verify-go-versions ## Build the project
68+
GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build $(BUILDFLAGS) -ldflags="$(LDFLAGS)" -o bin $(WHAT)
69+
.PHONY: build
70+
71+
crds: $(CONTROLLER_GEN) $(YAML_PATCH) ## Generate crds
72+
./hack/update-codegen-crds.sh
73+
.PHONY: crds
74+
75+
codegen: crds $(CODE_GENERATOR) ## Generate all
76+
go mod download
77+
./hack/update-codegen-clients.sh
78+
$(MAKE) imports
79+
80+
.PHONY: imports
81+
imports: $(OPENSHIFT_GOIMPORTS) verify-go-versions
82+
$(OPENSHIFT_GOIMPORTS) -m github.com/kcp-dev/contrib/mounts-virtualworkspace
83+
84+
test:
85+
go test ./...
86+
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Remote mounts virtual workspace example
2+
3+
This is an example of how to use the mounts feature in kcp to mount a target cluster into a workspace.
4+
Mount happens at front-proxy level via reverse proxy. You need to implement your own VirtualWorkspace to handle this.
5+
and this example shows how to do it.
6+
7+
## This is example codebase, and should be used only as example.
8+
9+
# Step by step guide
10+
11+
Step by step guide how to setup this example.
12+
13+
1. Start kcp with mounts feature gate enabled:
14+
15+
```
16+
go run ./cmd/kcp start --miniproxy-mapping-file=../contrib/20241013-kubecon-saltlakecity/mounts-vw/assets/path-mapping.yaml --feature-gates=WorkspaceMounts=true
17+
```
18+
19+
2. Setup all required workspaces and exports for virtual workspace to run:
20+
21+
Provider workspace where all the target cluster will be defined with secrets.
22+
These clusters can be mounted later on by the any workspace.
23+
24+
Setup providers:
25+
26+
```
27+
# Set kcp KUBECONFIG
28+
export KUBECONFIG=../../../kcp/.kcp/admin.kubeconfig
29+
30+
kubectl ws use :root
31+
# create provider workspaces
32+
kubectl ws create providers --enter
33+
kubectl ws create mounts --enter
34+
35+
# create exports
36+
kubectl create -f config/mounts/resources/apiresourceschema-targetkubeclusters.targets.contrib.kcp.io.yaml
37+
kubectl create -f config/mounts/resources/apiresourceschema-kubeclusters.mounts.contrib.kcp.io.yaml
38+
kubectl create -f config/mounts/resources/apiresourceschema-targetvclusters.targets.contrib.kcp.io.yaml
39+
kubectl create -f config/mounts/resources/apiresourceschema-vclusters.mounts.contrib.kcp.io.yaml
40+
kubectl create -f config/mounts/resources/apiexport-mounts.contrib.kcp.io.yaml
41+
kubectl create -f config/mounts/resources/apiexport-targets.contrib.kcp.io.yaml
42+
43+
```
44+
45+
3. Start virtual workspace process:
46+
```
47+
go run ./cmd/virtual-workspaces/ start \
48+
--kubeconfig=../../../kcp/.kcp/admin.kubeconfig \
49+
--tls-cert-file=../../../kcp/.kcp/apiserver.crt \
50+
--tls-private-key-file=../../../kcp/.kcp/apiserver.key \
51+
--authentication-kubeconfig=../../../kcp/.kcp/admin.kubeconfig \
52+
--virtual-workspaces-proxy-hostname=https://localhost:6444 \
53+
-v=8
54+
```
55+
56+
4. Continue bootstrapping the mounts example:
57+
58+
```
59+
# create operators namespace where platforms operators will create objects. This could be many of them.
60+
# for this example we will use only one.
61+
62+
kubectl ws use :root
63+
kubectl ws create operators --enter
64+
kubectl ws create mounts --enter
65+
66+
# bind the exports
67+
kubectl kcp bind apiexport root:providers:mounts:targets.contrib.kcp.io --accept-permission-claim secrets.core
68+
69+
# Create a target cluster to `kind` cluster locally:
70+
71+
# create kind cluster if not already created
72+
kind create cluster --name kind --kubeconfig kind.kubeconfig
73+
74+
#create secret with kubeconfig:
75+
kubectl ws use :root:operators:mounts
76+
kubectl create secret generic kind-kubeconfig --from-file=kubeconfig=kind.kubeconfig
77+
78+
# create target cluster:
79+
kubectl create -f config/mounts/resources/example-target-cluster.yaml
80+
81+
# create vcluster target:
82+
kubectl create -f config/mounts/resources/example-target-vcluster.yaml
83+
84+
# get secret string:
85+
kubectl get TargetKubeCluster proxy-cluster -o jsonpath='{.status.secretString}'
86+
kTPlAYLMjKJDRly5
87+
88+
Nis8xbLPoqPUrapA%
89+
90+
kubectl get TargetVCluster proxy-cluster -o jsonpath='{.status.secretString}'
91+
Nis8xbLPoqPUrapA
92+
93+
# Create a consumer workspace for mounts:
94+
kubectl ws use :root
95+
kubectl ws create consumer --enter
96+
97+
# This is not yet available in CLI
98+
kubectlcreate -f config/mounts/resources/example-workspace-kind-cluster-mounted.yaml
99+
100+
kubectl kcp bind apiexport root:providers:mounts:mounts.contrib.kcp.io
101+
102+
# !!!!! replace secrets string first in the file bellow :
103+
kubectl create -f config/mounts/resources/example-mount-cluster.yaml
104+
```
105+
106+
5. Check the mounts reconciler logs:
107+
Now workspace should be backed by mountpoint from front-proxy:
108+
109+
```
110+
kubectl ws use kind-cluster
111+
k get pods -A
112+
NAMESPACE NAME READY STATUS RESTARTS AGE
113+
kube-system coredns-7db6d8ff4d-4l625 1/1 Running 0 22h
114+
kube-system coredns-7db6d8ff4d-ntf95 1/1 Running 0 22h
115+
kube-system etcd-kind-control-plane 1/1 Running 0 22h
116+
kube-system kindnet-vv872 1/1 Running 0 22h
117+
kube-system kube-apiserver-kind-control-plane 1/1 Running 0 22h
118+
kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 22h
119+
kube-system kube-proxy-lkv29 1/1 Running 0 22h
120+
kube-system kube-scheduler-kind-control-plane 1/1 Running 0 22h
121+
local-path-storage local-path-provisioner-988d74bc-dqnd7 1/1 Running 0 22h
122+
```
123+
124+
# Vclusters example
125+
126+
vCluster are backed by vCluster mounts. This is a way to create a virtual cluster that is backed by a real cluster.
127+
You can either provide a kubeconfig or a target cluster to back the vCluster or secretString for "target" in the system.
128+
129+
kubectl create -f config/mounts/resources/example-workspace-vcluster-mounted.yaml
130+
131+
kubectl create -f config/mounts/resources/example-mount-vcluster.yaml
132+
133+
# Known issues
134+
135+
1. `TargetKubeCluster` changes do not propagate to `KubeCluster` need to wire them up.
136+
Challenge is that when these 2 objects are in separate bindings, its more machinery to make them work together.
137+
138+
2. VirtualWorkspace is not yet fully shards aware. Ideally it should be 1 per each shard, and handle only its
139+
own workspaces.
140+
141+
3. KubeCluster changes not applied to Workspaces. This might be a bug in core. Need to validate.
142+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
reviewers:
2+
- mjudeikis
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright 2023 The KCP Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package mounts
18+
19+
const (
20+
GroupName = "mounts.contrib.kcp.io"
21+
KubeClusterKind = "KubeCluster"
22+
VClusterKind = "VCluster"
23+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
Copyright 2024 The KCP Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// +k8s:deepcopy-gen=package,register
18+
// +groupName=mounts.contrib.kcp.io
19+
// +k8s:openapi-gen=true
20+
package v1alpha1
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
Copyright 2023 The KCP Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/apimachinery/pkg/runtime"
22+
"k8s.io/apimachinery/pkg/runtime/schema"
23+
24+
"github.com/kcp-dev/contrib/mounts-virtualworkspace/apis/mounts"
25+
)
26+
27+
// SchemeGroupVersion is group version used to register these objects.
28+
var SchemeGroupVersion = schema.GroupVersion{Group: mounts.GroupName, Version: "v1alpha1"}
29+
30+
// Kind takes an unqualified kind and returns back a Group qualified GroupKind.
31+
func Kind(kind string) schema.GroupKind {
32+
return SchemeGroupVersion.WithKind(kind).GroupKind()
33+
}
34+
35+
// Resource takes an unqualified resource and returns a Group qualified GroupResource.
36+
func Resource(resource string) schema.GroupResource {
37+
return SchemeGroupVersion.WithResource(resource).GroupResource()
38+
}
39+
40+
var (
41+
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
42+
AddToScheme = SchemeBuilder.AddToScheme
43+
)
44+
45+
// Adds the list of known types to Scheme.
46+
func addKnownTypes(scheme *runtime.Scheme) error {
47+
scheme.AddKnownTypes(SchemeGroupVersion,
48+
&KubeCluster{},
49+
&KubeClusterList{},
50+
&VCluster{},
51+
&VClusterList{},
52+
)
53+
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
54+
return nil
55+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package v1alpha1
2+
3+
const (
4+
5+
// InternalWorkspaceProxyKeyLabel is an internal label set on a WorkspaceProxy resource that contains the full hash of the WorkspaceProxyKey, generated with the ToProxyTargetKey(..)
6+
// helper func, this label is used for reverse lookups of workspaceProxyKey to WorkspaceProxy.
7+
InternalWorkspaceProxyKeyLabel = "internal.mounts.contrib.kcp.io/key"
8+
)

0 commit comments

Comments
 (0)