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.
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.
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
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.
We can run the existing application with ‘dotnet run’ and can see the output in the local machine.
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.
Now, change the ‘DotNet.Docker.csproj’ file also as shown in the figure 3.3.2.
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.
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).
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.
The ‘service.yaml’ file will create a service for the application deployed so that we can expose the service to the public.
Once the files are ready copy the files to the root directory as shown in figure 3.3.7.
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.
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.
Once the artifact registry is created, we can upload our YAML files namely, deployment.yaml and service.yaml to the 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.
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.
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.
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.
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.
Next, go to the ‘Environments’ section of the DevOps project and map the existing Kubernetes cluster.
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.
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
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.
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.
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.
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).
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.
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.
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.
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.
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.
This concludes the building of the Deployment pipeline for the project and figure 3.4.21 shows the final look of the same.
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.
We need to select the ‘Trigger deployment’ stage as shown in figure 3.4.23.
There’s a facility to select the previously created deployment pipeline.
Once this is completed, our build pipeline will look like in figure 3.4.25.
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.
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.
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.
As we configure to trigger the deployment pipeline as soon as the build pipeline is completed, we can see it running.
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.
The second and third stages will do the application deployment and service creation respectively.
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.
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.
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.