From e4d02cfeb7bb03fe3319dfc9e318c5f8ada73051 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Tue, 2 Feb 2021 13:58:06 -0800 Subject: [PATCH 1/4] feat: run accelerated unattended-upgrade at node creation time --- docs/topics/clusterdefinitions.md | 1 + parts/k8s/cloud-init/artifacts/cse_helpers.sh | 12 ++++++++++++ parts/k8s/cloud-init/artifacts/cse_main.sh | 4 ++++ pkg/api/converterfromapi.go | 1 + pkg/api/convertertoapi.go | 1 + pkg/api/types.go | 13 +++++++------ pkg/api/vlabs/types.go | 9 +++++---- pkg/engine/template_generator.go | 6 ++++++ pkg/engine/templates_generated.go | 16 ++++++++++++++++ test/e2e/test_cluster_configs/everything.json | 1 + 10 files changed, 54 insertions(+), 10 deletions(-) diff --git a/docs/topics/clusterdefinitions.md b/docs/topics/clusterdefinitions.md index b7e0a6f6ce..1da229549e 100644 --- a/docs/topics/clusterdefinitions.md +++ b/docs/topics/clusterdefinitions.md @@ -857,6 +857,7 @@ A cluster can have 0 to 12 agent pool profiles. Agent Pool Profiles are used for | adminUsername | yes | Describes the username to be used on all linux clusters | | ssh.publicKeys[].keyData | yes | The public SSH key used for authenticating access to all Linux nodes in the cluster | | secrets | no | Specifies an array of key vaults to pull secrets from and what secrets to pull from each | +| runUnattendedUpgradesOnBootstrap | no | Invoke an unattended-upgrade when each Linux node VM comes online for the first time. In practice this is accomplished by performing an `apt-get update`, followed by an `apt-get dist-upgrade`, to fetch updated apt configuration, and install all available downstream package updates, respectively. | | customSearchDomain.name | no | describes the search domain to be used on all linux clusters | | customSearchDomain.realmUser | no | describes the realm user with permissions to update dns registries on Windows Server DNS | | customSearchDomain.realmPassword | no | describes the realm user password to update dns registries on Windows Server DNS | diff --git a/parts/k8s/cloud-init/artifacts/cse_helpers.sh b/parts/k8s/cloud-init/artifacts/cse_helpers.sh index 3d15566048..78ec49ae6b 100755 --- a/parts/k8s/cloud-init/artifacts/cse_helpers.sh +++ b/parts/k8s/cloud-init/artifacts/cse_helpers.sh @@ -193,6 +193,18 @@ apt_get_dist_upgrade() { done echo Executed apt-get dist-upgrade $i times } +unnattended_upgrade() { + retries=10 + for i in $(seq 1 $retries); do + wait_for_apt_locks + /usr/bin/unattended-upgrade && break || + if [ $i -eq $retries ]; then + return 1 + else sleep 5 + fi + done + echo Executed unattended-upgrade $i times +} systemctl_restart() { retries=$1; wait_sleep=$2; timeout=$3 svcname=$4 for i in $(seq 1 $retries); do diff --git a/parts/k8s/cloud-init/artifacts/cse_main.sh b/parts/k8s/cloud-init/artifacts/cse_main.sh index e7088a4fbf..7b0019e56f 100755 --- a/parts/k8s/cloud-init/artifacts/cse_main.sh +++ b/parts/k8s/cloud-init/artifacts/cse_main.sh @@ -276,6 +276,10 @@ if [[ $OS == $UBUNTU_OS_NAME ]]; then fi {{end}} +{{- if RunUnattendedUpgrades}} +apt_get_update && apt_get_dist_upgrade && unnattended_upgrade +{{- end}} + if [ -f /var/run/reboot-required ]; then trace_info "RebootRequired" "reboot=true" /bin/bash -c "shutdown -r 1 &" diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index de69b2fce2..6b2d943b17 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -174,6 +174,7 @@ func convertLinuxProfileToVLabs(obj *LinuxProfile, vlabsProfile *vlabs.LinuxProf vlabsProfile.CustomNodesDNS = &vlabs.CustomNodesDNS{} vlabsProfile.CustomNodesDNS.DNSServer = obj.CustomNodesDNS.DNSServer } + vlabsProfile.RunUnattendedUpgradesOnBootstrap = obj.RunUnattendedUpgradesOnBootstrap } func convertWindowsProfileToVLabs(api *WindowsProfile, vlabsProfile *vlabs.WindowsProfile) { diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 7d09f4cb88..9069ba980e 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -169,6 +169,7 @@ func convertVLabsLinuxProfile(vlabs *vlabs.LinuxProfile, api *LinuxProfile) { api.CustomNodesDNS = &CustomNodesDNS{} api.CustomNodesDNS.DNSServer = vlabs.CustomNodesDNS.DNSServer } + api.RunUnattendedUpgradesOnBootstrap = vlabs.RunUnattendedUpgradesOnBootstrap } func convertVLabsWindowsProfile(vlabs *vlabs.WindowsProfile, api *WindowsProfile) { diff --git a/pkg/api/types.go b/pkg/api/types.go index f4d7d3ad3b..fb895af1e8 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -133,12 +133,13 @@ type LinuxProfile struct { SSH struct { PublicKeys []PublicKey `json:"publicKeys"` } `json:"ssh"` - Secrets []KeyVaultSecrets `json:"secrets,omitempty"` - Distro Distro `json:"distro,omitempty"` - ScriptRootURL string `json:"scriptroot,omitempty"` - CustomSearchDomain *CustomSearchDomain `json:"customSearchDomain,omitempty"` - CustomNodesDNS *CustomNodesDNS `json:"CustomNodesDNS,omitempty"` - IsSSHKeyAutoGenerated *bool `json:"isSSHKeyAutoGenerated,omitempty"` + Secrets []KeyVaultSecrets `json:"secrets,omitempty"` + Distro Distro `json:"distro,omitempty"` + ScriptRootURL string `json:"scriptroot,omitempty"` + CustomSearchDomain *CustomSearchDomain `json:"customSearchDomain,omitempty"` + CustomNodesDNS *CustomNodesDNS `json:"CustomNodesDNS,omitempty"` + IsSSHKeyAutoGenerated *bool `json:"isSSHKeyAutoGenerated,omitempty"` + RunUnattendedUpgradesOnBootstrap *bool `json:"runUnattendedUpgradesOnBootstrap,omitempty"` } // PublicKey represents an SSH key for LinuxProfile diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index 638c566ace..bfb4128f5f 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -136,10 +136,11 @@ type LinuxProfile struct { SSH struct { PublicKeys []PublicKey `json:"publicKeys" validate:"required,min=1"` } `json:"ssh" validate:"required"` - Secrets []KeyVaultSecrets `json:"secrets,omitempty"` - ScriptRootURL string `json:"scriptroot,omitempty"` - CustomSearchDomain *CustomSearchDomain `json:"customSearchDomain,omitempty"` - CustomNodesDNS *CustomNodesDNS `json:"customNodesDNS,omitempty"` + Secrets []KeyVaultSecrets `json:"secrets,omitempty"` + ScriptRootURL string `json:"scriptroot,omitempty"` + CustomSearchDomain *CustomSearchDomain `json:"customSearchDomain,omitempty"` + CustomNodesDNS *CustomNodesDNS `json:"customNodesDNS,omitempty"` + RunUnattendedUpgradesOnBootstrap *bool `json:"runUnattendedUpgradesOnBootstrap,omitempty"` } // PublicKey represents an SSH key for LinuxProfile diff --git a/pkg/engine/template_generator.go b/pkg/engine/template_generator.go index cf4f64c73f..a86b5cf266 100644 --- a/pkg/engine/template_generator.go +++ b/pkg/engine/template_generator.go @@ -775,6 +775,12 @@ func getContainerServiceFuncMap(cs *api.ContainerService) template.FuncMap { "GetLinuxCSELogPath": func() string { return linuxCSELogPath }, + "RunUnattendedUpgrades": func() bool { + if cs.Properties.LinuxProfile != nil { + return to.Bool(cs.Properties.LinuxProfile.RunUnattendedUpgradesOnBootstrap) + } + return false + }, "OpenBraces": func() string { return "{{" }, diff --git a/pkg/engine/templates_generated.go b/pkg/engine/templates_generated.go index dc20294cbc..4ac50288d0 100644 --- a/pkg/engine/templates_generated.go +++ b/pkg/engine/templates_generated.go @@ -13159,6 +13159,18 @@ apt_get_dist_upgrade() { done echo Executed apt-get dist-upgrade $i times } +unnattended_upgrade() { + retries=10 + for i in $(seq 1 $retries); do + wait_for_apt_locks + /usr/bin/unattended-upgrade && break || + if [ $i -eq $retries ]; then + return 1 + else sleep 5 + fi + done + echo Executed unattended-upgrade $i times +} systemctl_restart() { retries=$1; wait_sleep=$2; timeout=$3 svcname=$4 for i in $(seq 1 $retries); do @@ -13755,6 +13767,10 @@ if [[ $OS == $UBUNTU_OS_NAME ]]; then fi {{end}} +{{- if RunUnattendedUpgrades}} +apt_get_update && apt_get_dist_upgrade && unnattended_upgrade +{{- end}} + if [ -f /var/run/reboot-required ]; then trace_info "RebootRequired" "reboot=true" /bin/bash -c "shutdown -r 1 &" diff --git a/test/e2e/test_cluster_configs/everything.json b/test/e2e/test_cluster_configs/everything.json index 6813eb375f..91850e1904 100644 --- a/test/e2e/test_cluster_configs/everything.json +++ b/test/e2e/test_cluster_configs/everything.json @@ -146,6 +146,7 @@ } ], "linuxProfile": { + "runUnattendedUpgradesOnBootstrap": true, "adminUsername": "azureuser", "ssh": { "publicKeys": [ From 508dd448fff8190227073cf4bc12210b4f04fad1 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Tue, 2 Feb 2021 14:05:50 -0800 Subject: [PATCH 2/4] typo --- parts/k8s/cloud-init/artifacts/cse_helpers.sh | 2 +- parts/k8s/cloud-init/artifacts/cse_main.sh | 2 +- pkg/engine/templates_generated.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parts/k8s/cloud-init/artifacts/cse_helpers.sh b/parts/k8s/cloud-init/artifacts/cse_helpers.sh index 78ec49ae6b..b8a3f12e12 100755 --- a/parts/k8s/cloud-init/artifacts/cse_helpers.sh +++ b/parts/k8s/cloud-init/artifacts/cse_helpers.sh @@ -193,7 +193,7 @@ apt_get_dist_upgrade() { done echo Executed apt-get dist-upgrade $i times } -unnattended_upgrade() { +unattended_upgrade() { retries=10 for i in $(seq 1 $retries); do wait_for_apt_locks diff --git a/parts/k8s/cloud-init/artifacts/cse_main.sh b/parts/k8s/cloud-init/artifacts/cse_main.sh index 7b0019e56f..5d6d3b0ced 100755 --- a/parts/k8s/cloud-init/artifacts/cse_main.sh +++ b/parts/k8s/cloud-init/artifacts/cse_main.sh @@ -277,7 +277,7 @@ fi {{end}} {{- if RunUnattendedUpgrades}} -apt_get_update && apt_get_dist_upgrade && unnattended_upgrade +apt_get_update && apt_get_dist_upgrade && unattended_upgrade {{- end}} if [ -f /var/run/reboot-required ]; then diff --git a/pkg/engine/templates_generated.go b/pkg/engine/templates_generated.go index 4ac50288d0..1f676bea37 100644 --- a/pkg/engine/templates_generated.go +++ b/pkg/engine/templates_generated.go @@ -13159,7 +13159,7 @@ apt_get_dist_upgrade() { done echo Executed apt-get dist-upgrade $i times } -unnattended_upgrade() { +unattended_upgrade() { retries=10 for i in $(seq 1 $retries); do wait_for_apt_locks @@ -13768,7 +13768,7 @@ fi {{end}} {{- if RunUnattendedUpgrades}} -apt_get_update && apt_get_dist_upgrade && unnattended_upgrade +apt_get_update && apt_get_dist_upgrade && unattended_upgrade {{- end}} if [ -f /var/run/reboot-required ]; then From 94b7c6af33dcfe2e905990c11b9ae78560faa6bc Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 3 Feb 2021 11:41:28 -0800 Subject: [PATCH 3/4] skip dist-upgrade --- parts/k8s/cloud-init/artifacts/cse_main.sh | 2 +- pkg/engine/templates_generated.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parts/k8s/cloud-init/artifacts/cse_main.sh b/parts/k8s/cloud-init/artifacts/cse_main.sh index 5d6d3b0ced..d33688e001 100755 --- a/parts/k8s/cloud-init/artifacts/cse_main.sh +++ b/parts/k8s/cloud-init/artifacts/cse_main.sh @@ -277,7 +277,7 @@ fi {{end}} {{- if RunUnattendedUpgrades}} -apt_get_update && apt_get_dist_upgrade && unattended_upgrade +apt_get_update && unattended_upgrade {{- end}} if [ -f /var/run/reboot-required ]; then diff --git a/pkg/engine/templates_generated.go b/pkg/engine/templates_generated.go index 1f676bea37..a313ae7151 100644 --- a/pkg/engine/templates_generated.go +++ b/pkg/engine/templates_generated.go @@ -13768,7 +13768,7 @@ fi {{end}} {{- if RunUnattendedUpgrades}} -apt_get_update && apt_get_dist_upgrade && unattended_upgrade +apt_get_update && unattended_upgrade {{- end}} if [ -f /var/run/reboot-required ]; then From f9ba264f209d10742bd8dcadaca7331cf0f4113e Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 3 Feb 2021 15:09:35 -0800 Subject: [PATCH 4/4] correct docs --- docs/topics/clusterdefinitions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/clusterdefinitions.md b/docs/topics/clusterdefinitions.md index 1da229549e..2006dbdd57 100644 --- a/docs/topics/clusterdefinitions.md +++ b/docs/topics/clusterdefinitions.md @@ -857,7 +857,7 @@ A cluster can have 0 to 12 agent pool profiles. Agent Pool Profiles are used for | adminUsername | yes | Describes the username to be used on all linux clusters | | ssh.publicKeys[].keyData | yes | The public SSH key used for authenticating access to all Linux nodes in the cluster | | secrets | no | Specifies an array of key vaults to pull secrets from and what secrets to pull from each | -| runUnattendedUpgradesOnBootstrap | no | Invoke an unattended-upgrade when each Linux node VM comes online for the first time. In practice this is accomplished by performing an `apt-get update`, followed by an `apt-get dist-upgrade`, to fetch updated apt configuration, and install all available downstream package updates, respectively. | +| runUnattendedUpgradesOnBootstrap | no | Invoke an unattended-upgrade when each Linux node VM comes online for the first time. In practice this is accomplished by performing an `apt-get update`, followed by a manual invocation of `/usr/bin/unattended-upgrade`, to fetch updated apt configuration, and install all package updates provided by the unattended-upgrade facility, respectively. | | customSearchDomain.name | no | describes the search domain to be used on all linux clusters | | customSearchDomain.realmUser | no | describes the realm user with permissions to update dns registries on Windows Server DNS | | customSearchDomain.realmPassword | no | describes the realm user password to update dns registries on Windows Server DNS |