Hello, nice to meet you.
Welcome to the On.NET Show Korean version session.
Today, I will talk about how
to deploy an ASP.NET application
to the Azure Container Registry through a GitHub action
and load test it through the Azure Load Testing service
within the same GitHub
action workflow. I'll give you
Hello Jeunghoon Park, Nice to meet you
Could you briefly introduce yourself and start the session?
Hello, I am Jeunghoon Park from the Technical Support Department of
Microsoft's App Innovation Team.
I will first explain today's session as a whole.
The overall flow consists of deploying
a two-tier .NET 7 application through
GitHub actions.
When deploying an application,
it is deployed through a container image repository
called our container registry,
and then the application is deployed
using kubectl commands to a pre-configured Kubernetes cluster.
Deployed applications
are usually verified
through unit
tests or functional
tests.
It consists of running the verification of the application in the last step
through the Azure Load Testing service
released on our side a while ago.
So, the first topic to talk about is that
as the .NET 7 application becomes a container
registry or Docker Hub,
the first step is to deploy the application.
In the past, to execute that step, docker build, docker push, etc.
It was done in two or three steps,
but with .NET 7,
you can reduce that step to one.
So, in the case of my demo project,
there are now two front-end and back-end API sides,
but if you look at the front-end side, there is no Dockerfile.
So, we can subtract and specify the contents that existed in the existing Dockerfile
as the properties of the .csproj file.
If you look at the file now, the container registry
Then the image version, tag, image name, etc.
You can proceed by subtracting the parts previously specified in the Dockerfile
as properties like this.
Then, if you see below,
if you include Microsoft.NET.Build.Containers among the NuGet packages,
you can push the image to ACR, that is, the container registry
specified here, in one step, while doing dotnet publish.
If you look at that step now on the pipeline side, that step is done.
The first is to create a version
tag for the image
before pushing it to the container registry.
So, in my case, I created an image tag
using the build version used in the GitHub action
along with the date information.
Then, in the last step,
the application binary (artifact)
is created through the dotnet publish command.
In this case, the build and push are done at once
to the container registry at this stage.
If you look at the pipeline that is actually running,
you can see that the API build
and the frontend app build in the first step are now done simultaneously.
Then, in the second step, the image tag version
information generated here is applied to the YAML file
to deploy the application to the Kubernetes cluster, and in the third step,
the application is deployed to the Kubernetes cluster
through the kubectl command. consists of
So, let's modify the application a bit
and actually deploy it to a container registry and a Kubernetes cluster.
I'm going to add annotations to the
pre-generated application and push it to run a GitHub action.
I pushed the application changes to the GitHub side.
If you look at the GitHub Actions tab,
the GitHub action is executed by the currently pushed code.
To push the image to the container registry
I mentioned earlier, and to explain the second and third steps in a little detail,
the GitHub action workflow pipeline is a YAML file.
So, if you look at this side, the application is built at the same time, and in the next step,
there is a part that creates an image tag.
First, the current date, then the version
information from the GitHub action side
is used to replace the contents of the existing YAML file.
The existing YAML file is related to the deployment
and service on the Kubernetes side.
You can think of it as a general YAML file, and among these YAML files,
the image version of the API backend
app side and the frontend app side are
Since it is created in the pipeline,
I marked it like this like a placeholder.
When the actual GitHub action is executed,
it will replace this placeholder with the image tag information you saw earlier.
So, there is a placeholder on the API
side and a similar placeholder on the frontend side.
So, YAML files are distributed with image tag information.
In my case, for testing purposes,
I created an artifact in the GitHub action pipeline
and even uploaded the artifact
so that I could check the generated YAML file.
Then, the third step in the GitHub action,
that is, related to the actual deployment.
The YAML file created in the previous step
is logged in to Kubernetes,
logged in, and then deployed using the kubectl command.
So, you can see this line for the YAML file
reference used when actually deploying.
Then there's one more step when logging into
a Kubernetes cluster recently:
Because you have to run something called kubelogin to actually log in,
there was no previous step,
but one more step was added to the additional login procedure.
On GitHub's action tab side,
the first stage build is still in progress.
Then, in the last step, after giving the load
whether or not there is no load in the actually deployed application,
it is implemented through the Azure load
testing service to determine whether there is a delay
in response speed or failure.
You must first create it in the portal
The resource group and the load test instance name, then...
It's been a while since the release,
so unfortunately there is no Korean region yet.
The closest region to Korea is East Asia, so
in my case, I created an instance in East Asia.
So, before actually calling the GitHub action,
you need to create this Azure Load Test instance.
In the created load test instance,
you can choose what kind of load to give through the test.
So, in the case of this load test instance,
it is a JMeter-based load test,
so the existing .jmx file or
When POSTing, if you use a .csv file,
you give it as a parameter, so you can upload and create those files now.
When you create it,
you can additionally give environment variables or secrets.
For example, you can
configure such additional configurations,
such as simultaneous users or database connection strings,
such as importing them from Key Vault
without directly inserting a .jmx file,
and then you can use certificates here as well.
Then, on the fourth tab, there are load-related properties,
and you can see it as a screen
for configuring how many instances to create a load.
I was going to do a simple test,
so I designated one,
but our recommendation is
one instance
up to 250 concurrent connections.
The fifth tab is the test condition.
The test condition is the criterion for determining whether the load test passed or failed
when I shot the load.
Typically, the average response time took more than one second.
In that case, you can specify like this
and then the error rate is greater than 10% for example
Then, by giving
multi-conditions in
this way,
when you actually test
on GitHub,
you test with these conditions.
You can configure it to fail.
In the last monitoring item, you can configure monitoring items
in addition to the actual deployed target application
to monitor some details.
The pipeline is now in its third stage, so it hasn't come to the load test yet.
You can configure the content explained in the portal a while ago
by melting it into the GitHub action side.
In the case of a YAML file that calls a load test,
I took out and configured it separately.
If you look here, you can specify the target resource group,
then the actual load test name in this way,
and you can configure
how many concurrent users you want to use.
So, when the .jmx file
and then the .csv file are called, the argument
files are also located here.
Then, you can configure here
the same conditions that fail when you shoot the load
when you created it earlier in the portal.
So, if you look at the sample
YAML file, you can see that the .csv file to be used as a parameter
and the number of instances to be used for load testing are specified.
Then, in the last step, if the average response
time is greater than 1 second
or the HTTP error is greater than 20% is specified as a failure condition,
so that if load testing fails, the GitHub action itself fails.
If you look at the pipeline related to the load test,
the load test results are now displayed on the portal,
and the average data is displayed first.
After that, you can extract the load test execution
result by request (from GitHub action)
and check it as a .csv file.
In the last step, you can see that
the GitHub action test result is uploaded in the form
of an artifact of the GitHub action.
Currently, it is progressing to the load test stage.
If you look here, you can check the load test that is currently running.
I set it to 1 minute and now it's halfway through
and the average user is POSTing to 10 each and two endpoints,
/Privary and /Edit as I specified.
We are conducting a load test with 10 concurrent users,
and at the beginning of the load test,
since the application has not been warmed up
yet after deployment,
you can see that the latency is about 2 seconds.
You can see that
the current average is running about 360 ms.
And in the last graph, you can additionally
check how many requests per second are
now per page.
So, since I specified the load test in units of 1 minute,
you can see that the load test ended normally in the portal now,
and on the GitHub action side,
there is a part that pulls the actual result
value and saves it as an artifact of the GitHub action,
so there is a little delay You can check the result value next
Now, this last step takes some time,
so if you look at the result file
I saved in advance, you can see things
like average values on the portal.
You can see HTTP response codes such as 200 and 500,
and then you can see how long
it took for each request
in the latency section.
So, this latency value is in milliseconds,
so the first one took about 1.3 seconds.
As the load test progressed,
you can see that the response speed dropped a lot
in units of 200ms and 100ms.
You can directly download
the files and load test results
and view them on the client side
as you saw earlier.
Yes, today's session was very helpful.
Do you have any links to learning materials that other people watching
this session can follow alone?
Details will be shared by Justin again.
By the way, the starting point is "Deploying a
containerized operating program
to AKS" in the second item,
and then you can think of the "Deploying .NET microservices to AKS" link
as a starting point, which is a similar topic.
Yes, that's right
Now, the link at the bottom of the screen is flowing.
Through this link, you can self-directed learning
related to how to deploy apps as containers on Azure Kubernetes Service,
AKS, on the Microsoft Learn site.
I think you can think of it as link number 2
among the links that Jeunghoon shared earlier.
Now, once again, thank you
Jeunghoon for facilitating the session today.
We will try to find it again
with different content next time. thank you!