This article is contributed. See the original author and article here.

Overview


 


This article details building and deploying a container to an Azure Kubernetes Service(AKS) cluster in Azure Government cloud using Azure DevOps.


 


Private AKS Clusters has the API Server accessible only within the virtual network. This limits the deployments from Hosted Azure DevOps agents. To overcome this, a self-hosted agent within the same virtual network needs to be deployed.


 


Access to Azure Container Registry (ACR) can be restricted to the virtual network using Private Endpoints. This will limit ACR exposure to public internet. Since private ACR is available only within the vnet, self-hosted devops agents comes to the rescue.


 


Lastly, to ensure that Azure Pipelines can deploy to Azure Government Clouds, Azure Resource Manager Service Connection should be created with an Environment parameter.


 


Setup


 


The following steps replicates the above setup. The setup has 3 subnets with the following components



  • Azure Container Registry Private Endpoint

  • Azure DevOps self hosted agent

  • Azure Kubernetes Service


acr-aks-devops-gov.png


Network setup


 


Create a Virtual Network and add 3 subnets.


 


Use the below values for reference:


Address Space: 10.0.0.0/16


 
























Subnet name  


Address Space

acr-snt 10.0.1.0/24
devops-snt 10.0.2.0/24
aks-snt 10.0.4.0/22

 


 


 

az group create --name gov-devops --location usgovtexas

az network vnet create 
  --name gov-devops-vnet 
  --resource-group gov-devops 
  --subnet-name default
  
az network vnet subnet create 
  --address-prefixes 10.0.1.0/24
  --name acr-snt 
  --resource-group gov-devops 
  --vnet-name gov-devops-vnet
  
az network vnet subnet create 
  --address-prefixes 10.0.2.0/24
  --name devops-snt 
  --resource-group gov-devops 
  --vnet-name gov-devops-vnet
  
az network vnet subnet create 
  --address-prefixes 10.0.4.0/22
  --name aks-snt 
  --resource-group gov-devops 
  --vnet-name gov-devops-vnet

 


 


 


Create ACR


 


Create a Container Registry in the premium tier (required for private link)


 


 


 

az acr create --resource-group gov-devops 
  --name mygovacr --sku Premium

 


 


 


Create the registry’s private endpoint in the acr-snt subnet


 


 


 

az network vnet subnet update 
 --name acr-snt 
 --vnet-name gov-devops-vnet 
 --resource-group gov-devops 
 --disable-private-endpoint-network-policies
 
az network private-dns zone create 
  --resource-group gov-devops 
  --name "privatelink.azurecr.io"
  
az network private-dns link vnet create 
  --resource-group gov-devops 
  --zone-name "privatelink.azurecr.io" 
  --name govdns 
  --virtual-network gov-devops-vnet 
  --registration-enabled false
  
REGISTRY_ID=$(az acr show --name mygovacr 
  --query 'id' --output tsv)

az network private-endpoint create 
    --name myPrivateEndpoint 
    --resource-group gov-devops 
    --vnet-name gov-devops-vnet 
    --subnet acr-snt 
    --private-connection-resource-id $REGISTRY_ID 
    --group-id registry 
    --connection-name myConnection

NETWORK_INTERFACE_ID=$(az network private-endpoint show 
  --name myPrivateEndpoint 
  --resource-group gov-devops 
  --query 'networkInterfaces[0].id' 
  --output tsv)
  
PRIVATE_IP=$(az resource show 
  --ids $NETWORK_INTERFACE_ID 
  --api-version 2019-04-01 
  --query 'properties.ipConfigurations[1].properties.privateIPAddress' 
  --output tsv)

DATA_ENDPOINT_PRIVATE_IP=$(az resource show 
  --ids $NETWORK_INTERFACE_ID 
  --api-version 2019-04-01 
  --query 'properties.ipConfigurations[0].properties.privateIPAddress' 
  --output tsv)
  
az network private-dns record-set a create 
  --name mygovacr 
  --zone-name privatelink.azurecr.io 
  --resource-group gov-devops

# Specify registry region in data endpoint name
az network private-dns record-set a create 
  --name mygovacr.usgovtexas.data 
  --zone-name privatelink.azurecr.io 
  --resource-group gov-devops
  
az network private-dns record-set a add-record 
  --record-set-name mygovacr 
  --zone-name privatelink.azurecr.io 
  --resource-group gov-devops 
  --ipv4-address $PRIVATE_IP

# Specify registry region in data endpoint name
az network private-dns record-set a add-record 
  --record-set-name mygovacr.usgovtexas.data 
  --zone-name privatelink.azurecr.io 
  --resource-group gov-devops 
  --ipv4-address $DATA_ENDPOINT_PRIVATE_IP
  
az acr update --name mygovacr --public-network-enabled false

 


 


 


Choose one of the below authentication methods to perform docker login from the DevOps pipelines



 


 


 

az acr update -n mygovacr --admin-enabled true

 


 


 


Note the admin username and password from the ACR Access Keys blade in the portal


 


Create AKS


 


Create a private AKS cluster in the aks-snt subnet


 


Integrate ACR with AKS or create a pull secret


 


 


 

kubectl create secret docker-registry regcred 
  --docker-server=<your-registry-server> 
  --docker-username=<your-name> 
  --docker-password=<your-pword> 
  --docker-email=<your-email>

 


 


 


Create a VM and deploy DevOps agent


 


Create a Linux VM in devops-snt subnet to host the DevOps agent.


 


 


 

az vm create 
  --resource-group gov-devops 
  --name devopsagent 
  --image UbuntuLTS 
  --admin-username azureuser 
  --generate-ssh-keys 
  --subnet devops-snt 
  --vnet-name gov-devops-vnet

 


 


 


Note the publicIpAddress from the output


 


Deploy the DevOps agent on the VM



  • Generate a PAT token

  • Create an Agent Pool

    • Click Add Pool

    • Select New

    • Select pool Type as Self-hosted

    • Enter a name as govpool

    • Select New Agent -> Linux



  • Copy the Agent Download link

  • Deploy the agent on the VM


 


 


 

ssh azureuser@publicIpAddress

curl -O <<url copied above>
mkdir myagent && cd myagent
tar zxvf ../{tar file name}

./config.sh
sudo ./svc.sh install
sudo ./svc.sh start

 


 


 


Install docker, az cli and kubectl


 


 


 

sudo apt -y update
sudo apt -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER
newgrp docker

curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
sudo az aks install-cli

 


 


 


Create the pipeline


 


Create Service Connections

 


From Azure DevOps, create a Docker Registry Service Connection



  • Navigate to Project Settings

  • Click New Service Connection

  • Select Docker Registry

  • Select Registry Type as Others

  • Provide the below details:

    • Docker Registry: { ACR url eg: https://mygovacr.azurecr.us }

    • Docker ID: { admin username or Service principal App ID }

    • Docker Password: { admin password or service principal secret }

    • Service Connection name: { Connection name }




To run kubectl task against the AKS cluster, Create Service Principal and grant contributor access to the resource group


From Azure DevOps, create an Azure Resource Manager Service Connection



  • Navigate to Project Settings

  • Click New Service Connection

  • Select Azure Resource Manager

  • Select Service Principal (manual)

  • Provide the below details:

    • Environment: Azure US Government

    • Subscription Id: { Gov Subscription ID }

    • Subscription Name: { Gov Subscription Name }

    • Service Principal Id: { Create Service Principal using Portal or PowerShell }

    • Credential: Service Principal key: { Secret of the Service Principal }

    • Tenant Id: { Gov Tenant ID }

    • Service Connection name: { Connection name }




 

Create pipeline

 



  • Fork the sample repo

  • Copy the contents below to a deploy.yaml file in the repo (Remove imagePullSecrets if ACR integrated with AKS)


 


 


 

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: mygovacr.azurecr.us/nginx-echo-headers:latest
  imagePullSecrets:
  - name: regcred

 


 


 



  • Navigate to the project in Azure DevOps

  • Go to Pipelines, and then select New Pipeline

  • Select GitHub as the location of your source code and select your repository

  • Select Starter pipeline

  • Replace the contents of the yaml in the Review tab


 


 


 

trigger:
- master

pool:
  name: 'govpool'

steps:
- task: Docker@2
  inputs:
    containerRegistry: '{Docker Registry Service Connection Name}'
    repository: 'nginx-echo-headers'
    command: 'buildAndPush'
    Dockerfile: 'Dockerfile'
    tags: 'latest'
- task: Kubernetes@1
  inputs:
    connectionType: 'Azure Resource Manager'
    azureSubscriptionEndpoint: '{Azure Resource Manager Service Connection Name}'
    azureResourceGroup: 'gov-devops'
    kubernetesCluster: '{aks cluster name}'
    command: 'apply'
    arguments: '-f deploy.yaml'

 


 


 


Summary


The setup facilitates secure deployments to private ACR/AKS on Azure Government Cloud using Pipelines.

Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.