Skip to content

Instantly share code, notes, and snippets.

@mustafakirimli
Last active December 15, 2022 20:02
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mustafakirimli/12c337d337e83fd8ce498f65115c0a98 to your computer and use it in GitHub Desktop.
Save mustafakirimli/12c337d337e83fd8ce498f65115c0a98 to your computer and use it in GitHub Desktop.
Enable nested virtualization on GKE (be careful when running)
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
# $IG_URLS as env
# GET auth token to be used in curl/rest api
AUTH_TOKEN=$(gcloud auth print-access-token)
function isGoogResExists {
PARAMS=(
-s
-I
-o /dev/null
-w "%{http_code}"
-H "Authorization: Bearer ${AUTH_TOKEN}"
-H "Content-Type: application/json"
)
status_code=$(curl "${PARAMS[@]}" $1);
if [ $status_code -eq 404 ]; then
return 1
elif [ $status_code -eq 200 ]; then
return 0
fi
}
function makeGoogGetReq {
PARAMS=(
-s
-H "Authorization: Bearer ${AUTH_TOKEN}"
-H "Content-Type: application/json"
)
curl "${PARAMS[@]}" $1;
}
function makeGoogPostReq {
PARAMS=(
-s
-XPOST
-H "Authorization: Bearer ${AUTH_TOKEN}"
-H "Content-Type: application/json"
)
curl "${PARAMS[@]}" $1 --data "$2";
}
# Loop over intances group urls
for igurl in ${IG_URLS//,/ }; do
# GET instance template from instance group
it_url=$(makeGoogGetReq $igurl | jq -r .instanceTemplate);
BASE_IT_URL="${it_url%/instanceTemplates*}/instanceTemplates"
it_json=$(makeGoogGetReq $it_url);
# STEP 1: DUPLICATE INSTANCE TEMPLATE
it_name=$(echo $it_json | jq -r '.name')
if [[ "$it_name" != *-vmx ]]; then
it_name="${it_name}-vmx";
fi
new_it_url="${BASE_IT_URL}/${it_name}"
if isGoogResExists "$new_it_url"; then
echo "Instance Template exists.."
else
echo "Creating new InstanceTemplate.."
extra_pkg=(
'apt-get update && '
'apt-get install -y '
'qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils'
);
printf -v _extra_pkg "%s" "${extra_pkg[@]}";
OPS=(
'.name = $it_name'
'.properties.advancedMachineFeatures.enableNestedVirtualization = true'
'(.properties.metadata.items[] | select(.key == "configure-sh") | .value) += $extra_pkg'
'(.properties.metadata.items[] | select(.key == "configure-sh") | .value) += "\n"'
)
printf -v _OPS " | %s" "${OPS[@]}"
ARGS=(
--arg it_name "$it_name"
--arg extra_pkg "$_extra_pkg"
)
new_it_json=$(echo "$it_json" | jq -r ". $_OPS" "${ARGS[@]}");
makeGoogPostReq $BASE_IT_URL "$new_it_json"
fi
# STEP 2: UPDATE INSTANCE GROUP WITH NEW INSTANCE TEMPLATE
if [[ $(makeGoogGetReq "$igurl" | jq -r .instanceTemplate) == "$new_it_url" ]]; then
echo "InstanceGroup up-to-date"
else
# UPDATE IG with new IT
echo "Updating InstanceGroup with ${new_it_url}.."
body=$(printf '{"instanceTemplate": "%s"}' "$new_it_url")
makeGoogPostReq "$igurl/setInstanceTemplate" "$body"
echo "InstanceGroup updated!"
until [ $(makeGoogGetReq "$igurl" | jq -r .instanceTemplate) == "$new_it_url" ]; do
echo "Waiting new InstanceTemplate to get applied.."
sleep 3
done
# STEP 3: RECREATE/REPLACE INSTANCES in IG
body='{"allInstances": "true", "minimalAction":"REPLACE"}'
makeGoogPostReq "$igurl/applyUpdatesToInstances" "$body"
echo "InstanceGroup instances recreate request sent!"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment