Skip to content
This repository was archived by the owner on Oct 28, 2024. It is now read-only.

Commit 6f1e5b0

Browse files
authored
Merge pull request #53 from Fei-Guo/master
Move virtualcluster directory from WG repo to CAPN
2 parents e9cd910 + dbcdf7c commit 6f1e5b0

File tree

369 files changed

+61755
-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.

369 files changed

+61755
-0
lines changed

virtualcluster/.gitignore

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
# Binaries for programs and plugins
3+
*.exe
4+
*.exe~
5+
*.dll
6+
*.so
7+
*.dylib
8+
_output
9+
coverage
10+
11+
# Test binary, build with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Kubernetes Generated files - skip generated files, except for vendored files
18+
19+
vendor/
20+
21+
# editor and IDE paraphernalia
22+
.idea
23+
*.swp
24+
*.swo
25+
*~

virtualcluster/Dockerfile

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Build the manager binary
2+
FROM golang:1.12 as builder
3+
4+
ENV GO111MODULE=on
5+
6+
WORKDIR /go/virtualcluster
7+
8+
COPY go.mod .
9+
COPY go.sum .
10+
11+
RUN go mod download
12+
13+
COPY pkg/ pkg/
14+
COPY cmd/ cmd/
15+
16+
# Build
17+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager sigs.k8s.io/cluster-api-provider-nested/virtualcluster/cmd/manager
18+
19+
# Copy the controller-manager into a thin image
20+
FROM ubuntu:latest
21+
WORKDIR /
22+
COPY --from=builder /go/virtualcluster/manager .
23+
ENTRYPOINT ["/manager"]

virtualcluster/Makefile

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Explicitly opt into go modules, even though we're inside a GOPATH directory
2+
export GO111MODULE=on
3+
4+
# Image URL to use all building/pushing image targets
5+
DOCKER_REG ?= ${or ${VC_DOCKER_REGISTRY},"virtualcluster"}
6+
IMG ?= ${DOCKER_REG}/manager-amd64 ${DOCKER_REG}/vn-agent-amd64 ${DOCKER_REG}/syncer-amd64
7+
8+
# TEST_FLAGS used as flags of go test.
9+
TEST_FLAGS ?= -v --race
10+
11+
# COVERAGE_PACKAGES is the coverage we care about.
12+
COVERAGE_PACKAGES=$(shell go list ./... | \
13+
grep -v sigs.k8s.io/cluster-api-provider-nested/virtualcluster/pkg/client | \
14+
grep -v sigs.k8s.io/cluster-api-provider-nested/virtualcluster/pkg/apis | \
15+
grep -v sigs.k8s.io/cluster-api-provider-nested/virtualcluster/cmd | \
16+
grep -v sigs.k8s.io/cluster-api-provider-nested/virtualcluster/test/e2e)
17+
18+
# CRD_OPTIONS ?= "crd:trivialVersions=true"
19+
CRD_OPTIONS ?= "crd:trivialVersions=true,maxDescLen=0"
20+
21+
# Build code.
22+
#
23+
# Args:
24+
# WHAT: Directory names to build. If any of these directories has a 'main'
25+
# package, the build will produce executable files under $(OUT_DIR).
26+
# If not specified, "everything" will be built.
27+
# GOFLAGS: Extra flags to pass to 'go' when building.
28+
# GOLDFLAGS: Extra linking flags passed to 'go' when building.
29+
# GOGCFLAGS: Additional go compile flags passed to 'go' when building.
30+
#
31+
# Example:
32+
# make
33+
# make all
34+
# make all WHAT=cmd/kubelet GOFLAGS=-v
35+
# make all GOLDFLAGS=""
36+
# Note: Specify GOLDFLAGS as an empty string for building unstripped binaries, which allows
37+
# you to use code debugging tools like delve. When GOLDFLAGS is unspecified, it defaults
38+
# to "-s -w" which strips debug information. Other flags that can be used for GOLDFLAGS
39+
# are documented at https://golang.org/cmd/link/
40+
.PHONY: all
41+
all: test build
42+
43+
build:
44+
hack/make-rules/build.sh $(WHAT)
45+
46+
# Run tests
47+
.PHONY: test
48+
PWD = $(CURDIR)
49+
test: generate fmt vet manifests
50+
@mkdir -p coverage
51+
@( for pkg in ${COVERAGE_PACKAGES}; do \
52+
go test ${TEST_FLAGS} \
53+
-coverprofile=coverage/unit-test-`echo $$pkg | tr "/" "_"`.out \
54+
$$pkg || exit 1 ;\
55+
done )
56+
@( cd ./pkg/vn-agent/server/test; \
57+
go test ${TEST_FLAGS} \
58+
-coverprofile=${PWD}/coverage/unit-test-pkg_vn-agent_server_test.out )
59+
@cd ${PWD}
60+
61+
.PHONY: coverage
62+
coverage: ## combine coverage after test
63+
@mkdir -p coverage
64+
@gocovmerge coverage/* > coverage/coverage.txt
65+
@go tool cover -html=coverage/coverage.txt -o coverage/coverage.html
66+
67+
.PHONY: clean
68+
clean: ## clean to remove bin/* and files created by module
69+
@go mod tidy
70+
@rm -rf _output/*
71+
@rm -rf coverage/*
72+
73+
# Run against the configured Kubernetes cluster in ~/.kube/config
74+
run: generate fmt vet
75+
go run ./cmd/manager/main.go
76+
77+
# Install CRDs into a cluster
78+
install: manifests
79+
kubectl apply -f config/crds
80+
81+
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
82+
deploy: manifests
83+
kubectl apply -f config/crds
84+
kustomize build config/default | kubectl apply -f -
85+
86+
# Generate manifests e.g. CRD, RBAC etc.
87+
manifests: controller-gen
88+
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role paths="./..." output:crd:artifacts:config=config/crds
89+
hack/make-rules/replace-null.sh
90+
# To work around a known controller gen issue
91+
# https://github.com/kubernetes-sigs/kubebuilder/issues/1544
92+
ifeq (, $(shell which yq))
93+
@echo "Please install yq for yaml patching. Get it from here: https://github.com/mikefarah/yq"
94+
@exit
95+
else
96+
@{ \
97+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.apiServer.properties.statefulset.properties.spec.properties.template.properties.spec.properties.containers.items.properties.ports.items.required[1]" protocol;\
98+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.controllerManager.properties.statefulset.properties.spec.properties.template.properties.spec.properties.containers.items.properties.ports.items.required[1]" protocol;\
99+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.etcd.properties.statefulset.properties.spec.properties.template.properties.spec.properties.containers.items.properties.ports.items.required[1]" protocol;\
100+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.apiServer.properties.statefulset.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.ports.items.required[1]" protocol;\
101+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.controllerManager.properties.statefulset.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.ports.items.required[1]" protocol;\
102+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.etcd.properties.statefulset.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.ports.items.required[1]" protocol;\
103+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.apiServer.properties.service.properties.spec.properties.ports.items.required[1]" protocol;\
104+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.controllerManager.properties.service.properties.spec.properties.ports.items.required[1]" protocol;\
105+
yq w -i config/crds/tenancy.x-k8s.io_clusterversions.yaml "spec.validation.openAPIV3Schema.properties.spec.properties.etcd.properties.service.properties.spec.properties.ports.items.required[1]" protocol;\
106+
}
107+
endif
108+
109+
# Run go fmt against code
110+
fmt:
111+
go fmt ./pkg/... ./cmd/...
112+
113+
# Run go vet against code
114+
vet:
115+
go vet ./pkg/... ./cmd/...
116+
117+
# Generate code
118+
generate: controller-gen
119+
ifndef GOPATH
120+
$(error GOPATH not defined, please define GOPATH. Run "go help gopath" to learn more about GOPATH)
121+
endif
122+
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
123+
124+
# Build release image.
125+
#
126+
# 1. run tests
127+
# 2. build docker image
128+
.PHONY: release-images
129+
release-images: test build-images
130+
131+
# Build docker image.
132+
#
133+
# 1. build all binaries.
134+
# 2. copy binaries to the corresponding docker image.
135+
build-images:
136+
hack/make-rules/release-images.sh $(WHAT)
137+
138+
# Push the docker image
139+
docker-push:
140+
$(foreach i,$(IMG),docker push $i;)
141+
142+
# find or download controller-gen
143+
# download controller-gen if necessary
144+
controller-gen:
145+
ifeq (, $(shell which controller-gen))
146+
@{ \
147+
set -e ;\
148+
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
149+
cd $$CONTROLLER_GEN_TMP_DIR ;\
150+
go mod init tmp ;\
151+
go get sigs.k8s.io/controller-tools/cmd/[email protected] ;\
152+
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
153+
}
154+
CONTROLLER_GEN=$(GOPATH)/bin/controller-gen
155+
else
156+
CONTROLLER_GEN=$(shell which controller-gen)
157+
endif
158+
159+
# Build and run kubernetes e2e tests.
160+
#
161+
# Args:
162+
# KUBECONFIG: kubeconfig to virtual cluster. If empty, create a virtual cluster.
163+
# Defaults to "".
164+
# FOCUS: Regexp that matches the tests to be run. Defaults to "\[Conformance\]".
165+
# SKIP: Regexp that matches the tests that needs to be skipped.
166+
# Defaults to "\[Flaky\]|\[Slow\]|\[Serial\]"
167+
# BUILD_DEPENDENCIES: if true, build dependencies related to e2e test.
168+
# Defaults to true.
169+
#
170+
# Example:
171+
# make test-e2e-k8s KUBECONFIG=/path/to/vc-kubeconfig
172+
.PHONY: test-e2e-k8s
173+
test-e2e-k8s:
174+
hack/make-rules/test-e2e-k8s.sh

virtualcluster/OWNERS

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md
2+
3+
approvers:
4+
- adohe
5+
- Fei-Guo
6+
- resouer
7+
- tashimi
8+
- zhuangqh
9+
10+
reviewers:
11+
- adohe
12+
- christopherhein
13+
- Fei-Guo
14+
- resouer
15+
- zhuangqh

virtualcluster/PROJECT

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
version: "1"
2+
domain: x-k8s.io
3+
projectName: virtualcluster
4+
repo: sigs.k8s.io/cluster-api-provider-nested/virtualcluster

virtualcluster/README.md

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# VirtualCluster - Enabling Kubernetes Hard Multi-tenancy
2+
3+
VirtualCluster represents a new architecture to address various Kubernetes control plane isolation challenges.
4+
It extends existing namespace based Kubernetes multi-tenancy model by providing each tenant a cluster view.
5+
VirtualCluster completely leverages Kubernetes extendability and preserves full API compatibility.
6+
That being said, the core Kubernetes components are not modified in virtual cluster.
7+
8+
With VirtualCluster, each tenant is assigned a dedicated tenant control plane, which is a upstream Kubernetes distribution.
9+
Tenants can create cluster scope resources such as namespaces and CRDs in the tenant control plane without affecting others.
10+
As a result, most of the isolation problems due to sharing one apiserver disappear.
11+
The Kubernetes cluster that manages the actual physical nodes is called a super cluster, which now
12+
becomes a Pod resource provider. VirtualCluster is composed of the following components:
13+
14+
- **vc-manager**: A new CRD [VirtualCluster](pkg/apis/tenancy/v1alpha1/virtualcluster_types.go) is introduced
15+
to model the tenant control plane. `vc-manager` manages the lifecycle of each `VirtualCluster` custom resource.
16+
Based on the specification, it either creates CAPN control plane Pods in local K8s cluster,
17+
or imports an existing cluster if a valid `kubeconfig` is provided.
18+
19+
- **syncer**: A centralized controller that populates API objects needed for Pod provisioning from every tenant control plane
20+
to the super cluster, and bidirectionally syncs the object statuses. It also periodically scans the synced objects to ensure
21+
the states between tenant control plane and super cluster are consistent.
22+
23+
- **vn-agent**: A node daemon that proxies all tenant kubelet API requests to the kubelet process that running
24+
in the node. It ensures each tenant can only access its own Pods in the node.
25+
26+
With all above, from the tenant’s perspective, each tenant control plane behaves like an intact Kubernetes with nearly full API capabilities.
27+
For more technical details, please check our [ICDCS 2021 paper.](./doc/vc-icdcs.pdf)
28+
29+
## Live Demos/Presentations
30+
31+
Kubecon EU 2020 talk (~25 mins) | WG meeting demo (~50 mins)
32+
--- | ---
33+
[![](http://img.youtube.com/vi/5RgF_dYyvEY/0.jpg)](https://www.youtube.com/watch?v=5RgF_dYyvEY "vc-kubecon-eu-2020") | [![](http://img.youtube.com/vi/Kow00IEUbAA/0.jpg)](http://www.youtube.com/watch?v=Kow00IEUbAA "vc-demo-long")
34+
35+
## Quick Start
36+
37+
Please follow the [instructions](./doc/demo.md) to install VirtualCluster in your local K8s cluster.
38+
39+
## Abstraction
40+
41+
In VirtualCluster, tenant control plane owns the source of the truth for the specs of all the synced objects.
42+
The exceptions are persistence volume, storage class and priority class resources whose source of the truth is the super cluster.
43+
The syncer updates the synced object's status in each tenant control plane,
44+
acting like a regular resource controller. This abstraction model means the following assumptions:
45+
- The synced object spec _SHOULD_ not be altered by any arbitrary controller in the super cluster.
46+
- Tenant master owns the lifecycle management for the synced object. The synced objects _SHOULD NOT_ be
47+
managed by any controllers (e.g., StatefulSet) in the super cluster.
48+
49+
If any of the above assumptions is violated, VirtualCluster may not work as expected. Note that this
50+
does not mean that a cluster administrator cannot install webhooks, for example, a sidecar webhook,
51+
in the super cluster. Those webhooks will still work but the changes are going
52+
to be hidden to tenants. Alternatively, those webhooks can be installed in tenant control planes so that
53+
tenants will be aware of all changes.
54+
55+
## Limitations
56+
57+
Ideally, tenants should not be aware of the existence of the super cluster in most cases.
58+
There are still some noticeable differences comparing a tenant control plane and a normal Kubernetes cluster.
59+
60+
- In the tenant control plane, node objects only show up after tenant Pods are created. The super cluster
61+
node topology is not fully exposed in the tenant control plane. This means the VirtualCluster does not support
62+
`DaemonSet` alike workloads in tenant control plane. Currently, the syncer controller rejects a newly
63+
created tenant Pod if its `nodename` has been set in the spec.
64+
65+
- The syncer controller manages the lifecycle of the node objects in tenant control plane but
66+
it does not update the node lease objects in order to reduce network traffic. As a result,
67+
it is recommended to increase the tenant control plane node controller `--node-monitor-grace-period`
68+
parameter to a larger value ( >60 seconds, done in the sample clusterversion
69+
[yaml](config/sampleswithspec/clusterversion_v1_nodeport.yaml) already).
70+
71+
- Coredns is not tenant-aware. Hence, tenant should install coredns in the tenant control plane if DNS is required.
72+
The DNS service should be created in the `kube-system` namespace using the name `kube-dns`. The syncer controller can then
73+
recognize the DNS service's cluster IP in super cluster and inject it into any Pod `spec.dnsConfig`.
74+
75+
- The cluster IP field in the tenant service spec is a bogus value. If any tenant controller requires the
76+
actual cluster IP that takes effect in the super cluster nodes, a special handling is required.
77+
The syncer will backpopulate the cluster IP used in the super cluster in the
78+
annotations of the tenant service object using `transparency.tenancy.x-k8s.io/clusterIP` as the key.
79+
Then, the workaround usually is going to be a simple code change in the controller.
80+
This [document](./doc/tenant-dns.md) shows an example for coredns.
81+
82+
- VirtualCluster does not support tenant PersistentVolumes. All PVs and Storageclasses are provided by the super cluster.
83+
84+
VirtualCluster passes most of the Kubernetes conformance tests. One failing test asks for supporting
85+
`subdomain` which cannot be easily done in the VirtualCluster.
86+
87+
## FAQ
88+
89+
### Q: What is the difference between VirtualCluster and multi-cluster solution?
90+
91+
One of the primary design goals of VirtualCluster is to improve the overall resource utilization
92+
of a super cluster by allowing multiple tenants to share the node resources in a control plane isolated manner.
93+
A multi-cluster solution can achieve the same isolation goal but resources won't be shared causing
94+
nodes to have lower utilization.
95+
96+
### Q: Can the tenant control plane run its own scheduler?
97+
98+
VirtualCluster was primarily designed for serverless use cases where users normally do not have
99+
scheduling preferences. Using the super cluster scheduler can much easily
100+
achieve good overall resource utilization. For these reasons,
101+
VirtualCluster does not support tenant scheduler. It is technically possible
102+
to support tenant scheduler by exposing some of the super cluster nodes directly in
103+
tenant control plane. Those nodes have to be dedicated to the tenant to avoid any scheduling
104+
conflicts. This type of tenant should be exceptional.
105+
106+
### Q: What is the difference between Syncer and Virtual Kubelet?
107+
108+
They have similarities. In some sense, the syncer controller can be viewed as the replacement of a virtual
109+
kubelet in cases where the resource provider of the virtual kubelet is a Kubernetes cluster. The syncer
110+
maintains the one to one mapping between a virtual node in tenant control plane and a real node
111+
in the super cluster. It preserves the Kubernetes API compatibility as closely as possible. Additionally,
112+
it provides fair queuing to mitigate tenant contention.
113+
114+
## Release
115+
116+
The first release is coming soon.
117+
118+
## Community
119+
VirtualCluster is a SIG cluster-api-provider-nested (CAPN) supporting project.
120+
If you have any questions or want to contribute, you are welcome to file issues or pull requests.
121+
122+
You can also directly contact VirtualCluster maintainers via the WG [slack channel](https://kubernetes.slack.com/messages/wg-multitenancy).
123+
124+
Lead developer: @Fei-Guo([email protected])

0 commit comments

Comments
 (0)