Compare commits
446 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84c8b1a135 | ||
|
|
7cf930cbe9 | ||
|
|
d5e146ef8f | ||
|
|
cb5fb00d7b | ||
|
|
ed00b934ec | ||
|
|
dbaf3d1915 | ||
|
|
a625f2218c | ||
|
|
617e802d02 | ||
|
|
eca04893a8 | ||
|
|
14c96b034a | ||
|
|
f53271cb87 | ||
|
|
8007fe8cd2 | ||
|
|
11d8262c74 | ||
|
|
877314f53d | ||
|
|
27480ba66a | ||
|
|
d3d18ef836 | ||
|
|
c81d190719 | ||
|
|
9284a43860 | ||
|
|
6cab15551f | ||
|
|
f0fb8b3c11 | ||
|
|
778a34a382 | ||
|
|
25b1c7a8fa | ||
|
|
2c6360ad82 | ||
|
|
523f1cf0e3 | ||
|
|
4d6d1461cc | ||
|
|
49e016d4da | ||
|
|
b7a2d9da8c | ||
|
|
39c7591457 | ||
|
|
327438e236 | ||
|
|
ba4b3eec8f | ||
|
|
d06affc216 | ||
|
|
236540d89f | ||
|
|
a5b7605e27 | ||
|
|
3821cf1d67 | ||
|
|
be1737d908 | ||
|
|
b5a7ff6e6c | ||
|
|
9f937a1eec | ||
|
|
0ae3659949 | ||
|
|
736fbf0505 | ||
|
|
8dc0672718 | ||
|
|
27f598fbfc | ||
|
|
d3603c7187 | ||
|
|
83797fc0b3 | ||
|
|
517a4a3458 | ||
|
|
649cf0c852 | ||
|
|
741090f4e6 | ||
|
|
6e8a86d975 | ||
|
|
21b01fae9d | ||
|
|
a0cd4591a9 | ||
|
|
f757c5a5aa | ||
|
|
b15a764381 | ||
|
|
8d3dcdf467 | ||
|
|
aada5c29a2 | ||
|
|
cb4a493e28 | ||
|
|
f783aff3c0 | ||
|
|
c8bdaf0aa2 | ||
|
|
d1c2fe020e | ||
|
|
5b93d7181f | ||
|
|
1273d95340 | ||
|
|
1e4c78b646 | ||
|
|
903cfc0bae | ||
|
|
7bd142bcb2 | ||
|
|
153a43e6f2 | ||
|
|
2abaeb5586 | ||
|
|
a8a41951cb | ||
|
|
a0485c338b | ||
|
|
89edc8bbf5 | ||
|
|
43765769ec | ||
|
|
0016f121ed | ||
|
|
c3fb5373f6 | ||
|
|
670f10ad4e | ||
|
|
4110b688c9 | ||
|
|
830d86a38a | ||
|
|
44d1f3fa7f | ||
|
|
e23ae3c7f3 | ||
|
|
713b0754bb | ||
|
|
da924b30ff | ||
|
|
0f0d83130f | ||
|
|
634e808d2d | ||
|
|
b99f224d32 | ||
|
|
d02b5f427e | ||
|
|
08b5bc05c3 | ||
|
|
4bd8e2d319 | ||
|
|
a1f155fcab | ||
|
|
743ea1343f | ||
|
|
41780bcb04 | ||
|
|
014297bb0f | ||
|
|
20cfdd6931 | ||
|
|
f03e250cf8 | ||
|
|
2cdee08924 | ||
|
|
6d27ca9e9e | ||
|
|
2293e49e4b | ||
|
|
6b0f92baa3 | ||
|
|
8e94039962 | ||
|
|
551df6df97 | ||
|
|
c905e16e75 | ||
|
|
e08792adc2 | ||
|
|
248b5082d0 | ||
|
|
5cebb05458 | ||
|
|
efbefba0b3 | ||
|
|
bc19203071 | ||
|
|
c8b8dcc2d3 | ||
|
|
cf2721201d | ||
|
|
4aa77924f4 | ||
|
|
a3c52e81f6 | ||
|
|
7ed3c44401 | ||
|
|
beebaf0364 | ||
|
|
b9cda29461 | ||
|
|
7db8a64bdd | ||
|
|
c6abe03fd1 | ||
|
|
723fa1aea6 | ||
|
|
7e0ec81ba2 | ||
|
|
7353bb5813 | ||
|
|
96cedadf0a | ||
|
|
76b603de1e | ||
|
|
7cff6b5850 | ||
|
|
6e6ea0189f | ||
|
|
aefdbc9481 | ||
|
|
074279b3c2 | ||
|
|
09891f4d71 | ||
|
|
18c60461e5 | ||
|
|
ceab662671 | ||
|
|
d38098a57e | ||
|
|
017a50b8f6 | ||
|
|
b07062b4dd | ||
|
|
b880cff8d7 | ||
|
|
3f7fa08871 | ||
|
|
8311f1fe1a | ||
|
|
77fff030bf | ||
|
|
abada61930 | ||
|
|
1eb1e0f17c | ||
|
|
e83c34776b | ||
|
|
3b902943f1 | ||
|
|
c5d62f3d82 | ||
|
|
938341a2e7 | ||
|
|
3ea721cf2b | ||
|
|
5cbd085cf8 | ||
|
|
e358fbe6bc | ||
|
|
9d55e77902 | ||
|
|
1e4640e8e6 | ||
|
|
1b14922f55 | ||
|
|
11f800063f | ||
|
|
e11b459a3d | ||
|
|
9c8de782f3 | ||
|
|
4c51eafc90 | ||
|
|
1a80fc5b28 | ||
|
|
02052d5339 | ||
|
|
7e47e33b39 | ||
|
|
28c47d9d13 | ||
|
|
1ec257a729 | ||
|
|
68006b1102 | ||
|
|
cd109dcf06 | ||
|
|
1138eb1dea | ||
|
|
f4f914098c | ||
|
|
5e78b6392a | ||
|
|
e25f95d7eb | ||
|
|
7f49fc6125 | ||
|
|
8b9683802b | ||
|
|
cb5e35699e | ||
|
|
0d6246c098 | ||
|
|
d8760fdc6e | ||
|
|
c00df62ff7 | ||
|
|
653a3933e8 | ||
|
|
6775b2ae57 | ||
|
|
5241fa64ed | ||
|
|
723fef5336 | ||
|
|
8d1d8598c1 | ||
|
|
c96f58974b | ||
|
|
2d1daa8498 | ||
|
|
fe948298d8 | ||
|
|
79942dda34 | ||
|
|
44919598ec | ||
|
|
2336d402c3 | ||
|
|
79c59e55e5 | ||
|
|
95d0983faa | ||
|
|
7e276e5ba1 | ||
|
|
b2e646064f | ||
|
|
3850ad9752 | ||
|
|
9e899379f4 | ||
|
|
a260a92495 | ||
|
|
cc4864ca9e | ||
|
|
ece1a4e7ee | ||
|
|
eb2440ae62 | ||
|
|
0c415707d7 | ||
|
|
7a6b0a8de3 | ||
|
|
a31fbdc875 | ||
|
|
4ff0cdf28b | ||
|
|
ae573b137c | ||
|
|
e81b3224c2 | ||
|
|
4298bdd73e | ||
|
|
15d0d57790 | ||
|
|
c17a31ef82 | ||
|
|
f0df1cfe6f | ||
|
|
1bcff90785 | ||
|
|
6c817a9ae2 | ||
|
|
5b9311f421 | ||
|
|
0d607dfe5d | ||
|
|
11502bf359 | ||
|
|
ff1c9fca16 | ||
|
|
adc4b7d98c | ||
|
|
a96133f342 | ||
|
|
81fb429c83 | ||
|
|
190acc99b3 | ||
|
|
b0a059d305 | ||
|
|
bcc7d0ebbd | ||
|
|
9dc0a9a168 | ||
|
|
d312738581 | ||
|
|
30bc8cc2bf | ||
|
|
55d7f09a34 | ||
|
|
2c892d79e4 | ||
|
|
43f1a6b95b | ||
|
|
78ef34c9d6 | ||
|
|
16d8b2d701 | ||
|
|
68764be716 | ||
|
|
b594b598b1 | ||
|
|
c8ce212730 | ||
|
|
714b173132 | ||
|
|
0217d579d6 | ||
|
|
c242f4ac58 | ||
|
|
d4d25a8a05 | ||
|
|
cff7f7c4e5 | ||
|
|
6c817fd7ab | ||
|
|
d31ada4da6 | ||
|
|
ee01f721d2 | ||
|
|
912e010363 | ||
|
|
e2b03ca873 | ||
|
|
dccf7bd540 | ||
|
|
25a65a7496 | ||
|
|
1ff03246c6 | ||
|
|
8335f645a5 | ||
|
|
70a791be74 | ||
|
|
b0293c23b5 | ||
|
|
50bba9bb2e | ||
|
|
f05f7eaf07 | ||
|
|
bfd34ef47e | ||
|
|
b73c7a20ed | ||
|
|
004441e77e | ||
|
|
0f85b6c534 | ||
|
|
b674738f0d | ||
|
|
6dc3cd1876 | ||
|
|
96a57fefa5 | ||
|
|
87b6f75f66 | ||
|
|
1b24806fa3 | ||
|
|
f32ba4a76b | ||
|
|
19d91aa4d2 | ||
|
|
a4e2ac24ac | ||
|
|
0dffd9ba46 | ||
|
|
90b2ca1bab | ||
|
|
df8ca7c1d1 | ||
|
|
65519d4f22 | ||
|
|
e0fa8169f1 | ||
|
|
41eddc0462 | ||
|
|
1a9a8a1854 | ||
|
|
0c8a16d604 | ||
|
|
b7adb314ad | ||
|
|
e55e6cfdd4 | ||
|
|
6388bf0a7f | ||
|
|
e089f0ad9a | ||
|
|
0b0bf09813 | ||
|
|
00ea4a562d | ||
|
|
2a33844c68 | ||
|
|
606926ec9a | ||
|
|
84b70b3b59 | ||
|
|
4ca79ceb4c | ||
|
|
8df8aa445a | ||
|
|
8da916b5cd | ||
|
|
f15eeebe02 | ||
|
|
7002d48ef9 | ||
|
|
79edd2606a | ||
|
|
650c20be2b | ||
|
|
7862717772 | ||
|
|
08eed7b244 | ||
|
|
1a561758b6 | ||
|
|
12f12832f7 | ||
|
|
b4d0f9b698 | ||
|
|
14624af093 | ||
|
|
52cdc90b48 | ||
|
|
fbb6e4eec5 | ||
|
|
880a29f543 | ||
|
|
b0b4ef95c6 | ||
|
|
bd909d6567 | ||
|
|
fcc10c95b2 | ||
|
|
7e912ed2e8 | ||
|
|
2374176faf | ||
|
|
aceeced53a | ||
|
|
53c9102ef3 | ||
|
|
15e1cf7d80 | ||
|
|
f853f25195 | ||
|
|
5acdc4cc41 | ||
|
|
360e8200cb | ||
|
|
b0c6972873 | ||
|
|
682006f8aa | ||
|
|
d59f494a69 | ||
|
|
7602d5d803 | ||
|
|
4c04edbfe8 | ||
|
|
cce4225e07 | ||
|
|
10f0021780 | ||
|
|
b99a685e2d | ||
|
|
a8de97e442 | ||
|
|
8273d7c7b4 | ||
|
|
a9ea894e32 | ||
|
|
ff780aaba6 | ||
|
|
1ddaeccc94 | ||
|
|
b23cbe3976 | ||
|
|
a23fcc502f | ||
|
|
baeee457a6 | ||
|
|
d6087949a9 | ||
|
|
ccb54b664c | ||
|
|
fdd1dd645e | ||
|
|
2c963881ab | ||
|
|
8e0b0c8ce7 | ||
|
|
fe231d6130 | ||
|
|
2ec6727de7 | ||
|
|
968b343db9 | ||
|
|
c3b72c8a3b | ||
|
|
f64cf284de | ||
|
|
e12509a970 | ||
|
|
626a0eed64 | ||
|
|
c32a890561 | ||
|
|
2eca4b0eeb | ||
|
|
47fc9fdc63 | ||
|
|
08022fc780 | ||
|
|
f6d330992d | ||
|
|
c449b01121 | ||
|
|
1dcafb91d4 | ||
|
|
766105b50e | ||
|
|
9d5b14f440 | ||
|
|
0954ae7494 | ||
|
|
ec55b203a8 | ||
|
|
d6c65cfbe6 | ||
|
|
99c3b47ec9 | ||
|
|
31b25f7c78 | ||
|
|
06504e7133 | ||
|
|
4e993b7402 | ||
|
|
ebdb24ce45 | ||
|
|
f85ddb1808 | ||
|
|
2b7143294b | ||
|
|
a57f0edd33 | ||
|
|
887655c077 | ||
|
|
f1b1802cf0 | ||
|
|
60c187464d | ||
|
|
3974214d6a | ||
|
|
f9c776bda5 | ||
|
|
1d6be44edf | ||
|
|
dce6c1330a | ||
|
|
922324a71b | ||
|
|
5da7058ed3 | ||
|
|
f7483dcb01 | ||
|
|
e4227e1c81 | ||
|
|
38ba07f3a4 | ||
|
|
5e5bd83b69 | ||
|
|
97a05b5f49 | ||
|
|
502cb64a5c | ||
|
|
c3ad545c97 | ||
|
|
0c634d1c16 | ||
|
|
cef05c3310 | ||
|
|
dce027b8f7 | ||
|
|
d1871cf378 | ||
|
|
a573805bad | ||
|
|
6a4baf99fc | ||
|
|
d290e73307 | ||
|
|
62129f3f0c | ||
|
|
a5b2c7825c | ||
|
|
315ef7aa4f | ||
|
|
161f43ed58 | ||
|
|
af6024ece1 | ||
|
|
2656bffc48 | ||
|
|
f496fefce9 | ||
|
|
094ea2b0e0 | ||
|
|
5ff197d2b6 | ||
|
|
b58fef8859 | ||
|
|
260767d770 | ||
|
|
5ecc9aace0 | ||
|
|
b2a23b0691 | ||
|
|
605d54716a | ||
|
|
e1bb7dc96f | ||
|
|
33420fc27a | ||
|
|
ad1abe1ea9 | ||
|
|
9ad5ea506d | ||
|
|
59b7139ada | ||
|
|
3baf187b88 | ||
|
|
942804531e | ||
|
|
0b8f15f86f | ||
|
|
8c24302d8e | ||
|
|
84dce57039 | ||
|
|
c4f9d4f8b3 | ||
|
|
1e9e247e8b | ||
|
|
bcd1627fed | ||
|
|
1d70a5c02b | ||
|
|
7fc19f7008 | ||
|
|
3443ce737c | ||
|
|
5f9927c48b | ||
|
|
eaa6899d50 | ||
|
|
eb699051a1 | ||
|
|
a914bad7ce | ||
|
|
40428c7983 | ||
|
|
938b35122e | ||
|
|
dadc5c4f50 | ||
|
|
a535d05073 | ||
|
|
d547fea661 | ||
|
|
a377bfc1ec | ||
|
|
a2541bfc00 | ||
|
|
c47875345d | ||
|
|
48fdd6088d | ||
|
|
a67e0f51c7 | ||
|
|
3d1bfc42f1 | ||
|
|
e6e51cf624 | ||
|
|
8cac5a0c9b | ||
|
|
b22e11a2a4 | ||
|
|
a4879084f2 | ||
|
|
478b0d5c3a | ||
|
|
9e3173676e | ||
|
|
8f59de6e13 | ||
|
|
3be6cf1c4f | ||
|
|
5b4de76229 | ||
|
|
69801d1fb9 | ||
|
|
ab1818672d | ||
|
|
8cd83da667 | ||
|
|
05562a775b | ||
|
|
2cd255b1c7 | ||
|
|
26ddbc084c | ||
|
|
fb6e24e3e9 | ||
|
|
22f8412daa | ||
|
|
c570afc643 | ||
|
|
357d549b8f | ||
|
|
33ddebc90c | ||
|
|
8be787adc5 | ||
|
|
6b452ccd40 | ||
|
|
0dbd73691c | ||
|
|
f57abb0d2e | ||
|
|
2f76841753 | ||
|
|
6cebf0950d | ||
|
|
6ee5196928 | ||
|
|
261aafbb07 | ||
|
|
de690a4039 | ||
|
|
258b1ff48f | ||
|
|
1d64932265 | ||
|
|
321a955fdb | ||
|
|
ba09748a5b | ||
|
|
a198c21987 | ||
|
|
3279a0e617 | ||
|
|
243dbddc69 | ||
|
|
6d7d900ac2 | ||
|
|
6bf838204d | ||
|
|
c0e718cb07 | ||
|
|
0be08a0099 |
24
.github/workflows/ci.yaml
vendored
@@ -9,25 +9,30 @@ on:
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
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.19'
|
||||
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:
|
||||
name: diff
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- 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.19'
|
||||
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
|
||||
@@ -35,3 +40,8 @@ jobs:
|
||||
run: test -z "$(git ls-files --others --exclude-standard 2> /dev/null)"
|
||||
- name: Checking if source code is not formatted
|
||||
run: test -z "$(git diff 2> /dev/null)"
|
||||
- run: make apidoc
|
||||
- name: Checking if generated API documentation files are 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
|
||||
- name: Checking if generated API documentation generated untracked files
|
||||
run: test -z "$(git ls-files --others --exclude-standard 2> /dev/null)"
|
||||
|
||||
91
.github/workflows/docker-ci.yml
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
name: docker-ci
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
docker-ci:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Generate build-args
|
||||
id: build-args
|
||||
run: |
|
||||
# Declare vars for internal use
|
||||
VERSION=$(git describe --abbrev=0 --tags)
|
||||
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")
|
||||
# Export to GH_ENV
|
||||
echo "GIT_LAST_TAG=$VERSION" >> $GITHUB_ENV
|
||||
echo "GIT_HEAD_COMMIT=$GIT_HEAD_COMMIT" >> $GITHUB_ENV
|
||||
echo "GIT_TAG_COMMIT=$GIT_TAG_COMMIT" >> $GITHUB_ENV
|
||||
echo "GIT_MODIFIED=$(echo "$GIT_MODIFIED_1""$GIT_MODIFIED_2")" >> $GITHUB_ENV
|
||||
echo "GIT_REPO=$(git config --get remote.origin.url)" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(git log -1 --format="%at" | xargs -I{} date -d @{} +%Y-%m-%dT%H:%M:%S)" >> $GITHUB_ENV
|
||||
|
||||
- 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
@@ -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-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
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
@@ -0,0 +1,46 @@
|
||||
name: Helm Chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "*" ]
|
||||
tags: [ "helm-v*" ]
|
||||
pull_request:
|
||||
branches: [ "*" ]
|
||||
|
||||
jobs:
|
||||
diff:
|
||||
name: diff
|
||||
runs-on: ubuntu-22.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-22.04
|
||||
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-22.04
|
||||
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
|
||||
1
.gitignore
vendored
@@ -29,4 +29,5 @@ bin
|
||||
**/*.key
|
||||
**/*.pem
|
||||
**/*.csr
|
||||
**/server-csr.json
|
||||
.DS_Store
|
||||
|
||||
@@ -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
|
||||
|
||||
21
Dockerfile
@@ -1,5 +1,5 @@
|
||||
# Build the manager binary
|
||||
FROM golang:1.17 as builder
|
||||
FROM golang:1.19 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
@@ -11,19 +11,30 @@ RUN go mod download
|
||||
|
||||
# Copy the go source
|
||||
COPY main.go main.go
|
||||
COPY cmd/ cmd/
|
||||
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
|
||||
ARG TARGETARCH
|
||||
ARG GIT_HEAD_COMMIT
|
||||
ARG GIT_TAG_COMMIT
|
||||
ARG GIT_LAST_TAG
|
||||
ARG GIT_MODIFIED
|
||||
ARG GIT_REPO
|
||||
ARG BUILD_DATE
|
||||
|
||||
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 kamaji main.go
|
||||
|
||||
# Use distroless as minimal base image to package the manager binary
|
||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||
FROM gcr.io/distroless/static:nonroot
|
||||
WORKDIR /
|
||||
COPY --from=builder /workspace/manager .
|
||||
COPY ./kamaji.yaml .
|
||||
COPY --from=builder /workspace/kamaji .
|
||||
USER 65532:65532
|
||||
|
||||
ENTRYPOINT ["/manager"]
|
||||
ENTRYPOINT ["/kamaji"]
|
||||
|
||||
176
Makefile
@@ -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.3.0
|
||||
|
||||
# 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,44 +68,125 @@ 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/v2/ginkgo@v2.6.0)
|
||||
|
||||
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.11.4)
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
go test ./... -coverprofile cover.out
|
||||
|
||||
test: manifests generate fmt vet envtest ## Run tests.
|
||||
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out
|
||||
_datastore-mysql:
|
||||
$(MAKE) NAME=$(NAME) -C deploy/kine/mysql mariadb
|
||||
kubectl apply -f $(shell pwd)/config/samples/kamaji_v1alpha1_datastore_mysql_$(NAME).yaml
|
||||
|
||||
datastore-mysql:
|
||||
$(MAKE) NAME=bronze _datastore-mysql
|
||||
$(MAKE) NAME=silver _datastore-mysql
|
||||
$(MAKE) NAME=gold _datastore-mysql
|
||||
|
||||
_datastore-postgres:
|
||||
$(MAKE) NAME=$(NAME) NAMESPACE=postgres-system -C deploy/kine/postgresql postgresql
|
||||
kubectl apply -f $(shell pwd)/config/samples/kamaji_v1alpha1_datastore_postgresql_$(NAME).yaml
|
||||
|
||||
datastore-postgres:
|
||||
$(MAKE) NAME=bronze _datastore-postgres
|
||||
$(MAKE) NAME=silver _datastore-postgres
|
||||
$(MAKE) NAME=gold _datastore-postgres
|
||||
|
||||
_datastore-etcd:
|
||||
$(HELM) upgrade --install etcd-$(NAME) clastix/kamaji-etcd --create-namespace -n etcd-system --set datastore.enabled=true
|
||||
|
||||
datastore-etcd: helm
|
||||
$(HELM) repo add clastix https://clastix.github.io/charts
|
||||
$(HELM) repo update
|
||||
$(MAKE) NAME=bronze _datastore-etcd
|
||||
$(MAKE) NAME=silver _datastore-etcd
|
||||
$(MAKE) NAME=gold _datastore-etcd
|
||||
|
||||
datastores: datastore-mysql datastore-etcd datastore-postgres ## Install all Kamaji DataStores with multiple drivers, and different tiers.
|
||||
|
||||
##@ Build
|
||||
|
||||
# Get information about git current status
|
||||
GIT_HEAD_COMMIT ?= $$(git rev-parse --short HEAD)
|
||||
GIT_TAG_COMMIT ?= $$(git rev-parse --short v$(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}
|
||||
|
||||
##@ Deployment
|
||||
|
||||
metallb:
|
||||
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
|
||||
kubectl apply -f https://kind.sigs.k8s.io/examples/loadbalancer/metallb-config.yaml
|
||||
echo ""
|
||||
docker network inspect -f '{{.IPAM.Config}}' kind
|
||||
|
||||
cert-manager:
|
||||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml
|
||||
|
||||
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 +207,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 +262,40 @@ 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 cert-manager ## 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"
|
||||
$(MAKE) datastores
|
||||
$(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
|
||||
|
||||
7
PROJECT
@@ -16,4 +16,11 @@ resources:
|
||||
kind: TenantControlPlane
|
||||
path: github.com/clastix/kamaji/api/v1alpha1
|
||||
version: v1alpha1
|
||||
- api:
|
||||
crdVersion: v1
|
||||
domain: clastix.io
|
||||
group: kamaji
|
||||
kind: DataStore
|
||||
path: github.com/clastix/kamaji/api/v1alpha1
|
||||
version: v1alpha1
|
||||
version: "3"
|
||||
|
||||
120
README.md
@@ -5,118 +5,64 @@
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/clastix/kamaji"/>
|
||||
<a href="https://github.com/clastix/kamaji/releases">
|
||||
<img src="https://img.shields.io/github/v/release/clastix/kamaji"/>
|
||||
<img src="https://goreportcard.com/badge/github.com/clastix/kamaji">
|
||||
</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.
|
||||

|
||||

|
||||
|
||||
<p align="center" style="padding: 6px 6px">
|
||||
<img src="assets/kamaji-logo.png" />
|
||||
</p>
|
||||
**Kamaji** deploys and operates **Kubernetes Control Plane** at scale with a fraction of the operational burden. Kamaji is special because the Control Plane components are running in a single pod instead of dedicated machines. This solution makes running multiple Control Planes cheaper and easier to deploy and operate.
|
||||
|
||||
> 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.
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
<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 doesn’t 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. We’re 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.
|
||||
<img src="docs/content/images/architecture.png" width="600">
|
||||
|
||||
## 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 clusters from a single admin cluster. Happy SREs.
|
||||
- **Cheaper Control Planes:** place multiple control planes on a single node, instead of having three nodes for a single control plane.
|
||||
- **Stronger Multi-Tenancy:** leave users to access the control plane with admin permissions while keeping them 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:** all clusters are CNCF compliant built with upstream Kubernetes binaries
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] Benchmarking and stress-test
|
||||
- [x] Support for dynamic address allocation on native Load Balancer
|
||||
- [x] Dynamic address on Load Balancer
|
||||
- [x] Zero Downtime Tenant Control Plane upgrade
|
||||
- [ ] `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
|
||||
- [x] Join worker nodes from anywhere
|
||||
- [x] Alternative datastore MySQL and PostgreSQL
|
||||
- [x] Pool of multiple datastores
|
||||
- [x] Seamless migration between datastores
|
||||
- [ ] Automatic assignment to a datastore
|
||||
- [ ] Autoscaling of Tenant Control Plane
|
||||
- [ ] Provisioning through Cluster APIs
|
||||
- [ ] Terraform provider
|
||||
- [ ] Custom Prometheus metrics for monitoring and alerting
|
||||
|
||||
|
||||
## 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.
|
||||
Kamaji is Open Source with Apache 2 license and any contribution is welcome. Open an issue or suggest an enhancement on the GitHub [project's page](https://github.com/clastix/kamaji). 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.
|
||||
|
||||
## FAQ
|
||||
Q. What does Kamaji means?
|
||||
## FAQs
|
||||
Q. What does Kamaji mean?
|
||||
|
||||
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`.
|
||||
A. No, Kamaji is a Kubernetes Operator you can install on top of any Kubernetes cluster to provide hundreds or thousands of managed Kubernetes clusters as a service. We tested Kamaji on vanilla Kubernetes 1.22+, KinD, and Azure AKS. We expect it to work smoothly on other Kubernetes distributions. The tenant clusters made with Kamaji are conformant CNCF Kubernetes clusters as we leverage [`kubeadm`](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/).
|
||||
|
||||
Q. Is it safe to run Kubernetes control plane components in a pod?
|
||||
Q. Is it safe to run Kubernetes control plane components in a pod instead of dedicated virtual machines?
|
||||
|
||||
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.
|
||||
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 their own server. The unchanged images of upstream `kube-apiserver`, `kube-scheduler`, and `kube-controller-manager` are used.
|
||||
|
||||
Q. And what about multi-tenant `etcd`? I never heard of it.
|
||||
Q. You already provide a Kubernetes multi-tenancy solution with [Capsule](https://capsule.clastix.io). Why does Kamaji matter?
|
||||
|
||||
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.
|
||||
A. A multi-tenancy solution, like Capsule shares the Kubernetes control plane among all tenants keeping tenant namespaces isolated by policies. While the solution is 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 cluster admin permissions to the tenant.
|
||||
|
||||
Q. You already provide a Kubernetes multi-tenancy solution with [Capsule](capsule.clastix.io). Why does Kamaji matter?
|
||||
Q. Well you convinced me, how to get a try?
|
||||
|
||||
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).
|
||||
A. It is possible to get started with Kamaji on a laptop with [KinD](getting-started.md) installed.
|
||||
39
api/v1alpha1/datastore_funcs.go
Normal 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[string(secretRef.KeyPath)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("secret %s does not have key %s", namespacedName.String(), secretRef.KeyPath)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
113
api/v1alpha1/datastore_types.go
Normal file
@@ -0,0 +1,113 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=etcd;MySQL;PostgreSQL
|
||||
|
||||
type Driver string
|
||||
|
||||
var (
|
||||
EtcdDriver Driver = "etcd"
|
||||
KineMySQLDriver Driver = "MySQL"
|
||||
KinePostgreSQLDriver Driver = "PostgreSQL"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
|
||||
type Endpoints []string
|
||||
|
||||
// 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 Endpoints `json:"endpoints"`
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
type secretReferKeyPath string
|
||||
|
||||
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 secretReferKeyPath `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{})
|
||||
}
|
||||
@@ -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 (
|
||||
|
||||
68
api/v1alpha1/indexer_datastore_usedsecret.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
DatastoreUsedSecretNamespacedNameKey = "secretRef"
|
||||
)
|
||||
|
||||
type DatastoreUsedSecret struct{}
|
||||
|
||||
func (d *DatastoreUsedSecret) SetupWithManager(ctx context.Context, mgr controllerruntime.Manager) error {
|
||||
return mgr.GetFieldIndexer().IndexField(ctx, d.Object(), d.Field(), d.ExtractValue())
|
||||
}
|
||||
|
||||
func (d *DatastoreUsedSecret) Object() client.Object {
|
||||
return &DataStore{}
|
||||
}
|
||||
|
||||
func (d *DatastoreUsedSecret) Field() string {
|
||||
return DatastoreUsedSecretNamespacedNameKey
|
||||
}
|
||||
|
||||
func (d *DatastoreUsedSecret) ExtractValue() client.IndexerFunc {
|
||||
return func(object client.Object) (res []string) {
|
||||
ds := object.(*DataStore) //nolint:forcetypeassert
|
||||
|
||||
if ds.Spec.BasicAuth != nil {
|
||||
if ds.Spec.BasicAuth.Username.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.BasicAuth.Username.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.BasicAuth.Password.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.BasicAuth.Password.SecretRef))
|
||||
}
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.Certificate.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.CertificateAuthority.PrivateKey != nil && ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.CertificateAuthority.PrivateKey.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.Certificate.SecretRef))
|
||||
}
|
||||
|
||||
if ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef != nil {
|
||||
res = append(res, d.namespacedName(*ds.Spec.TLSConfig.ClientCertificate.PrivateKey.SecretRef))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DatastoreUsedSecret) namespacedName(ref SecretReference) string {
|
||||
return fmt.Sprintf("%s/%s", ref.Namespace, ref.Name)
|
||||
}
|
||||
37
api/v1alpha1/indexer_tenantcontrolplane_useddatastore.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
TenantControlPlaneUsedDataStoreKey = "status.storage.dataStoreName"
|
||||
)
|
||||
|
||||
type TenantControlPlaneStatusDataStore struct{}
|
||||
|
||||
func (t *TenantControlPlaneStatusDataStore) Object() client.Object {
|
||||
return &TenantControlPlane{}
|
||||
}
|
||||
|
||||
func (t *TenantControlPlaneStatusDataStore) Field() string {
|
||||
return TenantControlPlaneUsedDataStoreKey
|
||||
}
|
||||
|
||||
func (t *TenantControlPlaneStatusDataStore) ExtractValue() client.IndexerFunc {
|
||||
return func(object client.Object) []string {
|
||||
tcp := object.(*TenantControlPlane) //nolint:forcetypeassert
|
||||
|
||||
return []string{tcp.Status.Storage.DataStoreName}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TenantControlPlaneStatusDataStore) SetupWithManager(ctx context.Context, mgr controllerruntime.Manager) error {
|
||||
return mgr.GetFieldIndexer().IndexField(ctx, t.Object(), t.Field(), t.ExtractValue())
|
||||
}
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
12
api/v1alpha1/tenantcontrolplane_interfaces.go
Normal 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)
|
||||
}
|
||||
17
api/v1alpha1/tenantcontrolplane_kubeadmphase_funcs.go
Normal 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
|
||||
}
|
||||
18
api/v1alpha1/tenantcontrolplane_registrysettings.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type RegistrySettings struct {
|
||||
// +kubebuilder:default="registry.k8s.io"
|
||||
Registry string `json:"registry,omitempty"`
|
||||
// The tag to append to all the Control Plane container images.
|
||||
// Optional.
|
||||
TagSuffix string `json:"tagSuffix,omitempty"`
|
||||
// +kubebuilder:default="kube-apiserver"
|
||||
APIServerImage string `json:"apiServerImage,omitempty"`
|
||||
// +kubebuilder:default="kube-controller-manager"
|
||||
ControllerManagerImage string `json:"controllerManagerImage,omitempty"`
|
||||
// +kubebuilder:default="kube-scheduler"
|
||||
SchedulerImage string `json:"schedulerImage,omitempty"`
|
||||
}
|
||||
30
api/v1alpha1/tenantcontrolplane_registrysettings_funcs.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (r *RegistrySettings) buildContainerImage(name, tag string) string {
|
||||
image := fmt.Sprintf("%s/%s:%s", r.Registry, name, tag)
|
||||
|
||||
if len(r.TagSuffix) > 0 {
|
||||
image += r.TagSuffix
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
func (r *RegistrySettings) KubeAPIServerImage(version string) string {
|
||||
return r.buildContainerImage(r.APIServerImage, version)
|
||||
}
|
||||
|
||||
func (r *RegistrySettings) KubeSchedulerImage(version string) string {
|
||||
return r.buildContainerImage(r.SchedulerImage, version)
|
||||
}
|
||||
|
||||
func (r *RegistrySettings) KubeControllerManagerImage(version string) string {
|
||||
return r.buildContainerImage(r.ControllerManagerImage, version)
|
||||
}
|
||||
237
api/v1alpha1/tenantcontrolplane_status.go
Normal file
@@ -0,0 +1,237 @@
|
||||
// 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 {
|
||||
BootstrapToken KubeadmPhaseStatus `json:"bootstrapToken"`
|
||||
}
|
||||
|
||||
type ExternalKubernetesObjectStatus struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Namespace string `json:"namespace,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"`
|
||||
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;CertificateAuthorityRotating;Upgrading;Migrating;Ready;NotReady
|
||||
type KubernetesVersionStatus string
|
||||
|
||||
var (
|
||||
VersionProvisioning KubernetesVersionStatus = "Provisioning"
|
||||
VersionCARotating KubernetesVersionStatus = "CertificateAuthorityRotating"
|
||||
VersionUpgrading KubernetesVersionStatus = "Upgrading"
|
||||
VersionMigrating KubernetesVersionStatus = "Migrating"
|
||||
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"`
|
||||
}
|
||||
@@ -4,12 +4,9 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
appv1 "k8s.io/api/apps/v1"
|
||||
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"
|
||||
|
||||
"github.com/clastix/kamaji/internal/etcd"
|
||||
)
|
||||
|
||||
// NetworkProfileSpec defines the desired state of NetworkProfile.
|
||||
@@ -22,18 +19,37 @@ 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"`
|
||||
}
|
||||
|
||||
// +kubebuilder:validation:Enum=Hostname;InternalIP;ExternalIP;InternalDNS;ExternalDNS
|
||||
type KubeletPreferredAddressType string
|
||||
|
||||
const (
|
||||
NodeHostName KubeletPreferredAddressType = "Hostname"
|
||||
NodeInternalIP KubeletPreferredAddressType = "InternalIP"
|
||||
NodeExternalIP KubeletPreferredAddressType = "ExternalIP"
|
||||
NodeInternalDNS KubeletPreferredAddressType = "InternalDNS"
|
||||
NodeExternalDNS KubeletPreferredAddressType = "ExternalDNS"
|
||||
)
|
||||
|
||||
type KubeletSpec struct {
|
||||
// Ordered list of the preferred NodeAddressTypes to use for kubelet connections.
|
||||
// Default to Hostname, InternalIP, ExternalIP.
|
||||
// +kubebuilder:default={"Hostname","InternalIP","ExternalIP"}
|
||||
// +kubebuilder:validation:MinItems=1
|
||||
PreferredAddressTypes []KubeletPreferredAddressType `json:"preferredAddressTypes,omitempty"`
|
||||
// CGroupFS defines the cgroup driver for Kubelet
|
||||
// https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/
|
||||
CGroupFS CGroupDriver `json:"cgroupfs,omitempty"`
|
||||
@@ -65,23 +81,91 @@ 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"`
|
||||
// Define the kine container resources.
|
||||
// Available only if Kamaji is running using Kine as backing storage.
|
||||
Kine *corev1.ResourceRequirements `json:"kine,omitempty"`
|
||||
}
|
||||
|
||||
type DeploymentSpec struct {
|
||||
// RegistrySettings allows to override the default images for the given Tenant Control Plane instance.
|
||||
// It could be used to point to a different container registry rather than the public one.
|
||||
// +kubebuilder:default={registry:"registry.k8s.io",apiServerImage:"kube-apiserver",controllerManagerImage:"kube-controller-manager",schedulerImage:"kube-scheduler"}
|
||||
RegistrySettings RegistrySettings `json:"registrySettings,omitempty"`
|
||||
// +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"`
|
||||
// RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used
|
||||
// to run the Tenant Control Plane pod. If no RuntimeClass resource matches the named class, the pod will not be run.
|
||||
// If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an
|
||||
// empty definition that uses the default runtime handler.
|
||||
// More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class
|
||||
RuntimeClassName string `json:"runtimeClassName,omitempty"`
|
||||
// Strategy describes how to replace existing pods with new ones for the given Tenant Control Plane.
|
||||
// Default value is set to Rolling Update, with a blue/green strategy.
|
||||
// +kubebuilder:default={type:"RollingUpdate",rollingUpdate:{maxUnavailable:0,maxSurge:"100%"}}
|
||||
Strategy appsv1.DeploymentStrategy `json:"strategy,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"`
|
||||
// AdditionalInitContainers allows adding additional init containers to the Control Plane deployment.
|
||||
AdditionalInitContainers []corev1.Container `json:"additionalInitContainers,omitempty"`
|
||||
// AdditionalContainers allows adding additional containers to the Control Plane deployment.
|
||||
AdditionalContainers []corev1.Container `json:"additionalContainers,omitempty"`
|
||||
// AdditionalVolumes allows to add additional volumes to the Control Plane deployment.
|
||||
AdditionalVolumes []corev1.Volume `json:"additionalVolumes,omitempty"`
|
||||
// AdditionalVolumeMounts allows to mount an additional volume into each component of the Control Plane
|
||||
// (kube-apiserver, controller-manager, and scheduler).
|
||||
AdditionalVolumeMounts *AdditionalVolumeMounts `json:"additionalVolumeMounts,omitempty"`
|
||||
}
|
||||
|
||||
// AdditionalVolumeMounts allows mounting additional volumes to the Control Plane components.
|
||||
type AdditionalVolumeMounts struct {
|
||||
APIServer []corev1.VolumeMount `json:"apiServer,omitempty"`
|
||||
ControllerManager []corev1.VolumeMount `json:"controllerManager,omitempty"`
|
||||
Scheduler []corev1.VolumeMount `json:"scheduler,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,187 +174,91 @@ 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"`
|
||||
}
|
||||
|
||||
// ExtraArgs allows adding additional arguments to said component.
|
||||
type ExtraArgs []string
|
||||
|
||||
type KonnectivityServerSpec struct {
|
||||
// The port which Konnectivity server is listening to.
|
||||
Port int32 `json:"port"`
|
||||
// Container image version of the Konnectivity server.
|
||||
// +kubebuilder:default=v0.0.32
|
||||
Version string `json:"version,omitempty"`
|
||||
// Container image used by the Konnectivity server.
|
||||
// +kubebuilder:default=registry.k8s.io/kas-network-proxy/proxy-server
|
||||
Image string `json:"image,omitempty"`
|
||||
// Resources define the amount of CPU and memory to allocate to the Konnectivity server.
|
||||
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
ExtraArgs ExtraArgs `json:"extraArgs,omitempty"`
|
||||
}
|
||||
|
||||
type KonnectivityAgentSpec struct {
|
||||
// AgentImage defines the container image for Konnectivity's agent.
|
||||
// +kubebuilder:default=registry.k8s.io/kas-network-proxy/proxy-agent
|
||||
Image string `json:"image,omitempty"`
|
||||
// Version for Konnectivity agent.
|
||||
// +kubebuilder:default=v0.0.32
|
||||
Version string `json:"version,omitempty"`
|
||||
ExtraArgs ExtraArgs `json:"extraArgs,omitempty"`
|
||||
}
|
||||
|
||||
// KonnectivitySpec defines the spec for Konnectivity.
|
||||
type KonnectivitySpec struct {
|
||||
// +kubebuilder:default={version:"v0.0.32",image:"registry.k8s.io/kas-network-proxy/proxy-server",port:8132}
|
||||
KonnectivityServerSpec KonnectivityServerSpec `json:"server,omitempty"`
|
||||
// +kubebuilder:default={version:"v0.0.32",image:"registry.k8s.io/kas-network-proxy/proxy-agent"}
|
||||
KonnectivityAgentSpec KonnectivityAgentSpec `json:"agent,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"
|
||||
// +kubebuilder:printcolumn:name="Control-Plane-Endpoint",type="string",JSONPath=".status.controlPlaneEndpoint",description="Tenant Control Plane Endpoint (API server)"
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.kubernetesResources.version.status",description="Status"
|
||||
// +kubebuilder:printcolumn:name="Control-Plane endpoint",type="string",JSONPath=".status.controlPlaneEndpoint",description="Tenant Control Plane Endpoint (API server)"
|
||||
// +kubebuilder:printcolumn:name="Kubeconfig",type="string",JSONPath=".status.kubeconfig.admin.secretName",description="Secret which contains admin kubeconfig"
|
||||
//+kubebuilder:printcolumn:name="Datastore",type="string",JSONPath=".status.storage.dataStoreName",description="DataStore actually used"
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
|
||||
|
||||
// TenantControlPlane is the Schema for the tenantcontrolplanes API.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -57,6 +58,122 @@ 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 *AdditionalVolumeMounts) DeepCopyInto(out *AdditionalVolumeMounts) {
|
||||
*out = *in
|
||||
if in.APIServer != nil {
|
||||
in, out := &in.APIServer, &out.APIServer
|
||||
*out = make([]v1.VolumeMount, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ControllerManager != nil {
|
||||
in, out := &in.ControllerManager, &out.ControllerManager
|
||||
*out = make([]v1.VolumeMount, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Scheduler != nil {
|
||||
in, out := &in.Scheduler, &out.Scheduler
|
||||
*out = make([]v1.VolumeMount, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdditionalVolumeMounts.
|
||||
func (in *AdditionalVolumeMounts) DeepCopy() *AdditionalVolumeMounts {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AdditionalVolumeMounts)
|
||||
in.DeepCopyInto(out)
|
||||
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 +193,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 +273,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,10 +337,311 @@ 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)
|
||||
}
|
||||
if in.Kine != nil {
|
||||
in, out := &in.Kine, &out.Kine
|
||||
*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(Endpoints, 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 *DatastoreUsedSecret) DeepCopyInto(out *DatastoreUsedSecret) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatastoreUsedSecret.
|
||||
func (in *DatastoreUsedSecret) DeepCopy() *DatastoreUsedSecret {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DatastoreUsedSecret)
|
||||
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
|
||||
out.RegistrySettings = in.RegistrySettings
|
||||
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
|
||||
}
|
||||
}
|
||||
in.Strategy.DeepCopyInto(&out.Strategy)
|
||||
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)
|
||||
if in.AdditionalInitContainers != nil {
|
||||
in, out := &in.AdditionalInitContainers, &out.AdditionalInitContainers
|
||||
*out = make([]v1.Container, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AdditionalContainers != nil {
|
||||
in, out := &in.AdditionalContainers, &out.AdditionalContainers
|
||||
*out = make([]v1.Container, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AdditionalVolumes != nil {
|
||||
in, out := &in.AdditionalVolumes, &out.AdditionalVolumes
|
||||
*out = make([]v1.Volume, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AdditionalVolumeMounts != nil {
|
||||
in, out := &in.AdditionalVolumeMounts, &out.AdditionalVolumeMounts
|
||||
*out = new(AdditionalVolumeMounts)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec.
|
||||
@@ -186,18 +688,70 @@ 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) {
|
||||
*out = *in
|
||||
in.Role.DeepCopyInto(&out.Role)
|
||||
in.User.DeepCopyInto(&out.User)
|
||||
func (in Endpoints) DeepCopyInto(out *Endpoints) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(Endpoints, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Endpoints.
|
||||
func (in Endpoints) DeepCopy() Endpoints {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ETCDStatus)
|
||||
out := new(Endpoints)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalKubernetesObjectStatus) DeepCopyInto(out *ExternalKubernetesObjectStatus) {
|
||||
*out = *in
|
||||
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
|
||||
}
|
||||
|
||||
// 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(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 ExtraArgs) DeepCopyInto(out *ExtraArgs) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(ExtraArgs, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraArgs.
|
||||
func (in ExtraArgs) DeepCopy() ExtraArgs {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExtraArgs)
|
||||
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 +772,105 @@ 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 *KonnectivityAgentSpec) DeepCopyInto(out *KonnectivityAgentSpec) {
|
||||
*out = *in
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(ExtraArgs, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivityAgentSpec.
|
||||
func (in *KonnectivityAgentSpec) DeepCopy() *KonnectivityAgentSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KonnectivityAgentSpec)
|
||||
in.DeepCopyInto(out)
|
||||
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 *KonnectivityServerSpec) DeepCopyInto(out *KonnectivityServerSpec) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = new(v1.ResourceRequirements)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ExtraArgs != nil {
|
||||
in, out := &in.ExtraArgs, &out.ExtraArgs
|
||||
*out = make(ExtraArgs, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivityServerSpec.
|
||||
func (in *KonnectivityServerSpec) DeepCopy() *KonnectivityServerSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KonnectivityServerSpec)
|
||||
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
|
||||
in.KonnectivityServerSpec.DeepCopyInto(&out.KonnectivityServerSpec)
|
||||
in.KonnectivityAgentSpec.DeepCopyInto(&out.KonnectivityAgentSpec)
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -253,10 +906,6 @@ func (in *KubeadmPhaseStatus) DeepCopy() *KubeadmPhaseStatus {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -307,6 +956,11 @@ func (in *KubeconfigsStatus) DeepCopy() *KubeconfigsStatus {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubeletSpec) DeepCopyInto(out *KubeletSpec) {
|
||||
*out = *in
|
||||
if in.PreferredAddressTypes != nil {
|
||||
in, out := &in.PreferredAddressTypes, &out.PreferredAddressTypes
|
||||
*out = make([]KubeletPreferredAddressType, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletSpec.
|
||||
@@ -323,6 +977,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.
|
||||
@@ -370,7 +1025,7 @@ func (in *KubernetesServiceStatus) DeepCopy() *KubernetesServiceStatus {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KubernetesSpec) DeepCopyInto(out *KubernetesSpec) {
|
||||
*out = *in
|
||||
out.Kubelet = in.Kubelet
|
||||
in.Kubelet.DeepCopyInto(&out.Kubelet)
|
||||
if in.AdmissionControllers != nil {
|
||||
in, out := &in.AdmissionControllers, &out.AdmissionControllers
|
||||
*out = make(AdmissionControllers, len(*in))
|
||||
@@ -394,7 +1049,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 +1089,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 +1127,37 @@ 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 *RegistrySettings) DeepCopyInto(out *RegistrySettings) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistrySettings.
|
||||
func (in *RegistrySettings) DeepCopy() *RegistrySettings {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RegistrySettings)
|
||||
in.DeepCopyInto(out)
|
||||
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 +1177,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 +1192,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 +1274,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 +1296,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.
|
||||
@@ -596,3 +1308,18 @@ func (in *TenantControlPlaneStatus) DeepCopy() *TenantControlPlaneStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TenantControlPlaneStatusDataStore) DeepCopyInto(out *TenantControlPlaneStatusDataStore) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantControlPlaneStatusDataStore.
|
||||
func (in *TenantControlPlaneStatusDataStore) DeepCopy() *TenantControlPlaneStatusDataStore {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TenantControlPlaneStatusDataStore)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 12 KiB |
BIN
assets/logo-black.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
assets/logo-white.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 119 KiB |
24
charts/kamaji/Chart.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
appVersion: v0.3.0
|
||||
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.0-0"
|
||||
maintainers:
|
||||
- email: dario@tranchitella.eu
|
||||
name: Dario Tranchitella
|
||||
- email: me@maxgio.it
|
||||
name: Massimiliano Giovagnoli
|
||||
- email: me@bsctl.io
|
||||
name: Adriano Pezzuto
|
||||
name: kamaji
|
||||
sources:
|
||||
- https://github.com/clastix/kamaji
|
||||
type: application
|
||||
version: 0.12.0
|
||||
annotations:
|
||||
catalog.cattle.io/certified: partner
|
||||
catalog.cattle.io/release-name: kamaji
|
||||
catalog.cattle.io/display-name: Kamaji - Managed Kubernetes Service
|
||||
139
charts/kamaji/README.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# kamaji
|
||||
|
||||
  
|
||||
|
||||
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> | |
|
||||
|
||||
## Source Code
|
||||
|
||||
* <https://github.com/clastix/kamaji>
|
||||
|
||||
## Requirements
|
||||
|
||||
Kubernetes: `>=1.21.0-0`
|
||||
|
||||
[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 weren’t 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 |
|
||||
| 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.6"}` | 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.customAnnotations | object | `{}` | The custom annotations to add to the PVC |
|
||||
| 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. |
|
||||
| serviceAccount.annotations | object | `{}` | |
|
||||
| serviceAccount.create | bool | `true` | |
|
||||
| serviceAccount.name | string | `"kamaji-controller-manager"` | |
|
||||
| serviceMonitor.enabled | bool | `false` | Toggle the ServiceMonitor true if you have Prometheus Operator installed and configured |
|
||||
| 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.
|
||||
62
charts/kamaji/README.md.gotmpl
Normal 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 weren’t 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.
|
||||
30
charts/kamaji/app-readme.md
Normal 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
|
||||
239
charts/kamaji/crds/datastore.yaml
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: kamaji-system/kamaji-serving-cert
|
||||
controller-gen.kubebuilder.io/version: v0.11.4
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
enum:
|
||||
- etcd
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
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
|
||||
minItems: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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: {}
|
||||
4497
charts/kamaji/crds/tenantcontrolplane.yaml
Normal file
5
charts/kamaji/templates/NOTES.txt
Normal 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
|
||||
@@ -46,9 +46,9 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "kamaji.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "kamaji.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: controller-manager
|
||||
app.kubernetes.io/name: {{ default (include "kamaji.name" .) .name }}
|
||||
app.kubernetes.io/instance: {{ default .Release.Name .instance }}
|
||||
app.kubernetes.io/component: {{ default "controller-manager" .component }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
@@ -61,3 +61,31 @@ Create the name of the service account to use
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the Service to user for webhooks
|
||||
*/}}
|
||||
{{- define "kamaji.webhookServiceName" -}}
|
||||
{{- printf "%s-webhook-service" (include "kamaji.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the Service to user for metrics
|
||||
*/}}
|
||||
{{- define "kamaji.metricsServiceName" -}}
|
||||
{{- printf "%s-metrics-service" (include "kamaji.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the cert-manager secret
|
||||
*/}}
|
||||
{{- define "kamaji.webhookSecretName" -}}
|
||||
{{- printf "%s-webhook-server-cert" (include "kamaji.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the cert-manager Certificate
|
||||
*/}}
|
||||
{{- define "kamaji.certificateName" -}}
|
||||
{{- printf "%s-serving-cert" (include "kamaji.fullname" .) }}
|
||||
{{- end }}
|
||||
90
charts/kamaji/templates/_helpers_datastore.tpl
Normal 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 }}
|
||||
142
charts/kamaji/templates/_helpers_etcd.tpl
Normal 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 }}
|
||||
16
charts/kamaji/templates/certmanager_certificate.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "component" "certificate") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: {{ include "kamaji.certificateName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
dnsNames:
|
||||
- {{ include "kamaji.webhookServiceName" . }}.{{ .Release.Namespace }}.svc
|
||||
- {{ include "kamaji.webhookServiceName" . }}.{{ .Release.Namespace }}.svc.cluster.local
|
||||
issuerRef:
|
||||
kind: Issuer
|
||||
name: kamaji-selfsigned-issuer
|
||||
secretName: {{ include "kamaji.webhookSecretName" . }}
|
||||
10
charts/kamaji/templates/certmanager_issuer.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "component" "issuer") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: kamaji-selfsigned-issuer
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selfSigned: {}
|
||||
@@ -28,28 +28,12 @@ spec:
|
||||
serviceAccountName: {{ include "kamaji.serviceAccountName" . }}
|
||||
containers:
|
||||
- args:
|
||||
- --secure-listen-address=0.0.0.0:8443
|
||||
- --upstream=http://127.0.0.1:8080/
|
||||
- --logtostderr=true
|
||||
- --v=10
|
||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0
|
||||
name: kube-rbac-proxy
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
name: https
|
||||
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 }}
|
||||
- manager
|
||||
- --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 }}
|
||||
@@ -57,7 +41,16 @@ spec:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- /manager
|
||||
- /kamaji
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: SERVICE_ACCOUNT
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- with .Values.livenessProbe }}
|
||||
@@ -66,6 +59,12 @@ spec:
|
||||
{{- end }}
|
||||
name: manager
|
||||
ports:
|
||||
- containerPort: 9443
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
- containerPort: 8080
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
- containerPort: 8081
|
||||
name: healthcheck
|
||||
protocol: TCP
|
||||
@@ -77,7 +76,21 @@ spec:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: cert
|
||||
readOnly: true
|
||||
terminationGracePeriodSeconds: 10
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
- name: cert
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: {{ include "kamaji.webhookSecretName" . }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
26
charts/kamaji/templates/datastore.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: {{ include "datastore.fullname" . }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
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:
|
||||
username:
|
||||
secretReference:
|
||||
{{- .Values.datastore.basicAuth.usernameSecret | toYaml | nindent 8 }}
|
||||
password:
|
||||
secretReference:
|
||||
{{- .Values.datastore.basicAuth.passwordSecret | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
{{- include "datastore.certificateAuthority" . | indent 6 }}
|
||||
clientCertificate:
|
||||
{{- include "datastore.clientCertificate" . | indent 6 }}
|
||||
98
charts/kamaji/templates/etcd_cm.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
{{- if .Values.etcd.deploy }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "etcd.labels" . | nindent 4 }}
|
||||
name: {{ include "etcd.csrConfigMapName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"
|
||||
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 }}
|
||||
35
charts/kamaji/templates/etcd_job_postdelete.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
{{- 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" . }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
70
charts/kamaji/templates/etcd_job_postinstall.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
{{- 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: kubectl
|
||||
image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |-
|
||||
kubectl --namespace={{ .Release.Namespace }} rollout status sts/etcd --timeout=300s
|
||||
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" . }}
|
||||
- name: certs
|
||||
secret:
|
||||
secretName: {{ include "etcd.caSecretName" . }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
64
charts/kamaji/templates/etcd_job_preinstall.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
{{- if .Values.etcd.deploy }}
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "etcd.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": "hook-succeeded"
|
||||
name: "{{ .Release.Name }}-etcd-certs"
|
||||
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
|
||||
containers:
|
||||
- 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
|
||||
volumeMounts:
|
||||
- mountPath: /certs
|
||||
name: certs
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
volumes:
|
||||
- name: csr
|
||||
configMap:
|
||||
name: {{ include "etcd.csrConfigMapName" . }}
|
||||
- name: certs
|
||||
emptyDir: {}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
55
charts/kamaji/templates/etcd_rbac.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
{{- if .Values.etcd.deploy }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "etcd.labels" . | nindent 4 }}
|
||||
name: etcd-gen-certs-role
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
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 }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: etcd-gen-certs-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "etcd.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
12
charts/kamaji/templates/etcd_sa.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
{{- if .Values.etcd.deploy }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "etcd.labels" . | nindent 4 }}
|
||||
name: {{ include "etcd.serviceAccountName" . }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
"helm.sh/hook-weight": "-5"
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
18
charts/kamaji/templates/etcd_service.yaml
Normal 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 }}
|
||||
97
charts/kamaji/templates/etcd_sts.yaml
Normal file
@@ -0,0 +1,97 @@
|
||||
{{- 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
|
||||
{{- with .Values.etcd.persistence.customAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
storageClassName: {{ .Values.etcd.persistence.storageClassName }}
|
||||
accessModes:
|
||||
{{- range .Values.etcd.persistence.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.etcd.persistence.size }}
|
||||
{{- end }}
|
||||
30
charts/kamaji/templates/mutatingwebhookconfiguration.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "kamaji.certificateName" . }}
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "instance" "mutating-webhook-configuration") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: kamaji-mutating-webhook-configuration
|
||||
webhooks:
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
clientConfig:
|
||||
service:
|
||||
name: {{ include "kamaji.webhookServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
path: /mutate-kamaji-clastix-io-v1alpha1-tenantcontrolplane
|
||||
failurePolicy: Fail
|
||||
name: mtenantcontrolplane.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- kamaji.clastix.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
resources:
|
||||
- tenantcontrolplanes
|
||||
sideEffects: None
|
||||
@@ -66,6 +66,16 @@ rules:
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
@@ -102,6 +112,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:
|
||||
16
charts/kamaji/templates/service_metrics.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "component" "metrics") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: {{ include "kamaji.metricsServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
targetPort: metrics
|
||||
selector:
|
||||
{{- include "kamaji.selectorLabels" . | nindent 4 }}
|
||||
16
charts/kamaji/templates/service_webhook.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "component" "webhook" "instance" "webhook-service") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: {{ include "kamaji.webhookServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
name: webhook-server
|
||||
targetPort: webhook-server
|
||||
selector:
|
||||
{{- include "kamaji.selectorLabels" . | nindent 4 }}
|
||||
21
charts/kamaji/templates/servicemonitor.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") .Values.serviceMonitor.enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "component" "servicemonitor") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: {{ include "kamaji.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
endpoints:
|
||||
- path: /metrics
|
||||
port: metrics
|
||||
scheme: http
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "kamaji.name" . }}
|
||||
{{- end }}
|
||||
70
charts/kamaji/templates/validatingwebhookconfiguration.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "kamaji.certificateName" . }}
|
||||
labels:
|
||||
{{- $data := . | mustMergeOverwrite (dict "instance" "validating-webhook-configuration") -}}
|
||||
{{- include "kamaji.labels" $data | nindent 4 }}
|
||||
name: kamaji-validating-webhook-configuration
|
||||
webhooks:
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
clientConfig:
|
||||
service:
|
||||
name: {{ include "kamaji.webhookServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
path: /validate--v1-secret
|
||||
failurePolicy: Ignore
|
||||
name: vdatastoresecrets.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
apiVersions:
|
||||
- v1
|
||||
operations:
|
||||
- DELETE
|
||||
resources:
|
||||
- secrets
|
||||
sideEffects: None
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
clientConfig:
|
||||
service:
|
||||
name: {{ include "kamaji.webhookServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
path: /validate-kamaji-clastix-io-v1alpha1-datastore
|
||||
failurePolicy: Fail
|
||||
name: vdatastore.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- kamaji.clastix.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
- DELETE
|
||||
resources:
|
||||
- datastores
|
||||
sideEffects: None
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
clientConfig:
|
||||
service:
|
||||
name: {{ include "kamaji.webhookServiceName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
path: /validate-kamaji-clastix-io-v1alpha1-tenantcontrolplane
|
||||
failurePolicy: Fail
|
||||
name: vtenantcontrolplane.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- kamaji.clastix.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
resources:
|
||||
- tenantcontrolplanes
|
||||
sideEffects: None
|
||||
2
charts/kamaji/values.sample.yaml
Normal 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"
|
||||
211
charts/kamaji/values.yaml
Normal file
@@ -0,0 +1,211 @@
|
||||
# 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: []
|
||||
|
||||
|
||||
serviceMonitor:
|
||||
# -- Toggle the ServiceMonitor true if you have Prometheus Operator installed and configured
|
||||
enabled: false
|
||||
|
||||
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.6"
|
||||
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
|
||||
# -- The custom annotations to add to the PVC
|
||||
customAnnotations: {}
|
||||
# volumeType: local
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
239
cmd/manager/cmd.go
Normal file
@@ -0,0 +1,239 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package manager
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
goRuntime "runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
cmdutils "github.com/clastix/kamaji/cmd/utils"
|
||||
"github.com/clastix/kamaji/controllers"
|
||||
"github.com/clastix/kamaji/controllers/soot"
|
||||
"github.com/clastix/kamaji/internal"
|
||||
"github.com/clastix/kamaji/internal/builders/controlplane"
|
||||
datastoreutils "github.com/clastix/kamaji/internal/datastore/utils"
|
||||
"github.com/clastix/kamaji/internal/webhook"
|
||||
"github.com/clastix/kamaji/internal/webhook/handlers"
|
||||
"github.com/clastix/kamaji/internal/webhook/routes"
|
||||
)
|
||||
|
||||
func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
// CLI flags
|
||||
var (
|
||||
metricsBindAddress string
|
||||
healthProbeBindAddress string
|
||||
leaderElect bool
|
||||
tmpDirectory string
|
||||
kineImage string
|
||||
datastore string
|
||||
managerNamespace string
|
||||
managerServiceAccountName string
|
||||
managerServiceName string
|
||||
webhookCABundle []byte
|
||||
migrateJobImage string
|
||||
maxConcurrentReconciles int
|
||||
|
||||
webhookCAPath string
|
||||
)
|
||||
|
||||
ctx := ctrl.SetupSignalHandler()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "manager",
|
||||
Short: "Start the Kamaji Kubernetes Operator",
|
||||
SilenceErrors: false,
|
||||
SilenceUsage: true,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
// Avoid to pollute Kamaji stdout with useless details by the underlying klog implementations
|
||||
klog.SetOutput(io.Discard)
|
||||
klog.LogToStderr(false)
|
||||
|
||||
if err = cmdutils.CheckFlags(cmd.Flags(), []string{"kine-image", "datastore", "migrate-image", "tmp-directory", "pod-namespace", "webhook-service-name", "serviceaccount-name", "webhook-ca-path"}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if webhookCABundle, err = os.ReadFile(webhookCAPath); err != nil {
|
||||
return fmt.Errorf("unable to read webhook CA: %w", err)
|
||||
}
|
||||
|
||||
if err = datastoreutils.CheckExists(ctx, scheme, datastore); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
setupLog := ctrl.Log.WithName("setup")
|
||||
|
||||
setupLog.Info(fmt.Sprintf("Kamaji version %s %s%s", internal.GitTag, internal.GitCommit, internal.GitDirty))
|
||||
setupLog.Info(fmt.Sprintf("Build from: %s", internal.GitRepo))
|
||||
setupLog.Info(fmt.Sprintf("Build date: %s", internal.BuildTime))
|
||||
setupLog.Info(fmt.Sprintf("Go Version: %s", goRuntime.Version()))
|
||||
setupLog.Info(fmt.Sprintf("Go OS/Arch: %s/%s", goRuntime.GOOS, goRuntime.GOARCH))
|
||||
|
||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||
Scheme: scheme,
|
||||
MetricsBindAddress: metricsBindAddress,
|
||||
Port: 9443,
|
||||
HealthProbeBindAddress: healthProbeBindAddress,
|
||||
LeaderElection: leaderElect,
|
||||
LeaderElectionNamespace: managerNamespace,
|
||||
LeaderElectionID: "799b98bc.clastix.io",
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start manager")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
tcpChannel := make(controllers.TenantControlPlaneChannel)
|
||||
|
||||
if err = (&controllers.DataStore{TenantControlPlaneTrigger: tcpChannel}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "DataStore")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
reconciler := &controllers.TenantControlPlaneReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
APIReader: mgr.GetAPIReader(),
|
||||
Config: controllers.TenantControlPlaneReconcilerConfig{
|
||||
DefaultDataStoreName: datastore,
|
||||
KineContainerImage: kineImage,
|
||||
TmpBaseDirectory: tmpDirectory,
|
||||
},
|
||||
TriggerChan: tcpChannel,
|
||||
KamajiNamespace: managerNamespace,
|
||||
KamajiServiceAccount: managerServiceAccountName,
|
||||
KamajiService: managerServiceName,
|
||||
KamajiMigrateImage: migrateJobImage,
|
||||
MaxConcurrentReconciles: maxConcurrentReconciles,
|
||||
}
|
||||
|
||||
if err = reconciler.SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "Namespace")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err = (&kamajiv1alpha1.DatastoreUsedSecret{}).SetupWithManager(ctx, mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create indexer", "indexer", "DatastoreUsedSecret")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err = (&kamajiv1alpha1.TenantControlPlaneStatusDataStore{}).SetupWithManager(ctx, mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create indexer", "indexer", "TenantControlPlaneStatusDataStore")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
err = webhook.Register(mgr, map[routes.Route][]handlers.Handler{
|
||||
routes.TenantControlPlaneMigrate{}: {
|
||||
handlers.Freeze{},
|
||||
},
|
||||
routes.TenantControlPlaneDefaults{}: {
|
||||
handlers.TenantControlPlaneDefaults{DefaultDatastore: datastore},
|
||||
},
|
||||
routes.TenantControlPlaneValidate{}: {
|
||||
handlers.TenantControlPlaneVersion{},
|
||||
handlers.TenantControlPlaneKubeletAddresses{},
|
||||
handlers.TenantControlPlaneDataStore{Client: mgr.GetClient()},
|
||||
handlers.TenantControlPlaneDeployment{
|
||||
Client: mgr.GetClient(),
|
||||
DeploymentBuilder: controlplane.Deployment{
|
||||
Client: mgr.GetClient(),
|
||||
KineContainerImage: kineImage,
|
||||
},
|
||||
KonnectivityBuilder: controlplane.Konnectivity{
|
||||
Scheme: *mgr.GetScheme(),
|
||||
},
|
||||
},
|
||||
},
|
||||
routes.DataStoreValidate{}: {
|
||||
handlers.DataStoreValidation{Client: mgr.GetClient()},
|
||||
},
|
||||
routes.DataStoreSecrets{}: {
|
||||
handlers.DataStoreSecretValidation{Client: mgr.GetClient()},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to create webhook")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err = (&soot.Manager{
|
||||
MigrateCABundle: webhookCABundle,
|
||||
MigrateServiceName: managerServiceName,
|
||||
MigrateServiceNamespace: managerNamespace,
|
||||
AdminClient: mgr.GetClient(),
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to set up soot manager")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err = mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up health check")
|
||||
|
||||
return err
|
||||
}
|
||||
if err = mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up ready check")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
setupLog.Info("starting manager")
|
||||
if err = mgr.Start(ctx); err != nil {
|
||||
setupLog.Error(err, "problem running manager")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// Setting zap logger
|
||||
zapfs := flag.NewFlagSet("zap", flag.ExitOnError)
|
||||
opts := zap.Options{
|
||||
Development: true,
|
||||
}
|
||||
opts.BindFlags(zapfs)
|
||||
cmd.Flags().AddGoFlagSet(zapfs)
|
||||
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||
// Setting CLI flags
|
||||
cmd.Flags().StringVar(&metricsBindAddress, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
|
||||
cmd.Flags().StringVar(&healthProbeBindAddress, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
|
||||
cmd.Flags().BoolVar(&leaderElect, "leader-elect", true, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
|
||||
cmd.Flags().StringVar(&tmpDirectory, "tmp-directory", "/tmp/kamaji", "Directory which will be used to work with temporary files.")
|
||||
cmd.Flags().StringVar(&kineImage, "kine-image", "rancher/kine:v0.9.2-amd64", "Container image along with tag to use for the Kine sidecar container (used only if etcd-storage-type is set to one of kine strategies).")
|
||||
cmd.Flags().StringVar(&datastore, "datastore", "etcd", "The default DataStore that should be used by Kamaji to setup the required storage.")
|
||||
cmd.Flags().StringVar(&migrateJobImage, "migrate-image", fmt.Sprintf("clastix/kamaji:v%s", internal.GitTag), "Specify the container image to launch when a TenantControlPlane is migrated to a new datastore.")
|
||||
cmd.Flags().IntVar(&maxConcurrentReconciles, "max-concurrent-tcp-reconciles", 1, "Specify the number of workers for the Tenant Control Plane controller (beware of CPU consumption)")
|
||||
cmd.Flags().StringVar(&managerNamespace, "pod-namespace", os.Getenv("POD_NAMESPACE"), "The Kubernetes Namespace on which the Operator is running in, required for the TenantControlPlane migration jobs.")
|
||||
cmd.Flags().StringVar(&managerServiceName, "webhook-service-name", "kamaji-webhook-service", "The Kamaji webhook server Service name which is used to get validation webhooks, required for the TenantControlPlane migration jobs.")
|
||||
cmd.Flags().StringVar(&managerServiceAccountName, "serviceaccount-name", os.Getenv("SERVICE_ACCOUNT"), "The Kubernetes Namespace on which the Operator is running in, required for the TenantControlPlane migration jobs.")
|
||||
cmd.Flags().StringVar(&webhookCAPath, "webhook-ca-path", "/tmp/k8s-webhook-server/serving-certs/ca.crt", "Path to the Manager webhook server CA, required for the TenantControlPlane migration jobs.")
|
||||
|
||||
cobra.OnInitialize(func() {
|
||||
viper.AutomaticEnv()
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
119
cmd/migrate/cmd.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/datastore"
|
||||
)
|
||||
|
||||
func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
// CLI flags
|
||||
var (
|
||||
tenantControlPlane string
|
||||
targetDataStore string
|
||||
timeout time.Duration
|
||||
)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Migrate the data of a TenantControlPlane to another compatible DataStore",
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancelFn()
|
||||
|
||||
log := ctrl.Log
|
||||
|
||||
log.Info("generating the controller-runtime client")
|
||||
|
||||
client, err := ctrlclient.New(ctrl.GetConfigOrDie(), ctrlclient.Options{
|
||||
Scheme: scheme,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parts := strings.Split(tenantControlPlane, string(types.Separator))
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("non well-formed namespaced name for the tenant control plane, expected <NAMESPACE>/NAME, fot %s", tenantControlPlane)
|
||||
}
|
||||
|
||||
log.Info("retrieving the TenantControlPlane")
|
||||
|
||||
tcp := &kamajiv1alpha1.TenantControlPlane{}
|
||||
if err = client.Get(ctx, types.NamespacedName{Namespace: parts[0], Name: parts[1]}, tcp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("retrieving the TenantControlPlane used DataStore")
|
||||
|
||||
originDs := &kamajiv1alpha1.DataStore{}
|
||||
if err = client.Get(ctx, types.NamespacedName{Name: tcp.Status.Storage.DataStoreName}, originDs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("retrieving the target DataStore")
|
||||
|
||||
targetDs := &kamajiv1alpha1.DataStore{}
|
||||
if err = client.Get(ctx, types.NamespacedName{Name: targetDataStore}, targetDs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tcp.Status.Storage.Driver != string(targetDs.Spec.Driver) {
|
||||
return fmt.Errorf("migration between DataStore with different driver is not supported")
|
||||
}
|
||||
|
||||
if tcp.Status.Storage.DataStoreName == targetDs.GetName() {
|
||||
return fmt.Errorf("cannot migrate to the same DataStore")
|
||||
}
|
||||
|
||||
log.Info("generating the origin storage connection")
|
||||
|
||||
originConnection, err := datastore.NewStorageConnection(ctx, client, *originDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer originConnection.Close()
|
||||
|
||||
log.Info("generating the target storage connection")
|
||||
|
||||
targetConnection, err := datastore.NewStorageConnection(ctx, client, *targetDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer targetConnection.Close()
|
||||
// Start migrating from the old Datastore to the new one
|
||||
log.Info("migration from origin to target started")
|
||||
|
||||
if err = originConnection.Migrate(ctx, *tcp, targetConnection); err != nil {
|
||||
return fmt.Errorf("unable to migrate data from %s to %s: %w", originDs.GetName(), targetDs.GetName(), err)
|
||||
}
|
||||
|
||||
log.Info("migration completed")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&tenantControlPlane, "tenant-control-plane", "", "Namespaced-name of the TenantControlPlane that must be migrated (e.g.: default/test)")
|
||||
cmd.Flags().StringVar(&targetDataStore, "target-datastore", "", "Name of the Datastore to which the TenantControlPlane will be migrated")
|
||||
cmd.Flags().DurationVar(&timeout, "timeout", 5*time.Minute, "Amount of time for the context timeout")
|
||||
|
||||
_ = cmd.MarkFlagRequired("tenant-control-plane")
|
||||
_ = cmd.MarkFlagRequired("target-datastore")
|
||||
|
||||
return cmd
|
||||
}
|
||||
31
cmd/root.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
_ "go.uber.org/automaxprocs" // Automatically set `GOMAXPROCS` to match Linux container CPU quota.
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
|
||||
func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "kamaji",
|
||||
Short: "Build and operate Kubernetes at scale with a fraction of operational burden.",
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
// Seed is required to ensure non reproducibility for the certificates generate by Kamaji.
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
utilruntime.Must(kamajiv1alpha1.AddToScheme(scheme))
|
||||
},
|
||||
}
|
||||
}
|
||||
22
cmd/utils/check_flags.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func CheckFlags(flags *pflag.FlagSet, args ...string) error {
|
||||
for _, arg := range args {
|
||||
v, _ := flags.GetString(arg)
|
||||
|
||||
if len(v) == 0 {
|
||||
return fmt.Errorf("expecting a value for --%s arg", arg)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
39
config/certmanager/certificate.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
# The following manifests contain a self-signed issuer CR and a certificate CR.
|
||||
# More document can be found at https://docs.cert-manager.io
|
||||
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: issuer
|
||||
app.kubernetes.io/instance: selfsigned-issuer
|
||||
app.kubernetes.io/component: certificate
|
||||
app.kubernetes.io/created-by: operator
|
||||
app.kubernetes.io/part-of: operator
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
name: selfsigned-issuer
|
||||
namespace: system
|
||||
spec:
|
||||
selfSigned: {}
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: certificate
|
||||
app.kubernetes.io/instance: serving-cert
|
||||
app.kubernetes.io/component: certificate
|
||||
app.kubernetes.io/created-by: operator
|
||||
app.kubernetes.io/part-of: operator
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
|
||||
namespace: system
|
||||
spec:
|
||||
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
|
||||
dnsNames:
|
||||
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
|
||||
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
|
||||
issuerRef:
|
||||
kind: Issuer
|
||||
name: selfsigned-issuer
|
||||
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
|
||||
5
config/certmanager/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
resources:
|
||||
- certificate.yaml
|
||||
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
16
config/certmanager/kustomizeconfig.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
# This configuration is for teaching kustomize how to update name ref and var substitution
|
||||
nameReference:
|
||||
- kind: Issuer
|
||||
group: cert-manager.io
|
||||
fieldSpecs:
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/issuerRef/name
|
||||
|
||||
varReference:
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/commonName
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/dnsNames
|
||||
278
config/crd/bases/kamaji.clastix.io_datastores.yaml
Normal file
@@ -0,0 +1,278 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.11.4
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
enum:
|
||||
- etcd
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
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
|
||||
minItems: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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.
|
||||
minLength: 1
|
||||
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: {}
|
||||
@@ -3,17 +3,15 @@
|
||||
# It should be run by config/default
|
||||
resources:
|
||||
- bases/kamaji.clastix.io_tenantcontrolplanes.yaml
|
||||
- bases/kamaji.clastix.io_datastores.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizeresource
|
||||
|
||||
patchesStrategicMerge:
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||
# patches here are for enabling the conversion webhook for each CRD
|
||||
#- patches/webhook_in_clusters.yaml
|
||||
- patches/webhook_in_clusters.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
|
||||
# patches here are for enabling the CA injection for each CRD
|
||||
#- patches/cainjection_in_clusters.yaml
|
||||
- patches/cainjection_in_clusters.yaml
|
||||
- patches/cainjection_in_datastores.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
|
||||
|
||||
# the following config is for teaching kustomize how to do kustomization for CRDs.
|
||||
|
||||
7
config/crd/patches/cainjection_in_datastores.yaml
Normal 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
|
||||
16
config/crd/patches/webhook_in_datastores.yaml
Normal 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
|
||||
@@ -16,59 +16,43 @@ bases:
|
||||
- ../crd
|
||||
- ../rbac
|
||||
- ../manager
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
#- ../webhook
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
|
||||
#- ../certmanager
|
||||
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
|
||||
#- ../prometheus
|
||||
- ../samples
|
||||
- ../webhook
|
||||
- ../certmanager
|
||||
- ../prometheus
|
||||
|
||||
patchesStrategicMerge:
|
||||
# Protect the /metrics endpoint by putting it behind auth.
|
||||
# If you want your controller-manager to expose the /metrics
|
||||
# endpoint w/o any authn/z, please comment the following line.
|
||||
- manager_auth_proxy_patch.yaml
|
||||
|
||||
# Mount the controller config file for loading manager configurations
|
||||
# through a ComponentConfig type
|
||||
#- manager_config_patch.yaml
|
||||
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
#- manager_webhook_patch.yaml
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
|
||||
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
|
||||
# 'CERTMANAGER' needs to be enabled to use ca injection
|
||||
#- webhookcainjection_patch.yaml
|
||||
- manager_webhook_patch.yaml
|
||||
- webhookcainjection_patch.yaml
|
||||
|
||||
# the following config is for teaching kustomize how to do var substitution
|
||||
vars:
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
|
||||
#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: CERTIFICATE_NAME
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
#- name: SERVICE_NAMESPACE # namespace of the service
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: SERVICE_NAME
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||
objref:
|
||||
kind: Certificate
|
||||
group: cert-manager.io
|
||||
version: v1
|
||||
name: serving-cert # this name should match the one in certificate.yaml
|
||||
fieldref:
|
||||
fieldpath: metadata.namespace
|
||||
- name: CERTIFICATE_NAME
|
||||
objref:
|
||||
kind: Certificate
|
||||
group: cert-manager.io
|
||||
version: v1
|
||||
name: serving-cert # this name should match the one in certificate.yaml
|
||||
- name: SERVICE_NAMESPACE # namespace of the service
|
||||
objref:
|
||||
kind: Service
|
||||
version: v1
|
||||
name: webhook-service
|
||||
fieldref:
|
||||
fieldpath: metadata.namespace
|
||||
- name: SERVICE_NAME
|
||||
objref:
|
||||
kind: Service
|
||||
version: v1
|
||||
name: webhook-service
|
||||
|
||||
@@ -25,3 +25,4 @@ spec:
|
||||
- "--health-probe-bind-address=:8081"
|
||||
- "--metrics-bind-address=127.0.0.1:8080"
|
||||
- "--leader-elect"
|
||||
- "--datastore=kamaji-etcd"
|
||||
|
||||
23
config/default/manager_webhook_patch.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
ports:
|
||||
- containerPort: 9443
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: cert
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: cert
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: webhook-server-cert
|
||||
29
config/default/webhookcainjection_patch.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
# This patch add annotation to admission webhook config and
|
||||
# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: mutatingwebhookconfiguration
|
||||
app.kubernetes.io/instance: mutating-webhook-configuration
|
||||
app.kubernetes.io/component: webhook
|
||||
app.kubernetes.io/created-by: operator
|
||||
app.kubernetes.io/part-of: operator
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
name: mutating-webhook-configuration
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: validatingwebhookconfiguration
|
||||
app.kubernetes.io/instance: validating-webhook-configuration
|
||||
app.kubernetes.io/component: webhook
|
||||
app.kubernetes.io/created-by: operator
|
||||
app.kubernetes.io/part-of: operator
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
name: validating-webhook-configuration
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
|
||||
4554
config/install.yaml
@@ -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.3.0
|
||||
|
||||
@@ -26,12 +26,26 @@ spec:
|
||||
runAsNonRoot: true
|
||||
containers:
|
||||
- command:
|
||||
- /manager
|
||||
- /kamaji
|
||||
args:
|
||||
- manager
|
||||
- --leader-elect
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: SERVICE_ACCOUNT
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
image: controller:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
imagePullPolicy: Always
|
||||
name: manager
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
livenessProbe:
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
resources:
|
||||
- monitor.yaml
|
||||
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
|
||||
4
config/prometheus/kustomizeconfig.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
varReference:
|
||||
- kind: ServiceMonitor
|
||||
group: monitoring.coreos.com
|
||||
path: spec/namespaceSelector/matchNames
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# Prometheus Monitor Service (Metrics)
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
@@ -10,11 +9,11 @@ metadata:
|
||||
spec:
|
||||
endpoints:
|
||||
- path: /metrics
|
||||
port: https
|
||||
scheme: https
|
||||
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
tlsConfig:
|
||||
insecureSkipVerify: true
|
||||
port: metrics
|
||||
scheme: http
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- $(SERVICE_NAMESPACE)
|
||||
selector:
|
||||
matchLabels:
|
||||
control-plane: controller-manager
|
||||
|
||||
24
config/rbac/datastore_editor_role.yaml
Normal 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
|
||||
20
config/rbac/datastore_viewer_role.yaml
Normal 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
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: manager-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
@@ -18,6 +16,16 @@ rules:
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
@@ -54,6 +62,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:
|
||||
|
||||
34
config/samples/kamaji_v1alpha1_datastore_etcd.yaml
Normal 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"
|
||||
34
config/samples/kamaji_v1alpha1_datastore_mysql_bronze.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: mysql-bronze
|
||||
spec:
|
||||
driver: MySQL
|
||||
endpoints:
|
||||
- bronze.mysql-system.svc:3306
|
||||
basicAuth:
|
||||
username:
|
||||
content: cm9vdA==
|
||||
password:
|
||||
secretReference:
|
||||
name: mysql-bronze-config
|
||||
namespace: mysql-system
|
||||
keyPath: MYSQL_ROOT_PASSWORD
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-bronze-config
|
||||
namespace: mysql-system
|
||||
keyPath: "ca.crt"
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-bronze-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.crt"
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: mysql-bronze-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.key"
|
||||
34
config/samples/kamaji_v1alpha1_datastore_mysql_gold.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: mysql-gold
|
||||
spec:
|
||||
driver: MySQL
|
||||
endpoints:
|
||||
- gold.mysql-system.svc:3306
|
||||
basicAuth:
|
||||
username:
|
||||
content: cm9vdA==
|
||||
password:
|
||||
secretReference:
|
||||
name: mysql-gold-config
|
||||
namespace: mysql-system
|
||||
keyPath: MYSQL_ROOT_PASSWORD
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-gold-config
|
||||
namespace: mysql-system
|
||||
keyPath: "ca.crt"
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-gold-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.crt"
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: mysql-gold-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.key"
|
||||
34
config/samples/kamaji_v1alpha1_datastore_mysql_silver.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: mysql-silver
|
||||
spec:
|
||||
driver: MySQL
|
||||
endpoints:
|
||||
- silver.mysql-system.svc:3306
|
||||
basicAuth:
|
||||
username:
|
||||
content: cm9vdA==
|
||||
password:
|
||||
secretReference:
|
||||
name: mysql-silver-config
|
||||
namespace: mysql-system
|
||||
keyPath: MYSQL_ROOT_PASSWORD
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-silver-config
|
||||
namespace: mysql-system
|
||||
keyPath: "ca.crt"
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: mysql-silver-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.crt"
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: mysql-silver-config
|
||||
namespace: mysql-system
|
||||
keyPath: "server.key"
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: postgresql-bronze
|
||||
spec:
|
||||
driver: PostgreSQL
|
||||
endpoints:
|
||||
- postgres-bronze-rw.postgres-system.svc:5432
|
||||
basicAuth:
|
||||
username:
|
||||
secretReference:
|
||||
name: postgres-bronze-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: username
|
||||
password:
|
||||
secretReference:
|
||||
name: postgres-bronze-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-bronze-ca
|
||||
namespace: postgres-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-bronze-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: postgres-bronze-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.key
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: postgresql-gold
|
||||
spec:
|
||||
driver: PostgreSQL
|
||||
endpoints:
|
||||
- postgres-gold-rw.postgres-system.svc:5432
|
||||
basicAuth:
|
||||
username:
|
||||
secretReference:
|
||||
name: postgres-gold-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: username
|
||||
password:
|
||||
secretReference:
|
||||
name: postgres-gold-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-gold-ca
|
||||
namespace: postgres-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-gold-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: postgres-gold-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.key
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
name: postgresql-silver
|
||||
spec:
|
||||
driver: PostgreSQL
|
||||
endpoints:
|
||||
- postgres-silver-rw.postgres-system.svc:5432
|
||||
basicAuth:
|
||||
username:
|
||||
secretReference:
|
||||
name: postgres-silver-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: username
|
||||
password:
|
||||
secretReference:
|
||||
name: postgres-silver-superuser
|
||||
namespace: postgres-system
|
||||
keyPath: password
|
||||
tlsConfig:
|
||||
certificateAuthority:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-silver-ca
|
||||
namespace: postgres-system
|
||||
keyPath: ca.crt
|
||||
clientCertificate:
|
||||
certificate:
|
||||
secretReference:
|
||||
name: postgres-silver-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.crt
|
||||
privateKey:
|
||||
secretReference:
|
||||
name: postgres-silver-root-cert
|
||||
namespace: postgres-system
|
||||
keyPath: tls.key
|
||||
@@ -1,48 +1,22 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: test
|
||||
name: k8s-126
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
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"
|
||||
version: "v1.26.0"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
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: {}
|
||||
konnectivity:
|
||||
server:
|
||||
port: 8132
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: additionalcontainers
|
||||
spec:
|
||||
dataStore: postgresql-bronze
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 1
|
||||
additionalInitContainers:
|
||||
- name: init
|
||||
image: registry.k8s.io/e2e-test-images/busybox:1.29-4
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- echo hello world
|
||||
additionalContainers:
|
||||
- name: nginx
|
||||
image: registry.k8s.io/e2e-test-images/nginx:1.15-4
|
||||
service:
|
||||
serviceType: LoadBalancer
|
||||
kubernetes:
|
||||
version: "v1.26.0"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
networkProfile:
|
||||
port: 6443
|
||||
addons:
|
||||
coreDNS: {}
|
||||
kubeProxy: {}
|
||||
@@ -0,0 +1,60 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: additional-volumes
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 1
|
||||
additionalVolumes:
|
||||
- name: api-server-volume
|
||||
configMap:
|
||||
name: api-server-extra-cm
|
||||
- name: controller-manager-volume
|
||||
configMap:
|
||||
name: controller-manager-extra-cm
|
||||
- name: scheduler-volume
|
||||
configMap:
|
||||
name: scheduler-extra-cm
|
||||
additionalVolumeMounts:
|
||||
apiServer:
|
||||
- name: api-server-volume
|
||||
mountPath: "/tmp/api-server"
|
||||
controllerManager:
|
||||
- name: controller-manager-volume
|
||||
mountPath: "/tmp/controller-manager"
|
||||
scheduler:
|
||||
- name: scheduler-volume
|
||||
mountPath: "/tmp/scheduler"
|
||||
service:
|
||||
serviceType: LoadBalancer
|
||||
kubernetes:
|
||||
version: "v1.26.0"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
networkProfile:
|
||||
port: 6443
|
||||
addons:
|
||||
coreDNS: {}
|
||||
kubeProxy: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
api-server: "This is an API Server volume"
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: api-server-extra-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
controller-manager: "This is a Controller Manager volume"
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: controller-manager-extra-cm
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
controller-manager: "This is a Scheduler volume"
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: scheduler-extra-cm
|
||||
18
config/samples/kamaji_v1alpha1_tenantcontrolplane_kine.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: kine
|
||||
spec:
|
||||
addons:
|
||||
coreDNS: {}
|
||||
kubeProxy: {}
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 1
|
||||
service:
|
||||
serviceType: LoadBalancer
|
||||
dataStore: postgresql-bronze
|
||||
kubernetes:
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
version: v1.26.0
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: konnectivity-addon
|
||||
spec:
|
||||
deployment:
|
||||
replicas: 2
|
||||
service:
|
||||
serviceType: LoadBalancer
|
||||
kubernetes:
|
||||
version: "v1.26.0"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
networkProfile:
|
||||
port: 6443
|
||||
addons:
|
||||
coreDNS: {}
|
||||
kubeProxy: {}
|
||||
konnectivity:
|
||||
server:
|
||||
port: 8132
|
||||