feat: init branch

Signed-off-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
joyceliu 2024-01-04 14:36:52 +08:00
parent 631e39357d
commit 2f4c2fa795
840 changed files with 0 additions and 109816 deletions

View File

@ -1,768 +0,0 @@
{
"projectName": "kubekey",
"projectOwner": "kubesphere",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md",
"CONTRIBUTORS.md",
"README_zh-CN.md"
],
"imageSize": 100,
"commit": true,
"commitConvention": "none",
"contributors": [
{
"login": "pixiake",
"name": "pixiake",
"avatar_url": "https://avatars0.githubusercontent.com/u/22290449?v=4",
"profile": "https://github.com/pixiake",
"contributions": [
"code",
"doc"
]
},
{
"login": "Forest-L",
"name": "Forest",
"avatar_url": "https://avatars2.githubusercontent.com/u/50984129?v=4",
"profile": "https://github.com/Forest-L",
"contributions": [
"code",
"doc"
]
},
{
"login": "rayzhou2017",
"name": "rayzhou2017",
"avatar_url": "https://avatars2.githubusercontent.com/u/28859385?v=4",
"profile": "https://kubesphere.io/",
"contributions": [
"code",
"doc"
]
},
{
"login": "shaowenchen",
"name": "shaowenchen",
"avatar_url": "https://avatars2.githubusercontent.com/u/43693241?v=4",
"profile": "https://www.chenshaowen.com/",
"contributions": [
"code",
"doc"
]
},
{
"login": "LinuxSuRen",
"name": "Zhao Xiaojie",
"avatar_url": "https://avatars1.githubusercontent.com/u/1450685?v=4",
"profile": "http://surenpi.com/",
"contributions": [
"code",
"doc"
]
},
{
"login": "zackzhangkai",
"name": "Zack Zhang",
"avatar_url": "https://avatars1.githubusercontent.com/u/20178386?v=4",
"profile": "https://github.com/zackzhangkai",
"contributions": [
"code"
]
},
{
"login": "akhilerm",
"name": "Akhil Mohan",
"avatar_url": "https://avatars1.githubusercontent.com/u/7610845?v=4",
"profile": "https://akhilerm.com/",
"contributions": [
"code"
]
},
{
"login": "FeynmanZhou",
"name": "pengfei",
"avatar_url": "https://avatars3.githubusercontent.com/u/40452856?v=4",
"profile": "https://github.com/FeynmanZhou",
"contributions": [
"doc"
]
},
{
"login": "min-zh",
"name": "min zhang",
"avatar_url": "https://avatars1.githubusercontent.com/u/35321102?v=4",
"profile": "https://github.com/min-zh",
"contributions": [
"code",
"doc"
]
},
{
"login": "zgldh",
"name": "zgldh",
"avatar_url": "https://avatars1.githubusercontent.com/u/312404?v=4",
"profile": "https://github.com/zgldh",
"contributions": [
"code"
]
},
{
"login": "xrjk",
"name": "xrjk",
"avatar_url": "https://avatars0.githubusercontent.com/u/16330256?v=4",
"profile": "https://github.com/xrjk",
"contributions": [
"code"
]
},
{
"login": "stoneshi-yunify",
"name": "yonghongshi",
"avatar_url": "https://avatars2.githubusercontent.com/u/70880165?v=4",
"profile": "https://github.com/stoneshi-yunify",
"contributions": [
"code"
]
},
{
"login": "shenhonglei",
"name": "Honglei",
"avatar_url": "https://avatars2.githubusercontent.com/u/20896372?v=4",
"profile": "https://github.com/shenhonglei",
"contributions": [
"doc"
]
},
{
"login": "liucy1983",
"name": "liucy1983",
"avatar_url": "https://avatars2.githubusercontent.com/u/2360302?v=4",
"profile": "https://github.com/liucy1983",
"contributions": [
"code"
]
},
{
"login": "lilien1010",
"name": "Lien",
"avatar_url": "https://avatars1.githubusercontent.com/u/3814966?v=4",
"profile": "https://github.com/lilien1010",
"contributions": [
"doc"
]
},
{
"login": "klj890",
"name": "Tony Wang",
"avatar_url": "https://avatars3.githubusercontent.com/u/19380605?v=4",
"profile": "https://github.com/klj890",
"contributions": [
"doc"
]
},
{
"login": "hlwanghl",
"name": "Hongliang Wang",
"avatar_url": "https://avatars3.githubusercontent.com/u/4861515?v=4",
"profile": "https://github.com/hlwanghl",
"contributions": [
"code"
]
},
{
"login": "fafucoder",
"name": "dawn",
"avatar_url": "https://avatars0.githubusercontent.com/u/16442491?v=4",
"profile": "https://fafucoder.github.io/",
"contributions": [
"code"
]
},
{
"login": "duanjiong",
"name": "Duan Jiong",
"avatar_url": "https://avatars1.githubusercontent.com/u/3678855?v=4",
"profile": "https://github.com/duanjiong",
"contributions": [
"code"
]
},
{
"login": "calvinyv",
"name": "calvinyv",
"avatar_url": "https://avatars3.githubusercontent.com/u/28883416?v=4",
"profile": "https://github.com/calvinyv",
"contributions": [
"doc"
]
},
{
"login": "benjaminhuo",
"name": "Benjamin Huo",
"avatar_url": "https://avatars2.githubusercontent.com/u/18525465?v=4",
"profile": "https://github.com/benjaminhuo",
"contributions": [
"doc"
]
},
{
"login": "Sherlock113",
"name": "Sherlock113",
"avatar_url": "https://avatars2.githubusercontent.com/u/65327072?v=4",
"profile": "https://github.com/Sherlock113",
"contributions": [
"doc"
]
},
{
"login": "Fuchange",
"name": "fu_changjie",
"avatar_url": "https://avatars1.githubusercontent.com/u/31716848?v=4",
"profile": "https://github.com/Fuchange",
"contributions": [
"doc"
]
},
{
"login": "yuswift",
"name": "yuswift",
"avatar_url": "https://avatars1.githubusercontent.com/u/37265389?v=4",
"profile": "https://github.com/yuswift",
"contributions": [
"code"
]
},
{
"login": "ruiyaoOps",
"name": "ruiyaoOps",
"avatar_url": "https://avatars.githubusercontent.com/u/35256376?v=4",
"profile": "https://github.com/ruiyaoOps",
"contributions": [
"doc"
]
},
{
"login": "lxm",
"name": "LXM",
"avatar_url": "https://avatars.githubusercontent.com/u/1918195?v=4",
"profile": "http://www.luxingmin.com",
"contributions": [
"doc"
]
},
{
"login": "sbhnet",
"name": "sbhnet",
"avatar_url": "https://avatars.githubusercontent.com/u/2368131?v=4",
"profile": "https://github.com/sbhnet",
"contributions": [
"code"
]
},
{
"login": "misteruly",
"name": "misteruly",
"avatar_url": "https://avatars.githubusercontent.com/u/31399968?v=4",
"profile": "https://github.com/misteruly",
"contributions": [
"code"
]
},
{
"login": "JohnNiang",
"name": "John Niang",
"avatar_url": "https://avatars.githubusercontent.com/u/16865714?v=4",
"profile": "https://johnniang.me",
"contributions": [
"doc"
]
},
{
"login": "alimy",
"name": "Michael Li",
"avatar_url": "https://avatars.githubusercontent.com/u/10525842?v=4",
"profile": "https://alimy.me",
"contributions": [
"code"
]
},
{
"login": "duguhaotian",
"name": "独孤昊天",
"avatar_url": "https://avatars.githubusercontent.com/u/3174621?v=4",
"profile": "https://github.com/duguhaotian",
"contributions": [
"code"
]
},
{
"login": "lshmouse",
"name": "Liu Shaohui",
"avatar_url": "https://avatars.githubusercontent.com/u/118687?v=4",
"profile": "https://github.com/lshmouse",
"contributions": [
"code"
]
},
{
"login": "24sama",
"name": "Leo Li",
"avatar_url": "https://avatars.githubusercontent.com/u/43993589?v=4",
"profile": "https://github.com/24sama",
"contributions": [
"code"
]
},
{
"login": "RolandMa1986",
"name": "Roland",
"avatar_url": "https://avatars.githubusercontent.com/u/1720333?v=4",
"profile": "https://github.com/RolandMa1986",
"contributions": [
"code"
]
},
{
"login": "vinsonzou",
"name": "Vinson Zou",
"avatar_url": "https://avatars.githubusercontent.com/u/2347587?v=4",
"profile": "https://ops.m114.org",
"contributions": [
"doc"
]
},
{
"login": "tagGeeY",
"name": "tag_gee_y",
"avatar_url": "https://avatars.githubusercontent.com/u/35259969?v=4",
"profile": "https://github.com/tagGeeY",
"contributions": [
"code"
]
},
{
"login": "liulangwa",
"name": "codebee",
"avatar_url": "https://avatars.githubusercontent.com/u/25916792?v=4",
"profile": "https://github.com/liulangwa",
"contributions": [
"code"
]
},
{
"login": "TheApeMachine",
"name": "Daniel Owen van Dommelen",
"avatar_url": "https://avatars.githubusercontent.com/u/9572060?v=4",
"profile": "https://github.com/TheApeMachine",
"contributions": [
"ideas"
]
},
{
"login": "Naidile-P-N",
"name": "Naidile P N",
"avatar_url": "https://avatars.githubusercontent.com/u/29476402?v=4",
"profile": "https://github.com/Naidile-P-N",
"contributions": [
"code"
]
},
{
"login": "haiker2011",
"name": "Haiker Sun",
"avatar_url": "https://avatars.githubusercontent.com/u/8073429?v=4",
"profile": "https://github.com/haiker2011",
"contributions": [
"code"
]
},
{
"login": "yj-cloud",
"name": "Jing Yu",
"avatar_url": "https://avatars.githubusercontent.com/u/19648473?v=4",
"profile": "https://github.com/yj-cloud",
"contributions": [
"code"
]
},
{
"login": "chaunceyjiang",
"name": "Chauncey",
"avatar_url": "https://avatars.githubusercontent.com/u/17962021?v=4",
"profile": "https://github.com/chaunceyjiang",
"contributions": [
"code"
]
},
{
"login": "tanguofu",
"name": "Tan Guofu",
"avatar_url": "https://avatars.githubusercontent.com/u/87045830?v=4",
"profile": "https://github.com/tanguofu",
"contributions": [
"code"
]
},
{
"login": "lvillis",
"name": "lvillis",
"avatar_url": "https://avatars.githubusercontent.com/u/56720445?v=4",
"profile": "https://github.com/lvillis",
"contributions": [
"doc"
]
},
{
"login": "vincenthe11",
"name": "Vincent He",
"avatar_url": "https://avatars.githubusercontent.com/u/8400716?v=4",
"profile": "https://github.com/vincenthe11",
"contributions": [
"code"
]
},
{
"login": "tpiperatgod",
"name": "laminar",
"avatar_url": "https://avatars.githubusercontent.com/u/2360535?v=4",
"profile": "https://laminar.fun/",
"contributions": [
"code"
]
},
{
"login": "cumirror",
"name": "tongjin",
"avatar_url": "https://avatars.githubusercontent.com/u/2455429?v=4",
"profile": "https://github.com/cumirror",
"contributions": [
"code"
]
},
{
"login": "muzi502",
"name": "Reimu",
"avatar_url": "https://avatars.githubusercontent.com/u/42566386?v=4",
"profile": "http://k8s.li",
"contributions": [
"code"
]
},
{
"login": "eltociear",
"name": "Ikko Ashimine",
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
"profile": "https://bandism.net/",
"contributions": [
"doc"
]
},
{
"login": "yeya24",
"name": "Ben Ye",
"avatar_url": "https://avatars.githubusercontent.com/u/25150124?v=4",
"profile": "https://yeya24.github.io/",
"contributions": [
"code"
]
},
{
"login": "yinheli",
"name": "yinheli",
"avatar_url": "https://avatars.githubusercontent.com/u/235094?v=4",
"profile": "https://github.com/yinheli",
"contributions": [
"code"
]
},
{
"login": "hellocn9",
"name": "hellocn9",
"avatar_url": "https://avatars.githubusercontent.com/u/102210430?v=4",
"profile": "https://github.com/hellocn9",
"contributions": [
"code"
]
},
{
"login": "brandan-schmitz",
"name": "Brandan Schmitz",
"avatar_url": "https://avatars.githubusercontent.com/u/6267549?v=4",
"profile": "https://github.com/brandan-schmitz",
"contributions": [
"code"
]
},
{
"login": "yjqg6666",
"name": "yjqg6666",
"avatar_url": "https://avatars.githubusercontent.com/u/1879641?v=4",
"profile": "https://github.com/yjqg6666",
"contributions": [
"doc",
"code"
]
},
{
"login": "zaunist",
"name": "失眠是真滴难受",
"avatar_url": "https://avatars.githubusercontent.com/u/38528079?v=4",
"profile": "https://github.com/zaunist",
"contributions": [
"code"
]
},
{
"login": "mangoGoForward",
"name": "mango",
"avatar_url": "https://avatars.githubusercontent.com/u/35127166?v=4",
"profile": "https://github.com/mangoGoForward",
"contributions": [
"review"
]
},
{
"login": "wenwutang1",
"name": "wenwutang",
"avatar_url": "https://avatars.githubusercontent.com/u/45817987?v=4",
"profile": "https://github.com/wenwutang1",
"contributions": [
"code"
]
},
{
"login": "kuops",
"name": "Shiny Hou",
"avatar_url": "https://avatars.githubusercontent.com/u/18283256?v=4",
"profile": "http://kuops.com",
"contributions": [
"code"
]
},
{
"login": "zhouqiu0103",
"name": "zhouqiu0103",
"avatar_url": "https://avatars.githubusercontent.com/u/108912268?v=4",
"profile": "https://github.com/zhouqiu0103",
"contributions": [
"code"
]
},
{
"login": "77yu77",
"name": "77yu77",
"avatar_url": "https://avatars.githubusercontent.com/u/73932296?v=4",
"profile": "https://github.com/77yu77",
"contributions": [
"code"
]
},
{
"login": "hzhhong",
"name": "hzhhong",
"avatar_url": "https://avatars.githubusercontent.com/u/83079531?v=4",
"profile": "https://github.com/hzhhong",
"contributions": [
"code"
]
},
{
"login": "arugal",
"name": "zhang-wei",
"avatar_url": "https://avatars.githubusercontent.com/u/26432832?v=4",
"profile": "https://github.com/arugal",
"contributions": [
"code"
]
},
{
"login": "xiaods",
"name": "Deshi Xiao",
"avatar_url": "https://avatars.githubusercontent.com/u/37678?v=4",
"profile": "https://twitter.com/xds2000",
"contributions": [
"code",
"doc"
]
},
{
"login": "besscroft",
"name": "besscroft",
"avatar_url": "https://avatars.githubusercontent.com/u/33775809?v=4",
"profile": "https://besscroft.com",
"contributions": [
"doc"
]
},
{
"login": "zhangzhiqiangcs",
"name": "张志强",
"avatar_url": "https://avatars.githubusercontent.com/u/8319897?v=4",
"profile": "https://github.com/zhangzhiqiangcs",
"contributions": [
"code"
]
},
{
"login": "lwabish",
"name": "lwabish",
"avatar_url": "https://avatars.githubusercontent.com/u/7044019?v=4",
"profile": "https://github.com/lwabish",
"contributions": [
"code",
"doc"
]
},
{
"login": "qyz87",
"name": "qyz87",
"avatar_url": "https://avatars.githubusercontent.com/u/36068894?v=4",
"profile": "https://github.com/qyz87",
"contributions": [
"code"
]
},
{
"login": "fangzhengjin",
"name": "ZhengJin Fang",
"avatar_url": "https://avatars.githubusercontent.com/u/12680972?v=4",
"profile": "https://github.com/fangzhengjin",
"contributions": [
"code"
]
},
{
"login": "ExerciseBook",
"name": "Eric_Lian",
"avatar_url": "https://avatars.githubusercontent.com/u/6327311?v=4",
"profile": "http://lhr.wiki",
"contributions": [
"code"
]
},
{
"login": "nicognaW",
"name": "nicognaw",
"avatar_url": "https://avatars.githubusercontent.com/u/66731869?v=4",
"profile": "https://github.com/nicognaW",
"contributions": [
"code"
]
},
{
"login": "deqingLv",
"name": "吕德庆",
"avatar_url": "https://avatars.githubusercontent.com/u/6064297?v=4",
"profile": "https://github.com/deqingLv",
"contributions": [
"code"
]
},
{
"login": "littleplus",
"name": "littleplus",
"avatar_url": "https://avatars.githubusercontent.com/u/11694750?v=4",
"profile": "https://github.com/littleplus",
"contributions": [
"code"
]
},
{
"login": "Nello-Angelo",
"name": "Konstantin",
"avatar_url": "https://avatars.githubusercontent.com/u/82488489?v=4",
"profile": "https://www.linkedin.com/in/%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD-%D0%B0%D0%BA%D0%B0%D0%BA%D0%B8%D0%B5%D0%B2-13130b1b4/",
"contributions": [
"ideas"
]
},
{
"login": "kiragoo",
"name": "kiragoo",
"avatar_url": "https://avatars.githubusercontent.com/u/7400711?v=4",
"profile": "https://kiragoo.github.io",
"contributions": [
"code"
]
},
{
"login": "jojotong",
"name": "jojotong",
"avatar_url": "https://avatars.githubusercontent.com/u/100849526?v=4",
"profile": "https://github.com/jojotong",
"contributions": [
"code"
]
},
{
"login": "littleBlackHouse",
"name": "littleBlackHouse",
"avatar_url": "https://avatars.githubusercontent.com/u/54946465?v=4",
"profile": "https://github.com/littleBlackHouse",
"contributions": [
"code",
"doc"
]
},
{
"login": "testwill",
"name": "guangwu",
"avatar_url": "https://avatars.githubusercontent.com/u/8717479?v=4",
"profile": "https://github.com/testwill",
"contributions": [
"code",
"doc"
]
},
{
"login": "wongearl",
"name": "wongearl",
"avatar_url": "https://avatars.githubusercontent.com/u/36498442?v=4",
"profile": "https://github.com/wongearl",
"contributions": [
"code"
]
},
{
"login": "wenwenxiong",
"name": "wenwenxiong",
"avatar_url": "https://avatars.githubusercontent.com/u/10548812?v=4",
"profile": "https://github.com/wenwenxiong",
"contributions": [
"code"
]
},
{
"login": "BaiMeow",
"name": "柏喵Sakura",
"avatar_url": "https://avatars.githubusercontent.com/u/38121125?v=4",
"profile": "https://baimeow.cn/",
"contributions": [
"code"
]
},
{
"login": "cuishuang",
"name": "cui fliter",
"avatar_url": "https://avatars.githubusercontent.com/u/15921519?v=4",
"profile": "https://dashen.tech",
"contributions": [
"doc"
]
},
{
"login": "liuxu623",
"name": "刘旭",
"avatar_url": "https://avatars.githubusercontent.com/u/9653438?v=4",
"profile": "https://github.com/liuxu623",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
"skipCi": true,
"commitType": "docs"
}

16
.github/.stale.yaml vendored
View File

@ -1,16 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- frozen
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Any further update will
cause the issue/pull request to no longer be considered stale. Thank you for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue is being automatically closed due to inactivity.

View File

@ -1,54 +0,0 @@
name: Bug Report
description: File a bug report
labels: [bug]
body:
- type: markdown
id: preface
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: markdown
id: environment
attributes:
value: "## Environment"
- type: input
id: version
validations:
required: true
attributes:
label: What is version of KubeKey has the issue?
description: "You can use the command to get `./kk version`"
- type: input
id: os
validations:
required: true
attributes:
label: What is your os environment?
description: "e.g. Ubuntu 16.04"
- type: textarea
id: config
attributes:
label: KubeKey config file
description: "If applicable, add the KubeKey config file content to help explain your problem."
render: yaml
- type: markdown
id: main
attributes:
value: "## Main"
- type: textarea
id: what
validations:
required: true
attributes:
label: A clear and concise description of what happend.
- type: textarea
id: logs
attributes:
label: "Relevant log output"
description: "Please copy and paste any relevant log output."
render: shell
- type: textarea
id: additional-information
attributes:
label: "Additional information"
description: "Add any other context about the information here (screenshots, video, etc.)."

View File

@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Any other questions about KubeKey
url: https://kubesphere.slack.com/
about: If you have any other questions, you can join our slack channel.

View File

@ -1,38 +0,0 @@
name: Feature Request
description: File a feature request
body:
- type: markdown
id: preface
attributes:
value: "Thank you for submitting new features for KubeKey."
- type: markdown
id: environment
attributes:
value: "## Environment"
- type: input
id: version
attributes:
label: "Your current KubeKey version"
description: "You can use the command to get `./kk version`"
- type: markdown
id: main
attributes:
value: "## Main"
- type: textarea
id: description
attributes:
label: "Describe this feature"
validations:
required: true
- type: textarea
id: solution
attributes:
label: "Describe the solution you'd like"
description: "You can have a concise description of any alternative solutions or ideas you've considered."
validations:
required: true
- type: textarea
id: additional-information
attributes:
label: "Additional information"
description: "Add any other context about the information here (screenshots, video, etc.)."

18
.github/OWNERS vendored
View File

@ -1,18 +0,0 @@
approvers:
- pixiake
- Forest-L
- rayzhou2017
- LinuxSuRen
reviewers:
- pixiake
- Forest-L
- rayzhou2017
- zryfish
- shaowenchen
- benjaminhuo
- calvinyv
- FeynmanZhou
- huanggze
- wansir
- LinuxSuRen

View File

@ -1,64 +0,0 @@
<!-- Thanks for sending a pull request! Here are some tips for you:
1. If you want **faster** PR reviews, read how: https://github.com/kubesphere/community/blob/master/developer-guide/development/the-pr-author-guide-to-getting-through-code-review.md
2. In case you want to know how your PR got reviewed, read: https://github.com/kubesphere/community/blob/master/developer-guide/development/code-review-guide.md
3. Here are some coding conventions followed by KubeSphere community: https://github.com/kubesphere/community/blob/master/developer-guide/development/coding-conventions.md
-->
### What type of PR is this?
<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design
/kind dependencies
/kind test
Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->
### What this PR does / why we need it:
### Which issue(s) this PR fixes:
<!--
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #
### Special notes for reviewers:
```
```
### Does this PR introduced a user-facing change?
<!--
If no, just write "None" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
For more information on release notes see: https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md
-->
```release-note
```
### Additional documentation, usage docs, etc.:
<!--
This section can be blank if this pull request does not require a release note.
Please use the following format for linking documentation or pass the
section below:
- [KEP]: <link>
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs
```

View File

@ -1,14 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
pull-request-branch-name:
separator: "-"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"
pull-request-branch-name:
separator: "-"

View File

@ -1,41 +0,0 @@
# Configuration for Release Drafter: https://github.com/toolmantim/release-drafter
name-template: 'v$NEXT_PATCH_VERSION 🌈'
tag-template: 'v$NEXT_PATCH_VERSION'
version-template: $MAJOR.$MINOR.$PATCH
# Emoji reference: https://gitmoji.carloscuesta.me/
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- 'kind/feature'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- 'regression'
- 'kind/bug'
- title: 📝 Documentation updates
labels:
- 'documentation'
- 'kind/documentation'
- title: 👻 Maintenance
labels:
- chore
- dependencies
- 'kind/cleanup'
- title: 🚦 Tests
labels:
- test
- tests
exclude-labels:
- reverted
- no-changelog
- skip-changelog
- invalid
change-template: '* $TITLE (#$NUMBER) @$AUTHOR'
template: |
## Whats Changed
$CHANGES

68
.github/settings.yml vendored
View File

@ -1,68 +0,0 @@
repository:
name: kubekey
description: "KubeKey provides a flexible, rapid and convenient way to install Kubernetes only, both Kubernetes and KubeSphere, and related cloud-native add-ons. It is also an efficient tool to scale and upgrade your cluster."
homepage: https://kubesphere.io/
private: false
has_issues: true
has_wiki: false
has_downloads: false
default_branch: master
allow_squash_merge: true
allow_merge_commit: true
allow_rebase_merge: true
labels:
- name: newbie
color: abe7f4
description: These're friendly issues for new comers
- name: bug
color: d73a4a
description: Something isn't working
- name: feature
color: ffc6a3
- name: enhancement
color: a2eeef
description: New feature or request
- name: help wanted
color: 008672
description: Extra attention is needed
- name: bugfix
color: 0412d6
- name: regression
color: c5def5
- name: documentation
color: 5ce05e
- name: Hacktoberfest
description: More details from https://hacktoberfest.digitalocean.com/
color: 5ce05e
- name: test
color: c2c2fc
- name: chore
color: c2c2fc
- name: dependencies
color: 0366d6
description: Pull requests that update a dependency file
- name: no-changelog
color: c2c2fc
- name: priority-high
color: D93F0B
- name: priority-medium
color: FBCA04
- name: priority-low
color: 006B75
branches:
- name: master
protection:
required_pull_request_reviews:
required_approving_review_count: 1
dismiss_stale_reviews: true
require_code_owner_reviews: true
dismissal_restrictions:
users: []
teams: []
required_status_checks:
strict: true
contexts: []
enforce_admins: false
restrictions:
users: []
teams: []

View File

@ -1,38 +0,0 @@
name: BuildContainerImage
on:
push:
tags:
- 'v3*'
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Set env
run: echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Check out code into the Go module directory
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: all
- name: Set up Docker buildx
uses: docker/setup-buildx-action@v2
- name: Build and push docker images
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
if: github.event_name == 'push'
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
make release-prod

View File

@ -1,47 +0,0 @@
name: CI
on:
push:
branches:
- 'master'
- 'release*'
tags:
- 'v*'
pull_request:
branches:
- 'master'
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Set up Go 1.19
uses: actions/setup-go@v3
with:
go-version: 1.19
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Downloading go dependencies
run: go mod tidy
# If there are any diffs from goimports or go mod tidy, fail.
- name: Verify no changes from goimports and go mod tidy.
run: |
if [ -n "$(git status --porcelain)" ]; then
echo 'To fix this check, run "go mod tidy"'
git status # Show the files that failed to pass the check.
exit 1
fi
- name: Build command-line tool
run: |
make kk

View File

@ -1,77 +0,0 @@
---
name: gen-repository-iso
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
include:
- name: centos7-rpms
dockerfile: dockerfile.centos7
- name: almalinux-9.0-rpms
dockerfile: dockerfile.almalinux90
- name: debian10-debs
dockerfile: dockerfile.debian10
- name: debian11-debs
dockerfile: dockerfile.debian11
- name: ubuntu-16.04-debs
dockerfile: dockerfile.ubuntu1604
- name: ubuntu-18.04-debs
dockerfile: dockerfile.ubuntu1804
- name: ubuntu-20.04-debs
dockerfile: dockerfile.ubuntu2004
- name: ubuntu-22.04-debs
dockerfile: dockerfile.ubuntu2204
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build iso image to local
uses: docker/build-push-action@v4
with:
context: hack/gen-repository-iso
file: hack/gen-repository-iso/${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64
outputs: type=local,dest=./output
- name: Prepare for upload iso
shell: bash
run: |
mv ./output/linux_amd64/*.iso ${{ matrix.name }}-amd64.iso
mv ./output/linux_arm64/*.iso ${{ matrix.name }}-arm64.iso
sha256sum *.iso > ${{ matrix.name }}.iso.sha256sum.txt
- name: Wait for release workflow to finish
uses: lewagon/wait-on-check-action@v1.3.1
with:
ref: ${{ github.ref }}
check-name: 'create draft release'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
allowed-conclusions: success
- name: Release and upload packages
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
draft: true
files: |
${{ matrix.name }}.iso.sha256sum.txt
${{ matrix.name }}-amd64.iso
${{ matrix.name }}-arm64.iso

View File

@ -1,28 +0,0 @@
name: golangci-lint
on:
pull_request:
types: [opened, edited, synchronize, reopened]
# Remove all permissions from GITHUB_TOKEN except metadata.
permissions: {}
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
strategy:
matrix:
working-directory:
- ""
- test
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19
- name: golangci-lint
uses: golangci/golangci-lint-action@v3.6.0
with:
version: v1.50.1
working-directory: ${{matrix.working-directory}}

View File

@ -1,70 +0,0 @@
---
name: Kubernetes-Auto-Support
on:
schedule:
- cron: '0 0 * * *'
jobs:
update-kubernetes-version:
runs-on: ubuntu-latest
if: github.repository == 'kubesphere/kubekey'
steps:
- uses: actions/checkout@v3
- name: Set up Go 1.19
uses: actions/setup-go@v3
with:
go-version: 1.19
id: go
- name: install dependiencies
run: |
sudo apt update
sudo apt install skopeo -y
pip install natsort
wget https://attack-on-titan.gd2.qingstor.com/qsctl/v2.4.3/qsctl_v2.4.3_linux_amd64.tar.gz
tar -zxvf qsctl_v2.4.3_linux_amd64.tar.gz
mv qsctl_v2.4.3_linux_amd64 /usr/local/bin/qsctl
rm -rf qsctl_v2.4.3_linux_amd64.tar.gz
- name: update components.json
id: get_new_version
run: |
chmod +x hack/auto-update-version.py
hack/auto-update-version.py
[ -f version.tmp ] && echo "UPDATE_VERSION=true" >> $GITHUB_OUTPUT || :
- name: sync kubernetes
id: sync_kubernetes
run: |
for v in $(cat version.tmp)
do
KUBERNETES_VERSION=$v QSCTL_ACCESS_KEY_ID=${{ secrets.QSCTL_ACCESS_KEY_ID }} QSCTL_SECRET_ACCESS_KEY=${{secrets.QSCTL_SECRET_ACCESS_KEY}} DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_PASSWORD=${{ secrets.DOCKERHUB_PASSWORD }} ALIYUNCS_USERNAME=${{ secrets.ALIYUNCS_USERNAME }} ALIYUNCS_PASSWORD=${{ secrets.ALIYUNCS_PASSWORD }} bash hack/sync-components.sh
done
echo "NEW_VERSION=`cat version.tmp | tr '\n' ', '`" >> $GITHUB_OUTPUT
rm -rf qsctl-config.yaml
rm -rf version.tmp
make kk
chmod +x bin/kk
echo "## Kubernetes Versions(amd64/arm64)" > docs/kubernetes-versions.md
echo "| Version | Supported |" >> docs/kubernetes-versions.md
echo "|----------|--------------------|" >> docs/kubernetes-versions.md
bin/kk version --show-supported-k8s | ( while read version; do echo "| $version | :white_check_mark: |" >> docs/kubernetes-versions.md; done )
if: steps.get_new_version.outputs.UPDATE_VERSION == 'true'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
commit-message: Add new kubernetes version
committer: GitHub <noreply@github.com>
signoff: false
branch: new_version
delete-branch: true
title: 'Add new kubernetes version'
body: |
Add kubernetes version: ${{ steps.sync_kubernetes.outputs.NEW_VERSION }}
if: steps.get_new_version.outputs.UPDATE_VERSION == 'true'

View File

@ -1,14 +0,0 @@
name: Release Drafter
on:
push:
branches:
- master
jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,46 +0,0 @@
name: Release
on:
push:
tags:
- '*'
jobs:
build:
name: create draft release
runs-on: ubuntu-latest
steps:
- name: Set env
run: echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install go
uses: actions/setup-go@v3
with:
go-version: '^1.19'
- name: generate release artifacts
run: |
make release
- name: Release
uses: softprops/action-gh-release@v1
with:
draft: true
files: out/*
- name: Get Version
id: get_version
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Synchronize artifacts to OSS
run: |
rm -rf qsctl_v2.4.3_linux_amd64.tar.gz
wget https://attack-on-titan.gd2.qingstor.com/qsctl/v2.4.3/qsctl_v2.4.3_linux_amd64.tar.gz
tar -zxvf qsctl_v2.4.3_linux_amd64.tar.gz
rm -rf qsctl_v2.4.3_linux_amd64.tar.gz
mv qsctl_v2.4.3_linux_amd64 /usr/local/bin/qsctl
echo "access_key_id: ${{secrets.KS_QSCTL_ACCESS_KEY_ID}}" > qsctl-config.yaml
echo "secret_access_key: ${{ secrets.KS_QSCTL_SECRET_ACCESS_KEY }}" >> qsctl-config.yaml
qsctl cp out/kubekey-${{ steps.get_version.outputs.VERSION }}-linux-amd64.tar.gz qs://kubernetes/kubekey/releases/download/${{ steps.get_version.outputs.VERSION }}/kubekey-${{ steps.get_version.outputs.VERSION }}-linux-amd64.tar.gz -c qsctl-config.yaml
qsctl cp out/kubekey-${{ steps.get_version.outputs.VERSION }}-linux-arm64.tar.gz qs://kubernetes/kubekey/releases/download/${{ steps.get_version.outputs.VERSION }}/kubekey-${{ steps.get_version.outputs.VERSION }}-linux-arm64.tar.gz -c qsctl-config.yaml
rm -rf qsctl-config.yaml

38
.gitignore vendored
View File

@ -1,38 +0,0 @@
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
*.tmp
bin
hack/tools/bin
# Test binary, build with `go test -c`
*.test
# E2E test templates
test/e2e/data/infrastructure-kubekey/v1beta1/cluster-template*.yaml
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# IntelliJ
.idea/
*.iml
# Vscode files
.vscode
# rbac and manager config for example provider
manager_image_patch.yaml-e
manager_pull_policy.yaml-e
# Sample config files auto-generated by kubebuilder
config/samples
# test results
_artifacts
# Used during parts of the build process. Files _should_ get cleaned up automatically.
# This is also a good location for any temporary manfiests used during development
tmp

View File

@ -1,288 +0,0 @@
linters:
disable-all: true
enable:
- asciicheck
- bodyclose
- containedctx
- deadcode
- depguard
- dogsled
- errcheck
- exportloopref
- gci
- goconst
- gocritic
- gofmt
- goimports
- goprintffuncname
- gosec
- gosimple
- govet
- importas
- ineffassign
- misspell
- nakedret
- nilerr
- noctx
- nolintlint
- prealloc
- predeclared
- revive
- rowserrcheck
- staticcheck
- structcheck
- stylecheck
- thelper
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
linters-settings:
godot:
# declarations - for top level declaration comments (default);
# toplevel - for top level comments;
# all - for all comments.
scope: toplevel
exclude:
- '^ \+.*'
- '^ ANCHOR.*'
ifshort:
# Maximum length of variable declaration measured in number of characters, after which linter won't suggest using short syntax.
max-decl-chars: 50
gci:
local-prefixes: "github.com/kubesphere/kubekey"
importas:
no-unaliased: true
alias:
# Kubernetes
- pkg: k8s.io/api/core/v1
alias: corev1
- pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
alias: apiextensionsv1
- pkg: k8s.io/apimachinery/pkg/apis/meta/v1
alias: metav1
- pkg: k8s.io/apimachinery/pkg/api/errors
alias: apierrors
- pkg: k8s.io/apimachinery/pkg/util/errors
alias: kerrors
# Controller Runtime
- pkg: sigs.k8s.io/controller-runtime
alias: ctrl
# CABPK
- pkg: sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1alpha3
alias: bootstrapv1alpha3
- pkg: sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1alpha4
alias: bootstrapv1alpha4
- pkg: sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1
alias: bootstrapv1
# KCP
- pkg: sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1alpha3
alias: controlplanev1alpha3
- pkg: sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1alpha4
alias: controlplanev1alpha4
- pkg: sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1
alias: controlplanev1
# CAPI
- pkg: sigs.k8s.io/cluster-api/api/v1alpha3
alias: clusterv1alpha3
- pkg: sigs.k8s.io/cluster-api/api/v1alpha4
alias: clusterv1alpha4
- pkg: sigs.k8s.io/cluster-api/api/v1beta1
alias: clusterv1
# CAPI exp
- pkg: sigs.k8s.io/cluster-api/exp/api/v1alpha3
alias: expv1alpha3
- pkg: sigs.k8s.io/cluster-api/exp/api/v1alpha4
alias: expv1alpha4
- pkg: sigs.k8s.io/cluster-api/exp/api/v1beta1
alias: expv1
# CAPI exp addons
- pkg: sigs.k8s.io/cluster-api/exp/addons/api/v1alpha3
alias: addonsv1alpha3
- pkg: sigs.k8s.io/cluster-api/exp/addons/api/v1alpha4
alias: addonsv1alpha4
- pkg: sigs.k8s.io/cluster-api/exp/addons/api/v1beta1
alias: addonsv1
# CAPI exp runtime
- pkg: sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1
alias: runtimev1
- pkg: sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1
alias: runtimehooksv1
- pkg: sigs.k8s.io/cluster-api/exp/runtime/controllers
alias: runtimecontrollers
- pkg: sigs.k8s.io/cluster-api/exp/runtime/catalog
alias: runtimecatalog
- pkg: sigs.k8s.io/cluster-api/internal/runtime/client
alias: runtimeclient
- pkg: sigs.k8s.io/cluster-api/internal/runtime/registry
alias: runtimeregistry
- pkg: sigs.k8s.io/cluster-api/internal/webhooks/runtime
alias: runtimewebhooks
# CAPKK
- pkg: github.com/kubesphere/kubekey/v3/api/v1beta1
alias: infrav1
- pkg: github.com/kubesphere/kubekey/v3/bootstrap/k3s/api/v1beta1
alias: infrabootstrapv1
- pkg: github.com/kubesphere/kubekey/v3/controlplane/k3s/api/v1beta1
alias: infracontrolplanev1
nolintlint:
allow-unused: false
allow-leading-space: false
require-specific: true
revive:
rules:
# The following rules are recommended https://github.com/mgechev/revive#recommended-configuration
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
#- name: if-return # TODO This is a recommended rule with many findings which may require it's own pr.
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
#- name: unused-parameter # TODO This is a recommended rule with many findings which may require it's own pr.
- name: unreachable-code
- name: redefines-builtin-id
#
# Rules in addition to the recommended configuration above.
#
- name: bool-literal-in-expr
- name: constant-logical-expr
gosec:
excludes:
- G307 # Deferring unsafe method "Close" on type "\*os.File"
- G108 # Profiling endpoint is automatically exposed on /debug/pprof
gocritic:
enabled-tags:
- experimental
disabled-checks:
- appendAssign
- dupImport # https://github.com/go-critic/go-critic/issues/845
- evalOrder
- ifElseChain
- octalLiteral
- regexpSimplify
- sloppyReassign
- truncateCmp
- typeDefFirst
- unnamedResult
- unnecessaryDefer
- whyNoLint
- wrapperFunc
- commentFormatting
- filepathJoin
- rangeValCopy
- hugeParam
issues:
max-same-issues: 0
max-issues-per-linter: 0
# We are disabling default golangci exclusions because we want to help reviewers to focus on reviewing the most relevant
# changes in PRs and avoid nitpicking.
exclude-use-default: false
exclude-rules:
- linters:
- revive
text: "exported: exported method .*\\.(Reconcile|SetupWithManager|SetupWebhookWithManager) should have comment or be unexported"
- linters:
- errcheck
text: Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv). is not checked
# Exclude revive's exported for certain packages and code, e.g. tests and fake.
- linters:
- revive
text: exported (method|function|type|const) (.+) should have comment or be unexported
source: (func|type).*Fake.*
- linters:
- revive
text: exported (method|function|type|const) (.+) should have comment or be unexported
path: fake_\.go
- linters:
- revive
text: exported (method|function|type|const) (.+) should have comment or be unexported
path: .*test/(providers|framework|e2e).*.go
- linters:
- errcheck
text: Error return value is not checked
path: _test\.go
- linters:
- errcheck
text: Error return value of (.+) is not checked
path: _test\.go
- linters:
- gosec
text: "G108: Profiling endpoint is automatically exposed on /debug/pprof"
- linters:
- godot
text: "Comment should end in a period"
path: "(.*)/(v1beta1|v1beta2)/(.*)types.go"
- linters:
- errcheck
text: Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv). is not checked
# With Go 1.16, the new embed directive can be used with an un-named import,
# revive (previously, golint) only allows these to be imported in a main.go, which wouldn't work for us.
# This directive allows the embed package to be imported with an underscore everywhere.
- linters:
- revive
source: _ "embed"
# This directive allows the variable in defaults.go files to have underscore
- linters:
- revive
text: "var-naming: don't use underscores in Go names; func (.+) should be (.+)"
path: .*/defaults.go
# Disable unparam "always receives" which might not be really
# useful when building libraries.
- linters:
- unparam
text: always receives
# Dot imports for gomega or ginkgo are allowed
# within test files.
- path: _test\.go
text: should not use dot imports
- path: (framework|e2e)/.*.go
text: should not use dot imports
- path: _test\.go
text: cyclomatic complexity
- linters:
- unparam
text: (.+) - (`t`|`g`) is unused
- path: _test\.go
text: cyclomatic complexity
# Append should be able to assign to a different var/slice.
- linters:
- gocritic
text: "appendAssign: append result not assigned to the same slice"
# We don't care about defer in for loops in test files.
- linters:
- gocritic
text: "deferInLoop: Possible resource leak, 'defer' is called in the 'for' loop"
path: _test\.go
run:
timeout: 10m
go: "1.19"
build-tags:
- tools
- e2e
- containers_image_openpgp
- exclude_graphdriver_devicemapper
- exclude_graphdriver_btrfs
skip-files:
- "zz_generated.*\\.go$"
- "vendored_openapi\\.go$"
- "cmd"
allow-parallel-runners: true

View File

@ -1,122 +0,0 @@
### Sincere gratitude goes to the following people for their contributions to KubeKey
Contributions of any kind are welcome! Thanks goes to these wonderful contributors, they made our project grow fast.
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pixiake"><img src="https://avatars0.githubusercontent.com/u/22290449?v=4?s=100" width="100px;" alt="pixiake"/><br /><sub><b>pixiake</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Forest-L"><img src="https://avatars2.githubusercontent.com/u/50984129?v=4?s=100" width="100px;" alt="Forest"/><br /><sub><b>Forest</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kubesphere.io/"><img src="https://avatars2.githubusercontent.com/u/28859385?v=4?s=100" width="100px;" alt="rayzhou2017"/><br /><sub><b>rayzhou2017</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.chenshaowen.com/"><img src="https://avatars2.githubusercontent.com/u/43693241?v=4?s=100" width="100px;" alt="shaowenchen"/><br /><sub><b>shaowenchen</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://surenpi.com/"><img src="https://avatars1.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Zhao Xiaojie"/><br /><sub><b>Zhao Xiaojie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zackzhangkai"><img src="https://avatars1.githubusercontent.com/u/20178386?v=4?s=100" width="100px;" alt="Zack Zhang"/><br /><sub><b>Zack Zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zackzhangkai" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://akhilerm.com/"><img src="https://avatars1.githubusercontent.com/u/7610845?v=4?s=100" width="100px;" alt="Akhil Mohan"/><br /><sub><b>Akhil Mohan</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=akhilerm" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeynmanZhou"><img src="https://avatars3.githubusercontent.com/u/40452856?v=4?s=100" width="100px;" alt="pengfei"/><br /><sub><b>pengfei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=FeynmanZhou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/min-zh"><img src="https://avatars1.githubusercontent.com/u/35321102?v=4?s=100" width="100px;" alt="min zhang"/><br /><sub><b>min zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zgldh"><img src="https://avatars1.githubusercontent.com/u/312404?v=4?s=100" width="100px;" alt="zgldh"/><br /><sub><b>zgldh</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zgldh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xrjk"><img src="https://avatars0.githubusercontent.com/u/16330256?v=4?s=100" width="100px;" alt="xrjk"/><br /><sub><b>xrjk</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xrjk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stoneshi-yunify"><img src="https://avatars2.githubusercontent.com/u/70880165?v=4?s=100" width="100px;" alt="yonghongshi"/><br /><sub><b>yonghongshi</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=stoneshi-yunify" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenhonglei"><img src="https://avatars2.githubusercontent.com/u/20896372?v=4?s=100" width="100px;" alt="Honglei"/><br /><sub><b>Honglei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shenhonglei" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liucy1983"><img src="https://avatars2.githubusercontent.com/u/2360302?v=4?s=100" width="100px;" alt="liucy1983"/><br /><sub><b>liucy1983</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liucy1983" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lilien1010"><img src="https://avatars1.githubusercontent.com/u/3814966?v=4?s=100" width="100px;" alt="Lien"/><br /><sub><b>Lien</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lilien1010" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/klj890"><img src="https://avatars3.githubusercontent.com/u/19380605?v=4?s=100" width="100px;" alt="Tony Wang"/><br /><sub><b>Tony Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=klj890" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hlwanghl"><img src="https://avatars3.githubusercontent.com/u/4861515?v=4?s=100" width="100px;" alt="Hongliang Wang"/><br /><sub><b>Hongliang Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hlwanghl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://fafucoder.github.io/"><img src="https://avatars0.githubusercontent.com/u/16442491?v=4?s=100" width="100px;" alt="dawn"/><br /><sub><b>dawn</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fafucoder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duanjiong"><img src="https://avatars1.githubusercontent.com/u/3678855?v=4?s=100" width="100px;" alt="Duan Jiong"/><br /><sub><b>Duan Jiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duanjiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/calvinyv"><img src="https://avatars3.githubusercontent.com/u/28883416?v=4?s=100" width="100px;" alt="calvinyv"/><br /><sub><b>calvinyv</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=calvinyv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benjaminhuo"><img src="https://avatars2.githubusercontent.com/u/18525465?v=4?s=100" width="100px;" alt="Benjamin Huo"/><br /><sub><b>Benjamin Huo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=benjaminhuo" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Sherlock113"><img src="https://avatars2.githubusercontent.com/u/65327072?v=4?s=100" width="100px;" alt="Sherlock113"/><br /><sub><b>Sherlock113</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Sherlock113" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fuchange"><img src="https://avatars1.githubusercontent.com/u/31716848?v=4?s=100" width="100px;" alt="fu_changjie"/><br /><sub><b>fu_changjie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Fuchange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yuswift"><img src="https://avatars1.githubusercontent.com/u/37265389?v=4?s=100" width="100px;" alt="yuswift"/><br /><sub><b>yuswift</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yuswift" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruiyaoOps"><img src="https://avatars.githubusercontent.com/u/35256376?v=4?s=100" width="100px;" alt="ruiyaoOps"/><br /><sub><b>ruiyaoOps</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ruiyaoOps" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luxingmin.com"><img src="https://avatars.githubusercontent.com/u/1918195?v=4?s=100" width="100px;" alt="LXM"/><br /><sub><b>LXM</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lxm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sbhnet"><img src="https://avatars.githubusercontent.com/u/2368131?v=4?s=100" width="100px;" alt="sbhnet"/><br /><sub><b>sbhnet</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=sbhnet" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/misteruly"><img src="https://avatars.githubusercontent.com/u/31399968?v=4?s=100" width="100px;" alt="misteruly"/><br /><sub><b>misteruly</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=misteruly" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://johnniang.me"><img src="https://avatars.githubusercontent.com/u/16865714?v=4?s=100" width="100px;" alt="John Niang"/><br /><sub><b>John Niang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=JohnNiang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://alimy.me"><img src="https://avatars.githubusercontent.com/u/10525842?v=4?s=100" width="100px;" alt="Michael Li"/><br /><sub><b>Michael Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=alimy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duguhaotian"><img src="https://avatars.githubusercontent.com/u/3174621?v=4?s=100" width="100px;" alt="独孤昊天"/><br /><sub><b>独孤昊天</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duguhaotian" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lshmouse"><img src="https://avatars.githubusercontent.com/u/118687?v=4?s=100" width="100px;" alt="Liu Shaohui"/><br /><sub><b>Liu Shaohui</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lshmouse" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/24sama"><img src="https://avatars.githubusercontent.com/u/43993589?v=4?s=100" width="100px;" alt="Leo Li"/><br /><sub><b>Leo Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=24sama" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RolandMa1986"><img src="https://avatars.githubusercontent.com/u/1720333?v=4?s=100" width="100px;" alt="Roland"/><br /><sub><b>Roland</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=RolandMa1986" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ops.m114.org"><img src="https://avatars.githubusercontent.com/u/2347587?v=4?s=100" width="100px;" alt="Vinson Zou"/><br /><sub><b>Vinson Zou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vinsonzou" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tagGeeY"><img src="https://avatars.githubusercontent.com/u/35259969?v=4?s=100" width="100px;" alt="tag_gee_y"/><br /><sub><b>tag_gee_y</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tagGeeY" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liulangwa"><img src="https://avatars.githubusercontent.com/u/25916792?v=4?s=100" width="100px;" alt="codebee"/><br /><sub><b>codebee</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liulangwa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TheApeMachine"><img src="https://avatars.githubusercontent.com/u/9572060?v=4?s=100" width="100px;" alt="Daniel Owen van Dommelen"/><br /><sub><b>Daniel Owen van Dommelen</b></sub></a><br /><a href="#ideas-TheApeMachine" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Naidile-P-N"><img src="https://avatars.githubusercontent.com/u/29476402?v=4?s=100" width="100px;" alt="Naidile P N"/><br /><sub><b>Naidile P N</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Naidile-P-N" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haiker2011"><img src="https://avatars.githubusercontent.com/u/8073429?v=4?s=100" width="100px;" alt="Haiker Sun"/><br /><sub><b>Haiker Sun</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=haiker2011" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yj-cloud"><img src="https://avatars.githubusercontent.com/u/19648473?v=4?s=100" width="100px;" alt="Jing Yu"/><br /><sub><b>Jing Yu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yj-cloud" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chaunceyjiang"><img src="https://avatars.githubusercontent.com/u/17962021?v=4?s=100" width="100px;" alt="Chauncey"/><br /><sub><b>Chauncey</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=chaunceyjiang" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tanguofu"><img src="https://avatars.githubusercontent.com/u/87045830?v=4?s=100" width="100px;" alt="Tan Guofu"/><br /><sub><b>Tan Guofu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tanguofu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lvillis"><img src="https://avatars.githubusercontent.com/u/56720445?v=4?s=100" width="100px;" alt="lvillis"/><br /><sub><b>lvillis</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lvillis" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vincenthe11"><img src="https://avatars.githubusercontent.com/u/8400716?v=4?s=100" width="100px;" alt="Vincent He"/><br /><sub><b>Vincent He</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vincenthe11" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://laminar.fun/"><img src="https://avatars.githubusercontent.com/u/2360535?v=4?s=100" width="100px;" alt="laminar"/><br /><sub><b>laminar</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tpiperatgod" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cumirror"><img src="https://avatars.githubusercontent.com/u/2455429?v=4?s=100" width="100px;" alt="tongjin"/><br /><sub><b>tongjin</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cumirror" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://k8s.li"><img src="https://avatars.githubusercontent.com/u/42566386?v=4?s=100" width="100px;" alt="Reimu"/><br /><sub><b>Reimu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=muzi502" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://yeya24.github.io/"><img src="https://avatars.githubusercontent.com/u/25150124?v=4?s=100" width="100px;" alt="Ben Ye"/><br /><sub><b>Ben Ye</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yeya24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yinheli"><img src="https://avatars.githubusercontent.com/u/235094?v=4?s=100" width="100px;" alt="yinheli"/><br /><sub><b>yinheli</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yinheli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hellocn9"><img src="https://avatars.githubusercontent.com/u/102210430?v=4?s=100" width="100px;" alt="hellocn9"/><br /><sub><b>hellocn9</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hellocn9" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brandan-schmitz"><img src="https://avatars.githubusercontent.com/u/6267549?v=4?s=100" width="100px;" alt="Brandan Schmitz"/><br /><sub><b>Brandan Schmitz</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=brandan-schmitz" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yjqg6666"><img src="https://avatars.githubusercontent.com/u/1879641?v=4?s=100" width="100px;" alt="yjqg6666"/><br /><sub><b>yjqg6666</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Documentation">📖</a> <a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zaunist"><img src="https://avatars.githubusercontent.com/u/38528079?v=4?s=100" width="100px;" alt="失眠是真滴难受"/><br /><sub><b>失眠是真滴难受</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zaunist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangoGoForward"><img src="https://avatars.githubusercontent.com/u/35127166?v=4?s=100" width="100px;" alt="mango"/><br /><sub><b>mango</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/pulls?q=is%3Apr+reviewed-by%3AmangoGoForward" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwutang1"><img src="https://avatars.githubusercontent.com/u/45817987?v=4?s=100" width="100px;" alt="wenwutang"/><br /><sub><b>wenwutang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwutang1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://kuops.com"><img src="https://avatars.githubusercontent.com/u/18283256?v=4?s=100" width="100px;" alt="Shiny Hou"/><br /><sub><b>Shiny Hou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kuops" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouqiu0103"><img src="https://avatars.githubusercontent.com/u/108912268?v=4?s=100" width="100px;" alt="zhouqiu0103"/><br /><sub><b>zhouqiu0103</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhouqiu0103" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/77yu77"><img src="https://avatars.githubusercontent.com/u/73932296?v=4?s=100" width="100px;" alt="77yu77"/><br /><sub><b>77yu77</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=77yu77" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hzhhong"><img src="https://avatars.githubusercontent.com/u/83079531?v=4?s=100" width="100px;" alt="hzhhong"/><br /><sub><b>hzhhong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hzhhong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/arugal"><img src="https://avatars.githubusercontent.com/u/26432832?v=4?s=100" width="100px;" alt="zhang-wei"/><br /><sub><b>zhang-wei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=arugal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/xds2000"><img src="https://avatars.githubusercontent.com/u/37678?v=4?s=100" width="100px;" alt="Deshi Xiao"/><br /><sub><b>Deshi Xiao</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://besscroft.com"><img src="https://avatars.githubusercontent.com/u/33775809?v=4?s=100" width="100px;" alt="besscroft"/><br /><sub><b>besscroft</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=besscroft" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhangzhiqiangcs"><img src="https://avatars.githubusercontent.com/u/8319897?v=4?s=100" width="100px;" alt="张志强"/><br /><sub><b>张志强</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhangzhiqiangcs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwabish"><img src="https://avatars.githubusercontent.com/u/7044019?v=4?s=100" width="100px;" alt="lwabish"/><br /><sub><b>lwabish</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyz87"><img src="https://avatars.githubusercontent.com/u/36068894?v=4?s=100" width="100px;" alt="qyz87"/><br /><sub><b>qyz87</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=qyz87" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fangzhengjin"><img src="https://avatars.githubusercontent.com/u/12680972?v=4?s=100" width="100px;" alt="ZhengJin Fang"/><br /><sub><b>ZhengJin Fang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fangzhengjin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://lhr.wiki"><img src="https://avatars.githubusercontent.com/u/6327311?v=4?s=100" width="100px;" alt="Eric_Lian"/><br /><sub><b>Eric_Lian</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ExerciseBook" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nicognaW"><img src="https://avatars.githubusercontent.com/u/66731869?v=4?s=100" width="100px;" alt="nicognaw"/><br /><sub><b>nicognaw</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=nicognaW" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deqingLv"><img src="https://avatars.githubusercontent.com/u/6064297?v=4?s=100" width="100px;" alt="吕德庆"/><br /><sub><b>吕德庆</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=deqingLv" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleplus"><img src="https://avatars.githubusercontent.com/u/11694750?v=4?s=100" width="100px;" alt="littleplus"/><br /><sub><b>littleplus</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleplus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD-%D0%B0%D0%BA%D0%B0%D0%BA%D0%B8%D0%B5%D0%B2-13130b1b4/"><img src="https://avatars.githubusercontent.com/u/82488489?v=4?s=100" width="100px;" alt="Konstantin"/><br /><sub><b>Konstantin</b></sub></a><br /><a href="#ideas-Nello-Angelo" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kiragoo.github.io"><img src="https://avatars.githubusercontent.com/u/7400711?v=4?s=100" width="100px;" alt="kiragoo"/><br /><sub><b>kiragoo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kiragoo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jojotong"><img src="https://avatars.githubusercontent.com/u/100849526?v=4?s=100" width="100px;" alt="jojotong"/><br /><sub><b>jojotong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=jojotong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleBlackHouse"><img src="https://avatars.githubusercontent.com/u/54946465?v=4?s=100" width="100px;" alt="littleBlackHouse"/><br /><sub><b>littleBlackHouse</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/testwill"><img src="https://avatars.githubusercontent.com/u/8717479?v=4?s=100" width="100px;" alt="guangwu"/><br /><sub><b>guangwu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wongearl"><img src="https://avatars.githubusercontent.com/u/36498442?v=4?s=100" width="100px;" alt="wongearl"/><br /><sub><b>wongearl</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wongearl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwenxiong"><img src="https://avatars.githubusercontent.com/u/10548812?v=4?s=100" width="100px;" alt="wenwenxiong"/><br /><sub><b>wenwenxiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwenxiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://baimeow.cn/"><img src="https://avatars.githubusercontent.com/u/38121125?v=4?s=100" width="100px;" alt="柏喵Sakura"/><br /><sub><b>柏喵Sakura</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=BaiMeow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dashen.tech"><img src="https://avatars.githubusercontent.com/u/15921519?v=4?s=100" width="100px;" alt="cui fliter"/><br /><sub><b>cui fliter</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cuishuang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liuxu623"><img src="https://avatars.githubusercontent.com/u/9653438?v=4?s=100" width="100px;" alt="刘旭"/><br /><sub><b>刘旭</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liuxu623" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

View File

@ -1,61 +0,0 @@
# Build architecture
ARG ARCH
# Download dependencies
FROM alpine:3.11 as base_os_context
ENV OUTDIR=/out
RUN mkdir -p ${OUTDIR}/usr/local/bin/
WORKDIR /tmp
RUN apk add --no-cache ca-certificates
# Build the manager binary
FROM golang:1.19 as builder
# Run this with docker build --build_arg $(go env GOPROXY) to override the goproxy
ARG goproxy=https://goproxy.cn,direct
ENV GOPROXY=$goproxy
WORKDIR /workspace
COPY go.mod go.mod
COPY go.sum go.sum
# Cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN --mount=type=cache,target=/go/pkg/mod \
go mod download
# Copy the go source
COPY ./ ./
# Cache the go build into the the Gos compiler cache folder so we take benefits of compiler caching across docker build calls
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
go build .
# Build
ARG package=.
ARG ARCH
ARG LDFLAGS
# Do not force rebuild of up-to-date packages (do not use -a) and use the compiler cache folder
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} \
go build -ldflags "${LDFLAGS}" \
-o manager ${package}
FROM --platform=${ARCH} alpine:3.16
WORKDIR /
RUN mkdir -p /var/lib/kubekey/rootfs
COPY --from=base_os_context /out/ /
COPY --from=builder /workspace/manager .
ENTRYPOINT ["/manager"]

201
LICENSE
View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018-2020 KubeSphere Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

601
Makefile
View File

@ -1,601 +0,0 @@
# Ensure Make is run with bash shell as some syntax below is bash-specific
SHELL:=/usr/bin/env bash
.DEFAULT_GOAL:=help
#
# Go.
#
GO_VERSION ?= 1.19.2
GO_CONTAINER_IMAGE ?= docker.io/library/golang:$(GO_VERSION)
# Use GOPROXY environment variable if set
GOPROXY := $(shell go env GOPROXY)
ifeq ($(GOPROXY),)
GOPROXY := https://goproxy.cn,direct
endif
export GOPROXY
# Active module mode, as we use go modules to manage dependencies
export GO111MODULE=on
# This option is for running docker manifest command
export DOCKER_CLI_EXPERIMENTAL := enabled
#
# Directories.
#
# Full directory of where the Makefile resides
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
EXP_DIR := exp
BIN_DIR := bin
TEST_DIR := test
TOOLS_DIR := hack/tools
TOOLS_BIN_DIR := $(abspath $(TOOLS_DIR)/$(BIN_DIR))
E2E_FRAMEWORK_DIR := $(TEST_DIR)/framework
GO_INSTALL := ./scripts/go_install.sh
export PATH := $(abspath $(TOOLS_BIN_DIR)):$(PATH)
#
# Binaries.
#
# Note: Need to use abspath so we can invoke these from subdirectories
KUSTOMIZE_VER := v4.5.2
KUSTOMIZE_BIN := kustomize
KUSTOMIZE := $(abspath $(TOOLS_BIN_DIR)/$(KUSTOMIZE_BIN)-$(KUSTOMIZE_VER))
KUSTOMIZE_PKG := sigs.k8s.io/kustomize/kustomize/v4
SETUP_ENVTEST_VER := v0.0.0-20211110210527-619e6b92dab9
SETUP_ENVTEST_BIN := setup-envtest
SETUP_ENVTEST := $(abspath $(TOOLS_BIN_DIR)/$(SETUP_ENVTEST_BIN)-$(SETUP_ENVTEST_VER))
SETUP_ENVTEST_PKG := sigs.k8s.io/controller-runtime/tools/setup-envtest
CONTROLLER_GEN_VER := v0.9.1
CONTROLLER_GEN_BIN := controller-gen
CONTROLLER_GEN := $(abspath $(TOOLS_BIN_DIR)/$(CONTROLLER_GEN_BIN)-$(CONTROLLER_GEN_VER))
CONTROLLER_GEN_PKG := sigs.k8s.io/controller-tools/cmd/controller-gen
GOTESTSUM_VER := v1.6.4
GOTESTSUM_BIN := gotestsum
GOTESTSUM := $(abspath $(TOOLS_BIN_DIR)/$(GOTESTSUM_BIN)-$(GOTESTSUM_VER))
GOTESTSUM_PKG := gotest.tools/gotestsum
HADOLINT_VER := v2.10.0
HADOLINT_FAILURE_THRESHOLD = warning
GOLANGCI_LINT_BIN := golangci-lint
GOLANGCI_LINT := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_BIN))
# Define Docker related variables. Releases should modify and double check these vars.
REGISTRY ?= docker.io/kubespheredev
PROD_REGISTRY ?= docker.io/kubesphere
# capkk
CAPKK_IMAGE_NAME ?= capkk-controller
CAPKK_CONTROLLER_IMG ?= $(REGISTRY)/$(CAPKK_IMAGE_NAME)
# bootstrap
K3S_BOOTSTRAP_IMAGE_NAME ?= k3s-bootstrap-controller
K3S_BOOTSTRAP_CONTROLLER_IMG ?= $(REGISTRY)/$(K3S_BOOTSTRAP_IMAGE_NAME)
# control plane
K3S_CONTROL_PLANE_IMAGE_NAME ?= k3s-control-plane-controller
K3S_CONTROL_PLANE_CONTROLLER_IMG ?= $(REGISTRY)/$(K3S_CONTROL_PLANE_IMAGE_NAME)
# It is set by Prow GIT_TAG, a git-based tag of the form vYYYYMMDD-hash, e.g., v20210120-v0.3.10-308-gc61521971
TAG ?= dev
ARCH ?= $(shell go env GOARCH)
ALL_ARCH = amd64 arm arm64 ppc64le s390x
# Allow overriding the imagePullPolicy
PULL_POLICY ?= Always
# Hosts running SELinux need :z added to volume mounts
SELINUX_ENABLED := $(shell cat /sys/fs/selinux/enforce 2> /dev/null || echo 0)
ifeq ($(SELINUX_ENABLED),1)
DOCKER_VOL_OPTS?=:z
endif
# Set build time variables including version details
LDFLAGS := $(shell hack/version.sh)
# Set kk build tags
BUILDTAGS = exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp
.PHONY: all
all: test managers
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} /^[0-9A-Za-z_-]+:.*?##/ { printf " \033[36m%-45s\033[0m %s\n", $$1, $$2 } /^\$$\([0-9A-Za-z_-]+\):.*?##/ { gsub("_","-", $$1); printf " \033[36m%-45s\033[0m %s\n", tolower(substr($$1, 3, length($$1)-7)), $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
## --------------------------------------
## Generate / Manifests
## --------------------------------------
##@ generate:
ALL_GENERATE_MODULES = capkk k3s-bootstrap k3s-control-plane
.PHONY: generate
generate: ## Run all generate-manifests-*, generate-go-deepcopy-* targets
$(MAKE) generate-modules generate-manifests generate-go-deepcopy
.PHONY: generate-manifests
generate-manifests: ## Run all generate-manifest-* targets
$(MAKE) $(addprefix generate-manifests-,$(ALL_GENERATE_MODULES))
.PHONY: generate-manifests-capkk
generate-manifests-capkk: $(CONTROLLER_GEN) $(KUSTOMIZE) ## Generate manifests e.g. CRD, RBAC etc. for core
$(MAKE) clean-generated-yaml SRC_DIRS="./config/crd/bases"
$(CONTROLLER_GEN) \
paths=./api/... \
paths=./controllers/... \
crd:crdVersions=v1 \
rbac:roleName=manager-role \
output:crd:dir=./config/crd/bases \
output:webhook:dir=./config/webhook \
webhook
.PHONY: generate-manifests-k3s-bootstrap
generate-manifests-k3s-bootstrap: $(CONTROLLER_GEN) $(KUSTOMIZE) ## Generate manifests e.g. CRD, RBAC etc. for core
$(MAKE) clean-generated-yaml SRC_DIRS="./bootstrap/k3s/config/crd/bases"
$(CONTROLLER_GEN) \
paths=./bootstrap/k3s/api/... \
paths=./bootstrap/k3s/controllers/... \
crd:crdVersions=v1 \
rbac:roleName=manager-role \
output:crd:dir=./bootstrap/k3s/config/crd/bases \
output:rbac:dir=./bootstrap/k3s/config/rbac \
output:webhook:dir=./bootstrap/k3s/config/webhook \
webhook
.PHONY: generate-manifests-k3s-control-plane
generate-manifests-k3s-control-plane: $(CONTROLLER_GEN) $(KUSTOMIZE) ## Generate manifests e.g. CRD, RBAC etc. for core
$(MAKE) clean-generated-yaml SRC_DIRS="./controlplane/k3s/config/crd/bases"
$(CONTROLLER_GEN) \
paths=./controlplane/k3s/api/... \
paths=./controlplane/k3s/controllers/... \
crd:crdVersions=v1 \
rbac:roleName=manager-role \
output:crd:dir=./controlplane/k3s/config/crd/bases \
output:rbac:dir=./controlplane/k3s/config/rbac \
output:webhook:dir=./controlplane/k3s/config/webhook \
webhook
.PHONY: generate-go-deepcopy
generate-go-deepcopy: ## Run all generate-go-deepcopy-* targets
$(MAKE) $(addprefix generate-go-deepcopy-,$(ALL_GENERATE_MODULES))
.PHONY: generate-go-deepcopy-capkk
generate-go-deepcopy-capkk: $(CONTROLLER_GEN) ## Generate deepcopy go code for capkk
$(MAKE) clean-generated-deepcopy SRC_DIRS="./api"
$(CONTROLLER_GEN) \
object:headerFile=./hack/boilerplate.go.txt \
paths=./api/... \
.PHONY: generate-go-deepcopy-k3s-bootstrap
generate-go-deepcopy-k3s-bootstrap: $(CONTROLLER_GEN) ## Generate deepcopy go code for k3s-bootstrap
$(MAKE) clean-generated-deepcopy SRC_DIRS="./bootstrap/k3s/api"
$(CONTROLLER_GEN) \
object:headerFile=./hack/boilerplate.go.txt \
paths=./bootstrap/k3s/api/... \
.PHONY: generate-go-deepcopy-k3s-control-plane
generate-go-deepcopy-k3s-control-plane: $(CONTROLLER_GEN) ## Generate deepcopy go code for k3s-control-plane
$(MAKE) clean-generated-deepcopy SRC_DIRS="./controlplane/k3s/api"
$(CONTROLLER_GEN) \
object:headerFile=./hack/boilerplate.go.txt \
paths=./controlplane/k3s/api/... \
.PHONY: generate-modules
generate-modules: ## Run go mod tidy to ensure modules are up to date
go mod tidy
## --------------------------------------
## Lint / Verify
## --------------------------------------
##@ lint and verify:
.PHONY: lint
lint: $(GOLANGCI_LINT) ## Lint the codebase
$(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_EXTRA_ARGS)
cd $(TEST_DIR); $(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_EXTRA_ARGS)
cd $(TOOLS_DIR); $(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_EXTRA_ARGS)
./scripts/ci-lint-dockerfiles.sh $(HADOLINT_VER) $(HADOLINT_FAILURE_THRESHOLD)
.PHONY: lint-dockerfiles
lint-dockerfiles:
./scripts/ci-lint-dockerfiles.sh $(HADOLINT_VER) $(HADOLINT_FAILURE_THRESHOLD)
.PHONY: verify
verify: $(addprefix verify-,$(ALL_VERIFY_CHECKS)) lint-dockerfiles ## Run all verify-* targets
.PHONY: verify-modules
verify-modules: generate-modules ## Verify go modules are up to date
@if !(git diff --quiet HEAD -- go.sum go.mod $(TOOLS_DIR)/go.mod $(TOOLS_DIR)/go.sum $(TEST_DIR)/go.mod $(TEST_DIR)/go.sum); then \
git diff; \
echo "go module files are out of date"; exit 1; \
fi
@if (find . -name 'go.mod' | xargs -n1 grep -q -i 'k8s.io/client-go.*+incompatible'); then \
find . -name "go.mod" -exec grep -i 'k8s.io/client-go.*+incompatible' {} \; -print; \
echo "go module contains an incompatible client-go version"; exit 1; \
fi
.PHONY: verify-gen
verify-gen: generate ## Verify go generated files are up to date
@if !(git diff --quiet HEAD); then \
git diff; \
echo "generated files are out of date, run make generate"; exit 1; \
fi
## --------------------------------------
## Binaries
## --------------------------------------
##@ build:
.PHONY: kk
kk:
CGO_ENABLED=0 go build -trimpath -tags "$(BUILDTAGS)" -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/kk github.com/kubesphere/kubekey/v3/cmd/kk;
ALL_MANAGERS = capkk k3s-bootstrap k3s-control-plane
.PHONY: managers
managers: $(addprefix manager-,$(ALL_MANAGERS)) ## Run all manager-* targets
.PHONY: manager-capkk
manager-capkk: ## Build the capkk manager binary into the ./bin folder
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/manager github.com/kubesphere/kubekey/v3
.PHONY: manager-k3s-bootstrap
manager-k3s-bootstrap: ## Build the k3s bootstrap manager binary into the ./bin folder
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/k3s-bootstrap-manager github.com/kubesphere/kubekey/v3/bootstrap/k3s
.PHONY: manager-k3s-control-plane
manager-k3s-control-plane: ## Build the k3s control plane manager binary into the ./bin folder
go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/k3s-control-plane-manager github.com/kubesphere/kubekey/v3/controlplane/k3s
.PHONY: docker-pull-prerequisites
docker-pull-prerequisites:
docker pull docker.io/docker/dockerfile:1.4
docker pull $(GO_CONTAINER_IMAGE)
.PHONY: docker-build-all
docker-build-all: $(addprefix docker-build-,$(ALL_ARCH)) ## Build docker images for all architectures
docker-build-%:
$(MAKE) ARCH=$* docker-build
ALL_DOCKER_BUILD = capkk k3s-bootstrap k3s-control-plane
.PHONY: docker-build
docker-build: docker-pull-prerequisites ## Run docker-build-* targets for all providers
$(MAKE) ARCH=$(ARCH) $(addprefix docker-build-,$(ALL_DOCKER_BUILD))
.PHONY: docker-build-capkk
docker-build-capkk: ## Build the docker image for capkk
DOCKER_BUILDKIT=1 docker build --build-arg builder_image=$(GO_CONTAINER_IMAGE) --build-arg goproxy=$(GOPROXY) --build-arg ARCH=$(ARCH) --build-arg ldflags="$(LDFLAGS)" . -t $(CAPKK_CONTROLLER_IMG)-$(ARCH):$(TAG)
.PHONY: docker-build-k3s-bootstrap
docker-build-k3s-bootstrap: ## Build the docker image for k3s bootstrap controller manager
DOCKER_BUILDKIT=1 docker build --build-arg builder_image=$(GO_CONTAINER_IMAGE) --build-arg goproxy=$(GOPROXY) --build-arg ARCH=$(ARCH) --build-arg package=./bootstrap/k3s --build-arg ldflags="$(LDFLAGS)" . -t $(K3S_BOOTSTRAP_CONTROLLER_IMG)-$(ARCH):$(TAG)
.PHONY: docker-build-k3s-control-plane
docker-build-k3s-control-plane: ## Build the docker image for k3s control plane controller manager
DOCKER_BUILDKIT=1 docker build --build-arg builder_image=$(GO_CONTAINER_IMAGE) --build-arg goproxy=$(GOPROXY) --build-arg ARCH=$(ARCH) --build-arg package=./controlplane/k3s --build-arg ldflags="$(LDFLAGS)" . -t $(K3S_CONTROL_PLANE_CONTROLLER_IMG)-$(ARCH):$(TAG)
.PHONY: docker-build-e2e
docker-build-e2e: ## Build the docker image for capkk
$(MAKE) docker-build REGISTRY=docker.io/kubespheredev PULL_POLICY=IfNotPresent TAG=e2e
## --------------------------------------
## Deployment
## --------------------------------------
##@ deployment
ifndef ignore-not-found
ignore-not-found = false
endif
.PHONY: install
install: generate $(KUSTOMIZE) ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | kubectl apply -f -
.PHONY: uninstall
uninstall: generate $(KUSTOMIZE) ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
.PHONY: deploy
deploy: generate $(KUSTOMIZE) ## Deploy controller to the K8s cluster specified in ~/.kube/config.
$(MAKE) set-manifest-image \
MANIFEST_IMG=$(REGISTRY)/$(CAPKK_IMAGE_NAME)-$(ARCH) MANIFEST_TAG=$(TAG) \
TARGET_RESOURCE="./config/default/manager_image_patch.yaml"
cd config/manager
$(KUSTOMIZE) build config/default | kubectl apply -f -
.PHONY: undeploy
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
## --------------------------------------
## Testing
## --------------------------------------
##@ test:
ARTIFACTS ?= ${ROOT_DIR}/_artifacts
ifeq ($(shell go env GOOS),darwin) # Use the darwin/amd64 binary until an arm64 version is available
KUBEBUILDER_ASSETS ?= $(shell $(SETUP_ENVTEST) use --use-env -p path --arch amd64 $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION))
else
KUBEBUILDER_ASSETS ?= $(shell $(SETUP_ENVTEST) use --use-env -p path $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION))
endif
.PHONY: test
test: $(SETUP_ENVTEST) ## Run unit and integration tests
KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test ./... $(TEST_ARGS)
.PHONY: test-verbose
test-verbose: ## Run unit and integration tests with verbose flag
$(MAKE) test TEST_ARGS="$(TEST_ARGS) -v"
.PHONY: test-junit
test-junit: $(SETUP_ENVTEST) $(GOTESTSUM) ## Run unit and integration tests and generate a junit report
set +o errexit; (KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test -json ./... $(TEST_ARGS); echo $$? > $(ARTIFACTS)/junit.exitcode) | tee $(ARTIFACTS)/junit.stdout
$(GOTESTSUM) --junitfile $(ARTIFACTS)/junit.xml --raw-command cat $(ARTIFACTS)/junit.stdout
exit $$(cat $(ARTIFACTS)/junit.exitcode)
.PHONY: test-cover
test-cover: ## Run unit and integration tests and generate a coverage report
$(MAKE) test TEST_ARGS="$(TEST_ARGS) -coverprofile=out/coverage.out"
go tool cover -func=out/coverage.out -o out/coverage.txt
go tool cover -html=out/coverage.out -o out/coverage.html
.PHONY: test-e2e
test-e2e: ## Run e2e tests
$(MAKE) -C $(TEST_DIR)/e2e run
.PHONY: test-e2e-k3s
test-e2e-k3s: ## Run e2e tests
$(MAKE) -C $(TEST_DIR)/e2e run-k3s
## --------------------------------------
## Release
## --------------------------------------
##@ release:
## latest git tag for the commit, e.g., v0.3.10
RELEASE_TAG ?= $(shell git describe --abbrev=0 2>/dev/null)
ifneq (,$(findstring -,$(RELEASE_TAG)))
PRE_RELEASE=true
endif
# the previous release tag, e.g., v0.3.9, excluding pre-release tags
PREVIOUS_TAG ?= $(shell git tag -l | grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$$" | sort -V | grep -B1 $(RELEASE_TAG) | head -n 1 2>/dev/null)
RELEASE_DIR := out
$(RELEASE_DIR):
mkdir -p $(RELEASE_DIR)/
.PHONY: release
release: clean-release ## Build and push container images using the latest git tag for the commit
@if [ -z "${RELEASE_TAG}" ]; then echo "RELEASE_TAG is not set"; exit 1; fi
@if ! [ -z "$$(git status --porcelain)" ]; then echo "Your local git repository contains uncommitted changes, use git clean before proceeding."; exit 1; fi
git checkout "${RELEASE_TAG}"
## Build binaries first.
GIT_VERSION=$(RELEASE_TAG) $(MAKE) release-binaries
# Set the manifest image to the production bucket.
$(MAKE) manifest-modification REGISTRY=$(PROD_REGISTRY)
## Build the manifests
$(MAKE) release-manifests
## Build the templates
$(MAKE) release-templates
## Clean the git artifacts modified in the release process
$(MAKE) clean-release-git
release-binaries: ## Build the binaries to publish with a release
RELEASE_BINARY=./cmd/kk GOOS=linux GOARCH=amd64 $(MAKE) release-binary
RELEASE_BINARY=./cmd/kk GOOS=linux GOARCH=amd64 $(MAKE) release-archive
RELEASE_BINARY=./cmd/kk GOOS=linux GOARCH=arm64 $(MAKE) release-binary
RELEASE_BINARY=./cmd/kk GOOS=linux GOARCH=arm64 $(MAKE) release-archive
RELEASE_BINARY=./cmd/kk GOOS=darwin GOARCH=amd64 $(MAKE) release-binary
RELEASE_BINARY=./cmd/kk GOOS=darwin GOARCH=amd64 $(MAKE) release-archive
RELEASE_BINARY=./cmd/kk GOOS=darwin GOARCH=arm64 $(MAKE) release-binary
RELEASE_BINARY=./cmd/kk GOOS=darwin GOARCH=arm64 $(MAKE) release-archive
release-binary: $(RELEASE_DIR)
docker run \
--rm \
-e CGO_ENABLED=0 \
-e GOOS=$(GOOS) \
-e GOARCH=$(GOARCH) \
-e GOPROXY=$(GOPROXY) \
-v "$$(pwd):/workspace$(DOCKER_VOL_OPTS)" \
-w /workspace \
golang:$(GO_VERSION) \
go build -a -trimpath -tags "$(BUILDTAGS)" -ldflags "$(LDFLAGS) -extldflags '-static'" \
-o $(RELEASE_DIR)/$(notdir $(RELEASE_BINARY)) $(RELEASE_BINARY)
release-archive: $(RELEASE_DIR)
tar -czf $(RELEASE_DIR)/kubekey-$(RELEASE_TAG)-$(GOOS)-$(GOARCH).tar.gz -C $(RELEASE_DIR)/ $(notdir $(RELEASE_BINARY))
rm -rf $(RELEASE_DIR)/$(notdir $(RELEASE_BINARY))
.PHONY: manifest-modification
manifest-modification: # Set the manifest images to the staging/production bucket.
$(MAKE) set-manifest-image \
MANIFEST_IMG=$(REGISTRY)/$(CAPKK_IMAGE_NAME) MANIFEST_TAG=$(RELEASE_TAG) \
TARGET_RESOURCE="./config/default/manager_image_patch.yaml"
$(MAKE) set-manifest-image \
MANIFEST_IMG=$(REGISTRY)/$(K3S_BOOTSTRAP_IMAGE_NAME) MANIFEST_TAG=$(RELEASE_TAG) \
TARGET_RESOURCE="./bootstrap/k3s/config/default/manager_image_patch.yaml"
$(MAKE) set-manifest-image \
MANIFEST_IMG=$(REGISTRY)/$(K3S_CONTROL_PLANE_IMAGE_NAME) MANIFEST_TAG=$(RELEASE_TAG) \
TARGET_RESOURCE="./controlplane/k3s/config/default/manager_image_patch.yaml"
$(MAKE) set-manifest-pull-policy PULL_POLICY=IfNotPresent TARGET_RESOURCE="./config/default/manager_pull_policy.yaml"
$(MAKE) set-manifest-pull-policy PULL_POLICY=IfNotPresent TARGET_RESOURCE="./bootstrap/k3s/config/default/manager_pull_policy.yaml"
$(MAKE) set-manifest-pull-policy PULL_POLICY=IfNotPresent TARGET_RESOURCE="./controlplane/k3s/config/default/manager_pull_policy.yaml"
.PHONY: release-manifests
release-manifests: $(RELEASE_DIR) $(KUSTOMIZE) ## Build the manifests to publish with a release
# Build capkk-components.
$(KUSTOMIZE) build config/default > $(RELEASE_DIR)/infrastructure-components.yaml
# Build bootstrap-components.
$(KUSTOMIZE) build bootstrap/k3s/config/default > $(RELEASE_DIR)/bootstrap-components.yaml
# Build control-plane-components.
$(KUSTOMIZE) build controlplane/k3s/config/default > $(RELEASE_DIR)/control-plane-components.yaml
# Add metadata to the release artifacts
cp metadata.yaml $(RELEASE_DIR)/metadata.yaml
.PHONY: release-templates
release-templates: $(RELEASE_DIR) ## Generate release templates
cp templates/cluster-template*.yaml $(RELEASE_DIR)/
.PHONY: release-prod
release-prod: ## Build and push container images to the prod
REGISTRY=$(PROD_REGISTRY) TAG=$(RELEASE_TAG) $(MAKE) docker-build-all docker-push-all
## --------------------------------------
## Docker
## --------------------------------------
.PHONY: docker-push-all
docker-push-all: $(addprefix docker-push-,$(ALL_ARCH)) ## Push the docker images to be included in the release for all architectures + related multiarch manifests
$(MAKE) docker-push-manifest-capkk
$(MAKE) docker-push-manifest-k3s-bootstrap
$(MAKE) docker-push-manifest-k3s-control-plane
docker-push-%:
$(MAKE) ARCH=$* docker-push
.PHONY: docker-push
docker-push: ## Push the docker images
docker push $(CAPKK_CONTROLLER_IMG)-$(ARCH):$(TAG)
docker push $(K3S_BOOTSTRAP_CONTROLLER_IMG)-$(ARCH):$(TAG)
docker push $(K3S_CONTROL_PLANE_CONTROLLER_IMG)-$(ARCH):$(TAG)
.PHONY: docker-push-manifest-capkk
docker-push-manifest-capkk: ## Push the multiarch manifest for the capkk docker images
## Minimum docker version 18.06.0 is required for creating and pushing manifest images.
docker manifest create --amend $(CAPKK_CONTROLLER_IMG):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(CAPKK_CONTROLLER_IMG)\-&:$(TAG)~g")
@for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${CAPKK_CONTROLLER_IMG}:${TAG} ${CAPKK_CONTROLLER_IMG}-$${arch}:${TAG}; done
docker manifest push --purge $(CAPKK_CONTROLLER_IMG):$(TAG)
.PHONY: docker-push-manifest-k3s-bootstrap
docker-push-manifest-k3s-bootstrap: ## Push the multiarch manifest for the k3s bootstrap docker images
## Minimum docker version 18.06.0 is required for creating and pushing manifest images.
docker manifest create --amend $(K3S_BOOTSTRAP_CONTROLLER_IMG):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(K3S_BOOTSTRAP_CONTROLLER_IMG)\-&:$(TAG)~g")
@for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${K3S_BOOTSTRAP_CONTROLLER_IMG}:${TAG} ${K3S_BOOTSTRAP_CONTROLLER_IMG}-$${arch}:${TAG}; done
docker manifest push --purge $(K3S_BOOTSTRAP_CONTROLLER_IMG):$(TAG)
.PHONY: docker-push-manifest-k3s-control-plane
docker-push-manifest-k3s-control-plane: ## Push the multiarch manifest for the k3s control plane docker images
## Minimum docker version 18.06.0 is required for creating and pushing manifest images.
docker manifest create --amend $(K3S_CONTROL_PLANE_CONTROLLER_IMG):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(K3S_CONTROL_PLANE_CONTROLLER_IMG)\-&:$(TAG)~g")
@for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${K3S_CONTROL_PLANE_CONTROLLER_IMG}:${TAG} ${K3S_CONTROL_PLANE_CONTROLLER_IMG}-$${arch}:${TAG}; done
docker manifest push --purge $(K3S_CONTROL_PLANE_CONTROLLER_IMG):$(TAG)
.PHONY: set-manifest-pull-policy
set-manifest-pull-policy:
$(info Updating kustomize pull policy file for manager resources)
sed -i'' -e 's@imagePullPolicy: .*@imagePullPolicy: '"$(PULL_POLICY)"'@' $(TARGET_RESOURCE)
.PHONY: set-manifest-image
set-manifest-image:
$(info Updating kustomize image patch file for manager resource)
sed -i'' -e 's@image: .*@image: '"${MANIFEST_IMG}:$(MANIFEST_TAG)"'@' $(TARGET_RESOURCE)
## --------------------------------------
## Cleanup / Verification
## --------------------------------------
##@ clean:
.PHONY: clean
clean: ## Remove all generated files
$(MAKE) clean-bin
.PHONY: clean-bin
clean-bin: ## Remove all generated binaries
rm -rf $(BIN_DIR)
rm -rf $(TOOLS_BIN_DIR)
.PHONY: clean-release
clean-release: ## Remove the release folder
rm -rf $(RELEASE_DIR)
.PHONY: clean-release-git
clean-release-git: ## Restores the git files usually modified during a release
git restore ./*manager_image_patch.yaml ./*manager_pull_policy.yaml
.PHONY: clean-generated-yaml
clean-generated-yaml: ## Remove files generated by conversion-gen from the mentioned dirs. Example SRC_DIRS="./api/v1beta1"
(IFS=','; for i in $(SRC_DIRS); do find $$i -type f -name '*.yaml' -exec rm -f {} \;; done)
.PHONY: clean-generated-deepcopy
clean-generated-deepcopy: ## Remove files generated by conversion-gen from the mentioned dirs. Example SRC_DIRS="./api/v1beta1"
(IFS=','; for i in $(SRC_DIRS); do find $$i -type f -name 'zz_generated.deepcopy*' -exec rm -f {} \;; done)
## --------------------------------------
## Hack / Tools
## --------------------------------------
##@ hack/tools:
.PHONY: $(CONTROLLER_GEN_BIN)
$(CONTROLLER_GEN_BIN): $(CONTROLLER_GEN) ## Build a local copy of controller-gen.
.PHONY: $(GOTESTSUM_BIN)
$(GOTESTSUM_BIN): $(GOTESTSUM) ## Build a local copy of gotestsum.
.PHONY: $(KUSTOMIZE_BIN)
$(KUSTOMIZE_BIN): $(KUSTOMIZE) ## Build a local copy of kustomize.
.PHONY: $(SETUP_ENVTEST_BIN)
$(SETUP_ENVTEST_BIN): $(SETUP_ENVTEST) ## Build a local copy of setup-envtest.
.PHONY: $(GOLANGCI_LINT_BIN)
$(GOLANGCI_LINT_BIN): $(GOLANGCI_LINT) ## Build a local copy of golangci-lint
$(CONTROLLER_GEN): # Build controller-gen from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(CONTROLLER_GEN_PKG) $(CONTROLLER_GEN_BIN) $(CONTROLLER_GEN_VER)
$(GOTESTSUM): # Build gotestsum from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(GOTESTSUM_PKG) $(GOTESTSUM_BIN) $(GOTESTSUM_VER)
$(KUSTOMIZE): # Build kustomize from tools folder.
CGO_ENABLED=0 GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(KUSTOMIZE_PKG) $(KUSTOMIZE_BIN) $(KUSTOMIZE_VER)
$(SETUP_ENVTEST): # Build setup-envtest from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(SETUP_ENVTEST_PKG) $(SETUP_ENVTEST_BIN) $(SETUP_ENVTEST_VER)
$(GOLANGCI_LINT): .github/workflows/golangci-lint.yml # Download golangci-lint using hack script into tools folder.
hack/ensure-golangci-lint.sh \
-b $(TOOLS_BIN_DIR) \
$(shell cat .github/workflows/golangci-lint.yml | grep [[:space:]]version | sed 's/.*version: //')
# build the artifact of repository iso
ISO_ARCH ?= amd64
ISO_OUTPUT_DIR ?= ./output
ISO_BUILD_WORKDIR := hack/gen-repository-iso
ISO_OS_NAMES := centos7 debian9 debian10 ubuntu1604 ubuntu1804 ubuntu2004 ubuntu2204
ISO_BUILD_NAMES := $(addprefix build-iso-,$(ISO_OS_NAMES))
build-iso-all: $(ISO_BUILD_NAMES)
.PHONY: $(ISO_BUILD_NAMES)
$(ISO_BUILD_NAMES):
@export DOCKER_BUILDKIT=1
docker build \
--platform linux/$(ISO_ARCH) \
--build-arg TARGETARCH=$(ISO_ARCH) \
-o type=local,dest=$(ISO_OUTPUT_DIR) \
-f $(ISO_BUILD_WORKDIR)/dockerfile.$(subst build-iso-,,$@) \
$(ISO_BUILD_WORKDIR)
go-releaser-test:
goreleaser release --rm-dist --skip-publish --snapshot

20
OWNERS
View File

@ -1,20 +0,0 @@
approvers:
- pixiake
- 24sama
- rayzhou2017
- littleBlackHouse
reviewers:
- pixiake
- Forest-L
- rayzhou2017
- zryfish
- shaowenchen
- benjaminhuo
- calvinyv
- FeynmanZhou
- huanggze
- wansir
- LinuxSuRen
- 24sama
- littleBlackHouse

73
PROJECT
View File

@ -1,73 +0,0 @@
domain: cluster.x-k8s.io
layout:
- go.kubebuilder.io/v3
plugins:
manifests.sdk.operatorframework.io/v2: {}
scorecard.sdk.operatorframework.io/v2: {}
projectName: cluster-api-provider-kubekey
repo: github.com/kubesphere/kubekey
resources:
- api:
crdVersion: v1
namespaced: true
controller: true
domain: cluster.x-k8s.io
group: infrastructure
kind: KKCluster
path: github.com/kubesphere/kubekey/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
domain: cluster.x-k8s.io
group: infrastructure
kind: KKClusterTemplate
path: github.com/kubesphere/kubekey/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: cluster.x-k8s.io
group: infrastructure
kind: KKMachine
path: github.com/kubesphere/kubekey/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
domain: cluster.x-k8s.io
group: infrastructure
kind: KKMachineTemplate
path: github.com/kubesphere/kubekey/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: cluster.x-k8s.io
group: infrastructure
kind: KKInstance
path: github.com/kubesphere/kubekey/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"

408
README.md
View File

@ -1,408 +0,0 @@
<div align=center><img src="docs/img/kubekey-logo.svg?raw=true"></div>
[![CI](https://github.com/kubesphere/kubekey/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/kubesphere/kubekey/actions?query=event%3Apush+branch%3Amaster+workflow%3ACI+)
> English | [中文](README_zh-CN.md)
### 👋 Welcome to KubeKey!
KubeKey is an open-source lightweight tool for deploying Kubernetes clusters. It provides a flexible, rapid, and convenient way to install Kubernetes/K3s only, both Kubernetes/K3s and KubeSphere, and related cloud-native add-ons. It is also an efficient tool to scale and upgrade your cluster.
In addition, KubeKey also supports customized Air-Gap package, which is convenient for users to quickly deploy clusters in offline environments.
> KubeKey has passed [CNCF kubernetes conformance verification](https://www.cncf.io/certification/software-conformance/).
Use KubeKey in the following three scenarios.
* Install Kubernetes/K3s only
* Install Kubernetes/K3s and KubeSphere together in one command
* Install Kubernetes/K3s first, then deploy KubeSphere on it using [ks-installer](https://github.com/kubesphere/ks-installer)
> **Important:** If you have existing Kubernetes clusters, please refer to [ks-installer (Install KubeSphere on existing Kubernetes cluster)](https://github.com/kubesphere/ks-installer).
## Supported Environment
### Linux Distributions
* **Ubuntu** *16.04, 18.04, 20.04, 22.04*
* **Debian** *Bullseye, Buster, Stretch*
* **CentOS/RHEL** *7*
* **AlmaLinux** *9.0*
* **SUSE Linux Enterprise Server** *15*
> Recommended Linux Kernel Version: `4.15 or later`
> You can run the `uname -srm` command to check the Linux Kernel Version.
### <span id = "KubernetesVersions">Kubernetes Versions</span>
* **v1.19**: &ensp; *v1.19.15*
* **v1.20**: &ensp; *v1.20.10*
* **v1.21**: &ensp; *v1.21.14*
* **v1.22**: &ensp; *v1.22.15*
* **v1.23**: &ensp; *v1.23.10* (default)
* **v1.24**: &ensp; *v1.24.7*
* **v1.25**: &ensp; *v1.25.3*
> Looking for more supported versions: \
> [Kubernetes Versions](./docs/kubernetes-versions.md) \
> [K3s Versions](./docs/k3s-versions.md)
### Container Manager
* **Docker** / **containerd** / **CRI-O** / **iSula**
> `Kata Containers` can be set to automatically install and configure runtime class for it when the container manager is containerd or CRI-O.
### Network Plugins
* **Calico** / **Flannel** / **Cilium** / **Kube-OVN** / **Multus-CNI**
> Kubekey also supports users to set the network plugin to `none` if there is a requirement for custom network plugin.
## Requirements and Recommendations
* Minimum resource requirements (For Minimal Installation of KubeSphere only)
* 2 vCPUs
* 4 GB RAM
* 20 GB Storage
> /var/lib/docker is mainly used to store the container data, and will gradually increase in size during use and operation. In the case of a production environment, it is recommended that /var/lib/docker mounts a drive separately.
* OS requirements:
* `SSH` can access to all nodes.
* Time synchronization for all nodes.
* `sudo`/`curl`/`openssl` should be used in all nodes.
* `docker` can be installed by yourself or by KubeKey.
* `Red Hat` includes `SELinux` in its `Linux release`. It is recommended to close SELinux or [switch the mode of SELinux](./docs/turn-off-SELinux.md) to `Permissive`
> * It's recommended that Your OS is clean (without any other software installed), otherwise there may be conflicts.
> * A container image mirror (accelerator) is recommended to be prepared if you have trouble downloading images from dockerhub.io. [Configure registry-mirrors for the Docker daemon](https://docs.docker.com/registry/recipes/mirror/#configure-the-docker-daemon).
> * KubeKey will install [OpenEBS](https://openebs.io/) to provision LocalPV for development and testing environment by default, this is convenient for new users. For production, please use NFS / Ceph / GlusterFS or commercial products as persistent storage, and install the [relevant client](docs/storage-client.md) in all nodes.
> * If you encounter `Permission denied` when copying, it is recommended to check [SELinux and turn off it](./docs/turn-off-SELinux.md) first
* Dependency requirements:
KubeKey can install Kubernetes and KubeSphere together. Some dependencies need to be installed before installing kubernetes after version 1.18. You can refer to the list below to check and install the relevant dependencies on your node in advance.
| | Kubernetes Version ≥ 1.18 |
| ------------- | -------------------------- |
| `socat` | Required |
| `conntrack` | Required |
| `ebtables` | Optional but recommended |
| `ipset` | Optional but recommended |
| `ipvsadm` | Optional but recommended |
* Networking and DNS requirements:
* Make sure the DNS address in `/etc/resolv.conf` is available. Otherwise, it may cause some issues of DNS in cluster.
* If your network configuration uses Firewall or Security Groupyou must ensure infrastructure components can communicate with each other through specific ports. It's recommended that you turn off the firewall or follow the link configuriation: [NetworkAccess](docs/network-access.md).
## Usage
### Get the KubeKey Executable File
* The fastest way to get KubeKey is to use the script:
```
curl -sfL https://get-kk.kubesphere.io | sh -
```
* Binary downloads of the KubeKey also can be found on the [Releases page](https://github.com/kubesphere/kubekey/releases).
Unpack the binary and you are good to go!
* Build Binary from Source Code
```shell
git clone https://github.com/kubesphere/kubekey.git
cd kubekey
make kk
```
### Create a Cluster
#### Quick Start
Quick Start is for `all-in-one` installation which is a good start to get familiar with Kubernetes and KubeSphere.
> Note: Since Kubernetes temporarily does not support uppercase NodeName, contains uppercase letters in the hostname will lead to subsequent installation error
##### Command
> If you have problem to access `https://storage.googleapis.com`, execute first `export KKZONE=cn`.
```shell
./kk create cluster [--with-kubernetes version] [--with-kubesphere version]
```
##### Examples
* Create a pure Kubernetes cluster with default version (Kubernetes v1.23.10).
```shell
./kk create cluster
```
* Create a Kubernetes cluster with a specified version.
```shell
./kk create cluster --with-kubernetes v1.24.1 --container-manager containerd
```
* Create a Kubernetes cluster with KubeSphere installed.
```shell
./kk create cluster --with-kubesphere v3.2.1
```
#### Advanced
You have more control to customize parameters or create a multi-node cluster using the advanced installation. Specifically, create a cluster by specifying a configuration file.
> If you have problem to access `https://storage.googleapis.com`, execute first `export KKZONE=cn`.
1. First, create an example configuration file
```shell
./kk create config [--with-kubernetes version] [--with-kubesphere version] [(-f | --filename) path]
```
**examples:**
* create an example config file with default configurations. You also can specify the file that could be a different filename, or in different folder.
```shell
./kk create config [-f ~/myfolder/abc.yaml]
```
* with KubeSphere
```shell
./kk create config --with-kubesphere v3.2.1
```
2. Modify the file config-sample.yaml according to your environment
> Note: Since Kubernetes temporarily does not support uppercase NodeName, contains uppercase letters in workerNode`s name will lead to subsequent installation error
>
> A persistent storage is required in the cluster, when kubesphere will be installed. The local volume is used default. If you want to use other persistent storage, please refer to [addons](./docs/addons.md).
3. Create a cluster using the configuration file
```shell
./kk create cluster -f config-sample.yaml
```
### Enable Multi-cluster Management
By default, KubeKey will only install a **solo** cluster without Kubernetes federation. If you want to set up a multi-cluster control plane to centrally manage multiple clusters using KubeSphere, you need to set the `ClusterRole` in [config-example.yaml](docs/config-example.md). For multi-cluster user guide, please refer to [How to Enable the Multi-cluster Feature](https://github.com/kubesphere/community/tree/master/sig-multicluster/how-to-setup-multicluster-on-kubesphere).
### Enable Pluggable Components
KubeSphere has decoupled some core feature components since v2.1.0. These components are designed to be pluggable which means you can enable them either before or after installation. By default, KubeSphere will be started with a minimal installation if you do not enable them.
You can enable any of them according to your demands. It is highly recommended that you install these pluggable components to discover the full-stack features and capabilities provided by KubeSphere. Please ensure your machines have sufficient CPU and memory before enabling them. See [Enable Pluggable Components](https://github.com/kubesphere/ks-installer#enable-pluggable-components) for the details.
### Add Nodes
Add new node's information to the cluster config file, then apply the changes.
```shell
./kk add nodes -f config-sample.yaml
```
### Delete Nodes
You can delete the node by the following commandthe nodeName that needs to be removed.
```shell
./kk delete node <nodeName> -f config-sample.yaml
```
### Delete Cluster
You can delete the cluster by the following command:
* If you started with the quick start (all-in-one):
```shell
./kk delete cluster
```
* If you started with the advanced (created with a configuration file):
```shell
./kk delete cluster [-f config-sample.yaml]
```
### Upgrade Cluster
#### Allinone
Upgrading cluster with a specified version.
```shell
./kk upgrade [--with-kubernetes version] [--with-kubesphere version]
```
* Support upgrading Kubernetes only.
* Support upgrading KubeSphere only.
* Support upgrading Kubernetes and KubeSphere.
#### Multi-nodes
Upgrading cluster with a specified configuration file.
```shell
./kk upgrade [--with-kubernetes version] [--with-kubesphere version] [(-f | --filename) path]
```
* If `--with-kubernetes` or `--with-kubesphere` is specified, the configuration file will be also updated.
* Use `-f` to specify the configuration file which was generated for cluster creation.
> Note: Upgrading multi-nodes cluster need a specified configuration file. If the cluster was installed without kubekey or the configuration file for installation was not found, the configuration file needs to be created by yourself or following command.
Getting cluster info and generating kubekey's configuration file (optional).
```shell
./kk create config [--from-cluster] [(-f | --filename) path] [--kubeconfig path]
```
* `--from-cluster` means fetching cluster's information from an existing cluster.
* `-f` refers to the path where the configuration file is generated.
* `--kubeconfig` refers to the path where the kubeconfig.
* After generating the configuration file, some parameters need to be filled in, such as the ssh information of the nodes.
## Documents
* [Features List](docs/features.md)
* [Commands](docs/commands/kk.md)
* [Configuration example](docs/config-example.md)
* [Air-Gapped Installation](docs/manifest_and_artifact.md)
* [Highly Available clusters](docs/ha-mode.md)
* [Addons](docs/addons.md)
* [Network access](docs/network-access.md)
* [Storage clients](docs/storage-client.md)
* [kubectl auto-completion](docs/kubectl-autocompletion.md)
* [kubekey auto-completion](docs/kubekey-autocompletion.md)
* [Roadmap](docs/roadmap.md)
* [Check-Renew-Certificate](docs/check-renew-certificate.md)
* [Developer-Guide](docs/developer-guide.md)
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pixiake"><img src="https://avatars0.githubusercontent.com/u/22290449?v=4?s=100" width="100px;" alt="pixiake"/><br /><sub><b>pixiake</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Forest-L"><img src="https://avatars2.githubusercontent.com/u/50984129?v=4?s=100" width="100px;" alt="Forest"/><br /><sub><b>Forest</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kubesphere.io/"><img src="https://avatars2.githubusercontent.com/u/28859385?v=4?s=100" width="100px;" alt="rayzhou2017"/><br /><sub><b>rayzhou2017</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.chenshaowen.com/"><img src="https://avatars2.githubusercontent.com/u/43693241?v=4?s=100" width="100px;" alt="shaowenchen"/><br /><sub><b>shaowenchen</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://surenpi.com/"><img src="https://avatars1.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Zhao Xiaojie"/><br /><sub><b>Zhao Xiaojie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zackzhangkai"><img src="https://avatars1.githubusercontent.com/u/20178386?v=4?s=100" width="100px;" alt="Zack Zhang"/><br /><sub><b>Zack Zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zackzhangkai" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://akhilerm.com/"><img src="https://avatars1.githubusercontent.com/u/7610845?v=4?s=100" width="100px;" alt="Akhil Mohan"/><br /><sub><b>Akhil Mohan</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=akhilerm" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeynmanZhou"><img src="https://avatars3.githubusercontent.com/u/40452856?v=4?s=100" width="100px;" alt="pengfei"/><br /><sub><b>pengfei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=FeynmanZhou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/min-zh"><img src="https://avatars1.githubusercontent.com/u/35321102?v=4?s=100" width="100px;" alt="min zhang"/><br /><sub><b>min zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zgldh"><img src="https://avatars1.githubusercontent.com/u/312404?v=4?s=100" width="100px;" alt="zgldh"/><br /><sub><b>zgldh</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zgldh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xrjk"><img src="https://avatars0.githubusercontent.com/u/16330256?v=4?s=100" width="100px;" alt="xrjk"/><br /><sub><b>xrjk</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xrjk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stoneshi-yunify"><img src="https://avatars2.githubusercontent.com/u/70880165?v=4?s=100" width="100px;" alt="yonghongshi"/><br /><sub><b>yonghongshi</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=stoneshi-yunify" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenhonglei"><img src="https://avatars2.githubusercontent.com/u/20896372?v=4?s=100" width="100px;" alt="Honglei"/><br /><sub><b>Honglei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shenhonglei" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liucy1983"><img src="https://avatars2.githubusercontent.com/u/2360302?v=4?s=100" width="100px;" alt="liucy1983"/><br /><sub><b>liucy1983</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liucy1983" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lilien1010"><img src="https://avatars1.githubusercontent.com/u/3814966?v=4?s=100" width="100px;" alt="Lien"/><br /><sub><b>Lien</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lilien1010" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/klj890"><img src="https://avatars3.githubusercontent.com/u/19380605?v=4?s=100" width="100px;" alt="Tony Wang"/><br /><sub><b>Tony Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=klj890" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hlwanghl"><img src="https://avatars3.githubusercontent.com/u/4861515?v=4?s=100" width="100px;" alt="Hongliang Wang"/><br /><sub><b>Hongliang Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hlwanghl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://fafucoder.github.io/"><img src="https://avatars0.githubusercontent.com/u/16442491?v=4?s=100" width="100px;" alt="dawn"/><br /><sub><b>dawn</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fafucoder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duanjiong"><img src="https://avatars1.githubusercontent.com/u/3678855?v=4?s=100" width="100px;" alt="Duan Jiong"/><br /><sub><b>Duan Jiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duanjiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/calvinyv"><img src="https://avatars3.githubusercontent.com/u/28883416?v=4?s=100" width="100px;" alt="calvinyv"/><br /><sub><b>calvinyv</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=calvinyv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benjaminhuo"><img src="https://avatars2.githubusercontent.com/u/18525465?v=4?s=100" width="100px;" alt="Benjamin Huo"/><br /><sub><b>Benjamin Huo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=benjaminhuo" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Sherlock113"><img src="https://avatars2.githubusercontent.com/u/65327072?v=4?s=100" width="100px;" alt="Sherlock113"/><br /><sub><b>Sherlock113</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Sherlock113" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fuchange"><img src="https://avatars1.githubusercontent.com/u/31716848?v=4?s=100" width="100px;" alt="fu_changjie"/><br /><sub><b>fu_changjie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Fuchange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yuswift"><img src="https://avatars1.githubusercontent.com/u/37265389?v=4?s=100" width="100px;" alt="yuswift"/><br /><sub><b>yuswift</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yuswift" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruiyaoOps"><img src="https://avatars.githubusercontent.com/u/35256376?v=4?s=100" width="100px;" alt="ruiyaoOps"/><br /><sub><b>ruiyaoOps</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ruiyaoOps" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luxingmin.com"><img src="https://avatars.githubusercontent.com/u/1918195?v=4?s=100" width="100px;" alt="LXM"/><br /><sub><b>LXM</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lxm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sbhnet"><img src="https://avatars.githubusercontent.com/u/2368131?v=4?s=100" width="100px;" alt="sbhnet"/><br /><sub><b>sbhnet</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=sbhnet" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/misteruly"><img src="https://avatars.githubusercontent.com/u/31399968?v=4?s=100" width="100px;" alt="misteruly"/><br /><sub><b>misteruly</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=misteruly" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://johnniang.me"><img src="https://avatars.githubusercontent.com/u/16865714?v=4?s=100" width="100px;" alt="John Niang"/><br /><sub><b>John Niang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=JohnNiang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://alimy.me"><img src="https://avatars.githubusercontent.com/u/10525842?v=4?s=100" width="100px;" alt="Michael Li"/><br /><sub><b>Michael Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=alimy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duguhaotian"><img src="https://avatars.githubusercontent.com/u/3174621?v=4?s=100" width="100px;" alt="独孤昊天"/><br /><sub><b>独孤昊天</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duguhaotian" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lshmouse"><img src="https://avatars.githubusercontent.com/u/118687?v=4?s=100" width="100px;" alt="Liu Shaohui"/><br /><sub><b>Liu Shaohui</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lshmouse" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/24sama"><img src="https://avatars.githubusercontent.com/u/43993589?v=4?s=100" width="100px;" alt="Leo Li"/><br /><sub><b>Leo Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=24sama" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RolandMa1986"><img src="https://avatars.githubusercontent.com/u/1720333?v=4?s=100" width="100px;" alt="Roland"/><br /><sub><b>Roland</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=RolandMa1986" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ops.m114.org"><img src="https://avatars.githubusercontent.com/u/2347587?v=4?s=100" width="100px;" alt="Vinson Zou"/><br /><sub><b>Vinson Zou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vinsonzou" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tagGeeY"><img src="https://avatars.githubusercontent.com/u/35259969?v=4?s=100" width="100px;" alt="tag_gee_y"/><br /><sub><b>tag_gee_y</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tagGeeY" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liulangwa"><img src="https://avatars.githubusercontent.com/u/25916792?v=4?s=100" width="100px;" alt="codebee"/><br /><sub><b>codebee</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liulangwa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TheApeMachine"><img src="https://avatars.githubusercontent.com/u/9572060?v=4?s=100" width="100px;" alt="Daniel Owen van Dommelen"/><br /><sub><b>Daniel Owen van Dommelen</b></sub></a><br /><a href="#ideas-TheApeMachine" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Naidile-P-N"><img src="https://avatars.githubusercontent.com/u/29476402?v=4?s=100" width="100px;" alt="Naidile P N"/><br /><sub><b>Naidile P N</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Naidile-P-N" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haiker2011"><img src="https://avatars.githubusercontent.com/u/8073429?v=4?s=100" width="100px;" alt="Haiker Sun"/><br /><sub><b>Haiker Sun</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=haiker2011" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yj-cloud"><img src="https://avatars.githubusercontent.com/u/19648473?v=4?s=100" width="100px;" alt="Jing Yu"/><br /><sub><b>Jing Yu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yj-cloud" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chaunceyjiang"><img src="https://avatars.githubusercontent.com/u/17962021?v=4?s=100" width="100px;" alt="Chauncey"/><br /><sub><b>Chauncey</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=chaunceyjiang" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tanguofu"><img src="https://avatars.githubusercontent.com/u/87045830?v=4?s=100" width="100px;" alt="Tan Guofu"/><br /><sub><b>Tan Guofu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tanguofu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lvillis"><img src="https://avatars.githubusercontent.com/u/56720445?v=4?s=100" width="100px;" alt="lvillis"/><br /><sub><b>lvillis</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lvillis" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vincenthe11"><img src="https://avatars.githubusercontent.com/u/8400716?v=4?s=100" width="100px;" alt="Vincent He"/><br /><sub><b>Vincent He</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vincenthe11" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://laminar.fun/"><img src="https://avatars.githubusercontent.com/u/2360535?v=4?s=100" width="100px;" alt="laminar"/><br /><sub><b>laminar</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tpiperatgod" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cumirror"><img src="https://avatars.githubusercontent.com/u/2455429?v=4?s=100" width="100px;" alt="tongjin"/><br /><sub><b>tongjin</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cumirror" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://k8s.li"><img src="https://avatars.githubusercontent.com/u/42566386?v=4?s=100" width="100px;" alt="Reimu"/><br /><sub><b>Reimu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=muzi502" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://yeya24.github.io/"><img src="https://avatars.githubusercontent.com/u/25150124?v=4?s=100" width="100px;" alt="Ben Ye"/><br /><sub><b>Ben Ye</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yeya24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yinheli"><img src="https://avatars.githubusercontent.com/u/235094?v=4?s=100" width="100px;" alt="yinheli"/><br /><sub><b>yinheli</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yinheli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hellocn9"><img src="https://avatars.githubusercontent.com/u/102210430?v=4?s=100" width="100px;" alt="hellocn9"/><br /><sub><b>hellocn9</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hellocn9" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brandan-schmitz"><img src="https://avatars.githubusercontent.com/u/6267549?v=4?s=100" width="100px;" alt="Brandan Schmitz"/><br /><sub><b>Brandan Schmitz</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=brandan-schmitz" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yjqg6666"><img src="https://avatars.githubusercontent.com/u/1879641?v=4?s=100" width="100px;" alt="yjqg6666"/><br /><sub><b>yjqg6666</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Documentation">📖</a> <a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zaunist"><img src="https://avatars.githubusercontent.com/u/38528079?v=4?s=100" width="100px;" alt="失眠是真滴难受"/><br /><sub><b>失眠是真滴难受</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zaunist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangoGoForward"><img src="https://avatars.githubusercontent.com/u/35127166?v=4?s=100" width="100px;" alt="mango"/><br /><sub><b>mango</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/pulls?q=is%3Apr+reviewed-by%3AmangoGoForward" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwutang1"><img src="https://avatars.githubusercontent.com/u/45817987?v=4?s=100" width="100px;" alt="wenwutang"/><br /><sub><b>wenwutang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwutang1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://kuops.com"><img src="https://avatars.githubusercontent.com/u/18283256?v=4?s=100" width="100px;" alt="Shiny Hou"/><br /><sub><b>Shiny Hou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kuops" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouqiu0103"><img src="https://avatars.githubusercontent.com/u/108912268?v=4?s=100" width="100px;" alt="zhouqiu0103"/><br /><sub><b>zhouqiu0103</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhouqiu0103" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/77yu77"><img src="https://avatars.githubusercontent.com/u/73932296?v=4?s=100" width="100px;" alt="77yu77"/><br /><sub><b>77yu77</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=77yu77" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hzhhong"><img src="https://avatars.githubusercontent.com/u/83079531?v=4?s=100" width="100px;" alt="hzhhong"/><br /><sub><b>hzhhong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hzhhong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/arugal"><img src="https://avatars.githubusercontent.com/u/26432832?v=4?s=100" width="100px;" alt="zhang-wei"/><br /><sub><b>zhang-wei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=arugal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/xds2000"><img src="https://avatars.githubusercontent.com/u/37678?v=4?s=100" width="100px;" alt="Deshi Xiao"/><br /><sub><b>Deshi Xiao</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://besscroft.com"><img src="https://avatars.githubusercontent.com/u/33775809?v=4?s=100" width="100px;" alt="besscroft"/><br /><sub><b>besscroft</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=besscroft" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhangzhiqiangcs"><img src="https://avatars.githubusercontent.com/u/8319897?v=4?s=100" width="100px;" alt="张志强"/><br /><sub><b>张志强</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhangzhiqiangcs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwabish"><img src="https://avatars.githubusercontent.com/u/7044019?v=4?s=100" width="100px;" alt="lwabish"/><br /><sub><b>lwabish</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyz87"><img src="https://avatars.githubusercontent.com/u/36068894?v=4?s=100" width="100px;" alt="qyz87"/><br /><sub><b>qyz87</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=qyz87" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fangzhengjin"><img src="https://avatars.githubusercontent.com/u/12680972?v=4?s=100" width="100px;" alt="ZhengJin Fang"/><br /><sub><b>ZhengJin Fang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fangzhengjin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://lhr.wiki"><img src="https://avatars.githubusercontent.com/u/6327311?v=4?s=100" width="100px;" alt="Eric_Lian"/><br /><sub><b>Eric_Lian</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ExerciseBook" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nicognaW"><img src="https://avatars.githubusercontent.com/u/66731869?v=4?s=100" width="100px;" alt="nicognaw"/><br /><sub><b>nicognaw</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=nicognaW" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deqingLv"><img src="https://avatars.githubusercontent.com/u/6064297?v=4?s=100" width="100px;" alt="吕德庆"/><br /><sub><b>吕德庆</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=deqingLv" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleplus"><img src="https://avatars.githubusercontent.com/u/11694750?v=4?s=100" width="100px;" alt="littleplus"/><br /><sub><b>littleplus</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleplus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD-%D0%B0%D0%BA%D0%B0%D0%BA%D0%B8%D0%B5%D0%B2-13130b1b4/"><img src="https://avatars.githubusercontent.com/u/82488489?v=4?s=100" width="100px;" alt="Konstantin"/><br /><sub><b>Konstantin</b></sub></a><br /><a href="#ideas-Nello-Angelo" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kiragoo.github.io"><img src="https://avatars.githubusercontent.com/u/7400711?v=4?s=100" width="100px;" alt="kiragoo"/><br /><sub><b>kiragoo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kiragoo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jojotong"><img src="https://avatars.githubusercontent.com/u/100849526?v=4?s=100" width="100px;" alt="jojotong"/><br /><sub><b>jojotong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=jojotong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleBlackHouse"><img src="https://avatars.githubusercontent.com/u/54946465?v=4?s=100" width="100px;" alt="littleBlackHouse"/><br /><sub><b>littleBlackHouse</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/testwill"><img src="https://avatars.githubusercontent.com/u/8717479?v=4?s=100" width="100px;" alt="guangwu"/><br /><sub><b>guangwu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wongearl"><img src="https://avatars.githubusercontent.com/u/36498442?v=4?s=100" width="100px;" alt="wongearl"/><br /><sub><b>wongearl</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wongearl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwenxiong"><img src="https://avatars.githubusercontent.com/u/10548812?v=4?s=100" width="100px;" alt="wenwenxiong"/><br /><sub><b>wenwenxiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwenxiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://baimeow.cn/"><img src="https://avatars.githubusercontent.com/u/38121125?v=4?s=100" width="100px;" alt="柏喵Sakura"/><br /><sub><b>柏喵Sakura</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=BaiMeow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dashen.tech"><img src="https://avatars.githubusercontent.com/u/15921519?v=4?s=100" width="100px;" alt="cui fliter"/><br /><sub><b>cui fliter</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cuishuang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liuxu623"><img src="https://avatars.githubusercontent.com/u/9653438?v=4?s=100" width="100px;" alt="刘旭"/><br /><sub><b>刘旭</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liuxu623" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

View File

@ -1,423 +0,0 @@
# KubeKey
[![CI](https://github.com/kubesphere/kubekey/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/kubesphere/kubekey/actions?query=event%3Apush+branch%3Amaster+workflow%3ACI+)
> [English](README.md) | 中文
KubeKey是一个开源的轻量级工具用于部署Kubernetes集群。它提供了一种灵活、快速、方便的方式来安装Kubernetes/K3s、Kubernetes/K3s和KubeSphere以及相关的云原生附加组件。它也是扩展和升级集群的有效工具。
此外KubeKey还支持定制离线包artifact方便用户在离线环境下快速部署集群。
> KubeKey 通过了 [CNCF kubernetes 一致性认证](https://www.cncf.io/certification/software-conformance/)。
有三种情况可以使用 KubeKey。
* 仅安装 Kubernetes
* 用一个命令中安装 Kubernetes 和 KubeSphere
* 首先安装 Kubernetes然后使用 [ks-installer](https://github.com/kubesphere/ks-installer) 在其上部署 KubeSphere
> 重要提示Kubekey 将会帮您安装 Kubernetes若已有 Kubernetes 集群请参考 [在 Kubernetes 之上安装 KubeSphere](https://github.com/kubesphere/ks-installer/)。
## 优势
* 基于 Ansible 的安装程序具有大量软件依赖性,例如 Python。KubeKey 是使用 Go 语言开发的,可以消除在各种环境中出现的问题,从而提高安装成功率。
* KubeKey 使用 Kubeadm 在节点上尽可能多地并行安装 K8s 集群,以降低安装复杂性并提高效率。与较早的安装程序相比,它将大大节省安装时间。
* KubeKey 支持将集群从 all-in-one 扩展到多节点集群甚至 HA 集群。
* KubeKey 旨在将集群当作一个对象操作,即 CaaO。
## 支持的环境
### Linux 发行版
* **Ubuntu** *16.04, 18.04, 20.04, 22.04*
* **Debian** *Bullseye, Buster, Stretch*
* **CentOS/RHEL** *7*
* **AlmaLinux** *9.0*
* **SUSE Linux Enterprise Server** *15*
> 建议使用 Linux Kernel 版本: `4.15 or later`
> 可以通过命令 `uname -srm` 查看 Linux Kernel 版本。
### <span id = "KubernetesVersions">Kubernetes 版本</span>
* **v1.19**: &ensp; *v1.19.15*
* **v1.20**: &ensp; *v1.20.10*
* **v1.21**: &ensp; *v1.21.14*
* **v1.22**: &ensp; *v1.22.15*
* **v1.23**: &ensp; *v1.23.10* (default)
* **v1.24**: &ensp; *v1.24.7*
* **v1.25**: &ensp; *v1.25.3*
> 查看更多支持的版本: \
> [Kubernetes 版本](./docs/kubernetes-versions.md) \
> [K3s 版本](./docs/k3s-versions.md)
## 要求和建议
* 最低资源要求(仅对于最小安装 KubeSphere
* 2 核虚拟 CPU
* 4 GB 内存
* 20 GB 储存空间
> /var/lib/docker 主要用于存储容器数据,在使用和操作过程中会逐渐增大。对于生产环境,建议 /var/lib/docker 单独挂盘。
* 操作系统要求:
* `SSH` 可以访问所有节点。
* 所有节点的时间同步。
* `sudo`/`curl`/`openssl` 应在所有节点使用。
* `docker` 可以自己安装,也可以通过 KubeKey 安装。
* `Red Hat` 在其 `Linux` 发行版本中包括了 `SELinux`,建议[关闭SELinux](./docs/turn-off-SELinux_zh-CN.md)或者将[SELinux的模式切换](./docs/turn-off-SELinux_zh-CN.md)为Permissive[宽容]工作模式
> * 建议您的操作系统环境足够干净 (不安装任何其他软件),否则可能会发生冲突。
> * 如果在从 dockerhub.io 下载镜像时遇到问题,建议准备一个容器镜像仓库 (加速器)。[为 Docker 守护程序配置镜像加速](https://docs.docker.com/registry/recipes/mirror/#configure-the-docker-daemon)。
> * 默认情况下KubeKey 将安装 [OpenEBS](https://openebs.io/) 来为开发和测试环境配置 LocalPV这对新用户来说非常方便。对于生产请使用 NFS/Ceph/GlusterFS 或商业化存储作为持久化存储,并在所有节点中安装[相关的客户端](./docs/storage-client.md) 。
> * 如果遇到拷贝时报权限问题Permission denied,建议优先考虑查看[SELinux的原因](./docs/turn-off-SELinux_zh-CN.md)。
* 依赖要求:
KubeKey 可以同时安装 Kubernetes 和 KubeSphere。在版本1.18之后安装kubernetes前需要安装一些依赖。你可以参考下面的列表提前在你的节点上检查并安装相关依赖。
| | Kubernetes 版本 ≥ 1.18 |
| ------------- | ----------------------- |
| `socat` | 必须安装 |
| `conntrack` | 必须安装 |
| `ebtables` | 可选,但推荐安装 |
| `ipset` | 可选,但推荐安装 |
| `ipvsadm` | 可选,但推荐安装 |
* 网络和 DNS 要求:
* 确保 `/etc/resolv.conf` 中的 DNS 地址可用。否则,可能会导致集群中出现某些 DNS 问题。
* 如果您的网络配置使用防火墙或安全组,则必须确保基础结构组件可以通过特定端口相互通信。建议您关闭防火墙或遵循链接配置:[网络访问](docs/network-access.md)。
## 用法
### 获取安装程序可执行文件
* 使用脚本获取 KubeKey
> 如果无法访问 https://github.com, 请先执行 export KKZONE=cn.
```
curl -sfL https://get-kk.kubesphere.io | sh -
```
* 下载KubeKey可执行文件 [Releases page](https://github.com/kubesphere/kubekey/releases)
下载解压后可直接使用。
* 从源代码生成二进制文件
```shell
git clone https://github.com/kubesphere/kubekey.git
cd kubekey
make kk
```
### 创建集群
#### 快速开始
快速入门使用 `all-in-one` 安装,这是熟悉 KubeSphere 的良好开始。
> 注意: 由于 Kubernetes 暂不支持大写 NodeName hostname 中包含大写字母将导致后续安装过程无法正常结束
##### 命令
> 如果无法访问 `https://storage.googleapis.com`, 请先执行 `export KKZONE=cn`.
```shell
./kk create cluster [--with-kubernetes version] [--with-kubesphere version]
```
##### 例子
* 使用默认版本创建一个纯 Kubernetes 集群
```shell
./kk create cluster
```
* 创建指定一个([支持的版本](#KubernetesVersions))的 Kubernetes 集群
```shell
./kk create cluster --with-kubernetes v1.19.8
```
* 创建一个部署了 KubeSphere 的 Kubernetes 集群 (例如 `--with-kubesphere v3.1.0`
```shell
./kk create cluster --with-kubesphere [version]
```
* 创建一个指定的 container runtime 的 Kubernetes 集群docker, crio, containerd and isula
```shell
./kk create cluster --container-manager containerd
```
#### 高级用法
您可以使用高级安装来控制自定义参数或创建多节点集群。具体来说,通过指定配置文件来创建集群。
> 如果无法访问 `https://storage.googleapis.com`, 请先执行 `export KKZONE=cn`.
1. 首先,创建一个示例配置文件
```shell
./kk create config [--with-kubernetes version] [--with-kubesphere version] [(-f | --filename) path]
```
**例子:**
* 使用默认配置创建一个示例配置文件。您也可以指定文件名称或文件所在的文件夹。
```shell
./kk create config [-f ~/myfolder/config-sample.yaml]
```
* 同时安装 KubeSphere
```shell
./kk create config --with-kubesphere
```
2. 根据您的环境修改配置文件 config-sample.yaml
> 注意: 由于 Kubernetes 暂不支持大写 NodeName worker 节点名中包含大写字母将导致后续安装过程无法正常结束
>
> 当指定安装KubeSphere时要求集群中有可用的持久化存储。默认使用localVolume如果需要使用其他持久化存储请参阅 [addons](./docs/addons.md) 配置。
3. 使用配置文件创建集群。
```shell
./kk create cluster -f ~/myfolder/config-sample.yaml
```
### 启用多集群管理
默认情况下Kubekey 将仅安装一个 Solo 模式的单集群,即未开启 Kubernetes 多集群联邦。如果您希望将 KubeSphere 作为一个支持多集群集中管理的中央面板,您需要在 [config-example.yaml](docs/config-example.md) 中设置 `ClusterRole`。关于多集群的使用文档,请参考 [如何启用多集群](https://github.com/kubesphere/community/blob/master/sig-multicluster/how-to-setup-multicluster-on-kubesphere/README_zh.md)。
### 开启可插拔功能组件
KubeSphere 从 2.1.0 版本开始对 Installer 的各功能组件进行了解耦快速安装将默认仅开启最小化安装Minimal InstallationInstaller 支持在安装前或安装后自定义可插拔的功能组件的安装。使最小化安装更快速轻量且资源占用更少,也方便不同用户按需选择安装不同的功能组件。
KubeSphere 有多个可插拔功能组件,功能组件的介绍可参考 [配置示例](docs/config-example.md)。您可以根据需求,选择开启安装 KubeSphere 的可插拔功能组件。我们非常建议您开启这些功能组件来体验 KubeSphere 完整的功能以及端到端的解决方案。请在安装前确保您的机器有足够的 CPU 与内存资源。开启可插拔功能组件可参考 [开启可选功能组件](https://github.com/kubesphere/ks-installer/blob/master/README_zh.md#%E5%AE%89%E8%A3%85%E5%8A%9F%E8%83%BD%E7%BB%84%E4%BB%B6)。
### 添加节点
将新节点的信息添加到集群配置文件,然后应用更改。
```shell
./kk add nodes -f config-sample.yaml
```
### 删除节点
通过以下命令删除节点nodename指需要删除的节点名。
```shell
./kk delete node <nodeName> -f config-sample.yaml
```
### 删除集群
您可以通过以下命令删除集群:
* 如果您以快速入门all-in-one开始
```shell
./kk delete cluster
```
* 如果从高级安装开始(使用配置文件创建的集群):
```shell
./kk delete cluster [-f config-sample.yaml]
```
### 集群升级
#### 单节点集群
升级集群到指定版本。
```shell
./kk upgrade [--with-kubernetes version] [--with-kubesphere version]
```
* `--with-kubernetes` 指定kubernetes目标版本。
* `--with-kubesphere` 指定kubesphere目标版本。
#### 多节点集群
通过指定配置文件对集群进行升级。
```shell
./kk upgrade [--with-kubernetes version] [--with-kubesphere version] [(-f | --filename) path]
```
* `--with-kubernetes` 指定kubernetes目标版本。
* `--with-kubesphere` 指定kubesphere目标版本。
* `-f` 指定集群安装时创建的配置文件。
> 注意: 升级多节点集群需要指定配置文件. 如果集群非kubekey创建或者创建集群时生成的配置文件丢失需要重新生成配置文件或使用以下方法生成。
Getting cluster info and generating kubekey's configuration file (optional).
```shell
./kk create config [--from-cluster] [(-f | --filename) path] [--kubeconfig path]
```
* `--from-cluster` 根据已存在集群信息生成配置文件.
* `-f` 指定生成配置文件路径.
* `--kubeconfig` 指定集群kubeconfig文件.
* 由于无法全面获取集群配置,生成配置文件后,请根据集群实际信息补全配置文件。
### 启用 kubectl 自动补全
KubeKey 不会启用 kubectl 自动补全功能。请参阅下面的指南并将其打开:
**先决条件**:确保已安装 `bash-autocompletion` 并可以正常工作。
```shell
# 安装 bash-completion
apt-get install bash-completion
# 将 completion 脚本添加到你的 ~/.bashrc 文件
echo 'source <(kubectl completion bash)' >>~/.bashrc
# 将 completion 脚本添加到 /etc/bash_completion.d 目录
kubectl completion bash >/etc/bash_completion.d/kubectl
```
更详细的参考可以在[这里](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion)找到。
## 相关文档
* [特性列表](docs/features.md)
* [命令手册](docs/commands/kk.md)
* [配置示例](docs/config-example.md)
* [离线安装](docs/zh/manifest_and_artifact.md)
* [高可用集群](docs/ha-mode.md)
* [自定义插件安装](docs/addons.md)
* [网络访问](docs/network-access.md)
* [存储客户端](docs/storage-client.md)
* [路线图](docs/roadmap.md)
* [查看或更新证书](docs/check-renew-certificate.md)
* [开发指南](docs/developer-guide.md)
## 贡献者 ✨
欢迎任何形式的贡献! 感谢这些优秀的贡献者,是他们让我们的项目快速成长。
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pixiake"><img src="https://avatars0.githubusercontent.com/u/22290449?v=4?s=100" width="100px;" alt="pixiake"/><br /><sub><b>pixiake</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=pixiake" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Forest-L"><img src="https://avatars2.githubusercontent.com/u/50984129?v=4?s=100" width="100px;" alt="Forest"/><br /><sub><b>Forest</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=Forest-L" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kubesphere.io/"><img src="https://avatars2.githubusercontent.com/u/28859385?v=4?s=100" width="100px;" alt="rayzhou2017"/><br /><sub><b>rayzhou2017</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=rayzhou2017" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.chenshaowen.com/"><img src="https://avatars2.githubusercontent.com/u/43693241?v=4?s=100" width="100px;" alt="shaowenchen"/><br /><sub><b>shaowenchen</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=shaowenchen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://surenpi.com/"><img src="https://avatars1.githubusercontent.com/u/1450685?v=4?s=100" width="100px;" alt="Zhao Xiaojie"/><br /><sub><b>Zhao Xiaojie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=LinuxSuRen" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zackzhangkai"><img src="https://avatars1.githubusercontent.com/u/20178386?v=4?s=100" width="100px;" alt="Zack Zhang"/><br /><sub><b>Zack Zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zackzhangkai" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://akhilerm.com/"><img src="https://avatars1.githubusercontent.com/u/7610845?v=4?s=100" width="100px;" alt="Akhil Mohan"/><br /><sub><b>Akhil Mohan</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=akhilerm" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeynmanZhou"><img src="https://avatars3.githubusercontent.com/u/40452856?v=4?s=100" width="100px;" alt="pengfei"/><br /><sub><b>pengfei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=FeynmanZhou" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/min-zh"><img src="https://avatars1.githubusercontent.com/u/35321102?v=4?s=100" width="100px;" alt="min zhang"/><br /><sub><b>min zhang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=min-zh" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zgldh"><img src="https://avatars1.githubusercontent.com/u/312404?v=4?s=100" width="100px;" alt="zgldh"/><br /><sub><b>zgldh</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zgldh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xrjk"><img src="https://avatars0.githubusercontent.com/u/16330256?v=4?s=100" width="100px;" alt="xrjk"/><br /><sub><b>xrjk</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xrjk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/stoneshi-yunify"><img src="https://avatars2.githubusercontent.com/u/70880165?v=4?s=100" width="100px;" alt="yonghongshi"/><br /><sub><b>yonghongshi</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=stoneshi-yunify" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shenhonglei"><img src="https://avatars2.githubusercontent.com/u/20896372?v=4?s=100" width="100px;" alt="Honglei"/><br /><sub><b>Honglei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=shenhonglei" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liucy1983"><img src="https://avatars2.githubusercontent.com/u/2360302?v=4?s=100" width="100px;" alt="liucy1983"/><br /><sub><b>liucy1983</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liucy1983" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lilien1010"><img src="https://avatars1.githubusercontent.com/u/3814966?v=4?s=100" width="100px;" alt="Lien"/><br /><sub><b>Lien</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lilien1010" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/klj890"><img src="https://avatars3.githubusercontent.com/u/19380605?v=4?s=100" width="100px;" alt="Tony Wang"/><br /><sub><b>Tony Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=klj890" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hlwanghl"><img src="https://avatars3.githubusercontent.com/u/4861515?v=4?s=100" width="100px;" alt="Hongliang Wang"/><br /><sub><b>Hongliang Wang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hlwanghl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://fafucoder.github.io/"><img src="https://avatars0.githubusercontent.com/u/16442491?v=4?s=100" width="100px;" alt="dawn"/><br /><sub><b>dawn</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fafucoder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duanjiong"><img src="https://avatars1.githubusercontent.com/u/3678855?v=4?s=100" width="100px;" alt="Duan Jiong"/><br /><sub><b>Duan Jiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duanjiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/calvinyv"><img src="https://avatars3.githubusercontent.com/u/28883416?v=4?s=100" width="100px;" alt="calvinyv"/><br /><sub><b>calvinyv</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=calvinyv" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/benjaminhuo"><img src="https://avatars2.githubusercontent.com/u/18525465?v=4?s=100" width="100px;" alt="Benjamin Huo"/><br /><sub><b>Benjamin Huo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=benjaminhuo" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Sherlock113"><img src="https://avatars2.githubusercontent.com/u/65327072?v=4?s=100" width="100px;" alt="Sherlock113"/><br /><sub><b>Sherlock113</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Sherlock113" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Fuchange"><img src="https://avatars1.githubusercontent.com/u/31716848?v=4?s=100" width="100px;" alt="fu_changjie"/><br /><sub><b>fu_changjie</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Fuchange" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yuswift"><img src="https://avatars1.githubusercontent.com/u/37265389?v=4?s=100" width="100px;" alt="yuswift"/><br /><sub><b>yuswift</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yuswift" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ruiyaoOps"><img src="https://avatars.githubusercontent.com/u/35256376?v=4?s=100" width="100px;" alt="ruiyaoOps"/><br /><sub><b>ruiyaoOps</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ruiyaoOps" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.luxingmin.com"><img src="https://avatars.githubusercontent.com/u/1918195?v=4?s=100" width="100px;" alt="LXM"/><br /><sub><b>LXM</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lxm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sbhnet"><img src="https://avatars.githubusercontent.com/u/2368131?v=4?s=100" width="100px;" alt="sbhnet"/><br /><sub><b>sbhnet</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=sbhnet" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/misteruly"><img src="https://avatars.githubusercontent.com/u/31399968?v=4?s=100" width="100px;" alt="misteruly"/><br /><sub><b>misteruly</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=misteruly" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://johnniang.me"><img src="https://avatars.githubusercontent.com/u/16865714?v=4?s=100" width="100px;" alt="John Niang"/><br /><sub><b>John Niang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=JohnNiang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://alimy.me"><img src="https://avatars.githubusercontent.com/u/10525842?v=4?s=100" width="100px;" alt="Michael Li"/><br /><sub><b>Michael Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=alimy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/duguhaotian"><img src="https://avatars.githubusercontent.com/u/3174621?v=4?s=100" width="100px;" alt="独孤昊天"/><br /><sub><b>独孤昊天</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=duguhaotian" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lshmouse"><img src="https://avatars.githubusercontent.com/u/118687?v=4?s=100" width="100px;" alt="Liu Shaohui"/><br /><sub><b>Liu Shaohui</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lshmouse" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/24sama"><img src="https://avatars.githubusercontent.com/u/43993589?v=4?s=100" width="100px;" alt="Leo Li"/><br /><sub><b>Leo Li</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=24sama" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RolandMa1986"><img src="https://avatars.githubusercontent.com/u/1720333?v=4?s=100" width="100px;" alt="Roland"/><br /><sub><b>Roland</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=RolandMa1986" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ops.m114.org"><img src="https://avatars.githubusercontent.com/u/2347587?v=4?s=100" width="100px;" alt="Vinson Zou"/><br /><sub><b>Vinson Zou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vinsonzou" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tagGeeY"><img src="https://avatars.githubusercontent.com/u/35259969?v=4?s=100" width="100px;" alt="tag_gee_y"/><br /><sub><b>tag_gee_y</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tagGeeY" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liulangwa"><img src="https://avatars.githubusercontent.com/u/25916792?v=4?s=100" width="100px;" alt="codebee"/><br /><sub><b>codebee</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liulangwa" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TheApeMachine"><img src="https://avatars.githubusercontent.com/u/9572060?v=4?s=100" width="100px;" alt="Daniel Owen van Dommelen"/><br /><sub><b>Daniel Owen van Dommelen</b></sub></a><br /><a href="#ideas-TheApeMachine" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Naidile-P-N"><img src="https://avatars.githubusercontent.com/u/29476402?v=4?s=100" width="100px;" alt="Naidile P N"/><br /><sub><b>Naidile P N</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=Naidile-P-N" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haiker2011"><img src="https://avatars.githubusercontent.com/u/8073429?v=4?s=100" width="100px;" alt="Haiker Sun"/><br /><sub><b>Haiker Sun</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=haiker2011" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yj-cloud"><img src="https://avatars.githubusercontent.com/u/19648473?v=4?s=100" width="100px;" alt="Jing Yu"/><br /><sub><b>Jing Yu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yj-cloud" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chaunceyjiang"><img src="https://avatars.githubusercontent.com/u/17962021?v=4?s=100" width="100px;" alt="Chauncey"/><br /><sub><b>Chauncey</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=chaunceyjiang" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tanguofu"><img src="https://avatars.githubusercontent.com/u/87045830?v=4?s=100" width="100px;" alt="Tan Guofu"/><br /><sub><b>Tan Guofu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tanguofu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lvillis"><img src="https://avatars.githubusercontent.com/u/56720445?v=4?s=100" width="100px;" alt="lvillis"/><br /><sub><b>lvillis</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lvillis" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vincenthe11"><img src="https://avatars.githubusercontent.com/u/8400716?v=4?s=100" width="100px;" alt="Vincent He"/><br /><sub><b>Vincent He</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=vincenthe11" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://laminar.fun/"><img src="https://avatars.githubusercontent.com/u/2360535?v=4?s=100" width="100px;" alt="laminar"/><br /><sub><b>laminar</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=tpiperatgod" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cumirror"><img src="https://avatars.githubusercontent.com/u/2455429?v=4?s=100" width="100px;" alt="tongjin"/><br /><sub><b>tongjin</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cumirror" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://k8s.li"><img src="https://avatars.githubusercontent.com/u/42566386?v=4?s=100" width="100px;" alt="Reimu"/><br /><sub><b>Reimu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=muzi502" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=eltociear" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://yeya24.github.io/"><img src="https://avatars.githubusercontent.com/u/25150124?v=4?s=100" width="100px;" alt="Ben Ye"/><br /><sub><b>Ben Ye</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yeya24" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yinheli"><img src="https://avatars.githubusercontent.com/u/235094?v=4?s=100" width="100px;" alt="yinheli"/><br /><sub><b>yinheli</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yinheli" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hellocn9"><img src="https://avatars.githubusercontent.com/u/102210430?v=4?s=100" width="100px;" alt="hellocn9"/><br /><sub><b>hellocn9</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hellocn9" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brandan-schmitz"><img src="https://avatars.githubusercontent.com/u/6267549?v=4?s=100" width="100px;" alt="Brandan Schmitz"/><br /><sub><b>Brandan Schmitz</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=brandan-schmitz" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yjqg6666"><img src="https://avatars.githubusercontent.com/u/1879641?v=4?s=100" width="100px;" alt="yjqg6666"/><br /><sub><b>yjqg6666</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Documentation">📖</a> <a href="https://github.com/kubesphere/kubekey/commits?author=yjqg6666" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zaunist"><img src="https://avatars.githubusercontent.com/u/38528079?v=4?s=100" width="100px;" alt="失眠是真滴难受"/><br /><sub><b>失眠是真滴难受</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zaunist" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mangoGoForward"><img src="https://avatars.githubusercontent.com/u/35127166?v=4?s=100" width="100px;" alt="mango"/><br /><sub><b>mango</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/pulls?q=is%3Apr+reviewed-by%3AmangoGoForward" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwutang1"><img src="https://avatars.githubusercontent.com/u/45817987?v=4?s=100" width="100px;" alt="wenwutang"/><br /><sub><b>wenwutang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwutang1" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://kuops.com"><img src="https://avatars.githubusercontent.com/u/18283256?v=4?s=100" width="100px;" alt="Shiny Hou"/><br /><sub><b>Shiny Hou</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kuops" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhouqiu0103"><img src="https://avatars.githubusercontent.com/u/108912268?v=4?s=100" width="100px;" alt="zhouqiu0103"/><br /><sub><b>zhouqiu0103</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhouqiu0103" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/77yu77"><img src="https://avatars.githubusercontent.com/u/73932296?v=4?s=100" width="100px;" alt="77yu77"/><br /><sub><b>77yu77</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=77yu77" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hzhhong"><img src="https://avatars.githubusercontent.com/u/83079531?v=4?s=100" width="100px;" alt="hzhhong"/><br /><sub><b>hzhhong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=hzhhong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/arugal"><img src="https://avatars.githubusercontent.com/u/26432832?v=4?s=100" width="100px;" alt="zhang-wei"/><br /><sub><b>zhang-wei</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=arugal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/xds2000"><img src="https://avatars.githubusercontent.com/u/37678?v=4?s=100" width="100px;" alt="Deshi Xiao"/><br /><sub><b>Deshi Xiao</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=xiaods" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://besscroft.com"><img src="https://avatars.githubusercontent.com/u/33775809?v=4?s=100" width="100px;" alt="besscroft"/><br /><sub><b>besscroft</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=besscroft" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zhangzhiqiangcs"><img src="https://avatars.githubusercontent.com/u/8319897?v=4?s=100" width="100px;" alt="张志强"/><br /><sub><b>张志强</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=zhangzhiqiangcs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lwabish"><img src="https://avatars.githubusercontent.com/u/7044019?v=4?s=100" width="100px;" alt="lwabish"/><br /><sub><b>lwabish</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=lwabish" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyz87"><img src="https://avatars.githubusercontent.com/u/36068894?v=4?s=100" width="100px;" alt="qyz87"/><br /><sub><b>qyz87</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=qyz87" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fangzhengjin"><img src="https://avatars.githubusercontent.com/u/12680972?v=4?s=100" width="100px;" alt="ZhengJin Fang"/><br /><sub><b>ZhengJin Fang</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=fangzhengjin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://lhr.wiki"><img src="https://avatars.githubusercontent.com/u/6327311?v=4?s=100" width="100px;" alt="Eric_Lian"/><br /><sub><b>Eric_Lian</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=ExerciseBook" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nicognaW"><img src="https://avatars.githubusercontent.com/u/66731869?v=4?s=100" width="100px;" alt="nicognaw"/><br /><sub><b>nicognaw</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=nicognaW" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deqingLv"><img src="https://avatars.githubusercontent.com/u/6064297?v=4?s=100" width="100px;" alt="吕德庆"/><br /><sub><b>吕德庆</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=deqingLv" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleplus"><img src="https://avatars.githubusercontent.com/u/11694750?v=4?s=100" width="100px;" alt="littleplus"/><br /><sub><b>littleplus</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleplus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B8%D0%BD-%D0%B0%D0%BA%D0%B0%D0%BA%D0%B8%D0%B5%D0%B2-13130b1b4/"><img src="https://avatars.githubusercontent.com/u/82488489?v=4?s=100" width="100px;" alt="Konstantin"/><br /><sub><b>Konstantin</b></sub></a><br /><a href="#ideas-Nello-Angelo" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kiragoo.github.io"><img src="https://avatars.githubusercontent.com/u/7400711?v=4?s=100" width="100px;" alt="kiragoo"/><br /><sub><b>kiragoo</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=kiragoo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jojotong"><img src="https://avatars.githubusercontent.com/u/100849526?v=4?s=100" width="100px;" alt="jojotong"/><br /><sub><b>jojotong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=jojotong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/littleBlackHouse"><img src="https://avatars.githubusercontent.com/u/54946465?v=4?s=100" width="100px;" alt="littleBlackHouse"/><br /><sub><b>littleBlackHouse</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=littleBlackHouse" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/testwill"><img src="https://avatars.githubusercontent.com/u/8717479?v=4?s=100" width="100px;" alt="guangwu"/><br /><sub><b>guangwu</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Code">💻</a> <a href="https://github.com/kubesphere/kubekey/commits?author=testwill" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wongearl"><img src="https://avatars.githubusercontent.com/u/36498442?v=4?s=100" width="100px;" alt="wongearl"/><br /><sub><b>wongearl</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wongearl" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wenwenxiong"><img src="https://avatars.githubusercontent.com/u/10548812?v=4?s=100" width="100px;" alt="wenwenxiong"/><br /><sub><b>wenwenxiong</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=wenwenxiong" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://baimeow.cn/"><img src="https://avatars.githubusercontent.com/u/38121125?v=4?s=100" width="100px;" alt="柏喵Sakura"/><br /><sub><b>柏喵Sakura</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=BaiMeow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dashen.tech"><img src="https://avatars.githubusercontent.com/u/15921519?v=4?s=100" width="100px;" alt="cui fliter"/><br /><sub><b>cui fliter</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=cuishuang" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liuxu623"><img src="https://avatars.githubusercontent.com/u/9653438?v=4?s=100" width="100px;" alt="刘旭"/><br /><sub><b>刘旭</b></sub></a><br /><a href="https://github.com/kubesphere/kubekey/commits?author=liuxu623" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->

View File

@ -1,54 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"time"
)
// Auth contains the SSH authentication configuration for machines.
type Auth struct {
// User is the username for SSH authentication.
// +optional
User string `yaml:"user,omitempty" json:"user,omitempty"`
// Password is the password for SSH authentication.
// +optional
Password string `yaml:"password,omitempty" json:"password,omitempty"`
// Port is the port for SSH authentication.
// +optional
Port *int `yaml:"port,omitempty" json:"port,omitempty"`
// PrivateKey is the value of the private key for SSH authentication.
// +optional
PrivateKey string `yaml:"privateKey,omitempty" json:"privateKey,omitempty"`
// PrivateKeyFile is the path to the private key for SSH authentication.
// +optional
PrivateKeyPath string `yaml:"privateKeyPath,omitempty" json:"privateKeyPath,omitempty"`
// Secret is the secret of the PrivateKey or Password for SSH authentication.It should in the same namespace as capkk.
// When Password is empty, replace it with data.password.
// When PrivateKey is empty, replace it with data.privateKey
// +optional
Secret string `yaml:"secret,omitempty" json:"secret,omitempty"`
// Timeout is the timeout for establish an SSH connection.
// +optional
Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
}

View File

@ -1,22 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
const (
// KKClusterLabelName is the label set on KKMachines and KKInstances linked to a kkCluster.
KKClusterLabelName = "kkcluster.infrastructure.cluster.x-k8s.io/cluster-name"
)

View File

@ -1,66 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
// Component is optional configuration for modifying the FTP server.
type Component struct {
// ZONE is the zone of the KKCluster where can get the binaries.
// If you have problem to access https://storage.googleapis.com, you can set "zone: cn".
// +optional
ZONE string `json:"zone,omitempty"`
// Host is the host to download the binaries.
// +optional
Host string `json:"host,omitempty"`
// Overrides is a list of components download information that need to be overridden.
// +optional
Overrides []Override `json:"overrides,omitempty"`
}
// Override is a component download information that need to be overridden.
type Override struct {
// ID is the component id name. e.g. kubeadm, kubelet, containerd, etc.
ID string `json:"id,omitempty"`
// Arch is the component arch. e.g. amd64, arm64, etc.
Arch string `json:"arch,omitempty"`
// Version is the component version. e.g. v1.21.1, v1.22.0, etc.
Version string `json:"version,omitempty"`
// URL is the download url of the binaries.
URL string `json:"url,omitempty"`
// Path defines the URL path, which is the string of information that comes after the top level domain name.
Path string `json:"path,omitempty"`
// Checksum is the SHA256 checksum of the binary.
// +optional
Checksum Checksum `json:"checksum,omitempty"`
}
// Checksum is the SHA256 checksum of the binary.
type Checksum struct {
// Value is the checksum string value.
// +optional
Value string `json:"value,omitempty"`
// Path defines the URL path, which is the path of the checksum file.
// +optional
Path string `json:"path,omitempty"`
}

View File

@ -1,135 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)
// KKCluster condition
const (
// PrincipalPreparedCondition reports whether the principal is prepared.
PrincipalPreparedCondition clusterv1.ConditionType = "PrincipalPrepared"
)
const (
// HostReadyCondition reports whether the host is ready to be used.
HostReadyCondition clusterv1.ConditionType = "HostReadyCondition"
)
const (
// ExternalLoadBalancerReadyCondition reports on whether a control plane load balancer was successfully reconciled.
ExternalLoadBalancerReadyCondition clusterv1.ConditionType = "ExternalLoadBalancerReady"
// WaitForDNSNameResolveReason used while waiting for DNS name to resolve.
WaitForDNSNameResolveReason = "WaitForDNSNameResolve"
)
const (
// CallKKInstanceInPlaceUpgradeCondition reports whether set up the InPlaceUpgradeVersionAnnotation annotation on all the KKInstance conditions.
CallKKInstanceInPlaceUpgradeCondition clusterv1.ConditionType = "CallKKInstanceInPlaceUpgrade"
// KKInstanceObjectNotUpdatedReason used when the KKInstance is not updated.
KKInstanceObjectNotUpdatedReason = "KKInstanceObjectNotUpdated"
// AllKKInstancesUpgradeCompletedCondition reports whether all the KKInstances are upgraded.
AllKKInstancesUpgradeCompletedCondition clusterv1.ConditionType = "AllKKInstancesUpgradeCompleted"
// WaitingForKKInstancesUpgradeReason used when the KKCluster is waiting for all KKInstance to be upgrading completed.
WaitingForKKInstancesUpgradeReason = "WaitingForKKInstancesUpgrade"
)
// KKMachine condition
const (
// InstanceReadyCondition reports on current status of the SSH instance. Ready indicates the instance is in a Running state.
InstanceReadyCondition clusterv1.ConditionType = "InstanceReady"
// InstanceNotFoundReason used when the instance couldn't be retrieved.
InstanceNotFoundReason = "InstanceNotFound"
// InstanceCleanedReason instance is in a Cleared state.
InstanceCleanedReason = "InstanceCleaned"
// InstanceNotReadyReason used when the instance is in a pending state.
InstanceNotReadyReason = "InstanceNotReady"
// InstanceInPlaceUpgradingReason used when the instance is in a InstanceStateInPlaceUpgrading state.
InstanceInPlaceUpgradingReason = "InstanceInPlaceUpgrading"
// InstanceBootstrapStartedReason set when the provisioning of an instance started.
InstanceBootstrapStartedReason = "InstanceBootstrapStarted"
// InstanceBootstrapFailedReason used for failures during instance provisioning.
InstanceBootstrapFailedReason = "InstanceBootstrapFailed"
// WaitingForClusterInfrastructureReason used when machine is waiting for cluster infrastructure to be ready before proceeding.
WaitingForClusterInfrastructureReason = "WaitingForClusterInfrastructure"
// WaitingForBootstrapDataReason used when machine is waiting for bootstrap data to be ready before proceeding.
WaitingForBootstrapDataReason = "WaitingForBootstrapData"
)
// KKInstance condition
const (
// KKInstanceBootstrappedCondition reports on current status of the instance. Ready indicates the instance is in a init Bootstrapped state.
KKInstanceBootstrappedCondition clusterv1.ConditionType = "InstanceBootstrapped"
// KKInstanceInitOSFailedReason used when the instance couldn't initialize os environment.
KKInstanceInitOSFailedReason = "InitOSFailed"
)
const (
// KKInstanceRepositoryReadyCondition reports on whether successful to use repository to install packages.
KKInstanceRepositoryReadyCondition clusterv1.ConditionType = "InstanceRepositoryReady"
// KKInstanceRepositoryFailedReason used when the instance couldn't use repository to install packages.
KKInstanceRepositoryFailedReason = "InstanceRepositoryFailed"
)
const (
// KKInstanceBinariesReadyCondition reports on whether successful to download binaries.
KKInstanceBinariesReadyCondition clusterv1.ConditionType = "InstanceBinariesReady"
// KKInstanceGetBinaryFailedReason used when the instance couldn't download binaries (or check existed binaries).
KKInstanceGetBinaryFailedReason = "GetBinaryFailed"
)
const (
// KKInstanceCRIReadyCondition reports on whether successful to download and install CRI.
KKInstanceCRIReadyCondition clusterv1.ConditionType = "InstanceCRIReady"
// KKInstanceInstallCRIFailedReason used when the instance couldn't download and install CRI.
KKInstanceInstallCRIFailedReason = "InstallCRIFailed"
)
const (
// KKInstanceProvisionedCondition reports on whether the instance is provisioned by cloud-init.
KKInstanceProvisionedCondition clusterv1.ConditionType = "InstanceProvisioned"
// KKInstanceRunCloudConfigFailedReason used when the instance couldn't be provisioned.
KKInstanceRunCloudConfigFailedReason = "RunCloudConfigFailed"
)
const (
// KKInstanceDeletingBootstrapCondition reports on whether the instance is deleting bootstrap data.
KKInstanceDeletingBootstrapCondition clusterv1.ConditionType = "InstanceDeletingBootstrapped"
// KKInstanceClearEnvironmentFailedReason used when the instance couldn't be deleting bootstrap data.
KKInstanceClearEnvironmentFailedReason = "ClearEnvironmentFailed"
// CleaningReason (Severity=Info) documents a machine node being cleaned.
CleaningReason = "Cleaning"
)
const (
// KKInstanceInPlaceUpgradedCondition reports on whether the instance is in place upgrade succeed.
KKInstanceInPlaceUpgradedCondition clusterv1.ConditionType = "KKInstanceInPlaceUpgraded"
)
const (
// KKInstanceInPlaceUpgradeBinariesCondition reports on whether the instance is in place upgrade download binaries succeed.
KKInstanceInPlaceUpgradeBinariesCondition clusterv1.ConditionType = "KKInstanceInPlaceUpgradeBinaries"
// KKInstanceInPlaceGetBinaryFailedReason used when the instance couldn't download binaries (or check existed binaries).
KKInstanceInPlaceGetBinaryFailedReason = "KKInstanceInPlaceUpgradeGetBinaryFailed"
)

View File

@ -1,53 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
// Default values.
const (
DockerType = "docker"
DefaultDockerVersion = "20.10.8"
DefaultCRIDockerdVersion = "0.2.6"
DefaultDockerCRISocket = "unix:///run/cri-dockerd.sock"
ContainerdType = "containerd"
DefaultContainerdVersion = "1.6.4"
DefaultContainerdCRISocket = "unix:///var/run/containerd/containerd.sock"
DefaultCrictlVersion = "v1.24.0"
)
// ContainerManager defines the desired state of ContainerManager
type ContainerManager struct {
// CRISocket is used to connect an existing CRIClient.
// +optional
CRISocket string `json:"criSocket,omitempty"`
// Type defines the type of ContainerManager.
// "docker", "containerd"
Type string `json:"type,omitempty"`
// Version defines the version of ContainerManager.
Version string `json:"version,omitempty"`
// CRICTLVersion defines the version of CRICTL.
CRICTLVersion string `json:"crictlVersion,omitempty"`
// CRIDockerdVersion defines the version of cri-dockerd, available only when Type is docker.
// https://github.com/Mirantis/cri-dockerd
// +optional
CRIDockerdVersion string `json:"criDockerdVersion,omitempty"`
}

View File

@ -1,18 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1beta1 contains the v1beta1 API implementation.
package v1beta1

View File

@ -1,36 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group
// +kubebuilder:object:generate=true
// +groupName=infrastructure.cluster.x-k8s.io
package v1beta1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1beta1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@ -1,191 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
)
const (
// ClusterFinalizer allows ReconcileKKCluster to clean up KK resources associated with KKCluster before
// removing it from the apiserver.
ClusterFinalizer = "kkcluster.infrastructure.cluster.x-k8s.io"
// KUBERNETES the Kubernetes distributions
KUBERNETES = "kubernetes"
// K3S the K3S distributions
K3S = "k3s"
// InPlaceUpgradeVersionAnnotation is the annotation that stores the version of the cluster used for in-place upgrade.
InPlaceUpgradeVersionAnnotation = "kkcluster.infrastructure.cluster.x-k8s.io/in-place-upgrade-version"
)
// KKClusterSpec defines the desired state of KKCluster
type KKClusterSpec struct {
// Distribution represents the Kubernetes distribution type of the cluster.
Distribution string `json:"distribution,omitempty"`
// Nodes represents the information about the nodes available to the cluster
Nodes Nodes `json:"nodes"`
// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
// +optional
ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"`
// ControlPlaneLoadBalancer is optional configuration for customizing control plane behavior.
ControlPlaneLoadBalancer *KKLoadBalancerSpec `json:"controlPlaneLoadBalancer,omitempty"`
// Component is optional configuration for modifying the FTP server
// that gets the necessary components for the cluster.
// +optional
Component *Component `json:"component,omitempty"`
// Registry represents the cluster image registry used to pull the images.
// +optional
Registry Registry `json:"registry,omitempty"`
}
// Nodes represents the information about the nodes available to the cluster
type Nodes struct {
// Auth is the SSH authentication information of all instance. It is a global auth configuration.
// +optional
Auth Auth `json:"auth"`
// Instances defines all instance contained in kkcluster.
Instances []InstanceInfo `json:"instances"`
}
// InstanceInfo defines the information about the instance.
type InstanceInfo struct {
// Name is the host name of the machine.
// +kubebuilder:validation:MinLength=1
Name string `json:"name,omitempty"`
// Address is the IP address of the machine.
Address string `json:"address,omitempty"`
// InternalAddress is the internal IP address of the machine.
InternalAddress string `json:"internalAddress,omitempty"`
// Roles is the role of the machine.
// +optional
Roles []Role `json:"roles,omitempty"`
// Arch is the architecture of the machine. e.g. "amd64", "arm64".
// +optional
Arch string `json:"arch,omitempty"`
// Auth is the SSH authentication information of this machine. It will override the global auth configuration.
// +optional
Auth Auth `json:"auth,omitempty"`
}
// KKLoadBalancerSpec defines the desired state of an KK load balancer.
type KKLoadBalancerSpec struct {
// The hostname on which the API server is serving.
Host string `json:"host,omitempty"`
}
// KKClusterStatus defines the observed state of KKCluster
type KKClusterStatus struct {
// +kubebuilder:default=false
Ready bool `json:"ready"`
// FailureReason will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a succinct value suitable
// for machine interpretation.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
// FailureMessage will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a more verbose string suitable
// for logging and human consumption.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureMessage *string `json:"failureMessage,omitempty"`
// Conditions defines current service state of the KKMachine.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=kkclusters,scope=Namespaced,categories=cluster-api,shortName=kkc
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this KKClusters belongs"
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="Cluster infrastructure is ready for SSH instances"
// +kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=".spec.controlPlaneEndpoint",description="API Endpoint",priority=1
// +k8s:defaulter-gen=true
// KKCluster is the Schema for the kkclusters API
type KKCluster struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec KKClusterSpec `json:"spec,omitempty"`
Status KKClusterStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// KKClusterList contains a list of KKCluster
type KKClusterList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KKCluster `json:"items"`
}
// GetConditions returns the observations of the operational state of the KKCluster resource.
func (k *KKCluster) GetConditions() clusterv1.Conditions {
return k.Status.Conditions
}
// SetConditions sets the underlying service state of the KKCluster to the predescribed clusterv1.Conditions.
func (k *KKCluster) SetConditions(conditions clusterv1.Conditions) {
k.Status.Conditions = conditions
}
func init() {
SchemeBuilder.Register(&KKCluster{}, &KKClusterList{})
}

View File

@ -1,247 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"fmt"
"net"
"strings"
"time"
mapset "github.com/deckarep/golang-set"
"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/storage/names"
"sigs.k8s.io/cluster-api/util/version"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
const (
defaultSSHUser = "root"
defaultSSHPort = 22
defaultSSHEstablishTimeout = 30 * time.Second
)
// log is for logging in this package.
var kkclusterlog = logf.Log.WithName("kkcluster-resource")
func (k *KKCluster) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(k).
Complete()
}
//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-kkcluster,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkclusters,verbs=create;update,versions=v1beta1,name=default.kkcluster.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &KKCluster{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (k *KKCluster) Default() {
kkclusterlog.Info("default", "name", k.Name)
defaultDistribution(&k.Spec)
defaultAuth(&k.Spec.Nodes.Auth)
defaultInstance(&k.Spec)
defaultInPlaceUpgradeAnnotation(k.GetAnnotations())
}
func defaultDistribution(spec *KKClusterSpec) {
if spec.Distribution == "" {
spec.Distribution = "kubernetes"
}
if spec.Distribution == "k8s" {
spec.Distribution = "kubernetes"
}
}
func defaultAuth(auth *Auth) {
if auth.User == "" {
auth.User = defaultSSHUser
}
if auth.Port == nil {
p := defaultSSHPort
auth.Port = &p
}
if auth.Timeout == nil {
t := defaultSSHEstablishTimeout
auth.Timeout = &t
}
}
func defaultInstance(spec *KKClusterSpec) {
for i := range spec.Nodes.Instances {
instance := &spec.Nodes.Instances[i]
if instance.Name == "" {
instance.Name = names.SimpleNameGenerator.GenerateName("kk-instance-")
}
if instance.InternalAddress == "" {
instance.InternalAddress = instance.Address
}
if instance.Arch == "" {
instance.Arch = "amd64"
}
if len(instance.Roles) == 0 {
instance.Roles = []Role{ControlPlane, Worker}
}
}
}
func defaultInPlaceUpgradeAnnotation(annotation map[string]string) {
upgradeVersion, ok := annotation[InPlaceUpgradeVersionAnnotation]
if !ok {
return
}
if !strings.HasPrefix(upgradeVersion, "v") {
annotation[InPlaceUpgradeVersionAnnotation] = "v" + upgradeVersion
}
}
//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-kkcluster,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkclusters,verbs=create;update,versions=v1beta1,name=validation.kkcluster.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Validator = &KKCluster{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (k *KKCluster) ValidateCreate() error {
kkclusterlog.Info("validate create", "name", k.Name)
var allErrs field.ErrorList
allErrs = append(allErrs, validateDistribution(k.Spec)...)
allErrs = append(allErrs, validateClusterNodes(k.Spec.Nodes)...)
allErrs = append(allErrs, validateLoadBalancer(k.Spec.ControlPlaneLoadBalancer)...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (k *KKCluster) ValidateUpdate(old runtime.Object) error {
kkclusterlog.Info("validate update", "name", k.Name)
var allErrs field.ErrorList
oldC, ok := old.(*KKCluster)
if !ok {
return apierrors.NewBadRequest(fmt.Sprintf("expected an KKCluster but got a %T", old))
}
newLoadBalancer := &KKLoadBalancerSpec{}
if k.Spec.ControlPlaneLoadBalancer != nil {
newLoadBalancer = k.Spec.ControlPlaneLoadBalancer.DeepCopy()
}
if oldC.Spec.ControlPlaneLoadBalancer != nil {
// If old scheme was not nil, the new scheme should be the same.
existingLoadBalancer := oldC.Spec.ControlPlaneLoadBalancer.DeepCopy()
if !cmp.Equal(newLoadBalancer, existingLoadBalancer) {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "controlPlaneLoadBalancer"),
k.Spec.ControlPlaneLoadBalancer, "field is immutable"),
)
}
}
allErrs = append(allErrs, validateClusterNodes(k.Spec.Nodes)...)
allErrs = append(allErrs, validateInPlaceUpgrade(k.GetAnnotations())...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (k *KKCluster) ValidateDelete() error {
return nil
}
func validateDistribution(spec KKClusterSpec) []*field.Error {
var errs field.ErrorList
path := field.NewPath("spec", "distribution")
switch spec.Distribution {
case K3S:
return errs
case KUBERNETES:
return errs
default:
errs = append(errs, field.NotSupported(path, spec.Distribution, []string{K3S, KUBERNETES}))
}
return errs
}
func validateLoadBalancer(loadBalancer *KKLoadBalancerSpec) []*field.Error {
var errs field.ErrorList
path := field.NewPath("spec", "controlPlaneLoadBalancer")
if loadBalancer.Host == "" {
errs = append(errs, field.Required(path.Child("host"), "can't be empty"))
}
return errs
}
func validateClusterNodes(nodes Nodes) []*field.Error {
var errs field.ErrorList
if nodes.Auth.Password == "" && nodes.Auth.PrivateKey == "" && nodes.Auth.PrivateKeyPath == "" && nodes.Auth.Secret == "" {
errs = append(errs, field.Required(field.NewPath("spec", "nodes", "auth"), "password and privateKey can't both be empty"))
}
nameSet := mapset.NewThreadUnsafeSet()
addrSet := mapset.NewThreadUnsafeSet()
internalAddrSet := mapset.NewThreadUnsafeSet()
for i := range nodes.Instances {
instance := nodes.Instances[i]
path := field.NewPath("spec", "nodes", fmt.Sprintf("instances[%d]", i))
if strings.ToLower(instance.Name) != instance.Name {
errs = append(errs,
field.Forbidden(path.Child("name"), "instance name must be the lower case"))
}
if !nameSet.Add(instance.Name) {
errs = append(errs, field.Duplicate(path.Child("name"), instance.Name))
}
if net.ParseIP(instance.Address) == nil {
errs = append(errs, field.Invalid(path.Child("address"), instance.Address, "instance address is invalid"))
}
if !addrSet.Add(instance.Address) {
errs = append(errs, field.Duplicate(path.Child("address"), instance.Address))
}
if net.ParseIP(instance.InternalAddress) == nil {
errs = append(errs, field.Invalid(path.Child("internalAddress"), instance.InternalAddress, "instance internalAddress is invalid"))
}
if !internalAddrSet.Add(instance.InternalAddress) {
errs = append(errs, field.Duplicate(path.Child("internalAddress"), instance.InternalAddress))
}
}
return errs
}
func validateInPlaceUpgrade(newAnnotation map[string]string) []*field.Error {
var allErrs field.ErrorList
if v, ok := newAnnotation[InPlaceUpgradeVersionAnnotation]; ok {
_, err := version.ParseMajorMinorPatch(v)
if err != nil {
allErrs = append(allErrs,
field.InternalError(
field.NewPath("metadata", "annotations"),
errors.Wrapf(err, "failed to parse in-place upgrade version: %s", v)),
)
}
}
return allErrs
}

View File

@ -1,63 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)
// KKClusterTemplateSpec defines the desired state of KKClusterTemplate
type KKClusterTemplateSpec struct {
Template KKClusterTemplateResource `json:"template"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=kkclustertemplates,scope=Namespaced,categories=cluster-api,shortName=kkct
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of KKClusterTemplate"
// +k8s:defaulter-gen=true
// KKClusterTemplate is the Schema for the kkclustertemplates API
type KKClusterTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec KKClusterTemplateSpec `json:"spec,omitempty"`
}
//+kubebuilder:object:root=true
// KKClusterTemplateList contains a list of KKClusterTemplate
type KKClusterTemplateList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KKClusterTemplate `json:"items"`
}
func init() {
SchemeBuilder.Register(&KKClusterTemplate{}, &KKClusterTemplateList{})
}
// KKClusterTemplateResource Standard object's metadata
type KKClusterTemplateResource struct {
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"`
Spec KKClusterSpec `json:"spec"`
}

View File

@ -1,82 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"github.com/google/go-cmp/cmp"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var kkclustertemplatelog = logf.Log.WithName("kkclustertemplate-resource")
// SetupWebhookWithManager sets up and registers the webhook with the manager.
func (r *KKClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-kkclustertemplate,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkclustertemplates,verbs=create;update,versions=v1beta1,name=default.kkclustertemplate.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &KKClusterTemplate{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *KKClusterTemplate) Default() {
kkclustertemplatelog.Info("default", "name", r.Name)
defaultDistribution(&r.Spec.Template.Spec)
defaultAuth(&r.Spec.Template.Spec.Nodes.Auth)
defaultInstance(&r.Spec.Template.Spec)
}
//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-kkclustertemplate,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkclustertemplates,verbs=create;update,versions=v1beta1,name=validation.kkclustertemplate.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Validator = &KKClusterTemplate{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *KKClusterTemplate) ValidateCreate() error {
kkclustertemplatelog.Info("validate create", "name", r.Name)
var allErrs field.ErrorList
allErrs = append(allErrs, validateDistribution(r.Spec.Template.Spec)...)
allErrs = append(allErrs, validateClusterNodes(r.Spec.Template.Spec.Nodes)...)
allErrs = append(allErrs, validateLoadBalancer(r.Spec.Template.Spec.ControlPlaneLoadBalancer)...)
return aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *KKClusterTemplate) ValidateUpdate(old runtime.Object) error {
kkclustertemplatelog.Info("validate update", "name", r.Name)
oldC := old.(*KKClusterTemplate)
if !cmp.Equal(r.Spec, oldC.Spec) {
return apierrors.NewBadRequest("KKClusterTemplate.Spec is immutable")
}
return nil
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *KKClusterTemplate) ValidateDelete() error {
return nil
}

