Seamlessly Deploy .NET Applications on Oracle Kubernetes with a CI/CD Pipeline: A Step-by-Step Guide

This article explains how to dockerize .Net applications on Oracle cloud infrastructure and deploy on Kubernetes cluster. This includes a complete CI/CD pipeline creation and configuration as well. 

The intention is to show the process and therefore the application chosen is a simple example

    1. Pre-requisites

    This blog expects you already have the following requirements prior to starting the implementation.

    • Container Engine for Kubernetes (OKE) cluster on Oracle Cloud Infrastructure. If you are not familiar with OKE please refer to my previous post here.
    • Dynamic groups, policies are created for the OKE and DevOps project.  Reference: OKE policies , DevOps policies
    • VS code or any other code source code editor

    2. Architecture

    Figure 2.1 shows the architecture that we are going to build. Here, a developer can push code to the OCI code repository which then uses continuous integration to build the docker image and then trigger continuous deployment to deploy on the OKE cluster. A sample application and configuration files will be discussed during the process.

    Figure 2.1: Architecture

    3. Step-by-Step Implementation

    This section will explain the implementation in detail. This includes the application and configuration files in addition to the relevant screenshots.

    3.1 Download and install Dotnet on your laptop

    In order to work on .Net applications you will need the necessary software on your laptop. If you are already a .Net developer, you can skip this step.
    The software can be downloaded from here. Once it’s completed you can verify the dotnet version as below.

    Figure 3.1.1: Check dotnet version

    3.2 Create sample .Net application

    The following steps are parts of official Microsoft documentation but amended certain files and parameters for convenience.

      The following command will create a new project with a subdirectory named ‘App’.

    dotnet new console -o App -n DotNet.Docker

    Figure 3.2.1: Create sample App

    Once the application is created you will see a directory structure as in figure 3.2.2. We’ll change related files to achieve our goal.

    Figure 3.2.2: App directory structure

    We can run the existing application with ‘dotnet run’ and can see the output in the local machine.

    Figure 3.2.3: Run application

    However, when we need to deploy the application on Kubernetes,  we will need to do slight changes on that.

    3.3 Preparing Configuration Files

    In this section we are going to prepare all the required configuration and application files prior to building the CI/CD pipeline.

    Firstly, We will make slight changes to the ‘Program.cs’ file as in figure 3.3.1. The ‘Program.cs’ file is located at the ‘App’ directory.

    Figure 3.3.1: Program.cs file

    Now, change the ‘DotNet.Docker.csproj’ file also as shown in the figure 3.3.2.

    Figure 3.3.2: DotNet.Docker.csproj file

    Both of the above files are part of the sample application. Next, we are creating the configuration files.

    Microsoft documentation provides a sample ‘Dockerfile’ and we are going to use the same in our scenario with minor changes. A working Dockerfile is shown in figure 3.3.3. 

    Figure 3.3.3: Dockerfile

    The ‘build_spec.yaml’ is a mandatory file for the continuous integration pipeline and a sample is shown in figure 3.3.4.  Here, ‘DOCKER_TAG’ and ‘REGISTRY’ parameters reflect the region of the deployment (in this case Ashburn – iad) and image registry name (in this case dotnetreg).

    Figure 3.3.4: Build_spec.yaml file

    Next we need to create files for the continuous deployment pipeline in order to deploy applications on Kubernetes cluster and create service.  

    The figure 3.3.5 is a sample of ‘deployment.yaml’ file which will manage the application deployment to the Kubernetes.

    Figure 3.3.5:Deployment.yaml file

    The ‘service.yaml’ file will create a service for the application deployed so that we can expose the service to the public.

    Figure 3.3.6: Service.yaml file

    Once the files are ready copy the files to the root directory as shown in figure 3.3.7.

    Figure 3.3.7: File structure

    3.4 Create DevOps Environment

    This section will explain how to build the CI/CD pipeline step-by-step for the application deployment.

     If you noticed in the ‘deployment.yaml’, there’s mention of image pull secrets. This is required to pull images from the Oracle container registry (OCIR) and deploy on the Kubernetes cluster. The details are mentioned in the Oracle documentation here.

    Login to cloud shell or environment configured to access the Kubernetes cluster and create the secret as below;

    Syntax: 

    $ kubectl create secret docker-registry ocirsecret

    –docker-server=<region-key>.ocir.io –docker-username='<tenancy-namespace>/<oci-username>’ –docker-password='<oci-auth-token>’ –docker-email='<email-address>’

    Example:

    kubectl create secret docker-registry ocirsecret

    –docker-server=iad.ocir.io –docker-username=’s/oracleidentitycloudservice/pradeepa.gunasekera@email.com’ 

    –docker-password=’2(IatTM-<g’ –docker-email=’pradeepa@email.com’

    We need to create a container registry (OCIR) to upload our dockerized images. It’s located under ‘Developer Services’. In this example I choose the name ‘dotnetreg’ for the registry and use that in configuration files.

    Figure 3.4.1: Container Registry

    We can upload other configuration files like YAML files to the artifact registry to be used for our project later. This again can be found under developer services.

    Figure 3.4.2: Artifact Registry

    Once the artifact registry is created, we can upload our YAML files namely, deployment.yaml and service.yaml to the registry.

    Figure 3.4.3: Create artifact registry

    Now, we can create our DevOps project which is again under developer services. The DevOps project has all the components to manage the CI/CD pipeline. This will be explored in next steps.

    Figure 3.4.4: Create Devops project

    Once the DevOps project is created, we need to create a code repository to store our code. This is one of the components inside the DevOps project and we can commit and sync our code there.

    Figure 3.4.5: Create Code Repository

    When we create the code repository, we can see two options to configure the sync. Choose either ‘SSH’ or ‘HTTPS’ and configure your code base (to your laptop) to sync. 

    Figure 3.4.6: Choose configuration methodology

    We can then push our code to the code repository created under DevOps project. As you can see in figure 3.4.7, git commands are used to add, commit and finally push the code.

    Figure 3.4.7: Push code to cloud repository

    You can verify whether the files are pushed correctly by refreshing the code repository in the DevOps project. There you can see the files, commits, branches and much more information graphically.

    Now go to the ‘Artifacts’ section of the DevOps project and map the previously created artifacts to the project. The container image registry (dotnetreg) needs to configure as ‘Docker image’ type and two YAML files need to be added as ‘Kubernetes manifest’ type.

    Figure 3.4.8: Map artifacts 

    Next, go to the ‘Environments’ section of the DevOps project and map the existing Kubernetes cluster.

    Figure 3.4.9: Map OKE environment

    All the ingredients for the build are ready and now time to create the pipelines. We are starting with the ‘Build Pipelines’ component available in the DevOps project.

    Figure 3.4.10: Create build pipeline

    When you create the pipeline after providing a name, a graphical user interface will appear. There, you can start adding the build pipeline stages. The first stage needs to be ‘Managed Build’ to do the dockerization

    Figure 3.4.11: Adding managed build stage

    The next screenshot will show the important sections of the managed build stage and other sections can go ahead with the default settings.

    Provide a meaningful name and optionally a description.

    Figure 3.4.12: Managed build stage name

    As in figure 3.4.13 we need to add our code repository in the DevOps project and ‘build_spec.yaml’ file name. In our case, the ‘build_spec.yaml’ file name can be ignored as we use the default file name.

    Figure 3.4.13:  Managed build configurations

    When you confirm and add the stage it will show graphically as in figure 3.4.14. From there we can add our second stage by clicking the plus sign under the stage name. At running the pipeline this stage will dockerize the application and get ready a docker image for the same.

    Figure 3.4.14: Adding next step

    The next two screenshots are for our second step in the build pipeline, which is to deliver the artifacts. In this stage the docker image created will be uploaded to the repository created on OCIR (container registry).

     Figure 3.4.15:  Choose ‘Deliver artifacts’

    As in figure 3.4.16, we need to select the artifact location for the docker image registry. Furthermore, ‘Build config/ result artifact name’ should be matched to the name given for ‘outputArtifacts’ parameter in ‘build_spec.yaml’ file.

    Figure 3.4.16: Select artifact

    It’s time to build the deployment pipeline now. This will take responsibility to pull the image from the container registry and deploy to the Kubernetes cluster. Further, it will create a service to expose the application to public use.

    Figure 3.4.17: Create Deployment pipeline

    Similar to build pipeline you will get a graphical user interface to add the stage. As the first stage we are going to include the ‘Approval’ stage. This is an optional requirement where it will wait till manual approval to proceed for the deployment.

    Figure 3.4.18: Approval Stage

    As the second step, we are going to add Kubernetes deployment as shown in figure 3.4.19. Here, you need to select the ‘deployment.yaml’ as the artifact and pre-created OKE cluster as the environment.

    Figure 3.4.19: Deployment stage

    Once the deployment stage is added to the pipeline, we can add the service creation stage. Here, we need to choose ‘service.yaml’ file as the artifact and select the same OKE cluster as the environment.

    Figure 3.4.20: Service stage

    This concludes the building of the Deployment pipeline for the project and figure 3.4.21 shows the final look of the same.

    Figure 3.4.21: Complete Deployment Pipeline

    Now we need to automate the flow from build pipeline to deployment pipeline. In order to achieve this visit to the build pipeline again. There we need to add a new stage to call the deployment pipeline.

    Figure 3.4.22: Adding stage to build pipeline

    We need to select the ‘Trigger deployment’ stage as shown in figure 3.4.23.

    Figure 3.4.23: Add Trigger deployment stage

    There’s a facility to select the previously created deployment pipeline.

    Figure 3.4.24: Choose the deployment pipeline

    Once this is completed, our build pipeline will look like in figure 3.4.25.

    Figure 3.4.25: Final build pipeline

    This concludes the building of CI/CD pipeline on Oracle cloud using the DevOps project.

    4. Run CI/CD Pipeline

    We can now run the build pipeline and observe the application dockerization and deployment scenarios.

    This can be achieved by clicking the ‘Start manual run’ button on the build pipeline.

    Figure 4.1:  Run build pipeline

    We can monitor the pipeline running stages, major milestones and log files as shown in figure 4.2. In the first stage the docker image for the .Net application will be built.

    Figure 4.2:  Build pipeline starting

    The second stage will upload the docker image to the container registry created. We can verify it by logging into the OCIR as shown in figure 4.3.

    Figure 4.3: Docker Image 

    As we configure to trigger the deployment pipeline as soon as the build pipeline is completed, we can see it running.

    Figure 4.4: Deployment pipeline triggering

    Since we added approval stage at the start of the pipeline, we’ll need to manually approve it prior running the rest of the deployment pipeline.

    Figure 4.5:  Approval stage

    The second and third stages will do the application deployment and service creation respectively.

    Figure 4.6: Deployment pipeline completed

    We can verify the application deployment and service creation on Kubernetes by issuing ‘kubectl get all’ command. The cloud shell used in the figure 4.7, in order to access the Kubernetes.

    Figure 4.7: Kubernetes Deployment

    We can get the public IP of the service (Load Balancer) from above. This can then be accessed via a web browser. Kindly note that if your virtual cloud network’s subnet does not allows port 80 traffic need to open port from the respective security list.

    Figure 4.8: Application Access

    This concludes the article of showing the dockerization of .Net application on Oracle cloud infrastructure and deploying the same on Kubernetes cluster.

    All views expressed in this blog are personal.

    Reference

    https://learn.microsoft.com/en-us/dotnet/core/docker/build-container?tabs=linux&pivots=dotnet-8-0

    https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengpolicyconfig.htm

    https://docs.oracle.com/en-us/iaas/Content/devops/using/devops_iampolicies.htm 
    https://www.oracle.com/webfolder/technetwork/tutorials/obe/oci/oke-and-registry/index.html

    All views expressed in this blog are personal.