Skip to content

Instantly share code, notes, and snippets.

@Ch4ni
Last active August 19, 2025 03:46
Show Gist options
  • Select an option

  • Save Ch4ni/adc43ae1c87d73221c494bccfb90b660 to your computer and use it in GitHub Desktop.

Select an option

Save Ch4ni/adc43ae1c87d73221c494bccfb90b660 to your computer and use it in GitHub Desktop.
Upgrade EKS script - automate upgrading k8s clusters in AWS
#! /usr/bin/env bash
# Set the target k8s verson for upgrade (must be max of current version+1)
# TODO: fetch the k8s version (server) using kubectl, parse/increment, and set this
TGT_K8S_VERSION=${TGT_K8S_VERSION:-1.26}
# build the cluster name. Doing it this way makes it a lot easier to run updates on
# multiple clusters with names we may or may not have at the time of writing this script.
TGT_K8S_CLUSTER="${TGT_K8S_CLUSTER:-${TGT_K8S_CLUSTER_PREFIX:+${TGT_K8S_CLUSTER_PREFIX}${SEPARATOR}}${TGT_ENV:-dev}${TGT_K8S_CLUSTER_SUFFIX:+${SEPARATOR}${TGT_K8S_CLUSTER_SUFFIX}}}"
# utility function
# since we're operating on production clusters, make sure we can inspect the
# computed configurations before running potentially dangerous operations.
function promptToContinue() {
printf '\n'
__msg=${1}
read -p "${__msg:+${__msg}. }Would you like to continue? [Yy]/[Nn] " __prompt_answer
return $([[ ${__prompt_answer,,} == 'y' ]]);
}
# utility function
# a little bit of basic formatting in the shell makes the outputs (including configuration)
# a lot easier to read on the terminal.
function underlineString() {
__msg=${1}
__msgLen=${#__msg}
printf '\n\n%s\n' "${__msg}"
printf '=%0.s' $(seq 1 ${__msgLen})
printf '\n'
}
# Group operations by target - addons
#
# Fetch the installed EKS addons from AWS, and extract out the latest supported
# version numbers for our cluster version. Upgrades go *a lot* smoother when
# running the most recent supported version of an addon for the current cluster version
# (this also gives us a chance to test the new addon versions as-needed).
function updateAddons() {
# convenience vars for filenames
addonConfigYaml="eksctl.get.addons.${TGT_K8S_CLUSTER}.yaml"
addonConfigUpgradeYaml="eksctl.get.addons.${TGT_K8S_CLUSTER}.upgradeToLatest.yaml"
# get the current add-ons (versions/config)
underlineString "Fetching eksctl addon config for ${TGT_K8S_CLUSTER}"
eksctl get addon --cluster ${TGT_K8S_CLUSTER} --output yaml 2>/dev/null | tee ${addonConfigYaml} && printf '\n\n'
# update the config to specify the latest compatible versions
underlineString "Update config for addon updates"
sed -e '/^\s\{0,\}NewerVersion/s/:.\{0,\}$/: ""/' -e '/^\s\{0,\}Version/s/:.\{0,\}$/: latest/' \
${addonConfigYaml} | \
tee ${addonConfigUpgradeYaml} && printf '\n\n'
promptToContinue "Ready to upgrade addons" && eksctl update addon -f ${addonConfigUpgradeYaml}
}
# Group operations by target - Cluster
#
# Perform the control-plane upgrade - view the new configuration before applying the upgrade
function upgradeCluster() {
underlineString "Prepare Cluster Control Plane Upgrade for ${TGT_K8S_CLUSTER} to version ${TGT_K8S_VERSION}"
eksctl upgrade cluster --name ${TGT_K8S_CLUSTER} --version ${TGT_K8S_VERSION}
promptToContinue "Apply Cluster Control Plane Upgrade for ${TGT_K8S_CLUSTER} to version ${TGT_K8S_VERSION}" && \
eksctl upgrade cluster --name ${TGT_K8S_CLUSTER} --version ${TGT_K8S_VERSION} --approve
}
# Group operations by target - NodeGroup
#
# Once the cluster is upgraded all of the nodes in the node group need an updated kubelet.
# This uses eksctl to run the upgrades, which attempts to ensure there's enough nodes up
# to service the cluster's compute requirements as it runs the upgrade.
function upgradeNodeGroup() {
promptToContinue "Apply Cluster Data Plane Upgrade for ${TGT_K8S_CLUSTER} to version ${TGT_K8S_VERSION}" && \
eksctl upgrade nodegroup --name ${TGT_K8S_CLUSTER}-node-group --cluster ${TGT_K8S_CLUSTER} --kubernetes-version ${TGT_K8S_VERSION}
}
# The full upgrade process:
updateAddons && upgradeCluster && upgradeNodeGroup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment