Cloud Experts Documentation

Azure DevOps with Managed OpenShift

This content is authored by Red Hat experts, but has not yet been tested on every supported configuration.

Author: Kevin Collins

Last edited: 03/14/2023

Adopted from Hosting an Azure Pipelines Build Agent in OpenShift and Kevin Chung Azure Pipelines OpenShift exampleexternal link (opens in new tab)

Azure DevOps is a very popular DevOps tool that has a host of features including the ability for developers to create CI/CD pipelines.

In this document, I will show you how to connect your Managed OpenShift Cluster to Azure DevOps end-to-end including running the pipeline build process in the cluster, setting up the OpenShift internal image registry to store the images, and then finally deploy a sample application. To demonstrate the flexibility of Azure DevOps, I will be deploying to a ROSA cluster, however the same procudures will apply to if you choose to deploy to any other OCP Cluster.

Prerequisites

  • A Public Cloud subscription (Azure Subscription)
  • Azure Dev Ops instance
  • An OpenShift Cluster (to create an Azure Red Hat OpenShift (ROSA) cluster, click here )

Clone example application and configuration files

git clone https://github.com/rh-mobb/azure-pipelines-openshift  cd azure-pipelines-openshift 

Configure Azure Devops

While logged into your Azure DevOps Organizationexternal link (opens in new tab) , create a new project. The examples in this document will assume the project is named azure-pipelines-openshift ADO New Project

Obtain a personal access token. While in Azure DevOPs, select Personal Access Token under User Settings. azpat

On the next screen, create a New Token. In this example, we will create a token with Full Access. Once you click create your token will be displayed. Make sure to store it somewhere safe as you won’t be able to see it again.
create-pat

Set Azure DevOps environment variables for your Azure DevOps instance

AZP_URL=https://dev.azure.com/<yourOrg> AZP_TOKEN=<Token you retrieved above> AZP_POOL=Default 

Host an Azure Pipelines Build Agent in OpenShift

note: this is an abreviated version of this blog by Kevin Chung and Mark Dunnett.

In this step, we will configure OpenShift to build our container image leveraging Universal Base Images ( UBI )

Configure the Azure DevOps build agent with OpenShift

Start by creating a new project

oc new-project azure-build 

Create the following artifacts that include a wrapper script for the build agent and an example BuildConfig that will build a .NET application using the Red Hat Universal Based Image for .NET

 oc create configmap start-sh --from-file=start.sh=assets/start.sh  oc create imagestream azure-build-agent  oc create -f assets/buildconfig.yaml 

Update the azure build agent image

oc set env bc/azure-build-agent AZP_AGENT_PACKAGE_LATEST_URL=https://vstsagentpackage.azureedge.net/agent/2.218.1/vsts-agent-linux-x64-2.218.1.tar.gz oc start-build azure-build-agent 

As a cluster admin, create a service account for the build agent

 oc create serviceaccount azure-build-sa  oc create -f assets/nonroot-builder.yaml  oc adm policy add-scc-to-user nonroot-builder -z azure-build-sa 

Make sure to be in the root directory of the Azure Pipelines OpenShift git repository you cloned in the previous step.

Create a secret with your Azure DevOps credentials

oc create secret generic azdevops \  --from-literal=AZP_URL=${AZP_URL} \  --from-literal=AZP_TOKEN=${AZP_TOKEN} \  --from-literal=AZP_POOL=${AZP_POOL} 

Deploy the azure build agent

 oc create -f assets/deployment.yaml 

Make sure the build agent is running:

oc get pods 

expected output:

NAME READY STATUS RESTARTS AGE azure-build-agent-1-build 0/1 Completed 0 18m azure-build-agent-2-build 0/1 Completed 0 15m azure-build-agent-5d7c455ffd-d2pcc 1/1 Running 0 46s 

Create an Azure DevOps Pipeline

The pipeline we will create has three steps.

  1. build the image on the OpenShift cluster
  2. push the image to the internal registry of the OpenShift cluster
  3. deploy the application to the cluster

Before we can do steps 2 and 3, we need to create a service account in OpenShift to both authenticate with OpenShift to push an image and also the internal image registry.

Create a new project for our application

 oc new-project ado-openshift 

Create a service account and grant it cluster-admin privileges

oc create sa azure-sa oc adm policy add-cluster-role-to-user cluster-admin -z azure-sa 

Create a secret token for the service account

cat <<EOF | oc apply -f - apiVersion: v1 kind: Secret metadata:  name: azure-sa-secret  annotations:  kubernetes.io/service-account.name: "azure-sa" type: kubernetes.io/service-account-token EOF 

Retrieve the secret name that we just created that was a token associated with it.

 oc get secrets | grep azure-sa-token | awk '{ print $1 }' 

expected output:

azure-sa-token-2qrgw 

note: your output will have a different name

Describe the secret to retrieve the token:

oc describe secret <secret name> 

expected output:

