Last active
July 11, 2025 22:19
-
-
Save Bryce-Soghigian/fc3de3a796b20dbed8fe5d2ca0c85dd4 to your computer and use it in GitHub Desktop.
Scoped Subnet Permissions GIST
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # AKS Custom Networking Setup Script - Approach B (Scoped Subnet Permissions) | |
| # This script creates an AKS cluster with custom VNet and subnets for Karpenter | |
| set -e # Exit on any error | |
| # Color codes for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' # No Color | |
| # Function to print colored output | |
| print_status() { | |
| echo -e "${GREEN}[INFO]${NC} $1" | |
| } | |
| print_warning() { | |
| echo -e "${YELLOW}[WARNING]${NC} $1" | |
| } | |
| print_error() { | |
| echo -e "${RED}[ERROR]${NC} $1" | |
| } | |
| # Check if Azure CLI is installed and logged in | |
| check_prerequisites() { | |
| print_status "Checking prerequisites..." | |
| if ! command -v az &> /dev/null; then | |
| print_error "Azure CLI is not installed. Please install it first." | |
| exit 1 | |
| fi | |
| if ! az account show &> /dev/null; then | |
| print_error "Not logged in to Azure. Please run 'az login' first." | |
| exit 1 | |
| fi | |
| print_status "Prerequisites check passed." | |
| } | |
| # Default values - can be overridden by environment variables | |
| RESOURCE_GROUP="${RESOURCE_GROUP:-my-aks-rg}" | |
| LOCATION="${LOCATION:-eastus}" | |
| VNET_NAME="${VNET_NAME:-my-aks-vnet}" | |
| CLUSTER_SUBNET="${CLUSTER_SUBNET:-cluster-subnet}" | |
| CUSTOM_SUBNET="${CUSTOM_SUBNET:-custom-subnet}" | |
| CLUSTER_NAME="${CLUSTER_NAME:-my-aks-cluster}" | |
| SUBSCRIPTION_ID="${SUBSCRIPTION_ID:-$(az account show --query id -o tsv)}" | |
| # Display configuration | |
| print_configuration() { | |
| print_status "Configuration:" | |
| echo " Resource Group: $RESOURCE_GROUP" | |
| echo " Location: $LOCATION" | |
| echo " VNet Name: $VNET_NAME" | |
| echo " Cluster Subnet: $CLUSTER_SUBNET" | |
| echo " Custom Subnet: $CUSTOM_SUBNET" | |
| echo " Cluster Name: $CLUSTER_NAME" | |
| echo " Subscription ID: $SUBSCRIPTION_ID" | |
| echo | |
| } | |
| # Create resource group | |
| create_resource_group() { | |
| print_status "Creating resource group: $RESOURCE_GROUP" | |
| az group create --name "$RESOURCE_GROUP" --location "$LOCATION" | |
| } | |
| # Create VNet and subnets | |
| create_networking() { | |
| print_status "Creating VNet: $VNET_NAME" | |
| az network vnet create \ | |
| --resource-group "$RESOURCE_GROUP" \ | |
| --name "$VNET_NAME" \ | |
| --address-prefixes 10.0.0.0/16 | |
| print_status "Creating cluster subnet: $CLUSTER_SUBNET" | |
| az network vnet subnet create \ | |
| --resource-group "$RESOURCE_GROUP" \ | |
| --vnet-name "$VNET_NAME" \ | |
| --name "$CLUSTER_SUBNET" \ | |
| --address-prefixes 10.0.1.0/24 | |
| print_status "Creating custom subnet: $CUSTOM_SUBNET" | |
| az network vnet subnet create \ | |
| --resource-group "$RESOURCE_GROUP" \ | |
| --vnet-name "$VNET_NAME" \ | |
| --name "$CUSTOM_SUBNET" \ | |
| --address-prefixes 10.0.2.0/24 | |
| } | |
| # Create AKS cluster | |
| create_aks_cluster() { | |
| print_status "Getting cluster subnet ID..." | |
| CLUSTER_SUBNET_ID=$(az network vnet subnet show \ | |
| --resource-group "$RESOURCE_GROUP" \ | |
| --vnet-name "$VNET_NAME" \ | |
| --name "$CLUSTER_SUBNET" \ | |
| --query id -o tsv) | |
| print_status "Creating AKS cluster: $CLUSTER_NAME" | |
| print_warning "This may take 10-15 minutes..." | |
| az aks create \ | |
| --resource-group "$RESOURCE_GROUP" \ | |
| --name "$CLUSTER_NAME" \ | |
| --node-count 1 \ | |
| --vnet-subnet-id "$CLUSTER_SUBNET_ID" \ | |
| --network-plugin azure \ | |
| --enable-managed-identity \ | |
| --node-provisioning-mode Auto \ | |
| --generate-ssh-keys | |
| } | |
| # Configure kubectl | |
| configure_kubectl() { | |
| print_status "Configuring kubectl..." | |
| az aks get-credentials --resource-group "$RESOURCE_GROUP" --name "$CLUSTER_NAME" | |
| } | |
| # Create custom role for subnet access | |
| create_custom_role() { | |
| print_status "Creating custom role for Karpenter subnet access..." | |
| cat > subnet-access-role.json << EOF | |
| { | |
| "Name": "Karpenter Subnet Access", | |
| "IsCustom": true, | |
| "Description": "Allows reading subnet information and joining VMs to subnets", | |
| "Actions": [ | |
| "Microsoft.Network/virtualNetworks/subnets/read", | |
| "Microsoft.Network/virtualNetworks/subnets/join/action" | |
| ], | |
| "NotActions": [], | |
| "DataActions": [], | |
| "NotDataActions": [], | |
| "AssignableScopes": [ | |
| "/subscriptions/$SUBSCRIPTION_ID" | |
| ] | |
| } | |
| EOF | |
| # Check if role already exists, if not create it | |
| if ! az role definition list --name "Karpenter Subnet Access" --query '[0].name' -o tsv &> /dev/null; then | |
| print_status "Creating custom role definition..." | |
| az role definition create --role-definition subnet-access-role.json | |
| else | |
| print_status "Custom role 'Karpenter Subnet Access' already exists, skipping creation." | |
| fi | |
| } | |
| # Setup RBAC permissions for Karpenter - Approach B (Scoped Subnet Permissions) | |
| setup_rbac() { | |
| print_status "Setting up RBAC permissions for Karpenter (Approach B)..." | |
| # Get cluster identity | |
| CLUSTER_IDENTITY=$(az aks show --resource-group "$RESOURCE_GROUP" --name "$CLUSTER_NAME" --query identity.principalId -o tsv) | |
| # Create custom role first | |
| create_custom_role | |
| # Get custom subnet resource ID | |
| CUSTOM_SUBNET_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/$VNET_NAME/subnets/$CUSTOM_SUBNET" | |
| print_status "Assigning custom role to specific subnet (Approach B - Scoped permissions)..." | |
| az role assignment create \ | |
| --assignee "$CLUSTER_IDENTITY" \ | |
| --role "Karpenter Subnet Access" \ | |
| --scope "$CUSTOM_SUBNET_ID" | |
| print_status "RBAC setup completed." | |
| print_status "Custom 'Karpenter Subnet Access' role assigned to specific subnet for cluster identity." | |
| } | |
| # Create sample AKSNodeClass | |
| create_sample_nodeclass() { | |
| print_status "Creating sample AKSNodeClass..." | |
| CUSTOM_SUBNET_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/$VNET_NAME/subnets/$CUSTOM_SUBNET" | |
| cat > sample-nodeclass.yaml << EOF | |
| apiVersion: karpenter.azure.com/v1beta1 | |
| kind: AKSNodeClass | |
| metadata: | |
| name: custom-networking | |
| spec: | |
| vnetSubnetID: "$CUSTOM_SUBNET_ID" | |
| EOF | |
| print_status "Sample AKSNodeClass saved to: sample-nodeclass.yaml" | |
| print_status "Custom subnet ID: $CUSTOM_SUBNET_ID" | |
| } | |
| # Create sample NodePool | |
| create_sample_nodepool() { | |
| print_status "Creating sample NodePool..." | |
| cat > sample-nodepool.yaml << EOF | |
| apiVersion: karpenter.sh/v1 | |
| kind: NodePool | |
| metadata: | |
| name: custom-networking-pool | |
| spec: | |
| template: | |
| spec: | |
| nodeClassRef: | |
| group: karpenter.azure.com | |
| kind: AKSNodeClass | |
| name: custom-networking | |
| requirements: | |
| - key: kubernetes.io/arch | |
| operator: In | |
| values: ["amd64"] | |
| - key: karpenter.sh/capacity-type | |
| operator: In | |
| values: ["on-demand"] | |
| limits: | |
| cpu: 1000 | |
| disruption: | |
| consolidationPolicy: WhenEmpty | |
| consolidateAfter: 30s | |
| EOF | |
| print_status "Sample NodePool saved to: sample-nodepool.yaml" | |
| } | |
| # Display next steps | |
| display_next_steps() { | |
| print_status "Setup completed successfully!" | |
| echo | |
| print_status "Next steps:" | |
| echo "Check on the status of the nodepools + nodeclasses" | |
| echo "Scale up a workload and validate nic connectivity" | |
| print_status "Custom subnet ID for reference:" | |
| echo " /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/$VNET_NAME/subnets/$CUSTOM_SUBNET" | |
| echo | |
| print_status "Custom role definition saved to: subnet-access-role.json" | |
| print_warning "To use additional subnets, assign the 'Karpenter Subnet Access' role to each subnet scope." | |
| } | |
| # Main execution | |
| main() { | |
| print_status "Starting AKS Custom Networking Setup (Approach B - Scoped Subnet Permissions)..." | |
| echo | |
| check_prerequisites | |
| print_configuration | |
| # Confirm before proceeding | |
| read -p "Do you want to proceed with this configuration? (y/N): " -n 1 -r | |
| echo | |
| if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
| print_warning "Setup cancelled by user." | |
| exit 0 | |
| fi | |
| create_resource_group | |
| create_networking | |
| create_aks_cluster | |
| configure_kubectl | |
| setup_rbac | |
| create_sample_nodeclass | |
| create_sample_nodepool | |
| display_next_steps | |
| } | |
| # Handle script arguments | |
| case "${1:-}" in | |
| --help|-h) | |
| echo "AKS Custom Networking Setup Script - Approach B (Scoped Subnet Permissions)" | |
| echo | |
| echo "Environment variables (with defaults):" | |
| echo " RESOURCE_GROUP=my-aks-rg" | |
| echo " LOCATION=eastus" | |
| echo " VNET_NAME=my-aks-vnet" | |
| echo " CLUSTER_SUBNET=cluster-subnet" | |
| echo " CUSTOM_SUBNET=custom-subnet" | |
| echo " CLUSTER_NAME=my-aks-cluster" | |
| echo " SUBSCRIPTION_ID=(current subscription)" | |
| echo | |
| echo "Usage: $0 [--help]" | |
| exit 0 | |
| ;; | |
| *) | |
| main | |
| ;; | |
| esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment