Quickstart
Azure Arc GA
https://portal.azure.com/#blade/HubsExtension/Resources/resourceType/Microsoft.Resources%2Fresources
Install Azure CLI
Azure Developer Guide#AzureCLIInstallation
Install Azure CLI on OSX
https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-macos?view=azure-cli-latest
$ brew install azure-cli ==> Installing dependencies for azure-cli: openssl@1.1, gdbm, readline, sqlite, xz and python@3.8 ==> Installing azure-cli dependency: openssl@1.1 /usr/local/Cellar/python@3.8/3.8.1: 4,094 files, 62.8MB ==> Installing azure-cli ==> Downloading https://homebrew.bintray.com/bottles/azure-cli-2.1.0.catalina.bottle.tar.gz # upgrade brew upgrade azure-cli
Create Azure Jumpbox on Ubuntu
Follow https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-apt?view=azure-cli-latest
Single
Login to Azure CLI
https://portal.azure.com/#blade/HubsExtension/Resources/resourceType/Microsoft.Resources%2Fresources
$ az login You have logged in. Now let us find all the subscriptions to which you have access... [{ "cloudName": "AzureCloud", "homeTenantId": "bcb.4f", "id": "f4b7..70e8b", "isDefault": true, "managedByTenants": [], "name": "Pay-As-You-Go", "state": "Enabled", "tenantId": "bcb..f4f", "user": { "name": "mic...sg", "type": "user" }}]
Kubernetes on Azure
see Kubernetes Developer Guide#SwitchingcontextfromAzureAKSbacktolocalDockerDesktopKubernetes
Kubernetes on Azure AKS - Managed
https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough
https://docs.microsoft.com/en-us/azure/aks/kubernetes-dashboard
Create AKS Cluster
Console and ARM version | |
---|---|
template | { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "resourceName": { "type": "string", "metadata": { "description": "The name of the Managed Cluster resource." } }, "location": { "type": "string", "metadata": { "description": "The location of AKS resource." } }, "dnsPrefix": { "type": "string", "metadata": { "description": "Optional DNS prefix to use with hosted Kubernetes API server FQDN." } }, "osDiskSizeGB": { "type": "int", "defaultValue": 0, "metadata": { "description": "Disk size (in GiB) to provision for each of the agent pool nodes. This value ranges from 0 to 1023. Specifying 0 will apply the default disk size for that agentVMSize." }, "minValue": 0, "maxValue": 1023 }, "kubernetesVersion": { "type": "string", "defaultValue": "1.7.7", "metadata": { "description": "The version of Kubernetes." } }, "networkPlugin": { "type": "string", "allowedValues": [ "azure", "kubenet" ], "metadata": { "description": "Network plugin used for building Kubernetes network." } }, "enableRBAC": { "type": "bool", "defaultValue": true, "metadata": { "description": "Boolean flag to turn on and off of RBAC." } }, "vmssNodePool": { "type": "bool", "defaultValue": false, "metadata": { "description": "Boolean flag to turn on and off of virtual machine scale sets" } }, "windowsProfile": { "type": "bool", "defaultValue": false, "metadata": { "description": "Boolean flag to turn on and off of virtual machine scale sets" } }, "servicePrincipalClientId": { "metadata": { "description": "Client ID (used by cloudprovider)." }, "type": "securestring" }, "servicePrincipalClientSecret": { "metadata": { "description": "The Service Principal Client Secret." }, "type": "securestring" }, "enablePrivateCluster": { "type": "bool", "defaultValue": false, "metadata": { "description": "Enable private network access to the Kubernetes cluster." } }, "aadSessionKey": { "type": "securestring", "defaultValue": "" }, "enableHttpApplicationRouting": { "type": "bool", "defaultValue": true, "metadata": { "description": "Boolean flag to turn on and off http application routing." } }, "enableAzurePolicy": { "type": "bool", "defaultValue": false, "metadata": { "description": "Boolean flag to turn on and off Azure Policy addon." } }, "principalId": { "type": "string", "metadata": { "description": "The objectId of service principal." } }, "enableOmsAgent": { "type": "bool", "defaultValue": true, "metadata": { "description": "Boolean flag to turn on and off omsagent addon." } }, "workspaceRegion": { "type": "string", "defaultValue": "East US", "metadata": { "description": "Specify the region for your OMS workspace." } }, "workspaceName": { "type": "string", "metadata": { "description": "Specify the name of the OMS workspace." } }, "omsWorkspaceId": { "type": "string", "metadata": { "description": "Specify the resource id of the OMS workspace." } }, "omsSku": { "type": "string", "defaultValue": "standalone", "allowedValues": [ "free", "standalone", "pernode" ], "metadata": { "description": "Select the SKU for your workspace." } } }, "resources": [ { "apiVersion": "2020-09-01", "dependsOn": [ "[concat('Microsoft.Resources/deployments/', 'WorkspaceDeployment-20210114120627')]" ], "type": "Microsoft.ContainerService/managedClusters", "location": "[parameters('location')]", "name": "[parameters('resourceName')]", "properties": { "kubernetesVersion": "[parameters('kubernetesVersion')]", "enableRBAC": "[parameters('enableRBAC')]", "dnsPrefix": "[parameters('dnsPrefix')]", "agentPoolProfiles": [ { "name": "agentpool", "osDiskSizeGB": "[parameters('osDiskSizeGB')]", "count": 1, "vmSize": "Standard_DS2_v2", "osType": "Linux", "storageProfile": "ManagedDisks", "type": "VirtualMachineScaleSets", "mode": "System", "maxPods": 110, "availabilityZones": [ "1", "2", "3" ] } ], "networkProfile": { "loadBalancerSku": "standard", "networkPlugin": "[parameters('networkPlugin')]" }, "servicePrincipalProfile": { "ClientId": "[parameters('servicePrincipalClientId')]", "Secret": "[parameters('servicePrincipalClientSecret')]", "aadSessionKey": "[parameters('aadSessionKey')]" }, "apiServerAccessProfile": { "enablePrivateCluster": "[parameters('enablePrivateCluster')]" }, "addonProfiles": { "httpApplicationRouting": { "enabled": "[parameters('enableHttpApplicationRouting')]" }, "azurePolicy": { "enabled": "[parameters('enableAzurePolicy')]" }, "omsAgent": { "enabled": "[parameters('enableOmsAgent')]", "config": { "logAnalyticsWorkspaceResourceID": "[parameters('omsWorkspaceId')]" } } } }, "tags": { "env": "stg" } }, { "type": "Microsoft.Resources/deployments", "name": "SolutionDeployment-20210114120627", "apiVersion": "2017-05-10", "resourceGroup": "[split(parameters('omsWorkspaceId'),'/')[4]]", "subscriptionId": "[split(parameters('omsWorkspaceId'),'/')[2]]", "properties": { "mode": "Incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": {}, "variables": {}, "resources": [ { "apiVersion": "2015-11-01-preview", "type": "Microsoft.OperationsManagement/solutions", "location": "[parameters('workspaceRegion')]", "name": "[concat('ContainerInsights', '(', split(parameters('omsWorkspaceId'),'/')[8], ')')]", "properties": { "workspaceResourceId": "[parameters('omsWorkspaceId')]" }, "plan": { "name": "[concat('ContainerInsights', '(', split(parameters('omsWorkspaceId'),'/')[8], ')')]", "product": "[concat('OMSGallery/', 'ContainerInsights')]", "promotionCode": "", "publisher": "Microsoft" } } ] } }, "dependsOn": [ "[concat('Microsoft.Resources/deployments/', 'WorkspaceDeployment-20210114120627')]" ] }, { "type": "Microsoft.Resources/deployments", "name": "WorkspaceDeployment-20210114120627", "apiVersion": "2017-05-10", "resourceGroup": "[split(parameters('omsWorkspaceId'),'/')[4]]", "subscriptionId": "[split(parameters('omsWorkspaceId'),'/')[2]]", "properties": { "mode": "Incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": {}, "variables": {}, "resources": [ { "apiVersion": "2015-11-01-preview", "type": "Microsoft.OperationalInsights/workspaces", "location": "[parameters('workspaceRegion')]", "name": "[parameters('workspaceName')]", "properties": { "sku": { "name": "[parameters('omsSku')]" } } } ] } } }, { "type": "Microsoft.Resources/deployments", "name": "ClusterMonitoringMetricPulisherRoleAssignmentDepl-20210114120627", "apiVersion": "2017-05-10", "resourceGroup": "aks-rg", "subscriptionId": "f4b79fca...e8b", "properties": { "mode": "Incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.ContainerService/managedClusters/providers/roleAssignments", "apiVersion": "2018-01-01-preview", "name": "biometric/Microsoft.Authorization/9be768bc-1810-4a0b-9898-d3b077d36f70", "properties": { "roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '3913510d-42f4-4e42-8a64-420c390055eb')]", "principalId": "[parameters('principalId')]", "scope": "/subscriptions/f4b79fca-5d87-4814-b97e-ec5012170e8b/resourceGroups/aks-rg/providers/Microsoft.ContainerService/managedClusters/biometric" } } ] } }, "dependsOn": [ "/subscriptions/f4b79fca-5d87-4814-b97e-ec5012170e8b/resourceGroups/aks-rg/providers/Microsoft.ContainerService/managedClusters/biometric" ] } ], "outputs": { "controlPlaneFQDN": { "type": "string", "value": "[reference(concat('Microsoft.ContainerService/managedClusters/', parameters('resourceName'))).fqdn]" } } } |
parameters | { "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "resourceName": { "value": "biometric" }, "location": { "value": "eastus" }, "dnsPrefix": { "value": "biometric-dns" }, "kubernetesVersion": { "value": "1.18.10" }, "networkPlugin": { "value": "kubenet" }, "enableRBAC": { "value": true }, "servicePrincipalClientId": { "value": null }, "servicePrincipalClientSecret": { "value": null }, "enablePrivateCluster": { "value": false }, "aadSessionKey": { "value": null }, "enableHttpApplicationRouting": { "value": false }, "enableAzurePolicy": { "value": false }, "vmssNodePool": { "value": true }, "workspaceName": { "value": "DefaultWorkspace-f4b79fca-5d87-4814-b97e-ec5012170e8b-EUS" }, "omsWorkspaceId": { "value": "/subscriptions/f4b79fca-5d87-4814-b97e-ec5012170e8b/resourceGroups/DefaultResourceGroup-EUS/providers/Microsoft.OperationalInsights/workspaces/DefaultWorkspace-f4b79fca-5d87-4814-b97e-ec5012170e8b-EUS" }, "workspaceRegion": { "value": "eastus" }, "principalId": { "value": "baa06276-b73c-4aef-a538-bec11f437eb7" } } } |
Connect to AKS Cluster
// windows 2021 PS C:\Windows\system32> az aks get-credentials --resource-group aks-rg --name biometric Merged "biometric" as current context in C:\Users\michaelobrien\.kube\config PS C:\Windows\system32> kubectl get nodes NAME STATUS ROLES AGE VERSION aks-agentpool-21090939-vmss000000 Ready agent 74m v1.18.10 PS C:\Windows\system32> kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-748cdb7bf4-r6tkc 1/1 Running 0 74m kube-system coredns-748cdb7bf4-vgzjd 1/1 Running 0 75m kube-system coredns-autoscaler-868b684fd4-xjrpr 1/1 Running 0 75m kube-system kube-proxy-dhctc 1/1 Running 0 74m kube-system metrics-server-58fdc875d5-7p4kx 1/1 Running 0 75m kube-system omsagent-qvgbv 1/1 Running 0 74m kube-system omsagent-rs-564f494847-hh975 1/1 Running 0 75m kube-system tunnelfront-8569f8cb64-txphv 1/1 Running 0 75m PS C:\Windows\system32> kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% aks-agentpool-21090939-vmss000000 168m 8% 995Mi 21% // osx biometric:azure michaelobrien$ az aks install-cli Downloading client to "/usr/local/bin/kubectl" from "https://storage.googleapis.com/kubernetes-release/release/v1.17.3/bin/darwin/amd64/kubectl" # will not conflict with a local docker desktop kubernetes install biometric:azure michaelobrien$ az aks get-credentials --resource-group obl_dev_aks --name obl-dev Merged "obl-dev" as current context in /Users/michaelobrien/.kube/config # add clusterrolebinding to avoid RBAC errors on the dashboard biometric:azure michaelobrien$ kubectl create clusterrolebinding kubernetes-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created # check the cluster for the pod kube-system kube-proxy-h89tp 1/1 Running 0 172m # view the kubernetes dashboard biometric:azure michaelobrien$ az aks browse --resource-group obl_dev_aks --name obl-dev Merged "obl-dev" as current context in /var/folders/vv/d6dvwfmx0cgd19qs2yw51p1m0000gn/T/tmphexar_yl Proxy running on http://127.0.0.1:8001/ Press CTRL+C to close the tunnel...
AKS Costing Model
It looks like Microsoft Azure is not charging for the control plane - just the underlying VMs - I ran both an unmanaged RKE K8S cluster on a Standard_D2s_v3 and an AKS Standard_DS2_v2 for a day and the costs were about the same for both VMs at .81 and .53 for 8h.
Kubernetes on Azure VM - Direct Unmanaged via RKE
Provision one or more VMs via ARM
Create Resource Group
git clone git@github.com:obrienlabs/infrastructure.git cd azure biometric:azure michaelobrien$ az group create --name obl_dev_kubernetes_eastus --location eastus
Run ARM template
biometric:azure michaelobrien$ az group deployment create --resource-group obl_dev_kubernetes_eastus --template-file arm_deploy_obl_dev_kubernetes.json --parameters @arm_deploy_obl_dev_kubernetes_parameters.json
Wait for Rancher/Kubernetes install
The entrypoint.sh script will be run as a cloud-init script on the VM
# on your laptop biometric:opt michaelobrien$ scp ~/.ssh/onap_rsa ubuntu@1.82.174.1:~/ # on the host biometric:opt michaelobrien$ ssh ubuntu@1.82.174.1 chmod 400 onap_rsa sudo mkdir ~/.ssh cp onap_rsa ~/.ssh sudo chown ubuntu:ubuntu ~/.ssh/onap_rsa git clone --recurse-submodules https://github.com/obrienlabs/magellan.git cd magellan/kubernetes/ sudo ./rke_setup.sh -b master -s 1.82.174.1 -e obl -k onap_rsa -l ubuntu ubuntu@obl-dev-kubernetes:~$ kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE ingress-nginx default-http-backend-5954bd5d8c-28lhq 1/1 Running 0 13m ingress-nginx nginx-ingress-controller-t9h5g 1/1 Running 0 13m kube-system canal-6zgp7 2/2 Running 0 14m kube-system coredns-autoscaler-5d5d49b8ff-9lgkd 1/1 Running 0 13m kube-system coredns-bdffbc666-dvqff 1/1 Running 0 14m kube-system metrics-server-7f6bd4c888-gtgl6 1/1 Running 0 13m kube-system rke-coredns-addon-deploy-job-9jwsq 0/1 Completed 0 14m kube-system rke-ingress-controller-deploy-job-pzs6h 0/1 Completed 0 13m kube-system rke-metrics-addon-deploy-job-hng52 0/1 Completed 0 13m kube-system rke-network-plugin-deploy-job-nnh4j 0/1 Completed 0 14m kube-system tiller-deploy-7f4d76c4b6-j6rgm 1/1 Running 0 11m ubuntu@obl-dev-kubernetes:~$ helm version Client: &version.Version{SemVer:"v2.14.3", GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.14.3", GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"}
Training
https://www.microsoft.com/en-us/learning/azure-training.aspx
https://learning.oreilly.com/library/view/exam-ref-az-300/9780135881477/ch02.xhtml
Certification
https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE2PjDI
Azure SA Expert : https://docs.microsoft.com/en-us/learn/certifications/azure-solutions-architect?wt.mc_id=learningredirect_certs-web-wwl
Outages
link | Root cause | ||
---|---|---|---|
200303 | 6h | https://www.zdnet.com/article/microsofts-march-3-azure-east-us-outage-what-went-wrong-or-right/ | https://status.azure.com/en-us/status/history/ |
Troubleshooting
AKS CLI behind a VPN
to fix the timeout
PS F:\> az aks install-cli The command failed with an unexpected error. Here is the traceback: <urlopen error [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond> Traceback (most recent call last): File "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\lib\urllib\request.py", line 1318, in do_open encode_chunked=req.has_header('Transfer-encoding'))
1 Comment
Michael O'Brien
AKS accounts secured with Azure AD Managed Identity MI
AKS authentication via AAD as the IDM provider (app level) - OAuth 2.0
token: access + refresh
mobile clean OAuth 2.0 auth code flow
app: single tenant AAD v2A