Name: azure-sa-token-2qrgw Namespace: ado-openshift Labels: <none> Annotations: kubernetes.io/created-by: openshift.io/create-dockercfg-secrets  kubernetes.io/service-account.name: azure-sa  kubernetes.io/service-account.uid: d361f12e-db7d-412b-9ab8-8ac3a0ba459b  Type: kubernetes.io/service-account-token  Data ==== token: eyJhbGciOiJSUzI1NiIsImtpZCI6IlFBcmE2b1N5NnA2OUJZcEh2WUVad1BCSGozck9fa2tpaG83bnctM0hUd00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJhZG8tb3BlbnNoaWZ0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImF6dXJlLXNhLXRva2VuLTJxcmd3Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImF6dXJlLXNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZDM2MWYxMmUtZGI3ZC00MTJiLTlhYjgtOGFjM2EwYmE0NTliIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmFkby1vcGVuc2hpZnQ6YXp1cmUtc2EifQ.GhLVRAJcG_CHuUxPaz3H_d_E_tGkFK6VaaFv_4UGZiwLLE1Hx-nSIYOA7YsOUvKOkdY2B6fIJrcLUBe5SUjiK0ZePSJZQNry_oZ9xKqhgSRFntxHT5mUR_BXT4cnF5zv0zrT3dvqWcM11mTSs2xfmCx8eACt-uEz2CtLHmxqkvpsiZA2wFQfxekInFFwFhbZSeQk6YBRGFu5f-eawP7qzzDibmo_GmMLHH4uLnpR1CJQFYzI09fEdzSf7IK2UzBgn6dmqpSzHnxLMjgHJVkX66FztJochlGUV8bE4acZk54lu_Xo7OhKxjhiqdeMHFBzq2PeSyvdvSspFME9y6_gXcy1-4QjxLM3t_K9yj7LsJSZKWn8HcmTJy_HoTvpbPtDznz_KEYJH1yX4zdK36D0ocUAb3gBNgfXlsEPAVXYV2o75ZL-AEwpumBv49rRNs_-wZKRO_3eR5zgZWGjZpVoDRb1F_QoFkxy-pnF2sSMQXZOEjwFTapESP182mWZtzzdU8TMOcdK44cr9mYB5IYBmJ2JTRQR2K_iTLfgK-im8O2K5n6OAwWBl4w8mpZDx0eHDp4IBfCBJk2AlopGrQ4TOf-l2bkcEnbJco7ei4D39tRR6xQcPddPEPEDbwIudI9IEzNhyJmHztUnjMV5NaC17hJ05AXWS83nPxFhH_a7pN8 ca.crt: 8717 bytes namespace: 13 bytes service-ca.crt: 9930 bytes 

Copy the value of the token.

Retrieve the host of your cluster image regstry.

 oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}' 

Expected Output:

default-route-openshift-image-registry.apps.ado-rosa.9s68.p1.openshiftapps.com 

Get the cluster api endpoint

oc cluster-info 

expected output:

 Kubernetes control plane is running at https://api.ado-rosa.9s68.p1.openshiftapps.com:6443 

note the api server url for usage later

Configure Azure DevOps service connections for the registry and OpenShift

From Azure DevOps, click on Project settings ( the gear icon ), then Service Connections, and finally Create service connection.

create-service-connection

Select Docker registry

docker-registry

Enter the settings we retrieved in the previous step:

  • Select Others for Docker Registry
  • Docker Registry - make sure to add https:// in front of the hostname you retrieved
  • Docker ID - the service account you created
  • Docker Password - the service account token
  • Service connection name - enter openshift-registry

Next, let’s create a another serivce connection for our cluster.

Click New service connection:

new-service-connection

Select Kubernetes

select-kubernetes
  • Server Url - the api server you retrieved in the previous step

  • Secret - using the name of the secret that we retieved earlier that has token in the name run:

    oc get secret azure-sa-token-2qrgw -o json 

    Copy the entire json results and paste it in the Secret field

  • Service connection name - select openshift

openshift-settings

Create an Azure DevOps Pipeline

We will be deploying an application from a GitHub repo. Fork the following Git Repo: https://github.com/rh-mobb/azure-pipelines-openshiftexternal link (opens in new tab)

In Azure DevOPs, click on Pipelines and then Create Pipeline

new-pipeline

On the next screen, select GitHub

pipeline-github

On the next screen, select your github repo that you forked to.

Review the azure-pipelines.yml file and then click run.

If this is the first time running, you might see a message like the following:

build-permissions

Clickad on the Build and Push Image tile, and then view permissions, and grat permissions to both the Default queue and the openshift-registry service connection.

grant-build-permissions

Like we saw with permissions on the build and push, we also need to give permissions to deploy.

permission-deploy

On the next screen, click on Permit to give access to the OpenShift connection.

grand-openshift-permission

After a few minutes, you should see both the Build and Push Image and Deploy to DEV stages complete.

successful-pipeline

To verify the application was successfully deployed in openshift run:

oc get pods -n ado-openshift 

expected output:

NAME READY STATUS RESTARTS AGE ado-dotnet-74b64db7d5-p8vr7 1/1 Running 0 98s 

Interested in contributing to these docs?

Collaboration drives progress. Help improve our documentation The Red Hat Way.

Red Hat logo LinkedIn YouTube Facebook Twitter

Products

Tools

Try, buy & sell

Communicate

About Red Hat

We’re the world’s leading provider of enterprise open source solutions—including Linux, cloud, container, and Kubernetes. We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Subscribe to our newsletter, Red Hat Shares

Sign up now
© 2023 Red Hat, Inc.