Azure Kubernetes Service - Setting up a Container Registry - Part 2

Over in Part 1 we used Terraform to spin up a really basic Kubernetes cluster in azure. CLI for the win always!

For the record, I’m following some really good documentation from Microsoft’s Azure documentation site (all references credited at the end). These are just my notes, screenshots and outputs for my own reference.

A lot of the how this I write these is how I would want to it to read if I were trying to learn this again myself :)

In this part, we just want to setup an Azure Container Registry (ACR) that’s going to be our private, or internal, holder of all things docker/container images and what-not.

Once we get this up and ready for service, this is where we will throw our applications to deploy from!

Series Overview

  • Part 1 - get Kubernetes cluster up and running on Azure Kubernetes Managed Service (AKS)
  • Part 2 - create a private Docker Registry in the cloud using Azure’s Container Registry Managed service (ACR)
  • Part 3 - deploy a simple application to it.

Now that we know where we are, let’s go!

Pre-requisites

As in Part 1, you’ll need the following already installed to get going:

  1. Azure portal account
  2. Azure az-cli (command line interface)
  3. Terraform installed (zipped binary, copy to ~/bin)
  4. (optional) Kubectl installed

Right, let’s have a look at the two methods we can use to stand things up:

Method 1: az-cli

with this method, we’ll be going through a series of azure-cli ‘az’ calls to set things up

login with azure-cli

from a terminal, login to your azure account

$ az login

a browser window opens, you select the email that gets you into your azure portal account.

create a resource group

$ az group create --name cloudbuilder-rg --location australiaeast

output looks like this

{
  "id": "/subscriptions/0d667072-XXXX-46ef-a5b4-86979fd2XXXX/resourceGroups/cloudbuilder-rg",
  "location": "australiaeast",
  "managedBy": null,
  "name": "cloudbuilder-rg",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": null
}

create a container registry

run this command

[email protected]:~ $ az acr create --resource-group "cloudbuilder-rg" --name cloudBRegistry --sku Basic

take note the registry name you choose after “–name” has to be a unique name when combined with suffix “.azurecr.io” otherwise you’ll get denied like so

[email protected]:~ $ az acr create --resource-group "cloudbuilder-rg" --name cloudRegistry --sku Basic
The registry DNS name cloudregistry.azurecr.io is already in use.

successful output looks like this

{
  "adminUserEnabled": false,
  "creationDate": "2019-02-04T08:19:59.124377+00:00",
  "id": "/subscriptions/0d667072-XXXX-46ef-a5b4-86979fd2XXXX/resourceGroups/cloudbuilder-rg/providers/Microsoft.ContainerRegistry/registries/cloudBRegistry",
  "location": "australiaeast",
  "loginServer": "cloudbregistry.azurecr.io",
  "name": "cloudBRegistry",
  "networkRuleSet": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "cloudbuilder-rg",
  "sku": {
    "name": "Basic",
    "tier": "Basic"
  },
  "status": null,
  "storageAccount": null,
  "tags": {},
  "type": "Microsoft.ContainerRegistry/registries"
}

right, so far so good.

key output here to take note of = "loginServer": "cloudbregistry.azurecr.io"

OR short-cut:

$ az acr list --resource-group $NAME_OF_ACR --query "[].{acrLoginServer:loginServer}" --output table

login to new ACR

I had issues with this on a corporate setup with multiple Azure accounts so it kept giving me weird errors and not letting me login. On my personal, simple, single account setup, the login is really straight forward

[email protected]:~ $ az acr login --name cloudBRegistry
Login Succeeded

that’s it.

Congratulations, you’ve got a brand spanking new ACR setup!

but its a bit useless sitting there doing nothing, let’s try and push some images to it!

Push an image?

hmmm, let’s just test it with a local docker image we can re-tag and push to see how it goes.

[email protected]:~ $ docker images
REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
tiangolo/uwsgi-nginx-flask                       python3.6           0f8df7d438f3        3 weeks ago         949MB
localhost:5000/golang                            1.10                b65fe5418f5f        5 weeks ago         729MB
golang                                           1.10                b65fe5418f5f        5 weeks ago         729MB
nginx                                            1.14                3f55d5bb33f3        5 weeks ago         109MB
mysql                                            5.7                 ba7a93aae2a8        5 weeks ago         372MB
redis                                            latest              5d2989ac9711        5 weeks ago         95MB
wordpress                                        php7.1-fpm-alpine   87b83134b87c        6 weeks ago         113MB
registry                                         2                   9c1f09fe9a86        6 weeks ago         33.3MB
alpine                                           3.8                 3f53bb00af94        6 weeks ago         4.41MB

‘registry’ looks small enough

[email protected]:~ $ docker tag registry:2 cloudbregistry.azurecr.io/registry:2

re-tagged with our new ACR as the destination, now for a Push

[email protected]:~ $ docker push cloudbregistry.azurecr.io/registry:2
The push refers to a repository [cloudbregistry.azurecr.io/registry]
2c2e689683cd: Pushed
0d2f98178000: Pushed
2a02e265caaa: Pushed
aa889911e071: Pushed
4a9dd85dec45: Pushed
2: digest: sha256:4dc58b720da3630db2be1cc811837c1671c55e419bf14f775752cee4178832d6 size: 1364

easy as that!

Useful ACR commands

quick look at all the images in our ACR

[email protected]:~ $ az acr repository list --name cloudbregistry --output table
Result
--------
registry

hmmm, not many!

any cool tags?

[email protected]:~ $ az acr repository show-tags --name cloudbregistry --repository registry --output table
Result
--------
2

