Compare commits

...

232 Commits

Author SHA1 Message Date
Dario Tranchitella
b594b598b1 chore(helm)!: tcp pod advanced scheduling 2022-10-21 14:39:24 +02:00
Dario Tranchitella
c8ce212730 chore(kustomize): tcp pod advanced scheduling 2022-10-21 14:39:24 +02:00
Dario Tranchitella
714b173132 docs: tcp pod advanced scheduling 2022-10-21 14:39:24 +02:00
Dario Tranchitella
0217d579d6 feat: tcp pod advanced scheduling 2022-10-21 14:39:24 +02:00
Dario Tranchitella
c242f4ac58 api!: tcp pod advanced scheduling 2022-10-21 14:39:24 +02:00
Dario Tranchitella
d4d25a8a05 chore(makefile): golint recipe 2022-10-21 14:39:24 +02:00
maxgio92
cff7f7c4e5 Refactor documentation and provide a website (#173) 2022-10-20 09:57:54 +02:00
Dario Tranchitella
6c817fd7ab fix(helm): kubeversion constraint 2022-10-12 11:27:45 +02:00
Massimiliano Giovagnoli
d31ada4da6 docs: add link to env file for admin cluster setup
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-10-12 10:20:13 +02:00
Massimiliano Giovagnoli
ee01f721d2 docs: add link script for joining nodes setup
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-10-11 17:48:06 +02:00
bsctl
912e010363 docs: add cncf conformance logo 2022-10-06 10:18:18 +02:00
bsctl
e2b03ca873 docs: add cncf conformance logo 2022-10-06 10:18:18 +02:00
Adriano Pezzuto
dccf7bd540 chore(helm): update metadata to helm chart 2022-10-05 09:47:37 +02:00
bsctl
25a65a7496 fix(docs): add logo in svg format 2022-09-23 19:32:16 +02:00
Dario Tranchitella
1ff03246c6 chore(helm): bumping to v0.1.0 2022-09-19 11:43:51 +02:00
Dario Tranchitella
8335f645a5 chore(kustomize): bumping to v0.1.0 2022-09-19 11:43:51 +02:00
Dario Tranchitella
70a791be74 chore(makefile): bumping to v0.1.0 2022-09-19 11:43:51 +02:00
bsctl
b0293c23b5 fix(docs): minor improvement 2022-09-16 20:36:49 +02:00
bsctl
50bba9bb2e fix(docs): deploy tenant nodes on separate subnet 2022-09-16 20:36:49 +02:00
bsctl
f05f7eaf07 fix(docs): remove outdated manifests 2022-09-16 20:36:49 +02:00
bsctl
bfd34ef47e fix(docs): minor improvements 2022-09-16 20:36:49 +02:00
bsctl
b73c7a20ed fix(docs): update roadmap in readme 2022-09-16 20:36:49 +02:00
bsctl
004441e77e fix(docs): use default md style for api reference 2022-09-16 20:36:49 +02:00
bsctl
0f85b6c534 fix(docs): wrong links in readme 2022-09-16 20:36:49 +02:00
bsctl
b674738f0d fix(docs): pin always the kubeadm versions 2022-09-16 20:36:49 +02:00
bsctl
6dc3cd1876 fix(docs): set requirements on kubeadm version 2022-09-16 20:36:49 +02:00
bsctl
96a57fefa5 refactor(docs): track new features and improvements 2022-09-16 20:36:49 +02:00
Dario Tranchitella
87b6f75f66 chore(ci): check helm non committed changes 2022-09-14 11:23:11 +02:00
Dario Tranchitella
1b24806fa3 fix(helm): protocol is not required for external etcd endpoints 2022-09-14 11:23:11 +02:00
Dario Tranchitella
f32ba4a76b fix(makefile): missing namespaces for postgresql kine setup 2022-09-14 11:23:11 +02:00
Dario Tranchitella
19d91aa4d2 chore(log): silencing klog 2022-09-14 11:23:11 +02:00
Dario Tranchitella
a4e2ac24ac fix(kustomize): installing default datastore with proper endpoints 2022-09-14 11:23:11 +02:00
Dario Tranchitella
0dffd9ba46 fix(datastore): default as name for the common datastore 2022-09-14 11:23:11 +02:00
Dario Tranchitella
90b2ca1bab fix(konnectivity): clean-up upon toggling addon
The TCP Deployment container kube-apiserver is deeply hacked with extra
details for konnectivity: most of them weren't cleaned-up properly, and
the function wasn't entirely idempotent in toggling the feature.

This fix is addressing this situation, and rearranging the code
according to the latest polish.
2022-09-12 09:38:36 +02:00
Dario Tranchitella
df8ca7c1d1 refactor: checksum for configmap and secret data 2022-09-12 09:38:36 +02:00
Dario Tranchitella
65519d4f22 refactor: using kamaji prefix for checksum annotation 2022-09-12 09:38:36 +02:00
Dario Tranchitella
e0fa8169f1 refactor: wrapping datastore errors 2022-09-12 09:38:36 +02:00
Dario Tranchitella
41eddc0462 refactor(crypto): eliminating bloated certs functions 2022-09-12 09:38:36 +02:00
Dario Tranchitella
1a9a8a1854 refactor: decoding kubeconfig with less bloated funcs 2022-09-12 09:38:36 +02:00
Dario Tranchitella
0c8a16d604 refactor(utils): encode to yaml uses the non deprecated serializer 2022-09-12 09:38:36 +02:00
Dario Tranchitella
b7adb314ad refactor: logging errors with stacktrace
Using the log facade and logging the error directly in the resource
handler we're getting a more detailed overview of the errors, along with
other metadata useful to understand quicker where the reconciliation
failed.
2022-09-12 09:38:36 +02:00
Dario Tranchitella
e55e6cfdd4 chore(golangci-lint): enabling interfacer and updating code 2022-09-12 09:38:36 +02:00
Dario Tranchitella
6388bf0a7f chore(golangci-lint): enabling used linters 2022-09-12 09:38:36 +02:00
Dario Tranchitella
e089f0ad9a chore: pointer.Int32Ptr is deprecated in favor of pointer.Int32 2022-09-12 09:38:36 +02:00
Dario Tranchitella
0b0bf09813 feat: seeding at startup 2022-09-12 09:38:36 +02:00
Dario Tranchitella
00ea4a562d refactor: moving cert functions to datastore resource 2022-09-12 09:38:36 +02:00
Dario Tranchitella
2a33844c68 refactor(utilities): decreasing bloating functions 2022-09-12 09:38:36 +02:00
Dario Tranchitella
606926ec9a refactor: go simple kubeconfig check 2022-09-12 09:38:36 +02:00
Dario Tranchitella
84b70b3b59 fix: check service-account certificate hash for reconciliation 2022-09-12 09:38:36 +02:00
Dario Tranchitella
4ca79ceb4c fix(helm)!: wrong path for scale spec path 2022-09-10 09:54:12 +02:00
Dario Tranchitella
8df8aa445a fix(kustomize)!: wrong path for scale spec path 2022-09-10 09:54:12 +02:00
Dario Tranchitella
8da916b5cd fix: wrong path for scale spec path 2022-09-10 09:54:12 +02:00
Dario Tranchitella
f15eeebe02 chore(gh): ensure to use go 1.18 for golangci-lint 2022-09-09 17:00:20 +02:00
Dario Tranchitella
7002d48ef9 fix(upgrade): minor release upgrades are allowed 2022-09-09 17:00:20 +02:00
Dario Tranchitella
79edd2606a refactor(kubeadm)!: updating code according to latest changes
Starting from this change, all the nodes trying to join a Kamaji TCP
must be initiated with kubeadm >= 1.25. This is not a hard-prerequisite
since a previous Kubernetes version can be used by specifying it in the
ClusterConfiguration kubernetesVersion field.
2022-09-09 17:00:20 +02:00
Dario Tranchitella
650c20be2b fix(deps): upgrading kubeadm to 1.25.0 2022-09-09 17:00:20 +02:00
Dario Tranchitella
7862717772 refactor: using constants for front-proxy common name 2022-09-09 17:00:10 +02:00
Dario Tranchitella
08eed7b244 fix: --etcd-compaction-interval flag is required for TCP API Server 2022-09-09 17:00:10 +02:00
Dario Tranchitella
1a561758b6 fix: service account issuer must be kubernetes.default.svc 2022-09-09 09:11:43 +02:00
Dario Tranchitella
12f12832f7 fix(kube-apiserver): required flag requestheader-client-ca-file 2022-09-06 19:20:40 +02:00
Dario Tranchitella
b4d0f9b698 chore(helm): adding scale subresource 2022-09-06 16:31:42 +02:00
Dario Tranchitella
14624af093 chore(kustomize)!: adding scale subresource 2022-09-06 16:31:42 +02:00
Dario Tranchitella
52cdc90b48 feat: adding scale subresource 2022-09-06 16:31:42 +02:00
Dario Tranchitella
fbb6e4eec5 chore(helm)!: repository and version override for addons 2022-09-02 14:38:46 +02:00
Dario Tranchitella
880a29f543 chore(kustomize)!: repository and version override for addons 2022-09-02 14:38:46 +02:00
Dario Tranchitella
b0b4ef95c6 feat: repository and version override for addons 2022-09-02 14:38:46 +02:00
Dario Tranchitella
bd909d6567 refactor(docs): updating repository and tag for konnectivity addon 2022-08-31 23:36:58 +02:00
Dario Tranchitella
fcc10c95b2 chore(helm): updating repository and tag 2022-08-31 23:36:58 +02:00
Dario Tranchitella
7e912ed2e8 chore(kustomize): updating repository and tag 2022-08-31 23:36:58 +02:00
Dario Tranchitella
2374176faf refactor(konnectivity): updating repository and tag 2022-08-31 23:36:58 +02:00
Dario Tranchitella
aceeced53a chore(helm)!: support for topology spread constraints 2022-08-31 23:35:54 +02:00
Dario Tranchitella
53c9102ef3 chore(kustomize)!: support for topology spread constraints 2022-08-31 23:35:54 +02:00
Dario Tranchitella
15e1cf7d80 feat: support for topology spread constraints 2022-08-31 23:35:54 +02:00
Dario Tranchitella
f853f25195 refactor: adding further context to error reporting 2022-08-30 16:22:06 +02:00
Dario Tranchitella
5acdc4cc41 refactor(datastore): checking the ca private key for the etcd driver 2022-08-30 16:22:06 +02:00
Dario Tranchitella
360e8200cb chore(helm)!: support for tcp specific data store 2022-08-30 16:22:06 +02:00
Dario Tranchitella
b0c6972873 chore(kustomize)!: support for tcp specific data store 2022-08-30 16:22:06 +02:00
Dario Tranchitella
682006f8aa chore(dockerfile): support for tcp specific data store 2022-08-30 16:22:06 +02:00
Dario Tranchitella
d59f494a69 feat: support for tcp specific data store 2022-08-30 16:22:06 +02:00
Dario Tranchitella
7602d5d803 chore(helm)!: kube-proxy image aligned to tcp version and allowing override 2022-08-27 23:17:01 +02:00
Dario Tranchitella
4c04edbfe8 chore(kustomize)!: kube-proxy image aligned to tcp version and allowing override 2022-08-27 23:17:01 +02:00
Dario Tranchitella
cce4225e07 feat(addons): kube-proxy image aligned to tcp version and allowing override 2022-08-27 23:17:01 +02:00
Dario Tranchitella
10f0021780 chore(controller-gen): upgrading to 0.9.2 2022-08-27 23:17:01 +02:00
Dario Tranchitella
b99a685e2d chore: updating manifests to latest descriptions 2022-08-27 15:39:30 +02:00
Dario Tranchitella
a8de97e442 chore(gomod): upgrading dependencies to k8s 1.25 2022-08-27 15:39:30 +02:00
Dario Tranchitella
8273d7c7b4 chore(golangci-lint): updating to v1.49.0 2022-08-27 15:16:31 +02:00
Dario Tranchitella
a9ea894e32 chore(kustomize)!: storage homogeneity 2022-08-27 15:16:31 +02:00
Dario Tranchitella
ff780aaba6 feat(helm)!: storage homogeneity 2022-08-27 15:16:31 +02:00
Dario Tranchitella
1ddaeccc94 feat: storage homogeneity 2022-08-27 15:16:31 +02:00
Dario Tranchitella
b23cbe3976 docs: documenting datastore feature 2022-08-26 22:05:59 +02:00
Dario Tranchitella
a23fcc502f chore(helm): adding support to datastore 2022-08-26 22:05:59 +02:00
Dario Tranchitella
baeee457a6 chore(kustomize): support for datastore 2022-08-26 22:05:59 +02:00
Dario Tranchitella
d6087949a9 chore: examples for the data store resources with drivers 2022-08-26 22:05:59 +02:00
Dario Tranchitella
ccb54b664c refactor: avoiding unnecessary name declaratin for handlers 2022-08-26 22:05:59 +02:00
Dario Tranchitella
fdd1dd645e refactor: removing unused func params 2022-08-26 22:05:59 +02:00
Dario Tranchitella
2c963881ab feat: using datastore api for backing storage driver 2022-08-26 22:05:59 +02:00
Dario Tranchitella
8e0b0c8ce7 feat(api): adding datastore type 2022-08-26 22:05:59 +02:00
Dario Tranchitella
fe231d6130 fix: ensuring idempotency for kine sidecar container 2022-08-24 14:16:58 +02:00
Dario Tranchitella
2ec6727de7 chore(gh): trigger helm release on tag 2022-08-23 11:17:47 +02:00
Dario Tranchitella
968b343db9 release(helm): 0.1.0 2022-08-23 11:08:26 +02:00
Dario Tranchitella
c3b72c8a3b chore(gh): helm chart has a new directory 2022-08-23 11:08:26 +02:00
Dario Tranchitella
f64cf284de chore(helm): moving to charts folder 2022-08-23 11:08:26 +02:00
Dario Tranchitella
e12509a970 feat(helm): publishing chart 2022-08-23 11:08:26 +02:00
Dario Tranchitella
626a0eed64 docs: postgresql support using kine 2022-08-23 08:48:56 +02:00
Dario Tranchitella
c32a890561 reorg(docs): ingress is no more mandatory 2022-08-23 08:48:56 +02:00
Dario Tranchitella
2eca4b0eeb refactor(test): ingress is no more required 2022-08-23 08:48:56 +02:00
Dario Tranchitella
47fc9fdc63 refactor: ingress is optional 2022-08-23 08:48:56 +02:00
Dario Tranchitella
08022fc780 refactor(helm)!: making ingress optional 2022-08-23 08:48:56 +02:00
Dario Tranchitella
f6d330992d refactor(kustomize)!: making ingress optional 2022-08-23 08:48:56 +02:00
Dario Tranchitella
c449b01121 refactor(api)!: making ingress optional 2022-08-23 08:48:56 +02:00
Dario Tranchitella
1dcafb91d4 refactor(helm)!: removing ingress from status when unused 2022-08-23 08:48:56 +02:00
Dario Tranchitella
766105b50e refactor(kustomize)!: removing ingress from status when unused 2022-08-23 08:48:56 +02:00
Dario Tranchitella
9d5b14f440 refactor(api)!: removing ingress from status when unused 2022-08-23 08:48:56 +02:00
Dario Tranchitella
0954ae7494 feat: checksum for status 2022-08-23 08:48:56 +02:00
Dario Tranchitella
ec55b203a8 feat(helm)!: checksum for status 2022-08-23 08:48:56 +02:00
Dario Tranchitella
d6c65cfbe6 feat(yaml)!: checksum for status 2022-08-23 08:48:56 +02:00
Dario Tranchitella
99c3b47ec9 feat(api)!: checksum for status 2022-08-23 08:48:56 +02:00
Dario Tranchitella
31b25f7c78 feat: postgresql kine driver 2022-08-23 08:48:56 +02:00
Dario Tranchitella
06504e7133 build(yaml)!: aligning to postgresql driver changes 2022-08-23 08:48:56 +02:00
Dario Tranchitella
4e993b7402 feat(helm)!: support for postgresql kine driver 2022-08-23 08:48:56 +02:00
Dario Tranchitella
ebdb24ce45 feat(api)!: support for postgresql kine driver 2022-08-23 08:48:56 +02:00
Dario Tranchitella
f85ddb1808 docs: refactoring documentation for kine integration 2022-08-23 08:48:56 +02:00
Dario Tranchitella
2b7143294b docs: documenting kine-postgresql 2022-08-23 08:48:56 +02:00
Dario Tranchitella
a57f0edd33 chore: support for postgresql as kine backend 2022-08-23 08:48:56 +02:00
Dario Tranchitella
887655c077 refactor(docs): moving docs in the kine folder 2022-08-23 08:48:56 +02:00
Dario Tranchitella
f1b1802cf0 docs: documenting the kine-mysql feature as datastore 2022-08-23 08:48:56 +02:00
Dario Tranchitella
60c187464d chore: making kine-mariadb make idempotent 2022-08-23 08:48:56 +02:00
Dario Tranchitella
3974214d6a fix: ensuring idempotency when kine is enabled 2022-08-23 08:48:56 +02:00
bsctl
f9c776bda5 fix(helm): peer port instead of client port 2022-08-18 09:48:51 +02:00
Dario Tranchitella
1d6be44edf refactor(etcd): using helm functions for endpoints and initial peers, along with ports 2022-08-17 19:51:44 +02:00
bsctl
dce6c1330a fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
922324a71b fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
5da7058ed3 fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
f7483dcb01 fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
e4227e1c81 fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
38ba07f3a4 fix(docs): update guides to latest changes 2022-08-17 16:24:48 +02:00
bsctl
5e5bd83b69 fix(helm): readme 2022-08-16 10:16:17 +02:00
bsctl
97a05b5f49 feat(helm): improve pvc management 2022-08-16 10:16:17 +02:00
bsctl
502cb64a5c fix(helm): restore etcd endpoints 2022-08-16 10:16:17 +02:00
bsctl
c3ad545c97 fix(helm): improve chart documentation 2022-08-16 10:16:17 +02:00
bsctl
0c634d1c16 feat(helm): improve liveness probe for etcd 2022-08-16 10:16:17 +02:00
Viktor Oreshkin
cef05c3310 fix(docs): update link to Capsule in README
Signed-off-by: Viktor Oreshkin <imselfish@stek29.rocks>
2022-08-14 09:04:46 +02:00
bsctl
dce027b8f7 fix(cloudinit): set SystemdCgroup 2022-08-13 07:44:05 +02:00
Dario Tranchitella
d1871cf378 fix(docs): aligning to latest konnectivity changes 2022-07-26 17:17:10 +02:00
Dario Tranchitella
a573805bad chore(kind): using kindest/node base image for local testing 2022-07-26 17:17:10 +02:00
Dario Tranchitella
6a4baf99fc fix: missing toleration for kube-proxy addon 2022-07-26 16:42:35 +02:00
Dario Tranchitella
d290e73307 feat: making kine container image configurable via kamaji flag
A new CLI flag (`--kine-container`) has been introduced, with the
default value of `rancher/kine:v0.9.2-amd64`. It can be overridden also
using the kamaji configuration file (`kamaji.yaml`) using the key
`kine-image`.
2022-07-21 13:53:42 +00:00
Dario Tranchitella
62129f3f0c fix: avoiding nil pointer dereference when cleaning up konnectivity server service 2022-07-21 13:33:57 +00:00
Dario Tranchitella
a5b2c7825c feat: additional extra args for tcp components 2022-07-21 13:33:57 +00:00
Dario Tranchitella
315ef7aa4f feat(api)!: additional extra arguments for control plane components 2022-07-21 13:33:57 +00:00
Dario Tranchitella
161f43ed58 refactor: unique service for tcp and konnectivity server 2022-07-18 20:13:43 +00:00
Dario Tranchitella
af6024ece1 refactor!: using a single service for konnectivity server 2022-07-18 20:13:43 +00:00
Dario Tranchitella
2656bffc48 feat(e2e): reporting tcp status and resources in case of failed test 2022-07-18 20:13:43 +00:00
Dario Tranchitella
f496fefce9 fix: using the announced ip address as source of truth 2022-07-18 20:13:43 +00:00
Dario Tranchitella
094ea2b0e0 feat(e2e): reporting tcp status and resources in case of failed test 2022-07-18 19:03:56 +00:00
Dario Tranchitella
5ff197d2b6 refactor: tcp address must stored during service reconciliation 2022-07-18 19:03:56 +00:00
Dario Tranchitella
b58fef8859 refactor(kubeadmphases): using ingress spec for status update 2022-07-18 19:03:56 +00:00
Dario Tranchitella
260767d770 refactor: removing rendundant options params 2022-07-18 19:03:56 +00:00
Dario Tranchitella
5ecc9aace0 fix(konnectivity): using the announced address of the tcp 2022-07-18 19:03:56 +00:00
Dario Tranchitella
b2a23b0691 fix: using the announced ip address as source of truth 2022-07-18 19:03:56 +00:00
Dario Tranchitella
605d54716a feat(e2e): reporting kamaji logs in case of test failure 2022-07-18 19:03:56 +00:00
Dario Tranchitella
e1bb7dc96f refactor: decoupling konnectivity from tcp k8s deployment handler 2022-07-18 17:09:41 +00:00
Dario Tranchitella
33420fc27a refactor: using builder strategy for tcp deployment 2022-07-18 17:09:41 +00:00
Dario Tranchitella
ad1abe1ea9 feat: utilities for lookups and mangling 2022-07-18 17:09:41 +00:00
Dario Tranchitella
9ad5ea506d feat!: support for components resource handling 2022-07-18 17:09:41 +00:00
Dario Tranchitella
59b7139ada refactor: isolating operations on controlplane deployment containers 2022-07-18 17:09:41 +00:00
Massimiliano Giovagnoli
3baf187b88 fix(internal/resources/konnectivity): get lb svc endpoint from cp status
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-07-14 12:57:45 +00:00
Dario Tranchitella
942804531e test(e2e): ensuring kubeconfig reconciliation upon port change 2022-07-14 06:57:10 +00:00
Dario Tranchitella
0b8f15f86f fix: ensuring reconciliation of kubeconfig hashing kubeadm config and ca 2022-07-14 06:57:10 +00:00
Dario Tranchitella
8c24302d8e fix: no need to point to https port when using ingress 2022-07-14 06:57:10 +00:00
Massimiliano Giovagnoli
84dce57039 fix(internal/resources/etcd_setup.go): close etcd client after etcdsetup reconcile
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
2022-07-13 12:31:57 +00:00
Dario Tranchitella
c4f9d4f8b3 test(e2e): no more required etcd provisioning using makefile 2022-07-12 20:20:45 +00:00
Dario Tranchitella
1e9e247e8b feat(helm): installing etcd along with Kamaji 2022-07-12 20:20:45 +00:00
Dario Tranchitella
bcd1627fed refactor(helm): updating notes with useful commands 2022-07-12 20:20:45 +00:00
Dario Tranchitella
1d70a5c02b refactor(helm): no need of ingress 2022-07-12 20:20:45 +00:00
Massimiliano Giovagnoli
7fc19f7008 docs(getting-started-kind): refactor guide with targets and manifests
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-07-12 07:55:02 +00:00
Massimiliano Giovagnoli
3443ce737c chore(deploy): add genera deploy makefile
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-07-12 07:55:02 +00:00
Massimiliano Giovagnoli
5f9927c48b cleanup(deploy/kind): remove unused etcd cluster manifest
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-07-12 07:55:02 +00:00
Massimiliano Giovagnoli
eaa6899d50 refactor(deploy/kind/join-node): accept tcp kubeconfig from different paths
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-07-12 07:55:02 +00:00
Dario Tranchitella
eb699051a1 feat: logging resource deletion 2022-07-11 09:01:53 +00:00
Dario Tranchitella
a914bad7ce refactor: functions to proper files and using set interface 2022-07-11 07:57:32 +00:00
Dario Tranchitella
40428c7983 refactor: moving kubeadm config interface to v1alpha1 package 2022-07-11 07:57:32 +00:00
Dario Tranchitella
938b35122e refactor!: ensuring reconciliation of kubeadm phases
For AddOns and KubeadmPhase the last revision reference has been removed
in favor of the md5 hash: this has been required since some information
required for the comparison is not persisted in the admin cluster.

With this change, the CRD definition has changed too, making this change
breaking, although still in v1alpha1.
2022-07-11 07:57:32 +00:00
Dario Tranchitella
dadc5c4f50 feat: support for announced clusterip address 2022-07-11 07:21:34 +00:00
Dario Tranchitella
a535d05073 build(helm): pull always images 2022-07-11 07:21:24 +00:00
Dario Tranchitella
d547fea661 build(kustomize): pull always images 2022-07-11 07:21:24 +00:00
Dario Tranchitella
a377bfc1ec refactor: pull always images for tenant control plane instance 2022-07-11 07:21:24 +00:00
Dario Tranchitella
a2541bfc00 refactor: retrying mutate function in case of conflict error 2022-07-09 09:04:49 +00:00
Dario Tranchitella
c47875345d fix(test): aligning test to latest changes 2022-07-09 08:49:26 +00:00
Dario Tranchitella
48fdd6088d docs: updating to api specification tcp.spec.networkProfile.certSANs 2022-07-09 08:49:26 +00:00
Dario Tranchitella
a67e0f51c7 refactor!(api): support for additional certificate SANs
Removing the field tcp.spec.networkProfile.domain in favor of the
tcp.spec.networkProfile.certSANs which allows specifying additional
extra domains that could be used to reach out to the tenant control
plane.
2022-07-09 08:49:26 +00:00
Dario Tranchitella
3d1bfc42f1 fix: konnectivity reconciliation loop 2022-07-08 19:52:37 +00:00
Dario Tranchitella
e6e51cf624 chore(ci): triggering e2e also for the internal package changes 2022-07-08 15:14:25 +00:00
Dario Tranchitella
8cac5a0c9b refactor: abstracting tenant control plane client generation 2022-07-08 15:14:25 +00:00
Dario Tranchitella
b22e11a2a4 style: ensuring headers are correct 2022-07-08 14:13:59 +00:00
Dario Tranchitella
a4879084f2 fix(docs): typo on namespace key name 2022-07-07 12:39:42 +00:00
Dario Tranchitella
478b0d5c3a fix: using local etcd point with kine integration 2022-07-07 12:39:42 +00:00
mendrugory
9e3173676e feat: kine 2022-07-07 12:39:42 +00:00
mendrugory
8f59de6e13 refactor: adaption for kine 2022-07-07 12:39:42 +00:00
mendrugory
3be6cf1c4f feat: konnectivity 2022-06-20 15:53:02 +02:00
mendrugory
5b4de76229 refactor:
* cleaning code
    * group of resources and code improvements
    * addons
    * manifest for helm
2022-06-20 15:53:02 +02:00
Dario Tranchitella
69801d1fb9 feat: providing binary version and details 2022-06-17 13:34:14 +00:00
Dario Tranchitella
ab1818672d refactor(kubeadm): using suggested serializer with options 2022-06-15 17:05:25 +00:00
Dario Tranchitella
8cd83da667 chore(e2e): ensure installation during e2e is done via helm 2022-06-15 10:41:42 +00:00
Dario Tranchitella
05562a775b reorg(test): ensuring networkprofile spec is no more required 2022-06-15 10:41:42 +00:00
Dario Tranchitella
2cd255b1c7 chore(helm): allowing default values for tenant control plane network profile 2022-06-15 10:41:42 +00:00
Dario Tranchitella
26ddbc084c chore(kustomize): allowing default values for tenant control plane network profile 2022-06-15 10:41:42 +00:00
Dario Tranchitella
fb6e24e3e9 feat: allowing default values for tenant control plane network profile 2022-06-15 10:41:42 +00:00
bsctl
22f8412daa fix(docs): wrong links 2022-06-09 18:16:00 +00:00
Davide Imola
c570afc643 chore(ci): helm release pipeline 2022-06-06 10:15:15 +00:00
Massimiliano Giovagnoli
357d549b8f Update the documentation and deploy tools
Also, add kamaji install and rename reqs make target.

Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2022-06-01 12:32:28 +02:00
Dario Tranchitella
33ddebc90c test(e2e): worker node join through kubeadm 2022-05-31 15:58:21 +00:00
Dario Tranchitella
8be787adc5 reorg: marking loadbalancer errors as debug 2022-05-29 16:41:39 +00:00
Adriano Pezzuto
6b452ccd40 Update documentation with latest changes (#44)
* docs: set the kind guide as getting started
* docs: update guides to latest changes
* docs: minor add to README
2022-05-29 17:17:46 +02:00
alegrey91
0dbd73691c chore(ci): adding e2e github action 2022-05-28 09:59:13 +00:00
alegrey91
f57abb0d2e test(e2e): add test suite for e2e 2022-05-28 09:59:13 +00:00
Dario Tranchitella
2f76841753 fix(helm): missing crd update upon addons feature 2022-05-28 09:47:13 +00:00
ptx96
6cebf0950d feat(docker): build according to targetarch 2022-05-26 16:13:39 +00:00
ptx96
6ee5196928 ci(docker): added docker build and push job 2022-05-26 16:13:39 +00:00
Pietro Terrizzi
261aafbb07 docs(kind): fixed URL for kamaji develop deploy 2022-05-26 15:27:47 +00:00
mendrugory
de690a4039 chore(helm): addons 2022-05-26 14:58:05 +02:00
mendrugory
258b1ff48f feat: addons 2022-05-26 10:16:02 +02:00
Dario Tranchitella
1d64932265 docs: pointing to k8s slack channel 2022-05-25 13:51:10 +00:00
Dario Tranchitella
321a955fdb reorg: scaffolding for e2e test suite 2022-05-25 08:35:31 +00:00
Dario Tranchitella
ba09748a5b chore(helm): aligning crd to latest code generation tool 2022-05-23 15:13:01 +00:00
Dario Tranchitella
a198c21987 chore(yaml): aligning crd to latest code generation tool 2022-05-23 15:13:01 +00:00
Dario Tranchitella
3279a0e617 build(dockerfile): upgrade to go 1.18 2022-05-23 15:13:01 +00:00
Dario Tranchitella
243dbddc69 chore(ci): upgrade to go 1.18 2022-05-23 15:13:01 +00:00
Dario Tranchitella
6d7d900ac2 chore: upgrade to go 1.18 2022-05-23 15:13:01 +00:00
Dario Tranchitella
6bf838204d chore: using go install rather than go get 2022-05-23 15:13:01 +00:00
Dario Tranchitella
c0e718cb07 chore: using docker hub as default container registry 2022-05-23 13:47:48 +00:00
Dario Tranchitella
0be08a0099 reorg: upgrade phase as first resource
Ensuring that upon a Tenant Control Plane upgrade the additional printer
columns are reporting a coherent status.
2022-05-23 10:19:43 +00:00
217 changed files with 23206 additions and 11676 deletions

View File

@@ -12,10 +12,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v2.3.0
- uses: actions/setup-go@v3
with:
version: v1.45.2
go-version: '1.18'
check-latest: true
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3.2.0
with:
version: v1.49.0
only-new-issues: false
args: --timeout 5m --config .golangci.yml
diff:
@@ -25,9 +29,10 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-go@v2
- uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.18'
check-latest: true
- run: make yaml-installation-file
- name: Checking if YAML installer file is not aligned
run: if [[ $(git diff | wc -l) -gt 0 ]]; then echo ">>> Untracked generated files have not been committed" && git --no-pager diff && exit 1; fi

74
.github/workflows/docker-ci.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
name: docker-ci
on:
push:
tags:
- "v*"
jobs:
docker-ci:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: |
quay.io/${{ github.repository }}
docker.io/${{ github.repository }}
tags: |
type=semver,pattern={{raw}}
flavor: |
latest=false
- name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v1
with:
platforms: arm64,arm
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
install: true
- name: Inspect builder
run: |
echo "Name: ${{ steps.buildx.outputs.name }}"
echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
echo "Status: ${{ steps.buildx.outputs.status }}"
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
- name: Login to quay.io Container Registry
uses: docker/login-action@v1
with:
registry: quay.io
username: ${{ secrets.QUAY_IO_USERNAME }}
password: ${{ secrets.QUAY_IO_TOKEN }}
- name: Login to docker.io Container Registry
uses: docker/login-action@v1
with:
registry: docker.io
username: ${{ secrets.DOCKER_IO_USERNAME }}
password: ${{ secrets.DOCKER_IO_TOKEN }}
- name: Build and push
id: build-release
uses: docker/build-push-action@v2
with:
file: Dockerfile
context: .
platforms: linux/amd64,linux/arm64,linux/arm
push: true
tags: ${{ steps.meta.outputs.tags }}
build-args:
- name: Image digest
run: echo ${{ steps.build-release.outputs.digest }}

45
.github/workflows/e2e.yaml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: e2e
on:
push:
branches: [ "*" ]
paths:
- '.github/workflows/e2e.yml'
- 'api/**'
- 'controllers/**'
- 'e2e/*'
- 'Dockerfile'
- 'go.*'
- 'main.go'
- 'Makefile'
- 'internal/**'
pull_request:
branches: [ "*" ]
paths:
- '.github/workflows/e2e.yml'
- 'api/**'
- 'controllers/**'
- 'e2e/*'
- 'Dockerfile'
- 'go.*'
- 'main.go'
- 'Makefile'
- 'internal/**'
jobs:
kind:
name: Kubernetes
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-go@v3
with:
go-version: '1.18'
check-latest: true
- run: |
sudo apt-get update
sudo apt-get install -y golang-cfssl
- name: e2e testing
run: make e2e

46
.github/workflows/helm.yaml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Helm Chart
on:
push:
branches: [ "*" ]
tags: [ "helm-v*" ]
pull_request:
branches: [ "*" ]
jobs:
diff:
name: diff
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- run: make -C charts/kamaji docs
- name: Checking if Helm docs is not aligned
run: if [[ $(git diff | wc -l) -gt 0 ]]; then echo ">>> Untracked changes have not been committed" && git --no-pager diff && exit 1; fi
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: azure/setup-helm@v1
with:
version: 3.3.4
- name: Linting Chart
run: helm lint ./charts/kamaji
release:
if: startsWith(github.ref, 'refs/tags/helm-v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Publish Helm chart
uses: stefanprodan/helm-gh-pages@master
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
charts_dir: charts
charts_url: https://clastix.github.io/charts
owner: clastix
repository: charts
branch: gh-pages
target_dir: .
commit_username: prometherion
commit_email: dario@tranchitella.eu

View File

@@ -4,15 +4,16 @@ linters-settings:
- standard
- default
- prefix(github.com/clastix/kamaji)
goheader:
template: |-
Copyright 2022 Clastix Labs
SPDX-License-Identifier: Apache-2.0
linters:
disable:
- wrapcheck
- gomnd
- scopelint
- golint
- interfacer
- maligned
- varnamelen
- testpackage
- tagliatelle
@@ -23,6 +24,10 @@ linters:
- exhaustivestruct
- wsl
- exhaustive
- nosprintfhostport
- nonamedreturns
- interfacebloat
- exhaustruct
- lll
- gosec
- gomoddirectives
@@ -30,6 +35,14 @@ linters:
- gochecknoinits
- funlen
- dupl
- maintidx
- cyclop
# deprecated linters
- deadcode
- golint
- interfacer
- structcheck
- varcheck
- nosnakecase
- ifshort
- maligned
enable-all: true

View File

@@ -1,5 +1,13 @@
# Build the manager binary
FROM golang:1.17 as builder
FROM golang:1.18 as builder
ARG TARGETARCH
ARG GIT_HEAD_COMMIT
ARG GIT_TAG_COMMIT
ARG GIT_LAST_TAG
ARG GIT_MODIFIED
ARG GIT_REPO
ARG BUILD_DATE
WORKDIR /workspace
# Copy the Go Modules manifests
@@ -14,9 +22,12 @@ COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
COPY internal/ internal/
COPY indexers/ indexers/
# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build \
-ldflags "-X github.com/clastix/kamaji/internal.GitRepo=$GIT_REPO -X github.com/clastix/kamaji/internal.GitTag=$GIT_LAST_TAG -X github.com/clastix/kamaji/internal.GitCommit=$GIT_HEAD_COMMIT -X github.com/clastix/kamaji/internal.GitDirty=$GIT_MODIFIED -X github.com/clastix/kamaji/internal.BuildTime=$BUILD_DATE" \
-a -o manager main.go
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details

140
Makefile
View File

@@ -3,7 +3,7 @@
# To re-generate a bundle for another specific version without changing the standard setup, you can:
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
VERSION ?= 0.0.1
VERSION ?= 0.1.1
# CHANNELS define the bundle channels used in the bundle.
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
@@ -36,11 +36,7 @@ IMAGE_TAG_BASE ?= clastix.io/operator
BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false"
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.21
IMG ?= clastix/kamaji:v$(VERSION)
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
@@ -50,7 +46,6 @@ GOBIN=$(shell go env GOBIN)
endif
# Setting SHELL to bash allows bash commands to be executed by recipes.
# This is a requirement for 'setup-envtest.sh' in the test target.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
@@ -73,33 +68,77 @@ all: build
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
##@ Binary
.PHONY: helm
HELM = $(shell pwd)/bin/helm
helm: ## Download helm locally if necessary.
$(call go-install-tool,$(HELM),helm.sh/helm/v3/cmd/helm@v3.9.0)
GINKGO = $(shell pwd)/bin/ginkgo
ginkgo: ## Download ginkgo locally if necessary.
$(call go-install-tool,$(GINKGO),github.com/onsi/ginkgo/ginkgo@v1.16.5)
KIND = $(shell pwd)/bin/kind
kind: ## Download kind locally if necessary.
$(call go-install-tool,$(KIND),sigs.k8s.io/kind/cmd/kind@v0.14.0)
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.9.2)
GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint
golangci-lint: ## Download golangci-lint locally if necessary.
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0)
KUSTOMIZE = $(shell pwd)/bin/kustomize
kustomize: ## Download kustomize locally if necessary.
$(call install-kustomize,$(KUSTOMIZE),3.8.7)
APIDOCS_GEN = $(shell pwd)/bin/crdoc
apidocs-gen: ## Download crdoc locally if necessary.
$(call go-install-tool,$(APIDOCS_GEN),fybrik.io/crdoc@latest)
##@ Development
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
cp config/crd/bases/kamaji.clastix.io_tenantcontrolplanes.yaml charts/kamaji/crds/tenantcontrolplane.yaml
cp config/crd/bases/kamaji.clastix.io_datastores.yaml charts/kamaji/crds/datastore.yaml
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
fmt: ## Run go fmt against code.
go fmt ./...
golint: golangci-lint ## Linting the code according to the styling guide.
$(GOLANGCI_LINT) run -c .golangci.yml
vet: ## Run go vet against code.
go vet ./...
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out
test:
go test ./... -coverprofile cover.out
##@ Build
# Get information about git current status
GIT_HEAD_COMMIT ?= $$(git rev-parse --short HEAD)
GIT_TAG_COMMIT ?= $$(git rev-parse --short $(VERSION))
GIT_MODIFIED_1 ?= $$(git diff $(GIT_HEAD_COMMIT) $(GIT_TAG_COMMIT) --quiet && echo "" || echo ".dev")
GIT_MODIFIED_2 ?= $$(git diff --quiet && echo "" || echo ".dirty")
GIT_MODIFIED ?= $$(echo "$(GIT_MODIFIED_1)$(GIT_MODIFIED_2)")
GIT_REPO ?= $$(git config --get remote.origin.url)
BUILD_DATE ?= $$(git log -1 --format="%at" | xargs -I{} date -d @{} +%Y-%m-%dT%H:%M:%S)
build: generate fmt vet ## Build manager binary.
go build -o bin/manager main.go
run: manifests generate fmt vet ## Run a controller from your host.
go run ./main.go
docker-build: test ## Build docker image with the manager.
docker build -t ${IMG} .
docker-build: ## Build docker image with the manager.
docker build -t ${IMG} . --build-arg GIT_HEAD_COMMIT=$(GIT_HEAD_COMMIT) \
--build-arg GIT_TAG_COMMIT=$(GIT_TAG_COMMIT) \
--build-arg GIT_MODIFIED=$(GIT_MODIFIED) \
--build-arg GIT_REPO=$(GIT_REPO) \
--build-arg GIT_LAST_TAG=$(VERSION) \
--build-arg BUILD_DATE=$(BUILD_DATE)
docker-push: ## Push docker image with the manager.
docker push ${IMG}
@@ -109,8 +148,8 @@ docker-push: ## Push docker image with the manager.
dev: generate manifests uninstall install rbac ## Full installation for development purposes
go fmt ./...
load: dev docker-build
kind load docker-image --name kamaji ${IMG}
load: docker-build kind
$(KIND) load docker-image --name kamaji ${IMG}
rbac: manifests kustomize ## Install RBAC into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/rbac | kubectl apply -f -
@@ -131,33 +170,6 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi
yaml-installation-file: manifests kustomize ## Create yaml installation file
$(KUSTOMIZE) build config/default > config/install.yaml
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.6.1)
KUSTOMIZE = $(shell pwd)/bin/kustomize
kustomize: ## Download kustomize locally if necessary.
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
ENVTEST = $(shell pwd)/bin/setup-envtest
envtest: ## Download envtest-setup locally if necessary.
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
# go-get-tool will 'go get' any package $2 and install it to $1.
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
define go-get-tool
@[ -f $(1) ] || { \
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef
.PHONY: bundle
bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.
operator-sdk generate kustomize manifests -q
@@ -213,3 +225,39 @@ catalog-build: opm ## Build a catalog image.
.PHONY: catalog-push
catalog-push: ## Push a catalog image.
$(MAKE) docker-push IMG=$(CATALOG_IMG)
define install-kustomize
@[ -f $(1) ] || { \
set -e ;\
echo "Installing v$(2)" ;\
cd bin ;\
wget "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" ;\
bash ./install_kustomize.sh $(2) ;\
}
endef
# go-install-tool will 'go install' any package $2 and install it to $1.
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
define go-install-tool
@[ -f $(1) ] || { \
set -e ;\
echo "Installing $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
}
endef
.PHONY: env
env:
@make -C deploy/kind kind ingress-nginx
##@ e2e
.PHONY: e2e
e2e: env load helm ginkgo ## Create a KinD cluster, install Kamaji on it and run the test suite.
$(HELM) upgrade --debug --install kamaji ./charts/kamaji --create-namespace --namespace kamaji-system --set "image.pullPolicy=Never"
$(GINKGO) -v ./e2e
##@ Document
apidoc: apidocs-gen
$(APIDOCS_GEN) crdoc --resources config/crd/bases --output docs/content/reference/api.md --template docs/templates/reference-cr.tmpl

View File

@@ -16,4 +16,12 @@ resources:
kind: TenantControlPlane
path: github.com/clastix/kamaji/api/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: false
domain: clastix.io
group: kamaji
kind: DataStore
path: github.com/clastix/kamaji/api/v1alpha1
version: v1alpha1
version: "3"

112
README.md
View File

@@ -8,115 +8,57 @@
</a>
</p>
**Kamaji** is a tool aimed to build and operate a **Managed Kubernetes Service** with a fraction of the operational burden. With **Kamaji**, you can deploy and operate hundreds of Kubernetes clusters as a hyper-scale cloud provider.
**Kamaji** deploys and operates **Kubernetes** at scale with a fraction of the operational burden.
<p align="center" style="padding: 6px 6px">
<img src="assets/kamaji-logo.png" />
</p>
> This project is still in the early development stage which means it's not ready for production as APIs, commands, flags, etc. are subject to change, but also that your feedback can still help to shape it. Please try it out and let us know what you like, dislike, what works, what doesn't, etc.
## Why we are building it?
Global hyper-scalers are leading the Managed Kubernetes space, while regional cloud providers, as well as large corporations, are struggling to offer the same level of experience to their developers because of the lack of the right tools. Also, Kubernetes solutions for the on-premises are designed with an enterprise-first approach and they are too costly when deployed at scale. Project Kamaji aims to solve this pain by leveraging multi-tenancy and simplifying how to run Kubernetes clusters at scale with a fraction of the operational burden.
Global hyper-scalers are leading the Managed Kubernetes space, while other cloud providers, as well as large corporations, are struggling to offer the same experience to their DevOps teams because of the lack of the right tools. Also, current Kubernetes solutions are mainly designed with an enterprise-first approach and they are too costly when deployed at scale.
**Kamaji** aims to solve these pains by leveraging multi-tenancy and simplifying how to run multiple control planes on the same infrastructure with a fraction of the operational burden.
## How it works
Kamaji turns any CNCF conformant Kubernetes cluster into an _“admin cluster”_ to orchestrate other Kubernetes clusters we're calling _“tenant clusters”_. As with every Kubernetes cluster, a tenant cluster has a set of nodes and a control plane, composed of several components: `APIs server`, `scheduler`, `controller manager`. What Kamaji does is deploy those components as a pod running in the admin cluster.
Kamaji turns any Kubernetes cluster into an _“admin cluster”_ to orchestrate other Kubernetes clusters called _“tenant clusters”_. What makes Kamaji special is that Control Planes of _“tenant clusters”_ are just regular pods running in the _“admin cluster”_ instead of dedicated Virtual Machines. This solution makes running control planes at scale cheaper and easier to deploy and operate.
![Architecture](docs/content/images/kamaji-light.png#gh-light-mode-only)
![Architecture](docs/content/images/kamaji-dark.png#gh-dark-mode-only)
And what about the tenant worker nodes? They are just worker nodes: regular instances, e.g. virtual or bare metal, connecting to the APIs server of the tenant cluster. Kamaji's goal is to manage the lifecycle of hundreds of these clusters, not only one, so how can we add another tenant cluster? As you could expect, Kamaji just deploys a new tenant control plane as a new pod in the admin cluster, and then it joins the new tenant worker nodes.
## Getting started
<p align="center">
<img src="assets/kamaji-light.png" />
</p>
All the tenant clusters built with Kamaji are fully compliant CNCF Kubernetes clusters and are compatible with the standard Kubernetes toolchains everybody knows and loves.
<p align="center">
<img src="assets/screenshot.png" />
</p>
## Save the state
Putting the tenant cluster control plane in a pod is the easiest part. Also, we have to make sure each tenant cluster saves the state to be able to store and retrieve data.
A dedicated `etcd` cluster for each tenant cluster doesnt scale well for a managed service because `etcd` data persistence can be cumbersome at scale, rising the operational effort to mitigate it. So we have to find an alternative keeping in mind our goal for a resilient and cost-optimized solution at the same time. As we can deploy any Kubernetes cluster with an external `etcd` cluster, we explored this option for the tenant control planes. On the admin cluster, we deploy a multi-tenant `etcd` cluster storing the state of multiple tenant clusters.
With this solution, the resiliency is guaranteed by the usual `etcd` mechanism, and the pods' count remains under control, so it solves the main goal of resiliency and costs optimization. The trade-off here is that we have to operate an external `etcd` cluster and manage the access to be sure that each tenant cluster uses only its data. Also, there are limits in size in `etcd`, defaulted to 2GB and configurable to a maximum of 8GB. Were solving this issue by pooling multiple `etcd` and sharding the tenant control planes.
## Use cases
Kamaji project has been initially started as a solution for actual and common problems such as minimizing the Total Cost of Ownership while running Kubernetes at scale. However, it can open a wider range of use cases. Here are a few:
### Managed Kubernetes
Enabling companies to provide Cloud Native Infrastructure with ease by introducing a strong separation of concerns between management and workloads. Centralize clusters management, monitoring, and observability by leaving developers to focus on the applications, increase productivity and reduce operational costs.
### Control Plane as a Service
Provide Kubernetes control plane in a self-service fashion by running management and workloads on different infrastructures and cost centers with the option of Bring Your Own Device - BYOD.
### Edge Computing
Distribute Kubernetes workloads across edge computing locations without having to manage multiple clusters across various providers. Centralize management of hundreds of control planes while leaving workloads to run isolated on their own dedicated infrastructure.
### Cluster Simulations
Test a new Kubernetes API or experimental flag or a new tool without impacting production operations. Kamaji will let you simulate such things in a safe and controlled environment.
Please refer to the [Getting Started guide](https://kamaji.clastix.io/getting-started/) to deploy a minimal setup of Kamaji on KinD.
## Features
### Self Service Kubernetes
Leave users the freedom to self-provision their Kubernetes clusters according to the assigned boundaries.
### Multi-cluster Management
Centrally manage multiple tenant clusters from a single admin cluster. Happy SREs.
### Cheaper Control Planes
Place multiple tenant control planes on a single node, instead of having three nodes for a single control plane.
### Stronger Multi-Tenancy
Leave tenants to access the control plane with admin permissions while keeping the tenant isolated at the infrastructure level.
### Kubernetes Inception
Use Kubernetes to manage Kubernetes by re-using all the Kubernetes goodies you already know and love.
### Full APIs compliant
Tenant clusters are fully CNCF compliant built with upstream Kubernetes binaries. A client does not see differences between a Kamaji provisioned cluster and a dedicated cluster.
- **Self Service Kubernetes:** leave users the freedom to self-provision their Kubernetes clusters according to the assigned boundaries.
- **Multi-cluster Management:** centrally manage multiple tenant clusters from a single admin cluster. Happy SREs.
- **Cheaper Control Planes:** place multiple tenant control planes on a single node, instead of having three nodes for a single control plane.
- **Stronger Multi-Tenancy:** leave tenants to access the control plane with admin permissions while keeping the tenant isolated at the infrastructure level.
- **Kubernetes Inception:** use Kubernetes to manage Kubernetes by re-using all the Kubernetes goodies you already know and love.
- **Full APIs compliant:** tenant clusters are fully CNCF compliant built with upstream Kubernetes binaries. A user does not see differences between a Kamaji provisioned cluster and a dedicated cluster.
## Roadmap
- [ ] Benchmarking and stress-test
- [x] Support for dynamic address allocation on native Load Balancer
- [x] Zero Downtime Tenant Control Plane upgrade
- [ ] `konnectivity` integration
- [x] `konnectivity` integration
- [ ] Provisioning of Tenant Control Plane through Cluster APIs
- [ ] Prometheus metrics for monitoring and alerting
- [ ] `kine` integration, i.e. use MySQL, SQLite, PostgreSQL as datastore
- [ ] Deeper `kubeadm` integration
- [ ] `etcd` pooling
- [ ] Tenant Control Planes sharding
- [ ] Terraform provider
- [ ] Custom Prometheus metrics for monitoring and alerting
- [x] `kine` integration for MySQL as datastore
- [x] `kine` integration for PostgreSQL as datastore
- [x] Pool of multiple datastores
- [ ] Automatic assigning of Tenant Control Plane to a datastore
- [ ] Autoscaling of Tenant Control Plane pods
## Documentation
Please, check the project's [documentation](./docs/) for getting started with Kamaji.
Please, check the project's [documentation](https://kamaji.clastix.io/) for getting started with Kamaji.
## Contributions
Kamaji is Open Source with Apache 2 license and any contribution is welcome.
## FAQ
Q. What does Kamaji means?
A. Kamaji is named as the character _Kamaji_ from the Japanese movie [_Spirited Away_](https://en.wikipedia.org/wiki/Spirited_Away).
Q. Is Kamaji another Kubernetes distribution?
A. No, Kamaji is a tool you can install on top of any CNCF conformant Kubernetes to provide hundreds of managed Tenant clusters as a service. We tested Kamaji on vanilla Kubernetes 1.23+, KinD, and MS Azure AKS. We expect it to work smoothly on other Kubernetes distributions. The tenant clusters made with Kamaji are conformant CNCF Kubernetes vanilla clusters built with `kubeadm`.
Q. Is it safe to run Kubernetes control plane components in a pod?
A. Yes, the tenant control plane components are packaged in the same way they are running in bare metal or virtual nodes. We leverage the `kubeadm` code to set up the control plane components as they were running on a server. The same unchanged images of upstream `APIs server`, `scheduler`, `controller manager` are used.
Q. And what about multi-tenant `etcd`? I never heard of it.
A. Even if multi-tenant deployment for `etcd` is not a common practice, multi-tenancy, RBAC, and client authentication has been [supported](https://etcd.io/docs/v3.5/op-guide/authentication/) in `etcd` from a long time.
Q. You already provide a Kubernetes multi-tenancy solution with [Capsule](capsule.clastix.io). Why does Kamaji matter?
A. Lighter Multi-Tenancy solutions, like Capsule shares the Kubernetes control plane among all tenants keeping tenant namespaces isolated by policies. While these solutions are the right choice by balancing between features and ease of usage, there are cases where a tenant user requires access to the control plane, for example, when a tenant requires to manage CRDs on his own. With Kamaji, you can provide admin permissions to the tenants.
Q. So I need a costly cloud infrastructure to try Kamaji?
A. No, it is possible to try Kamaji on your laptop with [KinD](./deploy/kind/README.md).
## Community
Join the [Kubernetes Slack Workspace](https://slack.k8s.io/) and the [`#kamaji`](https://kubernetes.slack.com/archives/C03GLTTMWNN) channel to meet end-users and contributors.

View File

@@ -0,0 +1,39 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// GetContent is the resolver for the container of the Secret.
// The bare content has priority over the external reference.
func (in *ContentRef) GetContent(ctx context.Context, client client.Client) ([]byte, error) {
if content := in.Content; len(content) > 0 {
return content, nil
}
secretRef := in.SecretRef
if secretRef == nil {
return nil, fmt.Errorf("no bare content and no external Secret reference")
}
secret, namespacedName := &corev1.Secret{}, types.NamespacedName{Name: secretRef.Name, Namespace: secretRef.Namespace}
if err := client.Get(ctx, namespacedName, secret); err != nil {
return nil, err
}
v, ok := secret.Data[secretRef.KeyPath]
if !ok {
return nil, fmt.Errorf("secret %s does not have key %s", namespacedName.String(), secretRef.KeyPath)
}
return v, nil
}

View File

@@ -0,0 +1,104 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type Driver string //+kubebuilder:validation:Enum=etcd;MySQL;PostgreSQL
var (
EtcdDriver Driver = "etcd"
KineMySQLDriver Driver = "MySQL"
KinePostgreSQLDriver Driver = "PostgreSQL"
)
// DataStoreSpec defines the desired state of DataStore.
type DataStoreSpec struct {
// The driver to use to connect to the shared datastore.
Driver Driver `json:"driver"`
// List of the endpoints to connect to the shared datastore.
// No need for protocol, just bare IP/FQDN and port.
Endpoints []string `json:"endpoints"` //+kubebuilder:validation:MinLength=1
// In case of authentication enabled for the given data store, specifies the username and password pair.
// This value is optional.
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
// Defines the TLS/SSL configuration required to connect to the data store in a secure way.
TLSConfig TLSConfig `json:"tlsConfig"`
}
// TLSConfig contains the information used to connect to the data store using a secured connection.
type TLSConfig struct {
// Retrieve the Certificate Authority certificate and private key, such as bare content of the file, or a SecretReference.
// The key reference is required since etcd authentication is based on certificates, and Kamaji is responsible in creating this.
CertificateAuthority CertKeyPair `json:"certificateAuthority"`
// Specifies the SSL/TLS key and private key pair used to connect to the data store.
ClientCertificate ClientCertificate `json:"clientCertificate"`
}
type ClientCertificate struct {
Certificate ContentRef `json:"certificate"`
PrivateKey ContentRef `json:"privateKey"`
}
type CertKeyPair struct {
Certificate ContentRef `json:"certificate"`
PrivateKey *ContentRef `json:"privateKey,omitempty"`
}
// BasicAuth contains the required information to perform the connection using user credentials to the data store.
type BasicAuth struct {
Username ContentRef `json:"username"`
Password ContentRef `json:"password"`
}
type ContentRef struct {
// Bare content of the file, base64 encoded.
// It has precedence over the SecretReference value.
Content []byte `json:"content,omitempty"`
SecretRef *SecretReference `json:"secretReference,omitempty"`
}
type SecretReference struct {
corev1.SecretReference `json:",inline"`
// Name of the key for the given Secret reference where the content is stored.
// This value is mandatory.
KeyPath string `json:"keyPath"`
}
// DataStoreStatus defines the observed state of DataStore.
type DataStoreStatus struct {
// List of the Tenant Control Planes, namespaced named, using this data store.
UsedBy []string `json:"usedBy,omitempty"`
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Cluster
//+kubebuilder:printcolumn:name="Driver",type="string",JSONPath=".spec.driver",description="Kamaji data store driver"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
// DataStore is the Schema for the datastores API.
type DataStore struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DataStoreSpec `json:"spec,omitempty"`
Status DataStoreStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// DataStoreList contains a list of DataStore.
type DataStoreList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []DataStore `json:"items"`
}
func init() {
SchemeBuilder.Register(&DataStore{}, &DataStoreList{})
}

View File

@@ -2,8 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
// Package v1alpha1 contains API Schema definitions for the kamaji v1alpha1 API group
//+kubebuilder:object:generate=true
//+groupName=kamaji.clastix.io
// +kubebuilder:object:generate=true
// +groupName=kamaji.clastix.io
//nolint
package v1alpha1
import (

View File

@@ -0,0 +1,17 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (in AddonStatus) GetChecksum() string {
return in.Checksum
}
func (in *AddonStatus) SetChecksum(checksum string) {
in.LastUpdate = metav1.Now()
in.Checksum = checksum
}

View File

@@ -6,14 +6,41 @@ package v1alpha1
import (
"context"
"fmt"
"net"
"strconv"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
kamajierrors "github.com/clastix/kamaji/internal/errors"
)
func (in *TenantControlPlane) GetAddress(ctx context.Context, client client.Client) (string, error) {
// AssignedControlPlaneAddress returns the announced address and port of a Tenant Control Plane.
// In case of non-well formed values, or missing announcement, an error is returned.
func (in *TenantControlPlane) AssignedControlPlaneAddress() (string, int32, error) {
if len(in.Status.ControlPlaneEndpoint) == 0 {
return "", 0, fmt.Errorf("the Tenant Control Plane is not yet exposed")
}
address, portString, err := net.SplitHostPort(in.Status.ControlPlaneEndpoint)
if err != nil {
return "", 0, errors.Wrap(err, "cannot split host port from Tenant Control Plane endpoint")
}
port, err := strconv.Atoi(portString)
if err != nil {
return "", 0, errors.Wrap(err, "cannot convert Tenant Control Plane port from endpoint")
}
return address, int32(port), nil
}
// DeclaredControlPlaneAddress returns the desired Tenant Control Plane address.
// In case of dynamic allocation, e.g. using a Load Balancer, it queries the API Server looking for the allocated IP.
// When an IP has not been yet assigned, or it is expected, an error is returned.
func (in *TenantControlPlane) DeclaredControlPlaneAddress(ctx context.Context, client client.Client) (string, error) {
var loadBalancerStatus corev1.LoadBalancerStatus
svc := &corev1.Service{}
@@ -26,10 +53,12 @@ func (in *TenantControlPlane) GetAddress(ctx context.Context, client client.Clie
case len(in.Spec.NetworkProfile.Address) > 0:
// Returning the hard-coded value in the specification in case of non LoadBalanced resources
return in.Spec.NetworkProfile.Address, nil
case svc.Spec.Type == corev1.ServiceTypeClusterIP:
return svc.Spec.ClusterIP, nil
case svc.Spec.Type == corev1.ServiceTypeLoadBalancer:
loadBalancerStatus = svc.Status.LoadBalancer
if len(loadBalancerStatus.Ingress) == 0 {
return "", fmt.Errorf("cannot retrieve the TenantControlPlane address, Service resource is not yet exposed as LoadBalancer")
return "", kamajierrors.NonExposedLoadBalancerError{}
}
for _, lb := range loadBalancerStatus.Ingress {
@@ -39,5 +68,5 @@ func (in *TenantControlPlane) GetAddress(ctx context.Context, client client.Clie
}
}
return "", fmt.Errorf("the actual resource doesn't have yet a valid IP address")
return "", kamajierrors.MissingValidIPError{}
}

View File

@@ -0,0 +1,12 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
// KubeadmConfigChecksumDependant is the interface used to retrieve the checksum of the kubeadm phases and addons
// configuration, required to validate the changes and, upon from that, perform the required reconciliation.
// +kubebuilder:object:generate=false
type KubeadmConfigChecksumDependant interface {
GetChecksum() string
SetChecksum(string)
}

View File

@@ -0,0 +1,17 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (in KubeadmPhaseStatus) GetChecksum() string {
return in.Checksum
}
func (in *KubeadmPhaseStatus) SetChecksum(checksum string) {
in.LastUpdate = metav1.Now()
in.Checksum = checksum
}

View File

@@ -0,0 +1,239 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// APIServerCertificatesStatus defines the observed state of ETCD Certificate for API server.
type APIServerCertificatesStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// ETCDCertificateStatus defines the observed state of ETCD Certificate for API server.
type ETCDCertificateStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// ETCDCertificatesStatus defines the observed state of ETCD Certificate for API server.
type ETCDCertificatesStatus struct {
APIServer APIServerCertificatesStatus `json:"apiServer,omitempty"`
CA ETCDCertificateStatus `json:"ca,omitempty"`
}
// CertificatePrivateKeyPairStatus defines the status.
type CertificatePrivateKeyPairStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// PublicKeyPrivateKeyPairStatus defines the status.
type PublicKeyPrivateKeyPairStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// CertificatesStatus defines the observed state of ETCD TLSConfig.
type CertificatesStatus struct {
CA CertificatePrivateKeyPairStatus `json:"ca,omitempty"`
APIServer CertificatePrivateKeyPairStatus `json:"apiServer,omitempty"`
APIServerKubeletClient CertificatePrivateKeyPairStatus `json:"apiServerKubeletClient,omitempty"`
FrontProxyCA CertificatePrivateKeyPairStatus `json:"frontProxyCA,omitempty"`
FrontProxyClient CertificatePrivateKeyPairStatus `json:"frontProxyClient,omitempty"`
SA PublicKeyPrivateKeyPairStatus `json:"sa,omitempty"`
ETCD *ETCDCertificatesStatus `json:"etcd,omitempty"`
}
type DataStoreCertificateStatus struct {
SecretName string `json:"secretName,omitempty"`
Checksum string `json:"checksum,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
type DataStoreConfigStatus struct {
SecretName string `json:"secretName,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
type DataStoreSetupStatus struct {
Schema string `json:"schema,omitempty"`
User string `json:"user,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// StorageStatus defines the observed state of StorageStatus.
type StorageStatus struct {
Driver string `json:"driver,omitempty"`
DataStoreName string `json:"dataStoreName,omitempty"`
Config DataStoreConfigStatus `json:"config,omitempty"`
Setup DataStoreSetupStatus `json:"setup,omitempty"`
Certificate DataStoreCertificateStatus `json:"certificate,omitempty"`
}
// KubeconfigStatus contains information about the generated kubeconfig.
type KubeconfigStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// KubeconfigsStatus stores information about all the generated kubeconfig resources.
type KubeconfigsStatus struct {
Admin KubeconfigStatus `json:"admin,omitempty"`
ControllerManager KubeconfigStatus `json:"controllerManager,omitempty"`
Scheduler KubeconfigStatus `json:"scheduler,omitempty"`
}
// KubeadmConfigStatus contains the status of the configuration required by kubeadm.
type KubeadmConfigStatus struct {
ConfigmapName string `json:"configmapName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
// Checksum of the kubeadm configuration to detect changes
Checksum string `json:"checksum,omitempty"`
}
// KubeadmPhaseStatus contains the status of a kubeadm phase action.
type KubeadmPhaseStatus struct {
Checksum string `json:"checksum,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// KubeadmPhasesStatus contains the status of the different kubeadm phases action.
type KubeadmPhasesStatus struct {
UploadConfigKubeadm KubeadmPhaseStatus `json:"uploadConfigKubeadm"`
UploadConfigKubelet KubeadmPhaseStatus `json:"uploadConfigKubelet"`
BootstrapToken KubeadmPhaseStatus `json:"bootstrapToken"`
}
type ExternalKubernetesObjectStatus struct {
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
Checksum string `json:"checksum,omitempty"`
// Last time when k8s object was updated
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// KonnectivityStatus defines the status of Konnectivity as Addon.
type KonnectivityStatus struct {
Enabled bool `json:"enabled"`
ConfigMap KonnectivityConfigMap `json:"configMap,omitempty"`
Certificate CertificatePrivateKeyPairStatus `json:"certificate,omitempty"`
Kubeconfig KubeconfigStatus `json:"kubeconfig,omitempty"`
ServiceAccount ExternalKubernetesObjectStatus `json:"sa,omitempty"`
ClusterRoleBinding ExternalKubernetesObjectStatus `json:"clusterrolebinding,omitempty"`
Agent ExternalKubernetesObjectStatus `json:"agent,omitempty"`
Service KubernetesServiceStatus `json:"service,omitempty"`
}
type KonnectivityConfigMap struct {
Name string `json:"name,omitempty"`
Checksum string `json:"checksum,omitempty"`
}
// AddonStatus defines the observed state of an Addon.
type AddonStatus struct {
Enabled bool `json:"enabled"`
Checksum string `json:"checksum,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// AddonsStatus defines the observed state of the different Addons.
type AddonsStatus struct {
CoreDNS AddonStatus `json:"coreDNS,omitempty"`
KubeProxy AddonStatus `json:"kubeProxy,omitempty"`
Konnectivity KonnectivityStatus `json:"konnectivity,omitempty"`
}
// TenantControlPlaneStatus defines the observed state of TenantControlPlane.
type TenantControlPlaneStatus struct {
// Storage Status contains information about Kubernetes storage system
Storage StorageStatus `json:"storage,omitempty"`
// Certificates contains information about the different certificates
// that are necessary to run a kubernetes control plane
Certificates CertificatesStatus `json:"certificates,omitempty"`
// KubeConfig contains information about the kubenconfigs that control plane pieces need
KubeConfig KubeconfigsStatus `json:"kubeconfig,omitempty"`
// Kubernetes contains information about the reconciliation of the required Kubernetes resources deployed in the admin cluster
Kubernetes KubernetesStatus `json:"kubernetesResources,omitempty"`
// KubeadmConfig contains the status of the configuration required by kubeadm
KubeadmConfig KubeadmConfigStatus `json:"kubeadmconfig,omitempty"`
// KubeadmPhase contains the status of the kubeadm phases action
KubeadmPhase KubeadmPhasesStatus `json:"kubeadmPhase,omitempty"`
// ControlPlaneEndpoint contains the status of the kubernetes control plane
ControlPlaneEndpoint string `json:"controlPlaneEndpoint,omitempty"`
// Addons contains the status of the different Addons
Addons AddonsStatus `json:"addons,omitempty"`
}
// KubernetesStatus defines the status of the resources deployed in the management cluster,
// such as Deployment and Service.
type KubernetesStatus struct {
// KubernetesVersion contains the information regarding the running Kubernetes version, and its upgrade status.
Version KubernetesVersion `json:"version,omitempty"`
Deployment KubernetesDeploymentStatus `json:"deployment,omitempty"`
Service KubernetesServiceStatus `json:"service,omitempty"`
Ingress *KubernetesIngressStatus `json:"ingress,omitempty"`
}
// +kubebuilder:validation:Enum=Provisioning;Upgrading;Ready;NotReady
type KubernetesVersionStatus string
var (
VersionProvisioning KubernetesVersionStatus = "Provisioning"
VersionUpgrading KubernetesVersionStatus = "Upgrading"
VersionReady KubernetesVersionStatus = "Ready"
VersionNotReady KubernetesVersionStatus = "NotReady"
)
type KubernetesVersion struct {
// Version is the running Kubernetes version of the Tenant Control Plane.
Version string `json:"version,omitempty"`
// +kubebuilder:default=Provisioning
// Status returns the current status of the Kubernetes version, such as its provisioning state, or completed upgrade.
Status *KubernetesVersionStatus `json:"status,omitempty"`
}
// KubernetesDeploymentStatus defines the status for the Tenant Control Plane Deployment in the management cluster.
type KubernetesDeploymentStatus struct {
appsv1.DeploymentStatus `json:",inline"`
// Selector is the label selector used to group the Tenant Control Plane Pods used by the scale subresource.
Selector string `json:"selector"`
// The name of the Deployment for the given cluster.
Name string `json:"name"`
// The namespace which the Deployment for the given cluster is deployed.
Namespace string `json:"namespace"`
// Last time when deployment was updated
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// KubernetesServiceStatus defines the status for the Tenant Control Plane Service in the management cluster.
type KubernetesServiceStatus struct {
corev1.ServiceStatus `json:",inline"`
// The name of the Service for the given cluster.
Name string `json:"name"`
// The namespace which the Service for the given cluster is deployed.
Namespace string `json:"namespace"`
// The port where the service is running
Port int32 `json:"port"`
}
// KubernetesIngressStatus defines the status for the Tenant Control Plane Ingress in the management cluster.
type KubernetesIngressStatus struct {
networkingv1.IngressStatus `json:",inline"`
// The name of the Ingress for the given cluster.
Name string `json:"name"`
// The namespace which the Ingress for the given cluster is deployed.
Namespace string `json:"namespace"`
}

View File

@@ -4,12 +4,8 @@
package v1alpha1
import (
appv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/clastix/kamaji/internal/etcd"
)
// NetworkProfileSpec defines the desired state of NetworkProfile.
@@ -22,15 +18,18 @@ type NetworkProfileSpec struct {
AllowAddressAsExternalIP bool `json:"allowAddressAsExternalIP,omitempty"`
// Port where API server of will be exposed
// +kubebuilder:default=6443
Port int32 `json:"port"`
// Domain of the tenant control plane
Domain string `json:"domain"`
Port int32 `json:"port,omitempty"`
// CertSANs sets extra Subject Alternative Names (SANs) for the API Server signing certificate.
// Use this field to add additional hostnames when exposing the Tenant Control Plane with third solutions.
CertSANs []string `json:"certSANs,omitempty"`
// Kubernetes Service
ServiceCIDR string `json:"serviceCidr"`
// +kubebuilder:default="10.96.0.0/16"
ServiceCIDR string `json:"serviceCidr,omitempty"`
// CIDR for Kubernetes Pods
PodCIDR string `json:"podCidr"`
DNSServiceIPs []string `json:"dnsServiceIPs"`
// +kubebuilder:default="10.244.0.0/16"
PodCIDR string `json:"podCidr,omitempty"`
// +kubebuilder:default={"10.96.0.10"}
DNSServiceIPs []string `json:"dnsServiceIPs,omitempty"`
}
type KubeletSpec struct {
@@ -65,23 +64,58 @@ type ControlPlane struct {
// Defining the options for the Tenant Control Plane Service resource.
Service ServiceSpec `json:"service"`
// Defining the options for an Optional Ingress which will expose API Server of the Tenant Control Plane
Ingress IngressSpec `json:"ingress,omitempty"`
Ingress *IngressSpec `json:"ingress,omitempty"`
}
// IngressSpec defines the options for the ingress which will expose API Server of the Tenant Control Plane.
type IngressSpec struct {
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
Enabled bool `json:"enabled"`
IngressClassName string `json:"ingressClassName,omitempty"`
// Hostname is an optional field which will be used as Ingress's Host. If it is not defined,
// Ingress's host will be "<tenant>.<namespace>.<domain>", where domain is specified under NetworkProfileSpec
Hostname string `json:"hostname,omitempty"`
}
type ControlPlaneComponentsResources struct {
APIServer *corev1.ResourceRequirements `json:"apiServer,omitempty"`
ControllerManager *corev1.ResourceRequirements `json:"controllerManager,omitempty"`
Scheduler *corev1.ResourceRequirements `json:"scheduler,omitempty"`
}
type DeploymentSpec struct {
// +kubebuilder:default=2
Replicas int32 `json:"replicas,omitempty"`
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
Replicas int32 `json:"replicas,omitempty"`
// NodeSelector is a selector which must be true for the pod to fit on a node.
// Selector which must match a node's labels for the pod to be scheduled on that node.
// More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// If specified, the Tenant Control Plane pod's tolerations.
// More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
// If specified, the Tenant Control Plane pod's scheduling constraints.
// More info: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/
Affinity *corev1.Affinity `json:"affinity,omitempty"`
// TopologySpreadConstraints describes how the Tenant Control Plane pods ought to spread across topology
// domains. Scheduler will schedule pods in a way which abides by the constraints.
// In case of nil underlying LabelSelector, the Kamaji one for the given Tenant Control Plane will be used.
// All topologySpreadConstraints are ANDed.
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
// Resources defines the amount of memory and CPU to allocate to each component of the Control Plane
// (kube-apiserver, controller-manager, and scheduler).
Resources *ControlPlaneComponentsResources `json:"resources,omitempty"`
// ExtraArgs allows adding additional arguments to the Control Plane components,
// such as kube-apiserver, controller-manager, and scheduler.
ExtraArgs *ControlPlaneExtraArgs `json:"extraArgs,omitempty"`
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
}
// ControlPlaneExtraArgs allows specifying additional arguments to the Control Plane components.
type ControlPlaneExtraArgs struct {
APIServer []string `json:"apiServer,omitempty"`
ControllerManager []string `json:"controllerManager,omitempty"`
Scheduler []string `json:"scheduler,omitempty"`
// Available only if Kamaji is running using Kine as backing storage.
Kine []string `json:"kine,omitempty"`
}
type ServiceSpec struct {
@@ -90,182 +124,67 @@ type ServiceSpec struct {
ServiceType ServiceType `json:"serviceType"`
}
// AddonSpec defines the spec for every addon.
type AddonSpec struct {
ImageOverrideTrait `json:",inline"`
}
type ImageOverrideTrait struct {
// ImageRepository sets the container registry to pull images from.
// if not set, the default ImageRepository will be used instead.
ImageRepository string `json:"imageRepository,omitempty"`
// ImageTag allows to specify a tag for the image.
// In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
ImageTag string `json:"imageTag,omitempty"`
}
// KonnectivitySpec defines the spec for Konnectivity.
type KonnectivitySpec struct {
// Port of Konnectivity proxy server.
ProxyPort int32 `json:"proxyPort"`
// Version for Konnectivity server and agent.
// +kubebuilder:default=v0.0.32
Version string `json:"version,omitempty"`
// ServerImage defines the container image for Konnectivity's server.
// +kubebuilder:default=registry.k8s.io/kas-network-proxy/proxy-server
ServerImage string `json:"serverImage,omitempty"`
// AgentImage defines the container image for Konnectivity's agent.
// +kubebuilder:default=registry.k8s.io/kas-network-proxy/proxy-agent
AgentImage string `json:"agentImage,omitempty"`
// Resources define the amount of CPU and memory to allocate to the Konnectivity server.
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
}
// AddonsSpec defines the enabled addons and their features.
type AddonsSpec struct {
// Enables the DNS addon in the Tenant Cluster.
// The registry and the tag are configurable, the image is hard-coded to `coredns`.
CoreDNS *AddonSpec `json:"coreDNS,omitempty"`
// Enables the Konnectivity addon in the Tenant Cluster, required if the worker nodes are in a different network.
Konnectivity *KonnectivitySpec `json:"konnectivity,omitempty"`
// Enables the kube-proxy addon in the Tenant Cluster.
// The registry and the tag are configurable, the image is hard-coded to `kube-proxy`.
KubeProxy *AddonSpec `json:"kubeProxy,omitempty"`
}
// TenantControlPlaneSpec defines the desired state of TenantControlPlane.
type TenantControlPlaneSpec struct {
// DataStore allows to specify a DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
// This parameter is optional and acts as an override over the default one which is used by the Kamaji Operator.
// Migration from a different DataStore to another one is not yet supported and the reconciliation will be blocked.
DataStore string `json:"dataStore,omitempty"`
ControlPlane ControlPlane `json:"controlPlane"`
// Kubernetes specification for tenant control plane
Kubernetes KubernetesSpec `json:"kubernetes"`
// NetworkProfile specifies how the network is
NetworkProfile NetworkProfileSpec `json:"networkProfile,omitempty"`
}
// ETCDAPIServerCertificate defines the observed state of ETCD Certificate for API server.
type APIServerCertificatesStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// ETCDAPIServerCertificate defines the observed state of ETCD Certificate for API server.
type ETCDCertificateStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// ETCDAPIServerCertificate defines the observed state of ETCD Certificate for API server.
type ETCDCertificatesStatus struct {
APIServer ETCDCertificateStatus `json:"apiServer,omitempty"`
CA ETCDCertificateStatus `json:"ca,omitempty"`
}
// CertificatePrivateKeyPair defines the status.
type CertificatePrivateKeyPairStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// CertificatePrivateKeyPair defines the status.
type PublicKeyPrivateKeyPairStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// ETCDCertificates defines the observed state of ETCD Certificates.
type CertificatesStatus struct {
CA CertificatePrivateKeyPairStatus `json:"ca,omitempty"`
APIServer CertificatePrivateKeyPairStatus `json:"apiServer,omitempty"`
APIServerKubeletClient CertificatePrivateKeyPairStatus `json:"apiServerKubeletClient,omitempty"`
FrontProxyCA CertificatePrivateKeyPairStatus `json:"frontProxyCA,omitempty"`
FrontProxyClient CertificatePrivateKeyPairStatus `json:"frontProxyClient,omitempty"`
SA PublicKeyPrivateKeyPairStatus `json:"sa,omitempty"`
ETCD *ETCDCertificatesStatus `json:"etcd,omitempty"`
}
// ETCDStatus defines the observed state of ETCDStatus.
type ETCDStatus struct {
Role etcd.Role `json:"role,omitempty"`
User etcd.User `json:"user,omitempty"`
}
// StorageStatus defines the observed state of StorageStatus.
type StorageStatus struct {
ETCD *ETCDStatus `json:"etcd,omitempty"`
}
// TenantControlPlaneKubeconfigsStatus contains information about a the generated kubeconfig.
type KubeconfigStatus struct {
SecretName string `json:"secretName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// TenantControlPlaneKubeconfigsStatus stores information about all the generated kubeconfigs.
type KubeconfigsStatus struct {
Admin KubeconfigStatus `json:"admin,omitempty"`
ControllerManager KubeconfigStatus `json:"controlerManager,omitempty"`
Scheduler KubeconfigStatus `json:"scheduler,omitempty"`
}
// KubeadmConfigStatus contains the status of the configuration required by kubeadm.
type KubeadmConfigStatus struct {
ConfigmapName string `json:"configmapName,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
ResourceVersion string `json:"resourceVersion"`
}
// KubeadmPhasesStatus contains the status of of a kubeadm phase action.
type KubeadmPhaseStatus struct {
KubeadmConfigResourceVersion string `json:"kubeadmConfigResourceVersion,omitempty"`
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
}
// KubeadmPhasesStatus contains the status of the different kubeadm phases action.
type KubeadmPhasesStatus struct {
UploadConfigKubeadm KubeadmPhaseStatus `json:"uploadConfigKubeadm"`
UploadConfigKubelet KubeadmPhaseStatus `json:"uploadConfigKubelet"`
AddonCoreDNS KubeadmPhaseStatus `json:"addonCoreDNS"`
AddonKubeProxy KubeadmPhaseStatus `json:"addonKubeProxy"`
BootstrapToken KubeadmPhaseStatus `json:"bootstrapToken"`
}
// TenantControlPlaneStatus defines the observed state of TenantControlPlane.
type TenantControlPlaneStatus struct {
// Storage Status contains information about Kubernetes storage system
Storage StorageStatus `json:"storage,omitempty"`
// Certificates contains information about the different certificates
// that are necessary to run a kubernetes control plane
Certificates CertificatesStatus `json:"certificates,omitempty"`
// KubeConfig contains information about the kubenconfigs that control plane pieces need
KubeConfig KubeconfigsStatus `json:"kubeconfig,omitempty"`
// Kubernetes contains information about the reconciliation of the required Kubernetes resources deployed in the admin cluster
Kubernetes KubernetesStatus `json:"kubernetesResources,omitempty"`
// KubeadmConfig contains the status of the configuration required by kubeadm
KubeadmConfig KubeadmConfigStatus `json:"kubeadmconfig,omitempty"`
// KubeadmPhase contains the status of the kubeadm phases action
KubeadmPhase KubeadmPhasesStatus `json:"kubeadmPhase,omitempty"`
// ControlPlaneEndpoint contains the status of the kubernetes control plane
ControlPlaneEndpoint string `json:"controlPlaneEndpoint,omitempty"`
}
// KubernetesStatus defines the status of the resources deployed in the management cluster,
// such as Deployment and Service.
type KubernetesStatus struct {
// KubernetesVersion contains the information regarding the running Kubernetes version, and its upgrade status.
Version KubernetesVersion `json:"version,omitempty"`
Deployment KubernetesDeploymentStatus `json:"deployment,omitempty"`
Service KubernetesServiceStatus `json:"service,omitempty"`
Ingress KubernetesIngressStatus `json:"ingress,omitempty"`
}
// +kubebuilder:validation:Enum=Provisioning;Upgrading;Ready;NotReady
type KubernetesVersionStatus string
var (
VersionProvisioning KubernetesVersionStatus = "Provisioning"
VersionUpgrading KubernetesVersionStatus = "Upgrading"
VersionReady KubernetesVersionStatus = "Ready"
VersionNotReady KubernetesVersionStatus = "NotReady"
)
type KubernetesVersion struct {
// Version is the running Kubernetes version of the Tenant Control Plane.
Version string `json:"version,omitempty"`
// +kubebuilder:default=Provisioning
// Status returns the current status of the Kubernetes version, such as its provisioning state, or completed upgrade.
Status *KubernetesVersionStatus `json:"status"`
}
// KubernetesDeploymentStatus defines the status for the Tenant Control Plane Deployment in the management cluster.
type KubernetesDeploymentStatus struct {
appv1.DeploymentStatus `json:",inline"`
// The name of the Deployment for the given cluster.
Name string `json:"name"`
// The namespace which the Deployment for the given cluster is deployed.
Namespace string `json:"namespace"`
}
// KubernetesServiceStatus defines the status for the Tenant Control Plane Service in the management cluster.
type KubernetesServiceStatus struct {
corev1.ServiceStatus `json:",inline"`
// The name of the Service for the given cluster.
Name string `json:"name"`
// The namespace which the Service for the given cluster is deployed.
Namespace string `json:"namespace"`
// The port where the service is running
Port int32 `json:"port"`
}
// KubernetesIngressStatus defines the status for the Tenant Control Plane Ingress in the management cluster.
type KubernetesIngressStatus struct {
networkingv1.IngressStatus `json:",inline"`
// The name of the Ingress for the given cluster.
Name string `json:"name"`
// The namespace which the Ingress for the given cluster is deployed.
Namespace string `json:"namespace"`
// Addons contain which addons are enabled
Addons AddonsSpec `json:"addons,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.controlPlane.deployment.replicas,statuspath=.status.kubernetesResources.deployment.replicas,selectorpath=.status.kubernetesResources.deployment.selector
// +kubebuilder:resource:shortName=tcp
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.kubernetes.version",description="Kubernetes version"
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.kubernetesResources.version.status",description="Kubernetes version"

View File

@@ -9,6 +9,7 @@
package v1alpha1
import (
"k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -57,6 +58,86 @@ func (in *AdditionalMetadata) DeepCopy() *AdditionalMetadata {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddonSpec) DeepCopyInto(out *AddonSpec) {
*out = *in
out.ImageOverrideTrait = in.ImageOverrideTrait
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonSpec.
func (in *AddonSpec) DeepCopy() *AddonSpec {
if in == nil {
return nil
}
out := new(AddonSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddonStatus) DeepCopyInto(out *AddonStatus) {
*out = *in
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonStatus.
func (in *AddonStatus) DeepCopy() *AddonStatus {
if in == nil {
return nil
}
out := new(AddonStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddonsSpec) DeepCopyInto(out *AddonsSpec) {
*out = *in
if in.CoreDNS != nil {
in, out := &in.CoreDNS, &out.CoreDNS
*out = new(AddonSpec)
**out = **in
}
if in.Konnectivity != nil {
in, out := &in.Konnectivity, &out.Konnectivity
*out = new(KonnectivitySpec)
(*in).DeepCopyInto(*out)
}
if in.KubeProxy != nil {
in, out := &in.KubeProxy, &out.KubeProxy
*out = new(AddonSpec)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsSpec.
func (in *AddonsSpec) DeepCopy() *AddonsSpec {
if in == nil {
return nil
}
out := new(AddonsSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddonsStatus) DeepCopyInto(out *AddonsStatus) {
*out = *in
in.CoreDNS.DeepCopyInto(&out.CoreDNS)
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
in.Konnectivity.DeepCopyInto(&out.Konnectivity)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsStatus.
func (in *AddonsStatus) DeepCopy() *AddonsStatus {
if in == nil {
return nil
}
out := new(AddonsStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in AdmissionControllers) DeepCopyInto(out *AdmissionControllers) {
{
@@ -76,6 +157,44 @@ func (in AdmissionControllers) DeepCopy() AdmissionControllers {
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BasicAuth) DeepCopyInto(out *BasicAuth) {
*out = *in
in.Username.DeepCopyInto(&out.Username)
in.Password.DeepCopyInto(&out.Password)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BasicAuth.
func (in *BasicAuth) DeepCopy() *BasicAuth {
if in == nil {
return nil
}
out := new(BasicAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CertKeyPair) DeepCopyInto(out *CertKeyPair) {
*out = *in
in.Certificate.DeepCopyInto(&out.Certificate)
if in.PrivateKey != nil {
in, out := &in.PrivateKey, &out.PrivateKey
*out = new(ContentRef)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertKeyPair.
func (in *CertKeyPair) DeepCopy() *CertKeyPair {
if in == nil {
return nil
}
out := new(CertKeyPair)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CertificatePrivateKeyPairStatus) DeepCopyInto(out *CertificatePrivateKeyPairStatus) {
*out = *in
@@ -118,12 +237,58 @@ func (in *CertificatesStatus) DeepCopy() *CertificatesStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClientCertificate) DeepCopyInto(out *ClientCertificate) {
*out = *in
in.Certificate.DeepCopyInto(&out.Certificate)
in.PrivateKey.DeepCopyInto(&out.PrivateKey)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientCertificate.
func (in *ClientCertificate) DeepCopy() *ClientCertificate {
if in == nil {
return nil
}
out := new(ClientCertificate)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContentRef) DeepCopyInto(out *ContentRef) {
*out = *in
if in.Content != nil {
in, out := &in.Content, &out.Content
*out = make([]byte, len(*in))
copy(*out, *in)
}
if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef
*out = new(SecretReference)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContentRef.
func (in *ContentRef) DeepCopy() *ContentRef {
if in == nil {
return nil
}
out := new(ContentRef)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlane) DeepCopyInto(out *ControlPlane) {
*out = *in
in.Deployment.DeepCopyInto(&out.Deployment)
in.Service.DeepCopyInto(&out.Service)
in.Ingress.DeepCopyInto(&out.Ingress)
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = new(IngressSpec)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlane.
@@ -136,9 +301,262 @@ func (in *ControlPlane) DeepCopy() *ControlPlane {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlaneComponentsResources) DeepCopyInto(out *ControlPlaneComponentsResources) {
*out = *in
if in.APIServer != nil {
in, out := &in.APIServer, &out.APIServer
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
if in.ControllerManager != nil {
in, out := &in.ControllerManager, &out.ControllerManager
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
if in.Scheduler != nil {
in, out := &in.Scheduler, &out.Scheduler
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponentsResources.
func (in *ControlPlaneComponentsResources) DeepCopy() *ControlPlaneComponentsResources {
if in == nil {
return nil
}
out := new(ControlPlaneComponentsResources)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlaneExtraArgs) DeepCopyInto(out *ControlPlaneExtraArgs) {
*out = *in
if in.APIServer != nil {
in, out := &in.APIServer, &out.APIServer
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ControllerManager != nil {
in, out := &in.ControllerManager, &out.ControllerManager
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Scheduler != nil {
in, out := &in.Scheduler, &out.Scheduler
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Kine != nil {
in, out := &in.Kine, &out.Kine
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneExtraArgs.
func (in *ControlPlaneExtraArgs) DeepCopy() *ControlPlaneExtraArgs {
if in == nil {
return nil
}
out := new(ControlPlaneExtraArgs)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStore) DeepCopyInto(out *DataStore) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStore.
func (in *DataStore) DeepCopy() *DataStore {
if in == nil {
return nil
}
out := new(DataStore)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataStore) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreCertificateStatus) DeepCopyInto(out *DataStoreCertificateStatus) {
*out = *in
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreCertificateStatus.
func (in *DataStoreCertificateStatus) DeepCopy() *DataStoreCertificateStatus {
if in == nil {
return nil
}
out := new(DataStoreCertificateStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreConfigStatus) DeepCopyInto(out *DataStoreConfigStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreConfigStatus.
func (in *DataStoreConfigStatus) DeepCopy() *DataStoreConfigStatus {
if in == nil {
return nil
}
out := new(DataStoreConfigStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreList) DeepCopyInto(out *DataStoreList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]DataStore, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreList.
func (in *DataStoreList) DeepCopy() *DataStoreList {
if in == nil {
return nil
}
out := new(DataStoreList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataStoreList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreSetupStatus) DeepCopyInto(out *DataStoreSetupStatus) {
*out = *in
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreSetupStatus.
func (in *DataStoreSetupStatus) DeepCopy() *DataStoreSetupStatus {
if in == nil {
return nil
}
out := new(DataStoreSetupStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreSpec) DeepCopyInto(out *DataStoreSpec) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.BasicAuth != nil {
in, out := &in.BasicAuth, &out.BasicAuth
*out = new(BasicAuth)
(*in).DeepCopyInto(*out)
}
in.TLSConfig.DeepCopyInto(&out.TLSConfig)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreSpec.
func (in *DataStoreSpec) DeepCopy() *DataStoreSpec {
if in == nil {
return nil
}
out := new(DataStoreSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataStoreStatus) DeepCopyInto(out *DataStoreStatus) {
*out = *in
if in.UsedBy != nil {
in, out := &in.UsedBy, &out.UsedBy
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataStoreStatus.
func (in *DataStoreStatus) DeepCopy() *DataStoreStatus {
if in == nil {
return nil
}
out := new(DataStoreStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) {
*out = *in
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Tolerations != nil {
in, out := &in.Tolerations, &out.Tolerations
*out = make([]v1.Toleration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Affinity != nil {
in, out := &in.Affinity, &out.Affinity
*out = new(v1.Affinity)
(*in).DeepCopyInto(*out)
}
if in.TopologySpreadConstraints != nil {
in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints
*out = make([]v1.TopologySpreadConstraint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = new(ControlPlaneComponentsResources)
(*in).DeepCopyInto(*out)
}
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = new(ControlPlaneExtraArgs)
(*in).DeepCopyInto(*out)
}
in.AdditionalMetadata.DeepCopyInto(&out.AdditionalMetadata)
}
@@ -186,18 +604,32 @@ func (in *ETCDCertificatesStatus) DeepCopy() *ETCDCertificatesStatus {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ETCDStatus) DeepCopyInto(out *ETCDStatus) {
func (in *ExternalKubernetesObjectStatus) DeepCopyInto(out *ExternalKubernetesObjectStatus) {
*out = *in
in.Role.DeepCopyInto(&out.Role)
in.User.DeepCopyInto(&out.User)
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ETCDStatus.
func (in *ETCDStatus) DeepCopy() *ETCDStatus {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalKubernetesObjectStatus.
func (in *ExternalKubernetesObjectStatus) DeepCopy() *ExternalKubernetesObjectStatus {
if in == nil {
return nil
}
out := new(ETCDStatus)
out := new(ExternalKubernetesObjectStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageOverrideTrait) DeepCopyInto(out *ImageOverrideTrait) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageOverrideTrait.
func (in *ImageOverrideTrait) DeepCopy() *ImageOverrideTrait {
if in == nil {
return nil
}
out := new(ImageOverrideTrait)
in.DeepCopyInto(out)
return out
}
@@ -218,6 +650,63 @@ func (in *IngressSpec) DeepCopy() *IngressSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KonnectivityConfigMap) DeepCopyInto(out *KonnectivityConfigMap) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivityConfigMap.
func (in *KonnectivityConfigMap) DeepCopy() *KonnectivityConfigMap {
if in == nil {
return nil
}
out := new(KonnectivityConfigMap)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KonnectivitySpec) DeepCopyInto(out *KonnectivitySpec) {
*out = *in
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivitySpec.
func (in *KonnectivitySpec) DeepCopy() *KonnectivitySpec {
if in == nil {
return nil
}
out := new(KonnectivitySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KonnectivityStatus) DeepCopyInto(out *KonnectivityStatus) {
*out = *in
out.ConfigMap = in.ConfigMap
in.Certificate.DeepCopyInto(&out.Certificate)
in.Kubeconfig.DeepCopyInto(&out.Kubeconfig)
in.ServiceAccount.DeepCopyInto(&out.ServiceAccount)
in.ClusterRoleBinding.DeepCopyInto(&out.ClusterRoleBinding)
in.Agent.DeepCopyInto(&out.Agent)
in.Service.DeepCopyInto(&out.Service)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivityStatus.
func (in *KonnectivityStatus) DeepCopy() *KonnectivityStatus {
if in == nil {
return nil
}
out := new(KonnectivityStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeadmConfigStatus) DeepCopyInto(out *KubeadmConfigStatus) {
*out = *in
@@ -255,8 +744,6 @@ func (in *KubeadmPhasesStatus) DeepCopyInto(out *KubeadmPhasesStatus) {
*out = *in
in.UploadConfigKubeadm.DeepCopyInto(&out.UploadConfigKubeadm)
in.UploadConfigKubelet.DeepCopyInto(&out.UploadConfigKubelet)
in.AddonCoreDNS.DeepCopyInto(&out.AddonCoreDNS)
in.AddonKubeProxy.DeepCopyInto(&out.AddonKubeProxy)
in.BootstrapToken.DeepCopyInto(&out.BootstrapToken)
}
@@ -323,6 +810,7 @@ func (in *KubeletSpec) DeepCopy() *KubeletSpec {
func (in *KubernetesDeploymentStatus) DeepCopyInto(out *KubernetesDeploymentStatus) {
*out = *in
in.DeploymentStatus.DeepCopyInto(&out.DeploymentStatus)
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesDeploymentStatus.
@@ -394,7 +882,11 @@ func (in *KubernetesStatus) DeepCopyInto(out *KubernetesStatus) {
in.Version.DeepCopyInto(&out.Version)
in.Deployment.DeepCopyInto(&out.Deployment)
in.Service.DeepCopyInto(&out.Service)
in.Ingress.DeepCopyInto(&out.Ingress)
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = new(KubernetesIngressStatus)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesStatus.
@@ -430,6 +922,11 @@ func (in *KubernetesVersion) DeepCopy() *KubernetesVersion {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NetworkProfileSpec) DeepCopyInto(out *NetworkProfileSpec) {
*out = *in
if in.CertSANs != nil {
in, out := &in.CertSANs, &out.CertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DNSServiceIPs != nil {
in, out := &in.DNSServiceIPs, &out.DNSServiceIPs
*out = make([]string, len(*in))
@@ -463,6 +960,22 @@ func (in *PublicKeyPrivateKeyPairStatus) DeepCopy() *PublicKeyPrivateKeyPairStat
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SecretReference) DeepCopyInto(out *SecretReference) {
*out = *in
out.SecretReference = in.SecretReference
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretReference.
func (in *SecretReference) DeepCopy() *SecretReference {
if in == nil {
return nil
}
out := new(SecretReference)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) {
*out = *in
@@ -482,11 +995,9 @@ func (in *ServiceSpec) DeepCopy() *ServiceSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageStatus) DeepCopyInto(out *StorageStatus) {
*out = *in
if in.ETCD != nil {
in, out := &in.ETCD, &out.ETCD
*out = new(ETCDStatus)
(*in).DeepCopyInto(*out)
}
out.Config = in.Config
in.Setup.DeepCopyInto(&out.Setup)
in.Certificate.DeepCopyInto(&out.Certificate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageStatus.
@@ -499,6 +1010,23 @@ func (in *StorageStatus) DeepCopy() *StorageStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
*out = *in
in.CertificateAuthority.DeepCopyInto(&out.CertificateAuthority)
in.ClientCertificate.DeepCopyInto(&out.ClientCertificate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
func (in *TLSConfig) DeepCopy() *TLSConfig {
if in == nil {
return nil
}
out := new(TLSConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TenantControlPlane) DeepCopyInto(out *TenantControlPlane) {
*out = *in
@@ -564,6 +1092,7 @@ func (in *TenantControlPlaneSpec) DeepCopyInto(out *TenantControlPlaneSpec) {
in.ControlPlane.DeepCopyInto(&out.ControlPlane)
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
in.NetworkProfile.DeepCopyInto(&out.NetworkProfile)
in.Addons.DeepCopyInto(&out.Addons)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantControlPlaneSpec.
@@ -585,6 +1114,7 @@ func (in *TenantControlPlaneStatus) DeepCopyInto(out *TenantControlPlaneStatus)
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
in.KubeadmConfig.DeepCopyInto(&out.KubeadmConfig)
in.KubeadmPhase.DeepCopyInto(&out.KubeadmPhase)
in.Addons.DeepCopyInto(&out.Addons)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantControlPlaneStatus.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 93 KiB

1
assets/kamaji-logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="11.85 8.10 202.80 187.55"><title>Kamaji</title><path d="M32.1 13.7c-2.4.9-6.3 3.5-8.6 5.8-7.7 7.7-7.5 5-7.5 82.5 0 77.4-.2 74.8 7.5 82.5 7.7 7.8 4.2 7.5 90 7.5s82.3.3 90-7.5c7.7-7.7 7.5-5.1 7.5-82.5s.2-74.8-7.5-82.5c-7.8-7.8-4.1-7.5-90.4-7.4-66.7 0-77.2.3-81 1.6zm160.5 9.9c1.9.9 4.4 3.1 5.7 4.8l2.2 3.1v141l-2.2 3.1c-4.8 6.7-1.1 6.4-84.8 6.4s-80 .3-84.8-6.4l-2.2-3.1v-141l2.2-3.1c4.8-6.6.8-6.4 84.6-6.4 68 0 76.3.2 79.3 1.6z"/><path d="M90.1 33.7c-5.1 2.5-7.3 6.7-6.8 13.1.3 4.1 1 5.9 3.3 8.4s2.5 3 .9 2.3c-2-.7-25.1-4.6-29-4.9-1.1 0-2 .5-2 1.4 0 1.1-1.2 1.5-4.9 1.5-6.7 0-6.8 1.9-.4 4 8.2 2.7 9 3.4 3.3 3.5-5.3 0-8.2 1.1-7.1 2.8.7 1.2-2.7 2.2-8.1 2.2-7 0-6.5 2.4 1.1 5.1l3.9 1.4-2.9.5c-4.3.8-3.2 2.3 2.8 4.1l5.3 1.5-5.2 2.7c-8.2 4.2-8.3 5.8-.4 6.1 5.6.2 7.3 1.1 4.2 2.1-2.3.7-2.8 3.1-.9 3.7.7.3-.5 2-2.8 4-5.6 5.3-4 6.4 6.2 4.5 4.4-.8 8.1-1.3 8.3-1.2.2.2-1.3 2.4-3.3 4.8-2 2.4-3.6 4.7-3.6 5.2 0 .4 1.4.5 3 .3 2.9-.4 4 .5 2 1.7-.5.3-1 1.3-1 2.2 0 1.6 2.2 1.5 6.5-.3 1.7-.7 1.6-.2-.9 3-5.4 7.2.7 6.5 13.6-1.4 2.7-1.7 5.1-3 5.4-3 .3 0-.9 2.1-2.7 4.6-4.5 6.6-2.5 7.9 3.7 2.3 4.6-4.3 4.7-4.3 3-1.2-1.9 3.8-2.1 5.6-.4 5.1.6-.2 7.1-7.1 14.3-15.4 7.2-8.2 13.7-14.9 14.5-14.9.8 0 7.3 6.7 14.6 15 7.2 8.2 13.7 15.1 14.3 15.3 1.6.5 1.4-1.4-.5-5-1.6-3.2-1.6-3.2 3.2 1 6 5.1 7.8 4 3.5-2.2-1.8-2.5-3-4.6-2.7-4.6.3 0 2.7 1.3 5.4 3 12.9 7.9 19 8.6 13.6 1.4-2.5-3.2-2.6-3.7-.9-3 5.9 2.5 7.7 1.7 5.6-2.3-.9-1.5-.6-1.7 2-1.3 3.8.6 3.7-.5-.7-5.7-2-2.3-3.5-4.4-3.2-4.6.2-.2 2.1 0 4.3.4 13.9 3 16.4 1.8 9.8-4.3-2.1-1.9-3.2-3.6-2.5-3.6 2 0 1.4-2.8-.9-3.5-3.2-1-1.3-2 4.2-2.1 7.9-.2 7.8-1.9-.4-6.1l-5.2-2.7 5.4-1.6c6.4-1.8 7.9-4 2.9-4.1h-3.3l3.9-1.5c7.3-2.6 8.4-5.4 2.2-5.4-5.1 0-9.6-1.1-9-2.2 1.1-1.7-1.8-2.8-7.1-2.8-5.7-.1-4.9-.8 3.3-3.5 6.4-2.1 6.3-4-.4-4-3.7 0-4.9-.4-4.9-1.5 0-.9-.9-1.4-2-1.4-3.9.3-27 4.2-29 4.9-1.6.7-1.4.2.9-2.3 3.7-4 4.7-11.3 2.2-16.1-4.8-9.2-18.8-9.3-23.8 0-4.4 8.3.2 18.4 9.5 20.5 3 .6 2.8.8-5.5 4l-8.8 3.3-8.7-3.3c-8.1-3.2-8.4-3.4-5.5-4.1 1.7-.3 4.3-1.5 5.7-2.7 13.1-10.3.6-30.4-14.4-23.1zm77.6 98.4c-3.6 2.1-.8 7.7 3.2 6.4 2.1-.6 3.5-3.1 2.5-4.6-1.1-1.8-4-2.7-5.7-1.8zm8.3 3.9c0 1.9.5 2.1 6.3 1.8 4.7-.2 6.2-.7 6.2-1.8s-1.5-1.6-6.2-1.8c-5.8-.3-6.3-.1-6.3 1.8zm-135.6.3c-.2.7-.3 7.4-.2 14.8l.3 13.4 3.3.3c3.1.3 3.2.2 3.2-3.4 0-2.5.7-4.6 2.1-6l2.1-2.3 5 6c3.9 4.7 5.6 5.9 7.8 5.9 1.6 0 3.1-.3 3.3-.8.3-.4-2.1-4-5.4-8.1-3.2-4-5.9-7.6-5.9-8 0-.4 2.5-3.1 5.5-6.1 3-3 5.5-5.8 5.5-6.2 0-.4-1.5-.8-3.3-.8-2.8 0-4.4 1-9.6 6.5-3.5 3.6-6.5 6.5-6.7 6.5-.2 0-.4-2.9-.4-6.5V135h-3c-1.7 0-3.3.6-3.6 1.3zm31.2 7c-1.1.8-1.5 1.9-1 3 .5 1.4 1.3 1.6 4 1.1 4.2-.8 8.4.2 8.4 2 0 .8-1.8 1.5-5.1 1.9-6 .7-8.9 2.9-8.9 6.6 0 3.2.8 4.4 3.7 6 2.9 1.5 5.2 1.4 8.6-.3 2.3-1.3 2.7-1.3 2.7 0 0 .9 1.1 1.4 3 1.4h3v-8.6c0-8.1-.1-8.7-2.9-11.5-2.5-2.5-3.7-2.9-8.3-2.9-3 0-6.2.6-7.2 1.3zm11.2 13.9c-.2 1.7-1.1 2.4-3.2 2.6-3.3.4-5.1-1-4.3-3.2.4-1.1 1.9-1.6 4.2-1.6 3.2 0 3.6.3 3.3 2.2zm13.4-4l.3 11.3h6l.5-7.8c.5-7.6 1.5-9.6 4.7-9.7 3 0 4.3 3.2 4.3 10.6v7.4h3c3 0 3 0 3-5.9 0-7.3 1.2-10.7 4.1-11.6 3.8-1.3 5.9 2.5 5.9 10.6v6.9h6v-9c0-8.3-.2-9.3-2.5-11.5-2.9-3-9.8-3.5-12.7-.8-1.7 1.5-1.9 1.5-3.6 0-2.2-2-9.2-2.3-11.1-.5-1.1 1-1.4 1-1.8 0-.3-.6-1.8-1.2-3.4-1.2h-3l.3 11.2zm45.4-9.9c-1.1.8-1.5 1.9-1 3 .5 1.4 1.3 1.6 4 1.1 4.2-.8 8.4.2 8.4 2 0 .8-1.8 1.5-5.1 1.9-6 .7-8.9 2.9-8.9 6.6 0 3.2.8 4.4 3.7 6 2.9 1.5 5.2 1.4 8.6-.3 2.3-1.3 2.7-1.3 2.7 0 0 .9 1.1 1.4 3 1.4h3v-8.6c0-8.1-.1-8.7-2.9-11.5-2.5-2.5-3.7-2.9-8.3-2.9-3 0-6.2.6-7.2 1.3zm11.2 13.9c-.2 1.7-1.1 2.4-3.2 2.6-3.3.4-5.1-1-4.3-3.2.4-1.1 1.9-1.6 4.2-1.6 3.2 0 3.6.3 3.3 2.2zm13-2.5c-.3 12.8-.3 12.8-2.7 12.8-1.5 0-2.7.8-3.1 2-2 5.4 9.4 4.3 11.9-1.2.6-1.3 1.1-7.7 1.1-14.3v-12h-6.9l-.3 12.7zm13.4-1.5l.3 11.3h6v-22l-3.3-.3-3.3-.3.3 11.3z"/></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

26
charts/kamaji/Chart.yaml Normal file
View File

@@ -0,0 +1,26 @@
apiVersion: v2
appVersion: v0.1.1
description: Kamaji is a tool aimed to build and operate a Managed Kubernetes Service
with a fraction of the operational burden. With Kamaji, you can deploy and operate
hundreds of Kubernetes clusters as a hyper-scaler.
home: https://github.com/clastix/kamaji
icon: https://github.com/clastix/kamaji/raw/master/assets/kamaji-logo.png
kubeVersion: 1.21 - 1.25
maintainers:
- email: dario@tranchitella.eu
name: Dario Tranchitella
- email: me@maxgio.it
name: Massimiliano Giovagnoli
- email: me@bsctl.io
name: Adriano Pezzuto
- email: iam@mendrugory.com
name: Gonzalo Gabriel Jiménez Fuentes
name: kamaji
sources:
- https://github.com/clastix/kamaji
type: application
version: 0.10.0
annotations:
catalog.cattle.io/certified: partner
catalog.cattle.io/release-name: kamaji
catalog.cattle.io/display-name: Kamaji - Managed Kubernetes Service

141
charts/kamaji/README.md Normal file
View File

@@ -0,0 +1,141 @@
# kamaji
![Version: 0.10.0](https://img.shields.io/badge/Version-0.10.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.1.1](https://img.shields.io/badge/AppVersion-v0.1.1-informational?style=flat-square)
Kamaji is a tool aimed to build and operate a Managed Kubernetes Service with a fraction of the operational burden. With Kamaji, you can deploy and operate hundreds of Kubernetes clusters as a hyper-scaler.
## Maintainers
| Name | Email | Url |
| ---- | ------ | --- |
| Dario Tranchitella | <dario@tranchitella.eu> | |
| Massimiliano Giovagnoli | <me@maxgio.it> | |
| Adriano Pezzuto | <me@bsctl.io> | |
| Gonzalo Gabriel Jiménez Fuentes | <iam@mendrugory.com> | |
## Source Code
* <https://github.com/clastix/kamaji>
## Requirements
Kubernetes: `1.21 - 1.25`
[Kamaji](https://github.com/clastix/kamaji) requires a [multi-tenant `etcd`](https://github.com/clastix/kamaji-internal/blob/master/deploy/getting-started-with-kamaji.md#setup-internal-multi-tenant-etcd) cluster.
This Helm Chart starting from v0.1.1 provides the installation of an internal `etcd` in order to streamline the local test. If you'd like to use an externally managed etcd instance, you can specify the overrides and by setting the value `etcd.deploy=false`.
> For production use an externally managed `etcd` is highly recommended, the `etcd` addon offered by this Chart is not considered production-grade.
## Install Kamaji
To install the Chart with the release name `kamaji`:
helm upgrade --install --namespace kamaji-system --create-namespace clastix/kamaji
Show the status:
helm status kamaji -n kamaji-system
Upgrade the Chart
helm upgrade kamaji -n kamaji-system clastix/kamaji
Uninstall the Chart
helm uninstall kamaji -n kamaji-system
## Customize the installation
There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`.
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
Specify your overrides file when you install the Chart:
helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --values myvalues.yaml
The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that werent overridden will keep their defaults.
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --set etcd.deploy=false
Here the values you can override:
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | Kubernetes affinity rules to apply to Kamaji controller pods |
| configPath | string | `"./kamaji.yaml"` | Configuration file path alternative. (default "./kamaji.yaml") |
| datastore.basicAuth.passwordSecret.keyPath | string | `nil` | The Secret key where the data is stored. |
| datastore.basicAuth.passwordSecret.name | string | `nil` | The name of the Secret containing the password used to connect to the relational database. |
| datastore.basicAuth.passwordSecret.namespace | string | `nil` | The namespace of the Secret containing the password used to connect to the relational database. |
| datastore.basicAuth.usernameSecret.keyPath | string | `nil` | The Secret key where the data is stored. |
| datastore.basicAuth.usernameSecret.name | string | `nil` | The name of the Secret containing the username used to connect to the relational database. |
| datastore.basicAuth.usernameSecret.namespace | string | `nil` | The namespace of the Secret containing the username used to connect to the relational database. |
| datastore.driver | string | `"etcd"` | (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd). |
| datastore.endpoints | list | `[]` | (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. |
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty defaults to `default` |
| datastore.tlsConfig.certificateAuthority.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
| datastore.tlsConfig.certificateAuthority.certificate.name | string | `nil` | Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.certificate.namespace | string | `nil` | Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. |
| datastore.tlsConfig.certificateAuthority.privateKey.name | string | `nil` | Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.privateKey.namespace | string | `nil` | Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
| datastore.tlsConfig.clientCertificate.certificate.name | string | `nil` | Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.certificate.namespace | string | `nil` | Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. |
| datastore.tlsConfig.clientCertificate.privateKey.name | string | `nil` | Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.privateKey.namespace | string | `nil` | Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
| etcd.compactionInterval | int | `0` | ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) |
| etcd.deploy | bool | `true` | Install an etcd with enabled multi-tenancy along with Kamaji |
| etcd.image | object | `{"pullPolicy":"IfNotPresent","repository":"quay.io/coreos/etcd","tag":"v3.5.4"}` | Install specific etcd image |
| etcd.livenessProbe | object | `{"failureThreshold":8,"httpGet":{"path":"/health?serializable=true","port":2381,"scheme":"HTTP"},"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":15}` | The livenessProbe for the etcd container |
| etcd.overrides.caSecret.name | string | `"etcd-certs"` | Name of the secret which contains CA's certificate and private key. (default: "etcd-certs") |
| etcd.overrides.caSecret.namespace | string | `"kamaji-system"` | Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system") |
| etcd.overrides.clientSecret.name | string | `"root-client-certs"` | Name of the secret which contains ETCD client certificates. (default: "root-client-certs") |
| etcd.overrides.clientSecret.namespace | string | `"kamaji-system"` | Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system") |
| etcd.overrides.endpoints | object | `{"etcd-0":"etcd-0.etcd.kamaji-system.svc.cluster.local","etcd-1":"etcd-1.etcd.kamaji-system.svc.cluster.local","etcd-2":"etcd-2.etcd.kamaji-system.svc.cluster.local"}` | (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value. |
| etcd.peerApiPort | int | `2380` | The peer API port which servers are listening to. |
| etcd.persistence.accessModes[0] | string | `"ReadWriteOnce"` | |
| etcd.persistence.size | string | `"10Gi"` | |
| etcd.persistence.storageClass | string | `""` | |
| etcd.port | int | `2379` | The client request port. |
| etcd.serviceAccount.create | bool | `true` | Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) |
| etcd.serviceAccount.name | string | `""` | Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") |
| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones |
| fullnameOverride | string | `""` | |
| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") |
| image.pullPolicy | string | `"Always"` | |
| image.repository | string | `"clastix/kamaji"` | The container image of the Kamaji controller. |
| image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. |
| imagePullSecrets | list | `[]` | |
| livenessProbe | object | `{"httpGet":{"path":"/healthz","port":"healthcheck"},"initialDelaySeconds":15,"periodSeconds":20}` | The livenessProbe for the controller container |
| loggingDevel.enable | bool | `false` | (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false) |
| metricsBindAddress | string | `":8080"` | (string) The address the metric endpoint binds to. (default ":8080") |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | Kubernetes node selector rules to schedule Kamaji controller |
| podAnnotations | object | `{}` | The annotations to apply to the Kamaji controller pods. |
| podSecurityContext | object | `{"runAsNonRoot":true}` | The securityContext to apply to the Kamaji controller pods. |
| readinessProbe | object | `{"httpGet":{"path":"/readyz","port":"healthcheck"},"initialDelaySeconds":5,"periodSeconds":10}` | The readinessProbe for the controller container |
| replicaCount | int | `1` | The number of the pod replicas for the Kamaji controller. |
| resources.limits.cpu | string | `"200m"` | |
| resources.limits.memory | string | `"100Mi"` | |
| resources.requests.cpu | string | `"100m"` | |
| resources.requests.memory | string | `"20Mi"` | |
| securityContext | object | `{"allowPrivilegeEscalation":false}` | The securityContext to apply to the Kamaji controller container only. It does not apply to the Kamaji RBAC proxy container. |
| service.port | int | `8443` | |
| service.type | string | `"ClusterIP"` | |
| serviceAccount.annotations | object | `{}` | |
| serviceAccount.create | bool | `true` | |
| serviceAccount.name | string | `"kamaji-controller-manager"` | |
| temporaryDirectoryPath | string | `"/tmp/kamaji"` | Directory which will be used to work with temporary files. (default "/tmp/kamaji") |
| tolerations | list | `[]` | Kubernetes node taints that the Kamaji controller pods would tolerate |
## Installing and managing etcd as DataStore
Kamaji supports multiple data store, although `etcd` is the default one: thus, an initial cluster will be created upon the Chart installation.
The `DataStore` resource can be configured with the proper values in case of overrides when using a different driver, otherwise all the required data will be inherited by the Chart values.

View File

@@ -0,0 +1,62 @@
{{ template "chart.header" . }}
{{ template "chart.deprecationWarning" . }}
{{ template "chart.badgesSection" . }}
{{ template "chart.description" . }}
{{ template "chart.maintainersSection" . }}
{{ template "chart.sourcesSection" . }}
{{ template "chart.requirementsSection" . }}
[Kamaji](https://github.com/clastix/kamaji) requires a [multi-tenant `etcd`](https://github.com/clastix/kamaji-internal/blob/master/deploy/getting-started-with-kamaji.md#setup-internal-multi-tenant-etcd) cluster.
This Helm Chart starting from v0.1.1 provides the installation of an internal `etcd` in order to streamline the local test. If you'd like to use an externally managed etcd instance, you can specify the overrides and by setting the value `etcd.deploy=false`.
> For production use an externally managed `etcd` is highly recommended, the `etcd` addon offered by this Chart is not considered production-grade.
## Install Kamaji
To install the Chart with the release name `kamaji`:
helm upgrade --install --namespace kamaji-system --create-namespace clastix/kamaji
Show the status:
helm status kamaji -n kamaji-system
Upgrade the Chart
helm upgrade kamaji -n kamaji-system clastix/kamaji
Uninstall the Chart
helm uninstall kamaji -n kamaji-system
## Customize the installation
There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`.
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
Specify your overrides file when you install the Chart:
helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --values myvalues.yaml
The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that werent overridden will keep their defaults.
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
helm upgrade kamaji --install --namespace kamaji-system --create-namespace clastix/kamaji --set etcd.deploy=false
Here the values you can override:
{{ template "chart.valuesSection" . }}
## Installing and managing etcd as DataStore
Kamaji supports multiple data store, although `etcd` is the default one: thus, an initial cluster will be created upon the Chart installation.
The `DataStore` resource can be configured with the proper values in case of overrides when using a different driver, otherwise all the required data will be inherited by the Chart values.

View File

@@ -0,0 +1,30 @@
# Kamaji - Managed Kubernetes Service
Kamaji is a tool aimed to build and operate a Managed Kubernetes Service with a fraction of the operational burden.
Useful links:
- [Kamaji Github repository](https://github.com/clastix/kamaji)
- [Kamaji Documentation](https://github.com/clastix/kamaji/docs/)
## Requirements
* Kubernetes v1.22+
* Helm v3
# Installation
To install the Chart with the release name `kamaji`:
helm upgrade --install --namespace kamaji-system --create-namespace clastix/kamaji
Show the status:
helm status kamaji -n kamaji-system
Upgrade the Chart
helm upgrade kamaji -n kamaji-system clastix/kamaji
Uninstall the Chart
helm uninstall kamaji -n kamaji-system

View File

@@ -0,0 +1,268 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.2
creationTimestamp: null
name: datastores.kamaji.clastix.io
spec:
group: kamaji.clastix.io
names:
kind: DataStore
listKind: DataStoreList
plural: datastores
singular: datastore
scope: Cluster
versions:
- additionalPrinterColumns:
- description: Kamaji data store driver
jsonPath: .spec.driver
name: Driver
type: string
- description: Age
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: DataStore is the Schema for the datastores API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: DataStoreSpec defines the desired state of DataStore.
properties:
basicAuth:
description: In case of authentication enabled for the given data
store, specifies the username and password pair. This value is optional.
properties:
password:
properties:
content:
description: Bare content of the file, base64 encoded. It
has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret reference
where the content is stored. This value is mandatory.
type: string
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
username:
properties:
content:
description: Bare content of the file, base64 encoded. It
has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret reference
where the content is stored. This value is mandatory.
type: string
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- password
- username
type: object
driver:
description: The driver to use to connect to the shared datastore.
type: string
endpoints:
description: List of the endpoints to connect to the shared datastore.
No need for protocol, just bare IP/FQDN and port.
items:
type: string
type: array
tlsConfig:
description: Defines the TLS/SSL configuration required to connect
to the data store in a secure way.
properties:
certificateAuthority:
description: Retrieve the Certificate Authority certificate and
private key, such as bare content of the file, or a SecretReference.
The key reference is required since etcd authentication is based
on certificates, and Kamaji is responsible in creating this.
properties:
certificate:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
privateKey:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- certificate
type: object
clientCertificate:
description: Specifies the SSL/TLS key and private key pair used
to connect to the data store.
properties:
certificate:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
privateKey:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- certificate
- privateKey
type: object
required:
- certificateAuthority
- clientCertificate
type: object
required:
- driver
- endpoints
- tlsConfig
type: object
status:
description: DataStoreStatus defines the observed state of DataStore.
properties:
usedBy:
description: List of the Tenant Control Planes, namespaced named,
using this data store.
items:
type: string
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
List the available CRDs installed by Kamaji:
kubectl get customresourcedefinitions.apiextensions.k8s.io
List all the Tenant Control Plane resources deployed in your cluster:
kubectl get tenantcontrolplanes.kamaji.clastix.io --all-namespaces

View File

@@ -0,0 +1,90 @@
{{/*
Create a default fully qualified datastore name.
*/}}
{{- define "datastore.fullname" -}}
{{- default "default" .Values.datastore.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "datastore.labels" -}}
kamaji.clastix.io/datastore: {{ .Values.datastore.driver }}
helm.sh/chart: {{ include "kamaji.chart" . }}
{{ include "kamaji.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Datastore endpoints, in case of ETCD, retrieving the one provided by the chart.
*/}}
{{- define "datastore.endpoints" -}}
{{- if eq .Values.datastore.driver "etcd" }}
{{ include "etcd.endpoints" . }}
{{- else }}
{{ .Values.datastore.endpoints }}
{{- end }}
{{- end }}
{{/*
The Certificate Authority section for the DataSource object.
*/}}
{{- define "datastore.certificateAuthority" -}}
{{- if eq .Values.datastore.driver "etcd" }}
certificate:
secretReference:
name: {{ include "etcd.caSecretName" . }}
namespace: {{ include "etcd.caSecretNamespace" . }}
keyPath: ca.crt
privateKey:
secretReference:
name: {{ include "etcd.caSecretName" . }}
namespace: {{ include "etcd.caSecretNamespace" . }}
keyPath: ca.key
{{- else }}
certificate:
secretReference:
name: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.name }}
namespace: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.namespace }}
keyPath: {{ .Values.datastore.tlsConfig.certificateAuthority.certificate.keyPath }}
{{- if .Values.datastore.tlsConfig.certificateAuthority.privateKey.name }}
privateKey:
secretReference:
name: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.name }}
namespace: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.namespace }}
keyPath: {{ .Values.datastore.tlsConfig.certificateAuthority.privateKey.keyPath }}
{{- end }}
{{- end }}
{{- end }}
{{/*
The Client Certificate section for the DataSource object.
*/}}
{{- define "datastore.clientCertificate" -}}
{{- if eq .Values.datastore.driver "etcd" }}
certificate:
secretReference:
name: {{ include "etcd.clientSecretName" . }}
namespace: {{ include "etcd.clientSecretNamespace" . }}
keyPath: tls.crt
privateKey:
secretReference:
name: {{ include "etcd.clientSecretName" . }}
namespace: {{ include "etcd.clientSecretNamespace" . }}
keyPath: tls.key
{{- else }}
certificate:
secretReference:
name: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.name }}
namespace: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.namespace }}
keyPath: {{ .Values.datastore.tlsConfig.clientCertificate.certificate.keyPath }}
privateKey:
secretReference:
name: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.name }}
namespace: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.namespace }}
keyPath: {{ .Values.datastore.tlsConfig.clientCertificate.privateKey.keyPath }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,142 @@
{{/*
Create a default fully qualified etcd name.
*/}}
{{- define "etcd.fullname" -}}
{{- printf "etcd" }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "etcd.serviceAccountName" -}}
{{- if .Values.etcd.serviceAccount.create }}
{{- default (include "etcd.fullname" .) .Values.etcd.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.etcd.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the Service to use
*/}}
{{- define "etcd.serviceName" -}}
{{- printf "%s" (include "etcd.fullname" .) | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "etcd.labels" -}}
app.kubernetes.io/name: {{ include "kamaji.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/components: etcd
{{- end }}
{{/*
Selector labels.
*/}}
{{- define "etcd.selectorLabels" -}}
app.kubernetes.io/name: {{ include "kamaji.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: etcd
{{- end }}
{{/*
Name of the etcd CA secret.
*/}}
{{- define "etcd.caSecretName" }}
{{- if .Values.etcd.deploy }}
{{- printf "%s-%s" (include "etcd.fullname" .) "certs" | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- required "A valid .Values.etcd.overrides.caSecret.name required!" .Values.etcd.overrides.caSecret.name }}
{{- end }}
{{- end }}
{{/*
Namespace of the etcd CA secret.
*/}}
{{- define "etcd.caSecretNamespace" }}
{{- if .Values.etcd.deploy }}
{{- .Release.Namespace }}
{{- else }}
{{- required "A valid .Values.etcd.overrides.caSecret.namespace required!" .Values.etcd.overrides.caSecret.namespace }}
{{- end }}
{{- end }}
{{/*
Name of the certificate signing requests for the certificates required by etcd.
*/}}
{{- define "etcd.csrConfigMapName" }}
{{- printf "%s-csr" (include "etcd.fullname" .) }}
{{- end }}
{{/*
Name of the etcd root-client secret.
*/}}
{{- define "etcd.clientSecretName" }}
{{- if .Values.etcd.deploy }}
{{- printf "root-client-certs" }}
{{- else }}
{{- required "A valid .Values.etcd.overrides.clientSecret.name required!" .Values.etcd.overrides.clientSecret.name }}
{{- end }}
{{- end }}
{{/*
Namespace of the etcd root-client secret.
*/}}
{{- define "etcd.clientSecretNamespace" }}
{{- if .Values.etcd.deploy }}
{{- .Release.Namespace }}
{{- else }}
{{- required "A valid .Values.etcd.overrides.clientSecret.namespace required!" .Values.etcd.overrides.clientSecret.namespace }}
{{- end }}
{{- end }}
{{/*
Comma separated list of etcd endpoints, using the overrides in case of unmanaged etcd.
*/}}
{{- define "etcd.endpoints" }}
{{- $list := list -}}
{{- if .Values.etcd.deploy }}
{{- range $count := until 3 -}}
{{- $list = append $list (printf "%s-%d.%s.%s.svc.cluster.local:%d" "etcd" $count ( include "etcd.serviceName" . ) $.Release.Namespace (int $.Values.etcd.port) ) -}}
{{- end }}
{{- else if .Values.etcd.overrides.endpoints }}
{{- range $v := .Values.etcd.overrides.endpoints -}}
{{- $list = append $list (printf "%s:%d" $v (int $.Values.etcd.port) ) -}}
{{- end -}}
{{- else if not .Values.etcd.overrides.endpoints }}
{{- fail "A valid .Values.etcd.overrides.endpoints required!" }}
{{- end }}
{{- $list | toYaml }}
{{- end }}
{{/*
Key-value of the etcd peers, using the overrides in case of unmanaged etcd.
*/}}
{{- define "etcd.initialCluster" }}
{{- $list := list -}}
{{- if .Values.etcd.deploy }}
{{- range $i, $count := until 3 -}}
{{- $list = append $list ( printf "etcd-%d=https://%s-%d.%s.%s.svc.cluster.local:%d" $i "etcd" $count ( include "etcd.serviceName" . ) $.Release.Namespace (int $.Values.etcd.peerApiPort) ) -}}
{{- end }}
{{- else if .Values.etcd.overrides.endpoints }}
{{- range $k, $v := .Values.etcd.overrides.endpoints -}}
{{- $list = append $list ( printf "%s=%s:%d" $k $v (int $.Values.etcd.peerApiPort) ) -}}
{{- end -}}
{{- else if not .Values.etcd.overrides.endpoints }}
{{- fail "A valid .Values.etcd.overrides.endpoints required!" }}
{{- end }}
{{- join "," $list -}}
{{- end }}
{{/*
Retrieve the current Kubernetes version to launch a kubectl container with the minimum version skew possible.
*/}}
{{- define "etcd.jobsTagKubeVersion" -}}
{{- if contains "-eks-" .Capabilities.KubeVersion.GitVersion }}
{{- print "v" .Capabilities.KubeVersion.Major "." (.Capabilities.KubeVersion.Minor | replace "+" "") -}}
{{- else }}
{{- print "v" .Capabilities.KubeVersion.Major "." .Capabilities.KubeVersion.Minor -}}
{{- end }}
{{- end }}

View File

@@ -40,16 +40,11 @@ spec:
protocol: TCP
- args:
- --config-file={{ .Values.configPath }}
- --etcd-ca-secret-name={{ .Values.etcd.caSecret.name }}
- --etcd-ca-secret-namespace={{ .Values.etcd.caSecret.namespace }}
- --etcd-client-secret-name={{ .Values.etcd.clientSecret.name }}
- --etcd-client-secret-namespace={{ .Values.etcd.clientSecret.namespace }}
- --etcd-compaction-interval={{ .Values.etcd.compactionInterval }}
- --etcd-endpoints={{ .Values.etcd.endpoints }}
- --health-probe-bind-address={{ .Values.healthProbeBindAddress }}
- --leader-elect
- --metrics-bind-address={{ .Values.metricsBindAddress }}
- --tmp-directory={{ .Values.temporaryDirectoryPath }}
- --datastore={{ include "datastore.fullname" . }}
{{- if .Values.loggingDevel.enable }}
- --zap-devel
{{- end }}

View File

@@ -0,0 +1,19 @@
apiVersion: kamaji.clastix.io/v1alpha1
kind: DataStore
metadata:
name: {{ include "datastore.fullname" . }}
labels:
{{- include "datastore.labels" . | nindent 4 }}
spec:
driver: {{ .Values.datastore.driver }}
endpoints:
{{- include "datastore.endpoints" . | indent 4 }}
{{- if (and .Values.datastore.basicAuth.usernameSecret.name .Values.datastore.basicAuth.passwordSecret.name) }}
basicAuth:
{{- .Values.datastore.basicAuth | toYaml | nindent 4 }}
{{- end }}
tlsConfig:
certificateAuthority:
{{- include "datastore.certificateAuthority" . | indent 6 }}
clientCertificate:
{{- include "datastore.clientCertificate" . | indent 6 }}

View File

@@ -0,0 +1,94 @@
{{- if .Values.etcd.deploy }}
apiVersion: v1
kind: ConfigMap
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: {{ include "etcd.csrConfigMapName" . }}
namespace: {{ .Release.Namespace }}
data:
ca-csr.json: |-
{
"CN": "Clastix CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "IT",
"ST": "Italy",
"L": "Milan"
}
]
}
config.json: |-
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"server-authentication": {
"usages": ["signing", "key encipherment", "server auth"],
"expiry": "8760h"
},
"client-authentication": {
"usages": ["signing", "key encipherment", "client auth"],
"expiry": "8760h"
},
"peer-authentication": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
server-csr.json: |-
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
{{- range $count := until 3 -}}
{{ printf "\"etcd-%d.%s.%s.svc.cluster.local\"," $count (include "etcd.serviceName" .) $.Release.Namespace }}
{{- end }}
"etcd-server.{{ .Release.Namespace }}.svc.cluster.local",
"etcd-server.{{ .Release.Namespace }}.svc",
"etcd-server",
"127.0.0.1"
]
}
peer-csr.json: |-
{
"CN": "etcd",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
{{- range $count := until 3 -}}
{{ printf "\"etcd-%d\"," $count }}
{{ printf "\"etcd-%d.%s\"," $count (include "etcd.serviceName" .) }}
{{ printf "\"etcd-%d.%s.%s.svc\"," $count (include "etcd.serviceName" .) $.Release.Namespace }}
{{ printf "\"etcd-%d.%s.%s.svc.cluster.local\"," $count (include "etcd.serviceName" .) $.Release.Namespace }}
{{- end }}
"127.0.0.1"
]
}
root-client-csr.json: |-
{
"CN": "root",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"O": "system:masters"
}
]
}
{{- end }}

View File

@@ -0,0 +1,31 @@
{{- if .Values.etcd.deploy }}
apiVersion: batch/v1
kind: Job
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"
name: "{{ .Release.Name }}-etcd-teardown"
namespace: {{ .Release.Namespace }}
spec:
template:
metadata:
name: "{{ .Release.Name }}"
spec:
serviceAccountName: {{ include "etcd.serviceAccountName" . }}
restartPolicy: Never
containers:
- name: kubectl
image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }}
command:
- kubectl
- --namespace={{ .Release.Namespace }}
- delete
- secret
- --ignore-not-found=true
- {{ include "etcd.caSecretName" . }}
- {{ include "etcd.clientSecretName" . }}
{{- end }}

View File

@@ -0,0 +1,91 @@
{{- if .Values.etcd.deploy }}
apiVersion: batch/v1
kind: Job
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"
name: "{{ .Release.Name }}-etcd-setup"
namespace: {{ .Release.Namespace }}
spec:
template:
metadata:
name: "{{ .Release.Name }}"
spec:
serviceAccountName: {{ include "etcd.serviceAccountName" . }}
restartPolicy: Never
initContainers:
- name: cfssl
image: cfssl/cfssl:latest
command:
- bash
- -c
- |-
cfssl gencert -initca /csr/ca-csr.json | cfssljson -bare /certs/ca &&
mv /certs/ca.pem /certs/ca.crt && mv /certs/ca-key.pem /certs/ca.key &&
cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/peer-csr.json | cfssljson -bare /certs/peer &&
cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=peer-authentication /csr/server-csr.json | cfssljson -bare /certs/server &&
cfssl gencert -ca=/certs/ca.crt -ca-key=/certs/ca.key -config=/csr/config.json -profile=client-authentication /csr/root-client-csr.json | cfssljson -bare /certs/root-client
volumeMounts:
- mountPath: /certs
name: certs
- mountPath: /csr
name: csr
- name: kubectl
image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }}
command:
- sh
- -c
- |-
kubectl --namespace={{ .Release.Namespace }} delete secret --ignore-not-found=true {{ include "etcd.caSecretName" . }} {{ include "etcd.clientSecretName" . }} &&
kubectl --namespace={{ .Release.Namespace }} create secret generic {{ include "etcd.caSecretName" . }} --from-file=/certs/ca.crt --from-file=/certs/ca.key --from-file=/certs/peer-key.pem --from-file=/certs/peer.pem --from-file=/certs/server-key.pem --from-file=/certs/server.pem &&
kubectl --namespace={{ .Release.Namespace }} create secret tls {{ include "etcd.clientSecretName" . }} --key=/certs/root-client-key.pem --cert=/certs/root-client.pem &&
kubectl --namespace={{ .Release.Namespace }} rollout status sts/etcd --timeout=300s
volumeMounts:
- mountPath: /certs
name: certs
containers:
- command:
- bash
- -c
- |-
etcdctl member list -w table &&
etcdctl user add --no-password=true root &&
etcdctl role add root &&
etcdctl user grant-role root root &&
etcdctl auth enable
env:
- name: ETCDCTL_ENDPOINTS
value: https://etcd-0.{{ include "etcd.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local:2379
- name: ETCDCTL_CACERT
value: /opt/certs/ca/ca.crt
- name: ETCDCTL_CERT
value: /opt/certs/root-certs/tls.crt
- name: ETCDCTL_KEY
value: /opt/certs/root-certs/tls.key
image: quay.io/coreos/etcd:v3.5.1
imagePullPolicy: Always
name: etcd-client
volumeMounts:
- name: root-certs
mountPath: /opt/certs/root-certs
- name: certs
mountPath: /opt/certs/ca
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
volumes:
- name: root-certs
secret:
secretName: {{ include "etcd.clientSecretName" . }}
optional: true
- name: csr
configMap:
name: {{ include "etcd.csrConfigMapName" . }}
- name: certs
emptyDir: {}
{{- end }}

View File

@@ -0,0 +1,49 @@
{{- if .Values.etcd.deploy }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: etcd-gen-certs-role
namespace: {{ .Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- delete
resourceNames:
- {{ include "etcd.caSecretName" . }}
- {{ include "etcd.clientSecretName" . }}
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- apiGroups:
- apps
resources:
- statefulsets
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: etcd-gen-certs-rolebiding
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: etcd-gen-certs-role
subjects:
- kind: ServiceAccount
name: {{ include "etcd.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,9 @@
{{- if .Values.etcd.deploy }}
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: {{ include "etcd.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,18 @@
{{- if .Values.etcd.deploy }}
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: {{ include "etcd.serviceName" . }}
namespace: {{ .Release.Namespace }}
spec:
clusterIP: None
ports:
- port: {{ .Values.etcd.port }}
name: client
- port: {{ .Values.etcd.peerApiPort }}
name: peer
selector:
{{- include "etcd.selectorLabels" . | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,93 @@
{{- if .Values.etcd.deploy }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
{{- include "etcd.labels" . | nindent 4 }}
name: {{ include "etcd.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
serviceName: {{ include "etcd.serviceName" . }}
selector:
matchLabels:
{{- include "etcd.selectorLabels" . | nindent 6 }}
replicas: 3
template:
metadata:
name: etcd
labels:
{{- include "etcd.selectorLabels" . | nindent 8 }}
spec:
volumes:
- name: certs
secret:
secretName: {{ include "etcd.caSecretName" . }}
containers:
- name: etcd
image: {{ .Values.etcd.image.repository }}:{{ .Values.etcd.image.tag | default "v3.5.4" }}
imagePullPolicy: {{ .Values.etcd.image.pullPolicy }}
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer
volumeMounts:
- name: data
mountPath: /var/run/etcd
- name: certs
mountPath: /etc/etcd/pki
command:
- etcd
- --data-dir=/var/run/etcd
- --name=$(POD_NAME)
- --initial-cluster-state=new
- --initial-cluster={{ include "etcd.initialCluster" . }}
- --initial-advertise-peer-urls=https://$(POD_NAME).etcd.$(POD_NAMESPACE).svc.cluster.local:2380
- --advertise-client-urls=https://$(POD_NAME).etcd.$(POD_NAMESPACE).svc.cluster.local:2379
- --initial-cluster-token=kamaji
- --listen-client-urls=https://0.0.0.0:2379
- --listen-metrics-urls=http://0.0.0.0:2381
- --listen-peer-urls=https://0.0.0.0:2380
- --client-cert-auth=true
- --peer-client-cert-auth=true
- --trusted-ca-file=/etc/etcd/pki/ca.crt
- --cert-file=/etc/etcd/pki/server.pem
- --key-file=/etc/etcd/pki/server-key.pem
- --peer-trusted-ca-file=/etc/etcd/pki/ca.crt
- --peer-cert-file=/etc/etcd/pki/peer.pem
- --peer-key-file=/etc/etcd/pki/peer-key.pem
- --auto-compaction-mode=periodic
- --auto-compaction-retention=5m
- --snapshot-count=10000
- --quota-backend-bytes=8589934592
- --v=8
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- with .Values.etcd.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.etcd.startupProbe }}
startupProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: {{ .Values.etcd.persistence.storageClassName }}
accessModes:
{{- range .Values.etcd.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.etcd.persistence.size }}
{{- end }}

View File

@@ -102,6 +102,32 @@ rules:
- patch
- update
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores/finalizers
verbs:
- update
- apiGroups:
- kamaji.clastix.io
resources:
- datastores/status
verbs:
- get
- patch
- update
- apiGroups:
- kamaji.clastix.io
resources:

View File

@@ -0,0 +1,2 @@
etcd:
endpoints: "https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379"

210
charts/kamaji/values.yaml Normal file
View File

@@ -0,0 +1,210 @@
# Default values for kamaji.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# -- The number of the pod replicas for the Kamaji controller.
replicaCount: 1
image:
# -- The container image of the Kamaji controller.
repository: clastix/kamaji
pullPolicy: Always
# -- Overrides the image tag whose default is the chart appVersion.
tag:
# -- A list of extra arguments to add to the kamaji controller default ones
extraArgs: []
# -- Configuration file path alternative. (default "./kamaji.yaml")
configPath: "./kamaji.yaml"
etcd:
# -- Install an etcd with enabled multi-tenancy along with Kamaji
deploy: true
# -- The peer API port which servers are listening to.
peerApiPort: 2380
# -- The client request port.
port: 2379
# -- Install specific etcd image
image:
repository: quay.io/coreos/etcd
tag: "v3.5.4"
pullPolicy: IfNotPresent
# -- The livenessProbe for the etcd container
livenessProbe:
failureThreshold: 8
httpGet:
path: /health?serializable=true
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
serviceAccount:
# -- Create a ServiceAccount, required to install and provision the etcd backing storage (default: true)
create: true
# -- Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "")
name: ""
persistence:
size: 10Gi
storageClass: ""
accessModes:
- ReadWriteOnce
overrides:
caSecret:
# -- Name of the secret which contains CA's certificate and private key. (default: "etcd-certs")
name: etcd-certs
# -- Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system")
namespace: kamaji-system
clientSecret:
# -- Name of the secret which contains ETCD client certificates. (default: "root-client-certs")
name: root-client-certs
# -- Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system")
namespace: kamaji-system
# -- (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value.
endpoints:
etcd-0: etcd-0.etcd.kamaji-system.svc.cluster.local
etcd-1: etcd-1.etcd.kamaji-system.svc.cluster.local
etcd-2: etcd-2.etcd.kamaji-system.svc.cluster.local
# -- ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled))
compactionInterval: 0
# -- The address the probe endpoint binds to. (default ":8081")
healthProbeBindAddress: ":8081"
# -- The livenessProbe for the controller container
livenessProbe:
httpGet:
path: /healthz
port: healthcheck
initialDelaySeconds: 15
periodSeconds: 20
# -- The readinessProbe for the controller container
readinessProbe:
httpGet:
path: /readyz
port: healthcheck
initialDelaySeconds: 5
periodSeconds: 10
# -- (string) The address the metric endpoint binds to. (default ":8080")
metricsBindAddress: ":8080"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: kamaji-controller-manager
# -- The annotations to apply to the Kamaji controller pods.
podAnnotations: {}
# -- The securityContext to apply to the Kamaji controller pods.
podSecurityContext:
runAsNonRoot: true
# -- The securityContext to apply to the Kamaji controller container only. It does not apply to the Kamaji RBAC proxy container.
securityContext:
allowPrivilegeEscalation: false
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 8443
resources:
limits:
cpu: 200m
memory: 100Mi
requests:
cpu: 100m
memory: 20Mi
# -- Kubernetes node selector rules to schedule Kamaji controller
nodeSelector: {}
# -- Kubernetes node taints that the Kamaji controller pods would tolerate
tolerations: []
# -- Kubernetes affinity rules to apply to Kamaji controller pods
affinity: {}
# -- Directory which will be used to work with temporary files. (default "/tmp/kamaji")
temporaryDirectoryPath: "/tmp/kamaji"
loggingDevel:
# -- (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false)
enable: false
datastore:
# -- (string) The Datastore name override, if empty defaults to `default`
nameOverride:
# -- (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd).
driver: etcd
# -- (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically.
endpoints: []
basicAuth:
usernameSecret:
# -- The name of the Secret containing the username used to connect to the relational database.
name:
# -- The namespace of the Secret containing the username used to connect to the relational database.
namespace:
# -- The Secret key where the data is stored.
keyPath:
passwordSecret:
# -- The name of the Secret containing the password used to connect to the relational database.
name:
# -- The namespace of the Secret containing the password used to connect to the relational database.
namespace:
# -- The Secret key where the data is stored.
keyPath:
tlsConfig:
certificateAuthority:
certificate:
# -- Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the certificate.
keyPath:
privateKey:
# -- Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the private key.
keyPath:
clientCertificate:
certificate:
# -- Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the certificate.
keyPath:
privateKey:
# -- Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the private key.
keyPath:

View File

@@ -0,0 +1,268 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.2
creationTimestamp: null
name: datastores.kamaji.clastix.io
spec:
group: kamaji.clastix.io
names:
kind: DataStore
listKind: DataStoreList
plural: datastores
singular: datastore
scope: Cluster
versions:
- additionalPrinterColumns:
- description: Kamaji data store driver
jsonPath: .spec.driver
name: Driver
type: string
- description: Age
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: DataStore is the Schema for the datastores API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: DataStoreSpec defines the desired state of DataStore.
properties:
basicAuth:
description: In case of authentication enabled for the given data
store, specifies the username and password pair. This value is optional.
properties:
password:
properties:
content:
description: Bare content of the file, base64 encoded. It
has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret reference
where the content is stored. This value is mandatory.
type: string
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
username:
properties:
content:
description: Bare content of the file, base64 encoded. It
has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret reference
where the content is stored. This value is mandatory.
type: string
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- password
- username
type: object
driver:
description: The driver to use to connect to the shared datastore.
type: string
endpoints:
description: List of the endpoints to connect to the shared datastore.
No need for protocol, just bare IP/FQDN and port.
items:
type: string
type: array
tlsConfig:
description: Defines the TLS/SSL configuration required to connect
to the data store in a secure way.
properties:
certificateAuthority:
description: Retrieve the Certificate Authority certificate and
private key, such as bare content of the file, or a SecretReference.
The key reference is required since etcd authentication is based
on certificates, and Kamaji is responsible in creating this.
properties:
certificate:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
privateKey:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- certificate
type: object
clientCertificate:
description: Specifies the SSL/TLS key and private key pair used
to connect to the data store.
properties:
certificate:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
privateKey:
properties:
content:
description: Bare content of the file, base64 encoded.
It has precedence over the SecretReference value.
format: byte
type: string
secretReference:
properties:
keyPath:
description: Name of the key for the given Secret
reference where the content is stored. This value
is mandatory.
type: string
name:
description: name is unique within a namespace to
reference a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
required:
- keyPath
type: object
x-kubernetes-map-type: atomic
type: object
required:
- certificate
- privateKey
type: object
required:
- certificateAuthority
- clientCertificate
type: object
required:
- driver
- endpoints
- tlsConfig
type: object
status:
description: DataStoreStatus defines the observed state of DataStore.
properties:
usedBy:
description: List of the Tenant Control Planes, namespaced named,
using this data store.
items:
type: string
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
# It should be run by config/default
resources:
- bases/kamaji.clastix.io_tenantcontrolplanes.yaml
- bases/kamaji.clastix.io_datastores.yaml
#+kubebuilder:scaffold:crdkustomizeresource
patchesStrategicMerge:

View File

@@ -0,0 +1,7 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: datastores.kamaji.clastix.io

View File

@@ -0,0 +1,16 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: datastores.kamaji.clastix.io
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: system
name: webhook-service
path: /convert
conversionReviewVersions:
- v1

View File

@@ -16,6 +16,7 @@ bases:
- ../crd
- ../rbac
- ../manager
- ../samples
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- ../webhook

View File

@@ -25,3 +25,4 @@ spec:
- "--health-probe-bind-address=:8081"
- "--metrics-bind-address=127.0.0.1:8080"
- "--leader-elect"
- "--datastore=kamaji-etcd"

File diff suppressed because it is too large Load Diff

View File

@@ -12,5 +12,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: controller
newName: quay.io/clastix/kamaji
newTag: latest
newName: clastix/kamaji
newTag: v0.1.1

View File

@@ -30,7 +30,7 @@ spec:
args:
- --leader-elect
image: controller:latest
imagePullPolicy: IfNotPresent
imagePullPolicy: Always
name: manager
securityContext:
allowPrivilegeEscalation: false

View File

@@ -0,0 +1,24 @@
# permissions for end users to edit datastores.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: datastore-editor-role
rules:
- apiGroups:
- kamaji.clastix.io
resources:
- datastores
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores/status
verbs:
- get

View File

@@ -0,0 +1,20 @@
# permissions for end users to view datastores.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: datastore-viewer-role
rules:
- apiGroups:
- kamaji.clastix.io
resources:
- datastores
verbs:
- get
- list
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores/status
verbs:
- get

View File

@@ -1,4 +1,3 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -54,6 +53,26 @@ rules:
- patch
- update
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- kamaji.clastix.io
resources:
- datastores/status
verbs:
- get
- patch
- update
- apiGroups:
- kamaji.clastix.io
resources:

View File

@@ -0,0 +1,34 @@
apiVersion: kamaji.clastix.io/v1alpha1
kind: DataStore
metadata:
name: etcd
spec:
driver: etcd
endpoints:
- etcd-0.etcd.kamaji-system.svc.cluster.local:2379
- etcd-1.etcd.kamaji-system.svc.cluster.local:2379
- etcd-2.etcd.kamaji-system.svc.cluster.local:2379
basicAuth: null
tlsConfig:
certificateAuthority:
certificate:
secretReference:
name: etcd-certs
namespace: kamaji-system
keyPath: "ca.crt"
privateKey:
secretReference:
name: etcd-certs
namespace: kamaji-system
keyPath: "ca.key"
clientCertificate:
certificate:
secretReference:
name: root-client-certs
namespace: kamaji-system
keyPath: "tls.crt"
privateKey:
secretReference:
name: root-client-certs
namespace: kamaji-system
keyPath: "tls.key"

View File

@@ -0,0 +1,34 @@
apiVersion: kamaji.clastix.io/v1alpha1
kind: DataStore
metadata:
name: mysql
spec:
driver: MySQL
endpoints:
- mariadb.kamaji-system.svc:3306
basicAuth:
username:
content: cm9vdA==
password:
secretReference:
name: mysql-config
namespace: kamaji-system
keyPath: MYSQL_ROOT_PASSWORD
tlsConfig:
certificateAuthority:
certificate:
secretReference:
name: mysql-config
namespace: kamaji-system
keyPath: "ca.crt"
clientCertificate:
certificate:
secretReference:
name: mysql-config
namespace: kamaji-system
keyPath: "server.crt"
privateKey:
secretReference:
name: mysql-config
namespace: kamaji-system
keyPath: "server.key"

View File

@@ -0,0 +1,37 @@
apiVersion: kamaji.clastix.io/v1alpha1
kind: DataStore
metadata:
name: postgresql
spec:
driver: PostgreSQL
endpoints:
- postgresql-rw.kamaji-system.svc:5432
basicAuth:
username:
secretReference:
name: postgresql-superuser
namespace: kamaji-system
keyPath: username
password:
secretReference:
name: postgresql-superuser
namespace: kamaji-system
keyPath: password
tlsConfig:
certificateAuthority:
certificate:
secretReference:
name: postgresql-ca
namespace: kamaji-system
keyPath: ca.crt
clientCertificate:
certificate:
secretReference:
name: postgres-root-cert
namespace: kamaji-system
keyPath: tls.crt
privateKey:
secretReference:
name: postgres-root-cert
namespace: kamaji-system
keyPath: tls.key

View File

@@ -5,44 +5,18 @@ metadata:
spec:
controlPlane:
deployment:
replicas: 2
additionalMetadata:
annotations:
environment.clastix.io: test
tier.clastix.io: "0"
labels:
tenant.clastix.io: test
kind.clastix.io: deployment
replicas: 1
service:
additionalMetadata:
annotations:
environment.clastix.io: test
tier.clastix.io: "0"
labels:
tenant.clastix.io: test
kind.clastix.io: service
serviceType: ClusterIP
ingress:
enabled: true
hostname: kamaji.local
ingressClassName: nginx
additionalMetadata:
annotations:
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
serviceType: LoadBalancer
kubernetes:
version: "v1.23.1"
kubelet:
cgroupfs: systemd
cgroupfs: cgroupfs
admissionControllers:
- ResourceQuota
- LimitRanger
networkProfile:
address: "127.0.0.1"
port: 6443
domain: "clastix.labs"
serviceCidr: "10.96.0.0/16"
podCidr: "10.244.0.0/16"
dnsServiceIPs:
- "10.96.0.10"
addons:
coreDNS: {}
kubeProxy: {}

View File

@@ -1,4 +1,4 @@
## Append samples you want in your CSV to this file as resources ##
resources:
- kamaji_v1alpha1_tenantcontrolplane.yaml
- kamaji_v1alpha1_datastore_etcd.yaml
#+kubebuilder:scaffold:manifestskustomizesamples

View File

@@ -0,0 +1,180 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package controllers
import (
"context"
"fmt"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/fields"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/util/workqueue"
controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/indexers"
)
const (
dataStoreFinalizer = "finalizer.kamaji.clastix.io/datastore"
)
type DataStore struct {
client client.Client
// TenantControlPlaneTrigger is the channel used to communicate across the controllers:
// if a Data Source is updated we have to be sure that the reconciliation of the certificates content
// for each Tenant Control Plane is put in place properly.
TenantControlPlaneTrigger TenantControlPlaneChannel
}
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=datastores,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=datastores/status,verbs=get;update;patch
func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log := log.FromContext(ctx)
ds := &kamajiv1alpha1.DataStore{}
if err := r.client.Get(ctx, request.NamespacedName, ds); err != nil {
if k8serrors.IsNotFound(err) {
return reconcile.Result{}, nil
}
log.Error(err, "unable to retrieve the request")
return reconcile.Result{}, err
}
// Managing the finalizer, required to don't drop a DataSource if this is still used by a Tenant Control Plane.
switch {
case ds.DeletionTimestamp != nil && controllerutil.ContainsFinalizer(ds, dataStoreFinalizer):
log.Info("marked for deletion, checking conditions")
if len(ds.Status.UsedBy) == 0 {
log.Info("resource is no more used by any Tenant Control Plane")
controllerutil.RemoveFinalizer(ds, dataStoreFinalizer)
return reconcile.Result{}, r.client.Update(ctx, ds)
}
log.Info("DataStore is still used by some Tenant Control Planes, cannot be removed")
case ds.DeletionTimestamp == nil && !controllerutil.ContainsFinalizer(ds, dataStoreFinalizer):
log.Info("the resource is missing the required finalizer, adding it")
controllerutil.AddFinalizer(ds, dataStoreFinalizer)
return reconcile.Result{}, r.client.Update(ctx, ds)
}
// A Data Source can trigger several Tenant Control Planes and requires a minimum validation:
// we have to ensure the data provided by the Data Source is valid and referencing an existing Secret object.
if _, err := ds.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, r.client); err != nil {
log.Error(err, "invalid Certificate Authority data")
return reconcile.Result{}, err
}
if ds.Spec.Driver == kamajiv1alpha1.EtcdDriver {
if ds.Spec.TLSConfig.CertificateAuthority.PrivateKey == nil {
err := fmt.Errorf("a valid private key is required for the etcd driver")
log.Error(err, "missing Certificate Authority private key data")
return reconcile.Result{}, err
}
if _, err := ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.GetContent(ctx, r.client); err != nil {
log.Error(err, "invalid Certificate Authority private key data")
return reconcile.Result{}, err
}
}
if _, err := ds.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, r.client); err != nil {
log.Error(err, "invalid Client Certificate data")
return reconcile.Result{}, err
}
if _, err := ds.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, r.client); err != nil {
log.Error(err, "invalid Client Certificate private key data")
return reconcile.Result{}, err
}
tcpList := kamajiv1alpha1.TenantControlPlaneList{}
if err := r.client.List(ctx, &tcpList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(indexers.TenantControlPlaneUsedDataStoreKey, ds.GetName()),
}); err != nil {
log.Error(err, "cannot retrieve list of the Tenant Control Plane using the following instance")
return reconcile.Result{}, err
}
// Updating the status with the list of Tenant Control Plane using the following Data Source
tcpSets := sets.NewString()
for _, tcp := range tcpList.Items {
tcpSets.Insert(getNamespacedName(tcp.GetNamespace(), tcp.GetName()).String())
}
ds.Status.UsedBy = tcpSets.List()
if err := r.client.Status().Update(ctx, ds); err != nil {
log.Error(err, "cannot update the status for the given instance")
return reconcile.Result{}, err
}
// Triggering the reconciliation of the Tenant Control Plane upon a Secret change
for _, i := range tcpList.Items {
tcp := i
r.TenantControlPlaneTrigger <- event.GenericEvent{Object: &tcp}
}
return reconcile.Result{}, nil
}
func (r *DataStore) InjectClient(client client.Client) error {
r.client = client
return nil
}
func (r *DataStore) SetupWithManager(mgr controllerruntime.Manager) error {
enqueueFn := func(tcp *kamajiv1alpha1.TenantControlPlane, limitingInterface workqueue.RateLimitingInterface) {
if dataStoreName := tcp.Status.Storage.DataStoreName; len(dataStoreName) > 0 {
limitingInterface.AddRateLimited(reconcile.Request{
NamespacedName: k8stypes.NamespacedName{
Name: dataStoreName,
},
})
}
}
//nolint:forcetypeassert
return controllerruntime.NewControllerManagedBy(mgr).
For(&kamajiv1alpha1.DataStore{}, builder.WithPredicates(
predicate.ResourceVersionChangedPredicate{},
)).
Watches(&source.Kind{Type: &kamajiv1alpha1.TenantControlPlane{}}, handler.Funcs{
CreateFunc: func(createEvent event.CreateEvent, limitingInterface workqueue.RateLimitingInterface) {
enqueueFn(createEvent.Object.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
},
UpdateFunc: func(updateEvent event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) {
enqueueFn(updateEvent.ObjectOld.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
enqueueFn(updateEvent.ObjectNew.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
},
DeleteFunc: func(deleteEvent event.DeleteEvent, limitingInterface workqueue.RateLimitingInterface) {
enqueueFn(deleteEvent.Object.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
},
}).
Complete(r)
}

260
controllers/resources.go Normal file
View File

@@ -0,0 +1,260 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package controllers
import (
"fmt"
"github.com/go-logr/logr"
"github.com/google/uuid"
k8stypes "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/datastore"
"github.com/clastix/kamaji/internal/resources"
ds "github.com/clastix/kamaji/internal/resources/datastore"
"github.com/clastix/kamaji/internal/resources/konnectivity"
)
type GroupResourceBuilderConfiguration struct {
client client.Client
log logr.Logger
tcpReconcilerConfig TenantControlPlaneReconcilerConfig
tenantControlPlane kamajiv1alpha1.TenantControlPlane
Connection datastore.Connection
DataStore kamajiv1alpha1.DataStore
}
type GroupDeleteableResourceBuilderConfiguration struct {
client client.Client
log logr.Logger
tcpReconcilerConfig TenantControlPlaneReconcilerConfig
tenantControlPlane kamajiv1alpha1.TenantControlPlane
connection datastore.Connection
}
// GetResources returns a list of resources that will be used to provide tenant control planes
// Currently there is only a default approach
// TODO: the idea of this function is to become a factory to return the group of resources according to the given configuration.
func GetResources(config GroupResourceBuilderConfiguration) []resources.Resource {
return getDefaultResources(config)
}
// GetDeletableResources returns a list of resources that have to be deleted when tenant control planes are deleted
// Currently there is only a default approach
// TODO: the idea of this function is to become a factory to return the group of deleteable resources according to the given configuration.
func GetDeletableResources(config GroupDeleteableResourceBuilderConfiguration) []resources.DeleteableResource {
return getDefaultDeleteableResources(config)
}
func getDefaultResources(config GroupResourceBuilderConfiguration) []resources.Resource {
resources := append(getUpgradeResources(config.client), getKubernetesServiceResources(config.client)...)
resources = append(resources, getKubeadmConfigResources(config.client, getTmpDirectory(config.tcpReconcilerConfig.TmpBaseDirectory, config.tenantControlPlane), config.DataStore)...)
resources = append(resources, getKubernetesCertificatesResources(config.client, config.tcpReconcilerConfig, config.tenantControlPlane)...)
resources = append(resources, getKubeconfigResources(config.client, config.tcpReconcilerConfig, config.tenantControlPlane)...)
resources = append(resources, getKubernetesStorageResources(config.client, config.Connection, config.DataStore)...)
resources = append(resources, getInternalKonnectivityResources(config.client)...)
resources = append(resources, getKubernetesDeploymentResources(config.client, config.tcpReconcilerConfig, config.DataStore)...)
resources = append(resources, getKubernetesIngressResources(config.client)...)
resources = append(resources, getKubeadmPhaseResources(config.client)...)
resources = append(resources, getKubeadmAddonResources(config.client)...)
resources = append(resources, getExternalKonnectivityResources(config.client)...)
return resources
}
func getDefaultDeleteableResources(config GroupDeleteableResourceBuilderConfiguration) []resources.DeleteableResource {
return []resources.DeleteableResource{
&ds.Setup{
Client: config.client,
Connection: config.connection,
},
}
}
func getUpgradeResources(c client.Client) []resources.Resource {
return []resources.Resource{
&resources.KubernetesUpgrade{
Client: c,
},
}
}
func getKubernetesServiceResources(c client.Client) []resources.Resource {
return []resources.Resource{
&resources.KubernetesServiceResource{
Client: c,
},
}
}
func getKubeadmConfigResources(c client.Client, tmpDirectory string, dataStore kamajiv1alpha1.DataStore) []resources.Resource {
var endpoints []string
switch dataStore.Spec.Driver {
case kamajiv1alpha1.EtcdDriver:
endpoints = dataStore.Spec.Endpoints
default:
endpoints = []string{"127.0.0.1:2379"}
}
return []resources.Resource{
&resources.KubeadmConfigResource{
ETCDs: endpoints,
Client: c,
TmpDirectory: tmpDirectory,
},
}
}
func getKubernetesCertificatesResources(c client.Client, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
return []resources.Resource{
&resources.CACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.FrontProxyCACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.SACertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.APIServerCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.APIServerKubeletClientCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.FrontProxyClientCertificate{
Client: c,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
}
}
func getKubeconfigResources(c client.Client, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
return []resources.Resource{
&resources.KubeconfigResource{
Name: "admin-kubeconfig",
Client: c,
KubeConfigFileName: resources.AdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.KubeconfigResource{
Name: "controller-manager-kubeconfig",
Client: c,
KubeConfigFileName: resources.ControllerManagerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
&resources.KubeconfigResource{
Name: "scheduler-kubeconfig",
Client: c,
KubeConfigFileName: resources.SchedulerKubeConfigFileName,
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
},
}
}
func getKubernetesStorageResources(c client.Client, dbConnection datastore.Connection, datastore kamajiv1alpha1.DataStore) []resources.Resource {
return []resources.Resource{
&ds.Config{
Client: c,
ConnString: dbConnection.GetConnectionString(),
DataStore: datastore,
},
&ds.Setup{
Client: c,
Connection: dbConnection,
DataStore: datastore,
},
&ds.Certificate{
Client: c,
DataStore: datastore,
},
}
}
func getKubernetesDeploymentResources(c client.Client, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, dataStore kamajiv1alpha1.DataStore) []resources.Resource {
return []resources.Resource{
&resources.KubernetesDeploymentResource{
Client: c,
DataStore: dataStore,
KineContainerImage: tcpReconcilerConfig.KineContainerImage,
},
}
}
func getKubernetesIngressResources(c client.Client) []resources.Resource {
return []resources.Resource{
&resources.KubernetesIngressResource{
Client: c,
},
}
}
func getKubeadmPhaseResources(c client.Client) []resources.Resource {
return []resources.Resource{
&resources.KubeadmPhase{
Name: "upload-config-kubeadm",
Client: c,
Phase: resources.PhaseUploadConfigKubeadm,
},
&resources.KubeadmPhase{
Name: "upload-config-kubelet",
Client: c,
Phase: resources.PhaseUploadConfigKubelet,
},
&resources.KubeadmPhase{
Name: "bootstrap-token",
Client: c,
Phase: resources.PhaseBootstrapToken,
},
}
}
func getKubeadmAddonResources(c client.Client) []resources.Resource {
return []resources.Resource{
&resources.KubeadmAddonResource{
Name: "coredns",
Client: c,
KubeadmAddon: resources.AddonCoreDNS,
},
&resources.KubeadmAddonResource{
Name: "kubeproxy",
Client: c,
KubeadmAddon: resources.AddonKubeProxy,
},
}
}
func getExternalKonnectivityResources(c client.Client) []resources.Resource {
return []resources.Resource{
&konnectivity.ServiceAccountResource{Client: c},
&konnectivity.ClusterRoleBindingResource{Client: c},
&konnectivity.KubernetesDeploymentResource{Client: c},
&konnectivity.ServiceResource{Client: c},
&konnectivity.Agent{Client: c},
}
}
func getInternalKonnectivityResources(c client.Client) []resources.Resource {
return []resources.Resource{
&konnectivity.EgressSelectorConfigurationResource{Client: c},
&konnectivity.CertificateResource{Client: c},
&konnectivity.KubeconfigResource{Client: c},
}
}
func getNamespacedName(namespace string, name string) k8stypes.NamespacedName {
return k8stypes.NamespacedName{Namespace: namespace, Name: name}
}
func getTmpDirectory(base string, tenantControlPlane kamajiv1alpha1.TenantControlPlane) string {
return fmt.Sprintf("%s/%s/%s", base, tenantControlPlane.GetName(), uuid.New())
}

104
controllers/storage.go Normal file
View File

@@ -0,0 +1,104 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package controllers
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"strconv"
"github.com/pkg/errors"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/datastore"
)
func (r *TenantControlPlaneReconciler) getStorageConnection(ctx context.Context, ds kamajiv1alpha1.DataStore) (datastore.Connection, error) {
ca, err := ds.Spec.TLSConfig.CertificateAuthority.Certificate.GetContent(ctx, r.Client)
if err != nil {
return nil, err
}
crt, err := ds.Spec.TLSConfig.ClientCertificate.Certificate.GetContent(ctx, r.Client)
if err != nil {
return nil, err
}
key, err := ds.Spec.TLSConfig.ClientCertificate.PrivateKey.GetContent(ctx, r.Client)
if err != nil {
return nil, err
}
rootCAs := x509.NewCertPool()
if ok := rootCAs.AppendCertsFromPEM(ca); !ok {
return nil, fmt.Errorf("error create root CA for the DB connector")
}
certificate, err := tls.X509KeyPair(crt, key)
if err != nil {
return nil, errors.Wrap(err, "cannot retrieve x.509 key pair from the Kine Secret")
}
var user, password string
if auth := ds.Spec.BasicAuth; auth != nil {
u, err := auth.Username.GetContent(ctx, r.Client)
if err != nil {
return nil, err
}
user = string(u)
p, err := auth.Password.GetContent(ctx, r.Client)
if err != nil {
return nil, err
}
password = string(p)
}
eps := make([]datastore.ConnectionEndpoint, 0, len(ds.Spec.Endpoints))
for _, ep := range ds.Spec.Endpoints {
host, stringPort, err := net.SplitHostPort(ep)
if err != nil {
return nil, errors.Wrap(err, "cannot retrieve host-port pair from DataStore endpoints")
}
port, err := strconv.Atoi(stringPort)
if err != nil {
return nil, errors.Wrap(err, "cannot convert port from string for the given DataStore")
}
eps = append(eps, datastore.ConnectionEndpoint{
Host: host,
Port: port,
})
}
cc := datastore.ConnectionConfig{
User: user,
Password: password,
Endpoints: eps,
TLSConfig: &tls.Config{
RootCAs: rootCAs,
Certificates: []tls.Certificate{certificate},
},
}
switch ds.Spec.Driver {
case kamajiv1alpha1.KineMySQLDriver:
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
return datastore.NewMySQLConnection(cc)
case kamajiv1alpha1.KinePostgreSQLDriver:
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
//nolint:contextcheck
return datastore.NewPostgreSQLConnection(cc)
case kamajiv1alpha1.EtcdDriver:
return datastore.NewETCDConnection(cc)
default:
return nil, fmt.Errorf("%s is not a valid driver", ds.Spec.Driver)
}
}

View File

@@ -0,0 +1,8 @@
// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package controllers
import "sigs.k8s.io/controller-runtime/pkg/event"
type TenantControlPlaneChannel chan event.GenericEvent

View File

@@ -6,55 +6,55 @@ package controllers
import (
"context"
"fmt"
"strings"
"github.com/google/uuid"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/source"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
kamajierrors "github.com/clastix/kamaji/internal/errors"
"github.com/clastix/kamaji/internal/resources"
)
const (
separator = ","
finalizer = "finalizer.kamaji.clastix.io"
tenantControlPlaneFinalizer = "finalizer.kamaji.clastix.io"
)
// TenantControlPlaneReconciler reconciles a TenantControlPlane object.
type TenantControlPlaneReconciler struct {
client.Client
Scheme *runtime.Scheme
Config TenantControlPlaneReconcilerConfig
Scheme *runtime.Scheme
Config TenantControlPlaneReconcilerConfig
TriggerChan TenantControlPlaneChannel
}
// TenantControlPlaneReconcilerConfig gives the necessary configuration for TenantControlPlaneReconciler.
type TenantControlPlaneReconcilerConfig struct {
ETCDCASecretName string
ETCDCASecretNamespace string
ETCDClientSecretName string
ETCDClientSecretNamespace string
ETCDEndpoints string
ETCDCompactionInterval string
TmpBaseDirectory string
DefaultDataStoreName string
KineContainerImage string
TmpBaseDirectory string
}
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=tenantcontrolplanes,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=tenantcontrolplanes/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=kamaji.clastix.io,resources=tenantcontrolplanes/finalizers,verbs=update
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete
func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
@@ -62,6 +62,8 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
tenantControlPlane := &kamajiv1alpha1.TenantControlPlane{}
isTenantControlPlane, err := r.getTenantControlPlane(ctx, req.NamespacedName, tenantControlPlane)
if err != nil {
log.Error(err, "cannot retrieve the required instance")
return ctrl.Result{}, err
}
if !isTenantControlPlane {
@@ -69,196 +71,87 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
}
markedToBeDeleted := tenantControlPlane.GetDeletionTimestamp() != nil
hasFinalizer := hasFinalizer(*tenantControlPlane)
hasFinalizer := controllerutil.ContainsFinalizer(tenantControlPlane, tenantControlPlaneFinalizer)
if markedToBeDeleted && !hasFinalizer {
return ctrl.Result{}, nil
}
// Retrieving the DataStore to use for the current reconciliation
ds, err := r.dataStore(ctx, tenantControlPlane)
if err != nil {
log.Error(err, "cannot retrieve the DataStore for the given instance")
return ctrl.Result{}, err
}
dsConnection, err := r.getStorageConnection(ctx, *ds)
if err != nil {
log.Error(err, "cannot generate the DataStore connection for the given instance")
return ctrl.Result{}, err
}
defer dsConnection.Close()
if markedToBeDeleted {
registeredDeleteableResources := []resources.DeleteableResource{
&resources.ETCDSetupResource{
Name: "etcd-setup",
Client: r.Client,
Scheme: r.Scheme,
Log: log,
ETCDClientCertsSecret: getNamespacedName(r.Config.ETCDClientSecretNamespace, r.Config.ETCDClientSecretName),
ETCDCACertsSecret: getNamespacedName(r.Config.ETCDCASecretNamespace, r.Config.ETCDCASecretName),
Endpoints: getArrayFromString(r.Config.ETCDEndpoints),
},
}
log.Info("marked for deletion, performing clean-up")
groupDeleteableResourceBuilderConfiguration := GroupDeleteableResourceBuilderConfiguration{
client: r.Client,
log: log,
tcpReconcilerConfig: r.Config,
tenantControlPlane: *tenantControlPlane,
connection: dsConnection,
}
registeredDeletableResources := GetDeletableResources(groupDeleteableResourceBuilderConfiguration)
for _, resource := range registeredDeletableResources {
if err = resources.HandleDeletion(ctx, resource, tenantControlPlane); err != nil {
log.Error(err, "resource deletion failed", "resource", resource.GetName())
for _, resource := range registeredDeleteableResources {
if err := resource.Delete(ctx, tenantControlPlane); err != nil {
return ctrl.Result{}, err
}
}
if hasFinalizer {
controllerutil.RemoveFinalizer(tenantControlPlane, finalizer)
if err := r.Update(ctx, tenantControlPlane); err != nil {
log.Info("removing finalizer")
if err = r.RemoveFinalizer(ctx, tenantControlPlane); err != nil {
log.Error(err, "cannot remove the finalizer for the given resource")
return ctrl.Result{}, err
}
}
log.Info("resource deletion has been completed")
return ctrl.Result{}, nil
}
if !hasFinalizer {
controllerutil.AddFinalizer(tenantControlPlane, finalizer)
if err := r.Update(ctx, tenantControlPlane); err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
return ctrl.Result{}, r.AddFinalizer(ctx, tenantControlPlane)
}
registeredResources := []resources.Resource{
&resources.KubernetesServiceResource{
Client: r.Client,
},
&resources.KubeadmConfigResource{
Name: "kubeadmconfig",
Port: tenantControlPlane.Spec.NetworkProfile.Port,
KubernetesVersion: tenantControlPlane.Spec.Kubernetes.Version,
PodCIDR: tenantControlPlane.Spec.NetworkProfile.PodCIDR,
ServiceCIDR: tenantControlPlane.Spec.NetworkProfile.ServiceCIDR,
Domain: tenantControlPlane.Spec.NetworkProfile.Domain,
ETCDs: getArrayFromString(r.Config.ETCDEndpoints),
ETCDCompactionInterval: r.Config.ETCDCompactionInterval,
Client: r.Client,
Scheme: r.Scheme,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.CACertificate{
Name: "ca",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.FrontProxyCACertificate{
Name: "front-proxy-ca-certificate",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.SACertificate{
Name: "sa-certificate",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.APIServerCertificate{
Name: "api-server-certificate",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.APIServerKubeletClientCertificate{
Name: "api-server-kubelet-client-certificate",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.FrontProxyClientCertificate{
Name: "front-proxy-client-certificate",
Client: r.Client,
Log: log,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.KubeconfigResource{
Name: "admin-kubeconfig",
Client: r.Client,
Scheme: r.Scheme,
Log: log,
KubeConfigFileName: resources.AdminKubeConfigFileName,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.KubeconfigResource{
Name: "controller-manager-kubeconfig",
Client: r.Client,
Scheme: r.Scheme,
Log: log,
KubeConfigFileName: resources.ControllerManagerKubeConfigFileName,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.KubeconfigResource{
Name: "scheduler-kubeconfig",
Client: r.Client,
Scheme: r.Scheme,
Log: log,
KubeConfigFileName: resources.SchedulerKubeConfigFileName,
TmpDirectory: getTmpDirectory(r.Config.TmpBaseDirectory, *tenantControlPlane),
},
&resources.ETCDCACertificatesResource{
Name: "etcd-ca-certificates",
Client: r.Client,
Log: log,
ETCDCASecretName: r.Config.ETCDCASecretName,
ETCDCASecretNamespace: r.Config.ETCDCASecretNamespace,
},
&resources.ETCDCertificatesResource{
Name: "etcd-certificates",
Client: r.Client,
Log: log,
},
&resources.ETCDSetupResource{
Name: "etcd-setup",
Client: r.Client,
Scheme: r.Scheme,
Log: log,
ETCDClientCertsSecret: getNamespacedName(r.Config.ETCDClientSecretNamespace, r.Config.ETCDClientSecretName),
ETCDCACertsSecret: getNamespacedName(r.Config.ETCDCASecretNamespace, r.Config.ETCDCASecretName),
Endpoints: getArrayFromString(r.Config.ETCDEndpoints),
},
&resources.KubernetesUpgrade{
Name: "upgrade",
Client: r.Client,
},
&resources.KubernetesDeploymentResource{
Client: r.Client,
ETCDEndpoints: getArrayFromString(r.Config.ETCDEndpoints),
ETCDCompactionInterval: r.Config.ETCDCompactionInterval,
},
&resources.KubernetesIngressResource{
Client: r.Client,
},
&resources.KubeadmPhaseResource{
Name: "upload-config-kubeadm",
Client: r.Client,
Log: log,
KubeadmPhase: resources.PhaseUploadConfigKubeadm,
},
&resources.KubeadmPhaseResource{
Name: "upload-config-kubelet",
Client: r.Client,
Log: log,
KubeadmPhase: resources.PhaseUploadConfigKubelet,
},
&resources.KubeadmPhaseResource{
Name: "addon-coredns",
Client: r.Client,
Log: log,
KubeadmPhase: resources.PhaseAddonCoreDNS,
},
&resources.KubeadmPhaseResource{
Name: "addon-kubeproxy",
Client: r.Client,
Log: log,
KubeadmPhase: resources.PhaseAddonKubeProxy,
},
&resources.KubeadmPhaseResource{
Name: "bootstrap-token",
Client: r.Client,
Log: log,
KubeadmPhase: resources.PhaseBootstrapToken,
},
groupResourceBuilderConfiguration := GroupResourceBuilderConfiguration{
client: r.Client,
log: log,
tcpReconcilerConfig: r.Config,
tenantControlPlane: *tenantControlPlane,
DataStore: *ds,
Connection: dsConnection,
}
registeredResources := GetResources(groupResourceBuilderConfiguration)
for _, resource := range registeredResources {
result, err := resources.Handle(ctx, resource, tenantControlPlane)
if err != nil {
if kamajierrors.ShouldReconcileErrorBeIgnored(err) {
log.V(1).Info("sentinel error, enqueuing back request", "error", err.Error())
return ctrl.Result{Requeue: true}, nil
}
log.Error(err, "handling of resource failed", "resource", resource.GetName())
return ctrl.Result{}, err
}
@@ -267,6 +160,8 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
}
if err := r.updateStatus(ctx, req.NamespacedName, resource); err != nil {
log.Error(err, "update of the resource failed", "resource", resource.GetName())
return ctrl.Result{}, err
}
@@ -275,12 +170,22 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
return ctrl.Result{}, nil
}
log.Info(fmt.Sprintf("%s has been reconciled", tenantControlPlane.GetName()))
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *TenantControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Watches(&source.Channel{Source: r.TriggerChan}, handler.Funcs{GenericFunc: func(genericEvent event.GenericEvent, limitingInterface workqueue.RateLimitingInterface) {
limitingInterface.AddRateLimited(ctrl.Request{
NamespacedName: k8stypes.NamespacedName{
Namespace: genericEvent.Object.GetNamespace(),
Name: genericEvent.Object.GetName(),
},
})
}}).
For(&kamajiv1alpha1.TenantControlPlane{}).
Owns(&corev1.Secret{}).
Owns(&corev1.ConfigMap{}).
@@ -324,27 +229,34 @@ func (r *TenantControlPlaneReconciler) updateStatus(ctx context.Context, namespa
return nil
}
func getArrayFromString(s string) []string {
var a []string
a = append(a, strings.Split(s, separator)...)
func (r *TenantControlPlaneReconciler) AddFinalizer(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
controllerutil.AddFinalizer(tenantControlPlane, tenantControlPlaneFinalizer)
return a
return r.Update(ctx, tenantControlPlane)
}
func getNamespacedName(namespace string, name string) k8stypes.NamespacedName {
return k8stypes.NamespacedName{Namespace: namespace, Name: name}
func (r *TenantControlPlaneReconciler) RemoveFinalizer(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
controllerutil.RemoveFinalizer(tenantControlPlane, tenantControlPlaneFinalizer)
return r.Update(ctx, tenantControlPlane)
}
func getTmpDirectory(base string, tenantControlPlane kamajiv1alpha1.TenantControlPlane) string {
return fmt.Sprintf("%s/%s/%s", base, tenantControlPlane.GetName(), uuid.New())
}
func hasFinalizer(tenantControlPlane kamajiv1alpha1.TenantControlPlane) bool {
for _, f := range tenantControlPlane.GetFinalizers() {
if f == finalizer {
return true
}
// dataStore retrieves the override DataStore for the given Tenant Control Plane if specified,
// otherwise fallback to the default one specified in the Kamaji setup.
func (r *TenantControlPlaneReconciler) dataStore(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kamajiv1alpha1.DataStore, error) {
dataStoreName := tenantControlPlane.Spec.DataStore
if len(dataStoreName) == 0 {
dataStoreName = r.Config.DefaultDataStoreName
}
return false
if statusDataStore := tenantControlPlane.Status.Storage.DataStoreName; len(statusDataStore) > 0 && dataStoreName != statusDataStore {
return nil, fmt.Errorf("migration from a DataStore (current: %s) to another one (desired: %s) is not yet supported", statusDataStore, dataStoreName)
}
ds := &kamajiv1alpha1.DataStore{}
if err := r.Client.Get(ctx, k8stypes.NamespacedName{Name: dataStoreName}, ds); err != nil {
return nil, errors.Wrap(err, "cannot retrieve *kamajiv1alpha.DataStore object")
}
return ds, nil
}

View File

@@ -1,680 +0,0 @@
---
# Source: calico/templates/calico-config.yaml
# This ConfigMap is used to configure a self-hosted Calico installation.
kind: ConfigMap
apiVersion: v1
metadata:
name: calico-config
namespace: kube-system
data:
# Typha is disabled.
typha_service_name: "none"
# Configure the backend to use.
calico_backend: "vxlan"
# Configure the MTU to use for workload interfaces and tunnels.
# By default, MTU is auto-detected, and explicitly setting this field should not be required.
# You can override auto-detection by providing a non-zero value.
veth_mtu: "0"
# The CNI network configuration to install on each node. The special
# values in this config will be automatically populated.
cni_network_config: |-
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"log_level": "info",
"log_file_path": "/var/log/calico/cni/cni.log",
"datastore_type": "kubernetes",
"nodename": "__KUBERNETES_NODE_NAME__",
"mtu": __CNI_MTU__,
"ipam": {
"type": "calico-ipam"
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "__KUBECONFIG_FILEPATH__"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
]
}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: calico-node
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- namespaces
verbs:
- get
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- watch
- list
- apiGroups:
- ""
resources:
- endpoints
- services
verbs:
- watch
- list
- get
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
- update
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- watch
- list
- apiGroups:
- ""
resources:
- pods
- namespaces
- serviceaccounts
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- pods/status
verbs:
- patch
- apiGroups:
- crd.projectcalico.org
resources:
- globalfelixconfigs
- felixconfigurations
- bgppeers
- globalbgpconfigs
- bgpconfigurations
- ippools
- ipamblocks
- globalnetworkpolicies
- globalnetworksets
- networkpolicies
- networksets
- clusterinformations
- hostendpoints
- blockaffinities
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- ippools
- felixconfigurations
- clusterinformations
verbs:
- create
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- bgpconfigurations
- bgppeers
verbs:
- create
- update
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
- ipamblocks
- ipamhandles
verbs:
- get
- list
- create
- update
- delete
- apiGroups:
- crd.projectcalico.org
resources:
- ipamconfigs
verbs:
- get
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
verbs:
- watch
- apiGroups:
- apps
resources:
- daemonsets
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: calico-kube-controllers
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- watch
- list
- get
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- ippools
verbs:
- list
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
- ipamblocks
- ipamhandles
verbs:
- get
- list
- create
- update
- delete
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- hostendpoints
verbs:
- get
- list
- create
- update
- delete
- apiGroups:
- crd.projectcalico.org
resources:
- clusterinformations
verbs:
- get
- create
- update
- apiGroups:
- crd.projectcalico.org
resources:
- kubecontrollersconfigurations
verbs:
- get
- create
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: calico-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: calico-node
subjects:
- kind: ServiceAccount
name: calico-node
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: calico-kube-controllers
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: calico-kube-controllers
subjects:
- kind: ServiceAccount
name: calico-kube-controllers
namespace: kube-system
---
# Source: calico/templates/calico-node.yaml
# This manifest installs the calico-node container, as well
# as the CNI plugins and network config on
# each master and worker node in a Kubernetes cluster.
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: calico-node
namespace: kube-system
labels:
k8s-app: calico-node
spec:
selector:
matchLabels:
k8s-app: calico-node
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
k8s-app: calico-node
spec:
nodeSelector:
kubernetes.io/os: linux
hostNetwork: true
tolerations:
# Make sure calico-node gets scheduled on all nodes.
- effect: NoSchedule
operator: Exists
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
serviceAccountName: calico-node
# Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
# deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
terminationGracePeriodSeconds: 0
priorityClassName: system-node-critical
initContainers:
# This container performs upgrade from host-local IPAM to calico-ipam.
# It can be deleted if this is a fresh installation, or if you have already
# upgraded to use calico-ipam.
- name: upgrade-ipam
image: docker.io/calico/cni:v3.20.0
command: ["/opt/cni/bin/calico-ipam", "-upgrade"]
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: CALICO_NETWORKING_BACKEND
valueFrom:
configMapKeyRef:
name: calico-config
key: calico_backend
volumeMounts:
- mountPath: /var/lib/cni/networks
name: host-local-net-dir
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
securityContext:
privileged: true
# This container installs the CNI binaries
# and CNI network config file on each node.
- name: install-cni
image: docker.io/calico/cni:v3.20.0
command: ["/opt/cni/bin/install"]
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
# Name of the CNI config file to create.
- name: CNI_CONF_NAME
value: "10-calico.conflist"
# The CNI network config to install on each node.
- name: CNI_NETWORK_CONFIG
valueFrom:
configMapKeyRef:
name: calico-config
key: cni_network_config
# Set the hostname based on the k8s node name.
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# CNI MTU Config variable
- name: CNI_MTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Prevents the container from sleeping forever.
- name: SLEEP
value: "false"
volumeMounts:
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
securityContext:
privileged: true
# Adds a Flex Volume Driver that creates a per-pod Unix Domain Socket to allow Dikastes
# to communicate with Felix over the Policy Sync API.
- name: flexvol-driver
image: docker.io/calico/pod2daemon-flexvol:v3.20.0
volumeMounts:
- name: flexvol-driver-host
mountPath: /host/driver
securityContext:
privileged: true
containers:
# Runs calico-node container on each Kubernetes node. This
# container programs network policy and routes on each
# host.
- name: calico-node
image: docker.io/calico/node:v3.20.0
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
# Use Kubernetes API as the backing datastore.
- name: DATASTORE_TYPE
value: "kubernetes"
# Wait for the datastore.
- name: WAIT_FOR_DATASTORE
value: "true"
# Set based on the k8s node name.
- name: NODENAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# Choose the backend to use.
- name: CALICO_NETWORKING_BACKEND
valueFrom:
configMapKeyRef:
name: calico-config
key: calico_backend
# Cluster type to identify the deployment type
- name: CLUSTER_TYPE
value: "k8s"
# Auto-detect the BGP IP address.
- name: IP
value: "autodetect"
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
value: "Never"
# Enable or Disable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: "Always"
# Set MTU for tunnel device used if ipip is enabled
- name: FELIX_IPINIPMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Set MTU for the VXLAN tunnel device.
- name: FELIX_VXLANMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Set MTU for the Wireguard tunnel device.
- name: FELIX_WIREGUARDMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# The default IPv4 pool to create on startup if none exists. Pod IPs will be
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV4POOL_CIDR
value: "10.36.0.0/16"
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
value: "true"
# Set Felix endpoint to host default action to ACCEPT.
- name: FELIX_DEFAULTENDPOINTTOHOSTACTION
value: "ACCEPT"
# Disable IPv6 on Kubernetes.
- name: FELIX_IPV6SUPPORT
value: "false"
- name: FELIX_HEALTHENABLED
value: "true"
securityContext:
privileged: true
resources:
requests:
cpu: 250m
livenessProbe:
exec:
command:
- /bin/calico-node
- -felix-live
#- -bird-live
periodSeconds: 10
initialDelaySeconds: 10
failureThreshold: 6
timeoutSeconds: 10
readinessProbe:
exec:
command:
- /bin/calico-node
- -felix-ready
#- -bird-ready
periodSeconds: 10
timeoutSeconds: 10
volumeMounts:
# For maintaining CNI plugin API credentials.
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
readOnly: false
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- mountPath: /run/xtables.lock
name: xtables-lock
readOnly: false
- mountPath: /var/run/calico
name: var-run-calico
readOnly: false
- mountPath: /var/lib/calico
name: var-lib-calico
readOnly: false
- name: policysync
mountPath: /var/run/nodeagent
# For eBPF mode, we need to be able to mount the BPF filesystem at /sys/fs/bpf so we mount in the
# parent directory.
- name: sysfs
mountPath: /sys/fs/
# Bidirectional means that, if we mount the BPF filesystem at /sys/fs/bpf it will propagate to the host.
# If the host is known to mount that filesystem already then Bidirectional can be omitted.
mountPropagation: Bidirectional
- name: cni-log-dir
mountPath: /var/log/calico/cni
readOnly: true
volumes:
# Used by calico-node.
- name: lib-modules
hostPath:
path: /lib/modules
- name: var-run-calico
hostPath:
path: /var/run/calico
- name: var-lib-calico
hostPath:
path: /var/lib/calico
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
- name: sysfs
hostPath:
path: /sys/fs/
type: DirectoryOrCreate
# Used to install CNI.
- name: cni-bin-dir
hostPath:
path: /opt/cni/bin
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
# Used to access CNI logs.
- name: cni-log-dir
hostPath:
path: /var/log/calico/cni
# Mount in the directory for host-local IPAM allocations. This is
# used when upgrading from host-local to calico-ipam, and can be removed
# if not using the upgrade-ipam init container.
- name: host-local-net-dir
hostPath:
path: /var/lib/cni/networks
# Used to create per-pod Unix Domain Sockets
- name: policysync
hostPath:
type: DirectoryOrCreate
path: /var/run/nodeagent
# Used to install Flex Volume Driver
- name: flexvol-driver-host
hostPath:
type: DirectoryOrCreate
path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: calico-node
namespace: kube-system
---
# Source: calico/templates/calico-kube-controllers.yaml
# See https://github.com/projectcalico/kube-controllers
apiVersion: apps/v1
kind: Deployment
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
# The controllers can only have a single active instance.
replicas: 1
selector:
matchLabels:
k8s-app: calico-kube-controllers
strategy:
type: Recreate
template:
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
tolerations:
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/master
effect: NoSchedule
serviceAccountName: calico-kube-controllers
priorityClassName: system-cluster-critical
containers:
- name: calico-kube-controllers
image: docker.io/calico/kube-controllers:v3.20.0
resouces:
env:
# Choose which controllers to run.
- name: ENABLED_CONTROLLERS
value: node
- name: DATASTORE_TYPE
value: kubernetes
livenessProbe:
exec:
command:
- /usr/bin/check-status
- -l
periodSeconds: 10
initialDelaySeconds: 10
failureThreshold: 6
timeoutSeconds: 10
readinessProbe:
exec:
command:
- /usr/bin/check-status
- -r
periodSeconds: 10
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: calico-kube-controllers
namespace: kube-system
---
# This manifest creates a Pod Disruption Budget for Controller to allow K8s Cluster Autoscaler to evict
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: calico-kube-controllers

File diff suppressed because it is too large Load Diff

View File

@@ -1,687 +0,0 @@
---
# Source: calico/templates/calico-config.yaml
# This ConfigMap is used to configure a self-hosted Calico installation.
kind: ConfigMap
apiVersion: v1
metadata:
name: calico-config
namespace: kube-system
data:
# Typha is disabled.
typha_service_name: "none"
# Configure the backend to use.
calico_backend: "bird"
# Configure the MTU to use for workload interfaces and tunnels.
# By default, MTU is auto-detected, and explicitly setting this field should not be required.
# You can override auto-detection by providing a non-zero value.
veth_mtu: "0"
# The CNI network configuration to install on each node. The special
# values in this config will be automatically populated.
cni_network_config: |-
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"log_level": "info",
"log_file_path": "/var/log/calico/cni/cni.log",
"datastore_type": "kubernetes",
"nodename": "__KUBERNETES_NODE_NAME__",
"mtu": __CNI_MTU__,
"ipam": {
"type": "calico-ipam"
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "__KUBECONFIG_FILEPATH__"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
]
}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: calico-node
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- namespaces
verbs:
- get
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- watch
- list
- apiGroups:
- ""
resources:
- endpoints
- services
verbs:
- watch
- list
- get
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
- update
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- watch
- list
- apiGroups:
- ""
resources:
- pods
- namespaces
- serviceaccounts
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- pods/status
verbs:
- patch
- apiGroups:
- crd.projectcalico.org
resources:
- globalfelixconfigs
- felixconfigurations
- bgppeers
- globalbgpconfigs
- bgpconfigurations
- ippools
- ipamblocks
- globalnetworkpolicies
- globalnetworksets
- networkpolicies
- networksets
- clusterinformations
- hostendpoints
- blockaffinities
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- ippools
- felixconfigurations
- clusterinformations
verbs:
- create
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- bgpconfigurations
- bgppeers
verbs:
- create
- update
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
- ipamblocks
- ipamhandles
verbs:
- get
- list
- create
- update
- delete
- apiGroups:
- crd.projectcalico.org
resources:
- ipamconfigs
verbs:
- get
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
verbs:
- watch
- apiGroups:
- apps
resources:
- daemonsets
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: calico-kube-controllers
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- watch
- list
- get
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- ippools
verbs:
- list
- apiGroups:
- crd.projectcalico.org
resources:
- blockaffinities
- ipamblocks
- ipamhandles
verbs:
- get
- list
- create
- update
- delete
- watch
- apiGroups:
- crd.projectcalico.org
resources:
- hostendpoints
verbs:
- get
- list
- create
- update
- delete
- apiGroups:
- crd.projectcalico.org
resources:
- clusterinformations
verbs:
- get
- create
- update
- apiGroups:
- crd.projectcalico.org
resources:
- kubecontrollersconfigurations
verbs:
- get
- create
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: calico-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: calico-node
subjects:
- kind: ServiceAccount
name: calico-node
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: calico-kube-controllers
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: calico-kube-controllers
subjects:
- kind: ServiceAccount
name: calico-kube-controllers
namespace: kube-system
---
# Source: calico/templates/calico-node.yaml
# This manifest installs the calico-node container, as well
# as the CNI plugins and network config on
# each master and worker node in a Kubernetes cluster.
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: calico-node
namespace: kube-system
labels:
k8s-app: calico-node
spec:
selector:
matchLabels:
k8s-app: calico-node
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
k8s-app: calico-node
spec:
nodeSelector:
kubernetes.io/os: linux
hostNetwork: true
tolerations:
# Make sure calico-node gets scheduled on all nodes.
- effect: NoSchedule
operator: Exists
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
serviceAccountName: calico-node
# Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
# deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
terminationGracePeriodSeconds: 0
priorityClassName: system-node-critical
initContainers:
# This container performs upgrade from host-local IPAM to calico-ipam.
# It can be deleted if this is a fresh installation, or if you have already
# upgraded to use calico-ipam.
- name: upgrade-ipam
image: docker.io/calico/cni:v3.20.0
command: ["/opt/cni/bin/calico-ipam", "-upgrade"]
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: CALICO_NETWORKING_BACKEND
valueFrom:
configMapKeyRef:
name: calico-config
key: calico_backend
volumeMounts:
- mountPath: /var/lib/cni/networks
name: host-local-net-dir
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
securityContext:
privileged: true
# This container installs the CNI binaries
# and CNI network config file on each node.
- name: install-cni
image: docker.io/calico/cni:v3.20.0
command: ["/opt/cni/bin/install"]
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
# Name of the CNI config file to create.
- name: CNI_CONF_NAME
value: "10-calico.conflist"
# The CNI network config to install on each node.
- name: CNI_NETWORK_CONFIG
valueFrom:
configMapKeyRef:
name: calico-config
key: cni_network_config
# Set the hostname based on the k8s node name.
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# CNI MTU Config variable
- name: CNI_MTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Prevents the container from sleeping forever.
- name: SLEEP
value: "false"
volumeMounts:
- mountPath: /host/opt/cni/bin
name: cni-bin-dir
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
securityContext:
privileged: true
# Adds a Flex Volume Driver that creates a per-pod Unix Domain Socket to allow Dikastes
# to communicate with Felix over the Policy Sync API.
- name: flexvol-driver
image: docker.io/calico/pod2daemon-flexvol:v3.20.0
volumeMounts:
- name: flexvol-driver-host
mountPath: /host/driver
securityContext:
privileged: true
containers:
# Runs calico-node container on each Kubernetes node. This
# container programs network policy and routes on each
# host.
- name: calico-node
image: docker.io/calico/node:v3.20.0
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
# Use Kubernetes API as the backing datastore.
- name: DATASTORE_TYPE
value: "kubernetes"
# Wait for the datastore.
- name: WAIT_FOR_DATASTORE
value: "true"
# Set based on the k8s node name.
- name: NODENAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# Choose the backend to use.
- name: CALICO_NETWORKING_BACKEND
valueFrom:
configMapKeyRef:
name: calico-config
key: calico_backend
# Cluster type to identify the deployment type
- name: CLUSTER_TYPE
value: "k8s"
# Auto-detect the BGP IP address.
- name: IP
value: "autodetect"
- name: IP_AUTODETECTION_METHOD
value: "can-reach=192.168.32.0"
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
value: "Never"
# Enable or Disable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: "Never"
# Set MTU for tunnel device used if ipip is enabled
- name: FELIX_IPINIPMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Set MTU for the VXLAN tunnel device.
- name: FELIX_VXLANMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# Set MTU for the Wireguard tunnel device.
- name: FELIX_WIREGUARDMTU
valueFrom:
configMapKeyRef:
name: calico-config
key: veth_mtu
# The default IPv4 pool to create on startup if none exists. Pod IPs will be
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
# - name: CALICO_IPV4POOL_CIDR
# value: "192.168.0.0/16"
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
value: "true"
# Set Felix endpoint to host default action to ACCEPT.
- name: FELIX_DEFAULTENDPOINTTOHOSTACTION
value: "ACCEPT"
# Disable IPv6 on Kubernetes.
- name: FELIX_IPV6SUPPORT
value: "false"
- name: FELIX_HEALTHENABLED
value: "true"
securityContext:
privileged: true
resources:
requests:
cpu: 250m
livenessProbe:
exec:
command:
- /bin/calico-node
- -felix-live
- -bird-live
periodSeconds: 10
initialDelaySeconds: 10
failureThreshold: 6
timeoutSeconds: 10
readinessProbe:
exec:
command:
- /bin/calico-node
- -felix-ready
- -bird-ready
periodSeconds: 10
timeoutSeconds: 10
volumeMounts:
# For maintaining CNI plugin API credentials.
- mountPath: /host/etc/cni/net.d
name: cni-net-dir
readOnly: false
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- mountPath: /run/xtables.lock
name: xtables-lock
readOnly: false
- mountPath: /var/run/calico
name: var-run-calico
readOnly: false
- mountPath: /var/lib/calico
name: var-lib-calico
readOnly: false
- name: policysync
mountPath: /var/run/nodeagent
# For eBPF mode, we need to be able to mount the BPF filesystem at /sys/fs/bpf so we mount in the
# parent directory.
- name: sysfs
mountPath: /sys/fs/
# Bidirectional means that, if we mount the BPF filesystem at /sys/fs/bpf it will propagate to the host.
# If the host is known to mount that filesystem already then Bidirectional can be omitted.
mountPropagation: Bidirectional
- name: cni-log-dir
mountPath: /var/log/calico/cni
readOnly: true
volumes:
# Used by calico-node.
- name: lib-modules
hostPath:
path: /lib/modules
- name: var-run-calico
hostPath:
path: /var/run/calico
- name: var-lib-calico
hostPath:
path: /var/lib/calico
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
- name: sysfs
hostPath:
path: /sys/fs/
type: DirectoryOrCreate
# Used to install CNI.
- name: cni-bin-dir
hostPath:
path: /opt/cni/bin
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
# Used to access CNI logs.
- name: cni-log-dir
hostPath:
path: /var/log/calico/cni
# Mount in the directory for host-local IPAM allocations. This is
# used when upgrading from host-local to calico-ipam, and can be removed
# if not using the upgrade-ipam init container.
- name: host-local-net-dir
hostPath:
path: /var/lib/cni/networks
# Used to create per-pod Unix Domain Sockets
- name: policysync
hostPath:
type: DirectoryOrCreate
path: /var/run/nodeagent
# Used to install Flex Volume Driver
- name: flexvol-driver-host
hostPath:
type: DirectoryOrCreate
path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: calico-node
namespace: kube-system
---
# Source: calico/templates/calico-kube-controllers.yaml
# See https://github.com/projectcalico/kube-controllers
apiVersion: apps/v1
kind: Deployment
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
# The controllers can only have a single active instance.
replicas: 1
selector:
matchLabels:
k8s-app: calico-kube-controllers
strategy:
type: Recreate
template:
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
nodeSelector:
kubernetes.io/os: linux
tolerations:
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/master
effect: NoSchedule
serviceAccountName: calico-kube-controllers
priorityClassName: system-cluster-critical
containers:
- name: calico-kube-controllers
image: docker.io/calico/kube-controllers:v3.20.0
env:
# Choose which controllers to run.
- name: ENABLED_CONTROLLERS
value: node
- name: DATASTORE_TYPE
value: kubernetes
resources:
livenessProbe:
exec:
command:
- /usr/bin/check-status
- -l
periodSeconds: 10
initialDelaySeconds: 10
failureThreshold: 6
timeoutSeconds: 10
readinessProbe:
exec:
command:
- /usr/bin/check-status
- -r
periodSeconds: 10
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: calico-kube-controllers
namespace: kube-system
---
# This manifest creates a Pod Disruption Budget for Controller to allow K8s Cluster Autoscaler to evict
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: calico-kube-controllers
---

View File

@@ -90,9 +90,10 @@ spec:
- --peer-trusted-ca-file=/etc/etcd/pki/ca.crt
- --peer-cert-file=/etc/etcd/pki/peer.pem
- --peer-key-file=/etc/etcd/pki/peer-key.pem
- --snapshot-count=8000
- --auto-compaction-mode=periodic
- --auto-compaction-retention=5m
- --v=8
- --quota-backend-bytes=8589934592
env:
- name: POD_NAME
valueFrom:
@@ -109,5 +110,4 @@ spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
storage: 8Gi

View File

@@ -1,5 +1,31 @@
# azure parameters
export KAMAJI_REGION=westeurope
export KAMAJI_RG=Kamaji
# https://docs.microsoft.com/en-us/azure/aks/faq#why-are-two-resource-groups-created-with-aks
export KAMAJI_CLUSTER=kamaji
export KAMAJI_NODE_RG=MC_${KAMAJI_RG}_${KAMAJI_CLUSTER}_${KAMAJI_REGION}
export KAMAJI_CLUSTER=kamaji
export KAMAJI_VNET_NAME=kamaji-net
export KAMAJI_VNET_ADDRESS=10.224.0.0/12
export KAMAJI_SUBNET_NAME=kamaji-subnet
export KAMAJI_SUBNET_ADDRESS=10.224.0.0/16
# kamaji parameters
export KAMAJI_NAMESPACE=kamaji-system
# tenant cluster parameters
export TENANT_NAMESPACE=default
export TENANT_NAME=tenant-00
export TENANT_DOMAIN=$KAMAJI_REGION.cloudapp.azure.com
export TENANT_VERSION=v1.25.0
export TENANT_PORT=6443 # port used to expose the tenant api server
export TENANT_PROXY_PORT=8132 # port used to expose the konnectivity server
export TENANT_POD_CIDR=10.36.0.0/16
export TENANT_SVC_CIDR=10.96.0.0/16
export TENANT_DNS_SERVICE=10.96.0.10
export TENANT_VM_SIZE=Standard_D2ds_v4
export TENANT_VM_IMAGE=UbuntuLTS
export TENANT_SUBNET_NAME=$TENANT_NAME-subnet
export TENANT_SUBNET_ADDRESS=10.225.0.0/16
export TENANT_VMSS=$TENANT_NAME-vmss

View File

@@ -1,5 +0,0 @@
# etcd machine addresses
export ETCD0=192.168.32.10
export ETCD1=192.168.32.11
export ETCD2=192.168.32.12
export ETCDHOSTS=($ETCD0 $ETCD1 $ETCD2)

View File

@@ -1,5 +0,0 @@
# etcd endpoints
export ETCD_NAMESPACE=etcd-system
export ETCD0=etcd-0.etcd.${ETCD_NAMESPACE}.svc.cluster.local
export ETCD1=etcd-1.etcd.${ETCD_NAMESPACE}.svc.cluster.local
export ETCD2=etcd-2.etcd.${ETCD_NAMESPACE}.svc.cluster.local

View File

@@ -1,22 +0,0 @@
export KAMAJI_REGION=westeurope
# tenant cluster parameters
export TENANT_NAMESPACE=tenants
export TENANT_NAME=tenant-00
export TENANT_DOMAIN=$KAMAJI_REGION.cloudapp.azure.com
export TENANT_VERSION=v1.23.4
export TENANT_ADDR=10.240.0.100 # IP used to expose the tenant control plane
export TENANT_PORT=6443 # PORT used to expose the tenant control plane
export TENANT_POD_CIDR=10.36.0.0/16
export TENANT_SVC_CIDR=10.96.0.0/16
export TENANT_DNS_SERVICE=10.96.0.10
export TENANT_VM_SIZE=Standard_D2ds_v4
export TENANT_VM_IMAGE=UbuntuLTS
export TENANT_RG=$TENANT_NAME
export TENANT_NSG=$TENANT_NAME-nsg
export TENANT_VNET_NAME=$TENANT_NAME
export TENANT_VNET_ADDRESS=192.168.0.0/16
export TENANT_SUBNET_NAME=$TENANT_NAME-subnet
export TENANT_SUBNET_ADDRESS=192.168.10.0/24
export TENANT_VMSS=$TENANT_NAME-vmss

View File

@@ -1,17 +0,0 @@
# tenant cluster parameters
export TENANT_NAMESPACE=tenants
export TENANT_NAME=tenant-00
export TENANT_DOMAIN=clastix.labs
export TENANT_VERSION=v1.23.1
export TENANT_ADDR=192.168.32.150 # IP used to expose the tenant control plane
export TENANT_PORT=6443 # PORT used to expose the tenant control plane
export TENANT_POD_CIDR=10.36.0.0/16
export TENANT_SVC_CIDR=10.96.0.0/16
export TENANT_DNS_SERVICE=10.96.0.10
# tenant node addresses
export WORKER0=192.168.32.90
export WORKER1=192.168.32.91
export WORKER2=192.168.32.92
export WORKER3=192.168.32.93

18
deploy/kamaji.env Normal file
View File

@@ -0,0 +1,18 @@
# kamaji parameters
export KAMAJI_NAMESPACE=kamaji-system
# tenant cluster parameters
export TENANT_NAMESPACE=default
export TENANT_NAME=tenant-00
export TENANT_DOMAIN=clastix.labs
export TENANT_VERSION=v1.25.0
export TENANT_PORT=6443 # port used to expose the tenant api server
export TENANT_PROXY_PORT=8132 # port used to expose the konnectivity server
export TENANT_POD_CIDR=10.36.0.0/16
export TENANT_SVC_CIDR=10.96.0.0/16
export TENANT_DNS_SERVICE=10.96.0.10
# tenant node addresses
export WORKER0=172.12.0.10
export WORKER1=172.12.0.11
export WORKER2=172.12.0.12

View File

@@ -2,7 +2,7 @@ kind_path := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
include ../etcd/Makefile
.PHONY: kind ingress-nginx kamaji-kind-worker-build
.PHONY: kind ingress-nginx
.DEFAULT_GOAL := kamaji
@@ -11,7 +11,10 @@ prometheus-stack:
helm repo update
helm install prometheus-stack --create-namespace -n monitoring prometheus-community/kube-prometheus-stack
kamaji: kind ingress-nginx etcd-cluster
reqs: kind ingress-nginx etcd-cluster
kamaji: reqs
@kubectl apply -f $(kind_path)/../../config/install.yaml
destroy: kind/destroy etcd-certificates/cleanup
@@ -26,11 +29,5 @@ ingress-nginx: ingress-nginx-install
ingress-nginx-install:
kubectl apply -f $(kind_path)/nginx-deploy.yaml
kamaji-kind-worker-build:
docker build -f $(kind_path)/kamaji-kind-worker.dockerfile -t quay.io/clastix/kamaji-kind-worker:$${WORKER_VERSION:-latest} .
kamaji-kind-worker-push: kamaji-kind-worker-build
docker push quay.io/clastix/kamaji-kind-worker:$${WORKER_VERSION:-latest}
kamaji-kind-worker-join:
$(kind_path)/join-node.bash

View File

@@ -1,33 +0,0 @@
{
"cniVersion": "0.3.1",
"name": "kindnet",
"plugins": [
{
"type": "ptp",
"ipMasq": false,
"ipam": {
"type": "host-local",
"dataDir": "/run/cni-ipam-state",
"routes": [
{
"dst": "0.0.0.0/0"
}
],
"ranges": [
[
{
"subnet": "10.244.0.0/24"
}
]
]
},
"mtu": 1500
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}

View File

@@ -1,177 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2021-12-08T17:49:38Z"
name: etcd
namespace: kamaji-system
---
apiVersion: v1
kind: Service
metadata:
name: etcd-server
namespace: kamaji-system
spec:
type: ClusterIP
ports:
- name: client
port: 2379
protocol: TCP
targetPort: 2379
selector:
app: etcd
---
apiVersion: v1
kind: Service
metadata:
name: etcd
namespace: kamaji-system
spec:
clusterIP: None
ports:
- port: 2379
name: client
- port: 2380
name: peer
selector:
app: etcd
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: etcd
labels:
app: etcd
namespace: kamaji-system
spec:
serviceName: etcd
selector:
matchLabels:
app: etcd
replicas: 3
template:
metadata:
name: etcd
labels:
app: etcd
spec:
serviceAccountName: etcd
volumes:
- name: certs
secret:
secretName: etcd-certs
containers:
- name: etcd
image: quay.io/coreos/etcd:v3.5.1
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer
volumeMounts:
- name: data
mountPath: /var/run/etcd
- name: certs
mountPath: /etc/etcd/pki
command:
- etcd
- --data-dir=/var/run/etcd
- --name=$(POD_NAME)
- --initial-cluster-state=new
- --initial-cluster=etcd-0=https://etcd-0.etcd.$(POD_NAMESPACE).svc.cluster.local:2380,etcd-1=https://etcd-1.etcd.$(POD_NAMESPACE).svc.cluster.local:2380,etcd-2=https://etcd-2.etcd.$(POD_NAMESPACE).svc.cluster.local:2380
- --initial-advertise-peer-urls=https://$(POD_NAME).etcd.$(POD_NAMESPACE).svc.cluster.local:2380
- --initial-cluster-token=kamaji
- --listen-client-urls=https://0.0.0.0:2379
- --advertise-client-urls=https://etcd-0.etcd.$(POD_NAMESPACE).svc.cluster.local:2379,https://etcd-1.etcd.$(POD_NAMESPACE).svc.cluster.local:2379,https://etcd-2.etcd.$(POD_NAMESPACE).svc.cluster.local:2379,https://etcd-server.$(POD_NAMESPACE).svc.cluster.local:2379
- --client-cert-auth=true
- --trusted-ca-file=/etc/etcd/pki/ca.crt
- --cert-file=/etc/etcd/pki/server.pem
- --key-file=/etc/etcd/pki/server-key.pem
- --listen-peer-urls=https://0.0.0.0:2380
- --peer-client-cert-auth=true
- --peer-trusted-ca-file=/etc/etcd/pki/ca.crt
- --peer-cert-file=/etc/etcd/pki/peer.pem
- --peer-key-file=/etc/etcd/pki/peer-key.pem
- --auto-compaction-mode=periodic
- --auto-compaction-retention=5m
- --v=8
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
startupProbe:
failureThreshold: 24
httpGet:
host: 127.0.0.1
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 8Gi
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: etcd
name: etcd-root-client
namespace: kamaji-system
spec:
serviceAccountName: etcd
containers:
- command:
- sleep
- infinity
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: ETCDCTL_ENDPOINTS
value: https://etcd-server.$(POD_NAMESPACE).svc.cluster.local:2379
- name: ETCDCTL_CACERT
value: /opt/certs/ca/ca.crt
- name: ETCDCTL_CERT
value: /opt/certs/root-client-certs/tls.crt
- name: ETCDCTL_KEY
value: /opt/certs/root-client-certs/tls.key
image: quay.io/coreos/etcd:v3.5.1
imagePullPolicy: IfNotPresent
name: etcd-client
resources: {}
volumeMounts:
- name: root-client-certs
mountPath: /opt/certs/root-client-certs
- name: ca
mountPath: /opt/certs/ca
volumes:
- name: root-client-certs
secret:
secretName: root-client-certs
- name: ca
secret:
secretName: etcd-certs

View File

@@ -3,11 +3,12 @@
set -e
# Constants
export DOCKER_IMAGE_NAME="quay.io/clastix/kamaji-kind-worker"
export DOCKER_IMAGE_NAME="kindest/node"
export DOCKER_NETWORK="kind"
# Variables
export KUBERNETES_VERSION=${1:-latest}
export KUBERNETES_VERSION=${1:-v1.23.5}
export KUBECONFIG="${KUBECONFIG:-/tmp/kubeconfig}"
if [ -z $2 ]
then
@@ -24,9 +25,12 @@ kubectl cluster-info
echo "Are you pointing to the right tenant control plane? (Type return to continue)"
read
JOIN_CMD="$(kubeadm --kubeconfig=/tmp/kubeconfig token create --print-join-command) --ignore-preflight-errors=SystemVerification"
JOIN_CMD="$(kubeadm --kubeconfig=${KUBECONFIG} token create --print-join-command) --ignore-preflight-errors=SystemVerification"
echo "Deploying new node..."
NODE=$(docker run -d --privileged -v /lib/modules:/lib/modules:ro -v /var --net $DOCKER_NETWORK $MAPPING_PORT $DOCKER_IMAGE_NAME:$KUBERNETES_VERSION)
sleep 10
echo "Joining new node..."
docker exec -e JOIN_CMD="$JOIN_CMD" $NODE /bin/bash -c "$JOIN_CMD"
echo "Node has joined! Remember to install the kind-net CNI by issuing the following command:"
echo " $: kubectl apply -f https://raw.githubusercontent.com/aojea/kindnet/master/install-kindnet.yaml"

View File

@@ -1,4 +0,0 @@
ARG KUBERNETES_VERSION=v1.23.4
FROM kindest/node:$KUBERNETES_VERSION
COPY ./cni-kindnet-config.json /etc/cni/net.d/10-kindnet.conflist

View File

@@ -10,6 +10,10 @@ nodes:
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
## required for Cluster API local development
extraMounts:
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
extraPortMappings:
## expose port 80 of the node to port 80 on the host
- containerPort: 80
@@ -19,12 +23,15 @@ nodes:
- containerPort: 443
hostPort: 443
protocol: TCP
## expose port 31132 of the node to port 31132 on the host for konnectivity
- containerPort: 31132
hostPort: 31132
protocol: TCP
## expose port 31443 of the node to port 31443 on the host
- containerPort: 31443
hostPort: 31443
protocol: TCP
protocol: TCP
## expose port 6443 of the node to port 8443 on the host
- containerPort: 6443
hostPort: 8443
protocol: TCP

View File

@@ -0,0 +1,32 @@
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
mariadb: mariadb-certificates mariadb-secret mariadb-deployment
mariadb-certificates:
rm -rf $(ROOT_DIR)/certs && mkdir $(ROOT_DIR)/certs
cfssl gencert -initca $(ROOT_DIR)/ca-csr.json | cfssljson -bare $(ROOT_DIR)/certs/ca
@mv $(ROOT_DIR)/certs/ca.pem $(ROOT_DIR)/certs/ca.crt
@mv $(ROOT_DIR)/certs/ca-key.pem $(ROOT_DIR)/certs/ca.key
cfssl gencert -ca=$(ROOT_DIR)/certs/ca.crt -ca-key=$(ROOT_DIR)/certs/ca.key \
-config=$(ROOT_DIR)/config.json -profile=server \
$(ROOT_DIR)/server-csr.json | cfssljson -bare $(ROOT_DIR)/certs/server
@mv $(ROOT_DIR)/certs/server.pem $(ROOT_DIR)/certs/server.crt
@mv $(ROOT_DIR)/certs/server-key.pem $(ROOT_DIR)/certs/server.key
chmod 644 $(ROOT_DIR)/certs/*
mariadb-secret:
@kubectl create namespace kamaji-system --dry-run=client -o yaml | kubectl apply -f -
@kubectl -n kamaji-system create secret generic mysql-config \
--from-file=$(ROOT_DIR)/certs/ca.crt --from-file=$(ROOT_DIR)/certs/ca.key \
--from-file=$(ROOT_DIR)/certs/server.key --from-file=$(ROOT_DIR)/certs/server.crt \
--from-file=$(ROOT_DIR)/mysql-ssl.cnf \
--from-literal=MYSQL_ROOT_PASSWORD=root \
--dry-run=client -o yaml | kubectl apply -f -
mariadb-deployment:
@kubectl -n kamaji-system apply -f $(ROOT_DIR)/mariadb.yaml
mariadb-destroy:
@kubectl delete -n kamaji-system -f $(ROOT_DIR)/mariadb.yaml --ignore-not-found
@kubectl delete -n kamaji-system secret mysql-config --ignore-not-found
@kubectl delete -n kamaji-system secret kine-secret --ignore-not-found

View File

@@ -0,0 +1,18 @@
{
"CN": "Clastix CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "IT",
"ST": "Italy",
"L": "Milan"
}
],
"hosts": [
"127.0.0.1",
"localhost"
]
}

View File

@@ -0,0 +1,18 @@
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"server": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}

View File

@@ -0,0 +1,61 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kine-tenant
namespace:
---
apiVersion: v1
kind: Service
metadata:
name: kine-tenant
namespace:
spec:
type: ClusterIP
ports:
- name: server
port: 2379
protocol: TCP
targetPort: 2379
selector:
app: kine-tenant
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kine-tenant
labels:
app: kine-tenant
namespace:
spec:
selector:
matchLabels:
app: kine-tenant
replicas: 1
template:
metadata:
name: kine-tenant
labels:
app: kine-tenant
spec:
serviceAccountName: kine-tenant
volumes:
- name: certs
secret:
secretName: mysql-certs
containers:
- name: kine-tenant
image: rancher/kine:v0.9.2-amd64
ports:
- containerPort: 2379
name: server
volumeMounts:
- name: certs
mountPath: /kine
env:
- name: GODEBUG
value: "x509ignoreCN=0"
args:
- --endpoint=mysql://tenant1:tenant1@tcp(mysql:3306)/tenant1
- --ca-file=/kine/ca.crt
- --cert-file=/kine/server.crt
- --key-file=/kine/server.key

View File

@@ -0,0 +1,77 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: mariadb
namespace:
---
apiVersion: v1
kind: Service
metadata:
name: mariadb
namespace:
spec:
type: ClusterIP
ports:
- name: server
port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mariadb
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb
labels:
app: mariadb
namespace:
spec:
selector:
matchLabels:
app: mariadb
replicas: 1
template:
metadata:
name: mariadb
labels:
app: mariadb
spec:
serviceAccountName: mariadb
volumes:
- name: certs
secret:
secretName: mysql-config
- name: data
persistentVolumeClaim:
claimName: pvc-mariadb
containers:
- name: mariadb
image: mariadb:10.7.4
ports:
- containerPort: 3306
name: server
volumeMounts:
- name: data
mountPath: /var/lib/mariadb
- name: certs
mountPath: /etc/mysql/conf.d/
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-config
key: MYSQL_ROOT_PASSWORD
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-mariadb
namespace:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: standard

View File

@@ -0,0 +1,5 @@
[mysqld]
ssl-ca=/etc/mysql/conf.d/ca.crt
ssl-cert=/etc/mysql/conf.d/server.crt
ssl-key=/etc/mysql/conf.d/server.key
require_secure_transport=ON

View File

@@ -0,0 +1,19 @@
{
"CN": "mariadb.kamaji-system.svc.cluster.local",
"key": {
"algo": "rsa",
"size": 2048
},
"hosts": [
"127.0.0.1",
"localhost",
"mariadb",
"mariadb.kamaji-system",
"mariadb.kamaji-system.svc",
"mariadb.kamaji-system.svc.cluster.local",
"mysql",
"mysql.kamaji-system",
"mysql.kamaji-system.svc",
"mysql.kamaji-system.svc.cluster.local"
]
}

View File

@@ -0,0 +1,27 @@
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
postgresql: cnpg-setup cnpg-deploy postgresql-secret
cnpg-setup:
@kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.16.0.yaml
cnpg-deploy:
@kubectl -n cnpg-system rollout status deployment/cnpg-controller-manager
@kubectl create namespace kamaji-system --dry-run=client -o yaml | kubectl apply -f -
@kubectl -n kamaji-system apply -f postgresql.yaml
@while ! kubectl -n kamaji-system get secret postgresql-superuser > /dev/null 2>&1; do sleep 1; done
CNPG = $(shell git rev-parse --show-toplevel)/bin/kubectl-cnpg
cnpg:
@test -f $(shell git rev-parse --show-toplevel)/bin/kubectl-cnpg || curl -sSfL \
https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | \
sh -s -- -b $(shell git rev-parse --show-toplevel)/bin
postgresql-secret: cnpg
@kubectl -n kamaji-system get secret postgres-root-cert > /dev/null 2>&1 || $(CNPG) -n kamaji-system certificate postgres-root-cert \
--cnpg-cluster postgresql \
--cnpg-user $$(kubectl -n kamaji-system get secret postgresql-superuser -o jsonpath='{.data.username}' | base64 -d)
postgresql-destroy:
@kubectl delete -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.16.0.yaml --ignore-not-found && \
kubectl -n kamaji-system delete secret postgres-root-cert --ignore-not-found

View File

@@ -0,0 +1,13 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: postgresql
spec:
description: PostgreSQL cluster used by Kamaji along with kine
instances: 3
postgresql:
pg_hba:
- hostssl app all all cert # makes authentication entirely based on certificates
primaryUpdateStrategy: unsupervised
storage:
size: 1Gi

4
deploy/nodes-prerequisites.sh Normal file → Executable file
View File

@@ -18,7 +18,9 @@ EOF
for i in "${!HOSTS[@]}"; do
HOST=${HOSTS[$i]}
ssh ${USER}@${HOST} -t 'sudo apt update && sudo apt install -y containerd'
ssh ${USER}@${HOST} -t 'sudo systemctl start containerd && sudo systemctl enable containerd'
ssh ${USER}@${HOST} -t 'sudo mkdir -p /etc/containerd'
ssh ${USER}@${HOST} -t 'containerd config default | sed -e "s#SystemdCgroup = false#SystemdCgroup = true#g" | sudo tee -a /etc/containerd/config.toml'
ssh ${USER}@${HOST} -t 'sudo systemctl restart containerd && sudo systemctl enable containerd'
scp containerd.conf ${USER}@${HOST}:
ssh ${USER}@${HOST} -t 'sudo chown -R root:root containerd.conf && sudo mv containerd.conf /etc/modules-load.d/containerd.conf'
ssh ${USER}@${HOST} -t 'sudo modprobe overlay && sudo modprobe br_netfilter'

View File

@@ -21,10 +21,12 @@ runcmd:
- sudo modprobe overlay
- sudo modprobe br_netfilter
- sudo sysctl --system
- sudo systemctl start containerd
- sudo mkdir -p /etc/containerd
- containerd config default | sed -e 's#SystemdCgroup = false#SystemdCgroup = true#g' | sudo tee -a /etc/containerd/config.toml
- sudo systemctl restart containerd
- sudo systemctl enable containerd
- sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
- echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
- sudo apt update
- sudo apt install -y kubelet kubeadm kubectl containerd
- sudo apt-mark hold kubelet kubeadm kubectl
- sudo apt install -y kubelet=1.25.0-00 kubeadm=1.25.0-00 kubectl=1.25.0-00
- sudo apt-mark hold kubelet kubeadm kubectl containerd

View File

@@ -1 +0,0 @@
# Kamaji architecture

Some files were not shown because too many files have changed in this diff Show More