This document would share an experience on setting up kuburnate and then config your dotnetcore into your clustes. Then, it will also help to automate your deployment using kuberbetes cluster instead of visual studio publish tools.

This experiment case is contain; a) private cloud for kubernetes deployment, and b) automate deployment of your dotnet core services through a basic CI/CD based on Jenkins.

Requirement

  • Ubuntu 16.04 machine
  • git command-line client (installed by sudo apt install git)
  • Internet access

Quick outline

  • create or restore your .NET Core application on the Ubuntu machine and push the code to GitHub.
  • create and build a docker container and upload it to Docker Hub
  • setup Kubernetes cluster, the Canonical distribution.
  • Deploy your application on the Kubernetes cluster and expose it.
  • Deploy Jenkins next to Kubernetes and automate the deployment of your service.

Dotnet Core service on Linux

Installing dotnet core on Ubuntu 16.04 :

We can now copy our application into directory and then run dotnet run inside directory. Then open browser and hit localhost. (if you specified any port for your project, you have to add port after localhost: https://localhost:6600)

Dockerize application

Since you are able to run your application via command, now it is time to dockerize it and create container for application and its dependent services. If you do not have docker installed, please follow the steps:

You might create a dockerhub repository and push your dotnet docker image over there for easy pull and run. Therefore, go to https://hub.docker.com and create an account. After logging in to Docker Hub click on the “Create Repository” button and create a new public repository. That is where we will be pushing our docker images.

Now, try to run dotnet publish to make sure your project can be compile properly before moving to docker container.

Now, we tring to package everything under bin/Release/netcoreapp2.0/publish/. We create a Dockerfile on the root of our project with the following contents:

Building the container and testing that it works:

The Dockerfile should be part of the code so we commit it and push it to the git repository:

Kubernetes Cluster To utilize Kubernetes deployment we will go with Canonical’s solution. The reason being that Canonical offers a seamless and effortless transition from small deployment in localhost to a full blown production grade Kubernetes deployed on private, public clouds or even on bare metal. Therefore, we continue with deploying Kubernetes and Jenkins on localhost (just make sure your laptop/desktop have at least 8GB of RAM.
LXD
We first need to have LXD running. LXD is a really powerful type of container based on the similar technologies as Docker. Contrary to Docker, LXD containers resemble more to virtual machines (VMs). Lets simplify things and assume from now on that LXD containers are VMs that boot instantly and have no performance overhead!
For this deployment we are going to use LXD. While initialising ( /snap/bin/lxd init) make sure you go with the defaults but you do not enable ipv6. When asked “What IPv6 address should be used (CIDR subnet notation, “auto” or “none”) [default=auto]?” Reply with “none”. At this point we can use either Juju or Conjure-up to deploy Kubernetes. Conjure-up is essentially a wizard sitting on-top of Juju. To install Kubernetes with conjure-up you can simply use follow steps:
Canonical
Canonical Kubernetes comes in two flavours: kubernetes-core is a cut down version installed in two machines, in our case two LXD containers running on our localhost. canonical-kubernetes is the full production grade deployment with features such as HA and monitoring. We will go for kubernetes-core; on the next screen select localhost as the cloud provider. Follow the wizard’s steps till the end and wait for the deployment to finish. For a headless deployment you can do a `conjure-up kubernetes-core localhost` . To review the status of deployment have a look at: Getting into one of the LXD containers/machines we use juju ssh, for exmple: Inside kubernetes-master under /home/ubuntu you will find a config file you can use for accessing your cluster. We can fetch that file with: Conjure-up has already copied the Kubernetes config locally and installed kubectl for us. CI/CD To have an automated deployment process, you can use jenkins machine running beside other LXD which we just setup. Follows will be showing a few Jenkins jobs to automate the process of building, packaging and deploying our application. The intention here is to show everything that happens under the hood and not hide behind a flashy UI. You can simply run jenkins by following command: We deploy Jenkins next to our Kubernetes cluster. This will take some time, you can check the progress of the deployment with `juju status`. Next we need to set a password to Jenkins and expose it so we can access its UI on port 8080. Exposing Jenkins is not needed in the localhost deployment which uses LXD containers but we show it here for completeness. Before we start crafting our jobs we need to configure Jenkins a bit more. I can tell you beforehand our jobs need to sudo run without asking for a password. The easiest way to do that is to edit /etc/sudoers in the Jenkins machine. Here is how we append a line to the sudoers file with Juju: We also know that our Jenkins jobs need to talk to the Kubernetes. To this end Jenkins will need the kubeconfig file. We take the file from the kubernetes-master and place it in our Jenkins machine under /var/tmp: Last part of the configuration, I promise! We know our application will be exposed using Kubernetes NodePort on port 31576. We need to make sure there is no firewall blocking that port and requests can reach it: Jenkins is ready in `localhost:8080`. Then we can start creating our jobs. The first Jenkins jobs is the “Install dependencies”. This job is just a shell script installing all software packages needed to a) talk to kubernetes, b) build our .NET core service and c) package everything into a docker container. Place the following in a shell script job and run it once: The second Jenkins job bootstraps the service in Kubernetes. It creates a deployment using the v1 image we created above and it makes sure all operations are recorded ( — record param). This deployment is exposed using NodePort 31576. Place the following in a Jenkins jobs and run it once, remember to update the docker user name: Use juju status to find the IP of a kubernetes worker and open a browser at `http://:31576` . Your application is served from Kubernetes! But we are not done yet. Lets create a third job (“Build and release”) that pulls your code from GitHub, compiles it, puts it in a container and deploys that container. Replace the repository and the docker username in the following snippet. Then create a Jenkins job: Two parameters are needed: ${DOCKER_TAG} is a string, and ${DOCKER_PASS} holds the docker password of the user. You have to tick the checkbox indicating this is a parametrized job and add the two parameters. We are ready! Trigger the job and wait for it to finish. Your code should find its way to our Kubernetes cluster.

Enjoy!


ABOUT ATABAK

Atabak is a Software and Data Engineering Consultant


FOLLOW ATABAK

© Copyright 2017-2023