ah, just the ‘registry:2’ tag!

ah well, we’re done with the ACR, so quick way to DELETE IT ALL, is to delete the resource group - you remember the one “cloudbuilder-rg”

[email protected]:~ $ az group delete --name "cloudbuilder-rg"
Are you sure you want to perform this operation? (y/n): y

That’s it. pretty anti-climatic huh.

Method 2: Terraform!

Ok, this one I saw in passing after I’d already got things jiggy with az-cli

refresh existing tf build

Go back to the folder you were working out of for Part 1, and run this

[email protected]:~/repositories/code/terraform (master)$ terraform refresh
azurerm_resource_group.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...e4bd/resourceGroups/dev_resource_group)
azurerm_kubernetes_cluster.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...ontainerService/managedClusters/devbox)
local_file.kubeconfig: Refreshing state... (ID: 682263c9d17e39c1e7a6c0f2137df741a008783e)

Outputs:

host = https://devbox-d4752f36.hcp.australiaeast.azmk8s.io:443

now a few edits

resource.tf now looks like this

resource "azurerm_resource_group" "k8s" {
  name     = "${var.resource_group_name}"
  location = "${var.location}"
}

# Managed ACR Option

resource "azurerm_container_registry" "acr" {
  name                     = "containerRegistry1"
  resource_group_name      = "${azurerm_resource_group.k8s.name}"
  location                 = "${azurerm_resource_group.k8s.location}"
  sku                      = "Basic"
  admin_enabled            = false
}

resource "local_file" "kubeconfig" {
  content = "${azurerm_kubernetes_cluster.k8s.kube_config_raw}"
  filename = "./kubeconfig"
}

run a plan!

run terraform plan to check what we’re doing

[email protected]:~/repositories/code/terraform (master)$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

azurerm_resource_group.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...e4bd/resourceGroups/dev_resource_group)
azurerm_kubernetes_cluster.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...ontainerService/managedClusters/devbox)
local_file.kubeconfig: Refreshing state... (ID: 682263c9d17e39c1e7a6c0f2137df741a008783e)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + azurerm_container_registry.acr
      id:                  <computed>
      admin_enabled:       "false"
      admin_password:      <computed>
      admin_username:      <computed>
      location:            "australiaeast"
      login_server:        <computed>
      name:                "containerRegistry1"
      resource_group_name: "dev_resource_group"
      sku:                 "Basic"
      tags.%:              <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Terraform Apply!

after trying to run an ‘apply’, guess what we see!

Error: Error applying plan:

1 error(s) occurred:

* azurerm_container_registry.acr: 1 error(s) occurred:

* azurerm_container_registry.acr: containerregistry.RegistriesClient#Create: Failure sending request: StatusCode=409 -- Original Error: failed request: autorest/azure: Service returned an error. Status=<nil> Code="AlreadyInUse" Message="The registry DNS name containerregistry1.azurecr.io is already in use."

have to make sure these ACR names are unique! edit resource.tf and try again.

[email protected]:~/repositories/code/terraform (master)$ terraform apply
azurerm_resource_group.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...e4bd/resourceGroups/dev_resource_group)
azurerm_kubernetes_cluster.k8s: Refreshing state... (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...ontainerService/managedClusters/devbox)
local_file.kubeconfig: Refreshing state... (ID: 682263c9d17e39c1e7a6c0f2137df741a008783e)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + azurerm_container_registry.acr
      id:                  <computed>
      admin_enabled:       "false"
      admin_password:      <computed>
      admin_username:      <computed>
      location:            "australiaeast"
      login_server:        <computed>
      name:                "cloudBRegistry"
      resource_group_name: "dev_resource_group"
      sku:                 "Basic"
      tags.%:              <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_container_registry.acr: Creating...
  admin_enabled:       "" => "false"
  admin_password:      "" => "<computed>"
  admin_username:      "" => "<computed>"
  location:            "" => "australiaeast"
  login_server:        "" => "<computed>"
  name:                "" => "cloudBRegistry"
  resource_group_name: "" => "dev_resource_group"
  sku:                 "" => "Basic"
  tags.%:              "" => "<computed>"
azurerm_container_registry.acr: Creation complete after 3s (ID: /subscriptions/0d667072-8cd2-46ef-a5b4-...inerRegistry/registries/cloudBRegistry)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

host = https://devbox-d4752f36.hcp.australiaeast.azmk8s.io:443

That’s better.

Right, we should be able to tear through all the ACR stuff we did with the az-cli method

Quick: ACR run-through checks for Terraform method

login

[email protected]:~/repositories/code/terraform (master)$ az acr login --name "cloudBRegistry"
Login Succeeded

check

docker push

assuming already re-tagged something locally and ready to push

[email protected]:~/repositories/code/terraform (master)$ docker push cloudbregistry.azurecr.io/registry:2
The push refers to a repository [cloudbregistry.azurecr.io/registry]
2c2e689683cd: Pushed
0d2f98178000: Pushed
2a02e265caaa: Pushed
aa889911e071: Pushed
4a9dd85dec45: Pushed
2: digest: sha256:4dc58b720da3630db2be1cc811837c1671c55e419bf14f775752cee4178832d6 size: 1364

yep, looks good!

(can probably destroy it now, but I’ll clean up later)

So there you go. Azure Container Registry, at your beck and call, via 2 methods.

Thanks for reading!

In Part 3 - we tie it all together with an application deploy into our Kubernetes cluster, pulling from our private ACR!!

References

Leave a Comment