View File

@ -1,206 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
)
const (
// InstanceFinalizer allows ReconcileKKInstance to clean up KubeKey resources associated with KKInstance before
// removing it from the apiserver.
InstanceFinalizer = "kkinstance.infrastructure.cluster.x-k8s.io"
)
// InstanceState describes the state of an KK instance.
type InstanceState string
var (
// InstanceStatePending is the string representing an instance in a pending state.
InstanceStatePending = InstanceState("pending")
// InstanceStateBootstrapping is the string representing an instance in a bootstrapping state.
InstanceStateBootstrapping = InstanceState("bootstrapping")
// InstanceStateBootstrapped = InstanceState("bootstrapped")
// InstanceStateRunning is the string representing an instance in a running state.
InstanceStateRunning = InstanceState("running")
// InstanceStateInPlaceUpgrading is the string representing an instance in an in-place-upgrading state.
InstanceStateInPlaceUpgrading = InstanceState("InPlaceUpgrading")
// InstanceStateCleaning is the string representing an instance in a cleaning state.
InstanceStateCleaning = InstanceState("cleaning")
// InstanceStateCleaned is the string representing an instance in a cleared state.
InstanceStateCleaned = InstanceState("cleaned")
// InstanceRunningStates defines the set of states in which an SSH instance is
// running or going to be running soon.
InstanceRunningStates = sets.NewString(
string(InstanceStatePending),
string(InstanceStateRunning),
)
// InstanceKnownStates represents all known KKInstance states.
InstanceKnownStates = InstanceRunningStates.Union(
sets.NewString(
string(InstanceStateBootstrapping),
string(InstanceStateCleaning),
string(InstanceStateCleaned),
string(InstanceStateInPlaceUpgrading),
),
)
)
// KKInstanceSpec defines the desired state of KKInstance
type KKInstanceSpec struct {
// Name is the host name of the machine.
// +kubebuilder:validation:MinLength=1
Name string `json:"name,omitempty"`
// Address is the IP address of the machine.
Address string `json:"address,omitempty"`
// InternalAddress is the internal IP address of the machine.
InternalAddress string `json:"internalAddress,omitempty"`
// Roles is the role of the machine.
// +optional
Roles []Role `json:"roles,omitempty"`
// Arch is the architecture of the machine. e.g. "amd64", "arm64".
// +optional
Arch string `json:"arch,omitempty"`
// Auth is the SSH authentication information of this machine. It will override the global auth configuration.
// +optional
Auth Auth `json:"auth,omitempty"`
// ContainerManager is the container manager config of this machine.
// +optional
ContainerManager ContainerManager `json:"containerManager,omitempty"`
// Repository is the repository config of this machine.
// +optional
Repository *Repository `json:"repository,omitempty"`
}
// KKInstanceStatus defines the observed state of KKInstance
type KKInstanceStatus struct {
// The current state of the instance.
State InstanceState `json:"instanceState,omitempty"`
// NodeRef will point to the corresponding Node if it exists.
// +optional
NodeRef *corev1.ObjectReference `json:"nodeRef,omitempty"`
// NodeInfo is a set of ids/uuids to uniquely identify the node.
// More info: https://kubernetes.io/docs/concepts/nodes/node/#info
// +optional
NodeInfo *corev1.NodeSystemInfo `json:"nodeInfo,omitempty"`
// FailureReason will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a succinct value suitable
// for machine interpretation.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
// FailureMessage will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a more verbose string suitable
// for logging and human consumption.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureMessage *string `json:"failureMessage,omitempty"`
// Conditions defines current service state of the KKMachine.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=kkinstances,scope=Namespaced,categories=cluster-api,shortName=kki
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Hostname",type="string",JSONPath=".spec.name",description="kubekey instance hostname"
// +kubebuilder:printcolumn:name="Address",type="string",JSONPath=".spec.address",description="kubekey instance address"
// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.instanceState",description="KKInstance state"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of KKInstance"
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.nodeInfo.kubeletVersion",description="Kubernetes version associated with this KKInstance"
// +k8s:defaulter-gen=true
// KKInstance is the Schema for the kkinstances API
type KKInstance struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec KKInstanceSpec `json:"spec,omitempty"`
Status KKInstanceStatus `json:"status,omitempty"`
}
// GetConditions returns the observations of the operational state of the KKMachine resource.
func (k *KKInstance) GetConditions() clusterv1.Conditions {
return k.Status.Conditions
}
// SetConditions sets the underlying service state of the KKInstance to the predescribed clusterv1.Conditions.
func (k *KKInstance) SetConditions(conditions clusterv1.Conditions) {
k.Status.Conditions = conditions
}
//+kubebuilder:object:root=true
// KKInstanceList contains a list of KKInstance
type KKInstanceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KKInstance `json:"items"`
}
func init() {
SchemeBuilder.Register(&KKInstance{}, &KKInstanceList{})
}

