From bb7b580ca96b1a4889dee1d200ec01de408b688b Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 1 Jun 2023 10:41:47 +0000 Subject: [PATCH 01/10] Helper to get correct node name for windows Signed-off-by: Mikhail Sakhnov --- go.mod | 1 + go.sum | 2 + pkg/autopilot/common/hostname.go | 5 +- .../controller/controllersleasecounter.go | 5 +- .../worker/calico_installer_windows.go | 294 +++--------------- pkg/component/worker/kubelet.go | 25 +- pkg/component/worker/kubeproxy_windows.go | 3 +- pkg/component/worker/utils.go | 4 +- pkg/node/nodehostname.go | 55 ++++ pkg/node/nodehostname_test.go | 66 ++++ 10 files changed, 181 insertions(+), 279 deletions(-) create mode 100644 pkg/node/nodehostname.go create mode 100644 pkg/node/nodehostname_test.go diff --git a/go.mod b/go.mod index f548795be1c4..42ab3086d577 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/briandowns/spinner v1.19.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/carlmjohnson/requests v0.23.4 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cilium/ebpf v0.9.1 // indirect diff --git a/go.sum b/go.sum index cf828368ca9b..8f4ad8d290e8 100644 --- a/go.sum +++ b/go.sum @@ -119,6 +119,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= +github.com/carlmjohnson/requests v0.23.4 h1:AxcvapfB9RPXLSyvAHk9YJoodQ43ZjzNHj6Ft3tQGdg= +github.com/carlmjohnson/requests v0.23.4/go.mod h1:Qzp6tW4DQyainPP+tGwiJTzwxvElTIKm0B191TgTtOA= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= diff --git a/pkg/autopilot/common/hostname.go b/pkg/autopilot/common/hostname.go index 37908dfcf1fe..26f3d07a9f96 100644 --- a/pkg/autopilot/common/hostname.go +++ b/pkg/autopilot/common/hostname.go @@ -17,7 +17,7 @@ package common import ( "os" - nodeutil "k8s.io/component-helpers/node/util" + "github.com/k0sproject/k0s/pkg/node" ) const ( @@ -28,6 +28,5 @@ const ( // for an AUTOPILOT_HOSTNAME environment variable, falling back to whatever the OS // returns. func FindEffectiveHostname() (string, error) { - // nodeutil.GetHostname will return the "object name safe" hostname, overridden via the env var if non-empty value - return nodeutil.GetHostname(os.Getenv(envAutopilotHostname)) + return node.GetNodename(os.Getenv(envAutopilotHostname)) } diff --git a/pkg/component/controller/controllersleasecounter.go b/pkg/component/controller/controllersleasecounter.go index 716b22ed724b..98448a671b51 100644 --- a/pkg/component/controller/controllersleasecounter.go +++ b/pkg/component/controller/controllersleasecounter.go @@ -24,8 +24,7 @@ import ( "github.com/k0sproject/k0s/pkg/component/manager" kubeutil "github.com/k0sproject/k0s/pkg/kubernetes" "github.com/k0sproject/k0s/pkg/leaderelection" - - nodeutil "k8s.io/component-helpers/node/util" + "github.com/k0sproject/k0s/pkg/node" "github.com/sirupsen/logrus" ) @@ -58,7 +57,7 @@ func (l *K0sControllersLeaseCounter) Start(ctx context.Context) error { // hostname used to make the lease names be clear to which controller they belong to // follow kubelet convention for naming so we e.g. use lowercase hostname etc. - holderIdentity, err := nodeutil.GetHostname("") + holderIdentity, err := node.GetNodename("") if err != nil { return nil } diff --git a/pkg/component/worker/calico_installer_windows.go b/pkg/component/worker/calico_installer_windows.go index 66d52f1d8e8f..deb27dc68444 100644 --- a/pkg/component/worker/calico_installer_windows.go +++ b/pkg/component/worker/calico_installer_windows.go @@ -18,18 +18,9 @@ package worker import ( "context" - "crypto/tls" - "crypto/x509" "fmt" - "io" - "net/http" "os" - "github.com/k0sproject/k0s/internal/pkg/file" - "github.com/k0sproject/k0s/pkg/token" - - "k8s.io/client-go/tools/clientcmd" - "github.com/k0sproject/k0s/pkg/component/manager" "github.com/sirupsen/logrus" ) @@ -44,7 +35,7 @@ type CalicoInstaller struct { var _ manager.Component = (*CalicoInstaller)(nil) func (c CalicoInstaller) Init(_ context.Context) error { - path := "C:\\bootstrap.ps1" + // path := "C:\\bootstrap.ps1" if err := os.Mkdir("C:\\CalicoWindows", 777); err != nil { if os.IsExist(err) { @@ -54,62 +45,56 @@ func (c CalicoInstaller) Init(_ context.Context) error { return fmt.Errorf("can't create CalicoWindows dir: %v", err) } - if err := file.WriteContentAtomically(path, []byte(installCalicoPowershell), 777); err != nil { - return fmt.Errorf("can't unpack calico installer: %v", err) - } - - if err := c.SaveKubeConfig("C:\\calico-kube-config"); err != nil { - return fmt.Errorf("can't get calico-kube-config: %v", err) - } + return winExecute(installCalicoPowershell) - return nil } func (c CalicoInstaller) SaveKubeConfig(path string) error { - tokenBytes, err := token.DecodeJoinToken(c.Token) - if err != nil { - return fmt.Errorf("failed to decode token: %v", err) - } - clientConfig, err := clientcmd.NewClientConfigFromBytes(tokenBytes) - if err != nil { - return fmt.Errorf("failed to create api client config: %v", err) - } - config, err := clientConfig.ClientConfig() - if err != nil { - return fmt.Errorf("failed to create api client config: %v", err) - } - - ca := x509.NewCertPool() - ca.AppendCertsFromPEM(config.CAData) - tlsConfig := &tls.Config{ - InsecureSkipVerify: false, - RootCAs: ca, - } - tr := &http.Transport{TLSClientConfig: tlsConfig} - client := http.Client{Transport: tr} - - req, err := http.NewRequest(http.MethodGet, c.APIAddress+"/v1beta1/calico/kubeconfig", nil) - if err != nil { - return fmt.Errorf("can't create http request: %v", err) - } - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.BearerToken)) - resp, err := client.Do(req) - if err != nil { - return fmt.Errorf("can't download kubelet config for calico: %v", err) - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("unexpected response status: %s", resp.Status) - } - b, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("can't read response body: %v", err) - } - if err := file.WriteContentAtomically(path, b, 0700); err != nil { - return fmt.Errorf("can't save kubeconfig for calico: %v", err) - } - posh := NewPowershell() - return posh.execute(fmt.Sprintf("C:\\bootstrap.ps1 -ServiceCidr \"%s\" -DNSServerIPs \"%s\"", c.CIDRRange, c.ClusterDNS)) + return nil + // tokenBytes, err := token.DecodeJoinToken(c.Token) + // if err != nil { + // return fmt.Errorf("failed to decode token: %v", err) + // } + // clientConfig, err := clientcmd.NewClientConfigFromBytes(tokenBytes) + // if err != nil { + // return fmt.Errorf("failed to create api client config: %v", err) + // } + // config, err := clientConfig.ClientConfig() + // if err != nil { + // return fmt.Errorf("failed to create api client config: %v", err) + // } + + // ca := x509.NewCertPool() + // ca.AppendCertsFromPEM(config.CAData) + // tlsConfig := &tls.Config{ + // InsecureSkipVerify: false, + // RootCAs: ca, + // } + // tr := &http.Transport{TLSClientConfig: tlsConfig} + // client := http.Client{Transport: tr} + + // req, err := http.NewRequest(http.MethodGet, c.APIAddress+"/v1beta1/calico/kubeconfig", nil) + // if err != nil { + // return fmt.Errorf("can't create http request: %v", err) + // } + // req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.BearerToken)) + // resp, err := client.Do(req) + // if err != nil { + // return fmt.Errorf("can't download kubelet config for calico: %v", err) + // } + // defer resp.Body.Close() + // if resp.StatusCode != http.StatusOK { + // return fmt.Errorf("unexpected response status: %s", resp.Status) + // } + // b, err := io.ReadAll(resp.Body) + // if err != nil { + // return fmt.Errorf("can't read response body: %v", err) + // } + // if err := file.WriteContentAtomically(path, b, 0700); err != nil { + // return fmt.Errorf("can't save kubeconfig for calico: %v", err) + // } + // posh := NewPowershell() + // return posh.execute(fmt.Sprintf("C:\\bootstrap.ps1 -ServiceCidr \"%s\" -DNSServerIPs \"%s\"", c.CIDRRange, c.ClusterDNS)) } func (c CalicoInstaller) Start(_ context.Context) error { @@ -127,190 +112,5 @@ func (c CalicoInstaller) Stop() error { // the original script is done by Tigera, Inc // and can be accessed over the web on https://docs.projectcalico.org/scripts/install-calico-windows.ps1 const installCalicoPowershell = ` -# Copyright 2020 k0s 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. - -Param( - [parameter(Mandatory = $false)] $ReleaseBaseURL="https://github.com/projectcalico/calico/releases/download/v3.17.0/", - [parameter(Mandatory = $false)] $ReleaseFile="calico-windows-v3.17.0.zip", - [parameter(Mandatory = $false)] $Datastore="kubernetes", - [parameter(Mandatory = $false)] $ServiceCidr="10.96.0.0/12", - [parameter(Mandatory = $false)] $DNSServerIPs="10.96.0.10" -) - -function DownloadFiles() -{ - Write-Host "Downloading CNI binaries" - md $BaseDir\cni\config -ErrorAction Ignore - DownloadFile -Url "https://github.com/Microsoft/SDN/raw/master/Kubernetes/flannel/l2bridge/cni/host-local.exe" -Destination $BaseDir\cni\host-local.exe - - Write-Host "Downloading Windows Kubernetes scripts" - DownloadFile -Url https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/hns.psm1 -Destination $BaseDir\hns.psm1 - DownloadFile -Url https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/InstallImages.ps1 -Destination $BaseDir\InstallImages.ps1 - DownloadFile -Url https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/Dockerfile -Destination $BaseDir\Dockerfile -} - -function PrepareDockerFile() -{ - # Update Dockerfile for windows - $OSInfo = (Get-ComputerInfo | select WindowsVersion, OsBuildNumber) - $OSNumber = $OSInfo.WindowsVersion - $ExistOSNumber = cat c:\k\Dockerfile | findstr.exe $OSNumber - if (!$ExistOSNumber) - { - Write-Host "Update dockerfile for $OSNumber" - - $ImageWithOSNumber = "nanoserver:" + $OSNumber - (get-content c:\k\Dockerfile) | foreach-object {$_ -replace "nanoserver", "$ImageWithOSNumber"} | set-content c:\k\Dockerfile - } -} - -function PrepareKubernetes() -{ - DownloadFiles - ipmo C:\k\hns.psm1 - -} - -function GetPlatformType() -{ - # EC2 - $restError = $null - Try { - $awsNodeName=Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/local-hostname -ErrorAction Ignore - } Catch { - $restError = $_ - } - if ($restError -eq $null) { - return ("ec2") - } - - return ("bare-metal") -} - -function GetBackendType() -{ - return ("vxlan") -} - -function GetCalicoNamespace() { - - return ("kube-system") -} - -function GetCalicoKubeConfig() -{ - param( - [parameter(Mandatory=$true)] $CalicoNamespace, - [parameter(Mandatory=$false)] $SecretName = "calico-node", - [parameter(Mandatory=$false)] $KubeConfigPath = "C:\\var\\lib\\k0s\\kubelet-bootstrap.conf" - ) - Move-Item -Path C:\\calico-kube-config -Destination C:\\CalicoWindows\calico-kube-config -} - - -function SetConfigParameters { - param( - [parameter(Mandatory=$true)] $OldString, - [parameter(Mandatory=$true)] $NewString - ) - - (Get-Content $RootDir\config.ps1).replace($OldString, $NewString) | Set-Content $RootDir\config.ps1 -Force -} - -function StartCalico() -{ - Write-Host "Start Calico for Windows..." - - pushd - cd $RootDir - .\install-calico.ps1 - popd - Write-Host "Calico for Windows Started" -} - -$BaseDir="c:\k" -$RootDir="c:\CalicoWindows" -$CalicoZip="c:\calico-windows.zip" - -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - -$helper = "$BaseDir\helper.psm1" -$helperv2 = "$BaseDir\helper.v2.psm1" -md $BaseDir -ErrorAction Ignore -if (!(Test-Path $helper)) -{ - Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/SDN/master/Kubernetes/windows/helper.psm1 -O $BaseDir\helper.psm1 -} -if (!(Test-Path $helperv2)) -{ - Invoke-WebRequest https://raw.githubusercontent.com/Microsoft/SDN/master/Kubernetes/windows/helper.v2.psm1 -O $BaseDir\helper.v2.psm1 -} -ipmo -force $helper -ipmo -force $helperv2 - -$platform=GetPlatformType - -PrepareKubernetes - -Write-Host "Download Calico for Windows release..." -DownloadFile -Url $ReleaseBaseURL/$ReleaseFile -Destination c:\calico-windows.zip - -if ((Get-Service | where Name -Like 'Calico*' | where Status -EQ Running) -NE $null) { -Write-Host "Calico services are still running. In order to re-run the installation script, stop the CalicoNode and CalicoFelix services or uninstall them by running: $RootDir\uninstall-calico.ps1" -Exit -} - -Remove-Item $RootDir -Force -Recurse -ErrorAction SilentlyContinue -Write-Host "Unzip Calico for Windows release..." -Expand-Archive $CalicoZip c:\ - -Write-Host "Setup Calico for Windows..." -SetConfigParameters -OldString '' -NewString $Datastore - - -SetConfigParameters -OldString '' -NewString $ServiceCidr -SetConfigParameters -OldString '' -NewString $DNSServerIPs - - -if ($platform -EQ "ec2") { - $awsNodeName = Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/local-hostname -ErrorAction Ignore - Write-Host "Setup Calico for Windows for AWS, node name $awsNodeName ..." - $awsNodeNameQuote = """$awsNodeName""" - SetConfigParameters -OldString '$(hostname).ToLower()' -NewString "$awsNodeNameQuote" - - $calicoNs = GetCalicoNamespace - GetCalicoKubeConfig -CalicoNamespace $calicoNs - $Backend = GetBackendType - - Write-Host "Backend networking is $Backend" - if ($Backend -EQ "bgp") { - SetConfigParameters -OldString 'CALICO_NETWORKING_BACKEND="vxlan"' -NewString 'CALICO_NETWORKING_BACKEND="windows-bgp"' - } -} -if ($platform -EQ "bare-metal") { - $calicoNs = GetCalicoNamespace - GetCalicoKubeConfig -CalicoNamespace $calicoNs - $Backend = GetBackendType - - Write-Host "Backend networking is $Backend" - if ($Backend -EQ "bgp") { - SetConfigParameters -OldString 'CALICO_NETWORKING_BACKEND="vxlan"' -NewString 'CALICO_NETWORKING_BACKEND="windows-bgp"' - } -} - -StartCalico - New-NetFirewallRule -Name KubectlExec10250 -Description "Enable kubectl exec and log" -Action Allow -LocalPort 10250 -Enabled True -DisplayName "kubectl exec 10250" -Protocol TCP -ErrorAction SilentlyContinue ` diff --git a/pkg/component/worker/kubelet.go b/pkg/component/worker/kubelet.go index bb420ecdabab..59322d84ba84 100644 --- a/pkg/component/worker/kubelet.go +++ b/pkg/component/worker/kubelet.go @@ -20,9 +20,7 @@ import ( "bufio" "context" "fmt" - "io" "net" - "net/http" "os" "path/filepath" "regexp" @@ -38,6 +36,7 @@ import ( "github.com/k0sproject/k0s/pkg/component/manager" "github.com/k0sproject/k0s/pkg/config" "github.com/k0sproject/k0s/pkg/constant" + "github.com/k0sproject/k0s/pkg/node" "github.com/k0sproject/k0s/pkg/supervisor" corev1 "k8s.io/api/core/v1" @@ -172,7 +171,7 @@ func (k *Kubelet) Start(ctx context.Context) error { } if runtime.GOOS == "windows" { - node, err := getNodeName(ctx) + node, err := node.GetNodename("") if err != nil { return fmt.Errorf("can't get hostname: %v", err) } @@ -273,26 +272,6 @@ func (k *Kubelet) prepareLocalKubeletConfig(kubeletConfigData kubeletConfig) (st return string(preparedConfigBytes), nil } -const awsMetaInformationURI = "http://169.254.169.254/latest/meta-data/local-hostname" - -func getNodeName(ctx context.Context) (string, error) { - req, err := http.NewRequest("GET", awsMetaInformationURI, nil) - if err != nil { - return "", err - } - req = req.WithContext(ctx) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return os.Hostname() - } - defer resp.Body.Close() - h, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("can't read aws hostname: %v", err) - } - return string(h), nil -} - func parseTaint(st string) (corev1.Taint, error) { var taint corev1.Taint diff --git a/pkg/component/worker/kubeproxy_windows.go b/pkg/component/worker/kubeproxy_windows.go index 3953bce7e901..ce74a359a073 100644 --- a/pkg/component/worker/kubeproxy_windows.go +++ b/pkg/component/worker/kubeproxy_windows.go @@ -25,6 +25,7 @@ import ( "github.com/k0sproject/k0s/pkg/component/manager" "github.com/k0sproject/k0s/pkg/config" "github.com/k0sproject/k0s/pkg/constant" + "github.com/k0sproject/k0s/pkg/node" "github.com/k0sproject/k0s/pkg/supervisor" ) @@ -43,7 +44,7 @@ func (k KubeProxy) Init(_ context.Context) error { } func (k KubeProxy) Start(ctx context.Context) error { - node, err := getNodeName(ctx) + node, err := node.GetNodename("") if err != nil { return fmt.Errorf("can't get hostname: %v", err) } diff --git a/pkg/component/worker/utils.go b/pkg/component/worker/utils.go index 707ce4555061..8191dddba4b2 100644 --- a/pkg/component/worker/utils.go +++ b/pkg/component/worker/utils.go @@ -30,12 +30,12 @@ import ( "github.com/k0sproject/k0s/internal/pkg/flags" "github.com/k0sproject/k0s/pkg/config" "github.com/k0sproject/k0s/pkg/constant" + "github.com/k0sproject/k0s/pkg/node" "github.com/k0sproject/k0s/pkg/token" apitypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - nodeutil "k8s.io/component-helpers/node/util" "k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap" "github.com/avast/retry-go" @@ -136,7 +136,7 @@ func BootstrapKubeletKubeconfig(ctx context.Context, k0sVars *config.CfgVars, wo // path anyways in kubelet. So it's safe to assume that the following code // exactly matches the behavior of kubelet. - nodeName, err := nodeutil.GetHostname(flags.Split(workerOpts.KubeletExtraArgs)["--hostname-override"]) + nodeName, err := node.GetNodename(flags.Split(workerOpts.KubeletExtraArgs)["--hostname-override"]) if err != nil { return fmt.Errorf("failed to determine node name: %w", err) } diff --git a/pkg/node/nodehostname.go b/pkg/node/nodehostname.go new file mode 100644 index 000000000000..54d166d649a4 --- /dev/null +++ b/pkg/node/nodehostname.go @@ -0,0 +1,55 @@ +package node + +import ( + "context" + "fmt" + "runtime" + "time" + + "github.com/carlmjohnson/requests" + nodeutil "k8s.io/component-helpers/node/util" +) + +// GetNodename returns the node name for the node taking OS, cloud provider and override into account +func GetNodename(override string) (string, error) { + if runtime.GOOS == "windows" { + return getNodeNameWindows(override, awsMetaInformationHostnameURL) + } + nodeName, err := nodeutil.GetHostname(override) + if err != nil { + return "", fmt.Errorf("failed to determine node name: %w", err) + } + return nodeName, nil +} + +const awsMetaInformationHostnameURL = "http://169.254.169.254/latest/meta-data/local-hostname" + +func getHostnameFromAwsMeta(url string) string { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + + var s string + err := requests. + URL(url). + ToString(&s). + Fetch(ctx) + // if status code is 2XX and no transport error, we assume we are running on ec2 + if err != nil { + return "" + } + return s +} + +func getNodeNameWindows(override string, metadataUrl string) (string, error) { + // if we have explicit hostnameOverride, we use it as is even on windows + if override != "" { + return nodeutil.GetHostname(override) + } + + // we need to check if we have EC2 dns name available + if h := getHostnameFromAwsMeta(metadataUrl); h != "" { + return h, nil + } + // otherwise we use the k8s hostname helper + return nodeutil.GetHostname(override) +} diff --git a/pkg/node/nodehostname_test.go b/pkg/node/nodehostname_test.go new file mode 100644 index 000000000000..34ef705458cd --- /dev/null +++ b/pkg/node/nodehostname_test.go @@ -0,0 +1,66 @@ +package node + +import ( + "net/http" + "testing" + + "github.com/davecgh/go-spew/spew" + "github.com/stretchr/testify/require" + nodeutil "k8s.io/component-helpers/node/util" +) + +func TestGetNodename(t *testing.T) { + + startFakeMetadataServer(":8080") + t.Run("should_always_return_override_if_given", func(t *testing.T) { + name, err := GetNodename("override") + require.Equal(t, "override", name) + require.Nil(t, err) + }) + + t.Run("should_call_kubernetes_hostname_helper_on_linux", func(t *testing.T) { + name, err := GetNodename("") + name2, err2 := nodeutil.GetHostname("") + require.Equal(t, name, name2) + require.Nil(t, err) + require.Nil(t, err2) + }) + + t.Run("windows_no_metadata_service_available", func(t *testing.T) { + name, err := getNodeNameWindows("", "http://localhost:8080") + nodename, err2 := nodeutil.GetHostname("") + require.Nil(t, err) + require.Nil(t, err2) + require.Equal(t, nodename, name) + }) + + t.Run("windows_metadata_service_is_broken", func(t *testing.T) { + name, err := getNodeNameWindows("", "http://localhost:8080/not-found") + nodename, err2 := nodeutil.GetHostname("") + require.Nil(t, err) + require.Nil(t, err2) + require.Equal(t, nodename, name) + }) + + t.Run("windows_metadata_service_is_available", func(t *testing.T) { + name, err := getNodeNameWindows("", "http://localhost:8080/latest/meta-data/local-hostname") + nodename, err2 := nodeutil.GetHostname("") + require.Nil(t, err) + require.Nil(t, err2) + spew.Dump(name, nodename, err, err2) + require.NotEqual(t, nodename, name) + }) +} + +func startFakeMetadataServer(listenOn string) { + go func() { + http.HandleFunc("/latest/meta-data/local-hostname", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("some-hostname-from-metadata")) + w.WriteHeader(http.StatusOK) + }) + http.HandleFunc("/not-found", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + }) + http.ListenAndServe(listenOn, nil) + }() +} From 8f624036dcb6dd7656ef9fe6bdd8a4f296610404 Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 8 Jun 2023 09:42:34 +0000 Subject: [PATCH 02/10] Windows stack skeleton Signed-off-by: Mikhail Sakhnov --- cmd/controller/controller.go | 5 +- go.mod | 4 +- pkg/component/controller/calico.go | 2 +- .../controller/calicowindowscontroller.go | 181 ++++++++++++++++++ .../controller/extensions_controller.go | 2 +- ...taller_windows.go => nodesetup_windows.go} | 38 ++-- pkg/component/worker/utils_windows.go | 10 +- pkg/constant/constant_shared.go | 1 + .../ConfigMap/calico-windows-config.yaml | 26 +++ .../DaemonSet/calico-windows-node.yaml | 121 ++++++++++++ .../calico-ipamconfig-windows.yaml} | 5 +- 11 files changed, 371 insertions(+), 24 deletions(-) create mode 100644 pkg/component/controller/calicowindowscontroller.go rename pkg/component/worker/{calico_installer_windows.go => nodesetup_windows.go} (73%) create mode 100644 static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml create mode 100644 static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml rename static/manifests/{calico/IPAMConfig/ipamconfig.yaml => calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml} (63%) diff --git a/cmd/controller/controller.go b/cmd/controller/controller.go index 2348f331f607..59cc351affc3 100644 --- a/cmd/controller/controller.go +++ b/cmd/controller/controller.go @@ -417,7 +417,7 @@ func (c *command) start(ctx context.Context) error { return fmt.Errorf("failed to create calico_init manifests saver: %w", err) } clusterComponents.Add(ctx, controller.NewCalico(c.K0sVars, calicoInitSaver, calicoSaver)) - + clusterComponents.Add(ctx, controller.NewWindowsStackComponent(c.K0sVars, adminClientFactory, calicoSaver)) kubeRouterSaver, err := controller.NewManifestsSaver("kuberouter", c.K0sVars.DataDir) if err != nil { return fmt.Errorf("failed to create kuberouter manifests saver: %w", err) @@ -458,6 +458,9 @@ func (c *command) start(ctx context.Context) error { clusterComponents.Add(ctx, controller.NewNodeRole(c.K0sVars, adminClientFactory)) } + if !slices.Contains(c.DisableComponents, constant.WindowsNodeComponentName) { + } + if enableKonnectivity { clusterComponents.Add(ctx, &controller.Konnectivity{ SingleNode: c.SingleNode, diff --git a/go.mod b/go.mod index 42ab3086d577..d4d85381dd4c 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,11 @@ require ( github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 github.com/avast/retry-go v3.0.0+incompatible github.com/bombsimon/logrusr/v2 v2.0.1 + github.com/carlmjohnson/requests v0.23.4 github.com/cavaliergopher/grab/v3 v3.0.1 github.com/cloudflare/cfssl v1.6.4 github.com/containerd/containerd v1.7.5 + github.com/davecgh/go-spew v1.1.1 github.com/denisbrodbeck/machineid v1.0.1 github.com/estesp/manifest-tool/v2 v2.0.8 github.com/evanphx/json-patch v5.6.0+incompatible @@ -100,7 +102,6 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/briandowns/spinner v1.19.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/carlmjohnson/requests v0.23.4 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cilium/ebpf v0.9.1 // indirect @@ -119,7 +120,6 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/daviddengcn/go-colortext v1.0.0 // indirect github.com/docker/cli v23.0.5+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect diff --git a/pkg/component/controller/calico.go b/pkg/component/controller/calico.go index efd3241a1899..ff0c9239dfac 100644 --- a/pkg/component/controller/calico.go +++ b/pkg/component/controller/calico.go @@ -164,7 +164,7 @@ func (c *Calico) processConfigChanges(newConfig calicoConfig) error { output := bytes.NewBuffer([]byte{}) contents, err := static.Asset(fmt.Sprintf("manifests/calico/%s/%s", dir, filename)) if err != nil { - return fmt.Errorf("failed to unpack manifest %s: %w", filename, err) + return fmt.Errorf("can't find manifest %s: %w", manifestName, err) } tw := templatewriter.TemplateWriter{ diff --git a/pkg/component/controller/calicowindowscontroller.go b/pkg/component/controller/calicowindowscontroller.go new file mode 100644 index 000000000000..c6f13f58013e --- /dev/null +++ b/pkg/component/controller/calicowindowscontroller.go @@ -0,0 +1,181 @@ +/* +Copyright 2023 k0s 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 controller + +import ( + "bytes" + "context" + "fmt" + "path/filepath" + "reflect" + "strings" + "time" + + "github.com/davecgh/go-spew/spew" + "github.com/k0sproject/k0s/internal/pkg/templatewriter" + "github.com/k0sproject/k0s/static" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1" + "github.com/k0sproject/k0s/pkg/constant" + k8sutil "github.com/k0sproject/k0s/pkg/kubernetes" +) + +// WindowsStackComponent implements the component interface +// controller unpacks windows manifests +// if windows nodes are present in the cluster +type WindowsStackComponent struct { + log logrus.FieldLogger + + kubeClientFactory k8sutil.ClientFactoryInterface + k0sVars constant.CfgVars + saver manifestsSaver + prevRenderingContext windowsStackRenderingContext +} + +type windowsStackRenderingContext struct{} + +// NewWindowsStackComponent creates new WindowsStackComponent reconciler +func NewWindowsStackComponent(k0sVars constant.CfgVars, clientFactory k8sutil.ClientFactoryInterface, saver manifestsSaver) *WindowsStackComponent { + return &WindowsStackComponent{ + log: logrus.WithFields(logrus.Fields{"component": "WindowsNodeController"}), + saver: saver, + kubeClientFactory: clientFactory, + k0sVars: k0sVars, + } +} + +// Init no-op +func (n *WindowsStackComponent) Init(_ context.Context) error { + return nil +} + +// Run checks and adds labels +func (n *WindowsStackComponent) Start(ctx context.Context) error { + + go func() { + timer := time.NewTicker(1 * time.Minute) + defer timer.Stop() + for { + select { + case <-ctx.Done(): + return + case <-timer.C: + if err := n.handleWindowsNode(ctx, n.prevRenderingContext); err != nil { + n.log.Errorf("failed to handle windows node: %v", err) + } + } + } + }() + + return nil +} + +func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context, cfg windowsStackRenderingContext) error { + client, err := n.kubeClientFactory.GetClient() + if err != nil { + return fmt.Errorf("failed to get kube client: %v", err) + } + nodes, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{ + LabelSelector: "kubernetes.io/os=windows", + }) + if err != nil { + n.log.Errorf("failed to get node list: %v", err) + return fmt.Errorf("failed to get node list: %v", err) + } + + if len(nodes.Items) == 0 { + // TODO: may be delete windows stack if it exists + return nil + } + + n.log.Infof("found %d windows nodes", len(nodes.Items)) + if err := n.createWindowsStack(n.prevRenderingContext); err != nil { + n.log.Errorf("failed to create windows stack: %v", err) + return fmt.Errorf("failed to create windows stack: %v", err) + } else { + n.log.Infof("successfully created windows stack") + } + return nil +} + +func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.ClusterConfig) error { + if cfg.Spec.Network.Provider != "calico" { + return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + } + + existingCNI := existingCNIProvider(n.k0sVars.ManifestsDir) + if existingCNI != "" && existingCNI != constant.CNIProviderCalico { + return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + } + newConfig := n.makeCalicoRenderingContext(cfg) + if !reflect.DeepEqual(newConfig, n.prevRenderingContext) { + n.prevRenderingContext = newConfig + } + + return nil +} +func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) windowsStackRenderingContext { + return windowsStackRenderingContext{} +} + +// Stop no-op +func (n *WindowsStackComponent) Stop() error { + return nil +} + +// createWindowsStack creates windows stack + +func (n *WindowsStackComponent) createWindowsStack(newConfig windowsStackRenderingContext) error { + manifestDirectories, err := static.AssetDir("manifests/windows") + if err != nil { + return fmt.Errorf("error retrieving manifests: %v", err) + } + spew.Dump(manifestDirectories) + for _, dir := range manifestDirectories { + manifestPaths, err := static.AssetDir(fmt.Sprintf("manifests/windows/%s", dir)) + if err != nil { + return fmt.Errorf("error retrieving manifests: %s. will retry", err.Error()) + } + tryAndLog := func(name string, e error) { + n.log.Debugf("writing manifest %s", name) + if e != nil { + n.log.Errorf("failed to write manifest %s: %v, will re-try", name, e) + } + } + + for _, filename := range manifestPaths { + manifestName := fmt.Sprintf("windows-%s-%s", dir, filename) + output := bytes.NewBuffer([]byte{}) + n.log.Debugf("Reading manifest template %s", manifestName) + contents, err := static.Asset(fmt.Sprintf("manifests/windows/%s/%s", dir, filename)) + if err != nil { + return fmt.Errorf("can't unpack manifest %s: %v", manifestName, err) + } + + tw := templatewriter.TemplateWriter{ + Name: fmt.Sprintf("windows-%s-%s", dir, strings.TrimSuffix(filename, filepath.Ext(filename))), + Template: string(contents), + Data: newConfig, + } + tryAndLog(manifestName, tw.WriteToBuffer(output)) + tryAndLog(manifestName, n.saver.Save(manifestName, output.Bytes())) + } + } + return nil +} diff --git a/pkg/component/controller/extensions_controller.go b/pkg/component/controller/extensions_controller.go index 2c162a7d536c..3a356baa4282 100644 --- a/pkg/component/controller/extensions_controller.go +++ b/pkg/component/controller/extensions_controller.go @@ -340,7 +340,7 @@ func (ec *ExtensionsController) Init(_ context.Context) error { return nil } -// Run +// Start func (ec *ExtensionsController) Start(ctx context.Context) error { clientConfig, err := clientcmd.BuildConfigFromFlags("", ec.kubeConfig) if err != nil { diff --git a/pkg/component/worker/calico_installer_windows.go b/pkg/component/worker/nodesetup_windows.go similarity index 73% rename from pkg/component/worker/calico_installer_windows.go rename to pkg/component/worker/nodesetup_windows.go index deb27dc68444..75efc4695784 100644 --- a/pkg/component/worker/calico_installer_windows.go +++ b/pkg/component/worker/nodesetup_windows.go @@ -18,11 +18,8 @@ package worker import ( "context" - "fmt" - "os" "github.com/k0sproject/k0s/pkg/component/manager" - "github.com/sirupsen/logrus" ) type CalicoInstaller struct { @@ -37,16 +34,31 @@ var _ manager.Component = (*CalicoInstaller)(nil) func (c CalicoInstaller) Init(_ context.Context) error { // path := "C:\\bootstrap.ps1" - if err := os.Mkdir("C:\\CalicoWindows", 777); err != nil { - if os.IsExist(err) { - logrus.Warn("CalicoWindows already set up") - return nil - } - return fmt.Errorf("can't create CalicoWindows dir: %v", err) - } - + // if err := dir.Init("C:\\CalicoWindows", 777); err != nil { + // if os.IsExist(err) { + // logrus.Warn("CalicoWindows already set up") + // return nil + // } + // return fmt.Errorf("can't create CalicoWindows dir: %v", err) + // } + // // c:\etc\cni\net.d + // if err := dir.Init("C:\\etc\\cni\\net.d", 777); err != nil { + // if os.IsExist(err) { + // logrus.Warn("CalicoWindows already set up") + // } else { + // return fmt.Errorf("can't create CalicoWindows dir: %v", err) + // } + // } + // // C:\Program Files\containerd\cni\bin + // if err := dir.Init("C:\\Program Files\\containerd\\cni\\bin", 777); err != nil { + // if os.IsExist(err) { + // logrus.Warn("CalicoWindows already set up") + // } else { + // return fmt.Errorf("can't create CalicoWindows dir: %v", err) + // } + // } return winExecute(installCalicoPowershell) - + // return nil } func (c CalicoInstaller) SaveKubeConfig(path string) error { @@ -112,5 +124,5 @@ func (c CalicoInstaller) Stop() error { // the original script is done by Tigera, Inc // and can be accessed over the web on https://docs.projectcalico.org/scripts/install-calico-windows.ps1 const installCalicoPowershell = ` -New-NetFirewallRule -Name KubectlExec10250 -Description "Enable kubectl exec and log" -Action Allow -LocalPort 10250 -Enabled True -DisplayName "kubectl exec 10250" -Protocol TCP -ErrorAction SilentlyContinue +$existingRule = Get-NetFirewallRule -DisplayName "kubectl exec 10250" -ErrorAction SilentlyContinue; if ($existingRule -eq $null) { New-NetFirewallRule -Name "KubectlExec10250" -Description "Enable kubectl exec and log" -Action Allow -LocalPort 10250 -Enabled True -DisplayName "kubectl exec 10250" -Protocol TCP -ErrorAction SilentlyContinue } else { Write-Output "The firewall rule already exists." } ` diff --git a/pkg/component/worker/utils_windows.go b/pkg/component/worker/utils_windows.go index b5efa5ce4f3c..f79d2ed58b1a 100644 --- a/pkg/component/worker/utils_windows.go +++ b/pkg/component/worker/utils_windows.go @@ -22,6 +22,7 @@ import ( "github.com/Microsoft/hcsshim" "github.com/avast/retry-go" + "github.com/davecgh/go-spew/spew" "github.com/sirupsen/logrus" ) @@ -46,10 +47,9 @@ func (p *PowerShell) execute(args ...string) error { } args = append([]string{"-NoProfile", "-NonInteractive"}, args...) cmd := exec.Command(p.powerShell, args...) - + spew.Dump(args) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - return cmd.Run() } @@ -74,5 +74,9 @@ func getSourceVip() (string, error) { func winExecute(args ...string) error { ps := NewPowershell() - return ps.execute(args...) + spew.Dump(args) + + r := ps.execute(args...) + spew.Dump(r) + return r } diff --git a/pkg/constant/constant_shared.go b/pkg/constant/constant_shared.go index 37dde9e183ec..939ba160df33 100644 --- a/pkg/constant/constant_shared.go +++ b/pkg/constant/constant_shared.go @@ -112,6 +112,7 @@ const ( NetworkProviderComponentName = "network-provider" SystemRbacComponentName = "system-rbac" NodeRoleComponentName = "node-role" + WindowsNodeComponentName = "windows-node-role" AutopilotComponentName = "autopilot" // ClusterConfigNamespace is the namespace where we expect to find the ClusterConfig CRs diff --git a/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml b/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml new file mode 100644 index 000000000000..cb016e1d4c64 --- /dev/null +++ b/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: calico-windows-config + namespace: kube-system +data: + # Valid values for Calico networking are: "vxlan", "windows-bgp" + # For non-C alico networking, the only value is "none". + CALICO_NETWORKING_BACKEND: "vxlan" #"{{ .Mode }}" + # The Kubernetes API server host and port. This is required to + # bootstrap Calico for Windows. + KUBERNETES_SERVICE_HOST: "16.170.173.94" + KUBERNETES_SERVICE_PORT: "6443" + # The Kubernetes service clusterIP range configured in your cluster. + # This must match the service-cluster-ip-range used by kube-apiserver. + # from microk8s + K8S_SERVICE_CIDR: "10.96.0.0/12" + # The DNS nameservers that will be used in the CNI configuration. + DNS_NAME_SERVERS: "10.96.0.10" + # The CNI bin dir. This must match the containerd configuration on the Windows nodes. + CNI_BIN_DIR: "c:\\opt\\cni\\bin" # "{{ .CNIBin }}" + # The CNI conf dir. This must match the containerd configuration on the Windows nodes. + CNI_CONF_DIR: "c:\\etc\\cni\\net.d" # "{{ .CNIConf }}" # + # Felix health must be enabled. + FELIX_HEALTHENABLED: "true" \ No newline at end of file diff --git a/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml b/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml new file mode 100644 index 000000000000..e9713a86a310 --- /dev/null +++ b/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml @@ -0,0 +1,121 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: calico-node-windows + namespace: kube-system +spec: + selector: + matchLabels: + "kubernetes.io/os": windows + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + template: + metadata: + labels: + "kubernetes.io/os": windows + spec: + serviceAccountName: calico-node + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: "NT AUTHORITY\\system" + hostNetwork: true + tolerations: + # Make sure calico-node gets scheduled on all nodes. + - effect: NoSchedule + operator: Exists + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + initContainers: + - name: install + image: calico/windows:v3.23.5 + args: + - ".\\host-process-install.ps1" + imagePullPolicy: IfNotPresent + envFrom: + - configMapRef: + name: calico-windows-config + workingDir: "$env:CONTAINER_SANDBOX_MOUNT_POINT" + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + value: ip-172-31-1-241.eu-north-1.compute.internal + containers: + - name: node + image: calico/windows:v3.23.5 + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/node/node-service.ps1" + # The node container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: felix + image: calico/windows:v3.23.5 + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/felix/felix-service.ps1" + # The felix container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + livenessProbe: + exec: + command: + - c:\\CalicoWindows\\calico-node.exe + - -felix-live + periodSeconds: 10 + initialDelaySeconds: 10 + failureThreshold: 6 + timeoutSeconds: 10 + readinessProbe: + exec: + command: + - c:\\CalicoWindows\\calico-node.exe + - -felix-ready + periodSeconds: 10 + timeoutSeconds: 10 + - name: confd + image: calico/windows:v3.23.5 + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/confd/confd-service.ps1" + # The confd container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + nodeSelector: + kubernetes.io/os: windows \ No newline at end of file diff --git a/static/manifests/calico/IPAMConfig/ipamconfig.yaml b/static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml similarity index 63% rename from static/manifests/calico/IPAMConfig/ipamconfig.yaml rename to static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml index 761ad48c28d2..36daa0092bb7 100644 --- a/static/manifests/calico/IPAMConfig/ipamconfig.yaml +++ b/static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml @@ -1,10 +1,9 @@ -{{- if .WithWindowsNodes }} --- apiVersion: crd.projectcalico.org/v1 kind: IPAMConfig metadata: name: default + namespace: kube-system spec: strictAffinity: true - autoAllocateBlocks: true -{{- end }} \ No newline at end of file + autoAllocateBlocks: true \ No newline at end of file From 4737b557d3934ef19fa92e60f56b4f92c1658501 Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 8 Jun 2023 11:12:09 +0000 Subject: [PATCH 03/10] windows node gets ready without manual interventions Signed-off-by: Mikhail Sakhnov --- .../controller/calicowindowscontroller.go | 14 +- pkg/component/worker/containerd/criconfig.go | 8 +- pkg/component/worker/nodesetup_windows.go | 17 +++ .../ConfigMap/calico-windows-config.yaml | 26 ---- .../DaemonSet/calico-windows-node.yaml | 121 ------------------ .../IPAMConfig/calico-ipamconfig-windows.yaml | 9 -- 6 files changed, 35 insertions(+), 160 deletions(-) delete mode 100644 static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml delete mode 100644 static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml delete mode 100644 static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml diff --git a/pkg/component/controller/calicowindowscontroller.go b/pkg/component/controller/calicowindowscontroller.go index c6f13f58013e..f506a785fc70 100644 --- a/pkg/component/controller/calicowindowscontroller.go +++ b/pkg/component/controller/calicowindowscontroller.go @@ -48,7 +48,11 @@ type WindowsStackComponent struct { prevRenderingContext windowsStackRenderingContext } -type windowsStackRenderingContext struct{} +type windowsStackRenderingContext struct { + CNIBin string + CNIConf string + Mode string +} // NewWindowsStackComponent creates new WindowsStackComponent reconciler func NewWindowsStackComponent(k0sVars constant.CfgVars, clientFactory k8sutil.ClientFactoryInterface, saver manifestsSaver) *WindowsStackComponent { @@ -131,7 +135,13 @@ func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.Cluste return nil } func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) windowsStackRenderingContext { - return windowsStackRenderingContext{} + + return windowsStackRenderingContext{ + // template rendering unescapes double backslashes + CNIBin: "c:\\\\opt\\\\cni\\\\bin", + CNIConf: "c:\\\\opt\\\\cni\\\\conf", + Mode: cfg.Spec.Network.Calico.Mode, + } } // Stop no-op diff --git a/pkg/component/worker/containerd/criconfig.go b/pkg/component/worker/containerd/criconfig.go index ea839923fd78..3a5166a28999 100644 --- a/pkg/component/worker/containerd/criconfig.go +++ b/pkg/component/worker/containerd/criconfig.go @@ -25,6 +25,7 @@ import ( "runtime" "strings" + "github.com/davecgh/go-spew/spew" "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1" "github.com/mesosphere/toml-merge/pkg/patch" "github.com/pelletier/go-toml" @@ -104,7 +105,6 @@ func (c *CRIConfigurer) HandleImports() ([]string, error) { imports = append(imports, escapedPath(file)) } } - // Write the CRI config to a file and add it to imports err = os.WriteFile(c.criRuntimePath, []byte(finalConfig), 0644) if err != nil { @@ -137,7 +137,11 @@ func (c *CRIConfigurer) generateDefaultCRIConfig(w io.Writer) error { criPluginConfig := criconfig.DefaultConfig() // Set pause image criPluginConfig.SandboxImage = c.pauseImage - + if runtime.GOOS == "windows" { + criPluginConfig.CniConfig.NetworkPluginBinDir = "c:\\opt\\cni\\bin" + criPluginConfig.CniConfig.NetworkPluginConfDir = "c:\\opt\\cni\\conf" + spew.Dump("DEFAULT CONFIG FOR WINDOWS WITH CHANGED PATH", criPluginConfig) + } containerdConfig := config{ Version: 2, Plugins: map[string]interface{}{ diff --git a/pkg/component/worker/nodesetup_windows.go b/pkg/component/worker/nodesetup_windows.go index 75efc4695784..f7ddba891168 100644 --- a/pkg/component/worker/nodesetup_windows.go +++ b/pkg/component/worker/nodesetup_windows.go @@ -18,8 +18,12 @@ package worker import ( "context" + "fmt" + "os" + "github.com/k0sproject/k0s/internal/pkg/dir" "github.com/k0sproject/k0s/pkg/component/manager" + "github.com/sirupsen/logrus" ) type CalicoInstaller struct { @@ -57,6 +61,19 @@ func (c CalicoInstaller) Init(_ context.Context) error { // return fmt.Errorf("can't create CalicoWindows dir: %v", err) // } // } + + for _, path := range []string{ + "C:\\opt\\cni\\bin", + "C:\\opt\\cni\\conf", + } { + if err := dir.Init(path, 777); err != nil { + if os.IsExist(err) { + logrus.Warn("CalicoWindows already set up") + } else { + return fmt.Errorf("can't create CalicoWindows dir: %v", err) + } + } + } return winExecute(installCalicoPowershell) // return nil } diff --git a/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml b/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml deleted file mode 100644 index cb016e1d4c64..000000000000 --- a/static/manifests/calicoWindows/ConfigMap/calico-windows-config.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: calico-windows-config - namespace: kube-system -data: - # Valid values for Calico networking are: "vxlan", "windows-bgp" - # For non-C alico networking, the only value is "none". - CALICO_NETWORKING_BACKEND: "vxlan" #"{{ .Mode }}" - # The Kubernetes API server host and port. This is required to - # bootstrap Calico for Windows. - KUBERNETES_SERVICE_HOST: "16.170.173.94" - KUBERNETES_SERVICE_PORT: "6443" - # The Kubernetes service clusterIP range configured in your cluster. - # This must match the service-cluster-ip-range used by kube-apiserver. - # from microk8s - K8S_SERVICE_CIDR: "10.96.0.0/12" - # The DNS nameservers that will be used in the CNI configuration. - DNS_NAME_SERVERS: "10.96.0.10" - # The CNI bin dir. This must match the containerd configuration on the Windows nodes. - CNI_BIN_DIR: "c:\\opt\\cni\\bin" # "{{ .CNIBin }}" - # The CNI conf dir. This must match the containerd configuration on the Windows nodes. - CNI_CONF_DIR: "c:\\etc\\cni\\net.d" # "{{ .CNIConf }}" # - # Felix health must be enabled. - FELIX_HEALTHENABLED: "true" \ No newline at end of file diff --git a/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml b/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml deleted file mode 100644 index e9713a86a310..000000000000 --- a/static/manifests/calicoWindows/DaemonSet/calico-windows-node.yaml +++ /dev/null @@ -1,121 +0,0 @@ ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: calico-node-windows - namespace: kube-system -spec: - selector: - matchLabels: - "kubernetes.io/os": windows - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 1 - template: - metadata: - labels: - "kubernetes.io/os": windows - spec: - serviceAccountName: calico-node - securityContext: - windowsOptions: - hostProcess: true - runAsUserName: "NT AUTHORITY\\system" - hostNetwork: true - tolerations: - # Make sure calico-node gets scheduled on all nodes. - - effect: NoSchedule - operator: Exists - # Mark the pod as a critical add-on for rescheduling. - - key: CriticalAddonsOnly - operator: Exists - - effect: NoExecute - operator: Exists - initContainers: - - name: install - image: calico/windows:v3.23.5 - args: - - ".\\host-process-install.ps1" - imagePullPolicy: IfNotPresent - envFrom: - - configMapRef: - name: calico-windows-config - workingDir: "$env:CONTAINER_SANDBOX_MOUNT_POINT" - # Calico needs to know the name of the node on which it is running. - env: - - name: NODENAME - value: ip-172-31-1-241.eu-north-1.compute.internal - containers: - - name: node - image: calico/windows:v3.23.5 - imagePullPolicy: IfNotPresent - args: - - "C:/CalicoWindows/node/node-service.ps1" - # The node container's working dir is in c:\CalicoWindows on the host, - # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. - workingDir: "C:/CalicoWindows" - envFrom: - - configMapRef: - name: calico-windows-config - # Calico needs to know the name of the node on which it is running. - env: - - name: NODENAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: felix - image: calico/windows:v3.23.5 - imagePullPolicy: IfNotPresent - args: - - "C:/CalicoWindows/felix/felix-service.ps1" - # The felix container's working dir is in c:\CalicoWindows on the host, - # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. - workingDir: "C:/CalicoWindows" - envFrom: - - configMapRef: - name: calico-windows-config - # Calico needs to know the name of the node on which it is running. - env: - - name: NODENAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - livenessProbe: - exec: - command: - - c:\\CalicoWindows\\calico-node.exe - - -felix-live - periodSeconds: 10 - initialDelaySeconds: 10 - failureThreshold: 6 - timeoutSeconds: 10 - readinessProbe: - exec: - command: - - c:\\CalicoWindows\\calico-node.exe - - -felix-ready - periodSeconds: 10 - timeoutSeconds: 10 - - name: confd - image: calico/windows:v3.23.5 - imagePullPolicy: IfNotPresent - args: - - "C:/CalicoWindows/confd/confd-service.ps1" - # The confd container's working dir is in c:\CalicoWindows on the host, - # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. - workingDir: "C:/CalicoWindows" - envFrom: - - configMapRef: - name: calico-windows-config - # Calico needs to know the name of the node on which it is running. - env: - - name: NODENAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - nodeSelector: - kubernetes.io/os: windows \ No newline at end of file diff --git a/static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml b/static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml deleted file mode 100644 index 36daa0092bb7..000000000000 --- a/static/manifests/calicoWindows/IPAMConfig/calico-ipamconfig-windows.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -apiVersion: crd.projectcalico.org/v1 -kind: IPAMConfig -metadata: - name: default - namespace: kube-system -spec: - strictAffinity: true - autoAllocateBlocks: true \ No newline at end of file From ced1078be4f9ecb0a0e889e06f2e1df3736f8cac Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 8 Jun 2023 13:35:13 +0000 Subject: [PATCH 04/10] Configurable manifests for windows Signed-off-by: Mikhail Sakhnov --- pkg/apis/k0s/v1beta1/calico.go | 5 - pkg/component/controller/calico.go | 2 - .../controller/calicowindowscontroller.go | 35 +++-- .../k0s.k0sproject.io_clusterconfigs.yaml | 3 - .../ConfigMap/calico-windows-config.yaml | 22 ++++ .../DaemonSet/calico-windows-node.yaml | 122 ++++++++++++++++++ .../IPAMConfig/calico-ipamconfig-windows.yaml | 9 ++ 7 files changed, 179 insertions(+), 19 deletions(-) create mode 100644 static/manifests/windows/ConfigMap/calico-windows-config.yaml create mode 100644 static/manifests/windows/DaemonSet/calico-windows-node.yaml create mode 100644 static/manifests/windows/IPAMConfig/calico-ipamconfig-windows.yaml diff --git a/pkg/apis/k0s/v1beta1/calico.go b/pkg/apis/k0s/v1beta1/calico.go index 1258397868d8..c1b7d4fa5631 100644 --- a/pkg/apis/k0s/v1beta1/calico.go +++ b/pkg/apis/k0s/v1beta1/calico.go @@ -49,9 +49,6 @@ type Calico struct { // The virtual network ID for VXLAN (default: 4096) VxlanVNI int `json:"vxlanVNI"` - - // Windows Nodes (default: false) - WithWindowsNodes bool `json:"withWindowsNodes"` } // DefaultCalico returns sane defaults for calico @@ -63,7 +60,6 @@ func DefaultCalico() *Calico { MTU: 0, EnableWireguard: false, FlexVolumeDriverPath: "/usr/libexec/k0s/kubelet-plugins/volume/exec/nodeagent~uds", - WithWindowsNodes: false, Overlay: "Always", IPAutodetectionMethod: "", IPv6AutodetectionMethod: "", @@ -77,7 +73,6 @@ func (c *Calico) UnmarshalJSON(data []byte) error { c.VxlanVNI = 4096 c.MTU = 1450 c.EnableWireguard = false - c.WithWindowsNodes = false c.FlexVolumeDriverPath = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds" c.Overlay = "Always" c.IPAutodetectionMethod = "" diff --git a/pkg/component/controller/calico.go b/pkg/component/controller/calico.go index ff0c9239dfac..c82e6b1c2c30 100644 --- a/pkg/component/controller/calico.go +++ b/pkg/component/controller/calico.go @@ -65,7 +65,6 @@ type calicoConfig struct { ClusterCIDRIPv4 string ClusterCIDRIPv6 string EnableWireguard bool - WithWindowsNodes bool FlexVolumeDriverPath string DualStack bool EnvVars map[string]string @@ -199,7 +198,6 @@ func (c *Calico) getConfig(clusterConfig *v1beta1.ClusterConfig) (calicoConfig, CalicoCNIImage: clusterConfig.Spec.Images.Calico.CNI.URI(), CalicoNodeImage: clusterConfig.Spec.Images.Calico.Node.URI(), CalicoKubeControllersImage: clusterConfig.Spec.Images.Calico.KubeControllers.URI(), - WithWindowsNodes: clusterConfig.Spec.Network.Calico.WithWindowsNodes, Overlay: clusterConfig.Spec.Network.Calico.Overlay, IPAutodetectionMethod: clusterConfig.Spec.Network.Calico.IPAutodetectionMethod, IPV6AutodetectionMethod: ipv6AutoDetectionMethod, diff --git a/pkg/component/controller/calicowindowscontroller.go b/pkg/component/controller/calicowindowscontroller.go index f506a785fc70..1e360a46e724 100644 --- a/pkg/component/controller/calicowindowscontroller.go +++ b/pkg/component/controller/calicowindowscontroller.go @@ -49,9 +49,14 @@ type WindowsStackComponent struct { } type windowsStackRenderingContext struct { - CNIBin string - CNIConf string - Mode string + CNIBin string + CNIConf string + Mode string + KubeAPIHost string + KubeAPIPort string + IPv4ServiceCIDR string + Nameserver string + NodeImage string } // NewWindowsStackComponent creates new WindowsStackComponent reconciler @@ -127,21 +132,33 @@ func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.Cluste if existingCNI != "" && existingCNI != constant.CNIProviderCalico { return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) } - newConfig := n.makeCalicoRenderingContext(cfg) + newConfig, err := n.makeCalicoRenderingContext(cfg) + if err != nil { + return fmt.Errorf("failed to make calico rendering context: %v", err) + } if !reflect.DeepEqual(newConfig, n.prevRenderingContext) { n.prevRenderingContext = newConfig } return nil } -func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) windowsStackRenderingContext { +func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) (windowsStackRenderingContext, error) { + dns, err := cfg.Spec.Network.DNSAddress() + if err != nil { + return windowsStackRenderingContext{}, fmt.Errorf("failed to parse dns address: %v", err) + } return windowsStackRenderingContext{ // template rendering unescapes double backslashes - CNIBin: "c:\\\\opt\\\\cni\\\\bin", - CNIConf: "c:\\\\opt\\\\cni\\\\conf", - Mode: cfg.Spec.Network.Calico.Mode, - } + CNIBin: "c:\\\\opt\\\\cni\\\\bin", + CNIConf: "c:\\\\opt\\\\cni\\\\conf", + Mode: cfg.Spec.Network.Calico.Mode, + KubeAPIHost: cfg.Spec.API.Address, + KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port), + IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR, + Nameserver: dns, + NodeImage: "calico/windows:v3.23.5", + }, nil } // Stop no-op diff --git a/static/manifests/v1beta1/CustomResourceDefinition/k0s.k0sproject.io_clusterconfigs.yaml b/static/manifests/v1beta1/CustomResourceDefinition/k0s.k0sproject.io_clusterconfigs.yaml index 4b88bdb778f0..7c0641fac2a3 100644 --- a/static/manifests/v1beta1/CustomResourceDefinition/k0s.k0sproject.io_clusterconfigs.yaml +++ b/static/manifests/v1beta1/CustomResourceDefinition/k0s.k0sproject.io_clusterconfigs.yaml @@ -353,9 +353,6 @@ spec: description: 'Enable wireguard-based encryption (default: false)' type: boolean - withWindowsNodes: - description: 'Windows Nodes (default: false)' - type: boolean type: object clusterDomain: description: Cluster Domain diff --git a/static/manifests/windows/ConfigMap/calico-windows-config.yaml b/static/manifests/windows/ConfigMap/calico-windows-config.yaml new file mode 100644 index 000000000000..304a90961aa5 --- /dev/null +++ b/static/manifests/windows/ConfigMap/calico-windows-config.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: calico-windows-config + namespace: kube-system +data: + CALICO_NETWORKING_BACKEND: "{{ .Mode }}" + # The Kubernetes API server host and port. This is required to + # bootstrap Calico for Windows. + KUBERNETES_SERVICE_HOST: "{{ .KubeAPIHost }}" + KUBERNETES_SERVICE_PORT: "{{ .KubeAPIPort }}" + # The Kubernetes service clusterIP range configured in your cluster. + # This must match the service-cluster-ip-range used by kube-apiserver. + K8S_SERVICE_CIDR: "{{ .IPv4ServiceCIDR }}" + # The DNS nameservers that will be used in the CNI configuration. + DNS_NAME_SERVERS: "{{ .Nameserver }}" + # The CNI bin dir. This must match the containerd configuration on the Windows nodes. + CNI_BIN_DIR: "{{ .CNIBin }}" + # The CNI conf dir. This must match the containerd configuration on the Windows nodes. + CNI_CONF_DIR: "{{ .CNIConf }}" + FELIX_HEALTHENABLED: "true" \ No newline at end of file diff --git a/static/manifests/windows/DaemonSet/calico-windows-node.yaml b/static/manifests/windows/DaemonSet/calico-windows-node.yaml new file mode 100644 index 000000000000..3531d19bb8d1 --- /dev/null +++ b/static/manifests/windows/DaemonSet/calico-windows-node.yaml @@ -0,0 +1,122 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: calico-node-windows + namespace: kube-system +spec: + selector: + matchLabels: + "kubernetes.io/os": windows + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + template: + metadata: + labels: + "kubernetes.io/os": windows + spec: + serviceAccountName: calico-node + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: "NT AUTHORITY\\system" + hostNetwork: true + tolerations: + # Make sure calico-node gets scheduled on all nodes. + - effect: NoSchedule + operator: Exists + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + initContainers: + - name: install + image: "{{ .NodeImage }}" + args: + - ".\\host-process-install.ps1" + imagePullPolicy: IfNotPresent + envFrom: + - configMapRef: + name: calico-windows-config + workingDir: "$env:CONTAINER_SANDBOX_MOUNT_POINT" + env: + - name: NODENAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + containers: + - name: node + image: "{{ .NodeImage }}" + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/node/node-service.ps1" + # The node container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: felix + image: "{{ .NodeImage }}" + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/felix/felix-service.ps1" + # The felix container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + livenessProbe: + exec: + command: + - c:\\CalicoWindows\\calico-node.exe + - -felix-live + periodSeconds: 10 + initialDelaySeconds: 10 + failureThreshold: 6 + timeoutSeconds: 10 + readinessProbe: + exec: + command: + - c:\\CalicoWindows\\calico-node.exe + - -felix-ready + periodSeconds: 10 + timeoutSeconds: 10 + - name: confd + image: "{{ .NodeImage }}" + imagePullPolicy: IfNotPresent + args: + - "C:/CalicoWindows/confd/confd-service.ps1" + # The confd container's working dir is in c:\CalicoWindows on the host, + # which is two-levels up from the CONTAINER_SANDBOX_MOUNT_POINT. + workingDir: "C:/CalicoWindows" + envFrom: + - configMapRef: + name: calico-windows-config + # Calico needs to know the name of the node on which it is running. + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + nodeSelector: + kubernetes.io/os: windows \ No newline at end of file diff --git a/static/manifests/windows/IPAMConfig/calico-ipamconfig-windows.yaml b/static/manifests/windows/IPAMConfig/calico-ipamconfig-windows.yaml new file mode 100644 index 000000000000..36daa0092bb7 --- /dev/null +++ b/static/manifests/windows/IPAMConfig/calico-ipamconfig-windows.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: crd.projectcalico.org/v1 +kind: IPAMConfig +metadata: + name: default + namespace: kube-system +spec: + strictAffinity: true + autoAllocateBlocks: true \ No newline at end of file From a19d95a2dda02784c2b7c75a6e85faff3b809263 Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Mon, 12 Jun 2023 11:17:53 +0000 Subject: [PATCH 05/10] Apply cleanups: drop non used cli arguments Signed-off-by: Mikhail Sakhnov --- cmd/controller/controller.go | 7 +- cmd/worker/worker.go | 10 +- .../controller/calicowindowscontroller.go | 208 ------------------ pkg/component/worker/kubeproxy_windows.go | 6 +- pkg/component/worker/nodesetup_windows.go | 100 +-------- pkg/component/worker/stubs.go | 20 +- pkg/config/cli.go | 4 - 7 files changed, 23 insertions(+), 332 deletions(-) delete mode 100644 pkg/component/controller/calicowindowscontroller.go diff --git a/cmd/controller/controller.go b/cmd/controller/controller.go index 59cc351affc3..1d35e4fbb139 100644 --- a/cmd/controller/controller.go +++ b/cmd/controller/controller.go @@ -417,7 +417,9 @@ func (c *command) start(ctx context.Context) error { return fmt.Errorf("failed to create calico_init manifests saver: %w", err) } clusterComponents.Add(ctx, controller.NewCalico(c.K0sVars, calicoInitSaver, calicoSaver)) - clusterComponents.Add(ctx, controller.NewWindowsStackComponent(c.K0sVars, adminClientFactory, calicoSaver)) + if !slices.Contains(c.DisableComponents, constant.WindowsNodeComponentName) { + clusterComponents.Add(ctx, controller.NewWindowsStackComponent(c.K0sVars, adminClientFactory, calicoSaver)) + } kubeRouterSaver, err := controller.NewManifestsSaver("kuberouter", c.K0sVars.DataDir) if err != nil { return fmt.Errorf("failed to create kuberouter manifests saver: %w", err) @@ -458,9 +460,6 @@ func (c *command) start(ctx context.Context) error { clusterComponents.Add(ctx, controller.NewNodeRole(c.K0sVars, adminClientFactory)) } - if !slices.Contains(c.DisableComponents, constant.WindowsNodeComponentName) { - } - if enableKonnectivity { clusterComponents.Add(ctx, &controller.Konnectivity{ SingleNode: c.SingleNode, diff --git a/cmd/worker/worker.go b/cmd/worker/worker.go index 23e597070a6d..e630a2196341 100644 --- a/cmd/worker/worker.go +++ b/cmd/worker/worker.go @@ -167,20 +167,12 @@ func (c *Command) Start(ctx context.Context) error { }) if runtime.GOOS == "windows" { - if c.TokenArg == "" { - return fmt.Errorf("no join-token given, which is required for windows bootstrap") - } componentManager.Add(ctx, &worker.KubeProxy{ K0sVars: c.K0sVars, LogLevel: c.Logging["kube-proxy"], CIDRRange: c.CIDRRange, }) - componentManager.Add(ctx, &worker.CalicoInstaller{ - Token: c.TokenArg, - APIAddress: c.APIServer, - CIDRRange: c.CIDRRange, - ClusterDNS: c.ClusterDNS, - }) + componentManager.Add(ctx, &worker.NodesetupHelper{}) } certManager := worker.NewCertificateManager(ctx, kubeletKubeconfigPath) diff --git a/pkg/component/controller/calicowindowscontroller.go b/pkg/component/controller/calicowindowscontroller.go deleted file mode 100644 index 1e360a46e724..000000000000 --- a/pkg/component/controller/calicowindowscontroller.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright 2023 k0s 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 controller - -import ( - "bytes" - "context" - "fmt" - "path/filepath" - "reflect" - "strings" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/k0sproject/k0s/internal/pkg/templatewriter" - "github.com/k0sproject/k0s/static" - "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1" - "github.com/k0sproject/k0s/pkg/constant" - k8sutil "github.com/k0sproject/k0s/pkg/kubernetes" -) - -// WindowsStackComponent implements the component interface -// controller unpacks windows manifests -// if windows nodes are present in the cluster -type WindowsStackComponent struct { - log logrus.FieldLogger - - kubeClientFactory k8sutil.ClientFactoryInterface - k0sVars constant.CfgVars - saver manifestsSaver - prevRenderingContext windowsStackRenderingContext -} - -type windowsStackRenderingContext struct { - CNIBin string - CNIConf string - Mode string - KubeAPIHost string - KubeAPIPort string - IPv4ServiceCIDR string - Nameserver string - NodeImage string -} - -// NewWindowsStackComponent creates new WindowsStackComponent reconciler -func NewWindowsStackComponent(k0sVars constant.CfgVars, clientFactory k8sutil.ClientFactoryInterface, saver manifestsSaver) *WindowsStackComponent { - return &WindowsStackComponent{ - log: logrus.WithFields(logrus.Fields{"component": "WindowsNodeController"}), - saver: saver, - kubeClientFactory: clientFactory, - k0sVars: k0sVars, - } -} - -// Init no-op -func (n *WindowsStackComponent) Init(_ context.Context) error { - return nil -} - -// Run checks and adds labels -func (n *WindowsStackComponent) Start(ctx context.Context) error { - - go func() { - timer := time.NewTicker(1 * time.Minute) - defer timer.Stop() - for { - select { - case <-ctx.Done(): - return - case <-timer.C: - if err := n.handleWindowsNode(ctx, n.prevRenderingContext); err != nil { - n.log.Errorf("failed to handle windows node: %v", err) - } - } - } - }() - - return nil -} - -func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context, cfg windowsStackRenderingContext) error { - client, err := n.kubeClientFactory.GetClient() - if err != nil { - return fmt.Errorf("failed to get kube client: %v", err) - } - nodes, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{ - LabelSelector: "kubernetes.io/os=windows", - }) - if err != nil { - n.log.Errorf("failed to get node list: %v", err) - return fmt.Errorf("failed to get node list: %v", err) - } - - if len(nodes.Items) == 0 { - // TODO: may be delete windows stack if it exists - return nil - } - - n.log.Infof("found %d windows nodes", len(nodes.Items)) - if err := n.createWindowsStack(n.prevRenderingContext); err != nil { - n.log.Errorf("failed to create windows stack: %v", err) - return fmt.Errorf("failed to create windows stack: %v", err) - } else { - n.log.Infof("successfully created windows stack") - } - return nil -} - -func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.ClusterConfig) error { - if cfg.Spec.Network.Provider != "calico" { - return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) - } - - existingCNI := existingCNIProvider(n.k0sVars.ManifestsDir) - if existingCNI != "" && existingCNI != constant.CNIProviderCalico { - return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) - } - newConfig, err := n.makeCalicoRenderingContext(cfg) - if err != nil { - return fmt.Errorf("failed to make calico rendering context: %v", err) - } - if !reflect.DeepEqual(newConfig, n.prevRenderingContext) { - n.prevRenderingContext = newConfig - } - - return nil -} -func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) (windowsStackRenderingContext, error) { - dns, err := cfg.Spec.Network.DNSAddress() - if err != nil { - return windowsStackRenderingContext{}, fmt.Errorf("failed to parse dns address: %v", err) - } - - return windowsStackRenderingContext{ - // template rendering unescapes double backslashes - CNIBin: "c:\\\\opt\\\\cni\\\\bin", - CNIConf: "c:\\\\opt\\\\cni\\\\conf", - Mode: cfg.Spec.Network.Calico.Mode, - KubeAPIHost: cfg.Spec.API.Address, - KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port), - IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR, - Nameserver: dns, - NodeImage: "calico/windows:v3.23.5", - }, nil -} - -// Stop no-op -func (n *WindowsStackComponent) Stop() error { - return nil -} - -// createWindowsStack creates windows stack - -func (n *WindowsStackComponent) createWindowsStack(newConfig windowsStackRenderingContext) error { - manifestDirectories, err := static.AssetDir("manifests/windows") - if err != nil { - return fmt.Errorf("error retrieving manifests: %v", err) - } - spew.Dump(manifestDirectories) - for _, dir := range manifestDirectories { - manifestPaths, err := static.AssetDir(fmt.Sprintf("manifests/windows/%s", dir)) - if err != nil { - return fmt.Errorf("error retrieving manifests: %s. will retry", err.Error()) - } - tryAndLog := func(name string, e error) { - n.log.Debugf("writing manifest %s", name) - if e != nil { - n.log.Errorf("failed to write manifest %s: %v, will re-try", name, e) - } - } - - for _, filename := range manifestPaths { - manifestName := fmt.Sprintf("windows-%s-%s", dir, filename) - output := bytes.NewBuffer([]byte{}) - n.log.Debugf("Reading manifest template %s", manifestName) - contents, err := static.Asset(fmt.Sprintf("manifests/windows/%s/%s", dir, filename)) - if err != nil { - return fmt.Errorf("can't unpack manifest %s: %v", manifestName, err) - } - - tw := templatewriter.TemplateWriter{ - Name: fmt.Sprintf("windows-%s-%s", dir, strings.TrimSuffix(filename, filepath.Ext(filename))), - Template: string(contents), - Data: newConfig, - } - tryAndLog(manifestName, tw.WriteToBuffer(output)) - tryAndLog(manifestName, n.saver.Save(manifestName, output.Bytes())) - } - } - return nil -} diff --git a/pkg/component/worker/kubeproxy_windows.go b/pkg/component/worker/kubeproxy_windows.go index ce74a359a073..f67fdbdaea9c 100644 --- a/pkg/component/worker/kubeproxy_windows.go +++ b/pkg/component/worker/kubeproxy_windows.go @@ -39,11 +39,11 @@ type KubeProxy struct { var _ manager.Component = (*KubeProxy)(nil) // Init -func (k KubeProxy) Init(_ context.Context) error { +func (k *KubeProxy) Init(_ context.Context) error { return assets.Stage(k.K0sVars.BinDir, "kube-proxy.exe", constant.BinDirMode) } -func (k KubeProxy) Start(ctx context.Context) error { +func (k *KubeProxy) Start(ctx context.Context) error { node, err := node.GetNodename("") if err != nil { return fmt.Errorf("can't get hostname: %v", err) @@ -76,6 +76,6 @@ func (k KubeProxy) Start(ctx context.Context) error { return nil } -func (k KubeProxy) Stop() error { +func (k *KubeProxy) Stop() error { return k.supervisor.Stop() } diff --git a/pkg/component/worker/nodesetup_windows.go b/pkg/component/worker/nodesetup_windows.go index f7ddba891168..35a498823f60 100644 --- a/pkg/component/worker/nodesetup_windows.go +++ b/pkg/component/worker/nodesetup_windows.go @@ -26,42 +26,13 @@ import ( "github.com/sirupsen/logrus" ) -type CalicoInstaller struct { - Token string - APIAddress string - CIDRRange string - ClusterDNS string +// TODO: this all should be dropped in favor of init container for calico stack +type NodesetupHelper struct { } -var _ manager.Component = (*CalicoInstaller)(nil) - -func (c CalicoInstaller) Init(_ context.Context) error { - // path := "C:\\bootstrap.ps1" - - // if err := dir.Init("C:\\CalicoWindows", 777); err != nil { - // if os.IsExist(err) { - // logrus.Warn("CalicoWindows already set up") - // return nil - // } - // return fmt.Errorf("can't create CalicoWindows dir: %v", err) - // } - // // c:\etc\cni\net.d - // if err := dir.Init("C:\\etc\\cni\\net.d", 777); err != nil { - // if os.IsExist(err) { - // logrus.Warn("CalicoWindows already set up") - // } else { - // return fmt.Errorf("can't create CalicoWindows dir: %v", err) - // } - // } - // // C:\Program Files\containerd\cni\bin - // if err := dir.Init("C:\\Program Files\\containerd\\cni\\bin", 777); err != nil { - // if os.IsExist(err) { - // logrus.Warn("CalicoWindows already set up") - // } else { - // return fmt.Errorf("can't create CalicoWindows dir: %v", err) - // } - // } +var _ manager.Component = (*NodesetupHelper)(nil) +func (c NodesetupHelper) Init(_ context.Context) error { for _, path := range []string{ "C:\\opt\\cni\\bin", "C:\\opt\\cni\\conf", @@ -74,72 +45,17 @@ func (c CalicoInstaller) Init(_ context.Context) error { } } } - return winExecute(installCalicoPowershell) - // return nil -} - -func (c CalicoInstaller) SaveKubeConfig(path string) error { - return nil - // tokenBytes, err := token.DecodeJoinToken(c.Token) - // if err != nil { - // return fmt.Errorf("failed to decode token: %v", err) - // } - // clientConfig, err := clientcmd.NewClientConfigFromBytes(tokenBytes) - // if err != nil { - // return fmt.Errorf("failed to create api client config: %v", err) - // } - // config, err := clientConfig.ClientConfig() - // if err != nil { - // return fmt.Errorf("failed to create api client config: %v", err) - // } - - // ca := x509.NewCertPool() - // ca.AppendCertsFromPEM(config.CAData) - // tlsConfig := &tls.Config{ - // InsecureSkipVerify: false, - // RootCAs: ca, - // } - // tr := &http.Transport{TLSClientConfig: tlsConfig} - // client := http.Client{Transport: tr} - - // req, err := http.NewRequest(http.MethodGet, c.APIAddress+"/v1beta1/calico/kubeconfig", nil) - // if err != nil { - // return fmt.Errorf("can't create http request: %v", err) - // } - // req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.BearerToken)) - // resp, err := client.Do(req) - // if err != nil { - // return fmt.Errorf("can't download kubelet config for calico: %v", err) - // } - // defer resp.Body.Close() - // if resp.StatusCode != http.StatusOK { - // return fmt.Errorf("unexpected response status: %s", resp.Status) - // } - // b, err := io.ReadAll(resp.Body) - // if err != nil { - // return fmt.Errorf("can't read response body: %v", err) - // } - // if err := file.WriteContentAtomically(path, b, 0700); err != nil { - // return fmt.Errorf("can't save kubeconfig for calico: %v", err) - // } - // posh := NewPowershell() - // return posh.execute(fmt.Sprintf("C:\\bootstrap.ps1 -ServiceCidr \"%s\" -DNSServerIPs \"%s\"", c.CIDRRange, c.ClusterDNS)) + return winExecute(createFirewallRules) } -func (c CalicoInstaller) Start(_ context.Context) error { +func (c NodesetupHelper) Start(_ context.Context) error { return nil } -func (c CalicoInstaller) Stop() error { +func (c NodesetupHelper) Stop() error { return nil } -// installCalicoPowershell is port of the original calico installer -// with droped customization and no need to download kubernetes components -// since we have staged them. -// We also skip building the pause image as we're using the semi-official MS image from mcr.microsoft.com/oss/kubernetes/pause:1.4.1 -// the original script is done by Tigera, Inc -// and can be accessed over the web on https://docs.projectcalico.org/scripts/install-calico-windows.ps1 -const installCalicoPowershell = ` +const createFirewallRules = ` $existingRule = Get-NetFirewallRule -DisplayName "kubectl exec 10250" -ErrorAction SilentlyContinue; if ($existingRule -eq $null) { New-NetFirewallRule -Name "KubectlExec10250" -Description "Enable kubectl exec and log" -Action Allow -LocalPort 10250 -Enabled True -DisplayName "kubectl exec 10250" -Protocol TCP -ErrorAction SilentlyContinue } else { Write-Output "The firewall rule already exists." } ` diff --git a/pkg/component/worker/stubs.go b/pkg/component/worker/stubs.go index 56d370ce6a3b..0813b99e859c 100644 --- a/pkg/component/worker/stubs.go +++ b/pkg/component/worker/stubs.go @@ -26,25 +26,21 @@ import ( "github.com/k0sproject/k0s/pkg/config" ) -type CalicoInstaller struct { - Token string - APIAddress string - CIDRRange string - ClusterDNS string +type NodesetupHelper struct { } -var _ manager.Component = (*CalicoInstaller)(nil) +var _ manager.Component = (*NodesetupHelper)(nil) -func (c CalicoInstaller) Init(_ context.Context) error { - panic("stub component is used: CalicoInstaller") +func (c NodesetupHelper) Init(_ context.Context) error { + panic("stub component is used: NodesetupHelper which is implemented only for windows") } -func (c CalicoInstaller) Start(_ context.Context) error { - panic("stub component is used: CalicoInstaller") +func (c NodesetupHelper) Start(_ context.Context) error { + panic("stub component is used: NodesetupHelper which is implemented only for windows") } -func (c CalicoInstaller) Stop() error { - panic("stub component is used: CalicoInstaller") +func (c NodesetupHelper) Stop() error { + panic("stub component is used: NodesetupHelper which is implemented only for windows") } type KubeProxy struct { diff --git a/pkg/config/cli.go b/pkg/config/cli.go index 2fb693c62b48..c91b4210879e 100644 --- a/pkg/config/cli.go +++ b/pkg/config/cli.go @@ -78,10 +78,8 @@ type ControllerOptions struct { // Shared worker cli flags type WorkerOptions struct { - APIServer string CIDRRange string CloudProvider bool - ClusterDNS string CmdLogLevels map[string]string CriSocket string KubeletExtraArgs string @@ -175,9 +173,7 @@ func GetWorkerFlags() *pflag.FlagSet { flagset := &pflag.FlagSet{} flagset.StringVar(&workerOpts.WorkerProfile, "profile", "default", "worker profile to use on the node") - flagset.StringVar(&workerOpts.APIServer, "api-server", "", "HACK: api-server for the windows worker node") flagset.StringVar(&workerOpts.CIDRRange, "cidr-range", "10.96.0.0/12", "HACK: cidr range for the windows worker node") - flagset.StringVar(&workerOpts.ClusterDNS, "cluster-dns", "10.96.0.10", "HACK: cluster dns for the windows worker node") flagset.BoolVar(&workerOpts.CloudProvider, "enable-cloud-provider", false, "Whether or not to enable cloud provider support in kubelet") flagset.StringVar(&workerOpts.TokenFile, "token-file", "", "Path to the file containing token.") flagset.StringToStringVarP(&workerOpts.CmdLogLevels, "logging", "l", DefaultLogLevels(), "Logging Levels for the different components") From 427205a4ee503d9390e9c8ec480e81c865a7088b Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 15 Jun 2023 08:17:58 +0000 Subject: [PATCH 06/10] After rebase fix Signed-off-by: Mikhail Sakhnov --- .../controller/windowsstackcomponent.go | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 pkg/component/controller/windowsstackcomponent.go diff --git a/pkg/component/controller/windowsstackcomponent.go b/pkg/component/controller/windowsstackcomponent.go new file mode 100644 index 000000000000..c7b8c05ade33 --- /dev/null +++ b/pkg/component/controller/windowsstackcomponent.go @@ -0,0 +1,209 @@ +/* +Copyright 2023 k0s 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 controller + +import ( + "bytes" + "context" + "fmt" + "path/filepath" + "reflect" + "strings" + "time" + + "github.com/davecgh/go-spew/spew" + "github.com/k0sproject/k0s/internal/pkg/templatewriter" + "github.com/k0sproject/k0s/static" + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1" + "github.com/k0sproject/k0s/pkg/config" + "github.com/k0sproject/k0s/pkg/constant" + k8sutil "github.com/k0sproject/k0s/pkg/kubernetes" +) + +// WindowsStackComponent implements the component interface +// controller unpacks windows manifests +// if windows nodes are present in the cluster +type WindowsStackComponent struct { + log logrus.FieldLogger + + kubeClientFactory k8sutil.ClientFactoryInterface + k0sVars *config.CfgVars + saver manifestsSaver + prevRenderingContext windowsStackRenderingContext +} + +type windowsStackRenderingContext struct { + CNIBin string + CNIConf string + Mode string + KubeAPIHost string + KubeAPIPort string + IPv4ServiceCIDR string + Nameserver string + NodeImage string +} + +// NewWindowsStackComponent creates new WindowsStackComponent reconciler +func NewWindowsStackComponent(k0sVars *config.CfgVars, clientFactory k8sutil.ClientFactoryInterface, saver manifestsSaver) *WindowsStackComponent { + return &WindowsStackComponent{ + log: logrus.WithFields(logrus.Fields{"component": "WindowsNodeController"}), + saver: saver, + kubeClientFactory: clientFactory, + k0sVars: k0sVars, + } +} + +// Init no-op +func (n *WindowsStackComponent) Init(_ context.Context) error { + return nil +} + +// Run checks and adds labels +func (n *WindowsStackComponent) Start(ctx context.Context) error { + + go func() { + timer := time.NewTicker(1 * time.Minute) + defer timer.Stop() + for { + select { + case <-ctx.Done(): + return + case <-timer.C: + if err := n.handleWindowsNode(ctx, n.prevRenderingContext); err != nil { + n.log.Errorf("failed to handle windows node: %v", err) + } + } + } + }() + + return nil +} + +func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context, cfg windowsStackRenderingContext) error { + client, err := n.kubeClientFactory.GetClient() + if err != nil { + return fmt.Errorf("failed to get kube client: %v", err) + } + nodes, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{ + LabelSelector: "kubernetes.io/os=windows", + }) + if err != nil { + n.log.Errorf("failed to get node list: %v", err) + return fmt.Errorf("failed to get node list: %v", err) + } + + if len(nodes.Items) == 0 { + // TODO: may be delete windows stack if it exists + return nil + } + + n.log.Infof("found %d windows nodes", len(nodes.Items)) + if err := n.createWindowsStack(n.prevRenderingContext); err != nil { + n.log.Errorf("failed to create windows stack: %v", err) + return fmt.Errorf("failed to create windows stack: %v", err) + } else { + n.log.Infof("successfully created windows stack") + } + return nil +} + +func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.ClusterConfig) error { + if cfg.Spec.Network.Provider != "calico" { + return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + } + + existingCNI := existingCNIProvider(n.k0sVars.ManifestsDir) + if existingCNI != "" && existingCNI != constant.CNIProviderCalico { + return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + } + newConfig, err := n.makeCalicoRenderingContext(cfg) + if err != nil { + return fmt.Errorf("failed to make calico rendering context: %v", err) + } + if !reflect.DeepEqual(newConfig, n.prevRenderingContext) { + n.prevRenderingContext = newConfig + } + + return nil +} +func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) (windowsStackRenderingContext, error) { + dns, err := cfg.Spec.Network.DNSAddress() + if err != nil { + return windowsStackRenderingContext{}, fmt.Errorf("failed to parse dns address: %v", err) + } + + return windowsStackRenderingContext{ + // template rendering unescapes double backslashes + CNIBin: "c:\\\\opt\\\\cni\\\\bin", + CNIConf: "c:\\\\opt\\\\cni\\\\conf", + Mode: cfg.Spec.Network.Calico.Mode, + KubeAPIHost: cfg.Spec.API.Address, + KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port), + IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR, + Nameserver: dns, + NodeImage: "calico/windows:v3.23.5", + }, nil +} + +// Stop no-op +func (n *WindowsStackComponent) Stop() error { + return nil +} + +// createWindowsStack creates windows stack + +func (n *WindowsStackComponent) createWindowsStack(newConfig windowsStackRenderingContext) error { + manifestDirectories, err := static.AssetDir("manifests/windows") + if err != nil { + return fmt.Errorf("error retrieving manifests: %v", err) + } + spew.Dump(manifestDirectories) + for _, dir := range manifestDirectories { + manifestPaths, err := static.AssetDir(fmt.Sprintf("manifests/windows/%s", dir)) + if err != nil { + return fmt.Errorf("error retrieving manifests: %s. will retry", err.Error()) + } + tryAndLog := func(name string, e error) { + n.log.Debugf("writing manifest %s", name) + if e != nil { + n.log.Errorf("failed to write manifest %s: %v, will re-try", name, e) + } + } + + for _, filename := range manifestPaths { + manifestName := fmt.Sprintf("windows-%s-%s", dir, filename) + output := bytes.NewBuffer([]byte{}) + n.log.Debugf("Reading manifest template %s", manifestName) + contents, err := static.Asset(fmt.Sprintf("manifests/windows/%s/%s", dir, filename)) + if err != nil { + return fmt.Errorf("can't unpack manifest %s: %v", manifestName, err) + } + + tw := templatewriter.TemplateWriter{ + Name: fmt.Sprintf("windows-%s-%s", dir, strings.TrimSuffix(filename, filepath.Ext(filename))), + Template: string(contents), + Data: newConfig, + } + tryAndLog(manifestName, tw.WriteToBuffer(output)) + tryAndLog(manifestName, n.saver.Save(manifestName, output.Bytes())) + } + } + return nil +} From 7ddc16064acfdfa02083d135cd65bcee63f242ea Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 15 Jun 2023 08:40:26 +0000 Subject: [PATCH 07/10] Drop debug logging here and there Signed-off-by: Mikhail Sakhnov --- go.mod | 2 +- pkg/component/controller/windowsstackcomponent.go | 2 -- pkg/component/worker/containerd/criconfig.go | 2 -- pkg/component/worker/utils_windows.go | 4 ---- pkg/node/nodehostname_test.go | 2 -- 5 files changed, 1 insertion(+), 11 deletions(-) diff --git a/go.mod b/go.mod index d4d85381dd4c..fd7db2db8e98 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/cavaliergopher/grab/v3 v3.0.1 github.com/cloudflare/cfssl v1.6.4 github.com/containerd/containerd v1.7.5 - github.com/davecgh/go-spew v1.1.1 github.com/denisbrodbeck/machineid v1.0.1 github.com/estesp/manifest-tool/v2 v2.0.8 github.com/evanphx/json-patch v5.6.0+incompatible @@ -120,6 +119,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/daviddengcn/go-colortext v1.0.0 // indirect github.com/docker/cli v23.0.5+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect diff --git a/pkg/component/controller/windowsstackcomponent.go b/pkg/component/controller/windowsstackcomponent.go index c7b8c05ade33..838ad345afdb 100644 --- a/pkg/component/controller/windowsstackcomponent.go +++ b/pkg/component/controller/windowsstackcomponent.go @@ -25,7 +25,6 @@ import ( "strings" "time" - "github.com/davecgh/go-spew/spew" "github.com/k0sproject/k0s/internal/pkg/templatewriter" "github.com/k0sproject/k0s/static" "github.com/sirupsen/logrus" @@ -174,7 +173,6 @@ func (n *WindowsStackComponent) createWindowsStack(newConfig windowsStackRenderi if err != nil { return fmt.Errorf("error retrieving manifests: %v", err) } - spew.Dump(manifestDirectories) for _, dir := range manifestDirectories { manifestPaths, err := static.AssetDir(fmt.Sprintf("manifests/windows/%s", dir)) if err != nil { diff --git a/pkg/component/worker/containerd/criconfig.go b/pkg/component/worker/containerd/criconfig.go index 3a5166a28999..b664a027d703 100644 --- a/pkg/component/worker/containerd/criconfig.go +++ b/pkg/component/worker/containerd/criconfig.go @@ -25,7 +25,6 @@ import ( "runtime" "strings" - "github.com/davecgh/go-spew/spew" "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1" "github.com/mesosphere/toml-merge/pkg/patch" "github.com/pelletier/go-toml" @@ -140,7 +139,6 @@ func (c *CRIConfigurer) generateDefaultCRIConfig(w io.Writer) error { if runtime.GOOS == "windows" { criPluginConfig.CniConfig.NetworkPluginBinDir = "c:\\opt\\cni\\bin" criPluginConfig.CniConfig.NetworkPluginConfDir = "c:\\opt\\cni\\conf" - spew.Dump("DEFAULT CONFIG FOR WINDOWS WITH CHANGED PATH", criPluginConfig) } containerdConfig := config{ Version: 2, diff --git a/pkg/component/worker/utils_windows.go b/pkg/component/worker/utils_windows.go index f79d2ed58b1a..18fb950850f8 100644 --- a/pkg/component/worker/utils_windows.go +++ b/pkg/component/worker/utils_windows.go @@ -22,7 +22,6 @@ import ( "github.com/Microsoft/hcsshim" "github.com/avast/retry-go" - "github.com/davecgh/go-spew/spew" "github.com/sirupsen/logrus" ) @@ -47,7 +46,6 @@ func (p *PowerShell) execute(args ...string) error { } args = append([]string{"-NoProfile", "-NonInteractive"}, args...) cmd := exec.Command(p.powerShell, args...) - spew.Dump(args) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() @@ -74,9 +72,7 @@ func getSourceVip() (string, error) { func winExecute(args ...string) error { ps := NewPowershell() - spew.Dump(args) r := ps.execute(args...) - spew.Dump(r) return r } diff --git a/pkg/node/nodehostname_test.go b/pkg/node/nodehostname_test.go index 34ef705458cd..a9fc0ea2bb18 100644 --- a/pkg/node/nodehostname_test.go +++ b/pkg/node/nodehostname_test.go @@ -4,7 +4,6 @@ import ( "net/http" "testing" - "github.com/davecgh/go-spew/spew" "github.com/stretchr/testify/require" nodeutil "k8s.io/component-helpers/node/util" ) @@ -47,7 +46,6 @@ func TestGetNodename(t *testing.T) { nodename, err2 := nodeutil.GetHostname("") require.Nil(t, err) require.Nil(t, err2) - spew.Dump(name, nodename, err, err2) require.NotEqual(t, nodename, name) }) } From 87029cc9ab37ec268a9fc16b51ee7a546f7fec80 Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 15 Jun 2023 10:18:26 +0000 Subject: [PATCH 08/10] Deploy kube-proxy as windows pod Signed-off-by: Mikhail Sakhnov --- cmd/worker/worker.go | 5 -- .../controller/windowsstackcomponent.go | 25 +++--- pkg/component/worker/kubeproxy_windows.go | 81 ------------------- pkg/component/worker/stubs.go | 21 ----- .../windows/DaemonSet/kube-proxy-windows.yaml | 53 ++++++++++++ 5 files changed, 68 insertions(+), 117 deletions(-) delete mode 100644 pkg/component/worker/kubeproxy_windows.go create mode 100644 static/manifests/windows/DaemonSet/kube-proxy-windows.yaml diff --git a/cmd/worker/worker.go b/cmd/worker/worker.go index e630a2196341..16823d808ad9 100644 --- a/cmd/worker/worker.go +++ b/cmd/worker/worker.go @@ -167,11 +167,6 @@ func (c *Command) Start(ctx context.Context) error { }) if runtime.GOOS == "windows" { - componentManager.Add(ctx, &worker.KubeProxy{ - K0sVars: c.K0sVars, - LogLevel: c.Logging["kube-proxy"], - CIDRRange: c.CIDRRange, - }) componentManager.Add(ctx, &worker.NodesetupHelper{}) } diff --git a/pkg/component/controller/windowsstackcomponent.go b/pkg/component/controller/windowsstackcomponent.go index 838ad345afdb..267f0cea763e 100644 --- a/pkg/component/controller/windowsstackcomponent.go +++ b/pkg/component/controller/windowsstackcomponent.go @@ -57,6 +57,9 @@ type windowsStackRenderingContext struct { IPv4ServiceCIDR string Nameserver string NodeImage string + + KubeProxyImage string + KubeProxyVersion string } // NewWindowsStackComponent creates new WindowsStackComponent reconciler @@ -132,7 +135,7 @@ func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.Cluste if existingCNI != "" && existingCNI != constant.CNIProviderCalico { return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) } - newConfig, err := n.makeCalicoRenderingContext(cfg) + newConfig, err := n.makeRenderingContext(cfg) if err != nil { return fmt.Errorf("failed to make calico rendering context: %v", err) } @@ -142,7 +145,7 @@ func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.Cluste return nil } -func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterConfig) (windowsStackRenderingContext, error) { +func (n *WindowsStackComponent) makeRenderingContext(cfg *v1beta1.ClusterConfig) (windowsStackRenderingContext, error) { dns, err := cfg.Spec.Network.DNSAddress() if err != nil { return windowsStackRenderingContext{}, fmt.Errorf("failed to parse dns address: %v", err) @@ -150,14 +153,16 @@ func (n *WindowsStackComponent) makeCalicoRenderingContext(cfg *v1beta1.ClusterC return windowsStackRenderingContext{ // template rendering unescapes double backslashes - CNIBin: "c:\\\\opt\\\\cni\\\\bin", - CNIConf: "c:\\\\opt\\\\cni\\\\conf", - Mode: cfg.Spec.Network.Calico.Mode, - KubeAPIHost: cfg.Spec.API.Address, - KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port), - IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR, - Nameserver: dns, - NodeImage: "calico/windows:v3.23.5", + CNIBin: "c:\\\\opt\\\\cni\\\\bin", + CNIConf: "c:\\\\opt\\\\cni\\\\conf", + Mode: cfg.Spec.Network.Calico.Mode, + KubeAPIHost: cfg.Spec.API.Address, + KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port), + IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR, + Nameserver: dns, + NodeImage: "calico/windows:v3.23.5", + KubeProxyImage: "sigwindowstools/kube-proxy", + KubeProxyVersion: "v1.27.1-calico-hostprocess", }, nil } diff --git a/pkg/component/worker/kubeproxy_windows.go b/pkg/component/worker/kubeproxy_windows.go deleted file mode 100644 index f67fdbdaea9c..000000000000 --- a/pkg/component/worker/kubeproxy_windows.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2020 k0s 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 worker - -import ( - "context" - "fmt" - "strings" - - "github.com/k0sproject/k0s/pkg/assets" - "github.com/k0sproject/k0s/pkg/component/manager" - "github.com/k0sproject/k0s/pkg/config" - "github.com/k0sproject/k0s/pkg/constant" - "github.com/k0sproject/k0s/pkg/node" - "github.com/k0sproject/k0s/pkg/supervisor" -) - -type KubeProxy struct { - K0sVars *config.CfgVars - CIDRRange string - LogLevel string - supervisor supervisor.Supervisor -} - -var _ manager.Component = (*KubeProxy)(nil) - -// Init -func (k *KubeProxy) Init(_ context.Context) error { - return assets.Stage(k.K0sVars.BinDir, "kube-proxy.exe", constant.BinDirMode) -} - -func (k *KubeProxy) Start(ctx context.Context) error { - node, err := node.GetNodename("") - if err != nil { - return fmt.Errorf("can't get hostname: %v", err) - } - - sourceVip, err := getSourceVip() - if err != nil { - return fmt.Errorf("can't get source vip: %v", err) - } - cmd := k.K0sVars.BinDir + "\\kube-proxy.exe" - args := []string{ - "--hostname-override=" + node, - "--v=4", - "--proxy-mode=kernelspace", - fmt.Sprintf("--cluster-cidr=%s", k.CIDRRange), - "--network-name=Calico", // TODO: this is the default name - fmt.Sprintf("--kubeconfig=%s", "c:\\CalicoWindows\\calico-kube-config"), - fmt.Sprintf("--v=%s", k.LogLevel), - fmt.Sprintf("--source-vip=%s", strings.TrimSpace(sourceVip)), - "--feature-gates=WinOverlay=true", - } - k.supervisor = supervisor.Supervisor{ - Name: cmd, - BinPath: assets.BinPath(cmd, k.K0sVars.BinDir), - RunDir: k.K0sVars.RunDir, - DataDir: k.K0sVars.DataDir, - Args: args, - } - k.supervisor.Supervise() - return nil -} - -func (k *KubeProxy) Stop() error { - return k.supervisor.Stop() -} diff --git a/pkg/component/worker/stubs.go b/pkg/component/worker/stubs.go index 0813b99e859c..98833bf605e3 100644 --- a/pkg/component/worker/stubs.go +++ b/pkg/component/worker/stubs.go @@ -23,7 +23,6 @@ import ( "context" "github.com/k0sproject/k0s/pkg/component/manager" - "github.com/k0sproject/k0s/pkg/config" ) type NodesetupHelper struct { @@ -42,23 +41,3 @@ func (c NodesetupHelper) Start(_ context.Context) error { func (c NodesetupHelper) Stop() error { panic("stub component is used: NodesetupHelper which is implemented only for windows") } - -type KubeProxy struct { - K0sVars *config.CfgVars - CIDRRange string - LogLevel string -} - -var _ manager.Component = (*KubeProxy)(nil) - -func (k KubeProxy) Init(_ context.Context) error { - panic("stub component is used: KubeProxy") -} - -func (k KubeProxy) Start(_ context.Context) error { - panic("stub component is used: KubeProxy") -} - -func (k KubeProxy) Stop() error { - panic("stub component is used: KubeProxy") -} diff --git a/static/manifests/windows/DaemonSet/kube-proxy-windows.yaml b/static/manifests/windows/DaemonSet/kube-proxy-windows.yaml new file mode 100644 index 000000000000..342713738af0 --- /dev/null +++ b/static/manifests/windows/DaemonSet/kube-proxy-windows.yaml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + k8s-app: kube-proxy + name: kube-proxy-windows + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: kube-proxy-windows + template: + metadata: + labels: + k8s-app: kube-proxy-windows + spec: + serviceAccountName: kube-proxy + securityContext: + windowsOptions: + hostProcess: true + runAsUserName: "NT AUTHORITY\\system" + hostNetwork: true + containers: + - image: "{{ .KubeProxyImage }}:{{ .KubeProxyVersion }}" + args: ["$env:CONTAINER_SANDBOX_MOUNT_POINT/kube-proxy/start.ps1"] + workingDir: "$env:CONTAINER_SANDBOX_MOUNT_POINT/kube-proxy/" + name: kube-proxy + imagePullPolicy: Always + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - mountPath: /var/lib/kube-proxy + name: kube-proxy + nodeSelector: + kubernetes.io/os: windows + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - operator: Exists + volumes: + - configMap: + name: kube-proxy + name: kube-proxy + updateStrategy: + type: RollingUpdate \ No newline at end of file From 8e7063dfcf333d2612a497b2e72e0c837facf368 Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 15 Jun 2023 10:59:24 +0000 Subject: [PATCH 09/10] Use init container to create windows directories structure Signed-off-by: Mikhail Sakhnov --- cmd/controller/controller.go | 6 +- cmd/worker/worker.go | 4 -- pkg/component/worker/nodesetup_windows.go | 61 ------------------- pkg/component/worker/stubs.go | 43 ------------- .../DaemonSet/calico-windows-node.yaml | 7 +++ 5 files changed, 12 insertions(+), 109 deletions(-) delete mode 100644 pkg/component/worker/nodesetup_windows.go delete mode 100644 pkg/component/worker/stubs.go diff --git a/cmd/controller/controller.go b/cmd/controller/controller.go index 1d35e4fbb139..02efd2a9a864 100644 --- a/cmd/controller/controller.go +++ b/cmd/controller/controller.go @@ -416,9 +416,13 @@ func (c *command) start(ctx context.Context) error { if err != nil { return fmt.Errorf("failed to create calico_init manifests saver: %w", err) } + windowsStackSaver, err := controller.NewManifestsSaver("windows", c.K0sVars.DataDir) + if err != nil { + return fmt.Errorf("failed to create windows manifests saver: %w", err) + } clusterComponents.Add(ctx, controller.NewCalico(c.K0sVars, calicoInitSaver, calicoSaver)) if !slices.Contains(c.DisableComponents, constant.WindowsNodeComponentName) { - clusterComponents.Add(ctx, controller.NewWindowsStackComponent(c.K0sVars, adminClientFactory, calicoSaver)) + clusterComponents.Add(ctx, controller.NewWindowsStackComponent(c.K0sVars, adminClientFactory, windowsStackSaver)) } kubeRouterSaver, err := controller.NewManifestsSaver("kuberouter", c.K0sVars.DataDir) if err != nil { diff --git a/cmd/worker/worker.go b/cmd/worker/worker.go index 16823d808ad9..1ac28e8551e1 100644 --- a/cmd/worker/worker.go +++ b/cmd/worker/worker.go @@ -166,10 +166,6 @@ func (c *Command) Start(ctx context.Context) error { IPTablesMode: c.WorkerOptions.IPTablesMode, }) - if runtime.GOOS == "windows" { - componentManager.Add(ctx, &worker.NodesetupHelper{}) - } - certManager := worker.NewCertificateManager(ctx, kubeletKubeconfigPath) // if running inside a controller, status component is already running diff --git a/pkg/component/worker/nodesetup_windows.go b/pkg/component/worker/nodesetup_windows.go deleted file mode 100644 index 35a498823f60..000000000000 --- a/pkg/component/worker/nodesetup_windows.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2020 k0s 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 worker - -import ( - "context" - "fmt" - "os" - - "github.com/k0sproject/k0s/internal/pkg/dir" - "github.com/k0sproject/k0s/pkg/component/manager" - "github.com/sirupsen/logrus" -) - -// TODO: this all should be dropped in favor of init container for calico stack -type NodesetupHelper struct { -} - -var _ manager.Component = (*NodesetupHelper)(nil) - -func (c NodesetupHelper) Init(_ context.Context) error { - for _, path := range []string{ - "C:\\opt\\cni\\bin", - "C:\\opt\\cni\\conf", - } { - if err := dir.Init(path, 777); err != nil { - if os.IsExist(err) { - logrus.Warn("CalicoWindows already set up") - } else { - return fmt.Errorf("can't create CalicoWindows dir: %v", err) - } - } - } - return winExecute(createFirewallRules) -} - -func (c NodesetupHelper) Start(_ context.Context) error { - return nil -} - -func (c NodesetupHelper) Stop() error { - return nil -} - -const createFirewallRules = ` -$existingRule = Get-NetFirewallRule -DisplayName "kubectl exec 10250" -ErrorAction SilentlyContinue; if ($existingRule -eq $null) { New-NetFirewallRule -Name "KubectlExec10250" -Description "Enable kubectl exec and log" -Action Allow -LocalPort 10250 -Enabled True -DisplayName "kubectl exec 10250" -Protocol TCP -ErrorAction SilentlyContinue } else { Write-Output "The firewall rule already exists." } -` diff --git a/pkg/component/worker/stubs.go b/pkg/component/worker/stubs.go deleted file mode 100644 index 98833bf605e3..000000000000 --- a/pkg/component/worker/stubs.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !windows -// +build !windows - -/* -Copyright 2020 k0s 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 worker - -import ( - "context" - - "github.com/k0sproject/k0s/pkg/component/manager" -) - -type NodesetupHelper struct { -} - -var _ manager.Component = (*NodesetupHelper)(nil) - -func (c NodesetupHelper) Init(_ context.Context) error { - panic("stub component is used: NodesetupHelper which is implemented only for windows") -} - -func (c NodesetupHelper) Start(_ context.Context) error { - panic("stub component is used: NodesetupHelper which is implemented only for windows") -} - -func (c NodesetupHelper) Stop() error { - panic("stub component is used: NodesetupHelper which is implemented only for windows") -} diff --git a/static/manifests/windows/DaemonSet/calico-windows-node.yaml b/static/manifests/windows/DaemonSet/calico-windows-node.yaml index 3531d19bb8d1..7c7e03902a22 100644 --- a/static/manifests/windows/DaemonSet/calico-windows-node.yaml +++ b/static/manifests/windows/DaemonSet/calico-windows-node.yaml @@ -33,6 +33,13 @@ spec: - effect: NoExecute operator: Exists initContainers: + - name: initfilesystem + image: mcr.microsoft.com/powershell + command: [ + 'powershell.exe', + '-C', + "New-Item -Path '{{ .CNIBin }}' -ItemType Directory -Force ; New-Item -Path '{{ .CNIConf }}' -ItemType Directory -Force ; $existingRule = Get-NetFirewallRule -DisplayName 'kubectl exec 10250' -ErrorAction SilentlyContinue; if ($existingRule -eq $null) { New-NetFirewallRule -Name 'KubectlExec10250' -Description 'Enable kubectl exec and log' -Action Allow -LocalPort 10250 -Enabled True -DisplayName 'kubectl exec 10250' -Protocol TCP -ErrorAction SilentlyContinue }" + ] - name: install image: "{{ .NodeImage }}" args: From ce2b760f533952608aab69158542a01469b9fc8f Mon Sep 17 00:00:00 2001 From: Mikhail Sakhnov Date: Thu, 15 Jun 2023 11:40:31 +0000 Subject: [PATCH 10/10] Rebase fixes: go mod tidy, copyright messages Signed-off-by: Mikhail Sakhnov --- .../controller/windowsstackcomponent.go | 7 +++---- pkg/component/worker/containerd.go | 2 +- pkg/node/nodehostname.go | 20 +++++++++++++++++-- pkg/node/nodehostname_test.go | 20 +++++++++++++++++-- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/pkg/component/controller/windowsstackcomponent.go b/pkg/component/controller/windowsstackcomponent.go index 267f0cea763e..5824a6bb622d 100644 --- a/pkg/component/controller/windowsstackcomponent.go +++ b/pkg/component/controller/windowsstackcomponent.go @@ -120,20 +120,19 @@ func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context, cfg windo if err := n.createWindowsStack(n.prevRenderingContext); err != nil { n.log.Errorf("failed to create windows stack: %v", err) return fmt.Errorf("failed to create windows stack: %v", err) - } else { - n.log.Infof("successfully created windows stack") } + n.log.Infof("successfully created windows stack") return nil } func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.ClusterConfig) error { if cfg.Spec.Network.Provider != "calico" { - return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + return nil } existingCNI := existingCNIProvider(n.k0sVars.ManifestsDir) if existingCNI != "" && existingCNI != constant.CNIProviderCalico { - return fmt.Errorf("windows node controller available only for %s", constant.CNIProviderCalico) + return nil } newConfig, err := n.makeRenderingContext(cfg) if err != nil { diff --git a/pkg/component/worker/containerd.go b/pkg/component/worker/containerd.go index e6214e3ce7f7..e305d8266d34 100644 --- a/pkg/component/worker/containerd.go +++ b/pkg/component/worker/containerd.go @@ -75,9 +75,9 @@ type ContainerD struct { K0sVars *config.CfgVars Profile *workerconfig.Profile binaries []string + OCIBundlePath string confPath string importsPath string - OCIBundlePath string } func NewContainerd(logLevel string, vars *config.CfgVars, profile *workerconfig.Profile) *ContainerD { diff --git a/pkg/node/nodehostname.go b/pkg/node/nodehostname.go index 54d166d649a4..6e133cde30e5 100644 --- a/pkg/node/nodehostname.go +++ b/pkg/node/nodehostname.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 k0s 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 node import ( @@ -40,14 +56,14 @@ func getHostnameFromAwsMeta(url string) string { return s } -func getNodeNameWindows(override string, metadataUrl string) (string, error) { +func getNodeNameWindows(override string, metadataURL string) (string, error) { // if we have explicit hostnameOverride, we use it as is even on windows if override != "" { return nodeutil.GetHostname(override) } // we need to check if we have EC2 dns name available - if h := getHostnameFromAwsMeta(metadataUrl); h != "" { + if h := getHostnameFromAwsMeta(metadataURL); h != "" { return h, nil } // otherwise we use the k8s hostname helper diff --git a/pkg/node/nodehostname_test.go b/pkg/node/nodehostname_test.go index a9fc0ea2bb18..766212fe2860 100644 --- a/pkg/node/nodehostname_test.go +++ b/pkg/node/nodehostname_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 k0s 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 node import ( @@ -53,12 +69,12 @@ func TestGetNodename(t *testing.T) { func startFakeMetadataServer(listenOn string) { go func() { http.HandleFunc("/latest/meta-data/local-hostname", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("some-hostname-from-metadata")) + _, _ = w.Write([]byte("some-hostname-from-metadata")) w.WriteHeader(http.StatusOK) }) http.HandleFunc("/not-found", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }) - http.ListenAndServe(listenOn, nil) + _ = http.ListenAndServe(listenOn, nil) }() }