staging/provisioning/windows/kubeletstart.ps1 (179 lines of code) (raw):
$Global:ClusterConfiguration = ConvertFrom-Json ((Get-Content "c:\k\kubeclusterconfig.json" -ErrorAction Stop) | out-string)
$global:MasterIP = $Global:ClusterConfiguration.Kubernetes.ControlPlane.IpAddress
$global:KubeDnsSearchPath = "svc.cluster.local"
$global:KubeDnsServiceIp = $Global:ClusterConfiguration.Kubernetes.Network.DnsIp
$global:MasterSubnet = $Global:ClusterConfiguration.Kubernetes.ControlPlane.MasterSubnet
$global:KubeClusterCIDR = $Global:ClusterConfiguration.Kubernetes.Network.ClusterCidr
$global:KubeServiceCIDR = $Global:ClusterConfiguration.Kubernetes.Network.ServiceCidr
$global:KubeBinariesVersion = $Global:ClusterConfiguration.Kubernetes.Source.Release
$global:KubeDir = $Global:ClusterConfiguration.Install.Destination
$global:NetworkMode = "L2Bridge"
$global:ExternalNetwork = "ext"
$global:CNIConfig = "$CNIConfig"
$global:HNSModule = "c:\k\hns.v2.psm1"
$global:NetworkPlugin = $Global:ClusterConfiguration.Cni.Name
$global:KubeletNodeLabels = $Global:ClusterConfiguration.Kubernetes.Kubelet.NodeLabels
$global:AzureCNIDir = [Io.path]::Combine("$global:KubeDir", "azurecni")
$global:AzureCNIBinDir = [Io.path]::Combine("$global:AzureCNIDir", "bin")
$global:AzureCNIConfDir = [Io.path]::Combine("$global:AzureCNIDir", "netconf")
$global:CNIPath = [Io.path]::Combine("$global:KubeDir", "cni")
$global:CNIConfig = [Io.path]::Combine($global:CNIPath, "config", "$global:NetworkMode.conf")
$global:CNIConfigPath = [Io.path]::Combine("$global:CNIPath", "config")
ipmo $global:HNSModule
#TODO ksbrmnn refactor to be sensical instead of if if if ...
# Calculate some local paths
$global:VolumePluginDir = [Io.path]::Combine($global:KubeDir, "volumeplugins")
mkdir $global:VolumePluginDir -Force
$KubeletArgList = $Global:ClusterConfiguration.Kubernetes.Kubelet.ConfigArgs # This is the initial list passed in from aks-engine
$KubeletArgList += "--node-labels=$global:KubeletNodeLabels"
# $KubeletArgList += "--hostname-override=$global:AzureHostname" TODO: remove - dead code?
$KubeletArgList += "--volume-plugin-dir=$global:VolumePluginDir"
# If you are thinking about adding another arg here, you should be considering pkg/engine/defaults-kubelet.go first
# Only args that need to be calculated or combined with other ones on the Windows agent should be added here.
# Update args to use ContainerD
$KubeletArgList += @("--container-runtime-endpoint=npipe://./pipe/containerd-containerd")
# Kubelet flag --container-runtime has been removed from k8s 1.27
# Reference: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.27.md#other-cleanup-or-flake
if ($global:KubeBinariesVersion -lt "1.27.0") {
$KubeletArgList += @("--container-runtime=remote")
}
# Used in WinCNI version of kubeletstart.ps1
$KubeletArgListStr = ""
$KubeletArgList | Foreach-Object {
# Since generating new code to be written to a file, need to escape quotes again
if ($KubeletArgListStr.length -gt 0) {
$KubeletArgListStr = $KubeletArgListStr + ", "
}
# TODO ksbrmnn figure out what's going on here re tick marks
$KubeletArgListStr = $KubeletArgListStr + "`"" + $_.Replace("`"`"", "`"`"`"`"") + "`""
}
$KubeletArgListStr = "@($KubeletArgListStr`)"
# Used in Azure-CNI version of kubeletstart.ps1
$KubeletCommandLine = "$global:KubeDir\kubelet.exe " + ($KubeletArgList -join " ")
# Turn off Firewall to enable pods to talk to service endpoints. (Kubelet should eventually do this)
# TODO move this to CSE
netsh advfirewall set allprofiles state off
function
Get-DefaultGateway($CIDR) {
return $CIDR.substring(0, $CIDR.lastIndexOf(".")) + ".1"
}
function
Get-PodCIDR() {
$podCIDR = c:\k\kubectl.exe --kubeconfig=c:\k\config get nodes/$($env:computername.ToLower()) -o custom-columns=podCidr:.spec.podCIDR --no-headers
return $podCIDR
}
function
Test-PodCIDR($podCIDR) {
return $podCIDR.length -gt 0
}
function
Update-CNIConfigKubenetContainerD($podCIDR, $masterSubnetGW) {
$jsonSampleConfig =
"{
""cniVersion"": ""0.2.0"",
""name"": ""<NetworkMode>"",
""type"": ""sdnbridge.exe"",
""master"": ""Ethernet"",
""capabilities"": { ""portMappings"": true },
""ipam"": {
""environment"": ""azure"",
""subnet"":""<PODCIDR>"",
""routes"": [{
""GW"":""<PODGW>""
}]
},
""dns"" : {
""Nameservers"" : [ ""<NameServers>"" ],
""Search"" : [ ""<Cluster DNS Suffix or Search Path>"" ]
},
""AdditionalArgs"" : [
{
""Name"" : ""EndpointPolicy"", ""Value"" : { ""Type"" : ""OutBoundNAT"", ""Settings"" : { ""Exceptions"": [ ""<ClusterCIDR>"", ""<MgmtSubnet>"" ] }}
},
{
""Name"" : ""EndpointPolicy"", ""Value"" : { ""Type"" : ""SDNRoute"", ""Settings"" : { ""DestinationPrefix"": ""<ServiceCIDR>"", ""NeedEncap"" : true }}
}
]
}"
$configJson = ConvertFrom-Json $jsonSampleConfig
$configJson.name = $global:NetworkMode.ToLower()
$configJson.ipam.subnet = $podCIDR
$configJson.ipam.routes[0].GW = $masterSubnetGW
$configJson.dns.Nameservers[0] = $global:KubeDnsServiceIp
$configJson.dns.Search[0] = $global:KubeDnsSearchPath
$configJson.AdditionalArgs[0].Value.Settings.Exceptions[0] = $global:KubeClusterCIDR
$configJson.AdditionalArgs[0].Value.Settings.Exceptions[1] = $global:MasterSubnet
$configJson.AdditionalArgs[1].Value.Settings.DestinationPrefix = $global:KubeServiceCIDR
if (Test-Path $global:CNIConfig) {
Clear-Content -Path $global:CNIConfig
}
Write-Host "Generated CNI Config [$configJson]"
Add-Content -Path $global:CNIConfig -Value (ConvertTo-Json $configJson -Depth 20)
}
# Required to clean up the HNS policy lists properly
Write-Host "Stopping kubeproxy service"
Stop-Service kubeproxy
if ($global:NetworkPlugin -eq "azure") {
Write-Host "NetworkPlugin azure, starting kubelet."
# Find if network created by CNI exists, if yes, remove it
# This is required to keep the network non-persistent behavior
# Going forward, this would be done by HNS automatically during restart of the node
& "c:\k\cleanupnetwork.ps1"
# Restart Kubeproxy, which would wait, until the network is created
# This was fixed in 1.15, workaround still needed for 1.14 https://github.com/kubernetes/kubernetes/pull/78612
Restart-Service Kubeproxy -Force
# Set env file for Azure Stack
$env:AZURE_ENVIRONMENT_FILEPATH = "c:\k\azurestackcloud.json"
}
if ($global:NetworkPlugin -eq "kubenet") {
try {
$env:AZURE_ENVIRONMENT_FILEPATH = "c:\k\azurestackcloud.json"
$masterSubnetGW = Get-DefaultGateway $global:MasterSubnet
$podCIDR = Get-PodCIDR
$podCidrDiscovered = Test-PodCIDR($podCIDR)
# if the podCIDR has not yet been assigned to this node, start the kubelet process to get the podCIDR, and then promptly kill it.
if (-not $podCidrDiscovered) {
$process = Start-Process -FilePath c:\k\kubelet.exe -PassThru -ArgumentList $KubeletArgList
# run kubelet until podCidr is discovered
Write-Host "waiting to discover pod CIDR"
while (-not $podCidrDiscovered) {
Write-Host "Sleeping for 10s, and then waiting to discover pod CIDR"
Start-Sleep 10
$podCIDR = Get-PodCIDR
$podCidrDiscovered = Test-PodCIDR($podCIDR)
}
# stop the kubelet process now that we have our CIDR, discard the process output
$process | Stop-Process | Out-Null
}
& "c:\k\cleanupnetwork.ps1"
Write-Host "Creating a new hns Network"
$hnsNetwork = New-HNSNetwork -Type $global:NetworkMode -AddressPrefix $podCIDR -Gateway $masterSubnetGW -Name $global:NetworkMode.ToLower() -Verbose
# New network has been created, Kubeproxy service has to be restarted
# This was fixed in 1.15, workaround still needed for 1.14 https://github.com/kubernetes/kubernetes/pull/78612
Restart-Service Kubeproxy
Start-Sleep 10
if ($global:ContainerRuntime -eq "containerd") {
Write-Host "Updating CNI config"
Update-CNIConfigKubenetContainerD $podCIDR $masterSubnetGW
}
if ($global:ContainerRuntime -eq "docker") {
# Add route to all other POD networks
Update-CNIConfigKubenetDocker $podCIDR $masterSubnetGW
}
}
catch {
Write-Error $_
}
}
# Start the kubelet
# Use run-process.cs to set process priority class as 'AboveNormal'
# Load a signed version of runprocess.dll if it exists for Azure SysLock compliance
# otherwise load class from cs file (for CI/testing)
if (Test-Path "$global:KubeDir\runprocess.dll") {
[System.Reflection.Assembly]::LoadFrom("$global:KubeDir\runprocess.dll")
} else {
Add-Type -Path "$global:KubeDir\run-process.cs"
}
$exe = "$global:KubeDir\kubelet.exe"
$args = ($KubeletArgList -join " ")
[RunProcess.exec]::RunProcess($exe, $args, [System.Diagnostics.ProcessPriorityClass]::AboveNormal)