View File

@ -1,112 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/cluster-api/util/version"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var kkinstancelog = logf.Log.WithName("kkinstance-resource")
func (k *KKInstance) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(k).
Complete()
}
//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-kkinstance,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkinstances,verbs=create;update,versions=v1beta1,name=default.kkinstance.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &KKInstance{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (k *KKInstance) Default() {
kkinstancelog.Info("default", "name", k.Name)
}
//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-kkinstance,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkinstances,verbs=create;update,versions=v1beta1,name=validation.kkinstance.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Validator = &KKInstance{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (k *KKInstance) ValidateCreate() error {
kkinstancelog.Info("validate create", "name", k.Name)
return nil
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (k *KKInstance) ValidateUpdate(old runtime.Object) error {
kkinstancelog.Info("validate update", "name", k.Name)
var allErrs field.ErrorList
if v, ok := k.GetAnnotations()[InPlaceUpgradeVersionAnnotation]; ok {
if k.Status.NodeInfo == nil {
allErrs = append(allErrs,
field.Invalid(
field.NewPath("status", "nodeInfo"),
k.Status.NodeInfo,
"nodeInfo is required for in-place upgrade"))
}
newSemverVersion, err := version.ParseMajorMinorPatch(v)
if err != nil {
allErrs = append(allErrs,
field.InternalError(
field.NewPath("metadata", "annotations"),
errors.Wrapf(err, "failed to parse in-place upgrade version: %s", v)),
)
}
oldSemverVersion, err := version.ParseMajorMinorPatch(k.Status.NodeInfo.KubeletVersion)
if err != nil {
allErrs = append(allErrs,
field.InternalError(
field.NewPath("status", "nodeInfo", "kubeletVersion"),
errors.Wrapf(err, "failed to parse old version: %s", k.Status.NodeInfo.KubeletVersion)),
)
}
if newSemverVersion.Equals(oldSemverVersion) {
allErrs = append(allErrs,
field.Invalid(
field.NewPath("metadata", "annotations"),
v,
"new version must be different from old version"),
)
}
if !(newSemverVersion.GT(oldSemverVersion) &&
newSemverVersion.Major == oldSemverVersion.Major &&
(newSemverVersion.Minor == oldSemverVersion.Minor+1 || newSemverVersion.Minor == oldSemverVersion.Minor)) {
allErrs = append(allErrs,
field.Invalid(field.NewPath("metadata", "annotations"),
v, "Skipping MINOR versions when upgrading is unsupported."))
}
}
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (k *KKInstance) ValidateDelete() error {
kkinstancelog.Info("validate delete", "name", k.Name)
return nil
}

View File

@ -1,148 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
)
const (
// MachineFinalizer allows ReconcileKKMachine to clean up KubeKey resources associated with KKMachine before
// removing it from the apiserver.
MachineFinalizer = "kkmachine.infrastructure.cluster.x-k8s.io"
)
// KKMachineSpec defines the desired state of KKMachine
type KKMachineSpec struct {
// ProviderID is the unique identifier as specified by the kubekey provider.
ProviderID *string `json:"providerID,omitempty"`
// InstanceID is the name of the KKInstance.
InstanceID *string `json:"instanceID,omitempty"`
// Roles is the role of the machine.
// +optional
Roles []Role `json:"roles"`
// ContainerManager is the container manager config of this machine.
// +optional
ContainerManager ContainerManager `json:"containerManager"`
// Repository is the repository config of this machine.
// +optional
Repository *Repository `json:"repository,omitempty"`
}
// KKMachineStatus defines the observed state of KKMachine
type KKMachineStatus struct {
// Ready is true when the provider resource is ready.
// +optional
Ready bool `json:"ready"`
// Addresses contains the KK instance associated addresses.
Addresses []clusterv1.MachineAddress `json:"addresses,omitempty"`
// InstanceState is the state of the KK instance for this machine.
// +optional
InstanceState *InstanceState `json:"instanceState,omitempty"`
// FailureReason will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a succinct value suitable
// for machine interpretation.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
// FailureMessage will be set in the event that there is a terminal problem
// reconciling the Machine and will contain a more verbose string suitable
// for logging and human consumption.
//
// This field should not be set for transitive errors that a controller
// faces that are expected to be fixed automatically over
// time (like service outages), but instead indicate that something is
// fundamentally wrong with the Machine's spec or the configuration of
// the controller, and that manual intervention is required. Examples
// of terminal errors would be invalid combinations of settings in the
// spec, values that are unsupported by the controller, or the
// responsible controller itself being critically misconfigured.
//
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
// +optional
FailureMessage *string `json:"failureMessage,omitempty"`
// Conditions defines current service state of the KKMachine.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=kkmachines,scope=Namespaced,categories=cluster-api,shortName=kkm
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels.cluster\\.x-k8s\\.io/cluster-name",description="Cluster to which this KKMachine belongs"
// +kubebuilder:printcolumn:name="Instance",type="string",JSONPath=".spec.instanceID",description="KKInstance name"
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="Machine ready status"
// +kubebuilder:printcolumn:name="Machine",type="string",JSONPath=".metadata.ownerReferences[?(@.kind==\"Machine\")].name",description="Machine object which owns with this KKMachine"
// +k8s:defaulter-gen=true
// KKMachine is the Schema for the kkmachines API
type KKMachine struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec KKMachineSpec `json:"spec,omitempty"`
Status KKMachineStatus `json:"status,omitempty"`
}
// GetConditions returns the observations of the operational state of the KKMachine resource.
func (k *KKMachine) GetConditions() clusterv1.Conditions {
return k.Status.Conditions
}
// SetConditions sets the underlying service state of the KKMachine to the predescribed clusterv1.Conditions.
func (k *KKMachine) SetConditions(conditions clusterv1.Conditions) {
k.Status.Conditions = conditions
}
//+kubebuilder:object:root=true
// KKMachineList contains a list of KKMachine
type KKMachineList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KKMachine `json:"items"`
}
func init() {
SchemeBuilder.Register(&KKMachine{}, &KKMachineList{})
}

View File

@ -1,119 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var kkmachinelog = logf.Log.WithName("kkmachine-resource")
func (k *KKMachine) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(k).
Complete()
}
//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-kkmachine,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkmachines,verbs=create;update,versions=v1beta1,name=default.kkmachine.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &KKMachine{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (k *KKMachine) Default() {
kkmachinelog.Info("default", "name", k.Name)
defaultContainerManager(&k.Spec)
}
func defaultContainerManager(spec *KKMachineSpec) {
// Direct connection to the user-provided CRI socket
if spec.ContainerManager.CRISocket != "" {
return
}
if spec.ContainerManager.Type == "" {
spec.ContainerManager.Type = ContainerdType
}
switch spec.ContainerManager.Type {
case ContainerdType:
if spec.ContainerManager.Version == "" {
spec.ContainerManager.Version = DefaultContainerdVersion
}
spec.ContainerManager.CRISocket = DefaultContainerdCRISocket
case DockerType:
if spec.ContainerManager.Version == "" {
spec.ContainerManager.Version = DefaultDockerVersion
}
if spec.ContainerManager.CRIDockerdVersion == "" {
spec.ContainerManager.CRIDockerdVersion = DefaultCRIDockerdVersion
}
spec.ContainerManager.CRISocket = DefaultDockerCRISocket
}
if spec.ContainerManager.CRICTLVersion == "" {
spec.ContainerManager.CRICTLVersion = DefaultCrictlVersion
}
spec.ContainerManager.Version = strings.TrimPrefix(spec.ContainerManager.Version, "v")
if !strings.HasPrefix(spec.ContainerManager.CRICTLVersion, "v") {
spec.ContainerManager.CRICTLVersion = "v" + spec.ContainerManager.CRICTLVersion
}
}
//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-kkmachine,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkmachines,verbs=create;update,versions=v1beta1,name=validation.kkmachine.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Validator = &KKMachine{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachine) ValidateCreate() error {
kkmachinelog.Info("validate create", "name", k.Name)
var allErrs field.ErrorList
allErrs = append(allErrs, validateRepository(k.Spec.Repository)...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachine) ValidateUpdate(old runtime.Object) error {
kkmachinelog.Info("validate update", "name", k.Name)
var allErrs field.ErrorList
allErrs = append(allErrs, validateRepository(k.Spec.Repository)...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachine) ValidateDelete() error {
kkmachinelog.Info("validate delete", "name", k.Name)
return nil
}
func validateRepository(repo *Repository) field.ErrorList { //nolint:unparam
var allErrs field.ErrorList
if repo == nil {
return allErrs
}
return allErrs
}

View File

@ -1,61 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"testing"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utildefaulting "sigs.k8s.io/cluster-api/util/defaulting"
)
func TestKKMachine_Default(t *testing.T) {
g := NewWithT(t)
kkm := &KKMachine{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foobar",
},
}
t.Run("for KKMachine", utildefaulting.DefaultValidateTest(kkm))
kkm.Default()
g.Expect(kkm.Spec.ContainerManager.Type).To(Equal(ContainerdType))
g.Expect(kkm.Spec.ContainerManager.Version).To(Equal(DefaultContainerdVersion))
g.Expect(kkm.Spec.ContainerManager.CRICTLVersion).To(Equal(DefaultCrictlVersion))
kkm2 := &KKMachine{
ObjectMeta: metav1.ObjectMeta{
Namespace: "foobar",
},
Spec: KKMachineSpec{
ContainerManager: ContainerManager{
Type: ContainerdType,
Version: "v1.6.4",
CRICTLVersion: "1.24.0",
},
},
}
t.Run("for KKMachine2", utildefaulting.DefaultValidateTest(kkm2))
kkm2.Default()
g.Expect(kkm2.Spec.ContainerManager.Type).To(Equal(ContainerdType))
g.Expect(kkm2.Spec.ContainerManager.Version).To(Equal("1.6.4"))
g.Expect(kkm2.Spec.ContainerManager.CRICTLVersion).To(Equal("v1.24.0"))
}

View File

@ -1,76 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)
// KKMachineTemplateStatus defines a status for an KKMachineTemplate.
type KKMachineTemplateStatus struct {
// Capacity defines the resource capacity for this machine.
// This value is used for autoscaling from zero operations as defined in:
// https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md
// +optional
Capacity corev1.ResourceList `json:"capacity,omitempty"`
}
// KKMachineTemplateSpec defines the desired state of KKMachineTemplate
type KKMachineTemplateSpec struct {
Template KKMachineTemplateResource `json:"template"`
}
// KKMachineTemplateResource describes the data needed to create am KKMachine from a template.
type KKMachineTemplateResource struct {
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"`
// Spec is the specification of the desired behavior of the machine.
Spec KKMachineSpec `json:"spec"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=kkmachinetemplates,scope=Namespaced,categories=cluster-api,shortName=kkmt
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of KKMachineTemplate"
// +k8s:defaulter-gen=true
// KKMachineTemplate is the Schema for the kkmachinetemplates API
type KKMachineTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec KKMachineTemplateSpec `json:"spec,omitempty"`
Status KKMachineTemplateStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// KKMachineTemplateList contains a list of KKMachineTemplate
type KKMachineTemplateList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []KKMachineTemplate `json:"items"`
}
func init() {
SchemeBuilder.Register(&KKMachineTemplate{}, &KKMachineTemplateList{})
}

View File

@ -1,76 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var kkmachinetemplatelog = logf.Log.WithName("kkmachinetemplate-resource")
func (k *KKMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(k).
Complete()
}
//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-kkmachinetemplate,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkmachinetemplates,verbs=create;update,versions=v1beta1,name=default.kkmachinetemplate.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Defaulter = &KKMachineTemplate{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (k *KKMachineTemplate) Default() {
kkmachinetemplatelog.Info("default", "name", k.Name)
defaultContainerManager(&k.Spec.Template.Spec)
}
//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-kkmachinetemplate,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=kkmachinetemplates,verbs=create;update,versions=v1beta1,name=validation.kkmachinetemplate.infrastructure.cluster.x-k8s.io,admissionReviewVersions=v1
var _ webhook.Validator = &KKMachineTemplate{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachineTemplate) ValidateCreate() error {
kkmachinetemplatelog.Info("validate create", "name", k.Name)
spec := k.Spec.Template.Spec
var allErrs field.ErrorList
allErrs = append(allErrs, validateRepository(spec.Repository)...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachineTemplate) ValidateUpdate(old runtime.Object) error {
kkmachinetemplatelog.Info("validate update", "name", k.Name)
spec := k.Spec.Template.Spec
var allErrs field.ErrorList
allErrs = append(allErrs, validateRepository(spec.Repository)...)
return aggregateObjErrors(k.GroupVersionKind().GroupKind(), k.Name, allErrs)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (k *KKMachineTemplate) ValidateDelete() error {
kkmachinetemplatelog.Info("validate delete", "name", k.Name)
return nil
}

View File

@ -1,68 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Registry is the configuration for a cluster registry
type Registry struct {
metav1.TypeMeta `json:",inline"`
// PrivateRegistry defines the private registry address of ContainerManager.
PrivateRegistry string `json:"privateRegistry"`
// InsecureRegistries defines the insecure registries of ContainerManager.
InsecureRegistries []string `json:"insecureRegistries,omitempty"`
// RegistryMirrors defines the registry mirrors of this PrivateRegistry.
RegistryMirrors []string `json:"registryMirrors,omitempty"`
// NamespaceOverride defines the namespace override of this PrivateRegistry.
NamespaceOverride string `json:"namespaceOverride"`
// Auth defines the auth of this PrivateRegistry.
Auth RegistryAuth `json:"auth"`
}
// RegistryAuth defines the auth of a registry
type RegistryAuth struct {
// Username defines the username of this PrivateRegistry.
Username string `json:"username"`
// Password defines the password of this PrivateRegistry.
Password string `json:"password"`
// InsecureSkipVerify allow contacting this PrivateRegistry over HTTPS with failed TLS verification.
InsecureSkipVerify bool `json:"insecureSkipVerify"`
// PlainHTTP allow contacting this PrivateRegistry over HTTP.
PlainHTTP bool `json:"plainHTTP"`
// CertsPath defines the path of the certs files of this PrivateRegistry.
CertsPath string `json:"certsPath"`
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
CAFile string `yaml:"caFile" json:"caFile,omitempty"`
// CertFile is an SSL certification file used to secure etcd communication.
CertFile string `yaml:"certFile" json:"certFile,omitempty"`
// KeyFile is an SSL key file used to secure etcd communication.
KeyFile string `yaml:"keyFile" json:"keyFile,omitempty"`
}

View File

@ -1,42 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
// ISO type
const (
NONE = "none"
AUTO = "auto"
)
// Repository defines the repository of the instance.
type Repository struct {
// ISO specifies the ISO file name. There are 3 options:
// "": empty string means will not install the packages.
// "none": no ISO file will be used. And capkk will use the default repository to install the required packages.
// "auto": capkk will detect the ISO file automatically. Only support Ubuntu/Debian/CentOS.
// "xxx-20.04-debs-amd64.iso": use the specified name to get the ISO file name.
// +optional
ISO string `json:"iso,omitempty"`
// Update will update the repository packages list and cache if it is true.
// +optional
Update bool `json:"update,omitempty"`
// Packages is a list of packages to be installed.
// +optional
Packages []string `json:"packages,omitempty"`
}

View File

@ -1,27 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
// Role represents a role of a node.
type Role string
// Internal roles.
const (
ControlPlane Role = "control-plane"
Master Role = "master"
Worker Role = "worker"
)

View File

@ -1,35 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
)
func aggregateObjErrors(gk schema.GroupKind, name string, allErrs field.ErrorList) error {
if len(allErrs) == 0 {
return nil
}
return apierrors.NewInvalid(
gk,
name,
allErrs,
)
}

View File

@ -1,839 +0,0 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1beta1
import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
apiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
timex "time"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Auth) DeepCopyInto(out *Auth) {
*out = *in
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(int)
**out = **in
}
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(timex.Duration)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Auth.
func (in *Auth) DeepCopy() *Auth {
if in == nil {
return nil
}
out := new(Auth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Checksum) DeepCopyInto(out *Checksum) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Checksum.
func (in *Checksum) DeepCopy() *Checksum {
if in == nil {
return nil
}
out := new(Checksum)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Component) DeepCopyInto(out *Component) {
*out = *in
if in.Overrides != nil {
in, out := &in.Overrides, &out.Overrides
*out = make([]Override, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Component.
func (in *Component) DeepCopy() *Component {
if in == nil {
return nil
}
out := new(Component)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerManager) DeepCopyInto(out *ContainerManager) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerManager.
func (in *ContainerManager) DeepCopy() *ContainerManager {
if in == nil {
return nil
}
out := new(ContainerManager)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InstanceInfo) DeepCopyInto(out *InstanceInfo) {
*out = *in
if in.Roles != nil {
in, out := &in.Roles, &out.Roles
*out = make([]Role, len(*in))
copy(*out, *in)
}
in.Auth.DeepCopyInto(&out.Auth)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstanceInfo.
func (in *InstanceInfo) DeepCopy() *InstanceInfo {
if in == nil {
return nil
}
out := new(InstanceInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKCluster) DeepCopyInto(out *KKCluster) {
*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 KKCluster.
func (in *KKCluster) DeepCopy() *KKCluster {
if in == nil {
return nil
}
out := new(KKCluster)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKCluster) 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 *KKClusterList) DeepCopyInto(out *KKClusterList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KKCluster, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterList.
func (in *KKClusterList) DeepCopy() *KKClusterList {
if in == nil {
return nil
}
out := new(KKClusterList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKClusterList) 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 *KKClusterSpec) DeepCopyInto(out *KKClusterSpec) {
*out = *in
in.Nodes.DeepCopyInto(&out.Nodes)
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
if in.ControlPlaneLoadBalancer != nil {
in, out := &in.ControlPlaneLoadBalancer, &out.ControlPlaneLoadBalancer
*out = new(KKLoadBalancerSpec)
**out = **in
}
if in.Component != nil {
in, out := &in.Component, &out.Component
*out = new(Component)
(*in).DeepCopyInto(*out)
}
in.Registry.DeepCopyInto(&out.Registry)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterSpec.
func (in *KKClusterSpec) DeepCopy() *KKClusterSpec {
if in == nil {
return nil
}
out := new(KKClusterSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKClusterStatus) DeepCopyInto(out *KKClusterStatus) {
*out = *in
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
**out = **in
}
if in.FailureMessage != nil {
in, out := &in.FailureMessage, &out.FailureMessage
*out = new(string)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(apiv1beta1.Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterStatus.
func (in *KKClusterStatus) DeepCopy() *KKClusterStatus {
if in == nil {
return nil
}
out := new(KKClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKClusterTemplate) DeepCopyInto(out *KKClusterTemplate) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterTemplate.
func (in *KKClusterTemplate) DeepCopy() *KKClusterTemplate {
if in == nil {
return nil
}
out := new(KKClusterTemplate)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKClusterTemplate) 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 *KKClusterTemplateList) DeepCopyInto(out *KKClusterTemplateList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KKClusterTemplate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterTemplateList.
func (in *KKClusterTemplateList) DeepCopy() *KKClusterTemplateList {
if in == nil {
return nil
}
out := new(KKClusterTemplateList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKClusterTemplateList) 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 *KKClusterTemplateResource) DeepCopyInto(out *KKClusterTemplateResource) {
*out = *in
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterTemplateResource.
func (in *KKClusterTemplateResource) DeepCopy() *KKClusterTemplateResource {
if in == nil {
return nil
}
out := new(KKClusterTemplateResource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKClusterTemplateSpec) DeepCopyInto(out *KKClusterTemplateSpec) {
*out = *in
in.Template.DeepCopyInto(&out.Template)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKClusterTemplateSpec.
func (in *KKClusterTemplateSpec) DeepCopy() *KKClusterTemplateSpec {
if in == nil {
return nil
}
out := new(KKClusterTemplateSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKInstance) DeepCopyInto(out *KKInstance) {
*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 KKInstance.
func (in *KKInstance) DeepCopy() *KKInstance {
if in == nil {
return nil
}
out := new(KKInstance)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKInstance) 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 *KKInstanceList) DeepCopyInto(out *KKInstanceList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KKInstance, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKInstanceList.
func (in *KKInstanceList) DeepCopy() *KKInstanceList {
if in == nil {
return nil
}
out := new(KKInstanceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKInstanceList) 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 *KKInstanceSpec) DeepCopyInto(out *KKInstanceSpec) {
*out = *in
if in.Roles != nil {
in, out := &in.Roles, &out.Roles
*out = make([]Role, len(*in))
copy(*out, *in)
}
in.Auth.DeepCopyInto(&out.Auth)
out.ContainerManager = in.ContainerManager
if in.Repository != nil {
in, out := &in.Repository, &out.Repository
*out = new(Repository)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKInstanceSpec.
func (in *KKInstanceSpec) DeepCopy() *KKInstanceSpec {
if in == nil {
return nil
}
out := new(KKInstanceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKInstanceStatus) DeepCopyInto(out *KKInstanceStatus) {
*out = *in
if in.NodeRef != nil {
in, out := &in.NodeRef, &out.NodeRef
*out = new(v1.ObjectReference)
**out = **in
}
if in.NodeInfo != nil {
in, out := &in.NodeInfo, &out.NodeInfo
*out = new(v1.NodeSystemInfo)
**out = **in
}
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
**out = **in
}
if in.FailureMessage != nil {
in, out := &in.FailureMessage, &out.FailureMessage
*out = new(string)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(apiv1beta1.Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKInstanceStatus.
func (in *KKInstanceStatus) DeepCopy() *KKInstanceStatus {
if in == nil {
return nil
}
out := new(KKInstanceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKLoadBalancerSpec) DeepCopyInto(out *KKLoadBalancerSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKLoadBalancerSpec.
func (in *KKLoadBalancerSpec) DeepCopy() *KKLoadBalancerSpec {
if in == nil {
return nil
}
out := new(KKLoadBalancerSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKMachine) DeepCopyInto(out *KKMachine) {
*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 KKMachine.
func (in *KKMachine) DeepCopy() *KKMachine {
if in == nil {
return nil
}
out := new(KKMachine)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKMachine) 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 *KKMachineList) DeepCopyInto(out *KKMachineList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KKMachine, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineList.
func (in *KKMachineList) DeepCopy() *KKMachineList {
if in == nil {
return nil
}
out := new(KKMachineList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKMachineList) 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 *KKMachineSpec) DeepCopyInto(out *KKMachineSpec) {
*out = *in
if in.ProviderID != nil {
in, out := &in.ProviderID, &out.ProviderID
*out = new(string)
**out = **in
}
if in.InstanceID != nil {
in, out := &in.InstanceID, &out.InstanceID
*out = new(string)
**out = **in
}
if in.Roles != nil {
in, out := &in.Roles, &out.Roles
*out = make([]Role, len(*in))
copy(*out, *in)
}
out.ContainerManager = in.ContainerManager
if in.Repository != nil {
in, out := &in.Repository, &out.Repository
*out = new(Repository)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineSpec.
func (in *KKMachineSpec) DeepCopy() *KKMachineSpec {
if in == nil {
return nil
}
out := new(KKMachineSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKMachineStatus) DeepCopyInto(out *KKMachineStatus) {
*out = *in
if in.Addresses != nil {
in, out := &in.Addresses, &out.Addresses
*out = make([]apiv1beta1.MachineAddress, len(*in))
copy(*out, *in)
}
if in.InstanceState != nil {
in, out := &in.InstanceState, &out.InstanceState
*out = new(InstanceState)
**out = **in
}
if in.FailureReason != nil {
in, out := &in.FailureReason, &out.FailureReason
*out = new(errors.MachineStatusError)
**out = **in
}
if in.FailureMessage != nil {
in, out := &in.FailureMessage, &out.FailureMessage
*out = new(string)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(apiv1beta1.Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineStatus.
func (in *KKMachineStatus) DeepCopy() *KKMachineStatus {
if in == nil {
return nil
}
out := new(KKMachineStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKMachineTemplate) DeepCopyInto(out *KKMachineTemplate) {
*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 KKMachineTemplate.
func (in *KKMachineTemplate) DeepCopy() *KKMachineTemplate {
if in == nil {
return nil
}
out := new(KKMachineTemplate)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKMachineTemplate) 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 *KKMachineTemplateList) DeepCopyInto(out *KKMachineTemplateList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KKMachineTemplate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineTemplateList.
func (in *KKMachineTemplateList) DeepCopy() *KKMachineTemplateList {
if in == nil {
return nil
}
out := new(KKMachineTemplateList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KKMachineTemplateList) 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 *KKMachineTemplateResource) DeepCopyInto(out *KKMachineTemplateResource) {
*out = *in
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineTemplateResource.
func (in *KKMachineTemplateResource) DeepCopy() *KKMachineTemplateResource {
if in == nil {
return nil
}
out := new(KKMachineTemplateResource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKMachineTemplateSpec) DeepCopyInto(out *KKMachineTemplateSpec) {
*out = *in
in.Template.DeepCopyInto(&out.Template)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineTemplateSpec.
func (in *KKMachineTemplateSpec) DeepCopy() *KKMachineTemplateSpec {
if in == nil {
return nil
}
out := new(KKMachineTemplateSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KKMachineTemplateStatus) DeepCopyInto(out *KKMachineTemplateStatus) {
*out = *in
if in.Capacity != nil {
in, out := &in.Capacity, &out.Capacity
*out = make(v1.ResourceList, len(*in))
for key, val := range *in {
(*out)[key] = val.DeepCopy()
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KKMachineTemplateStatus.
func (in *KKMachineTemplateStatus) DeepCopy() *KKMachineTemplateStatus {
if in == nil {
return nil
}
out := new(KKMachineTemplateStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Nodes) DeepCopyInto(out *Nodes) {
*out = *in
in.Auth.DeepCopyInto(&out.Auth)
if in.Instances != nil {
in, out := &in.Instances, &out.Instances
*out = make([]InstanceInfo, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nodes.
func (in *Nodes) DeepCopy() *Nodes {
if in == nil {
return nil
}
out := new(Nodes)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Override) DeepCopyInto(out *Override) {
*out = *in
out.Checksum = in.Checksum
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Override.
func (in *Override) DeepCopy() *Override {
if in == nil {
return nil
}
out := new(Override)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Registry) DeepCopyInto(out *Registry) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.InsecureRegistries != nil {
in, out := &in.InsecureRegistries, &out.InsecureRegistries
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.RegistryMirrors != nil {
in, out := &in.RegistryMirrors, &out.RegistryMirrors
*out = make([]string, len(*in))
copy(*out, *in)
}
out.Auth = in.Auth
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Registry.
func (in *Registry) DeepCopy() *Registry {
if in == nil {
return nil
}
out := new(Registry)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Registry) 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 *RegistryAuth) DeepCopyInto(out *RegistryAuth) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryAuth.
func (in *RegistryAuth) DeepCopy() *RegistryAuth {
if in == nil {
return nil
}
out := new(RegistryAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Repository) DeepCopyInto(out *Repository) {
*out = *in
if in.Packages != nil {
in, out := &in.Packages, &out.Packages
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repository.
func (in *Repository) DeepCopy() *Repository {
if in == nil {
return nil
}
out := new(Repository)
in.DeepCopyInto(out)
return out
}

View File

@ -1,35 +0,0 @@
domain: cluster.x-k8s.io
layout:
- go.kubebuilder.io/v3
plugins:
manifests.sdk.operatorframework.io/v2: {}
scorecard.sdk.operatorframework.io/v2: {}
projectName: cluster-api-bootstrap-provider-kubekey-k3s
repo: github.com/kubesphere/kubekey/bootstrap/k3s
resources:
- api:
crdVersion: v1
namespaced: true
controller: true
domain: cluster.x-k8s.io
group: bootstrap
kind: K3sConfig
path: github.com/kubesphere/kubekey/bootstrap/k3s/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
domain: cluster.x-k8s.io
group: bootstrap
kind: K3sConfigTemplate
path: github.com/kubesphere/kubekey/bootstrap/k3s/api/v1beta1
version: v1beta1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"

View File

@ -1,36 +0,0 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1beta1 contains API Schema definitions for the bootstrap v1beta1 API group
// +kubebuilder:object:generate=true
// +groupName=bootstrap.cluster.x-k8s.io
package v1beta1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "bootstrap.cluster.x-k8s.io", Version: "v1beta1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@ -1,212 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
// ServerConfiguration defines the desired state of k3s server configuration.
type ServerConfiguration struct {
// Database is the database configuration.
Database Database `json:"database,omitempty"`
// Listener is the listener configuration.
Listener Listener `json:"listener,omitempty"`
// Networking is the networking configuration.
Networking Networking `json:"networking,omitempty"`
// KubernetesComponents is the kubernetes components configuration.
KubernetesComponents KubernetesComponents `json:"kubernetesComponents,omitempty"`
// KubernetesProcesses is the kubernetes processes configuration.
KubernetesProcesses KubernetesProcesses `json:"kubernetesProcesses,omitempty"`
// Agent is the agent configuration.
Agent AgentConfiguration `json:"agent,omitempty"`
}
// AgentConfiguration defines the desired state of k3s agent configuration.
type AgentConfiguration struct {
// Node defines the k3s agent node configuration.
Node AgentNode `json:"node,omitempty"`
// Runtime defines the k3s agent runtime configuration.
Runtime AgentRuntime `json:"runtime,omitempty"`
// Networking defines the k3s agent networking configuration.
Networking AgentNetworking `json:"networking,omitempty"`
// KubernetesAgentProcesses defines the k3s agent kubernetes processes configuration.
KubernetesAgentProcesses KubernetesAgentProcesses `json:"kubernetesAgentProcesses,omitempty"`
}
// Database defines the desired state of k3s database configuration.
type Database struct {
// DataStoreEndPoint specify etcd, Mysql, Postgres, or Sqlite (default) data source name.
DataStoreEndPoint string `json:"dataStoreEndPoint,omitempty"`
// DataStoreCAFile TLS Certificate Authority file used to secure datastore backend communication.
DataStoreCAFile string `json:"dataStoreCAFile,omitempty"`
// DataStoreCertFile TLS certification file used to secure datastore backend communication.
DataStoreCertFile string `json:"dataStoreCertFile,omitempty"`
// DataStoreKeyFile TLS key file used to secure datastore backend communication.
DataStoreKeyFile string `json:"dataStoreKeyFile,omitempty"`
// ClusterInit initialize a new cluster using embedded Etcd.
ClusterInit *bool `json:"clusterInit,omitempty"`
}
// Cluster is the desired state of k3s cluster configuration.
type Cluster struct {
// Token shared secret used to join a server or agent to a cluster.
Token string `json:"token,omitempty"`
// TokenFile file containing the cluster-secret/token.
TokenFile string `json:"tokenFile,omitempty"`
// Server which server to connect to, used to join a cluster.
Server string `json:"server,omitempty"`
}
// Listener defines the desired state of k3s listener configuration.
type Listener struct {
// BindAddress k3s bind address.
BindAddress string `json:"bindAddress,omitempty"`
// HTTPSListenPort HTTPS listen port.
HTTPSListenPort int `json:"httpsListenPort,omitempty"`
// AdvertiseAddress IP address that apiserver uses to advertise to members of the cluster.
AdvertiseAddress string `json:"advertiseAddress,omitempty"`
// AdvertisePort Port that apiserver uses to advertise to members of the cluster (default: listen-port).
AdvertisePort int `json:"advertisePort,omitempty"`
// TLSSan Add additional hostname or IP as a Subject Alternative Name in the TLS cert.
TLSSan string `json:"tlsSan,omitempty"`
}
// Networking defines the desired state of k3s networking configuration.
type Networking struct {
// ClusterCIDR Network CIDR to use for pod IPs.
ClusterCIDR string `json:"clusterCIDR,omitempty"`
// ServiceCIDR Network CIDR to use for services IPs.
ServiceCIDR string `json:"serviceCIDR,omitempty"`
// ServiceNodePortRange Port range to reserve for services with NodePort visibility.
ServiceNodePortRange string `json:"serviceNodePortRange,omitempty"`
// ClusterDNS cluster IP for coredns service. Should be in your service-cidr range.
ClusterDNS string `json:"clusterDNS,omitempty"`
// ClusterDomain cluster Domain.
ClusterDomain string `json:"clusterDomain,omitempty"`
// FlannelBackend One of none, vxlan, ipsec, host-gw, or wireguard. (default: vxlan)
FlannelBackend string `json:"flannelBackend,omitempty"`
}
// AgentNode defines the desired state of k3s agent node configuration.
type AgentNode struct {
// NodeName k3s node name.
NodeName string `json:"nodeName,omitempty"`
// NodeLabels registering and starting kubelet with set of labels.
NodeLabels []string `json:"nodeLabels,omitempty"`
// NodeTaints registering and starting kubelet with set of taints.
NodeTaints []string `json:"nodeTaints,omitempty"`
// SeLinux Enable SELinux in containerd
SeLinux bool `json:"seLinux,omitempty"`
// LBServerPort
// Local port for supervisor client load-balancer.
// If the supervisor and apiserver are not colocated an additional port 1 less than this port
// will also be used for the apiserver client load-balancer. (default: 6444)
LBServerPort int `json:"lbServerPort,omitempty"`
// DataDir Folder to hold state.
DataDir string `json:"dataDir,omitempty"`
}
// AgentRuntime defines the desired state of k3s agent runtime configuration.
type AgentRuntime struct {
// ContainerRuntimeEndpoint Disable embedded containerd and use alternative CRI implementation.
ContainerRuntimeEndpoint string `json:"containerRuntimeEndpoint,omitempty"`
// PauseImage Customized pause image for containerd or Docker sandbox.
PauseImage string `json:"pauseImage,omitempty"`
// PrivateRegistry Path to a private registry configuration file.
PrivateRegistry string `json:"privateRegistry,omitempty"`
}
// AgentNetworking defines the desired state of k3s agent networking configuration.
type AgentNetworking struct {
// NodeIP IP address to advertise for node.
NodeIP string `json:"nodeIP,omitempty"`
// NodeExternalIP External IP address to advertise for node.
NodeExternalIP string `json:"nodeExternalIP,omitempty"`
// ResolvConf Path to Kubelet resolv.conf file.
ResolvConf string `json:"resolvConf,omitempty"`
}
// KubernetesComponents defines the desired state of k3s kubernetes components configuration.
type KubernetesComponents struct {
// Disable do not deploy packaged components and delete any deployed components
// (valid items: coredns, servicelb, traefik,local-storage, metrics-server).
Disable string `json:"disable,omitempty"`
// DisableKubeProxy disable running kube-proxy.
DisableKubeProxy bool `json:"disableKubeProxy,omitempty"`
// DisableNetworkPolicy disable k3s default network policy controller.
DisableNetworkPolicy bool `json:"disableNetworkPolicy,omitempty"`
// DisableHelmController disable Helm controller.
DisableHelmController bool `json:"disableHelmController,omitempty"`
}
// KubernetesProcesses defines the desired state of kubernetes processes configuration.
type KubernetesProcesses struct {
// KubeAPIServerArgs is a customized flag for kube-apiserver process
// +optional
KubeAPIServerArgs []string `json:"kubeAPIServerArg,omitempty"`
// KubeControllerManagerArgs is a customized flag for kube-controller-manager process
// +optional
KubeControllerManagerArgs []string `json:"kubeControllerManagerArgs,omitempty"`
// KubeSchedulerArgs is a customized flag for kube-scheduler process
// +optional
KubeSchedulerArgs []string `json:"kubeSchedulerArgs,omitempty"`
}
// KubernetesAgentProcesses defines the desired state of kubernetes agent processes configuration.
type KubernetesAgentProcesses struct {
// KubeletArgs Customized flag for kubelet process
// +optional
KubeletArgs []string `json:"kubeletArgs,omitempty"`
// KubeProxyArgs Customized flag for kube-proxy process
// +optional
KubeProxyArgs []string `json:"kubeProxyArgs,omitempty"`
}

View File

@ -1,120 +0,0 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
)
// K3sConfigSpec defines the desired state of K3sConfig
type K3sConfigSpec struct {
// Files specifies extra files to be passed to user_data upon creation.
// +optional
Files []bootstrapv1.File `json:"files,omitempty"`
// Cluster defines the k3s cluster Options.
Cluster *Cluster `json:"cluster,omitempty"`
// ServerConfiguration defines the k3s server configuration.
// +optional
ServerConfiguration *ServerConfiguration `json:"serverConfiguration,omitempty"`
// AgentConfiguration defines the k3s agent configuration.
// +optional
AgentConfiguration *AgentConfiguration `json:"agentConfiguration,omitempty"`
// PreK3sCommands specifies extra commands to run before k3s setup runs
// +optional
PreK3sCommands []string `json:"preK3sCommands,omitempty"`
// PostK3sCommands specifies extra commands to run after k3s setup runs
// +optional
PostK3sCommands []string `json:"postK3sCommands,omitempty"`
// Version specifies the k3s version
// +optional
Version string `json:"version,omitempty"`
}
// K3sConfigStatus defines the observed state of K3sConfig
type K3sConfigStatus struct {
// Ready indicates the BootstrapData field is ready to be consumed
Ready bool `json:"ready,omitempty"`
BootstrapData []byte `json:"bootstrapData,omitempty"`
// DataSecretName is the name of the secret that stores the bootstrap data script.
// +optional
DataSecretName *string `json:"dataSecretName,omitempty"`
// FailureReason will be set on non-retryable errors
// +optional
FailureReason string `json:"failureReason,omitempty"`
// FailureMessage will be set on non-retryable errors
// +optional
FailureMessage string `json:"failureMessage,omitempty"`
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions defines current service state of the K3sConfig.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=k3sconfigs,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".metadata.labels['cluster\\.x-k8s\\.io/cluster-name']",description="Cluster"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of K3sConfig"
// K3sConfig is the Schema for the k3sConfigs API
type K3sConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec K3sConfigSpec `json:"spec,omitempty"`
Status K3sConfigStatus `json:"status,omitempty"`
}
// GetConditions returns the set of conditions for this object.
func (c *K3sConfig) GetConditions() clusterv1.Conditions {
return c.Status.Conditions
}
// SetConditions sets the conditions on this object.
func (c *K3sConfig) SetConditions(conditions clusterv1.Conditions) {
c.Status.Conditions = conditions
}
//+kubebuilder:object:root=true
// K3sConfigList contains a list of K3sConfig
type K3sConfigList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []K3sConfig `json:"items"`
}
func init() {
SchemeBuilder.Register(&K3sConfig{}, &K3sConfigList{})
}

View File

@ -1,146 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
var (
conflictingFileSourceMsg = "only one of content or contentFrom may be specified for a single file"
missingSecretNameMsg = "secret file source must specify non-empty secret name"
missingSecretKeyMsg = "secret file source must specify non-empty secret key"
pathConflictMsg = "path property must be unique among all files"
)
func (c *K3sConfig) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(c).
Complete()
}
// +kubebuilder:webhook:verbs=create;update,path=/mutate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfig,mutating=true,failurePolicy=fail,sideEffects=None,groups=bootstrap.cluster.x-k8s.io,resources=k3sconfigs,versions=v1beta1,name=default.k3sconfig.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
var _ webhook.Defaulter = &K3sConfig{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (c *K3sConfig) Default() {
DefaultK3sConfigSpec(&c.Spec)
}
// DefaultK3sConfigSpec defaults a K3sConfigSpec.
func DefaultK3sConfigSpec(c *K3sConfigSpec) {
}
// +kubebuilder:webhook:verbs=create;update,path=/validate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfig,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=bootstrap.cluster.x-k8s.io,resources=k3sconfigs,versions=v1beta1,name=validation.k3sconfig.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
var _ webhook.Validator = &K3sConfig{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (c *K3sConfig) ValidateCreate() error {
return c.Spec.validate(c.Name)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (c *K3sConfig) ValidateUpdate(old runtime.Object) error {
return c.Spec.validate(c.Name)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (c *K3sConfig) ValidateDelete() error {
return nil
}
func (c *K3sConfigSpec) validate(name string) error {
allErrs := c.Validate(field.NewPath("spec"))
if len(allErrs) == 0 {
return nil
}
return apierrors.NewInvalid(GroupVersion.WithKind("K3sConfig").GroupKind(), name, allErrs)
}
// Validate ensures the K3sConfigSpec is valid.
func (c *K3sConfigSpec) Validate(pathPrefix *field.Path) field.ErrorList {
var allErrs field.ErrorList
allErrs = append(allErrs, c.validateFiles(pathPrefix)...)
return allErrs
}
func (c *K3sConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorList {
var allErrs field.ErrorList
knownPaths := map[string]struct{}{}
for i := range c.Files {
file := c.Files[i]
if file.Content != "" && file.ContentFrom != nil {
allErrs = append(
allErrs,
field.Invalid(
pathPrefix.Child("files").Index(i),
file,
conflictingFileSourceMsg,
),
)
}
// n.b.: if we ever add types besides Secret as a ContentFrom
// Source, we must add webhook validation here for one of the
// sources being non-nil.
if file.ContentFrom != nil {
if file.ContentFrom.Secret.Name == "" {
allErrs = append(
allErrs,
field.Required(
pathPrefix.Child("files").Index(i).Child("contentFrom", "secret", "name"),
missingSecretNameMsg,
),
)
}
if file.ContentFrom.Secret.Key == "" {
allErrs = append(
allErrs,
field.Required(
pathPrefix.Child("files").Index(i).Child("contentFrom", "secret", "key"),
missingSecretKeyMsg,
),
)
}
}
_, conflict := knownPaths[file.Path]
if conflict {
allErrs = append(
allErrs,
field.Invalid(
pathPrefix.Child("files").Index(i).Child("path"),
file,
pathConflictMsg,
),
)
}
knownPaths[file.Path] = struct{}{}
}
return allErrs
}

View File

@ -1,57 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// K3sConfigTemplateSpec defines the desired state of K3sConfigTemplate
type K3sConfigTemplateSpec struct {
Template K3sConfigTemplateResource `json:"template"`
}
// K3sConfigTemplateResource defines the Template structure
type K3sConfigTemplateResource struct {
Spec K3sConfigSpec `json:"spec,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=k3sconfigtemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of K3sConfigTemplate"
// K3sConfigTemplate is the Schema for the k3sconfigtemplates API
type K3sConfigTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec K3sConfigTemplateSpec `json:"spec,omitempty"`
}
//+kubebuilder:object:root=true
// K3sConfigTemplateList contains a list of K3sConfigTemplate
type K3sConfigTemplateList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []K3sConfigTemplate `json:"items"`
}
func init() {
SchemeBuilder.Register(&K3sConfigTemplate{}, &K3sConfigTemplateList{})
}

View File

@ -1,71 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
func (r *K3sConfigTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// +kubebuilder:webhook:verbs=create;update,path=/mutate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfigtemplate,mutating=true,failurePolicy=fail,groups=bootstrap.cluster.x-k8s.io,resources=k3sconfigtemplates,versions=v1beta1,name=default.k3sconfigtemplate.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
var _ webhook.Defaulter = &K3sConfigTemplate{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *K3sConfigTemplate) Default() {
DefaultK3sConfigSpec(&r.Spec.Template.Spec)
}
// +kubebuilder:webhook:verbs=create;update,path=/validate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfigtemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=bootstrap.cluster.x-k8s.io,resources=k3sconfigtemplates,versions=v1beta1,name=validation.k3sconfigtemplate.bootstrap.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
var _ webhook.Validator = &K3sConfigTemplate{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *K3sConfigTemplate) ValidateCreate() error {
return r.Spec.validate(r.Name)
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *K3sConfigTemplate) ValidateUpdate(old runtime.Object) error {
return r.Spec.validate(r.Name)
}
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *K3sConfigTemplate) ValidateDelete() error {
return nil
}
func (r *K3sConfigTemplateSpec) validate(name string) error {
var allErrs field.ErrorList
allErrs = append(allErrs, r.Template.Spec.Validate(field.NewPath("spec", "template", "spec"))...)
if len(allErrs) == 0 {
return nil
}
return apierrors.NewInvalid(GroupVersion.WithKind("K3sConfigTemplate").GroupKind(), name, allErrs)
}

View File

