Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 172 additions & 2 deletions pkg/cluster/internal/kubeadm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,174 @@ conntrack:
{{end}}{{end}}
`

// ConfigTemplateBetaV4 is the kubeadm config template for API version v1beta4
const ConfigTemplateBetaV4 = `# config generated by kind
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
metadata:
name: config
kubernetesVersion: {{.KubernetesVersion}}
clusterName: "{{.ClusterName}}"
{{ if .KubeadmFeatureGates}}featureGates:
{{ range $key, $value := .KubeadmFeatureGates }}
"{{ $key }}": {{ $value }}
{{end}}{{end}}
controlPlaneEndpoint: "{{ .ControlPlaneEndpoint }}"
# on docker for mac we have to expose the api server via port forward,
# so we need to ensure the cert is valid for localhost so we can talk
# to the cluster after rewriting the kubeconfig to point to localhost
apiServer:
certSANs: [localhost, "{{.APIServerAddress}}"]
extraArgs:
- name: "runtime-config"
value: "{{ .RuntimeConfigString }}"
{{ if .FeatureGates }}
- name: "feature-gates"
value: "{{ .FeatureGatesString }}"
{{ end}}
controllerManager:
extraArgs:
{{ if .FeatureGates }}
- name: "feature-gates"
value: "{{ .FeatureGatesString }}"
{{ end }}
- name: "enable-hostpath-provisioner"
value: "true"
# configure ipv6 default addresses for IPv6 clusters
{{ if .IPv6 -}}
- name: "bind-address"
value: "::"
{{- end }}
scheduler:
extraArgs:
{{ if .FeatureGates }}
- name: "feature-gates"
value: "{{ .FeatureGatesString }}"
{{ end }}
# configure ipv6 default addresses for IPv6 clusters
{{ if .IPv6 -}}
- name: "bind-address"
value: "::"
{{- end }}
networking:
podSubnet: "{{ .PodSubnet }}"
serviceSubnet: "{{ .ServiceSubnet }}"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
metadata:
name: config
# we use a well know token for TLS bootstrap
bootstrapTokens:
- token: "{{ .Token }}"
# we use a well know port for making the API server discoverable inside docker network.
# from the host machine such port will be accessible via a random local port instead.
localAPIEndpoint:
advertiseAddress: "{{ .AdvertiseAddress }}"
bindPort: {{.APIBindPort}}
nodeRegistration:
criSocket: "unix:///run/containerd/containerd.sock"
kubeletExtraArgs:
- name: "node-ip"
value: "{{ .NodeAddress }}"
- name: "provider-id"
value: "kind://{{.NodeProvider}}/{{.ClusterName}}/{{.NodeName}}"
- name: "node-labels"
value: "{{ .NodeLabels }}"
{{ if .InitSkipPhases -}}
skipPhases:
{{- range $phase := .InitSkipPhases }}
- "{{ $phase }}"
{{- end }}
{{- end }}
---
# no-op entry that exists solely so it can be patched
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
metadata:
name: config
{{ if .ControlPlane -}}
controlPlane:
localAPIEndpoint:
advertiseAddress: "{{ .AdvertiseAddress }}"
bindPort: {{.APIBindPort}}
{{- end }}
nodeRegistration:
criSocket: "unix:///run/containerd/containerd.sock"
kubeletExtraArgs:
- name: "node-ip"
value: "{{ .NodeAddress }}"
- name: "provider-id"
value: "kind://{{.NodeProvider}}/{{.ClusterName}}/{{.NodeName}}"
- name: "node-labels"
value: "{{ .NodeLabels }}"
discovery:
bootstrapToken:
apiServerEndpoint: "{{ .ControlPlaneEndpoint }}"
token: "{{ .Token }}"
unsafeSkipCAVerification: true
{{ if .JoinSkipPhases -}}
skipPhases:
{{ range $phase := .JoinSkipPhases -}}
- "{{ $phase }}"
{{- end }}
{{- end }}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
metadata:
name: config
cgroupDriver: {{ .CgroupDriver }}
cgroupRoot: /kubelet
failSwapOn: false
# configure ipv6 addresses in IPv6 mode
{{ if .IPv6 -}}
address: "::"
healthzBindAddress: "::"
{{- end }}
# disable disk resource management by default
# kubelet will see the host disk that the inner container runtime
# is ultimately backed by and attempt to recover disk space. we don't want that.
imageGCHighThresholdPercent: 100
evictionHard:
nodefs.available: "0%"
nodefs.inodesFree: "0%"
imagefs.available: "0%"
{{if .FeatureGates}}featureGates:
{{ range $index, $gate := .SortedFeatureGates }}
"{{ $gate.Name }}": {{ $gate.Value }}
{{end}}{{end}}
{{if ne .KubeProxyMode "none"}}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
metadata:
name: config
mode: "{{ .KubeProxyMode }}"
{{if .FeatureGates}}featureGates:
{{ range $index, $gate := .SortedFeatureGates }}
"{{ $gate.Name }}": {{ $gate.Value }}
{{end}}{{end}}
iptables:
minSyncPeriod: 1s
conntrack:
# Skip setting sysctl value "net.netfilter.nf_conntrack_max"
# It is a global variable that affects other namespaces
maxPerCore: 0
# Set sysctl value "net.netfilter.nf_conntrack_tcp_be_liberal"
# for nftables proxy (theoretically for kernels older than 6.1)
# xref: https://github.com/kubernetes/kubernetes/issues/117924
{{if and (eq .KubeProxyMode "nftables") (not .RootlessProvider)}}
tcpBeLiberal: true
{{end}}
{{if .RootlessProvider}}
# Skip setting "net.netfilter.nf_conntrack_tcp_timeout_established"
tcpEstablishedTimeout: 0s
# Skip setting "net.netfilter.nf_conntrack_tcp_timeout_close"
tcpCloseWaitTimeout: 0s
{{end}}{{end}}
`

// Config returns a kubeadm config generated from config data, in particular
// the kubernetes version
func Config(data ConfigData) (config string, err error) {
Expand All @@ -502,8 +670,10 @@ func Config(data ConfigData) (config string, err error) {
}

// assume the latest API version, then fallback if the k8s version is too low
templateSource := ConfigTemplateBetaV3
if ver.LessThan(version.MustParseSemantic("v1.23.0")) {
templateSource := ConfigTemplateBetaV4
if ver.LessThan(version.MustParseSemantic("v1.35.0")) {
templateSource = ConfigTemplateBetaV3
} else if ver.LessThan(version.MustParseSemantic("v1.23.0")) {
templateSource = ConfigTemplateBetaV2
}

Expand Down
Loading