feat: Experimental support for Windows+ContainerD (#1322)

This commit is contained in:
Mark Rossetti 2020-03-05 12:40:01 -08:00 коммит произвёл GitHub
Родитель 1bbc94a1cc
Коммит b068aa700c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
22 изменённых файлов: 1246 добавлений и 98 удалений

Просмотреть файл

@ -1,5 +1,7 @@
# Cluster Definitions
## Cluster Defintions for apiVersion "vlabs"
Here are the cluster definitions for apiVersion "vlabs":
@ -41,13 +43,15 @@ $ aks-engine get-versions
| apiServerConfig | no | Configure various runtime configuration for apiserver. See `apiServerConfig` [below](#feat-apiserver-config) |
| cloudControllerManagerConfig | no | Configure various runtime configuration for cloud-controller-manager. See `cloudControllerManagerConfig` [below](#feat-cloud-controller-manager-config) |
| clusterSubnet | no | The IP subnet used for allocating IP addresses for pod network interfaces. The subnet must be in the VNET address space. With Azure CNI enabled, the default value is 10.240.0.0/12. Without Azure CNI, the default value is 10.244.0.0/16. |
| containerRuntime | no | The container runtime to use as a backend. The default is `docker`. The other options are `kata-containers`, and `containerd` |
| containerRuntime | no | The container runtime to use as a backend. The default is `docker`. The other options are `kata-containers`, and `containerd`. Windows support for `containerd` is **Experimental** - see [Windows ContainerD](features.md#windows-containerd) |
| controllerManagerConfig | no | Configure various runtime configuration for controller-manager. See `controllerManagerConfig` [below](#feat-controller-manager-config) |
| customWindowsPackageURL | no | Configure custom windows Kubernetes release package URL for deployment on Windows. The format of this file is a zip file with multiple items (binaries, cni, infra container) in it. This setting will be deprecated in a future release of aks-engine where the binaries will be pulled in the format of Kubernetes releases that only contain the kubernetes binaries. |
| WindowsNodeBinariesURL | no | Windows Kubernetes Node binaries can be provided in the format of Kubernetes release (example: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md#node-binaries-1). This setting allows overriding the binaries for custom builds. |
| WindowsContainerdURL | no (for development only) | **Experimental** - see [Windows ContainerD](features.md#windows-containerd) |
| WindowsSdnPluginURL | no (for development only) | **Experimental** - see [Windows ContainerD](features.md#windows-containerd) |
| dnsServiceIP | no | IP address for coredns or kube-dns to listen on. If specified must be in the range of `serviceCidr` |
| mobyVersion | no (for development only) | Enables an explicit moby version, e.g. `3.0.3`. Default is `3.0.5`. This `kubernetesConfig` property is for development only, and applies only to cluster creation: `aks-engine upgrade` will always statically set `mobyVersion` to the default version at the time of upgrade, to ensure that upgraded clusters have the most recent, validated version of moby. |
| containerdVersion | no (for development only) | Enables an explicit containerd version, e.g. `1.1.4`. Default is `1.1.5`. This `kubernetesConfig` property is for development only, and applies only to cluster creation: `aks-engine upgrade` will always statically set `containerdVersion` to the default version at the time of upgrade, to ensure that upgraded clusters have the most recent, validated version of containerd. |
| containerdVersion | no (for development only) | Enables an explicit containerd version, e.g. `1.1.4`. Default is `1.1.5`. This `kubernetesConfig` property is for development only, and applies only to cluster creation: `aks-engine upgrade` will always statically set `containerdVersion` to the default version at the time of upgrade, to ensure that upgraded clusters have the most recent, validated version of containerd. This value is currently ignored for Windows. |
| dockerBridgeSubnet | no | The specific IP and subnet used for allocating IP addresses for the docker bridge network created on the kubernetes master and agents. Default value is 172.17.0.1/16. This value is used to configure the docker daemon using the [--bip flag](https://docs.docker.com/engine/userguide/networking/default_network/custom-docker0) |
| enableAggregatedAPIs | no | Enable [Kubernetes Aggregated APIs](https://kubernetes.io/docs/concepts/api-extension/apiserver-aggregation/). enableRbac must be set to true to use aggregated APIs. Aggregated API functionality is required by [Service Catalog](https://github.com/kubernetes-incubator/service-catalog/blob/master/README.md). (boolean - default is true) |
| enableDataEncryptionAtRest | no | Enable [kubernetes data encryption at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).This is currently an alpha feature. (boolean - default == false) |

Просмотреть файл

@ -2,17 +2,17 @@
|Feature|Status|API Version|Example|Description|
|---|---|---|---|---|
|Managed Disks|Beta|`vlabs`|[kubernetes-vmas.json](../../examples/disks-managed/kubernetes-vmas.json)|[Description](#feat-managed-disks)|
|Antrea Network Policy|Alpha|`vlabs`|[kubernetes-antrea.json](../../examples/networkpolicy/kubernetes-antrea.json)|[Description](#feat-antrea)|
|Azure Key Vault Encryption|Alpha|`vlabs`|[kubernetes-keyvault-encryption.json](../../examples/kubernetes-config/kubernetes-keyvault-encryption.json)|[Description](#feat-keyvault-encryption)|
|Calico Network Policy|Alpha|`vlabs`|[kubernetes-calico.json](../../examples/networkpolicy/kubernetes-calico-azure.json)|[Description](#feat-calico)|
|Cilium Network Policy|Alpha|`vlabs`|[kubernetes-cilium.json](../../examples/networkpolicy/kubernetes-cilium.json)|[Description](#feat-cilium)|
|Antrea Network Policy|Alpha|`vlabs`|[kubernetes-antrea.json](../../examples/networkpolicy/kubernetes-antrea.json)|[Description](#feat-antrea)|
|ContainerD Runtime for Windows|Experimental|`vlabs`|[kubernetes-hybrid.containerd.json](../../examples/windows/kubernetes-hybrid.containerd.json)|[Description](#windows-containerd)|
|Custom VNET|Beta|`vlabs`|[kubernetesvnet-azure-cni.json](../../examples/vnet/kubernetesvnet-azure-cni.json)|[Description](#feat-custom-vnet)|
|Kata Containers Runtime|Alpha|`vlabs`|[kubernetes-kata-containers.json](../../examples/kubernetes-kata-containers.json)|[Description](#feat-kata-containers)|
|Private Cluster|Alpha|`vlabs`|[kubernetes-private-cluster.json](../../examples/kubernetes-config/kubernetes-private-cluster.json)|[Description](#feat-private-cluster)|
|Azure Key Vault Encryption|Alpha|`vlabs`|[kubernetes-keyvault-encryption.json](../../examples/kubernetes-config/kubernetes-keyvault-encryption.json)|[Description](#feat-keyvault-encryption)|
|Shared Image Gallery images|Alpha|`vlabs`|[custom-shared-image.json](../../examples/custom-shared-image.json)|[Description](#feat-shared-image-gallery)|
|Ephemeral OS Disks|Experimental|`vlabs`|[ephmeral-disk.json](../../examples/disks-ephemeral/ephemeral-disks.json)|[Description](#ephemeral-os-disks)|
|Kata Containers Runtime|Alpha|`vlabs`|[kubernetes-kata-containers.json](../../examples/kubernetes-kata-containers.json)|[Description](#feat-kata-containers)|
|Managed Disks|Beta|`vlabs`|[kubernetes-vmas.json](../../examples/disks-managed/kubernetes-vmas.json)|[Description](#feat-managed-disks)|
|Private Cluster|Alpha|`vlabs`|[kubernetes-private-cluster.json](../../examples/kubernetes-config/kubernetes-private-cluster.json)|[Description](#feat-private-cluster)|
|Shared Image Gallery images|Alpha|`vlabs`|[custom-shared-image.json](../../examples/custom-shared-image.json)|[Description](#feat-shared-image-gallery)|
<a name="feat-kubernetes-msi"></a>
@ -543,3 +543,34 @@ We are investigating possible risks & mitigations for when VMs are deprovisioned
[Ephemeral OS Disks]: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/ephemeral-os-disks
## Windows ContainerD
> This feature is currently experimental, and has open issues.
Kubernetes 1.18 introduces alpha support for the ContainerD runtime on Windows Server 2019. This is still a work-in-progress tracked in [kubernetes/enhancements#1001](https://github.com/kubernetes/enhancements/issues/1001). This feature in AKS-Engine is for testing the in-development versions of ContainerD and Kubernetes, and is not for production use. Be sure to review [open issues](https://github.com/azure/aks-engine/issues?q=containerd+label%3Awindows+is%3Aopen) if you want to test or contribute to this effort.
Currently it only supports the `kubenet` networking model, and requires URLs to custom ContainerD and CNI plugin builds.
### Deploying multi-OS clusters with ContainerD
If you want to test or develop with Windows & ContainerD in AKS-Engine, see this sample
[kubernetes-hybrid.containerd.json](../../examples/windows/kubernetes-hybrid.containerd.json)
These parameters are all required.
```json
"kubernetesConfig": {
"networkPlugin": "kubenet",
"containerRuntime": "containerd",
"windowsContainerdURL": "...",
"windowsSdnPluginURL": "..."
}
```
### Building ContainerD
As of March 3, 2020, the ContainerD and network plugin repos don't have public builds available. This repo has a script that will build them from source and create two ZIP files: [build-windows-containerd.sh](../../scripts/build-windows-containerd.sh)
Upload these ZIP files to a location that your cluster will be able to reach, then put those URLs in `windowsContainerdURL` and `windowsSdnPluginURL` in the AKS-Engine apimodel shown above.

Просмотреть файл

@ -0,0 +1,55 @@
{
"apiVersion": "vlabs",
"properties": {
"orchestratorProfile": {
"orchestratorType": "Kubernetes",
"orchestratorRelease": "1.18",
"kubernetesConfig": {
"networkPlugin": "kubenet",
"containerRuntime": "containerd",
"windowsContainerdURL": "https://aksenginee2etestimages.blob.core.windows.net/test-content/windows-cri-containerd.zip",
"windowsSdnPluginURL": "https://aksenginee2etestimages.blob.core.windows.net/test-content/windows-cni-containerd.zip"
}
},
"masterProfile": {
"count": 1,
"dnsPrefix": "",
"vmSize": "Standard_D2_v2"
},
"agentPoolProfiles": [
{
"name": "linuxpool1",
"count": 2,
"vmSize": "Standard_D2_v2",
"availabilityProfile": "AvailabilitySet"
},
{
"name": "windowspool2",
"count": 2,
"vmSize": "Standard_D2s_v3",
"availabilityProfile": "AvailabilitySet",
"osType": "Windows"
}
],
"windowsProfile": {
"adminUsername": "azureuser",
"adminPassword": "replacepassword1234$",
"enableAutomaticUpdates": false,
"sshEnabled": true
},
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": ""
}
]
}
},
"servicePrincipalProfile": {
"clientId": "",
"secret": ""
}
}
}

Просмотреть файл

@ -220,3 +220,14 @@ function Register-NodeResetScriptTask {
$definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Description "k8s-restart-job"
Register-ScheduledTask -TaskName "k8s-restart-job" -InputObject $definition
}
function Assert-FileExists {
Param(
[Parameter(Mandatory=$true,Position=0)][string]
$Filename
)
if (-Not (Test-Path $Filename)) {
throw "$Filename does not exist"
}
}

Просмотреть файл

@ -65,10 +65,15 @@ $global:AgentCertificate = "{{WrapAsParameter "clientCertificate"}}"
$global:KubeBinariesPackageSASURL = "{{WrapAsParameter "kubeBinariesSASURL"}}"
$global:WindowsKubeBinariesURL = "{{WrapAsParameter "windowsKubeBinariesURL"}}"
$global:KubeBinariesVersion = "{{WrapAsParameter "kubeBinariesVersion"}}"
$global:ContainerdUrl = "{{WrapAsParameter "windowsContainerdURL"}}"
$global:ContainerdSdnPluginUrl = "{{WrapAsParameter "windowsSdnPluginURL"}}"
## Docker Version
$global:DockerVersion = "{{WrapAsParameter "windowsDockerVersion"}}"
## ContainerD Usage
$global:ContainerRuntime = "{{WrapAsParameter "containerRuntime"}}"
## VM configuration passed by Azure
$global:WindowsTelemetryGUID = "{{WrapAsParameter "windowsTelemetryGUID"}}"
{{if eq GetIdentitySystem "adfs"}}
@ -145,14 +150,9 @@ Expand-Archive scripts.zip -DestinationPath "C:\\AzureData\\"
. c:\AzureData\k8s\windowscnifunc.ps1
. c:\AzureData\k8s\windowsazurecnifunc.ps1
. c:\AzureData\k8s\windowsinstallopensshfunc.ps1
. c:\AzureData\k8s\windowscontainerdfunc.ps1
function
Update-ServiceFailureActions()
{
sc.exe failure "kubelet" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "kubeproxy" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "docker" actions= restart/60000/restart/60000/restart/60000 reset= 900
}
$useContainerD = ($global:ContainerRuntime -eq "containerd")
try
{
@ -222,12 +222,22 @@ try
Write-Log "Create required data directories as needed"
Initialize-DataDirectories
Write-Log "Install docker"
$dockerTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Docker -DockerVersion $global:DockerVersion
Set-DockerLogFileOptions
$dockerTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-Docker", $dockerTimer.Elapsed.TotalSeconds)
if ($useContainerD) {
Write-Log "Installing ContainerD"
$containerdTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Containerd -ContainerdUrl $global:ContainerdUrl
$containerdTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-ContainerD", $containerdTimer.Elapsed.TotalSeconds)
# TODO: disable/uninstall Docker later
} else {
Write-Log "Install docker"
$dockerTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Docker -DockerVersion $global:DockerVersion
Set-DockerLogFileOptions
$dockerTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-Docker", $dockerTimer.Elapsed.TotalSeconds)
}
Write-Log "Download kubelet binaries and unzip"
Get-KubePackage -KubeBinariesSASURL $global:KubeBinariesPackageSASURL
@ -284,14 +294,19 @@ try
Write-Log "Create the Pause Container kubletwin/pause"
$infraContainerTimer = [System.Diagnostics.Stopwatch]::StartNew()
New-InfraContainer -KubeDir $global:KubeDir
New-InfraContainer -KubeDir $global:KubeDir -ContainerRuntime $global:ContainerRuntime
$infraContainerTimer.Stop()
$global:AppInsightsClient.TrackMetric("New-InfraContainer", $infraContainerTimer.Elapsed.TotalSeconds)
if (-not (Test-ContainerImageExists -Image "kubletwin/pause")) {
if (-not (Test-ContainerImageExists -Image "kubletwin/pause" -ContainerRuntime $global:ContainerRuntime)) {
Write-Log "Could not find container with name kubletwin/pause"
$o = docker image list
Write-Log $o
if ($useContainerD) {
$o = ctr -n k8s.io image list
Write-Log $o
} else {
$o = docker image list
Write-Log $o
}
throw "kubletwin/pause container does not exist!"
}
@ -330,7 +345,13 @@ try
}
elseif ($global:NetworkPlugin -eq "kubenet") {
Write-Log "Fetching additional files needed for kubenet"
Update-WinCNI -CNIPath $global:CNIPath
if ($useContainerD) {
# TODO: CNI may need to move to c:\program files\containerd\cni\bin with ContainerD
Install-SdnBridge -Url $global:ContainerdSdnPluginUrl -CNIPath $global:CNIPath
} else {
Update-WinCNI -CNIPath $global:CNIPath
}
Get-HnsPsm1 -HNSModule $global:HNSModule
}
New-ExternalHnsNetwork
@ -354,7 +375,8 @@ try
-KubeClusterCIDR $global:KubeClusterCIDR `
-KubeServiceCIDR $global:KubeServiceCIDR `
-HNSModule $global:HNSModule `
-KubeletNodeLabels $global:KubeletNodeLabels
-KubeletNodeLabels $global:KubeletNodeLabels `
-UseContainerD $useContainerD
Get-LogCollectionScripts
@ -368,7 +390,7 @@ try
PREPROVISION_EXTENSION
Write-Log "Update service failure actions"
Update-ServiceFailureActions
Update-ServiceFailureActions -ContainerRuntime $global:ContainerRuntime
Adjust-DynamicPortRange
Register-LogsCleanupScriptTask
@ -390,7 +412,7 @@ try
else
{
# keep for debugging purposes
Write-Log ".\CustomDataSetupScript.ps1 -MasterIP $MasterIP -KubeDnsServiceIp $KubeDnsServiceIp -MasterFQDNPrefix $MasterFQDNPrefix -Location $Location -AgentKey $AgentKey -AADClientId $AADClientId -AADClientSecret $AADClientSecret"
Write-Log ".\CustomDataSetupScript.ps1 -MasterIP $MasterIP -KubeDnsServiceIp $KubeDnsServiceIp -MasterFQDNPrefix $MasterFQDNPrefix -Location $Location -AgentKey $AgentKey -AADClientId $AADClientId -AADClientSecret $AADClientSecret -NetworkAPIVersion $NetworkAPIVersion -TargetEnvironment $TargetEnvironment"
}
}
catch

Просмотреть файл

@ -22,4 +22,19 @@ function Update-WinCNI
DownloadFileOverHttp -Url $WinCniUrl -DestinationPath $wincniFile
}
function Install-SdnBridge
{
Param(
[Parameter(Mandatory=$true)][string]
$Url,
[Parameter(Mandatory=$true)][string]
$CNIPath
)
$cnizip = [Io.path]::Combine($CNIPath, "cni.zip")
DownloadFileOverHttp -Url $Url -DestinationPath $cnizip
Expand-Archive -path $cnizip -DestinationPath $CNIPath
del $cnizip
}
# TODO: Move the code that creates the wincni configuration file out of windowskubeletfunc.ps1 and put it here

Просмотреть файл

@ -143,4 +143,39 @@ function Adjust-DynamicPortRange()
# Kube-proxy load balancing should be set to DSR mode when it releases with future versions of the OS
Invoke-Executable -Executable "netsh.exe" -ArgList @("int", "ipv4", "set", "dynamicportrange", "tcp", "16385", "49151")
}
# TODO: should this be in this PR?
# Service start actions. These should be split up later and included in each install step
function Update-ServiceFailureActions
{
Param(
[Parameter(Mandatory = $true)][string]
$ContainerRuntime
)
sc.exe failure "kubelet" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "kubeproxy" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure $ContainerRuntime actions= restart/60000/restart/60000/restart/60000 reset= 900
}
function Add-SystemPathEntry
{
Param(
[Parameter(Mandatory = $true)][string]
$Directory
)
# update the path variable if it doesn't have the needed paths
$path = [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine)
$updated = $false
if(-not ($path -match $Directory.Replace("\","\\")+"(;|$)"))
{
$path += ";"+$Directory
$updated = $true
}
if($updated)
{
Write-Output "Updating path, added $Directory"
[Environment]::SetEnvironmentVariable("Path", $path, [EnvironmentVariableTarget]::Machine)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
}

Просмотреть файл

@ -0,0 +1,154 @@
# this is $global to persist across all functions since this is dot-sourced
$global:ContainerdInstallLocation = "$Env:ProgramFiles\containerd"
function RegisterContainerDService
{
Assert-FileExists (Join-Path $global:ContainerdInstallLocation containerd.exe)
Write-Host "Registering containerd as a service"
$cdbinary = Join-Path $global:ContainerdInstallLocation containerd.exe
$svc = Get-Service -Name containerd -ErrorAction SilentlyContinue
if ($null -ne $svc) {
& $cdbinary --unregister-service
}
& $cdbinary --register-service
$svc = Get-Service -Name "containerd" -ErrorAction SilentlyContinue
if ($null -eq $svc) {
throw "containerd.exe did not get installed as a service correctly."
}
$svc | Start-Service
if ($svc.Status -ne "Running") {
throw "containerd service is not running"
}
}
function Install-Containerd
{
Param(
[Parameter(Mandatory = $true)][string]
$ContainerdUrl
)
$zipfile = [Io.path]::Combine($ENV:TEMP, "containerd.zip")
DownloadFileOverHttp -Url $ContainerdUrl -DestinationPath $zipfile
Expand-Archive -path $zipfile -DestinationPath $global:ContainerdInstallLocation
del $zipfile
Add-SystemPathEntry $global:ContainerdInstallLocation
# TODO: remove if the node comes up without this code
# $configDir = [Io.Path]::Combine($ENV:ProgramData, "containerd")
# if (-Not (Test-Path $configDir)) {
# mkdir $configDir
# }
# TODO: call containerd.exe dump config, then modify instead of starting with hardcoded
$configFile = [Io.Path]::Combine($global:ContainerdInstallLocation, "config.toml")
@"
version = 2
root = "C:\\ProgramData\\containerd\\root"
state = "C:\\ProgramData\\containerd\\state"
plugin_dir = ""
disabled_plugins = []
required_plugins = []
oom_score = 0
[grpc]
address = "\\\\.\\pipe\\containerd-containerd"
tcp_address = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
[ttrpc]
address = ""
uid = 0
gid = 0
[debug]
address = ""
uid = 0
gid = 0
level = ""
[metrics]
address = ""
grpc_histogram = false
[cgroup]
path = ""
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
pause_threshold = 0.02
deletion_threshold = 0
mutation_threshold = 100
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
disable_tcp_service = true
stream_server_address = "127.0.0.1"
stream_server_port = "0"
stream_idle_timeout = "4h0m0s"
enable_selinux = false
sandbox_image = "mcr.microsoft.com/k8s/core/pause:1.2.0"
stats_collect_period = 10
systemd_cgroup = false
enable_tls_streaming = false
max_container_log_line_size = 16384
disable_cgroup = false
disable_apparmor = false
restrict_oom_score_adj = false
max_concurrent_downloads = 3
disable_proc_mount = false
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "windows"
default_runtime_name = "runhcs-wcow-process"
no_pivot = false
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runhcs-wcow-process]
runtime_type = "io.containerd.runhcs.v1"
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "C:\\k\\cni"
conf_dir = "C:\\k\\cni\\config"
max_conf_num = 1
conf_template = ""
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.runtime.v2.task"]
platforms = ["windows/amd64", "linux/amd64"]
[plugins."io.containerd.service.v1.diff-service"]
default = ["windows", "windows-lcow"]
"@ | Out-File -Encoding ascii $configFile
RegisterContainerDService
}

Просмотреть файл

@ -41,7 +41,9 @@ Write-AzureConfig {
[Parameter(Mandatory = $true)][string]
$KubeDir,
[Parameter(Mandatory = $true)][string]
$TargetEnvironment
$TargetEnvironment,
[Parameter(Mandatory = $false)][bool]
$UseContainerD = $false
)
if ( -Not $PrimaryAvailabilitySetName -And -Not $PrimaryScaleSetName ) {
@ -133,17 +135,51 @@ users:
$kubeConfig | Out-File -encoding ASCII -filepath "$kubeConfigFile"
}
function
Test-ContainerImageExists {
Param(
[Parameter(Mandatory = $true)][string]
$Image,
[Parameter(Mandatory = $false)][string]
$Tag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
$target = $Image
if ($Tag) {
$target += ":$Tag"
}
if ($ContainerRuntime -eq "docker") {
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
}
else
{
return ( (ctr.exe -n k8s.io images list) | Select-String $target) -ne $Null
}
}
function
Build-PauseContainer {
Param(
[Parameter(Mandatory = $true)][string]
$WindowsBase,
$DestinationTag
$DestinationTag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
# Future work: This needs to build wincat - see https://github.com/Azure/aks-engine/issues/1461
# Otherwise, delete this code and require a prebuilt pause image (or override with one from an Azure Container Registry instance)
# ContainerD can't build, so doing the builds outside of node deployment is probably the right long-term solution.
"FROM $($WindowsBase)" | Out-File -encoding ascii -FilePath Dockerfile
"CMD cmd /c ping -t localhost" | Out-File -encoding ascii -FilePath Dockerfile -Append
Invoke-Executable -Executable "docker" -ArgList @("build", "-t", "$DestinationTag", ".")
if ($ContainerRuntime -eq "docker") {
Invoke-Executable -Executable "docker" -ArgList @("build", "-t", "$DestinationTag", ".")
} else {
throw "Cannot build pause container without Docker"
}
}
function
@ -151,7 +187,9 @@ New-InfraContainer {
Param(
[Parameter(Mandatory = $true)][string]
$KubeDir,
$DestinationTag = "kubletwin/pause"
$DestinationTag = "kubletwin/pause",
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
cd $KubeDir
$computerInfo = Get-ComputerInfo
@ -164,14 +202,21 @@ New-InfraContainer {
$pauseImageVersions = @("1803", "1809", "1903", "1909")
if ($pauseImageVersions -icontains $computerInfo.WindowsVersion) {
$imageList = docker images $defaultPauseImage --format "{{.Repository}}:{{.Tag}}"
if (-not $imageList) {
Invoke-Executable -Executable "docker" -ArgList @("pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
if ($ContainerRuntime -eq "docker") {
if (-not (Test-ContainerImageExists -Image $defaultPauseImage -ContainerRuntime $ContainerRuntime)) {
Invoke-Executable -Executable "docker" -ArgList @("pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
}
Invoke-Executable -Executable "docker" -ArgList @("tag", "$defaultPauseImage", "$DestinationTag")
} else {
# containerd
if (-not (Test-ContainerImageExists -Image $defaultPauseImage -ContainerRuntime $ContainerRuntime)) {
Invoke-Executable -Executable "ctr" -ArgList @("-n", "k8s.io", "image", "pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
}
Invoke-Executable -Executable "ctr" -ArgList @("-n", "k8s.io", "image", "tag", "$defaultPauseImage", "$DestinationTag")
}
Invoke-Executable -Executable "docker" -ArgList @("tag", "$defaultPauseImage", "$DestinationTag")
}
else {
Build-PauseContainer -WindowsBase "mcr.microsoft.com/nanoserver-insider" -DestinationTag $DestinationTag
Build-PauseContainer -WindowsBase "mcr.microsoft.com/nanoserver-insider" -DestinationTag $DestinationTag -ContainerRuntime $ContainerRuntime
}
}
@ -181,7 +226,9 @@ Test-ContainerImageExists {
[Parameter(Mandatory = $true)][string]
$Image,
[Parameter(Mandatory = $false)][string]
$Tag
$Tag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
$target = $Image
@ -189,12 +236,16 @@ Test-ContainerImageExists {
$target += ":$Tag"
}
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
if ($ContainerRuntime -eq "docker") {
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
}
else
{
return ( (ctr.exe -n k8s.io images list) | Select-String $target) -ne $Null
}
}
# TODO: Deprecate this and replace with methods that get individual components instead of zip containing everything
# This expects the ZIP file created by Azure Pipelines.
function
@ -343,7 +394,9 @@ Install-KubernetesServices {
[Parameter(Mandatory = $true)][string]
$HNSModule,
[Parameter(Mandatory = $true)][string]
$KubeletNodeLabels
$KubeletNodeLabels,
[Parameter(Mandatory = $false)][bool]
$UseContainerD = $false
)
# Calculate some local paths
@ -381,6 +434,11 @@ Install-KubernetesServices {
throw "Unknown network type $NetworkPlugin, can't configure kubelet"
}
# Update args to use ContainerD if needed
if ($UseContainerD -eq $true) {
$KubeletArgList += @("--container-runtime=remote", "--container-runtime-endpoint=npipe://./pipe/containerd-containerd")
}
# Used in WinCNI version of kubeletstart.ps1
$KubeletArgListStr = ""
$KubeletArgList | Foreach-Object {
@ -472,7 +530,8 @@ $KubeletCommandLine
"@
}
else {
elseif (($NetworkPlugin -eq "kubenet" ) -and ($UseContainerD -eq $false))
{
# using WinCNI. TODO: If WinCNI support is removed, then delete this as dead code later
$KubeNetwork = "l2bridge"
$kubeStartStr += @"
@ -605,7 +664,161 @@ catch
}
"@
} # end else using WinCNI.
} # end elseif using WinCNI and Docker.
elseif (($NetworkPlugin -eq "kubenet" ) -and ($UseContainerD -eq $true))
{
# TODO: something is wrong with the CNI configuration
# Warning FailedCreatePodSandBox 2m16s (x222 over 50m) kubelet, 4068k8s011 (combined from similar events): Failed to create pod sandbox:
# rpc error: code = Unknown desc = failed to setup network for sandbox "922b1a200078edb15c7a5732612cbe19e5dadf7cf8a4622d72b376874522435d": error creating endpoint hcnCreateEndpoint failed in Win32: Invalid JSON document string. (0x803b001b) {"Success":false,"Error":"Invalid JSON document string. {{Policies.Type,UnknownEnumValue}}","ErrorCode":2151350299} : endpoint config &{ 922b1a200078edb15c7a5732612cbe19e5dadf7cf8a4622d72b376874522435d_l2bridge f94e9649-d4df-486e-bcd4-2721938d89f3 [{OutBoundNAT []} {ROUTE []}] [] { [default.svc.cluster.local] [10.0.0.10] []} [{10.240.0.1 0.0.0.0/0 0}] 0 {2 0}}
# using SDNBridge & Containerd
$KubeNetwork = "l2bridge"
$kubeStartStr += @"
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-CNIConfig(`$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)
}
try
{
`$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)
{
`$argList = $KubeletArgListStr
`$process = Start-Process -FilePath c:\k\kubelet.exe -PassThru -ArgumentList `$argList
# 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
}
# Turn off Firewall to enable pods to talk to service endpoints. (Kubelet should eventually do this)
netsh advfirewall set allprofiles state off
# startup the service
`$hnsNetwork = Get-HnsNetwork | ? Name -EQ `$global:NetworkMode.ToLower()
if (`$hnsNetwork)
{
# Kubelet has been restarted with existing network.
# Cleanup all containers
# TODO: convert this to ctr.exe -n k8s.io container list ; container rm
docker ps -q | foreach {docker rm `$_ -f}
# cleanup network
Write-Host "Cleaning up old HNS network found"
Remove-HnsNetwork `$hnsNetwork
Start-Sleep 10
}
Write-Host "Creating a new hns Network"
ipmo `$global:HNSModule
`$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
Restart-Service Kubeproxy
Start-Sleep 10
# Add route to all other POD networks
Write-Host "Updating CNI config"
Update-CNIConfig `$podCIDR `$masterSubnetGW
$KubeletCommandLine
}
catch
{
Write-Error `$_
}
"@
} # end elseif using sdnbridge and containerd.
else
{
throw "The combination of $NetworkPlugin and UseContainerD=$UseContainerD is not implemented"
}
# Now that the script is generated, based on what CNI plugin and startup options are needed, write it to disk
$kubeStartStr | Out-File -encoding ASCII -filepath $KubeletStartFile

Просмотреть файл

@ -17,6 +17,18 @@
},
"type": "string"
},
"windowsContainerdURL": {
"metadata": {
"description": "TODO: containerd - these binaries are not available yet"
},
"type": "string"
},
"windowsSdnPluginURL": {
"metadata": {
"description": "TODO: containerd - these binaries are not available yet"
},
"type": "string"
},
"kubeServiceCidr": {
"metadata": {
"description": "Kubernetes service address space"

Просмотреть файл

@ -297,6 +297,8 @@ func convertKubernetesConfigToVLabs(apiCfg *KubernetesConfig, vlabsCfg *vlabs.Ku
vlabsCfg.UseCloudControllerManager = apiCfg.UseCloudControllerManager
vlabsCfg.CustomWindowsPackageURL = apiCfg.CustomWindowsPackageURL
vlabsCfg.WindowsNodeBinariesURL = apiCfg.WindowsNodeBinariesURL
vlabsCfg.WindowsContainerdURL = apiCfg.WindowsContainerdURL
vlabsCfg.WindowsSdnPluginURL = apiCfg.WindowsSdnPluginURL
vlabsCfg.UseInstanceMetadata = apiCfg.UseInstanceMetadata
vlabsCfg.LoadBalancerSku = apiCfg.LoadBalancerSku
vlabsCfg.ExcludeMasterFromStandardLB = apiCfg.ExcludeMasterFromStandardLB

Просмотреть файл

@ -310,6 +310,8 @@ func convertVLabsKubernetesConfig(vlabs *vlabs.KubernetesConfig, api *Kubernetes
api.UseCloudControllerManager = vlabs.UseCloudControllerManager
api.CustomWindowsPackageURL = vlabs.CustomWindowsPackageURL
api.WindowsNodeBinariesURL = vlabs.WindowsNodeBinariesURL
api.WindowsContainerdURL = vlabs.WindowsContainerdURL
api.WindowsSdnPluginURL = vlabs.WindowsSdnPluginURL
api.UseInstanceMetadata = vlabs.UseInstanceMetadata
api.LoadBalancerSku = vlabs.LoadBalancerSku
api.ExcludeMasterFromStandardLB = vlabs.ExcludeMasterFromStandardLB

Просмотреть файл

@ -130,6 +130,22 @@ func TestConvertVLabsKubernetesConfigProfile(t *testing.T) {
WindowsNodeBinariesURL: "http://test/test.tar.gz",
},
},
"WindowsContainerdURL": {
props: &vlabs.KubernetesConfig{
WindowsContainerdURL: "http://test/testcontainerd.tar.gz",
},
expect: &KubernetesConfig{
WindowsContainerdURL: "http://test/testcontainerd.tar.gz",
},
},
"WindowsSdnPluginURL": {
props: &vlabs.KubernetesConfig{
WindowsSdnPluginURL: "http://test/testsdnplugin.tar.gz",
},
expect: &KubernetesConfig{
WindowsSdnPluginURL: "http://test/testsdnplugin.tar.gz",
},
},
}
for name, test := range tests {

Просмотреть файл

@ -446,6 +446,8 @@ type KubernetesConfig struct {
UseCloudControllerManager *bool `json:"useCloudControllerManager,omitempty"`
CustomWindowsPackageURL string `json:"customWindowsPackageURL,omitempty"`
WindowsNodeBinariesURL string `json:"windowsNodeBinariesURL,omitempty"`
WindowsContainerdURL string `json:"windowsContainerdURL,omitempty"`
WindowsSdnPluginURL string `json:"windowsSdnPluginURL,omitempty"`
UseInstanceMetadata *bool `json:"useInstanceMetadata,omitempty"`
EnableRbac *bool `json:"enableRbac,omitempty"`
EnableSecureKubelet *bool `json:"enableSecureKubelet,omitempty"`

Просмотреть файл

@ -328,6 +328,8 @@ type KubernetesConfig struct {
UseCloudControllerManager *bool `json:"useCloudControllerManager,omitempty"`
CustomWindowsPackageURL string `json:"customWindowsPackageURL,omitempty"`
WindowsNodeBinariesURL string `json:"windowsNodeBinariesURL,omitempty"`
WindowsContainerdURL string `json:"windowsContainerdURL,omitempty"`
WindowsSdnPluginURL string `json:"windowsSdnPluginURL,omitempty"`
UseInstanceMetadata *bool `json:"useInstanceMetadata,omitempty"`
EnableRbac *bool `json:"enableRbac,omitempty"`
EnableSecureKubelet *bool `json:"enableSecureKubelet,omitempty"`

Просмотреть файл

@ -1590,10 +1590,23 @@ func (a *Properties) validateContainerRuntime() error {
}
// Make sure we don't use unsupported container runtimes on windows.
if (containerRuntime == KataContainers || containerRuntime == Containerd) && a.HasWindows() {
if (containerRuntime == KataContainers) && a.HasWindows() {
return errors.Errorf("containerRuntime %q is not supporting windows agents", containerRuntime)
}
// TODO: These validations should be relaxed once ContainerD and CNI plugins are more readily available
if containerRuntime == Containerd && a.HasWindows() {
if a.OrchestratorProfile.KubernetesConfig.NetworkPlugin != "kubenet" {
return errors.Errorf("Windows only supports kubenet with containerd runtime. %q is not supported", a.OrchestratorProfile.KubernetesConfig.NetworkPlugin)
}
if a.OrchestratorProfile.KubernetesConfig.WindowsContainerdURL == "" {
return errors.Errorf("WindowsContainerdURL must be provided when using Windows with ContainerRuntime=containerd")
}
if a.OrchestratorProfile.KubernetesConfig.WindowsSdnPluginURL == "" {
return errors.Errorf("WindowsSdnPluginURL must be provided when using Windows with ContainerRuntime=containerd")
}
}
return nil
}

Просмотреть файл

@ -76,16 +76,17 @@ const (
const (
kubeConfigJSON = "k8s/kubeconfig.json"
// Windows custom scripts
kubernetesWindowsAgentCustomDataPS1 = "k8s/kuberneteswindowssetup.ps1"
kubernetesWindowsAgentFunctionsPS1 = "k8s/kuberneteswindowsfunctions.ps1"
kubernetesWindowsConfigFunctionsPS1 = "k8s/windowsconfigfunc.ps1"
kubernetesWindowsKubeletFunctionsPS1 = "k8s/windowskubeletfunc.ps1"
kubernetesWindowsCniFunctionsPS1 = "k8s/windowscnifunc.ps1"
kubernetesWindowsAzureCniFunctionsPS1 = "k8s/windowsazurecnifunc.ps1"
kubernetesWindowsOpenSSHFunctionPS1 = "k8s/windowsinstallopensshfunc.ps1"
kubernetesWindowsLogsCleanupPS1 = "k8s/windowslogscleanup.ps1"
kubernetesWindowsNodeResetPS1 = "k8s/windowsnodereset.ps1"
// Windows custom scripts. These should all be listed in template_generator.go:func GetKubernetesWindowsAgentFunctions
kubernetesWindowsAgentCustomDataPS1 = "k8s/kuberneteswindowssetup.ps1"
kubernetesWindowsAgentFunctionsPS1 = "k8s/kuberneteswindowsfunctions.ps1"
kubernetesWindowsConfigFunctionsPS1 = "k8s/windowsconfigfunc.ps1"
kubernetesWindowsContainerdFunctionsPS1 = "k8s/windowscontainerdfunc.ps1"
kubernetesWindowsKubeletFunctionsPS1 = "k8s/windowskubeletfunc.ps1"
kubernetesWindowsCniFunctionsPS1 = "k8s/windowscnifunc.ps1"
kubernetesWindowsAzureCniFunctionsPS1 = "k8s/windowsazurecnifunc.ps1"
kubernetesWindowsOpenSSHFunctionPS1 = "k8s/windowsinstallopensshfunc.ps1"
kubernetesWindowsLogsCleanupPS1 = "k8s/windowslogscleanup.ps1"
kubernetesWindowsNodeResetPS1 = "k8s/windowsnodereset.ps1"
)
// cloud-init (i.e. ARM customData) source file references

Просмотреть файл

@ -112,6 +112,8 @@ func assignKubernetesParameters(properties *api.Properties, parametersMap params
addValue(parametersMap, "kubeServiceCidr", kubernetesConfig.ServiceCIDR)
addValue(parametersMap, "kubeBinariesVersion", k8sVersion)
addValue(parametersMap, "windowsTelemetryGUID", cloudSpecConfig.KubernetesSpecConfig.WindowsTelemetryGUID)
addValue(parametersMap, "windowsContainerdURL", kubernetesConfig.WindowsContainerdURL)
addValue(parametersMap, "windowsSdnPluginURL", kubernetesConfig.WindowsSdnPluginURL)
}
}

Просмотреть файл

@ -469,12 +469,14 @@ func getContainerServiceFuncMap(cs *api.ContainerService) template.FuncMap {
var parts = []string{
kubernetesWindowsAgentFunctionsPS1,
kubernetesWindowsConfigFunctionsPS1,
kubernetesWindowsContainerdFunctionsPS1,
kubernetesWindowsKubeletFunctionsPS1,
kubernetesWindowsCniFunctionsPS1,
kubernetesWindowsAzureCniFunctionsPS1,
kubernetesWindowsLogsCleanupPS1,
kubernetesWindowsNodeResetPS1,
kubernetesWindowsOpenSSHFunctionPS1}
kubernetesWindowsOpenSSHFunctionPS1,
}
// Create a buffer, new zip
buf := new(bytes.Buffer)

Просмотреть файл

@ -212,6 +212,7 @@
// ../../parts/k8s/windowsazurecnifunc.tests.ps1
// ../../parts/k8s/windowscnifunc.ps1
// ../../parts/k8s/windowsconfigfunc.ps1
// ../../parts/k8s/windowscontainerdfunc.ps1
// ../../parts/k8s/windowsinstallopensshfunc.ps1
// ../../parts/k8s/windowskubeletfunc.ps1
// ../../parts/k8s/windowslogscleanup.ps1
@ -39369,6 +39370,17 @@ function Register-NodeResetScriptTask {
$definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Description "k8s-restart-job"
Register-ScheduledTask -TaskName "k8s-restart-job" -InputObject $definition
}
function Assert-FileExists {
Param(
[Parameter(Mandatory=$true,Position=0)][string]
$Filename
)
if (-Not (Test-Path $Filename)) {
throw "$Filename does not exist"
}
}
`)
func k8sKuberneteswindowsfunctionsPs1Bytes() ([]byte, error) {
@ -39453,10 +39465,15 @@ $global:AgentCertificate = "{{WrapAsParameter "clientCertificate"}}"
$global:KubeBinariesPackageSASURL = "{{WrapAsParameter "kubeBinariesSASURL"}}"
$global:WindowsKubeBinariesURL = "{{WrapAsParameter "windowsKubeBinariesURL"}}"
$global:KubeBinariesVersion = "{{WrapAsParameter "kubeBinariesVersion"}}"
$global:ContainerdUrl = "{{WrapAsParameter "windowsContainerdURL"}}"
$global:ContainerdSdnPluginUrl = "{{WrapAsParameter "windowsSdnPluginURL"}}"
## Docker Version
$global:DockerVersion = "{{WrapAsParameter "windowsDockerVersion"}}"
## ContainerD Usage
$global:ContainerRuntime = "{{WrapAsParameter "containerRuntime"}}"
## VM configuration passed by Azure
$global:WindowsTelemetryGUID = "{{WrapAsParameter "windowsTelemetryGUID"}}"
{{if eq GetIdentitySystem "adfs"}}
@ -39533,14 +39550,9 @@ Expand-Archive scripts.zip -DestinationPath "C:\\AzureData\\"
. c:\AzureData\k8s\windowscnifunc.ps1
. c:\AzureData\k8s\windowsazurecnifunc.ps1
. c:\AzureData\k8s\windowsinstallopensshfunc.ps1
. c:\AzureData\k8s\windowscontainerdfunc.ps1
function
Update-ServiceFailureActions()
{
sc.exe failure "kubelet" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "kubeproxy" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "docker" actions= restart/60000/restart/60000/restart/60000 reset= 900
}
$useContainerD = ($global:ContainerRuntime -eq "containerd")
try
{
@ -39610,12 +39622,22 @@ try
Write-Log "Create required data directories as needed"
Initialize-DataDirectories
Write-Log "Install docker"
$dockerTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Docker -DockerVersion $global:DockerVersion
Set-DockerLogFileOptions
$dockerTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-Docker", $dockerTimer.Elapsed.TotalSeconds)
if ($useContainerD) {
Write-Log "Installing ContainerD"
$containerdTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Containerd -ContainerdUrl $global:ContainerdUrl
$containerdTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-ContainerD", $containerdTimer.Elapsed.TotalSeconds)
# TODO: disable/uninstall Docker later
} else {
Write-Log "Install docker"
$dockerTimer = [System.Diagnostics.Stopwatch]::StartNew()
Install-Docker -DockerVersion $global:DockerVersion
Set-DockerLogFileOptions
$dockerTimer.Stop()
$global:AppInsightsClient.TrackMetric("Install-Docker", $dockerTimer.Elapsed.TotalSeconds)
}
Write-Log "Download kubelet binaries and unzip"
Get-KubePackage -KubeBinariesSASURL $global:KubeBinariesPackageSASURL
@ -39672,14 +39694,19 @@ try
Write-Log "Create the Pause Container kubletwin/pause"
$infraContainerTimer = [System.Diagnostics.Stopwatch]::StartNew()
New-InfraContainer -KubeDir $global:KubeDir
New-InfraContainer -KubeDir $global:KubeDir -ContainerRuntime $global:ContainerRuntime
$infraContainerTimer.Stop()
$global:AppInsightsClient.TrackMetric("New-InfraContainer", $infraContainerTimer.Elapsed.TotalSeconds)
if (-not (Test-ContainerImageExists -Image "kubletwin/pause")) {
if (-not (Test-ContainerImageExists -Image "kubletwin/pause" -ContainerRuntime $global:ContainerRuntime)) {
Write-Log "Could not find container with name kubletwin/pause"
$o = docker image list
Write-Log $o
if ($useContainerD) {
$o = ctr -n k8s.io image list
Write-Log $o
} else {
$o = docker image list
Write-Log $o
}
throw "kubletwin/pause container does not exist!"
}
@ -39718,7 +39745,13 @@ try
}
elseif ($global:NetworkPlugin -eq "kubenet") {
Write-Log "Fetching additional files needed for kubenet"
Update-WinCNI -CNIPath $global:CNIPath
if ($useContainerD) {
# TODO: CNI may need to move to c:\program files\containerd\cni\bin with ContainerD
Install-SdnBridge -Url $global:ContainerdSdnPluginUrl -CNIPath $global:CNIPath
} else {
Update-WinCNI -CNIPath $global:CNIPath
}
Get-HnsPsm1 -HNSModule $global:HNSModule
}
New-ExternalHnsNetwork
@ -39742,7 +39775,8 @@ try
-KubeClusterCIDR $global:KubeClusterCIDR ` + "`" + `
-KubeServiceCIDR $global:KubeServiceCIDR ` + "`" + `
-HNSModule $global:HNSModule ` + "`" + `
-KubeletNodeLabels $global:KubeletNodeLabels
-KubeletNodeLabels $global:KubeletNodeLabels ` + "`" + `
-UseContainerD $useContainerD
Get-LogCollectionScripts
@ -39756,7 +39790,7 @@ try
PREPROVISION_EXTENSION
Write-Log "Update service failure actions"
Update-ServiceFailureActions
Update-ServiceFailureActions -ContainerRuntime $global:ContainerRuntime
Adjust-DynamicPortRange
Register-LogsCleanupScriptTask
@ -39778,7 +39812,7 @@ try
else
{
# keep for debugging purposes
Write-Log ".\CustomDataSetupScript.ps1 -MasterIP $MasterIP -KubeDnsServiceIp $KubeDnsServiceIp -MasterFQDNPrefix $MasterFQDNPrefix -Location $Location -AgentKey $AgentKey -AADClientId $AADClientId -AADClientSecret $AADClientSecret"
Write-Log ".\CustomDataSetupScript.ps1 -MasterIP $MasterIP -KubeDnsServiceIp $KubeDnsServiceIp -MasterFQDNPrefix $MasterFQDNPrefix -Location $Location -AgentKey $AgentKey -AADClientId $AADClientId -AADClientSecret $AADClientSecret -NetworkAPIVersion $NetworkAPIVersion -TargetEnvironment $TargetEnvironment"
}
}
catch
@ -40474,6 +40508,21 @@ function Update-WinCNI
DownloadFileOverHttp -Url $WinCniUrl -DestinationPath $wincniFile
}
function Install-SdnBridge
{
Param(
[Parameter(Mandatory=$true)][string]
$Url,
[Parameter(Mandatory=$true)][string]
$CNIPath
)
$cnizip = [Io.path]::Combine($CNIPath, "cni.zip")
DownloadFileOverHttp -Url $Url -DestinationPath $cnizip
Expand-Archive -path $cnizip -DestinationPath $CNIPath
del $cnizip
}
# TODO: Move the code that creates the wincni configuration file out of windowskubeletfunc.ps1 and put it here`)
func k8sWindowscnifuncPs1Bytes() ([]byte, error) {
@ -40636,6 +40685,41 @@ function Adjust-DynamicPortRange()
# Kube-proxy load balancing should be set to DSR mode when it releases with future versions of the OS
Invoke-Executable -Executable "netsh.exe" -ArgList @("int", "ipv4", "set", "dynamicportrange", "tcp", "16385", "49151")
}
# TODO: should this be in this PR?
# Service start actions. These should be split up later and included in each install step
function Update-ServiceFailureActions
{
Param(
[Parameter(Mandatory = $true)][string]
$ContainerRuntime
)
sc.exe failure "kubelet" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure "kubeproxy" actions= restart/60000/restart/60000/restart/60000 reset= 900
sc.exe failure $ContainerRuntime actions= restart/60000/restart/60000/restart/60000 reset= 900
}
function Add-SystemPathEntry
{
Param(
[Parameter(Mandatory = $true)][string]
$Directory
)
# update the path variable if it doesn't have the needed paths
$path = [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine)
$updated = $false
if(-not ($path -match $Directory.Replace("\","\\")+"(;|$)"))
{
$path += ";"+$Directory
$updated = $true
}
if($updated)
{
Write-Output "Updating path, added $Directory"
[Environment]::SetEnvironmentVariable("Path", $path, [EnvironmentVariableTarget]::Machine)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
}`)
func k8sWindowsconfigfuncPs1Bytes() ([]byte, error) {
@ -40653,6 +40737,176 @@ func k8sWindowsconfigfuncPs1() (*asset, error) {
return a, nil
}
var _k8sWindowscontainerdfuncPs1 = []byte(`# this is $global to persist across all functions since this is dot-sourced
$global:ContainerdInstallLocation = "$Env:ProgramFiles\containerd"
function RegisterContainerDService
{
Assert-FileExists (Join-Path $global:ContainerdInstallLocation containerd.exe)
Write-Host "Registering containerd as a service"
$cdbinary = Join-Path $global:ContainerdInstallLocation containerd.exe
$svc = Get-Service -Name containerd -ErrorAction SilentlyContinue
if ($null -ne $svc) {
& $cdbinary --unregister-service
}
& $cdbinary --register-service
$svc = Get-Service -Name "containerd" -ErrorAction SilentlyContinue
if ($null -eq $svc) {
throw "containerd.exe did not get installed as a service correctly."
}
$svc | Start-Service
if ($svc.Status -ne "Running") {
throw "containerd service is not running"
}
}
function Install-Containerd
{
Param(
[Parameter(Mandatory = $true)][string]
$ContainerdUrl
)
$zipfile = [Io.path]::Combine($ENV:TEMP, "containerd.zip")
DownloadFileOverHttp -Url $ContainerdUrl -DestinationPath $zipfile
Expand-Archive -path $zipfile -DestinationPath $global:ContainerdInstallLocation
del $zipfile
Add-SystemPathEntry $global:ContainerdInstallLocation
# TODO: remove if the node comes up without this code
# $configDir = [Io.Path]::Combine($ENV:ProgramData, "containerd")
# if (-Not (Test-Path $configDir)) {
# mkdir $configDir
# }
# TODO: call containerd.exe dump config, then modify instead of starting with hardcoded
$configFile = [Io.Path]::Combine($global:ContainerdInstallLocation, "config.toml")
@"
version = 2
root = "C:\\ProgramData\\containerd\\root"
state = "C:\\ProgramData\\containerd\\state"
plugin_dir = ""
disabled_plugins = []
required_plugins = []
oom_score = 0
[grpc]
address = "\\\\.\\pipe\\containerd-containerd"
tcp_address = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
[ttrpc]
address = ""
uid = 0
gid = 0
[debug]
address = ""
uid = 0
gid = 0
level = ""
[metrics]
address = ""
grpc_histogram = false
[cgroup]
path = ""
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
pause_threshold = 0.02
deletion_threshold = 0
mutation_threshold = 100
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
disable_tcp_service = true
stream_server_address = "127.0.0.1"
stream_server_port = "0"
stream_idle_timeout = "4h0m0s"
enable_selinux = false
sandbox_image = "mcr.microsoft.com/k8s/core/pause:1.2.0"
stats_collect_period = 10
systemd_cgroup = false
enable_tls_streaming = false
max_container_log_line_size = 16384
disable_cgroup = false
disable_apparmor = false
restrict_oom_score_adj = false
max_concurrent_downloads = 3
disable_proc_mount = false
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "windows"
default_runtime_name = "runhcs-wcow-process"
no_pivot = false
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runhcs-wcow-process]
runtime_type = "io.containerd.runhcs.v1"
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "C:\\k\\cni"
conf_dir = "C:\\k\\cni\\config"
max_conf_num = 1
conf_template = ""
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.runtime.v2.task"]
platforms = ["windows/amd64", "linux/amd64"]
[plugins."io.containerd.service.v1.diff-service"]
default = ["windows", "windows-lcow"]
"@ | Out-File -Encoding ascii $configFile
RegisterContainerDService
}`)
func k8sWindowscontainerdfuncPs1Bytes() ([]byte, error) {
return _k8sWindowscontainerdfuncPs1, nil
}
func k8sWindowscontainerdfuncPs1() (*asset, error) {
bytes, err := k8sWindowscontainerdfuncPs1Bytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "k8s/windowscontainerdfunc.ps1", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _k8sWindowsinstallopensshfuncPs1 = []byte(`function
Install-OpenSSH {
Param(
@ -40772,7 +41026,9 @@ Write-AzureConfig {
[Parameter(Mandatory = $true)][string]
$KubeDir,
[Parameter(Mandatory = $true)][string]
$TargetEnvironment
$TargetEnvironment,
[Parameter(Mandatory = $false)][bool]
$UseContainerD = $false
)
if ( -Not $PrimaryAvailabilitySetName -And -Not $PrimaryScaleSetName ) {
@ -40864,17 +41120,51 @@ users:
$kubeConfig | Out-File -encoding ASCII -filepath "$kubeConfigFile"
}
function
Test-ContainerImageExists {
Param(
[Parameter(Mandatory = $true)][string]
$Image,
[Parameter(Mandatory = $false)][string]
$Tag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
$target = $Image
if ($Tag) {
$target += ":$Tag"
}
if ($ContainerRuntime -eq "docker") {
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
}
else
{
return ( (ctr.exe -n k8s.io images list) | Select-String $target) -ne $Null
}
}
function
Build-PauseContainer {
Param(
[Parameter(Mandatory = $true)][string]
$WindowsBase,
$DestinationTag
$DestinationTag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
# Future work: This needs to build wincat - see https://github.com/Azure/aks-engine/issues/1461
# Otherwise, delete this code and require a prebuilt pause image (or override with one from an Azure Container Registry instance)
# ContainerD can't build, so doing the builds outside of node deployment is probably the right long-term solution.
"FROM $($WindowsBase)" | Out-File -encoding ascii -FilePath Dockerfile
"CMD cmd /c ping -t localhost" | Out-File -encoding ascii -FilePath Dockerfile -Append
Invoke-Executable -Executable "docker" -ArgList @("build", "-t", "$DestinationTag", ".")
if ($ContainerRuntime -eq "docker") {
Invoke-Executable -Executable "docker" -ArgList @("build", "-t", "$DestinationTag", ".")
} else {
throw "Cannot build pause container without Docker"
}
}
function
@ -40882,7 +41172,9 @@ New-InfraContainer {
Param(
[Parameter(Mandatory = $true)][string]
$KubeDir,
$DestinationTag = "kubletwin/pause"
$DestinationTag = "kubletwin/pause",
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
cd $KubeDir
$computerInfo = Get-ComputerInfo
@ -40895,14 +41187,21 @@ New-InfraContainer {
$pauseImageVersions = @("1803", "1809", "1903", "1909")
if ($pauseImageVersions -icontains $computerInfo.WindowsVersion) {
$imageList = docker images $defaultPauseImage --format "{{.Repository}}:{{.Tag}}"
if (-not $imageList) {
Invoke-Executable -Executable "docker" -ArgList @("pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
if ($ContainerRuntime -eq "docker") {
if (-not (Test-ContainerImageExists -Image $defaultPauseImage -ContainerRuntime $ContainerRuntime)) {
Invoke-Executable -Executable "docker" -ArgList @("pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
}
Invoke-Executable -Executable "docker" -ArgList @("tag", "$defaultPauseImage", "$DestinationTag")
} else {
# containerd
if (-not (Test-ContainerImageExists -Image $defaultPauseImage -ContainerRuntime $ContainerRuntime)) {
Invoke-Executable -Executable "ctr" -ArgList @("-n", "k8s.io", "image", "pull", "$defaultPauseImage") -Retries 5 -RetryDelaySeconds 30
}
Invoke-Executable -Executable "ctr" -ArgList @("-n", "k8s.io", "image", "tag", "$defaultPauseImage", "$DestinationTag")
}
Invoke-Executable -Executable "docker" -ArgList @("tag", "$defaultPauseImage", "$DestinationTag")
}
else {
Build-PauseContainer -WindowsBase "mcr.microsoft.com/nanoserver-insider" -DestinationTag $DestinationTag
Build-PauseContainer -WindowsBase "mcr.microsoft.com/nanoserver-insider" -DestinationTag $DestinationTag -ContainerRuntime $ContainerRuntime
}
}
@ -40912,7 +41211,9 @@ Test-ContainerImageExists {
[Parameter(Mandatory = $true)][string]
$Image,
[Parameter(Mandatory = $false)][string]
$Tag
$Tag,
[Parameter(Mandatory = $false)][string]
$ContainerRuntime = "docker"
)
$target = $Image
@ -40920,12 +41221,16 @@ Test-ContainerImageExists {
$target += ":$Tag"
}
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
if ($ContainerRuntime -eq "docker") {
$images = docker image list $target --format "{{json .}}"
return $images.Count -gt 0
}
else
{
return ( (ctr.exe -n k8s.io images list) | Select-String $target) -ne $Null
}
}
# TODO: Deprecate this and replace with methods that get individual components instead of zip containing everything
# This expects the ZIP file created by Azure Pipelines.
function
@ -41074,7 +41379,9 @@ Install-KubernetesServices {
[Parameter(Mandatory = $true)][string]
$HNSModule,
[Parameter(Mandatory = $true)][string]
$KubeletNodeLabels
$KubeletNodeLabels,
[Parameter(Mandatory = $false)][bool]
$UseContainerD = $false
)
# Calculate some local paths
@ -41112,6 +41419,11 @@ Install-KubernetesServices {
throw "Unknown network type $NetworkPlugin, can't configure kubelet"
}
# Update args to use ContainerD if needed
if ($UseContainerD -eq $true) {
$KubeletArgList += @("--container-runtime=remote", "--container-runtime-endpoint=npipe://./pipe/containerd-containerd")
}
# Used in WinCNI version of kubeletstart.ps1
$KubeletArgListStr = ""
$KubeletArgList | Foreach-Object {
@ -41203,7 +41515,8 @@ $KubeletCommandLine
"@
}
else {
elseif (($NetworkPlugin -eq "kubenet" ) -and ($UseContainerD -eq $false))
{
# using WinCNI. TODO: If WinCNI support is removed, then delete this as dead code later
$KubeNetwork = "l2bridge"
$kubeStartStr += @"
@ -41336,7 +41649,161 @@ catch
}
"@
} # end else using WinCNI.
} # end elseif using WinCNI and Docker.
elseif (($NetworkPlugin -eq "kubenet" ) -and ($UseContainerD -eq $true))
{
# TODO: something is wrong with the CNI configuration
# Warning FailedCreatePodSandBox 2m16s (x222 over 50m) kubelet, 4068k8s011 (combined from similar events): Failed to create pod sandbox:
# rpc error: code = Unknown desc = failed to setup network for sandbox "922b1a200078edb15c7a5732612cbe19e5dadf7cf8a4622d72b376874522435d": error creating endpoint hcnCreateEndpoint failed in Win32: Invalid JSON document string. (0x803b001b) {"Success":false,"Error":"Invalid JSON document string. {{Policies.Type,UnknownEnumValue}}","ErrorCode":2151350299} : endpoint config &{ 922b1a200078edb15c7a5732612cbe19e5dadf7cf8a4622d72b376874522435d_l2bridge f94e9649-d4df-486e-bcd4-2721938d89f3 [{OutBoundNAT []} {ROUTE []}] [] { [default.svc.cluster.local] [10.0.0.10] []} [{10.240.0.1 0.0.0.0/0 0}] 0 {2 0}}
# using SDNBridge & Containerd
$KubeNetwork = "l2bridge"
$kubeStartStr += @"
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-CNIConfig(` + "`" + `$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)
}
try
{
` + "`" + `$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)
{
` + "`" + `$argList = $KubeletArgListStr
` + "`" + `$process = Start-Process -FilePath c:\k\kubelet.exe -PassThru -ArgumentList ` + "`" + `$argList
# 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
}
# Turn off Firewall to enable pods to talk to service endpoints. (Kubelet should eventually do this)
netsh advfirewall set allprofiles state off
# startup the service
` + "`" + `$hnsNetwork = Get-HnsNetwork | ? Name -EQ ` + "`" + `$global:NetworkMode.ToLower()
if (` + "`" + `$hnsNetwork)
{
# Kubelet has been restarted with existing network.
# Cleanup all containers
# TODO: convert this to ctr.exe -n k8s.io container list ; container rm
docker ps -q | foreach {docker rm ` + "`" + `$_ -f}
# cleanup network
Write-Host "Cleaning up old HNS network found"
Remove-HnsNetwork ` + "`" + `$hnsNetwork
Start-Sleep 10
}
Write-Host "Creating a new hns Network"
ipmo ` + "`" + `$global:HNSModule
` + "`" + `$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
Restart-Service Kubeproxy
Start-Sleep 10
# Add route to all other POD networks
Write-Host "Updating CNI config"
Update-CNIConfig ` + "`" + `$podCIDR ` + "`" + `$masterSubnetGW
$KubeletCommandLine
}
catch
{
Write-Error ` + "`" + `$_
}
"@
} # end elseif using sdnbridge and containerd.
else
{
throw "The combination of $NetworkPlugin and UseContainerD=$UseContainerD is not implemented"
}
# Now that the script is generated, based on what CNI plugin and startup options are needed, write it to disk
$kubeStartStr | Out-File -encoding ASCII -filepath $KubeletStartFile
@ -44790,6 +45257,18 @@ var _windowsparamsT = []byte(` {{if IsKubernetes}}
},
"type": "string"
},
"windowsContainerdURL": {
"metadata": {
"description": "TODO: containerd - these binaries are not available yet"
},
"type": "string"
},
"windowsSdnPluginURL": {
"metadata": {
"description": "TODO: containerd - these binaries are not available yet"
},
"type": "string"
},
"kubeServiceCidr": {
"metadata": {
"description": "Kubernetes service address space"
@ -45152,6 +45631,7 @@ var _bindata = map[string]func() (*asset, error){
"k8s/windowsazurecnifunc.tests.ps1": k8sWindowsazurecnifuncTestsPs1,
"k8s/windowscnifunc.ps1": k8sWindowscnifuncPs1,
"k8s/windowsconfigfunc.ps1": k8sWindowsconfigfuncPs1,
"k8s/windowscontainerdfunc.ps1": k8sWindowscontainerdfuncPs1,
"k8s/windowsinstallopensshfunc.ps1": k8sWindowsinstallopensshfuncPs1,
"k8s/windowskubeletfunc.ps1": k8sWindowskubeletfuncPs1,
"k8s/windowslogscleanup.ps1": k8sWindowslogscleanupPs1,
@ -45466,6 +45946,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
"windowsazurecnifunc.tests.ps1": {k8sWindowsazurecnifuncTestsPs1, map[string]*bintree{}},
"windowscnifunc.ps1": {k8sWindowscnifuncPs1, map[string]*bintree{}},
"windowsconfigfunc.ps1": {k8sWindowsconfigfuncPs1, map[string]*bintree{}},
"windowscontainerdfunc.ps1": {k8sWindowscontainerdfuncPs1, map[string]*bintree{}},
"windowsinstallopensshfunc.ps1": {k8sWindowsinstallopensshfuncPs1, map[string]*bintree{}},
"windowskubeletfunc.ps1": {k8sWindowskubeletfuncPs1, map[string]*bintree{}},
"windowslogscleanup.ps1": {k8sWindowslogscleanupPs1, map[string]*bintree{}},

Просмотреть файл

@ -6,7 +6,9 @@
"orchestratorRelease": "1.13",
"kubernetesConfig": {
"useInstanceMetadata": false,
"windowsNodeBinariesURL": "http://test/test.tar.gz"
"windowsNodeBinariesURL": "http://test/test.tar.gz",
"windowsContainerdURL": "http://test/testcontainerd.tar.gz",
"windowsSdnPluginURL": "http://test/testsdnplugin.tar.gz"
}
},
"masterProfile": {

Просмотреть файл

@ -0,0 +1,71 @@
#!/bin/bash
set -e -x -o pipefail
GOTAG="1.13.7"
DOCKERARGS="--network=host"
OUTDIR="$(pwd)/_output"
if [ ! -d $OUTDIR ]; then
mkdir $OUTDIR
fi
cat <<EOF > $OUTDIR/buildcri.sh
set -e -x -o pipefail
export GOOS=windows
export GOARCH=amd64
go get github.com/Microsoft/hcsshim
cd src/github.com/Microsoft/hcsshim
git rev-parse HEAD > /output/hcsshim-revision.txt
cd \$GOPATH
go build -o /output/containerd-shim-runhcs-v1.exe github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1
mkdir -p src/github.com/containerd
cd src/github.com/containerd
pwd
git clone https://github.com/containerd/containerd.git
cd containerd
git rev-parse HEAD > /output/containerd-revision.txt
make
# make cri-release # should work, but doesn't
cp bin/ctr.exe /output
#cp bin/containerd.exe /output # missing CRI plugin, so build from containerd/cri
cd \$GOPATH
cd src/github.com/containerd
git clone https://github.com/containerd/cri.git
cd cri
git rev-parse HEAD > /output/cri-revision.txt
make containerd
cp _output/containerd.exe /output
apt update
apt install -y zip
cd /output
zip windows-cri-containerd.zip *.exe *.txt
rm -f /output/*.exe
rm -f /output/*.txt
EOF
chmod +x $OUTDIR/buildcri.sh
cat <<EOF > $OUTDIR/buildcni.sh
set -e -x -o pipefail
export GOOS=windows
export GOARCH=amd64
mkdir -p src/github.com/Microsoft
cd src/github.com/Microsoft
git clone https://github.com/Microsoft/windows-container-networking.git
cd windows-container-networking
git rev-parse HEAD > /output/cni-revision.txt
make all
mv out/*.exe /output
apt update
apt install -y zip
cd /output
zip windows-cni-containerd.zip *.exe *.txt
rm -f /output/*.exe
rm -f /output/*.txt
EOF
chmod +x $OUTDIR/buildcni.sh
docker run $DOCKERARGS -v $OUTDIR:/output golang:$GOTAG /bin/bash -c /output/buildcri.sh
docker run $DOCKERARGS -v $OUTDIR:/output golang:$GOTAG /bin/bash -c /output/buildcni.sh