@ -1,486 +0,0 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1beta1
import (
"k8s.io/apimachinery/pkg/runtime"
cluster_apiapiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
apiv1beta1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AgentConfiguration) DeepCopyInto(out *AgentConfiguration) {
*out = *in
in.Node.DeepCopyInto(&out.Node)
out.Runtime = in.Runtime
out.Networking = in.Networking
in.KubernetesAgentProcesses.DeepCopyInto(&out.KubernetesAgentProcesses)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentConfiguration.
func (in *AgentConfiguration) DeepCopy() *AgentConfiguration {
if in == nil {
return nil
}
out := new(AgentConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AgentNetworking) DeepCopyInto(out *AgentNetworking) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentNetworking.
func (in *AgentNetworking) DeepCopy() *AgentNetworking {
if in == nil {
return nil
}
out := new(AgentNetworking)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AgentNode) DeepCopyInto(out *AgentNode) {
*out = *in
if in.NodeLabels != nil {
in, out := &in.NodeLabels, &out.NodeLabels
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NodeTaints != nil {
in, out := &in.NodeTaints, &out.NodeTaints
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentNode.
func (in *AgentNode) DeepCopy() *AgentNode {
if in == nil {
return nil
}
out := new(AgentNode)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AgentRuntime) DeepCopyInto(out *AgentRuntime) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentRuntime.
func (in *AgentRuntime) DeepCopy() *AgentRuntime {
if in == nil {
return nil
}
out := new(AgentRuntime)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cluster) DeepCopyInto(out *Cluster) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster.
func (in *Cluster) DeepCopy() *Cluster {
if in == nil {
return nil
}
out := new(Cluster)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Database) DeepCopyInto(out *Database) {
*out = *in
if in.ClusterInit != nil {
in, out := &in.ClusterInit, &out.ClusterInit
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database.
func (in *Database) DeepCopy() *Database {
if in == nil {
return nil
}
out := new(Database)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *K3sConfig) DeepCopyInto(out *K3sConfig) {
*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 K3sConfig.
func (in *K3sConfig) DeepCopy() *K3sConfig {
if in == nil {
return nil
}
out := new(K3sConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *K3sConfig) 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 *K3sConfigList) DeepCopyInto(out *K3sConfigList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]K3sConfig, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigList.
func (in *K3sConfigList) DeepCopy() *K3sConfigList {
if in == nil {
return nil
}
out := new(K3sConfigList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *K3sConfigList) 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 *K3sConfigSpec) DeepCopyInto(out *K3sConfigSpec) {
*out = *in
if in.Files != nil {
in, out := &in.Files, &out.Files
*out = make([]apiv1beta1.File, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Cluster != nil {
in, out := &in.Cluster, &out.Cluster
*out = new(Cluster)
**out = **in
}
if in.ServerConfiguration != nil {
in, out := &in.ServerConfiguration, &out.ServerConfiguration
*out = new(ServerConfiguration)
(*in).DeepCopyInto(*out)
}
if in.AgentConfiguration != nil {
in, out := &in.AgentConfiguration, &out.AgentConfiguration
*out = new(AgentConfiguration)
(*in).DeepCopyInto(*out)
}
if in.PreK3sCommands != nil {
in, out := &in.PreK3sCommands, &out.PreK3sCommands
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.PostK3sCommands != nil {
in, out := &in.PostK3sCommands, &out.PostK3sCommands
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigSpec.
func (in *K3sConfigSpec) DeepCopy() *K3sConfigSpec {
if in == nil {
return nil
}
out := new(K3sConfigSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *K3sConfigStatus) DeepCopyInto(out *K3sConfigStatus) {
*out = *in
if in.BootstrapData != nil {
in, out := &in.BootstrapData, &out.BootstrapData
*out = make([]byte, len(*in))
copy(*out, *in)
}
if in.DataSecretName != nil {
in, out := &in.DataSecretName, &out.DataSecretName
*out = new(string)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(cluster_apiapiv1beta1.Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigStatus.
func (in *K3sConfigStatus) DeepCopy() *K3sConfigStatus {
if in == nil {
return nil
}
out := new(K3sConfigStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *K3sConfigTemplate) DeepCopyInto(out *K3sConfigTemplate) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigTemplate.
func (in *K3sConfigTemplate) DeepCopy() *K3sConfigTemplate {
if in == nil {
return nil
}
out := new(K3sConfigTemplate)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *K3sConfigTemplate) 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 *K3sConfigTemplateList) DeepCopyInto(out *K3sConfigTemplateList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]K3sConfigTemplate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigTemplateList.
func (in *K3sConfigTemplateList) DeepCopy() *K3sConfigTemplateList {
if in == nil {
return nil
}
out := new(K3sConfigTemplateList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *K3sConfigTemplateList) 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 *K3sConfigTemplateResource) DeepCopyInto(out *K3sConfigTemplateResource) {
*out = *in
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigTemplateResource.
func (in *K3sConfigTemplateResource) DeepCopy() *K3sConfigTemplateResource {
if in == nil {
return nil
}
out := new(K3sConfigTemplateResource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *K3sConfigTemplateSpec) DeepCopyInto(out *K3sConfigTemplateSpec) {
*out = *in
in.Template.DeepCopyInto(&out.Template)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new K3sConfigTemplateSpec.
func (in *K3sConfigTemplateSpec) DeepCopy() *K3sConfigTemplateSpec {
if in == nil {
return nil
}
out := new(K3sConfigTemplateSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesAgentProcesses) DeepCopyInto(out *KubernetesAgentProcesses) {
*out = *in
if in.KubeletArgs != nil {
in, out := &in.KubeletArgs, &out.KubeletArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.KubeProxyArgs != nil {
in, out := &in.KubeProxyArgs, &out.KubeProxyArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesAgentProcesses.
func (in *KubernetesAgentProcesses) DeepCopy() *KubernetesAgentProcesses {
if in == nil {
return nil
}
out := new(KubernetesAgentProcesses)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesComponents) DeepCopyInto(out *KubernetesComponents) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesComponents.
func (in *KubernetesComponents) DeepCopy() *KubernetesComponents {
if in == nil {
return nil
}
out := new(KubernetesComponents)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesProcesses) DeepCopyInto(out *KubernetesProcesses) {
*out = *in
if in.KubeAPIServerArgs != nil {
in, out := &in.KubeAPIServerArgs, &out.KubeAPIServerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.KubeControllerManagerArgs != nil {
in, out := &in.KubeControllerManagerArgs, &out.KubeControllerManagerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.KubeSchedulerArgs != nil {
in, out := &in.KubeSchedulerArgs, &out.KubeSchedulerArgs
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesProcesses.
func (in *KubernetesProcesses) DeepCopy() *KubernetesProcesses {
if in == nil {
return nil
}
out := new(KubernetesProcesses)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Listener) DeepCopyInto(out *Listener) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener.
func (in *Listener) DeepCopy() *Listener {
if in == nil {
return nil
}
out := new(Listener)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Networking) DeepCopyInto(out *Networking) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
func (in *Networking) DeepCopy() *Networking {
if in == nil {
return nil
}
out := new(Networking)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServerConfiguration) DeepCopyInto(out *ServerConfiguration) {
*out = *in
in.Database.DeepCopyInto(&out.Database)
out.Listener = in.Listener
out.Networking = in.Networking
out.KubernetesComponents = in.KubernetesComponents
in.KubernetesProcesses.DeepCopyInto(&out.KubernetesProcesses)
in.Agent.DeepCopyInto(&out.Agent)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerConfiguration.
func (in *ServerConfiguration) DeepCopy() *ServerConfiguration {
if in == nil {
return nil
}
out := new(ServerConfiguration)
in.DeepCopyInto(out)
return out
}

View File

@ -1,25 +0,0 @@
# 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 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for breaking changes
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
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: $(SERVICE_NAME)-cert # this secret will not be prefixed, since it's not managed by kustomize

View File

@ -1,5 +0,0 @@
resources:
- certificate.yaml
configurations:
- kustomizeconfig.yaml

View File

@ -1,19 +0,0 @@
# 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
- kind: Certificate
group: cert-manager.io
path: spec/secretName

View File

@ -1,496 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.1
creationTimestamp: null
name: k3sconfigs.bootstrap.cluster.x-k8s.io
spec:
group: bootstrap.cluster.x-k8s.io
names:
categories:
- cluster-api
kind: K3sConfig
listKind: K3sConfigList
plural: k3sconfigs
singular: k3sconfig
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: Cluster
jsonPath: .metadata.labels['cluster\.x-k8s\.io/cluster-name']
name: Cluster
type: string
- description: Time duration since creation of K3sConfig
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: K3sConfig is the Schema for the k3sConfigs 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: K3sConfigSpec defines the desired state of K3sConfig
properties:
agentConfiguration:
description: AgentConfiguration defines the k3s agent configuration.
properties:
kubernetesAgentProcesses:
description: KubernetesAgentProcesses defines the k3s agent kubernetes
processes configuration.
properties:
kubeProxyArgs:
description: KubeProxyArgs Customized flag for kube-proxy
process
items:
type: string
type: array
kubeletArgs:
description: KubeletArgs Customized flag for kubelet process
items:
type: string
type: array
type: object
networking:
description: Networking defines the k3s agent networking configuration.
properties:
nodeExternalIP:
description: NodeExternalIP External IP address to advertise
for node.
type: string
nodeIP:
description: NodeIP IP address to advertise for node.
type: string
resolvConf:
description: ResolvConf Path to Kubelet resolv.conf file.
type: string
type: object
node:
description: Node defines the k3s agent node configuration.
properties:
dataDir:
description: DataDir Folder to hold state.
type: string
lbServerPort:
description: 'LBServerPort Local port for supervisor client
load-balancer. If the supervisor and apiserver are not colocated
an additional port 1 less than this port will also be used
for the apiserver client load-balancer. (default: 6444)'
type: integer
nodeLabels:
description: NodeLabels registering and starting kubelet with
set of labels.
items:
type: string
type: array
nodeName:
description: NodeName k3s node name.
type: string
nodeTaints:
description: NodeTaints registering and starting kubelet with
set of taints.
items:
type: string
type: array
seLinux:
description: SeLinux Enable SELinux in containerd
type: boolean
type: object
runtime:
description: Runtime defines the k3s agent runtime configuration.
properties:
containerRuntimeEndpoint:
description: ContainerRuntimeEndpoint Disable embedded containerd
and use alternative CRI implementation.
type: string
pauseImage:
description: PauseImage Customized pause image for containerd
or Docker sandbox.
type: string
privateRegistry:
description: PrivateRegistry Path to a private registry configuration
file.
type: string
type: object
type: object
cluster:
description: Cluster defines the k3s cluster Options.
properties:
server:
description: Server which server to connect to, used to join a
cluster.
type: string
token:
description: Token shared secret used to join a server or agent
to a cluster.
type: string
tokenFile:
description: TokenFile file containing the cluster-secret/token.
type: string
type: object
files:
description: Files specifies extra files to be passed to user_data
upon creation.
items:
description: File defines the input for generating write_files in
cloud-init.
properties:
append:
description: Append specifies whether to append Content to existing
file if Path exists.
type: boolean
content:
description: Content is the actual content of the file.
type: string
contentFrom:
description: ContentFrom is a referenced source of content to
populate the file.
properties:
secret:
description: Secret represents a secret that should populate
this file.
properties:
key:
description: Key is the key in the secret's data map
for this value.
type: string
name:
description: Name of the secret in the KubeadmBootstrapConfig's
namespace to use.
type: string
required:
- key
- name
type: object
required:
- secret
type: object
encoding:
description: Encoding specifies the encoding of the file contents.
enum:
- base64
- gzip
- gzip+base64
type: string
owner:
description: Owner specifies the ownership of the file, e.g.
"root:root".
type: string
path:
description: Path specifies the full path on disk where to store
the file.
type: string
permissions:
description: Permissions specifies the permissions to assign
to the file, e.g. "0640".
type: string
required:
- path
type: object
type: array
postK3sCommands:
description: PostK3sCommands specifies extra commands to run after
k3s setup runs
items:
type: string
type: array
preK3sCommands:
description: PreK3sCommands specifies extra commands to run before
k3s setup runs
items:
type: string
type: array
serverConfiguration:
description: ServerConfiguration defines the k3s server configuration.
properties:
agent:
description: Agent is the agent configuration.
properties:
kubernetesAgentProcesses:
description: KubernetesAgentProcesses defines the k3s agent
kubernetes processes configuration.
properties:
kubeProxyArgs:
description: KubeProxyArgs Customized flag for kube-proxy
process
items:
type: string
type: array
kubeletArgs:
description: KubeletArgs Customized flag for kubelet process
items:
type: string
type: array
type: object
networking:
description: Networking defines the k3s agent networking configuration.
properties:
nodeExternalIP:
description: NodeExternalIP External IP address to advertise
for node.
type: string
nodeIP:
description: NodeIP IP address to advertise for node.
type: string
resolvConf:
description: ResolvConf Path to Kubelet resolv.conf file.
type: string
type: object
node:
description: Node defines the k3s agent node configuration.
properties:
dataDir:
description: DataDir Folder to hold state.
type: string
lbServerPort:
description: 'LBServerPort Local port for supervisor client
load-balancer. If the supervisor and apiserver are not
colocated an additional port 1 less than this port will
also be used for the apiserver client load-balancer.
(default: 6444)'
type: integer
nodeLabels:
description: NodeLabels registering and starting kubelet
with set of labels.
items:
type: string
type: array
nodeName:
description: NodeName k3s node name.
type: string
nodeTaints:
description: NodeTaints registering and starting kubelet
with set of taints.
items:
type: string
type: array
seLinux:
description: SeLinux Enable SELinux in containerd
type: boolean
type: object
runtime:
description: Runtime defines the k3s agent runtime configuration.
properties:
containerRuntimeEndpoint:
description: ContainerRuntimeEndpoint Disable embedded
containerd and use alternative CRI implementation.
type: string
pauseImage:
description: PauseImage Customized pause image for containerd
or Docker sandbox.
type: string
privateRegistry:
description: PrivateRegistry Path to a private registry
configuration file.
type: string
type: object
type: object
database:
description: Database is the database configuration.
properties:
clusterInit:
description: ClusterInit initialize a new cluster using embedded
Etcd.
type: boolean
dataStoreCAFile:
description: DataStoreCAFile TLS Certificate Authority file
used to secure datastore backend communication.
type: string
dataStoreCertFile:
description: DataStoreCertFile TLS certification file used
to secure datastore backend communication.
type: string
dataStoreEndPoint:
description: DataStoreEndPoint specify etcd, Mysql, Postgres,
or Sqlite (default) data source name.
type: string
dataStoreKeyFile:
description: DataStoreKeyFile TLS key file used to secure
datastore backend communication.
type: string
type: object
kubernetesComponents:
description: KubernetesComponents is the kubernetes components
configuration.
properties:
disable:
description: 'Disable do not deploy packaged components and
delete any deployed components (valid items: coredns, servicelb,
traefik,local-storage, metrics-server).'
type: string
disableHelmController:
description: DisableHelmController disable Helm controller.
type: boolean
disableKubeProxy:
description: DisableKubeProxy disable running kube-proxy.
type: boolean
disableNetworkPolicy:
description: DisableNetworkPolicy disable k3s default network
policy controller.
type: boolean
type: object
kubernetesProcesses:
description: KubernetesProcesses is the kubernetes processes configuration.
properties:
kubeAPIServerArg:
description: KubeAPIServerArgs is a customized flag for kube-apiserver
process
items:
type: string
type: array
kubeControllerManagerArgs:
description: KubeControllerManagerArgs is a customized flag
for kube-controller-manager process
items:
type: string
type: array
kubeSchedulerArgs:
description: KubeSchedulerArgs is a customized flag for kube-scheduler
process
items:
type: string
type: array
type: object
listener:
description: Listener is the listener configuration.
properties:
advertiseAddress:
description: AdvertiseAddress IP address that apiserver uses
to advertise to members of the cluster.
type: string
advertisePort:
description: 'AdvertisePort Port that apiserver uses to advertise
to members of the cluster (default: listen-port).'
type: integer
bindAddress:
description: BindAddress k3s bind address.
type: string
httpsListenPort:
description: HTTPSListenPort HTTPS listen port.
type: integer
tlsSan:
description: TLSSan Add additional hostname or IP as a Subject
Alternative Name in the TLS cert.
type: string
type: object
networking:
description: Networking is the networking configuration.
properties:
clusterCIDR:
description: ClusterCIDR Network CIDR to use for pod IPs.
type: string
clusterDNS:
description: ClusterDNS cluster IP for coredns service. Should
be in your service-cidr range.
type: string
clusterDomain:
description: ClusterDomain cluster Domain.
type: string
flannelBackend:
description: 'FlannelBackend One of none, vxlan, ipsec,
host-gw, or wireguard. (default: vxlan)'
type: string
serviceCIDR:
description: ServiceCIDR Network CIDR to use for services
IPs.
type: string
serviceNodePortRange:
description: ServiceNodePortRange Port range to reserve for
services with NodePort visibility.
type: string
type: object
type: object
version:
description: Version specifies the k3s version
type: string
type: object
status:
description: K3sConfigStatus defines the observed state of K3sConfig
properties:
bootstrapData:
format: byte
type: string
conditions:
description: Conditions defines current service state of the K3sConfig.
items:
description: Condition defines an observation of a Cluster API resource
operational state.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another. This should be when the underlying condition changed.
If that is not known, then using the time when the API field
changed is acceptable.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition. This field may be empty.
type: string
reason:
description: The reason for the condition's last transition
in CamelCase. The specific API may choose whether or not this
field is considered a guaranteed API. This field may not be
empty.
type: string
severity:
description: Severity provides an explicit classification of
Reason code, so the users or machines can immediately understand
the current situation and act accordingly. The Severity field
MUST be set only when Status=False.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important.
type: string
required:
- lastTransitionTime
- status
- type
type: object
type: array
dataSecretName:
description: DataSecretName is the name of the secret that stores
the bootstrap data script.
type: string
failureMessage:
description: FailureMessage will be set on non-retryable errors
type: string
failureReason:
description: FailureReason will be set on non-retryable errors
type: string
observedGeneration:
description: ObservedGeneration is the latest generation observed
by the controller.
format: int64
type: integer
ready:
description: Ready indicates the BootstrapData field is ready to be
consumed
type: boolean
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -1,445 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.9.1
creationTimestamp: null
name: k3sconfigtemplates.bootstrap.cluster.x-k8s.io
spec:
group: bootstrap.cluster.x-k8s.io
names:
categories:
- cluster-api
kind: K3sConfigTemplate
listKind: K3sConfigTemplateList
plural: k3sconfigtemplates
singular: k3sconfigtemplate
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: Time duration since creation of K3sConfigTemplate
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: K3sConfigTemplate is the Schema for the k3sconfigtemplates 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: K3sConfigTemplateSpec defines the desired state of K3sConfigTemplate
properties:
template:
description: K3sConfigTemplateResource defines the Template structure
properties:
spec:
description: K3sConfigSpec defines the desired state of K3sConfig
properties:
agentConfiguration:
description: AgentConfiguration defines the k3s agent configuration.
properties:
kubernetesAgentProcesses:
description: KubernetesAgentProcesses defines the k3s
agent kubernetes processes configuration.
properties:
kubeProxyArgs:
description: KubeProxyArgs Customized flag for kube-proxy
process
items:
type: string
type: array
kubeletArgs:
description: KubeletArgs Customized flag for kubelet
process
items:
type: string
type: array
type: object
networking:
description: Networking defines the k3s agent networking
configuration.
properties:
nodeExternalIP:
description: NodeExternalIP External IP address to
advertise for node.
type: string
nodeIP:
description: NodeIP IP address to advertise for node.
type: string
resolvConf:
description: ResolvConf Path to Kubelet resolv.conf
file.
type: string
type: object
node:
description: Node defines the k3s agent node configuration.
properties:
dataDir:
description: DataDir Folder to hold state.
type: string
lbServerPort:
description: 'LBServerPort Local port for supervisor
client load-balancer. If the supervisor and apiserver
are not colocated an additional port 1 less than
this port will also be used for the apiserver client
load-balancer. (default: 6444)'
type: integer
nodeLabels:
description: NodeLabels registering and starting kubelet
with set of labels.
items:
type: string
type: array
nodeName:
description: NodeName k3s node name.
type: string
nodeTaints:
description: NodeTaints registering and starting kubelet
with set of taints.
items:
type: string
type: array
seLinux:
description: SeLinux Enable SELinux in containerd
type: boolean
type: object
runtime:
description: Runtime defines the k3s agent runtime configuration.
properties:
containerRuntimeEndpoint:
description: ContainerRuntimeEndpoint Disable embedded
containerd and use alternative CRI implementation.
type: string
pauseImage:
description: PauseImage Customized pause image for
containerd or Docker sandbox.
type: string
privateRegistry:
description: PrivateRegistry Path to a private registry
configuration file.
type: string
type: object
type: object
cluster:
description: Cluster defines the k3s cluster Options.
properties:
server:
description: Server which server to connect to, used to
join a cluster.
type: string
token:
description: Token shared secret used to join a server
or agent to a cluster.
type: string
tokenFile:
description: TokenFile file containing the cluster-secret/token.
type: string
type: object
files:
description: Files specifies extra files to be passed to user_data
upon creation.
items:
description: File defines the input for generating write_files
in cloud-init.
properties:
append:
description: Append specifies whether to append Content
to existing file if Path exists.
type: boolean
content:
description: Content is the actual content of the file.
type: string
contentFrom:
description: ContentFrom is a referenced source of content
to populate the file.
properties:
secret:
description: Secret represents a secret that should
populate this file.
properties:
key:
description: Key is the key in the secret's
data map for this value.
type: string
name:
description: Name of the secret in the KubeadmBootstrapConfig's
namespace to use.
type: string
required:
- key
- name
type: object
required:
- secret
type: object
encoding:
description: Encoding specifies the encoding of the
file contents.
enum:
- base64
- gzip
- gzip+base64
type: string
owner:
description: Owner specifies the ownership of the file,
e.g. "root:root".
type: string
path:
description: Path specifies the full path on disk where
to store the file.
type: string
permissions:
description: Permissions specifies the permissions to
assign to the file, e.g. "0640".
type: string
required:
- path
type: object
type: array
postK3sCommands:
description: PostK3sCommands specifies extra commands to run
after k3s setup runs
items:
type: string
type: array
preK3sCommands:
description: PreK3sCommands specifies extra commands to run
before k3s setup runs
items:
type: string
type: array
serverConfiguration:
description: ServerConfiguration defines the k3s server configuration.
properties:
agent:
description: Agent is the agent configuration.
properties:
kubernetesAgentProcesses:
description: KubernetesAgentProcesses defines the
k3s agent kubernetes processes configuration.
properties:
kubeProxyArgs:
description: KubeProxyArgs Customized flag for
kube-proxy process
items:
type: string
type: array
kubeletArgs:
description: KubeletArgs Customized flag for kubelet
process
items:
type: string
type: array
type: object
networking:
description: Networking defines the k3s agent networking
configuration.
properties:
nodeExternalIP:
description: NodeExternalIP External IP address
to advertise for node.
type: string
nodeIP:
description: NodeIP IP address to advertise for
node.
type: string
resolvConf:
description: ResolvConf Path to Kubelet resolv.conf
file.
type: string
type: object
node:
description: Node defines the k3s agent node configuration.
properties:
dataDir:
description: DataDir Folder to hold state.
type: string
lbServerPort:
description: 'LBServerPort Local port for supervisor
client load-balancer. If the supervisor and
apiserver are not colocated an additional port
1 less than this port will also be used for
the apiserver client load-balancer. (default:
6444)'
type: integer
nodeLabels:
description: NodeLabels registering and starting
kubelet with set of labels.
items:
type: string
type: array
nodeName:
description: NodeName k3s node name.
type: string
nodeTaints:
description: NodeTaints registering and starting
kubelet with set of taints.
items:
type: string
type: array
seLinux:
description: SeLinux Enable SELinux in containerd
type: boolean
type: object
runtime:
description: Runtime defines the k3s agent runtime
configuration.
properties:
containerRuntimeEndpoint:
description: ContainerRuntimeEndpoint Disable
embedded containerd and use alternative CRI
implementation.
type: string
pauseImage:
description: PauseImage Customized pause image
for containerd or Docker sandbox.
type: string
privateRegistry:
description: PrivateRegistry Path to a private
registry configuration file.
type: string
type: object
type: object
database:
description: Database is the database configuration.
properties:
clusterInit:
description: ClusterInit initialize a new cluster
using embedded Etcd.
type: boolean
dataStoreCAFile:
description: DataStoreCAFile TLS Certificate Authority
file used to secure datastore backend communication.
type: string
dataStoreCertFile:
description: DataStoreCertFile TLS certification file
used to secure datastore backend communication.
type: string
dataStoreEndPoint:
description: DataStoreEndPoint specify etcd, Mysql,
Postgres, or Sqlite (default) data source name.
type: string
dataStoreKeyFile:
description: DataStoreKeyFile TLS key file used to
secure datastore backend communication.
type: string
type: object
kubernetesComponents:
description: KubernetesComponents is the kubernetes components
configuration.
properties:
disable:
description: 'Disable do not deploy packaged components
and delete any deployed components (valid items:
coredns, servicelb, traefik,local-storage, metrics-server).'
type: string
disableHelmController:
description: DisableHelmController disable Helm controller.
type: boolean
disableKubeProxy:
description: DisableKubeProxy disable running kube-proxy.
type: boolean
disableNetworkPolicy:
description: DisableNetworkPolicy disable k3s default
network policy controller.
type: boolean
type: object
kubernetesProcesses:
description: KubernetesProcesses is the kubernetes processes
configuration.
properties:
kubeAPIServerArg:
description: KubeAPIServerArgs is a customized flag
for kube-apiserver process
items:
type: string
type: array
kubeControllerManagerArgs:
description: KubeControllerManagerArgs is a customized
flag for kube-controller-manager process
items:
type: string
type: array
kubeSchedulerArgs:
description: KubeSchedulerArgs is a customized flag
for kube-scheduler process
items:
type: string
type: array
type: object
listener:
description: Listener is the listener configuration.
properties:
advertiseAddress:
description: AdvertiseAddress IP address that apiserver
uses to advertise to members of the cluster.
type: string
advertisePort:
description: 'AdvertisePort Port that apiserver uses
to advertise to members of the cluster (default:
listen-port).'
type: integer
bindAddress:
description: BindAddress k3s bind address.
type: string
httpsListenPort:
description: HTTPSListenPort HTTPS listen port.
type: integer
tlsSan:
description: TLSSan Add additional hostname or IP
as a Subject Alternative Name in the TLS cert.
type: string
type: object
networking:
description: Networking is the networking configuration.
properties:
clusterCIDR:
description: ClusterCIDR Network CIDR to use for pod
IPs.
type: string
clusterDNS:
description: ClusterDNS cluster IP for coredns service.
Should be in your service-cidr range.
type: string
clusterDomain:
description: ClusterDomain cluster Domain.
type: string
flannelBackend:
description: 'FlannelBackend One of none, vxlan,
ipsec, host-gw, or wireguard. (default: vxlan)'
type: string
serviceCIDR:
description: ServiceCIDR Network CIDR to use for services
IPs.
type: string
serviceNodePortRange:
description: ServiceNodePortRange Port range to reserve
for services with NodePort visibility.
type: string
type: object
type: object
version:
description: Version specifies the k3s version
type: string
type: object
type: object
required:
- template
type: object
type: object
served: true
storage: true
subresources: {}

View File

@ -1,27 +0,0 @@
# This kustomization.yaml is not intended to be run by itself,
# since it depends on service name and namespace that are out of this kustomize package.
# It should be run by config/default
resources:
- bases/bootstrap.cluster.x-k8s.io_k3sconfigs.yaml
- bases/bootstrap.cluster.x-k8s.io_k3sconfigtemplates.yaml
#+kubebuilder:scaffold:crdkustomizeresource
commonLabels:
cluster.x-k8s.io/v1beta1: v1beta1
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_k3sconfigs.yaml
- patches/webhook_in_k3sconfigtemplates.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_k3sconfigs.yaml
- patches/cainjection_in_k3sconfigtemplates.yaml
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
- kustomizeconfig.yaml

View File

@ -1,19 +0,0 @@
# This file is for teaching kustomize how to substitute name and namespace reference in CRD
nameReference:
- kind: Service
version: v1
fieldSpecs:
- kind: CustomResourceDefinition
version: v1
group: apiextensions.k8s.io
path: spec/conversion/webhook/clientConfig/service/name
namespace:
- kind: CustomResourceDefinition
version: v1
group: apiextensions.k8s.io
path: spec/conversion/webhook/clientConfig/service/namespace
create: false
varReference:
- path: metadata/annotations

View File

@ -1,7 +0,0 @@
# 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: k3sconfigs.bootstrap.cluster.x-k8s.io

View File

@ -1,7 +0,0 @@
# 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: k3sconfigtemplates.bootstrap.cluster.x-k8s.io

View File

@ -1,18 +0,0 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: k3sconfigs.bootstrap.cluster.x-k8s.io
spec:
conversion:
strategy: Webhook
webhook:
conversionReviewVersions: ["v1", "v1beta1"]
clientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert

View File

@ -1,18 +0,0 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: k3sconfigtemplates.bootstrap.cluster.x-k8s.io
spec:
conversion:
strategy: Webhook
webhook:
conversionReviewVersions: ["v1", "v1beta1"]
clientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert

View File

@ -1,54 +0,0 @@
namePrefix: capkk-k3s-bootstrap-
namespace: capkk-k3s-bootstrap-system
commonLabels:
cluster.x-k8s.io/provider: "bootstrap-k3s"
resources:
- namespace.yaml
bases:
- ../rbac
- ../manager
- ../crd
- ../certmanager
- ../webhook
patchesStrategicMerge:
# Provide customizable hook for make targets.
- manager_image_patch.yaml
- manager_pull_policy.yaml
# Enable webhook.
- manager_webhook_patch.yaml
# Inject certificate in the webhook definition.
- webhookcainjection_patch.yaml
configurations:
- kustomizeconfig.yaml
vars:
- 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

View File

@ -1,4 +0,0 @@
# This configuration is for teaching kustomize how to update name ref and var substitution
varReference:
- kind: Deployment
path: spec/template/spec/volumes/secret/secretName

View File

@ -1,11 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- image: docker.io/kubespheredev/k3s-bootstrap-controller:main
name: manager

View File

@ -1,11 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
imagePullPolicy: Always

View File

@ -1,22 +0,0 @@
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:
secretName: $(SERVICE_NAME)-cert

View File

@ -1,6 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
name: system

View File

@ -1,14 +0,0 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)

View File

@ -1,2 +0,0 @@
resources:
- manager.yaml

View File

@ -1,44 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
labels:
control-plane: controller-manager
spec:
selector:
matchLabels:
control-plane: controller-manager
replicas: 1
template:
metadata:
labels:
control-plane: controller-manager
spec:
containers:
- command:
- /manager
args:
- "--leader-elect"
- "--metrics-bind-addr=localhost:8080"
image: controller:latest
name: manager
ports:
- containerPort: 9440
name: healthz
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: healthz
livenessProbe:
httpGet:
path: /healthz
port: healthz
terminationGracePeriodSeconds: 10
serviceAccountName: manager
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane

View File

@ -1,6 +0,0 @@
resources:
- service_account.yaml
- role.yaml
- role_binding.yaml
- leader_election_role.yaml
- leader_election_role_binding.yaml

View File

@ -1,37 +0,0 @@
# permissions to do leader election.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leader-election-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch

View File

@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leader-election-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: leader-election-role
subjects:
- kind: ServiceAccount
name: manager
namespace: system

View File

@ -1,49 +0,0 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
- events
- secrets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- bootstrap.cluster.x-k8s.io
resources:
- k3sconfigs
- k3sconfigs/finalizers
- k3sconfigs/status
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cluster.x-k8s.io
resources:
- clusters
- clusters/status
- machinepools
- machinepools/status
- machines
- machines/status
- machinesets
verbs:
- get
- list
- watch

View File

@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: manager-role
subjects:
- kind: ServiceAccount
name: manager
namespace: system

View File

@ -1,5 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: manager
namespace: system

View File

@ -1,6 +0,0 @@
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: K3sConfig
metadata:
name: k3sconfig-sample
spec:
# TODO(user): Add fields here

View File

@ -1,6 +0,0 @@
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: K3sConfigTemplate
metadata:
name: k3sconfigtemplate-sample
spec:
# TODO(user): Add fields here

View File

@ -1,5 +0,0 @@
## Append samples you want in your CSV to this file as resources ##
resources:
- bootstrap_v1beta1_k3sconfig.yaml
- bootstrap_v1beta1_k3sconfigtemplate.yaml
#+kubebuilder:scaffold:manifestskustomizesamples

View File

@ -1,7 +0,0 @@
apiVersion: scorecard.operatorframework.io/v1alpha3
kind: Configuration
metadata:
name: config
stages:
- parallel: true
tests: []

View File

@ -1,16 +0,0 @@
resources:
- bases/config.yaml
patchesJson6902:
- path: patches/basic.config.yaml
target:
group: scorecard.operatorframework.io
version: v1alpha3
kind: Configuration
name: config
- path: patches/olm.config.yaml
target:
group: scorecard.operatorframework.io
version: v1alpha3
kind: Configuration
name: config
#+kubebuilder:scaffold:patchesJson6902

View File

@ -1,10 +0,0 @@
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- basic-check-spec
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: basic
test: basic-check-spec-test

View File

@ -1,50 +0,0 @@
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-bundle-validation
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: olm
test: olm-bundle-validation-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-crds-have-validation
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: olm
test: olm-crds-have-validation-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-crds-have-resources
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: olm
test: olm-crds-have-resources-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-spec-descriptors
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: olm
test: olm-spec-descriptors-test
- op: add
path: /stages/0/tests/-
value:
entrypoint:
- scorecard-test
- olm-status-descriptors
image: quay.io/operator-framework/scorecard-test:v1.22.2
labels:
suite: olm
test: olm-status-descriptors-test

View File

@ -1,6 +0,0 @@
resources:
- manifests.yaml
- service.yaml
configurations:
- kustomizeconfig.yaml

View File

@ -1,25 +0,0 @@
# the following config is for teaching kustomize where to look at when substituting vars.
# It requires kustomize v2.1.0 or newer to work properly.
nameReference:
- kind: Service
version: v1
fieldSpecs:
- kind: MutatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/name
- kind: ValidatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/name
namespace:
- kind: MutatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/namespace
create: true
- kind: ValidatingWebhookConfiguration
group: admissionregistration.k8s.io
path: webhooks/clientConfig/service/namespace
create: true
varReference:
- path: metadata/annotations

View File

@ -1,100 +0,0 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfig
failurePolicy: Fail
name: default.k3sconfig.bootstrap.cluster.x-k8s.io
rules:
- apiGroups:
- bootstrap.cluster.x-k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- k3sconfigs
sideEffects: None
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfigtemplate
failurePolicy: Fail
name: default.k3sconfigtemplate.bootstrap.cluster.x-k8s.io
rules:
- apiGroups:
- bootstrap.cluster.x-k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- k3sconfigtemplates
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfig
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.k3sconfig.bootstrap.cluster.x-k8s.io
rules:
- apiGroups:
- bootstrap.cluster.x-k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- k3sconfigs
sideEffects: None
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-bootstrap-cluster-x-k8s-io-v1beta1-k3sconfigtemplate
failurePolicy: Fail
matchPolicy: Equivalent
name: validation.k3sconfigtemplate.bootstrap.cluster.x-k8s.io
rules:
- apiGroups:
- bootstrap.cluster.x-k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- k3sconfigtemplates
sideEffects: None

View File

@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: webhook-service
namespace: system
spec:
ports:
- port: 443
protocol: TCP
targetPort: 9443
selector:
control-plane: controller-manager

View File

@ -1,18 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package controllers contains k3s config controllers.
package controllers

View File

@ -1,794 +0,0 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
"context"
"fmt"
"time"
"github.com/go-logr/logr"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
kerrors "k8s.io/apimachinery/pkg/util/errors"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
bsutil "sigs.k8s.io/cluster-api/bootstrap/util"
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
"sigs.k8s.io/cluster-api/feature"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/annotations"
"sigs.k8s.io/cluster-api/util/conditions"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/cluster-api/util/predicates"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"
infrabootstrapv1 "github.com/kubesphere/kubekey/v3/bootstrap/k3s/api/v1beta1"
"github.com/kubesphere/kubekey/v3/bootstrap/k3s/pkg/cloudinit"
"github.com/kubesphere/kubekey/v3/bootstrap/k3s/pkg/locking"
k3stypes "github.com/kubesphere/kubekey/v3/bootstrap/k3s/pkg/types"
kklog "github.com/kubesphere/kubekey/v3/util/log"
"github.com/kubesphere/kubekey/v3/util/secret"
)
// InitLocker is a lock that is used around kubeadm init.
type InitLocker interface {
Lock(ctx context.Context, cluster *clusterv1.Cluster, machine *clusterv1.Machine) bool
Unlock(ctx context.Context, cluster *clusterv1.Cluster) bool
}
// +kubebuilder:rbac:groups=bootstrap.cluster.x-k8s.io,resources=k3sconfigs;k3sconfigs/status;k3sconfigs/finalizers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status;machinesets;machines;machines/status;machinepools;machinepools/status,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=secrets;events;configmaps,verbs=get;list;watch;create;update;patch;delete
// K3sConfigReconciler reconciles a K3sConfig object
type K3sConfigReconciler struct {
client.Client
K3sInitLock InitLocker
// WatchFilterValue is the label value used to filter events prior to reconciliation.
WatchFilterValue string
}
// Scope is a scoped struct used during reconciliation.
type Scope struct {
logr.Logger
Config *infrabootstrapv1.K3sConfig
ConfigOwner *bsutil.ConfigOwner
Cluster *clusterv1.Cluster
}
// SetupWithManager sets up the controller with the Manager.
func (r *K3sConfigReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
if r.K3sInitLock == nil {
r.K3sInitLock = locking.NewControlPlaneInitMutex(mgr.GetClient())
}
b := ctrl.NewControllerManagedBy(mgr).
For(&infrabootstrapv1.K3sConfig{}).
WithOptions(options).
Watches(
&source.Kind{Type: &clusterv1.Machine{}},
handler.EnqueueRequestsFromMapFunc(r.MachineToBootstrapMapFunc),
).WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue))
if feature.Gates.Enabled(feature.MachinePool) {
b = b.Watches(
&source.Kind{Type: &expv1.MachinePool{}},
handler.EnqueueRequestsFromMapFunc(r.MachinePoolToBootstrapMapFunc),
).WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue))
}
c, err := b.Build(r)
if err != nil {
return errors.Wrap(err, "failed setting up with a controller manager")
}
err = c.Watch(
&source.Kind{Type: &clusterv1.Cluster{}},
handler.EnqueueRequestsFromMapFunc(r.ClusterToK3sConfigs),
predicates.All(ctrl.LoggerFrom(ctx),
predicates.ClusterUnpausedAndInfrastructureReady(ctrl.LoggerFrom(ctx)),
predicates.ResourceHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue),
),
)
if err != nil {
return errors.Wrap(err, "failed adding Watch for Clusters to controller manager")
}
return nil
}
// Reconcile handles K3sConfig events.
func (r *K3sConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, retErr error) {
log := ctrl.LoggerFrom(ctx)
// Lookup the kubeadm config
config := &infrabootstrapv1.K3sConfig{}
if err := r.Client.Get(ctx, req.NamespacedName, config); err != nil {
if apierrors.IsNotFound(err) {
return ctrl.Result{}, nil
}
log.Error(err, "Failed to get config")
return ctrl.Result{}, err
}
// AddOwners adds the owners of K3sConfig as k/v pairs to the logger.
// Specifically, it will add K3sControlPlane, MachineSet and MachineDeployment.
ctx, log, err := kklog.AddOwners(ctx, r.Client, config)
if err != nil {
return ctrl.Result{}, err
}
// Look up the owner of this k3s config if there is one
configOwner, err := bsutil.GetConfigOwner(ctx, r.Client, config)
if apierrors.IsNotFound(err) {
// Could not find the owner yet, this is not an error and will rereconcile when the owner gets set.
return ctrl.Result{}, nil
}
if err != nil {
log.Error(err, "Failed to get owner")
return ctrl.Result{}, err
}
if configOwner == nil {
return ctrl.Result{}, nil
}
log = log.WithValues(configOwner.GetKind(), klog.KRef(configOwner.GetNamespace(), configOwner.GetName()), "resourceVersion", configOwner.GetResourceVersion())
log = log.WithValues("Cluster", klog.KRef(configOwner.GetNamespace(), configOwner.ClusterName()))
ctx = ctrl.LoggerInto(ctx, log)
// Lookup the cluster the config owner is associated with
cluster, err := util.GetClusterByName(ctx, r.Client, configOwner.GetNamespace(), configOwner.ClusterName())
if err != nil {
if errors.Cause(err) == util.ErrNoCluster {
log.Info(fmt.Sprintf("%s does not belong to a cluster yet, waiting until it's part of a cluster", configOwner.GetKind()))
return ctrl.Result{}, nil
}
if apierrors.IsNotFound(err) {
log.Info("Cluster does not exist yet, waiting until it is created")
return ctrl.Result{}, nil
}
log.Error(err, "Could not get cluster with metadata")
return ctrl.Result{}, err
}
if annotations.IsPaused(cluster, config) {
log.Info("Reconciliation is paused for this object")
return ctrl.Result{}, nil
}
scope := &Scope{
Logger: log,
Config: config,
ConfigOwner: configOwner,
Cluster: cluster,
}
// Initialize the patch helper.
patchHelper, err := patch.NewHelper(config, r.Client)
if err != nil {
return ctrl.Result{}, err
}
// Attempt to Patch the K3sConfig object and status after each reconciliation if no error occurs.
defer func() {
// always update the readyCondition; the summary is represented using the "1 of x completed" notation.
conditions.SetSummary(config,
conditions.WithConditions(
bootstrapv1.DataSecretAvailableCondition,
bootstrapv1.CertificatesAvailableCondition,
),
)
// Patch ObservedGeneration only if the reconciliation completed successfully
var patchOpts []patch.Option
if retErr == nil {
patchOpts = append(patchOpts, patch.WithStatusObservedGeneration{})
}
if err := patchHelper.Patch(ctx, config, patchOpts...); err != nil {
log.Error(retErr, "Failed to patch config")
if retErr == nil {
retErr = err
}
}
}()
switch {
// Wait for the infrastructure to be ready.
case !cluster.Status.InfrastructureReady:
log.Info("Cluster infrastructure is not ready, waiting")
conditions.MarkFalse(config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.WaitingForClusterInfrastructureReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{}, nil
// Reconcile status for machines that already have a secret reference, but our status isn't up-to-date.
// This case solves the pivoting scenario (or a backup restore) which doesn't preserve the status subresource on objects.
case configOwner.DataSecretName() != nil && (!config.Status.Ready || config.Status.DataSecretName == nil):
config.Status.Ready = true
config.Status.DataSecretName = configOwner.DataSecretName()
conditions.MarkTrue(config, bootstrapv1.DataSecretAvailableCondition)
return ctrl.Result{}, nil
// Status is ready means a config has been generated.
case config.Status.Ready:
return ctrl.Result{}, nil
}
// Note: can't use IsFalse here because we need to handle the absence of the condition as well as false.
if !conditions.IsTrue(cluster, clusterv1.ControlPlaneInitializedCondition) {
return r.handleClusterNotInitialized(ctx, scope)
}
// Every other case it's a join scenario
// Nb. in this case ClusterConfiguration and InitConfiguration should not be defined by users, but in case of misconfigurations, CABPK3s simply ignore them
// Unlock any locks that might have been set during init process
r.K3sInitLock.Unlock(ctx, cluster)
// if the .spec.cluster is missing, create a default one
if config.Spec.Cluster == nil {
log.Info("Creating default .spec.cluster")
config.Spec.Cluster = &infrabootstrapv1.Cluster{}
}
// it's a control plane join
if configOwner.IsControlPlaneMachine() {
return r.joinControlplane(ctx, scope)
}
// It's a worker join
return r.joinWorker(ctx, scope)
}
func (r *K3sConfigReconciler) handleClusterNotInitialized(ctx context.Context, scope *Scope) (_ ctrl.Result, retErr error) {
// initialize the DataSecretAvailableCondition if missing.
// this is required in order to avoid the condition's LastTransitionTime to flicker in case of errors surfacing
// using the DataSecretGeneratedFailedReason
if conditions.GetReason(scope.Config, bootstrapv1.DataSecretAvailableCondition) != bootstrapv1.DataSecretGenerationFailedReason {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, clusterv1.WaitingForControlPlaneAvailableReason, clusterv1.ConditionSeverityInfo, "")
}
// if it's NOT a control plane machine, requeue
if !scope.ConfigOwner.IsControlPlaneMachine() {
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}
// if the machine has not ClusterConfiguration and InitConfiguration, requeue
if scope.Config.Spec.ServerConfiguration == nil && scope.Config.Spec.Cluster == nil {
scope.Info("Control plane is not ready, requeing joining control planes until ready.")
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}
machine := &clusterv1.Machine{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(scope.ConfigOwner.Object, machine); err != nil {
return ctrl.Result{}, errors.Wrapf(err, "cannot convert %s to Machine", scope.ConfigOwner.GetKind())
}
// acquire the init lock so that only the first machine configured
// as control plane get processed here
// if not the first, requeue
if !r.K3sInitLock.Lock(ctx, scope.Cluster, machine) {
scope.Info("A control plane is already being initialized, requeing until control plane is ready")
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}
defer func() {
if retErr != nil {
if !r.K3sInitLock.Unlock(ctx, scope.Cluster) {
retErr = kerrors.NewAggregate([]error{retErr, errors.New("failed to unlock the kubeadm init lock")})
}
}
}()
scope.Info("Creating BootstrapData for the first control plane")
if scope.Config.Spec.ServerConfiguration == nil {
scope.Config.Spec.ServerConfiguration = &infrabootstrapv1.ServerConfiguration{}
}
// injects into config.ClusterConfiguration values from top level object
r.reconcileTopLevelObjectSettings(ctx, scope.Cluster, machine, scope.Config)
certificates := secret.NewCertificatesForInitialControlPlane()
err := certificates.LookupOrGenerate(
ctx,
r.Client,
util.ObjectKey(scope.Cluster),
*metav1.NewControllerRef(scope.Config, infrabootstrapv1.GroupVersion.WithKind("K3sConfig")),
)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.CertificatesAvailableCondition, bootstrapv1.CertificatesGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
return ctrl.Result{}, err
}
conditions.MarkTrue(scope.Config, bootstrapv1.CertificatesAvailableCondition)
t, err := r.generateAndStoreToken(ctx, scope)
if err != nil {
return ctrl.Result{}, err
}
initData, err := k3stypes.MarshalInitServerConfiguration(&scope.Config.Spec, t)
if err != nil {
scope.Error(err, "Failed to marshal server configuration")
return ctrl.Result{}, err
}
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
return ctrl.Result{}, err
}
initConfigFile := bootstrapv1.File{
Path: k3stypes.DefaultK3sConfigLocation,
Content: initData,
Owner: "root:root",
Permissions: "0640",
}
controlPlaneInput := &cloudinit.ControlPlaneInput{
BaseUserData: cloudinit.BaseUserData{
AdditionalFiles: files,
PreK3sCommands: scope.Config.Spec.PreK3sCommands,
PostK3sCommands: scope.Config.Spec.PostK3sCommands,
ConfigFile: initConfigFile,
},
Certificates: certificates,
}
bootstrapInitData, err := cloudinit.NewInitControlPlane(controlPlaneInput)
if err != nil {
scope.Error(err, "Failed to generate user data for bootstrap control plane")
return ctrl.Result{}, err
}
if err := r.storeBootstrapData(ctx, scope, bootstrapInitData); err != nil {
scope.Error(err, "Failed to store bootstrap data")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
func (r *K3sConfigReconciler) joinWorker(ctx context.Context, scope *Scope) (ctrl.Result, error) {
scope.Info("Creating BootstrapData for the worker node")
machine := &clusterv1.Machine{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(scope.ConfigOwner.Object, machine); err != nil {
return ctrl.Result{}, errors.Wrapf(err, "cannot convert %s to Machine", scope.ConfigOwner.GetKind())
}
// injects into config.Spec values from top level object
r.reconcileWorkerTopLevelObjectSettings(ctx, scope.Cluster, machine, scope.Config)
// Ensure that agentConfiguration is properly set for joining node on the current cluster.
if res, err := r.reconcileDiscovery(ctx, scope.Cluster, scope.Config); err != nil {
return ctrl.Result{}, err
} else if !res.IsZero() {
return res, nil
}
if scope.Config.Spec.AgentConfiguration == nil {
scope.Config.Spec.AgentConfiguration = &infrabootstrapv1.AgentConfiguration{}
}
joinWorkerData, err := k3stypes.MarshalJoinAgentConfiguration(&scope.Config.Spec)
if err != nil {
scope.Error(err, "Failed to marshal join configuration")
return ctrl.Result{}, err
}
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
return ctrl.Result{}, err
}
joinConfigFile := bootstrapv1.File{
Path: k3stypes.DefaultK3sConfigLocation,
Content: joinWorkerData,
Owner: "root:root",
Permissions: "0640",
}
workerJoinInput := &cloudinit.NodeInput{
BaseUserData: cloudinit.BaseUserData{
AdditionalFiles: files,
PreK3sCommands: scope.Config.Spec.PreK3sCommands,
PostK3sCommands: scope.Config.Spec.PostK3sCommands,
ConfigFile: joinConfigFile,
},
}
cloudInitData, err := cloudinit.NewNode(workerJoinInput)
if err != nil {
scope.Error(err, "Failed to generate user data for bootstrap control plane")
return ctrl.Result{}, err
}
if err := r.storeBootstrapData(ctx, scope, cloudInitData); err != nil {
scope.Error(err, "Failed to store bootstrap data")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
func (r *K3sConfigReconciler) joinControlplane(ctx context.Context, scope *Scope) (ctrl.Result, error) {
scope.Info("Creating BootstrapData for the joining control plane")
if !scope.ConfigOwner.IsControlPlaneMachine() {
return ctrl.Result{}, fmt.Errorf("%s is not a valid control plane kind, only Machine is supported", scope.ConfigOwner.GetKind())
}
if scope.Config.Spec.ServerConfiguration == nil {
scope.Config.Spec.ServerConfiguration = &infrabootstrapv1.ServerConfiguration{}
}
machine := &clusterv1.Machine{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(scope.ConfigOwner.Object, machine); err != nil {
return ctrl.Result{}, errors.Wrapf(err, "cannot convert %s to Machine", scope.ConfigOwner.GetKind())
}
// injects into config.ClusterConfiguration values from top level object
r.reconcileTopLevelObjectSettings(ctx, scope.Cluster, machine, scope.Config)
// Ensure that joinConfiguration.Discovery is properly set for joining node on the current cluster.
if res, err := r.reconcileDiscovery(ctx, scope.Cluster, scope.Config); err != nil {
return ctrl.Result{}, err
} else if !res.IsZero() {
return res, nil
}
joinData, err := k3stypes.MarshalJoinServerConfiguration(&scope.Config.Spec)
if err != nil {
scope.Error(err, "Failed to marshal join configuration")
return ctrl.Result{}, err
}
files, err := r.resolveFiles(ctx, scope.Config)
if err != nil {
conditions.MarkFalse(scope.Config, bootstrapv1.DataSecretAvailableCondition, bootstrapv1.DataSecretGenerationFailedReason, clusterv1.ConditionSeverityWarning, err.Error())
return ctrl.Result{}, err
}
joinConfigFile := bootstrapv1.File{
Path: k3stypes.DefaultK3sConfigLocation,
Content: joinData,
Owner: "root:root",
Permissions: "0640",
}
controlPlaneJoinInput := &cloudinit.ControlPlaneInput{
BaseUserData: cloudinit.BaseUserData{
AdditionalFiles: files,
PreK3sCommands: scope.Config.Spec.PreK3sCommands,
PostK3sCommands: scope.Config.Spec.PostK3sCommands,
ConfigFile: joinConfigFile,
},
}
cloudInitData, err := cloudinit.NewJoinControlPlane(controlPlaneJoinInput)
if err != nil {
scope.Error(err, "Failed to generate user data for bootstrap control plane")
return ctrl.Result{}, err
}
if err := r.storeBootstrapData(ctx, scope, cloudInitData); err != nil {
scope.Error(err, "Failed to store bootstrap data")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
func (r *K3sConfigReconciler) generateAndStoreToken(ctx context.Context, scope *Scope) (string, error) {
t, err := bootstraputil.GenerateBootstrapToken()
if err != nil {
return "", errors.Wrap(err, "unable to generate bootstrap token")
}
s := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-token", scope.Cluster.Name),
Namespace: scope.Config.Namespace,
Labels: map[string]string{
clusterv1.ClusterLabelName: scope.Cluster.Name,
},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: infrabootstrapv1.GroupVersion.String(),
Kind: "K3sConfig",
Name: scope.Config.Name,
UID: scope.Config.UID,
Controller: pointer.Bool(true),
},
},
},
Data: map[string][]byte{
"value": []byte(t),
},
Type: clusterv1.ClusterSecretType,
}
// as secret creation and scope.Config status patch are not atomic operations
// it is possible that secret creation happens but the config.Status patches are not applied
if err := r.Client.Create(ctx, s); err != nil {
if !apierrors.IsAlreadyExists(err) {
return "", errors.Wrapf(err, "failed to create token for K3sConfig %s/%s", scope.Config.Namespace, scope.Config.Name)
}
if err := r.Client.Update(ctx, s); err != nil {
return "", errors.Wrapf(err, "failed to update bootstrap token secret for K3sConfig %s/%s", scope.Config.Namespace, scope.Config.Name)
}
}
return t, nil
}
// resolveFiles maps .Spec.Files into cloudinit.Files, resolving any object references
// along the way.
func (r *K3sConfigReconciler) resolveFiles(ctx context.Context, cfg *infrabootstrapv1.K3sConfig) ([]bootstrapv1.File, error) {
collected := make([]bootstrapv1.File, 0, len(cfg.Spec.Files))
for i := range cfg.Spec.Files {
in := cfg.Spec.Files[i]
if in.ContentFrom != nil {
data, err := r.resolveSecretFileContent(ctx, cfg.Namespace, in)
if err != nil {
return nil, errors.Wrapf(err, "failed to resolve file source")
}
in.ContentFrom = nil
in.Content = string(data)
}
collected = append(collected, in)
}
return collected, nil
}
// resolveSecretFileContent returns file content fetched from a referenced secret object.
func (r *K3sConfigReconciler) resolveSecretFileContent(ctx context.Context, ns string, source bootstrapv1.File) ([]byte, error) {
s := &corev1.Secret{}
key := types.NamespacedName{Namespace: ns, Name: source.ContentFrom.Secret.Name}
if err := r.Client.Get(ctx, key, s); err != nil {
if apierrors.IsNotFound(err) {
return nil, errors.Wrapf(err, "secret not found: %s", key)
}
return nil, errors.Wrapf(err, "failed to retrieve Secret %q", key)
}
data, ok := s.Data[source.ContentFrom.Secret.Key]
if !ok {
return nil, errors.Errorf("secret references non-existent secret key: %q", source.ContentFrom.Secret.Key)
}
return data, nil
}
// storeBootstrapData creates a new secret with the data passed in as input,
// sets the reference in the configuration status and ready to true.
func (r *K3sConfigReconciler) storeBootstrapData(ctx context.Context, scope *Scope, data []byte) error {
log := ctrl.LoggerFrom(ctx)
s := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: scope.Config.Name,
Namespace: scope.Config.Namespace,
Labels: map[string]string{
clusterv1.ClusterLabelName: scope.Cluster.Name,
},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: infrabootstrapv1.GroupVersion.String(),
Kind: "K3sConfig",
Name: scope.Config.Name,
UID: scope.Config.UID,
Controller: pointer.Bool(true),
},
},
},
Data: map[string][]byte{
"value": data,
},
Type: clusterv1.ClusterSecretType,
}
// as secret creation and scope.Config status patch are not atomic operations
// it is possible that secret creation happens but the config.Status patches are not applied
if err := r.Client.Create(ctx, s); err != nil {
if !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "failed to create bootstrap data secret for K3sConfig %s/%s", scope.Config.Namespace, scope.Config.Name)
}
log.Info("bootstrap data secret for K3sConfig already exists, updating", "Secret", klog.KObj(s))
if err := r.Client.Update(ctx, s); err != nil {
return errors.Wrapf(err, "failed to update bootstrap data secret for K3sConfig %s/%s", scope.Config.Namespace, scope.Config.Name)
}
}
scope.Config.Status.DataSecretName = pointer.String(s.Name)
scope.Config.Status.Ready = true
conditions.MarkTrue(scope.Config, bootstrapv1.DataSecretAvailableCondition)
return nil
}
func (r *K3sConfigReconciler) reconcileDiscovery(ctx context.Context, cluster *clusterv1.Cluster, config *infrabootstrapv1.K3sConfig) (ctrl.Result, error) {
log := ctrl.LoggerFrom(ctx)
// if config already contains a file discovery configuration, respect it without further validations
if config.Spec.Cluster.TokenFile != "" {
return ctrl.Result{}, nil
}
// if BootstrapToken already contains an APIServerEndpoint, respect it; otherwise inject the APIServerEndpoint endpoint defined in cluster status
apiServerEndpoint := config.Spec.Cluster.Server
if apiServerEndpoint == "" {
if !cluster.Spec.ControlPlaneEndpoint.IsValid() {
log.V(1).Info("Waiting for Cluster Controller to set Cluster.Server")
return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
}
apiServerEndpoint = cluster.Spec.ControlPlaneEndpoint.String()
config.Spec.Cluster.Server = fmt.Sprintf("https://%s", apiServerEndpoint)
log.V(3).Info("Altering Cluster.Server", "Server", apiServerEndpoint)
}
// if BootstrapToken already contains a token, respect it; otherwise create a new bootstrap token for the node to join
if config.Spec.Cluster.Token == "" {
s := &corev1.Secret{}
obj := client.ObjectKey{
Namespace: config.Namespace,
Name: fmt.Sprintf("%s-token", cluster.Name),
}
if err := r.Client.Get(ctx, obj, s); err != nil {
return ctrl.Result{}, errors.Wrapf(err, "failed to get token for K3sConfig %s/%s", config.Namespace, config.Name)
}
config.Spec.Cluster.Token = string(s.Data["value"])
log.V(3).Info("Altering Cluster.Token")
}
return ctrl.Result{}, nil
}
// MachineToBootstrapMapFunc is a handler.ToRequestsFunc to be used to enqueue
// request for reconciliation of K3sConfig.
func (r *K3sConfigReconciler) MachineToBootstrapMapFunc(o client.Object) []ctrl.Request {
m, ok := o.(*clusterv1.Machine)
if !ok {
panic(fmt.Sprintf("Expected a Machine but got a %T", o))
}
var result []ctrl.Request
if m.Spec.Bootstrap.ConfigRef != nil && m.Spec.Bootstrap.ConfigRef.GroupVersionKind() == infrabootstrapv1.GroupVersion.WithKind("K3sConfig") {
name := client.ObjectKey{Namespace: m.Namespace, Name: m.Spec.Bootstrap.ConfigRef.Name}
result = append(result, ctrl.Request{NamespacedName: name})
}
return result
}
// MachinePoolToBootstrapMapFunc is a handler.ToRequestsFunc to be used to enqueue
// request for reconciliation of K3sConfig.
func (r *K3sConfigReconciler) MachinePoolToBootstrapMapFunc(o client.Object) []ctrl.Request {
m, ok := o.(*expv1.MachinePool)
if !ok {
panic(fmt.Sprintf("Expected a MachinePool but got a %T", o))
}
var result []ctrl.Request
configRef := m.Spec.Template.Spec.Bootstrap.ConfigRef
if configRef != nil && configRef.GroupVersionKind().GroupKind() == infrabootstrapv1.GroupVersion.WithKind("K3sConfig").GroupKind() {
name := client.ObjectKey{Namespace: m.Namespace, Name: configRef.Name}
result = append(result, ctrl.Request{NamespacedName: name})
}
return result
}
// ClusterToK3sConfigs is a handler.ToRequestsFunc to be used to enqueue
// requests for reconciliation of K3sConfig.
func (r *K3sConfigReconciler) ClusterToK3sConfigs(o client.Object) []ctrl.Request {
var result []ctrl.Request
c, ok := o.(*clusterv1.Cluster)
if !ok {
panic(fmt.Sprintf("Expected a Cluster but got a %T", o))
}
selectors := []client.ListOption{
client.InNamespace(c.Namespace),
client.MatchingLabels{
clusterv1.ClusterLabelName: c.Name,
},
}
machineList := &clusterv1.MachineList{}
if err := r.Client.List(context.TODO(), machineList, selectors...); err != nil {
return nil
}
for _, m := range machineList.Items {
if m.Spec.Bootstrap.ConfigRef != nil &&
m.Spec.Bootstrap.ConfigRef.GroupVersionKind().GroupKind() == infrabootstrapv1.GroupVersion.WithKind("K3sConfig").GroupKind() {
name := client.ObjectKey{Namespace: m.Namespace, Name: m.Spec.Bootstrap.ConfigRef.Name}
result = append(result, ctrl.Request{NamespacedName: name})
}
}
if feature.Gates.Enabled(feature.MachinePool) {
machinePoolList := &expv1.MachinePoolList{}
if err := r.Client.List(context.TODO(), machinePoolList, selectors...); err != nil {
return nil
}
for _, mp := range machinePoolList.Items {
if mp.Spec.Template.Spec.Bootstrap.ConfigRef != nil &&
mp.Spec.Template.Spec.Bootstrap.ConfigRef.GroupVersionKind().GroupKind() == infrabootstrapv1.GroupVersion.WithKind("K3sConfig").GroupKind() {
name := client.ObjectKey{Namespace: mp.Namespace, Name: mp.Spec.Template.Spec.Bootstrap.ConfigRef.Name}
result = append(result, ctrl.Request{NamespacedName: name})
}
}
}
return result
}
// reconcileTopLevelObjectSettings injects into config.ClusterConfiguration values from top level objects like cluster and machine.
// The implementation func respect user provided config values, but in case some of them are missing, values from top level objects are used.
func (r *K3sConfigReconciler) reconcileTopLevelObjectSettings(ctx context.Context, cluster *clusterv1.Cluster, machine *clusterv1.Machine, config *infrabootstrapv1.K3sConfig) {
log := ctrl.LoggerFrom(ctx)
// If there are no Network settings defined in ClusterConfiguration, use ClusterNetwork settings, if defined
if cluster.Spec.ClusterNetwork != nil {
if config.Spec.ServerConfiguration.Networking.ClusterDomain == "" && cluster.Spec.ClusterNetwork.ServiceDomain != "" {
config.Spec.ServerConfiguration.Networking.ClusterDomain = cluster.Spec.ClusterNetwork.ServiceDomain
log.V(3).Info("Altering ServerConfiguration.Networking.ClusterDomain", "ClusterDomain", config.Spec.ServerConfiguration.Networking.ClusterDomain)
}
if config.Spec.ServerConfiguration.Networking.ServiceCIDR == "" &&
cluster.Spec.ClusterNetwork.Services != nil &&
len(cluster.Spec.ClusterNetwork.Services.CIDRBlocks) > 0 {
config.Spec.ServerConfiguration.Networking.ServiceCIDR = cluster.Spec.ClusterNetwork.Services.String()
log.V(3).Info("Altering ServerConfiguration.Networking.ServiceCIDR", "ServiceCIDR", config.Spec.ServerConfiguration.Networking.ServiceCIDR)
}
if config.Spec.ServerConfiguration.Networking.ClusterCIDR == "" &&
cluster.Spec.ClusterNetwork.Pods != nil &&
len(cluster.Spec.ClusterNetwork.Pods.CIDRBlocks) > 0 {
config.Spec.ServerConfiguration.Networking.ClusterCIDR = cluster.Spec.ClusterNetwork.Pods.String()
log.V(3).Info("Altering ServerConfiguration.Networking.ClusterCIDR", "ClusterCIDR", config.Spec.ServerConfiguration.Networking.ClusterCIDR)
}
}
// If there are no Version settings defined, use Version from machine, if defined
if config.Spec.Version == "" && machine.Spec.Version != nil {
config.Spec.Version = *machine.Spec.Version
log.V(3).Info("Altering Spec.Version", "Version", config.Spec.Version)
}
}
func (r *K3sConfigReconciler) reconcileWorkerTopLevelObjectSettings(ctx context.Context, _ *clusterv1.Cluster, machine *clusterv1.Machine, config *infrabootstrapv1.K3sConfig) {
log := ctrl.LoggerFrom(ctx)
// If there are no Version settings defined, use Version from machine, if defined
if config.Spec.Version == "" && machine.Spec.Version != nil {
config.Spec.Version = *machine.Spec.Version
log.V(3).Info("Altering Spec.Version", "Version", config.Spec.Version)
}
}

View File

@ -1,29 +0,0 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
//var (
// env *envtest.Environment
// ctx = ctrl.SetupSignalHandler()
//)
//
//func TestMain(m *testing.M) {
// os.Exit(envtest.Run(ctx, envtest.RunInput{
// M: m,
// SetupEnv: func(e *envtest.Environment) { env = e },
// }))
//}

View File

@ -1,15 +0,0 @@
/*
Copyright 2022 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

View File

@ -1,193 +0,0 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package main
package main
import (
"flag"
"fmt"
"math/rand"
"os"
"time"
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/klog/v2"
"k8s.io/klog/v2/klogr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/remote"
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
"sigs.k8s.io/cluster-api/feature"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/healthz"
infrabootstrapv1 "github.com/kubesphere/kubekey/v3/bootstrap/k3s/api/v1beta1"
"github.com/kubesphere/kubekey/v3/bootstrap/k3s/controllers"
infracontrolplanev1 "github.com/kubesphere/kubekey/v3/controlplane/k3s/api/v1beta1"
//+kubebuilder:scaffold:imports
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(clusterv1.AddToScheme(scheme))
utilruntime.Must(expv1.AddToScheme(scheme))
utilruntime.Must(infrabootstrapv1.AddToScheme(scheme))
utilruntime.Must(infracontrolplanev1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}
var (
metricsAddr string
enableLeaderElection bool
leaderElectionLeaseDuration time.Duration
leaderElectionRenewDeadline time.Duration
leaderElectionRetryPeriod time.Duration
k3sConfigConcurrency int
healthAddr string
watchFilterValue string
watchNamespace string
syncPeriod time.Duration
webhookPort int
webhookCertDir string
)
func main() {
klog.InitFlags(nil)
rand.Seed(time.Now().UnixNano())
initFlags(pflag.CommandLine)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
ctrl.SetLogger(klogr.New())
ctx := ctrl.SetupSignalHandler()
restConfig := ctrl.GetConfigOrDie()
restConfig.UserAgent = remote.DefaultClusterAPIUserAgent("cluster-api-k3s-bootstrap-manager")
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "k3s-bootstrap-manager-leader-election-capkk",
LeaderElectionResourceLock: resourcelock.LeasesResourceLock,
LeaseDuration: &leaderElectionLeaseDuration,
RenewDeadline: &leaderElectionRenewDeadline,
RetryPeriod: &leaderElectionRetryPeriod,
SyncPeriod: &syncPeriod,
ClientDisableCacheFor: []client.Object{
&corev1.ConfigMap{},
&corev1.Secret{},
},
Namespace: watchNamespace,
Port: webhookPort,
HealthProbeBindAddress: healthAddr,
CertDir: webhookCertDir,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
if err := (&controllers.K3sConfigReconciler{
Client: mgr.GetClient(),
WatchFilterValue: watchFilterValue,
}).SetupWithManager(ctx, mgr, concurrency(k3sConfigConcurrency)); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "K3sConfig")
os.Exit(1)
}
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up ready check")
os.Exit(1)
}
if err = (&infrabootstrapv1.K3sConfig{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "K3sConfig")
os.Exit(1)
}
if err = (&infrabootstrapv1.K3sConfigTemplate{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "K3sConfigTemplate")
os.Exit(1)
}
// +kubebuilder:scaffold:builder
setupLog.Info("starting manager")
if err := mgr.Start(ctx); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
func initFlags(fs *pflag.FlagSet) {
fs.StringVar(&metricsAddr, "metrics-bind-addr", "localhost:8080",
"The address the metric endpoint binds to.")
fs.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
fs.DurationVar(&leaderElectionLeaseDuration, "leader-elect-lease-duration", 15*time.Second,
"Interval at which non-leader candidates will wait to force acquire leadership (duration string)")
fs.DurationVar(&leaderElectionRenewDeadline, "leader-elect-renew-deadline", 10*time.Second,
"Duration that the leading controller manager will retry refreshing leadership before giving up (duration string)")
fs.DurationVar(&leaderElectionRetryPeriod, "leader-elect-retry-period", 2*time.Second,
"Duration the LeaderElector clients should wait between tries of actions (duration string)")
fs.StringVar(&watchNamespace, "namespace", "",
"Namespace that the controller watches to reconcile cluster-api objects. If unspecified, the controller watches for cluster-api objects across all namespaces.")
fs.StringVar(&healthAddr, "health-addr", ":9440",
"The address the health endpoint binds to.")
fs.IntVar(&k3sConfigConcurrency, "k3sconfig-concurrency", 10,
"Number of kubeadm configs to process simultaneously")
fs.DurationVar(&syncPeriod, "sync-period", 10*time.Minute,
"The minimum interval at which watched resources are reconciled (e.g. 15m)")
fs.StringVar(&watchFilterValue, "watch-filter", "",
fmt.Sprintf("Label value that the controller watches to reconcile cluster-api objects. Label key is always %s. If unspecified, the controller watches for all cluster-api objects.", clusterv1.WatchLabel))
fs.IntVar(&webhookPort, "webhook-port", 9443,
"Webhook Server port")
fs.StringVar(&webhookCertDir, "webhook-cert-dir", "/tmp/k8s-webhook-server/serving-certs/",
"Webhook cert dir, only used when webhook-port is specified.")
feature.MutableGates.AddFlag(fs)
}
func concurrency(c int) controller.Options {
return controller.Options{MaxConcurrentReconciles: c}
}

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