Kubernetes on Azure
Annotations
LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: internal-app
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: internal-app
ClusterManager
This script may be outdated as the code is now on github.
#!/bin/bash
#" ____ _ __ __ _ _ _ "
#"| _ \ ___ ___| | __ _ _ __ ___ \ \ / /_ _ _ __(_) __ _| |__ | | ___ ___ "
#"| | | |/ _ \/ __| |/ _` | '__/ _ \ \ \ / / _` | '__| |/ _` | '_ \| |/ _ \/ __|"
#"| |_| | __/ (__| | (_| | | | __/ \ V / (_| | | | | (_| | |_) | | __/\__ \"
#"|____/ \___|\___|_|\__,_|_| \___| \_/ \__,_|_| |_|\__,_|_.__/|_|\___||___/"
#"
export SUBSCRIPTION=""
export RESOURCEGROUP=""
export LOCATION=""
export CLUSTERNAME=""
export OSDISKSIZE="511"
export K8SVERSION="1.17.0"
# export TAGS=""
export SERVICECIDR=""
export DNSSERVICE=""
export PODCIDR=""
export DOCKERBRIDGE=""
export TAGTAMBIENTE=""
export TAGTRIBO=""
export TAGSQUAD=""
export SPCREDFILE="SP.json"
export SPCLIENTCREDFILE="SPCLIENT.json"
export SPSERVERCREDFILE="SPSERVER.json"
export VNETNAME=""
export SUBNETNAME=""
export SUBNETID="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export VNETRG="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export SERVICEPRINCIPALID="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export SERVICEPRINCIPALSECRET="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export TENANTID="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export CLIENTAPPID="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export SERVERAPPID="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
export SERVERAPPSECRET="" #Fill automatcaly if VNETNAME and SUBNNETNAME is setted
#" _____ _ _ "
#"| ___| _ _ __ ___| |_(_) ___ _ __ ___ "
#"| |_ | | | | '_ \ / __| __| |/ _ \| '_ \/ __|"
#"| _|| |_| | | | | (__| |_| | (_) | | | \__ \"
#"|_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/"
#"
function FIGLET() {
echo " ___ _____ __ ______ ______"
echo " / /__ / / / / / __ \/ ____/"
echo " / /| | / / / / / / /_/ / __/ "
echo " / ___ |/ /__/ /_/ / _, _/ /___ "
echo "/_/ |_/____/\____/_/ |_/_____/ "
echo " "
echo " __ _ _ ______ ____ ____ _____ _ _____ ___ ____ __ "
echo "| _| / \ | |/ / ___| / ___| _ \| ____| / \|_ _/ _ \| _ \_ |"
echo "| | / _ \ | ' /\___ \ | | | |_) | _| / _ \ | || | | | |_) | |"
echo "| |/ ___ \| . \ ___) | | |___| _ <| |___ / ___ \| || |_| | _ <| |"
echo "| /_/ \_\_|\_\____/ \____|_| \_\_____/_/ \_\_| \___/|_| \_\ |"
echo "|__| |__|"
}
function GET_SUBNETID() {
az network vnet subnet show \
--subscription $SUBSCRIPTION \
--vnet-name "$VNETNAME" \
--resource-group "$(GET_VNETRG)" \
--name "$SUBNETNAME" -o tsv \
--query "[id]"
}
function GET_VNETRG() {
az network vnet list \
--subscription $SUBSCRIPTION \
--query "[?name=='$VNETNAME'].[resourceGroup]" \
-o tsv
}
function UPGRADE_NODEPOOL() {
az aks nodepool upgrade \
--subscription $SUBSCRIPTION \
--resource-group $RESOURCEGROUP \
-n $1 \
--kubernetes-version $2 \
--cluster-name $CLUSTERNAME
}
function CREATE_AKS_NETAZURE() {
az aks create \
--subscription $SUBSCRIPTION \
-n $CLUSTERNAME \
-g $RESOURCEGROUP \
-l eastus2 \
--network-plugin azure \
--node-count 1 \
--node-vm-size $1 \
--node-osdisk-size 127 \
--nodepool-name default \
--tags $TAGS \
--vnet-subnet-id $SUBNETID \
--service-principal $SERVICEPRINCIPALID \
--client-secret $SERVICEPRINCIPALSECRET \
--enable-vmss \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 10 \
--node-count 3
# --network-policy calico
}
function CREATE_AKS() {
if [ $# -ne 1 ]
then
EXITNOW "CREATE AKS MISSING NODE SKU"
else
NODESKU=$1
az aks create \
--subscription $SUBSCRIPTION \
-n $CLUSTERNAME \
-g $RESOURCEGROUP \
-l $LOCATION \
--network-plugin kubenet \
--network-policy calico \
--service-cidr $SERVICECIDR \
--dns-service-ip $DNSSERVICE \
--pod-cidr $PODCIDR \
--docker-bridge-address $DOCKERBRIDGE \
--vnet-subnet-id $SUBNETID \
--node-vm-size $NODESKU \
--node-osdisk-size $OSDISKSIZE \
--nodepool-name default \
--tags $TAGTAMBIENTE $TAGTRIBO $TAGSQUAD \
--service-principal $SERVICEPRINCIPALID \
--client-secret $SERVICEPRINCIPALSECRET \
--enable-vmss \
--kubernetes-version $K8SVERSION \
--enable-cluster-autoscaler \
--min-count 1 \
--max-count 2 \
--node-count 1 \
--aad-client-app-id $CLIENTAPPID \
--aad-server-app-id $SERVERAPPID \
--aad-server-app-secret $SERVERAPPSECRET \
--aad-tenant-id $TENANTID \
--generate-ssh-keys
# --enable-private-cluster
fi
}
function TEMPFILE() {
case $1 in
criar)
mktemp -p /tmp --suffix azure
;;
apagar)
rm -f $2
;;
*)
EXITNOW "could not create temporary file"
;;
esac
}
function CREATE_NOODEPOOL() {
az aks nodepool add \
--subscription $SUBSCRIPTION \
--resource-group $RESOURCEGROUP \
--cluster-name $CLUSTERNAME \
--name $1 \
--node-vm-size Standard_B4ms \
--node-osdisk-size 127 \
--node-count 2 \
--vnet-subnet-id $SUBNETID \
--max-count 10 \
--min-count 2 \
--enable-cluster-autoscaler
}
function SCALE_NODEPOOL() {
az aks nodepool scale \
--subscription $SUBSCRIPTION \
--cluster-name $CLUSTERNAME \
--name $1 \
--resource-group $RESOURCEGROUP \
--node-count $2
}
function UPDATE_NODEPOOL_SCALE() {
az aks nodepool update \
--subscription $SUBSCRIPTION \
--cluster-name $CLUSTERNAME \
--name $1 \
--resource-group $RESOURCEGROUP \
--min-count $2 \
--max-count $3 \
--update-cluster-autoscaler \
--enable-cluster-autoscaler
}
function ADD_AZURE_EXTENSIONS() {
az extension add --name aks-preview
az feature register --name VMSSPreview --namespace Microsoft.ContainerService
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/VMSSPreview')].{Name:name,State:properties.state}"
az provider register --namespace Microsoft.ContainerService
}
function CRASH {
echo $1
exit 1
}
function EXITNOW() {
BANNER erro "$1"
exit 1
}
function BANNER() {
case $1 in
titulo)
echo -e "\e[45m" >&2
echo $(date +"%Y-%m-%d_%H-%M_%S")\;$2 >&2
echo -en "\e[0m" >&2
;;
conteudo)
echo -e "\e[44m" >&2
echo $(date +"%Y-%m-%d_%H-%M_%S")\;$2 >&2
echo -en "\e[0m" >&2
;;
sucesso)
echo -e "\e[32m" >&2
echo $(date +"%Y-%m-%d_%H-%M_%S")\;$2 >&2
echo -en "\e[0m" >&2
;;
erro)
echo -e "\e[91m" >&2
echo $(date +"%Y-%m-%d_%H-%M_%S")\;$2 >&2
echo -en "\e[0m" >&2
# exit 1
;;
*)
EXITNOW
;;
esac
}
function VALIDATE() {
#Testing Variables
export RC=OK
if [ "$TENANTID" == "" ]
then
BANNER erro "Variable TENANTID is empty"
export RC=NOK
else
BANNER sucesso "Variable TENANTID OK"
fi
if [ "$SERVERAPPSECRET" == "" ]
then
BANNER erro "Variable SERVERAPPSECRET is empty"
export RC=NOK
else
BANNER sucesso "Variable SERVERAPPSECRET OK"
fi
if [ "$SERVERAPPID" == "" ]
then
BANNER erro "Variable SERVERAPPID is empty"
export RC=NOK
else
BANNER sucesso "Variable SERVERAPPID OK"
fi
if [ "$CLIENTAPPID" == "" ]
then
BANNER erro "Variable CLIENTAPPID is empty"
export RC=NOK
else
BANNER sucesso "Variable CLIENTAPPID OK"
fi
if [ "$K8SVERSION" == "" ]
then
BANNER erro "Variable K8SVERSION is empty"
export RC=NOK
else
BANNER sucesso "Variable K8SVERSION OK"
fi
if [ "$TAGTAMBIENTE" == "" ]
then
BANNER erro "Variable TAGTAMBIENTE is empty"
export RC=NOK
else
BANNER sucesso "Variable TAGTAMBIENTE OK"
fi
if [ "$TAGTRIBO" == "" ]
then
BANNER erro "Variable TAGTRIBO is empty"
export RC=NOK
else
BANNER sucesso "Variable TAGTRIBO OK"
fi
if [ "$TAGSQUAD" == "" ]
then
BANNER erro "Variable TAGSQUAD is empty"
export RC=NOK
else
BANNER sucesso "Variable TAGSQUAD OK"
fi
if [ "$OSDISKSIZE" == "" ]
then
BANNER erro "Variable OSDISKSIZE is empty"
export RC=NOK
else
BANNER sucesso "Variable OSDISKSIZE OK"
fi
if [ "$PODCIDR" == "" ]
then
BANNER erro "Variable PODCIDR is empty"
export RC=NOK
else
BANNER sucesso "Variable PODCIDR OK"
fi
if [ "$DNSSERVICE" == "" ]
then
BANNER erro "Variable DNSSERVICE is empty"
export RC=NOK
else
BANNER sucesso "Variable DNSSERVICE OK"
fi
if [ "$SERVICECIDR" == "" ]
then
BANNER erro "Variable SERVICECIDR is empty"
export RC=NOK
else
BANNER sucesso "Variable SERVICECIDR OK"
fi
if [ "$LOCATION" == "" ]
then
BANNER erro "Variable LOCATION is empty"
export RC=NOK
else
BANNER sucesso "Variable LOCATION OK"
fi
if [ "$SUBSCRIPTION" == "" ]
then
BANNER erro "Variable SUBSCRIPTION is empty"
export RC=NOK
else
BANNER sucesso "Variable SUBSCRIPTION OK"
fi
if [ "$RESOURCEGROUP" == "" ]
then
BANNER erro "Variable RESOURCEGROUP is empty"
export RC=NOK
else
BANNER sucesso "Variable RESOURCEGROUP OK"
fi
if [ "$CLUSTERNAME" == "" ]
then
BANNER erro "Variable CLUSTERNAME is empty"
export RC=NOK
else
BANNER sucesso "Variable CLUSTERNAME OK"
fi
if [ "$SUBNETID" == "" ]
then
BANNER erro "Variable SUBNETID is empty"
export RC=NOK
else
BANNER sucesso "Variable SUBNETID OK"
fi
if [ "$SERVICEPRINCIPALID" == "" ]
then
BANNER erro "Variable SERVICEPRINCIPALID is empty"
export RC=NOK
else
BANNER sucesso "Variable SERVICEPRINCIPALID OK"
fi
if [ "$SERVICEPRINCIPALSECRET" == "" ]
then
BANNER erro "Variable SERVICEPRINCIPALSECRET is empty"
export RC=NOK
else
BANNER sucesso "Variable SERVICEPRINCIPALSECRET OK"
fi
# if [ "$TAGS" == "" ]
# then
# BANNER erro "Variable TAGS is empty"
# export RC=NOK
# else
# BANNER sucesso "Variable TAGS OK"
# fi
if [ "$VNETNAME" == "" ]
then
BANNER erro "Variable VNETNAME is empty"
export RC=NOK
else
BANNER sucesso "Variable VNETNAME OK"
fi
if [ "$SUBNETNAME" == "" ]
then
BANNER erro "Variable SUBNETNAME is empty"
export RC=NOK
else
BANNER sucesso "Variable SUBNETNAME OK"
fi
if [ "$RC" == "NOK" ]
then
EXITNOW "Aborted: Missing variables"
fi
#Test if resooure group exist
az group show --subscription $SUBSCRIPTION --name $RESOURCEGROUP 2>&1 > /dev/null
RETURN=$?
if [ $RETURN -ne 0 ]
then
EXITNOW "Resource group do not exist"
else
BANNER sucesso "Resource group exist"
fi
az aks show --subscription $SUBSCRIPTION --name $CLUSTERNAME --resource-group $RESOURCEGROUP 2>&1 > /dev/null
RETURN=$?
if [ $RETURN -eq 0 ]
then
EXITNOW "Cluster AKS already exist"
else
BANNER sucesso "Cluster AKS do not exist"
fi
# az network vnet list --query "[?name=='$VNETNAME'].[resourceGroup]" -o tsv
export VNETRG=$(az network vnet list --subscription $SUBSCRIPTION --query "[?name=='$VNETNAME'].[resourceGroup]" -o tsv)
az network vnet show --subscription $SUBSCRIPTION --name $VNETNAME --resource-group $VNETRG 2>&1 > /dev/null
RETURN=$?
if [ $RETURN -ne 0 ]
then
EXITNOW "VNET does not exist"
else
BANNER sucesso "VNET exist"
fi
az network vnet subnet show --subscription $SUBSCRIPTION --vnet-name $VNETNAME --resource-group $VNETRG --name $SUBNETNAME 2>&1 > /dev/null
RETURN=$?
if [ $RETURN -ne 0 ]
then
EXITNOW "SUBNET does not exist"
else
BANNER sucesso "SUBNET exist"
fi
}
function GETVARS(){
if [ "$SUBNETID" == "" ]
then
export SUBNETID=$(GET_SUBNETID)
fi
if [ "$VNETRG" == "" ]
then
export VNETRG=$(GET_VNETRG)
fi
if [ "$SERVICEPRINCIPALID" == "" ]
then
export SERVICEPRINCIPALID=$(GET_SERVICEPRINCIPALID)
fi
if [ "$SERVICEPRINCIPALSECRET" == "" ]
then
export SERVICEPRINCIPALSECRET=$(GET_SERVICEPRINCIPALSECRET)
fi
if [ "$TENANTID" == "" ]
then
export TENANTID=$(GET_TENANTID)
fi
if [ "$SERVERAPPID" == "" ]
then
export SERVERAPPID=$(GET_SERVERAPPID)
fi
if [ "$SERVERAPPSECRET" == "" ]
then
export SERVERAPPSECRET=$(GET_SERVERAPPSECRET)
fi
if [ "$CLIENTAPPID" == "" ]
then
export CLIENTAPPID=$(GET_CLIENTAPPID)
fi
}
function GET_SERVICEPRINCIPALID(){
if [ -f "$SPCREDFILE" ]
then
cat $SPCREDFILE | jq "[.appId]|@tsv" | sed -e "s/\"//g"
else
RETURN=$(az ad app list --all --query "[?displayName=='$CLUSTERNAME'].[displayName]" -o tsv | wc -l)
if [ $RETURN -eq 0 ]
then
az ad sp create-for-rbac -n $CLUSTERNAME --skip-assignment true > $SPCREDFILE
cat $SPCREDFILE | jq "[.appId]|@tsv" | sed -e "s/\"//g"
else
EXITNOW "Service principal allready exist"
fi
fi
}
function GET_SERVICEPRINCIPALSECRET(){
if [ -f "$SPCREDFILE" ]
then
cat $SPCREDFILE | jq "[.password]|@tsv" | sed -e "s/\"//g"
else
EXITNOW "Service principal secret is empty"
fi
}
function GET_TENANTID(){
if [ -f "$SPCREDFILE" ]
then
cat $SPCREDFILE | jq "[.tenant]|@tsv" | sed -e "s/\"//g"
else
EEXITNOW "Server APP allready exist"
fi
}
function GET_SERVERAPPID(){
if [ -f "$SPSERVERCREDFILE" ]
then
cat $SPSERVERCREDFILE | jq "[.appId]|@tsv" | sed -e "s/\"//g"
else
RETURN=$(az ad app list --all --query "[?displayName=='${CLUSTERNAME}Server'].[displayName]" -o tsv | wc -l)
if [ $RETURN -eq 0 ]
then
# Create the Azure AD application
serverApplicationId=$(az ad app create \
--display-name "${CLUSTERNAME}Server" \
--identifier-uris "https://${CLUSTERNAME}Server" \
--query appId -o tsv)
# Update the application group memebership claims
az ad app update --id $serverApplicationId --set groupMembershipClaims=All > /dev/null
# Create a service principal for the Azure AD application
az ad sp create --id $serverApplicationId > /dev/null
# Get the service principal secret
az ad sp credential reset \
--name $serverApplicationId \
--credential-description "AKSPassword" > $SPSERVERCREDFILE
# Add permissions for the Azure AD app to read directory data, sign in and read
# user profile, and read directory data
az ad app permission add \
--id $serverApplicationId \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions e1fe6dd8-ba31-4d61-89e7-88639da4683d=Scope 06da0dbc-49e2-44d2-8312-53f166ab848a=Scope 7ab1d382-f21e-4acd-a863-ba3e13f7da61=Role > /dev/null
# Grant permissions for the permissions assigned in the previous step
# You must be the Azure AD tenant admin for these steps to successfully complete
az ad app permission grant --id $serverApplicationId --api 00000003-0000-0000-c000-000000000000 > /dev/null
az ad app permission admin-consent --id $serverApplicationId > /dev/null
#Return the appid
cat $SPSERVERCREDFILE | jq "[.appId]|@tsv" | sed -e "s/\"//g"
else
EXITNOW "Server APP allready exist"
fi
fi
}
function GET_SERVERAPPSECRET(){
if [ -f "$SPSERVERCREDFILE" ]
then
cat $SPSERVERCREDFILE | jq "[.password]|@tsv" | sed -e "s/\"//g"
else
EXITNOW "Service principal Serversecret is empty"
fi
}
function GET_CLIENTAPPID(){
if [ -f "$SPCLIENTCREDFILE" ]
then
cat $SPCLIENTCREDFILE
else
RETURN=$(az ad app list --all --query "[?displayName=='${CLUSTERNAME}Client'].[displayName]" -o tsv | wc -l)
if [ $RETURN -eq 0 ]
then
# Create the Azure AD client application
az ad app create \
--display-name "${CLUSTERNAME}Client" \
--native-app \
--reply-urls "https://${CLUSTERNAME}Client" \
--query appId -o tsv > $SPCLIENTCREDFILE
export clientApplicationId=$(cat $SPCLIENTCREDFILE )
export serverApplicationId=$(GET_SERVERAPPID)
# Create a service principal for the client application
az ad sp create --id $clientApplicationId > /dev/null
# Get the oAuth2 ID for the server app to allow authentication flow
oAuthPermissionId=$(az ad app show --id $serverApplicationId --query "oauth2Permissions[0].id" -o tsv) > /dev/null
# Assign permissions for the client and server applications to communicate with each other
az ad app permission add --id $clientApplicationId --api $serverApplicationId --api-permissions $oAuthPermissionId=Scope > /dev/null
az ad app permission grant --id $clientApplicationId --api $serverApplicationId > /dev/null
cat $SPCLIENTCREDFILE
else
EXITNOW "Server APP allready exist"
fi
fi
}
function SET_SUBNET_PERMISSION() {
az role assignment create \
--role "Subnet Join [Custom]" \
--assignee $SERVICEPRINCIPALID \
--scope $SUBNETID
}
function SET_AKS_PERMISSION() {
export AKS_ID=$(az aks list \
--subscription $SUBSCRIPTION \
-g $RESOURCEGROUP \
--query "[?name=='${CLUSTERNAME}'].[id]" -o tsv)
az role assignment create \
--role "Contributor" \
--assignee $SERVICEPRINCIPALID \
--scope $AKS_ID
}
#" _____ _ _____ _ _ "
#"|_ _|_ _ ___| | __ | ____|_ _____ ___ _ _| |_(_) ___ _ __ ___ "
#" | |/ _` / __| |/ / | _| \ \/ / _ \/ __| | | | __| |/ _ \| '_ \/ __|"
#" | | (_| \__ \ < | |___ > < __/ (__| |_| | |_| | (_) | | | \__ \"
#" |_|\__,_|___/_|\_\ |_____/_/\_\___|\___|\__,_|\__|_|\___/|_| |_|___/"
#" "
FIGLET
GETVARS
VALIDATE
# ADD_AZURE_EXTENSIONS #Oly needed if using preview features
CREATE_AKS Standard_D2s_v3
SET_SUBNET_PERMISSION
SET_AKS_PERMISSION
CREATE_NOODEPOOL new_nodepool_name Standard_D4s_v3
UPGRADE_NODEPOOL new_nodepool_name 1.18.7
UPDATE_NODEPOOL_SCALE new_nodepool_name 2 20
# SCALE_NODEPOOL default 1
Old Version
# Create service principal for the cluster. The service principal will be used too to allow access to the registry.
az ad sp create-for-rbac --role="Contributor" --name "<name>" --scopes="/subscriptions/SUBSCRIPTION_ID"
# Register feature of the VMSS
az feature register --name VMSSPreview --namespace Microsoft.ContainerService
# List features from the Azure
az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/VMSSPreview')].{Name:name,State:properties.state}"
# Register the container service on Azure
az provider register --namespace Microsoft.ContainerService
# Add the aks-preview extension
az extension add --name aks-preview
#Command to create the AKS cluster on Azure
az aks create \
-n "" \
-g "" \
-l eastus2 \
--network-plugin azure \
--node-count 1 \
--node-vm-size Standard_B4ms \
--node-osdisk-size 127 \
--nodepool-name "" \
--tags "" \
--vnet-subnet-id "" \
--service-principal "" \
--client-secret "" \
--enable-vmss \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 10 \
--node-count 3