staging/cse/windows/kubeletfunc.ps1 (355 lines of code) (raw):
function Write-AzureConfig {
Param(
[Parameter(Mandatory = $true)][string]
$AADClientId,
[Parameter(Mandatory = $true)][string]
$AADClientSecret,
[Parameter(Mandatory = $true)][string]
$TenantId,
[Parameter(Mandatory = $true)][string]
$SubscriptionId,
[Parameter(Mandatory = $true)][string]
$ResourceGroup,
[Parameter(Mandatory = $true)][string]
$Location,
[Parameter(Mandatory = $true)][string]
$VmType,
[Parameter(Mandatory = $true)][string]
$SubnetName,
[Parameter(Mandatory = $true)][string]
$SecurityGroupName,
[Parameter(Mandatory = $true)][string]
$VNetName,
[Parameter(Mandatory = $true)][string]
$RouteTableName,
[Parameter(Mandatory = $false)][string] # Need one of these configured
$PrimaryAvailabilitySetName,
[Parameter(Mandatory = $false)][string] # Need one of these configured
$PrimaryScaleSetName,
[Parameter(Mandatory = $true)][string]
$UseManagedIdentityExtension,
[string]
$UserAssignedClientID,
[Parameter(Mandatory = $true)][string]
$UseInstanceMetadata,
[Parameter(Mandatory = $true)][string]
$LoadBalancerSku,
[Parameter(Mandatory = $true)][string]
$ExcludeMasterFromStandardLB,
[Parameter(Mandatory = $true)][string]
$KubeDir,
[Parameter(Mandatory = $true)][string]
$TargetEnvironment,
[Parameter(Mandatory = $false)][bool]
$UseContainerD = $false
)
Logs-To-Event -TaskName "AKS.WindowsCSE.WriteAzureCloudProviderConfig" -TaskMessage "Start to write Azure Cloud Provider Config"
if ( $VmType -eq "vmss" -And -Not $PrimaryAvailabilitySetName -And -Not $PrimaryScaleSetName ) {
Set-ExitCode -ExitCode $global:WINDOWS_CSE_ERROR_INVALID_PARAMETER_IN_AZURE_CONFIG -ErrorMessage "Either PrimaryAvailabilitySetName or PrimaryScaleSetName must be set"
}
$azureConfigFile = [io.path]::Combine($KubeDir, "azure.json")
$azureConfig = @"
{
"cloud": "$TargetEnvironment",
"tenantId": "$TenantId",
"subscriptionId": "$SubscriptionId",
"aadClientId": "$AADClientId",
"aadClientSecret": "$AADClientSecret",
"resourceGroup": "$ResourceGroup",
"location": "$Location",
"vmType": "$VmType",
"subnetName": "$SubnetName",
"securityGroupName": "$SecurityGroupName",
"vnetName": "$VNetName",
"routeTableName": "$RouteTableName",
"primaryAvailabilitySetName": "$PrimaryAvailabilitySetName",
"primaryScaleSetName": "$PrimaryScaleSetName",
"useManagedIdentityExtension": $UseManagedIdentityExtension,
"userAssignedIdentityID": "$UserAssignedClientID",
"useInstanceMetadata": $UseInstanceMetadata,
"loadBalancerSku": "$LoadBalancerSku",
"excludeMasterFromStandardLB": $ExcludeMasterFromStandardLB
}
"@
$azureConfig | Out-File -encoding ASCII -filepath "$azureConfigFile"
}
function Write-CACert {
Param(
[Parameter(Mandatory = $true)][string]
$CACertificate,
[Parameter(Mandatory = $true)][string]
$KubeDir
)
Logs-To-Event -TaskName "AKS.WindowsCSE.WriteCACert" -TaskMessage "Start to write ca root"
$caFile = [io.path]::Combine($KubeDir, "ca.crt")
[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($CACertificate)) | Out-File -Encoding ascii $caFile
}
function Write-KubeConfig {
Param(
[Parameter(Mandatory = $true)][string]
$CACertificate,
[Parameter(Mandatory = $true)][string]
$MasterFQDNPrefix,
[Parameter(Mandatory = $true)][string]
$MasterIP,
[Parameter(Mandatory = $true)][string]
$AgentKey,
[Parameter(Mandatory = $true)][string]
$AgentCertificate,
[Parameter(Mandatory = $true)][string]
$KubeDir
)
Logs-To-Event -TaskName "AKS.WindowsCSE.WriteKubeConfig" -TaskMessage "Start to write kube config"
$kubeConfigFile = [io.path]::Combine($KubeDir, "config")
$kubeConfig = @"
---
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: "$CACertificate"
server: https://${MasterIP}:443
name: "$MasterFQDNPrefix"
contexts:
- context:
cluster: "$MasterFQDNPrefix"
user: "$MasterFQDNPrefix-admin"
name: "$MasterFQDNPrefix"
current-context: "$MasterFQDNPrefix"
kind: Config
users:
- name: "$MasterFQDNPrefix-admin"
user:
client-certificate-data: "$AgentCertificate"
client-key-data: "$AgentKey"
"@
$kubeConfig | Out-File -encoding ASCII -filepath "$kubeConfigFile"
}
function Write-BootstrapKubeConfig {
Param(
[Parameter(Mandatory = $true)][string]
$CACertificate,
[Parameter(Mandatory = $true)][string]
$MasterFQDNPrefix,
[Parameter(Mandatory = $true)][string]
$MasterIP,
[Parameter(Mandatory = $true)][string]
$TLSBootstrapToken,
[Parameter(Mandatory = $true)][string]
$KubeDir
)
Logs-To-Event -TaskName "AKS.WindowsCSE.WriteBootstrapKubeConfig" -TaskMessage "Start to write TLS bootstrap kubeconfig"
$bootstrapKubeConfigFile = [io.path]::Combine($KubeDir, "bootstrap-config")
$bootstrapKubeConfig = @"
---
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: "$CACertificate"
server: https://${MasterIP}:443
name: "$MasterFQDNPrefix"
contexts:
- context:
cluster: "$MasterFQDNPrefix"
user: "kubelet-bootstrap"
name: "$MasterFQDNPrefix"
current-context: "$MasterFQDNPrefix"
kind: Config
users:
- name: "kubelet-bootstrap"
user:
token: "$TLSBootstrapToken"
"@
$bootstrapKubeConfig | Out-File -encoding ASCII -filepath "$bootstrapKubeConfigFIle"
}
function Get-KubePackage {
Param(
[Parameter(Mandatory = $true)][string]
$KubeBinariesSASURL
)
$mappingFile = [Io.path]::Combine($global:CacheDir, "private-packages\mapping.json")
if (Test-Path $mappingFile) {
$urls = @{}
(ConvertFrom-Json ((Get-Content $mappingFile -ErrorAction Stop) | Out-String)).psobject.properties | Foreach { $urls[$_.Name] = $_.Value }
if ($urls.ContainsKey($global:KubeBinariesVersion)) {
Write-Log "Found $global:KubeBinariesVersion in $mappingFile"
$KubeBinariesSASURL = $urls[$global:KubeBinariesVersion]
} else {
Write-Log "Did not find $global:KubeBinariesVersion in $mappingFile"
}
}
Logs-To-Event -TaskName "AKS.WindowsCSE.DownloadKubletBinaries" -TaskMessage "Start to download kubelet binaries and unzip. KubeBinariesPackageSASURL: $KubeBinariesSASURL"
$zipfile = "c:\k.zip"
for ($i = 0; $i -le 10; $i++) {
DownloadFileOverHttp -Url $KubeBinariesSASURL -DestinationPath $zipfile -ExitCode $global:WINDOWS_CSE_ERROR_DOWNLOAD_KUBERNETES_PACKAGE
if ($?) {
break
}
else {
Write-Log $Error[0].Exception.Message
}
}
Expand-Archive -path $zipfile -DestinationPath C:\
Remove-Item $zipfile
}
function Add-KubeletNodeLabel {
Param(
[Parameter(Mandatory=$true)][string]
$Label
)
$labelList = $global:KubeletNodeLabels -split ","
foreach ($existingLabel in $labelList) {
if ($existingLabel -eq $Label) {
Write-Log "found existing kubelet node label $existingLabel, will continue without adding anything"
return
}
}
Write-Log "adding label $Label to kubelet node labels..."
$labelList += $Label
$global:KubeletNodeLabels = $labelList -join ","
}
function Remove-KubeletNodeLabel {
Param(
[Parameter(Mandatory=$true)][string]
$Label
)
$labelList = $global:KubeletNodeLabels -split ","
$filtered = $labelList | Where-Object { $_ -ne $Label }
$global:KubeletNodeLabels = $filtered -join ","
}
function Get-TagValue {
Param(
[Parameter(Mandatory=$true)][string]
$TagName,
[Parameter(Mandatory=$true)][string]
$DefaultValue
)
$uri = "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
try {
$response = Retry-Command -Command "Invoke-RestMethod" -Args @{Uri=$uri; Method="Get"; ContentType="application/json"; Headers=@{"Metadata"="true"}} -Retries 3 -RetryDelaySeconds 5
} catch {
Set-ExitCode -ExitCode $global:WINDOWS_CSE_ERROR_LOOKUP_INSTANCE_DATA_TAG -ErrorMessage "Unable to lookup VM tag `"$TagName`" from IMDS instance data"
}
$tag = $response.compute.tagsList | Where-Object { $_.name -eq $TagName }
if (!$tag) {
return $DefaultValue
}
return $tag.value
}
# Note: this function modifies global kubelet config args and node labels. Thus, it MUST
# be called before Write-KubeClusterConfig, and any other function that relies on the values of
# kubelet config args and node labels.
function Configure-KubeletServingCertificateRotation {
Logs-To-Event `
-TaskName "AKS.WindowsCSE.ConfigureKubeletServingCertificateRotation" `
-TaskMessage "EnableKubeletServingCertificateRotation: $global:EnableKubeletServingCertificateRotation. Configure kubelet config args and node labels for serving certificate rotation"
if (!($global:EnableKubeletServingCertificateRotation)) {
Write-Log "Kubelet serving certificate rotation is disabled, nothing to configure"
return
}
$nodeLabel = "kubernetes.azure.com/kubelet-serving-ca=cluster"
# check if kubelet serving certificate rotation is disabled via customer-specified nodepool tags
$tagName = "aks-disable-kubelet-serving-certificate-rotation"
$disabled = Get-TagValue -TagName $tagName -DefaultValue "false"
if ($disabled -eq "true") {
Write-Log "Kubelet serving certificate rotation is disabled by nodepool tags, will reconfigure kubelet flags and node labels"
$global:KubeletConfigArgs = $global:KubeletConfigArgs -replace "--rotate-server-certificates=true", "--rotate-server-certificates=false"
Remove-KubeletNodeLabel -Label $nodeLabel
return
}
Write-Log "Kubelet serving certificate rotation is enabled, will add node label if needed"
Add-KubeletNodeLabel -Label $nodeLabel
}
# DEPRECATED - TODO(cameissner): remove once k8s setup script has been updated
function Disable-KubeletServingCertificateRotationForTags {
Logs-To-Event `
-TaskName "AKS.WindowsCSE.DisableKubeletServingCertificateRotationForTags" `
-TaskMessage "EnableKubeletServingCertificateRotation: $global:EnableKubeletServingCertificateRotation. Check whether to disable kubelet serving certificate rotation via nodepool tags."
Write-Log "Checking whether to disable kubelet serving certificate rotation for nodepool tags"
if (!($global:EnableKubeletServingCertificateRotation)) {
Write-Log "Kubelet serving certificate rotation is already disabled"
return
}
$tagName = "aks-disable-kubelet-serving-certificate-rotation"
$disabled = Get-TagValue -TagName $tagName -DefaultValue "false"
if ($disabled -ne "true") {
Write-Log "Nodepool tag `"$tagName`" is missing or not set to true, nothing to disable"
return
}
Write-Log "Kubelet serving certificate rotation is disabled by nodepool tags, will reconfigure kubelet flags and node labels"
$global:KubeletConfigArgs = $global:KubeletConfigArgs -replace "--rotate-server-certificates=true", "--rotate-server-certificates=false"
Remove-KubeletNodeLabel -Label "kubernetes.azure.com/kubelet-serving-ca=cluster"
}
# TODO: replace KubeletStartFile with a Kubelet config, remove NSSM, and use built-in service integration
function New-NSSMService {
Param(
[string]
[Parameter(Mandatory = $true)]
$KubeDir,
[string]
[Parameter(Mandatory = $true)]
$KubeletStartFile,
[string]
[Parameter(Mandatory = $true)]
$KubeProxyStartFile
)
$kubeletDependOnServices = "containerd"
if ($global:EnableCsiProxy) {
$kubeletDependOnServices += " csi-proxy"
}
if ($global:EnableHostsConfigAgent) {
$kubeletDependOnServices += " hosts-config-agent"
}
# setup kubelet
& "$KubeDir\nssm.exe" install Kubelet C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppDirectory $KubeDir | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppParameters $KubeletStartFile | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet DisplayName Kubelet | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppRestartDelay 5000 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet Description Kubelet | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet Start SERVICE_DEMAND_START | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet ObjectName LocalSystem | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet Type SERVICE_WIN32_OWN_PROCESS | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppThrottle 1500 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppStdout C:\k\kubelet.log | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppStderr C:\k\kubelet.err.log | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppStdoutCreationDisposition 4 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppStderrCreationDisposition 4 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppRotateFiles 1 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppRotateOnline 1 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppRotateSeconds 86400 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubelet AppRotateBytes 10485760 | RemoveNulls
# Do not use & when calling DependOnService since 'docker csi-proxy'
# is parsed as a single string instead of two separate strings
Invoke-Expression "$KubeDir\nssm.exe set Kubelet DependOnService $kubeletDependOnServices | RemoveNulls"
# setup kubeproxy
& "$KubeDir\nssm.exe" install Kubeproxy C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppDirectory $KubeDir | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppParameters $KubeProxyStartFile | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy DisplayName Kubeproxy | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy DependOnService Kubelet | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy Description Kubeproxy | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy Start SERVICE_DEMAND_START | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy ObjectName LocalSystem | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy Type SERVICE_WIN32_OWN_PROCESS | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppThrottle 1500 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppStdout C:\k\kubeproxy.log | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppStderr C:\k\kubeproxy.err.log | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppRotateFiles 1 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppRotateOnline 1 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppRotateSeconds 86400 | RemoveNulls
& "$KubeDir\nssm.exe" set Kubeproxy AppRotateBytes 10485760 | RemoveNulls
}
# Renamed from Write-KubernetesStartFiles
function Install-KubernetesServices {
param(
[Parameter(Mandatory = $true)][string]
$KubeDir
)
Logs-To-Event -TaskName "AKS.WindowsCSE.InstallKubernetesServices" -TaskMessage "Start to install kubernetes services"
# TODO ksbrmnn fix callers to this function
$KubeletStartFile = [io.path]::Combine($KubeDir, "kubeletstart.ps1")
$KubeProxyStartFile = [io.path]::Combine($KubeDir, "kubeproxystart.ps1")
New-NSSMService -KubeDir $KubeDir `
-KubeletStartFile $KubeletStartFile `
-KubeProxyStartFile $KubeProxyStartFile
}