<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tugay Ersoy</title>
    <description>The latest articles on DEV Community by Tugay Ersoy (@admiralkheir).</description>
    <link>https://dev.to/admiralkheir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1054691%2F41b40e6f-58a7-4c8e-a2c4-7eeeb2ceb307.jpeg</url>
      <title>DEV Community: Tugay Ersoy</title>
      <link>https://dev.to/admiralkheir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/admiralkheir"/>
    <language>en</language>
    <item>
      <title>Zero-Downtime Deployment for ASP.NET Applications in Kubernetes</title>
      <dc:creator>Tugay Ersoy</dc:creator>
      <pubDate>Sun, 04 Aug 2024 13:59:27 +0000</pubDate>
      <link>https://dev.to/admiralkheir/zero-downtime-deployment-for-aspnet-applications-in-kubernetes-30li</link>
      <guid>https://dev.to/admiralkheir/zero-downtime-deployment-for-aspnet-applications-in-kubernetes-30li</guid>
      <description>&lt;p&gt;In today's world, services can be deployed frequently throughout the day due to needs, and new developments can be implemented for specific services. Sometimes these services may be ones where momentary interruptions are not problematic, and other times they may be services where even a single request experiencing an interruption could negatively affect the customer side. In this article, I will discuss what we can do to eliminate this interruption, both for Kubernetes and a service developed with ASP.NET.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can access the Turkish version of this &lt;a href="https://dev.to/admiralkheir/aspnet-web-api-ile-kubernetes-uzerinde-kesintisiz-deployment-kurgusu-5c9o"&gt;article&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Termination, creation, and update strategies of pods on the Kubernetes side&lt;/li&gt;
&lt;li&gt;Examination of the &lt;code&gt;Host&lt;/code&gt; structure on the .Net side&lt;/li&gt;
&lt;li&gt;Examination of &lt;code&gt;IHostedLifecycleService&lt;/code&gt;, &lt;code&gt;IHostedService&lt;/code&gt;, and &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; interfaces&lt;/li&gt;
&lt;li&gt;Examination of the Host's shutdown process&lt;/li&gt;
&lt;li&gt;Creating a Kubernetes Cluster with &lt;code&gt;Kind&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Creating a sample &lt;code&gt;.Net&lt;/code&gt; project, &lt;code&gt;Dockerfile&lt;/code&gt;, and &lt;code&gt;Deployment&lt;/code&gt; manifest&lt;/li&gt;
&lt;li&gt;Deploying the service to the Kubernetes Cluster and performing the test&lt;/li&gt;
&lt;li&gt;Delay between Kubernetes Ingress and Kubernetes Control Plane&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Update Strategy on Kubernetes
&lt;/h2&gt;

&lt;p&gt;On the Kubernetes side, the update strategy is specified under &lt;code&gt;.spec.strategy.type&lt;/code&gt; in the deployment object's manifest. This strategy is either &lt;code&gt;Recreate&lt;/code&gt; or the default behavior &lt;code&gt;RollingUpdate&lt;/code&gt; if not specified.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article assumes that the application is published as a Deployment object. For StatefulSets and DaemonSets objects, these strategies are determined under the &lt;code&gt;.spec.updateStrategy.type&lt;/code&gt; spec and these strategies are &lt;code&gt;OnDelete&lt;/code&gt; and &lt;code&gt;RollingUpdate&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Recreate
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Recreate&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the &lt;code&gt;Recreate&lt;/code&gt; update strategy, all pods are terminated first, and then pods belonging to the new version are brought up. According to the manifest given above, Kubernetes will first kill all 10 pods and then bring up new pods. This strategy will likely cause &lt;strong&gt;down-time&lt;/strong&gt; (interruption). This is because Kubernetes terminates all pods before new pods are created and take their place.&lt;/p&gt;

&lt;h3&gt;
  
  
  RollingUpdate
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;25%&lt;/span&gt;
        &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;25%&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the &lt;code&gt;RollingUpdate&lt;/code&gt; update strategy, pods are gradually replaced with the new version image. First, a pod is created with the new image number, and then the pod with the old image number is killed. This operation continues until it is performed for all pods.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;maxSurge&lt;/code&gt; and &lt;code&gt;maxUnavailable&lt;/code&gt; parameters are specified in the &lt;code&gt;RollingUpdate&lt;/code&gt; strategy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maxUnavailable&lt;/code&gt;: Specifies the number of pods that can be unavailable during the update phase. The value can be given as a percentage or directly as the number of pods. It's an optional field, and the default value is &lt;code&gt;25%&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxSurge&lt;/code&gt;: Expresses the number of pods that can be above the number of replicas specified in the Deployment manifest. Like &lt;code&gt;maxUnavailable&lt;/code&gt;, a percentage or direct pod number value can be given. It's an optional field, and the default value is &lt;code&gt;25%&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When percentage values are given for the fields mentioned above, if the number of pods is not an integer, this value is rounded down for &lt;code&gt;maxUnavailable&lt;/code&gt; and rounded up for &lt;code&gt;maxSurge&lt;/code&gt;. For example, when 1 replica is specified, the &lt;code&gt;maxSurge&lt;/code&gt; value corresponds to &lt;strong&gt;1&lt;/strong&gt; by rounding up and the &lt;code&gt;maxUnavailable&lt;/code&gt; value corresponds to &lt;strong&gt;0&lt;/strong&gt; by rounding down. In this case, a pod is created first, and after it transitions to the running state, the existing pod is terminated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the Rolling Update strategy, Kubernetes ensures that the application is deployed with minimal interruption. Below are the stages that occur during a Rolling Update operation for a deployment with a single replica, and a sample deployment manifest:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.14.2&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.3"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;75Mi"&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50Mi"&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When the &lt;code&gt;kubectl set image deployment/nginx-deployment nginx=nginx:1.14.1&lt;/code&gt; command is run to update the image version, the following stages are performed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Since the &lt;code&gt;maxSurge&lt;/code&gt; value is &lt;strong&gt;1&lt;/strong&gt;, a pod with the new image number is first started to be brought up.&lt;/li&gt;
&lt;li&gt;After the pod status transitions to &lt;code&gt;Running&lt;/code&gt;, Kubernetes sends a &lt;code&gt;SIGTERM&lt;/code&gt; signal to the old Pod. The routing of new requests to the Pod is stopped, and open connections are waited for to complete requests already in progress for the duration of &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the termination of the Pod takes longer than &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt;, Kubernetes sends a &lt;code&gt;SIGKILL&lt;/code&gt; signal and kills the pod.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the deployment above, the pod statuses when updating the image version are given in order below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;-w&lt;/span&gt;
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-59994fb97c-5j4fv   1/1     Running   0          8m8s
nginx-deployment-59994fb97c-g789c   1/1     Running   0          8m9s
nginx-deployment-59994fb97c-nddlf   1/1     Running   0          8m9s
nginx-deployment-5fffc966ff-8crmb   0/1     Pending   0          1s
nginx-deployment-5fffc966ff-8crmb   0/1     Pending   0          1s
nginx-deployment-5fffc966ff-8crmb   0/1     ContainerCreating   0          1s
nginx-deployment-5fffc966ff-8crmb   1/1     Running             0          1s
nginx-deployment-59994fb97c-5j4fv   1/1     Terminating         0          8m16s
nginx-deployment-5fffc966ff-52knq   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-52knq   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-52knq   0/1     ContainerCreating   0          0s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m16s
nginx-deployment-5fffc966ff-52knq   1/1     Running             0          1s
nginx-deployment-59994fb97c-g789c   1/1     Terminating         0          8m18s
nginx-deployment-5fffc966ff-jwmtt   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-jwmtt   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-jwmtt   0/1     ContainerCreating   0          0s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m18s
nginx-deployment-5fffc966ff-jwmtt   1/1     Running             0          1s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   1/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; value specified is defined on a per-pod basis. The default value is &lt;strong&gt;30s&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before sending the &lt;code&gt;SIGTERM&lt;/code&gt; signal to sidecar containers, the main container in the same pod is terminated, and then the &lt;code&gt;SIGTERM&lt;/code&gt; signal is sent to the sidecar containers in the reverse order of their definition. This ensures that the sidecar container is terminated when it's no longer needed within the pod.&lt;/p&gt;

&lt;p&gt;The nginx application in the Deployment quickly terminates the process when it receives the &lt;code&gt;SIGTERM&lt;/code&gt; signal, including open connections. Therefore, for it to be &lt;strong&gt;gracefully shutdown&lt;/strong&gt;, it should be tracked when the &lt;code&gt;SIGTERM&lt;/code&gt; signal is received and a &lt;code&gt;SIGQUIT&lt;/code&gt; signal should be given. Nginx waits for the &lt;code&gt;SIGQUIT&lt;/code&gt; signal to perform a graceful shutdown on its side. This can be done with a bash operation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  .Net Host Model
&lt;/h2&gt;

&lt;p&gt;The new &lt;code&gt;Host&lt;/code&gt; model approach that came with the .Net Core framework aims to encapsulate the resources and lifecycle functions that the application will need within the &lt;code&gt;Host&lt;/code&gt; object. With this structure, it also aims to remove a lot of boilerplate code included in default templates. By making certain arrangements on this object, the following functionalities come ready by default for the application type and can be arranged as needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependency Injection (DI)&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;App Shutdown process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService&lt;/code&gt; implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The specified 'Host' model approach has shown differences in the application templates as the versions of the .Net framework have changed. Below are three different approaches specified with .Net versions:&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;.NET Core 2.x&lt;/code&gt; version, the &lt;code&gt;Host&lt;/code&gt; model is created and configured with the &lt;code&gt;CreateDefaultBuilder&lt;/code&gt; method under the &lt;code&gt;WebHost&lt;/code&gt; class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateWebHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IWebHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateWebHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;WebHost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Above is the code block in the &lt;code&gt;Program.cs&lt;/code&gt; file when an &lt;code&gt;ASP.Net Core&lt;/code&gt; project is created from scratch with the &lt;code&gt;dotnet&lt;/code&gt; cli in the specified version.&lt;/p&gt;

&lt;p&gt;Between &lt;code&gt;.NET Core 3.x&lt;/code&gt; and &lt;code&gt;.NET 5&lt;/code&gt; versions, a major change was made in the &lt;code&gt;Host&lt;/code&gt; model approach to create web projects through the generic &lt;code&gt;Host&lt;/code&gt; as well. With this change, worker services, gRPC services, Windows services can be developed using the same base code through the &lt;code&gt;Host&lt;/code&gt; model. With this method, the &lt;code&gt;Host&lt;/code&gt; model is built on the &lt;code&gt;IHostBuilder&lt;/code&gt; interface instead of the &lt;code&gt;IWebHostBuilder&lt;/code&gt; interface.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureWebHostDefaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;webBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Above is the code block in the &lt;code&gt;Program.cs&lt;/code&gt; file of the &lt;code&gt;ASP.NET&lt;/code&gt; project created from scratch with the &lt;code&gt;dotnet&lt;/code&gt; cli between &lt;code&gt;.NET Core 3.x&lt;/code&gt; and &lt;code&gt;.NET 5&lt;/code&gt; versions.&lt;/p&gt;

&lt;p&gt;It should be noted that in both approaches shared above, the &lt;code&gt;Startup&lt;/code&gt; class is tightly coupled on the web application, but we mentioned that different applications can be developed in the &lt;code&gt;Host&lt;/code&gt; model approach positioned on the &lt;code&gt;IHostBuilder&lt;/code&gt; interface besides web applications. These applications may not need the &lt;code&gt;Startup&lt;/code&gt; class. (For example, the &lt;code&gt;Configure&lt;/code&gt; method is used to set up the middlewares in the application, but there is no need for such configuration for worker services.) For this reason, framework developers have overcome this situation with the &lt;code&gt;ConfigureWebHostDefaults&lt;/code&gt; extension method.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;.NET 6&lt;/code&gt;, the configurations made on two different files (&lt;code&gt;Startup.cs&lt;/code&gt; and &lt;code&gt;Program.cs&lt;/code&gt;) were combined into a single file, and the &lt;code&gt;Host&lt;/code&gt; model was positioned on the &lt;code&gt;IHostApplicationBuilder&lt;/code&gt; class. In the migration notes, they referred to this approach as &lt;code&gt;Minimal Hosting&lt;/code&gt; and positioned &lt;code&gt;Minimal API&lt;/code&gt; as the default web template.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Example.Processor.Api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;

        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSwaggerGen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwagger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwaggerUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Above is the code block in the &lt;code&gt;Program.cs&lt;/code&gt; file of the &lt;code&gt;ASP.NET&lt;/code&gt; project created from scratch with the &lt;code&gt;dotnet&lt;/code&gt; cli with &lt;code&gt;.NET 6&lt;/code&gt; version. As you can see, all configurations are positioned in a single file and there is no &lt;code&gt;Startup&lt;/code&gt; class. Additionally, with this approach, the &lt;code&gt;WebApplication.CreateBuilder&lt;/code&gt; method is used instead of the &lt;code&gt;Host.CreateDefaultBuilder&lt;/code&gt; method, and &lt;code&gt;IHostApplicationBuilder&lt;/code&gt; is returned instead of &lt;code&gt;IHostBuilder&lt;/code&gt;. .NET developers introduced the &lt;code&gt;Host.CreateApplicationBuilder&lt;/code&gt; method with &lt;code&gt;.NET 7&lt;/code&gt; and recommended continuing the &lt;code&gt;Host&lt;/code&gt; model approach for Web and Non-Web applications as specified below. You can reach David Fowler's &lt;a href="https://github.com/dotnet/runtime/discussions/81090#discussioncomment-4784551" rel="noopener noreferrer"&gt;comment&lt;/a&gt; on this topic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example approach for Web Applications&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;BindConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyConfig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyWorker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Example approach for Non-Web Applications&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateApplicationBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;BindConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyConfig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyWorker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;WebApplication&lt;/code&gt; class has implemented 3 interfaces necessary for the web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IHost&lt;/code&gt; - Responsible for starting and terminating the Host.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IApplicationBuilder&lt;/code&gt; - Used to create middleware pipelines&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IEndpointRouteBuilder&lt;/code&gt; - Used for endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, the following 3 services are automatically registered to the DI container when the &lt;code&gt;HostApplicationBuilder.Build()&lt;/code&gt; method is called:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime&lt;/code&gt; - Used to handle graceful shutdown and post-startup operations by injecting it into any class&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostLifetime&lt;/code&gt; - Controls when the application will start or end.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostEnvironment&lt;/code&gt; - Used to get information such as application name, Root Path, Environment Name, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examining &lt;code&gt;IHostApplicationLifetime&lt;/code&gt;, &lt;code&gt;IHostLifecycleService&lt;/code&gt;, &lt;code&gt;IHostedService&lt;/code&gt; Interfaces
&lt;/h2&gt;

&lt;p&gt;To understand the specified interfaces and the Lifetime events implemented with these interfaces, an example &lt;code&gt;IHostedService&lt;/code&gt; implementation is provided below;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;BackgroundService&lt;/code&gt; is an &lt;code&gt;abstract&lt;/code&gt; class and is used to create background services. &lt;code&gt;IHostedService&lt;/code&gt; is an interface implemented by &lt;code&gt;BackgroundService&lt;/code&gt;. It contains methods to manage the &lt;code&gt;Host&lt;/code&gt;. &lt;code&gt;Worker Service&lt;/code&gt; is a template for creating background services. It is created with the &lt;code&gt;dotnet new worker&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;It is possible to create services that will perform background processing by only implementing &lt;code&gt;IHostedService&lt;/code&gt;, but here it is necessary to manually implement the graceful shutdown operation in the service by listening to the application's lifetime events. In &lt;code&gt;BackgroundService&lt;/code&gt;, the graceful shutdown operation can be performed more easily by checking the &lt;code&gt;CancellationToken&lt;/code&gt; passed as a parameter to the overridden &lt;code&gt;ExecuteAsync&lt;/code&gt; method in the operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHostedLifecycleService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStarted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStarted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStopping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStopping&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStopped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStopped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedService StartAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartedAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StartedAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StartingAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StopAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedService StopAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StoppedAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StoppedAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StoppingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StoppingAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStarted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStarted has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStopped&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStopped has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStopping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStopping has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I mentioned that I needed to implement &lt;code&gt;IHostedService&lt;/code&gt; because I wanted to do background processing. The reason I use &lt;code&gt;IHostedLifecycleService&lt;/code&gt; here is that this interface inherits from &lt;code&gt;IHostedService&lt;/code&gt;. This interface was introduced with &lt;code&gt;.Net 8&lt;/code&gt;. This way, we can more easily intervene in the application's lifecycle cycle and perform operations. It contains 4 new methods. These are &lt;code&gt;StartingAsync&lt;/code&gt;, &lt;code&gt;StartedAsync&lt;/code&gt;, &lt;code&gt;StoppingAsync&lt;/code&gt; and &lt;code&gt;StoppedAsync&lt;/code&gt;. Additionally, I mentioned that &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; is automatically registered when the host is built. The 3 properties under this class are actually &lt;code&gt;CancellationToken&lt;/code&gt;s and are triggered according to the Host's lifetime. I register to these tokens as I mentioned above.&lt;/p&gt;

&lt;p&gt;I register the &lt;code&gt;Hosted Service&lt;/code&gt; I created above to the DI container as follows:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Example.Worker.Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateApplicationBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;


&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When I run the application and then terminate it with &lt;code&gt;CTRL+C&lt;/code&gt;, I get the following console output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StartingAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedService StartAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StartedAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStarted has been called
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:&lt;span class="se"&gt;\C&lt;/span&gt;odes&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStopping has been called
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StoppingAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedService StopAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StoppedAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStopped has been called

C:&lt;span class="se"&gt;\C&lt;/span&gt;odes&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;ebug&lt;span class="se"&gt;\n&lt;/span&gt;et8.0&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service.exe &lt;span class="o"&gt;(&lt;/span&gt;process 35456&lt;span class="o"&gt;)&lt;/span&gt; exited with code 0.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When we check the output, it appears that the order is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StartingAsync&lt;/code&gt; is called. This is the method called before the application starts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService.StartAsync&lt;/code&gt; is called. This is the method called when the Host is ready to start the service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StartedAsync&lt;/code&gt; is called. It is called immediately after &lt;code&gt;IHostedService.StartAsync&lt;/code&gt;, that is, after the startup operation is completed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStarted&lt;/code&gt; indicates that the Host has fully started.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After the application is stopped, it is observed that the following sequence takes place:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStopping&lt;/code&gt; is triggered when the application starts to perform the graceful shutdown operation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StoppingAsync&lt;/code&gt; is called just before the application starts to shut down. It is located just before the &lt;code&gt;IHostedService.StopAsync&lt;/code&gt; operation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService.StopAsync&lt;/code&gt; performs the graceful shutdown operation of the application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StoppedAsync&lt;/code&gt; is called when the graceful shutdown operation of the application is completed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStopped&lt;/code&gt; indicates that the graceful shutdown operation of the application has been completed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another important point here is that the application is being terminated with the &lt;code&gt;CTRL+C&lt;/code&gt; combination. The Host has automatically registered the &lt;code&gt;IHostLifetime&lt;/code&gt; interface as &lt;code&gt;ConsoleLifetime&lt;/code&gt; by default. This is also valid for Web and Background Service. I mentioned that the &lt;code&gt;IHostLifetime&lt;/code&gt; interface controls when the application will start and end. In &lt;code&gt;ConsoleLifetime&lt;/code&gt;, we give a &lt;code&gt;SIGINT&lt;/code&gt; signal to the application by pressing the combination I mentioned above. For the reasons I explained in the first section, Kubernetes sends a &lt;code&gt;SIGTERM&lt;/code&gt; signal to the container to terminate the pod. As a result of these specified signals, a graceful shutdown operation is performed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before &lt;code&gt;.Net 6&lt;/code&gt;, posix signals were not supported and handled according to signal type. After &lt;code&gt;.Net 6&lt;/code&gt;, &lt;code&gt;ConsoleLifetime&lt;/code&gt; can perform graceful shutdown operation by listening to &lt;code&gt;SIGINT&lt;/code&gt;, &lt;code&gt;SIGQUIT&lt;/code&gt;, &lt;code&gt;SIGTERM&lt;/code&gt; signals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Host's Shutdown Process
&lt;/h2&gt;

&lt;p&gt;I mentioned that by default, in &lt;code&gt;.Net 6&lt;/code&gt; and later, the generic host implements the &lt;code&gt;IHostLifetime&lt;/code&gt; interface as &lt;code&gt;ConsoleLifetime&lt;/code&gt;. For the Host to be gracefully terminated, this operation can be performed by sending the following signals to &lt;code&gt;ConsoleLifetime&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SIGINT&lt;/code&gt; or &lt;code&gt;CTRL+C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SIGQUIT&lt;/code&gt; or &lt;code&gt;CTRL+BREAK&lt;/code&gt; (Windows)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SIGTERM&lt;/code&gt; (The signal sent by Kubernetes to the container to terminate the pod &lt;code&gt;docker stop&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Before &lt;code&gt;.Net 6&lt;/code&gt;, graceful shutdown operation could not be performed when the &lt;code&gt;SIGTERM&lt;/code&gt; signal came. As a workaround for this situation, on the &lt;code&gt;ConsoleLifetime&lt;/code&gt; side, the &lt;code&gt;System.AppDomain.ProcessExit&lt;/code&gt; event would be listened to, the &lt;code&gt;ProcessExit&lt;/code&gt; thread would be stopped, and the host would be waited to stop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdytobe7u5lsi1j4tzf8x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdytobe7u5lsi1j4tzf8x.PNG" alt="Host shut down süreci"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process that takes place during the graceful shut down operation is shown above. In order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;SIGTERM&lt;/code&gt; signal comes from Kubernetes or the user. As a result of this signal, the &lt;code&gt;StopApplication()&lt;/code&gt; method under &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; is triggered and the &lt;code&gt;ApplicationStopping&lt;/code&gt; event is fired. Previously, the &lt;code&gt;IHost.WaitForShutdownAsync&lt;/code&gt; method was listening to this specified event, and because the event is triggered, it unblocks the &lt;code&gt;Main&lt;/code&gt; execution.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;IHost.StopAsync()&lt;/code&gt; method is triggered, and from within this method, &lt;code&gt;IHostedService.StopAsync()&lt;/code&gt; is triggered, ensuring that each hosted service is stopped and then firing events indicating that it has been stopped.&lt;/li&gt;
&lt;li&gt;Finally, &lt;code&gt;IHost.WaitForShutdownAsync&lt;/code&gt; is completed, the code blocks that the application needs to execute are executed, and the graceful shut-down operation is performed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is possible to set the &lt;code&gt;ShutdownTimeout&lt;/code&gt; by configuring the Host. This value is the timeout period specified for the &lt;code&gt;IHost.StopAsync()&lt;/code&gt; method and its default value is 30 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Kubernetes Cluster with &lt;code&gt;Kind&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;Kind&lt;/code&gt; as a OpenSource project, it is possible to quickly set up Kubernetes clusters locally. For this article, the Kubernetes cluster where the developed application will be published was created with the &lt;code&gt;Kind&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, we install the &lt;code&gt;Kind&lt;/code&gt; cli locally with the command specified below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

curl.exe &lt;span class="nt"&gt;-Lo&lt;/span&gt; kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.23.0/kind-windows-amd64
Move-Item .&lt;span class="se"&gt;\k&lt;/span&gt;ind-windows-amd64.exe c:&lt;span class="se"&gt;\s&lt;/span&gt;ome-dir-in-your-PATH&lt;span class="se"&gt;\k&lt;/span&gt;ind.exe


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't forget to add the directory you specify to the &lt;code&gt;Path&lt;/code&gt; environment variable, so that you don't have to go to the directory where the cli is every time you want to perform operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, to set up a cluster with 3 worker nodes, the yaml file specified below is created.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cluster&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kind.x-k8s.io/v1alpha4&lt;/span&gt;
&lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;control-plane&lt;/span&gt;
  &lt;span class="na"&gt;kubeadmConfigPatches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InitConfiguration&lt;/span&gt;
    &lt;span class="na"&gt;nodeRegistration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kubeletExtraArgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ingress-ready=true"&lt;/span&gt;    
  &lt;span class="na"&gt;extraPortMappings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8081&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
    &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8443&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The yaml file I provided above; it is observed that there are definitions for each node role and forwarding requests sent to ports 8081 and 8443 locally to the ingress controller we will set up on the cluster.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kind create cluster &lt;span class="nt"&gt;--config&lt;/span&gt; .&lt;span class="se"&gt;\k&lt;/span&gt;ind-cluster.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I'm setting up the cluster with the command I provided above&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kind create cluster &lt;span class="nt"&gt;--config&lt;/span&gt; .&lt;span class="se"&gt;\k&lt;/span&gt;ind-config&lt;span class="se"&gt;\k&lt;/span&gt;ind-cluster.yaml
Creating cluster &lt;span class="s2"&gt;"kind"&lt;/span&gt; ...
 ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.30.0&lt;span class="o"&gt;)&lt;/span&gt; 🖼
 ✓ Preparing nodes 📦 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to &lt;span class="s2"&gt;"kind-kind"&lt;/span&gt;
You can now use your cluster with:

kubectl cluster-info &lt;span class="nt"&gt;--context&lt;/span&gt; kind-kind

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I install the ingress controller with the command I provided below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;This manifest file prepared specifically for &lt;code&gt;Kind&lt;/code&gt; and contains some patches and settings for forward operation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After these operations are completed, the cluster is now ready to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Web API
&lt;/h2&gt;

&lt;p&gt;We are creating a web api project with &lt;code&gt;.Net 8&lt;/code&gt; and we are modifying &lt;code&gt;Program.cs&lt;/code&gt; file as specified below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Unnecessary services have been removed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm renaming the Controller and Action names as specified below. In the previous section, I mentioned that the default value of &lt;code&gt;ShutdownTimeout&lt;/code&gt; is 30 seconds. I'm making a change to wait for 35 seconds within the action and return a response for the operation to get an error.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PingPongController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ping"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pong"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I'm creating the deployment manifest for deploying application&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi:0.1&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.5"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;In the images released with &lt;code&gt;.Net 8&lt;/code&gt;, the default port on which the application runs has been changed from &lt;code&gt;80&lt;/code&gt; to &lt;code&gt;8080&lt;/code&gt;. For this reason, the port information is set to &lt;code&gt;8080&lt;/code&gt; in the manifest. &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8/containers" rel="noopener noreferrer"&gt;İlgili doc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm creating &lt;code&gt;Dockerfile&lt;/code&gt; as shown below;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/aspnet:8.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./Publish .&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["dotnet", "Example.Ping.Api.dll"]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Deploying the Service and Performing the Test
&lt;/h2&gt;

&lt;p&gt;First, I'm publishing my application under the &lt;code&gt;Publish&lt;/code&gt; directory&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet publish &lt;span class="nt"&gt;-o&lt;/span&gt; ./Publish


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I'm building the image;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker build &lt;span class="nt"&gt;-t&lt;/span&gt; pingapi:0.1 &lt;span class="nb"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before applying the deployment manifest on the cluster, I transfer the tagged image to each node using the command specified below. Otherwise, I would need to push this image to an image repository and pull it from the cluster. Kind provides convenience here.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kind load docker-image pingapi:0.1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kind load docker-image pingapi:0.1
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker3"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-control-plane"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker2"&lt;/span&gt;, loading...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I'm applying the deployment with the command specified below;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; .&lt;span class="se"&gt;\K&lt;/span&gt;ubernetes&lt;span class="se"&gt;\d&lt;/span&gt;eployment.yaml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I'm forwarding the container's &lt;code&gt;8080&lt;/code&gt; port with the command specified below;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl port-forward deployment/pingapi-deployment &lt;span class="nt"&gt;-n&lt;/span&gt; default 8080:8080
Forwarding from 127.0.0.1:8080 -&amp;gt; 8080
Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1]:8080 -&amp;gt; 8080


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can start test. First, I send a request with the &lt;code&gt;httpstat http://localhost:8080/pingpong/ping&lt;/code&gt; command, then I run the &lt;code&gt;kubectl delete pod/pingapi-deployment-5c78cbdfc-bfd9b&lt;/code&gt; command to delete the pod. As expected, due to both the &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; being the default value of 30 seconds on the Kubernetes side (as we didn't specify it in the deployment manifest) and the &lt;code&gt;Host&lt;/code&gt; object's &lt;code&gt;ShutdownTimeout&lt;/code&gt; being the default value of 30 seconds on the .Net side, the connection is terminated for the request we sent, as seen in the error.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A similar scenario can be tested by deploying a new image version. The purpose here is to send a &lt;code&gt;SIGTERM&lt;/code&gt; signal to the pod, so the test process was carried out with a pod deletion operation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl374dafbokgwbegg5ef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl374dafbokgwbegg5ef.png" alt="Terminal görünümü"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To overcome this situation, I first configure the &lt;code&gt;Host&lt;/code&gt; on the application side, then update the value called &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; under the deployment manifest.&lt;/p&gt;

&lt;p&gt;The new version of the &lt;code&gt;Program.cs&lt;/code&gt; file is created as specified below;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;


&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Example.Ping.Api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHostOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShutdownTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;

        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The new version of the &lt;code&gt;deployment.yaml&lt;/code&gt; file is as follows;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi:0.2&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.5"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
      &lt;span class="na"&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;We update the newly built image as &lt;code&gt;pingapi:0.2&lt;/code&gt; in the deployment manifest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After making the specified update, we apply the test again, it is observed that no problems are encountered;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqawvrsv01mc2j03gy8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqawvrsv01mc2j03gy8m.png" alt="Terminal logları"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Delay Between Kubernetes Ingress and Control Plane
&lt;/h2&gt;

&lt;p&gt;Despite the adjustments we made above, there is still a possibility of encountering errors for a few requests, especially during the &lt;code&gt;RollingUpdate&lt;/code&gt; phase for heavily used services. This is due to the delay between the ingress and the control plane.&lt;/p&gt;

&lt;p&gt;The reason for this is that ingress and Kubernetes control plane are different entities within Kubernetes and perform their operations independently. When Kubernetes wants to terminate a pod, the control plane removes the pods to be terminated from the Service, and the ingress becomes aware of this and stops routing requests to the pods to be terminated. There is a delay between these two operations because the ingress updates these changes made in the Services on its side at certain intervals. This situation causes requests to be forwarded to pods in &lt;code&gt;terminating&lt;/code&gt; status for a small number of requests.&lt;/p&gt;

&lt;p&gt;On the .Net side, after &lt;code&gt;IHost.StopAsync()&lt;/code&gt; is called, the application does not allow new requests to come through already open connections and also does not allow opening a new connection. Therefore, this delay means that new requests can come when the &lt;code&gt;IHost.StopAsync()&lt;/code&gt; operation starts. This will cause an error for the requesting party.&lt;/p&gt;

&lt;p&gt;As a solution to this situation, the method I will use below has been recommended by the dotnet team. &lt;a href="https://github.com/dotnet/dotnet-docker/blob/main/samples/kubernetes/graceful-shutdown/graceful-shutdown.md#adding-a-shutdown-delay" rel="noopener noreferrer"&gt;ref&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In previous sections, it was mentioned that &lt;code&gt;IHostLifetime&lt;/code&gt; controls when the application will start or stop. Therefore, we first implement a new &lt;code&gt;IHostLifetime&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.InteropServices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DelayedShutdownHostLifetime&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHostLifetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;_delay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;_disposables&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DelayedShutdownHostLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_delay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StopAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;WaitForStartAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_disposables&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGQUIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignalContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cancel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delay&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ContinueWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StopApplication&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;disposable&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_disposables&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="n"&gt;Enumerable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;())&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When the operation is examined, a registration operation has been performed for certain &lt;code&gt;POSIX&lt;/code&gt; signals when the application first starts up. In this way, when one of these signals comes to the application side, a delay is defined with &lt;code&gt;Task.Delay&lt;/code&gt; before starting the &lt;code&gt;IHostApplicationLifetime.StopApplication()&lt;/code&gt; operation. Thanks to this delay, the graceful shut-down process will not start immediately when the specified signals are received, and new requests coming to the pod can be handled during the specified delay.&lt;/p&gt;

&lt;p&gt;As the final step, I register the newly created &lt;code&gt;IHostLifetime&lt;/code&gt; implementation under &lt;code&gt;Program.cs&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHostOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShutdownTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IHostLifetime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DelayedShutdownHostLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(),&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;It was mentioned that &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; and &lt;code&gt;IHostLifetime&lt;/code&gt; are registered as services within the &lt;code&gt;HostApplicationBuilder.Build()&lt;/code&gt; method. Here, &lt;code&gt;IHostLifetime&lt;/code&gt; is registered again to ensure it's used with the specified &lt;code&gt;DelayedShutdownHostLifetime&lt;/code&gt; implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the final operation, a seamless deployment process has been achieved on the Kubernetes side. Thank you for reading :)&lt;/p&gt;

&lt;p&gt;You can check application &lt;a href="https://github.com/Admiralkheir/Example.Ping.Api" rel="noopener noreferrer"&gt;code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/workers" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/core/extensions/workers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#host-shutdown" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#host-shutdown&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/webapplication?view=aspnetcore-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/webapplication?view=aspnetcore-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostlifetime?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostlifetime?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-6.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-6.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.sebastian-daschner.com/entries/zero-downtime-updates-kubernetes" rel="noopener noreferrer"&gt;https://blog.sebastian-daschner.com/entries/zero-downtime-updates-kubernetes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-8.0#ihostlifetime" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-8.0#ihostlifetime&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>kubernetes</category>
      <category>dotnet</category>
      <category>api</category>
    </item>
    <item>
      <title>ASP.NET Web API ile Kubernetes Üzerinde Kesintisiz Deployment Kurgusu</title>
      <dc:creator>Tugay Ersoy</dc:creator>
      <pubDate>Sat, 27 Jul 2024 22:05:00 +0000</pubDate>
      <link>https://dev.to/admiralkheir/aspnet-web-api-ile-kubernetes-uzerinde-kesintisiz-deployment-kurgusu-5c9o</link>
      <guid>https://dev.to/admiralkheir/aspnet-web-api-ile-kubernetes-uzerinde-kesintisiz-deployment-kurgusu-5c9o</guid>
      <description>&lt;p&gt;Günümüz dünyasında ihtiyaçlara binaen gün içerisinde servislere çok sık deploy çıkılabilmekte ve service özelinde yeni geliştirmeler devreye alınabilmektedir. Kimi zaman bu servisler anlık kesintinin problem olmayacağı kimi zaman da tek bir request özelinde bile kesinti yaşandığında müşteri tarafının olumsuz bir şekilde etkilenebileceği servisler olabilmektedir. Bu kesinti durumunu ortadan kaldırmak için gerek Kubernetes özelinde gerek de ASP.NET ile geliştirilen bir servis özelinde neler yapabileceğimize yazı kapsamında değiniyor olacağım.&lt;/p&gt;

&lt;h2&gt;
  
  
  İçerik
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes tarafında pod'un sonlandırılması, oluşturulması ve update stratejileri&lt;/li&gt;
&lt;li&gt;.Net tarafında &lt;code&gt;Host&lt;/code&gt; yapısının incelenmesi&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService&lt;/code&gt;, &lt;code&gt;IHostedService&lt;/code&gt; ve &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; interface'lerinin incelenmesi&lt;/li&gt;
&lt;li&gt;Host'un shutdown sürecinin incelenmesi&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Kind&lt;/code&gt; ile Kubernetes Cluster oluşturulması&lt;/li&gt;
&lt;li&gt;Örnek &lt;code&gt;.Net&lt;/code&gt; projesi, &lt;code&gt;Dockerfile&lt;/code&gt; ve &lt;code&gt;Deployment&lt;/code&gt; manifest'in oluşturulması&lt;/li&gt;
&lt;li&gt;Servisin Kubernetes Cluster'a deploy edilmesi ve testin gerçekleştirilmesi&lt;/li&gt;
&lt;li&gt;Kubernetes Ingress ve Kubernetes Control Plane arasındaki gecikme&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kubernetes Üzerinde Update Stratejisi
&lt;/h2&gt;

&lt;p&gt;Kubernetes tarafında, deployment objesinin manifestinde &lt;code&gt;.spec.strategy.type&lt;/code&gt; altında update stratejisi belirtilmektedir. Bu strateji &lt;code&gt;Recreate&lt;/code&gt; ya da verilmediği taktirde default davranış olan &lt;code&gt;RollingUpdate&lt;/code&gt;'dir.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bu makele kapsamında uygulamanın bir Deployment objesi olarak yayınlandığı baz alınmıştır. StatefulSets ve DaemonSets objelerinde &lt;code&gt;.spec.updateStrategy.type&lt;/code&gt; spec'di altında bu stratejiler belirlenmektedir. Bu stratejiler ise &lt;code&gt;OnDelete&lt;/code&gt; ve &lt;code&gt;RollingUpdate&lt;/code&gt;'dir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Recreate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Recreate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Recreate&lt;/code&gt; update stratejisinde; öncesinde bütün pod'lar terminate edilir ve ardından yeni versiyona ait pod'lar ayağa kaldırılır. Yukarıda verilen manifest'e göre öncesinde Kubernetes bütün 10 pod'u öldürecek ve ardından yeni pod'ları ayağa kaldıracaktır. Bu stratejide muhtemel &lt;strong&gt;down-time&lt;/strong&gt;'a (kesinti) neden olacaktır. Bunun sebebi ise Kubernetes'in öncesinde bütün pod'ları; yeni pod'lar oluşup yerlerine geçmeden terminate etmesidir.&lt;/p&gt;

&lt;h3&gt;
  
  
  RollingUpdate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;
        &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;RollingUpdate&lt;/code&gt; update stratejisinde ise kademeli olarak pod'lar yeni versiyonlu image ile replace edilir. Öncelikle pod yeni image numarası ile oluşturulur ve ardından eski image numaralı pod öldürülür. Bu operasyon bütün pod'lar için gerçekleşene kadar devam eder. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;maxSurge&lt;/code&gt; ve &lt;code&gt;maxUnavailable&lt;/code&gt; parametreleri &lt;code&gt;RollingUpdate&lt;/code&gt; stratejisinde belirtilmektedir.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maxUnavailable&lt;/code&gt;: Update aşamasında unavailable olabilecek pod sayısını belirtmektedir. Değer olarak yüzdelik ya da doğrudan pod sayısı verilebilir. Optional bir field'dır ve default değeri &lt;code&gt;%25&lt;/code&gt;'dir.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxSurge&lt;/code&gt;: Deployment manifest içerisinde belirtilen replica sayısının üstünde olabilecek pod sayısını ifade etmektedir. &lt;code&gt;maxUnavailable&lt;/code&gt;'da olduğu gibi yüzdelik ya da doğrudan pod sayısı değeri verilebilir. Optional bir field'dır ve default değeri &lt;code&gt;%25&lt;/code&gt;'dir.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Yukarıda belirtilen field'lar için yüzdelik değer verildiği durumlarda; pod sayısı tam sayı gelmez ise &lt;code&gt;maxUnavailable&lt;/code&gt; için bu değer aşağıya &lt;code&gt;maxSurge&lt;/code&gt; için ise bu değer yukarıya yuvarlanır. Örneğin 1 replica belirtildiği durumda &lt;code&gt;maxSurge&lt;/code&gt; değeri yukarı yuvarlanarak &lt;strong&gt;1&lt;/strong&gt;'e &lt;code&gt;maxUnavailable&lt;/code&gt; değeri ise aşağıya yuvarlanarak &lt;strong&gt;0&lt;/strong&gt;'a karşılık gelmektedir. Bu durumda önce bir pod oluşturulur ve running duruma geçtikten sonra hali hazırdaki pod terminate edilir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rolling Update stratejisi ile beraber Kubernetes uygulamanın minimum kesintiye uğrayarak deploy edilmesini sağlamaktadır. Aşağıda Rolling Update operasyonu sırasında tek replica'ya sahip bir deployment için oluşan aşamalar ve örnek deployment manifest aktarılmıştır;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;  name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;
&lt;span class="na"&gt;  labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;  replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="na"&gt;  selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;      app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;  template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;      labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;        app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;    spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;      containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;        - name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;          image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.14.2&lt;/span&gt;
&lt;span class="na"&gt;          ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;            - containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="na"&gt;          resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;            limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;              cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.3"&lt;/span&gt;
&lt;span class="na"&gt;              memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;75Mi"&lt;/span&gt;
&lt;span class="na"&gt;            requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;              cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
&lt;span class="na"&gt;              memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50Mi"&lt;/span&gt;
&lt;span class="na"&gt;  strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kubectl set image deployment/nginx-deployment nginx=nginx:1.14.1&lt;/code&gt; komutu çalıştırılarak image versiyonu update edildiğinde aşağıdaki aşamalar gerçekleştirilmektedir;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;maxSurge&lt;/code&gt; değeri &lt;strong&gt;1&lt;/strong&gt; olduğundan öncelikle yeni image numarası ile bir pod ayağa kaldırılmaya başlanır.&lt;/li&gt;
&lt;li&gt;Pod status'ü &lt;code&gt;Running&lt;/code&gt;'e geçtikten sonra hali hazırda olan Pod'a Kubernetes tarafından &lt;code&gt;SIGTERM&lt;/code&gt; sinyali gönderilir. Pod'a yeni gelen isteklerin yönlendirilmesi kesilir ve hali hazırda olan isteklerin tamamlanması için açık connection'lar &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; süresi zarfınca beklenir.&lt;/li&gt;
&lt;li&gt;Pod'un terminate olması &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; süresinde fazla ise Kubernetes tarafından &lt;code&gt;SIGKILL&lt;/code&gt; sinyali gönderilir ve pod kill edilir.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Kubernetes tarafında bu süre beklenir fakat uygulama tarafında da belirtilen &lt;code&gt;POSIX&lt;/code&gt; sinyali neticesinde graceful shutdown için işlemin yapılması gerekmektedir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yukarıdaki deployment için aşağıda image versiyonu update edildiğinde pod status'leri sırası ile verilmiştir;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;-w&lt;/span&gt;
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-59994fb97c-5j4fv   1/1     Running   0          8m8s
nginx-deployment-59994fb97c-g789c   1/1     Running   0          8m9s
nginx-deployment-59994fb97c-nddlf   1/1     Running   0          8m9s
nginx-deployment-5fffc966ff-8crmb   0/1     Pending   0          1s
nginx-deployment-5fffc966ff-8crmb   0/1     Pending   0          1s
nginx-deployment-5fffc966ff-8crmb   0/1     ContainerCreating   0          1s
nginx-deployment-5fffc966ff-8crmb   1/1     Running             0          1s
nginx-deployment-59994fb97c-5j4fv   1/1     Terminating         0          8m16s
nginx-deployment-5fffc966ff-52knq   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-52knq   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-52knq   0/1     ContainerCreating   0          0s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m16s
nginx-deployment-5fffc966ff-52knq   1/1     Running             0          1s
nginx-deployment-59994fb97c-g789c   1/1     Terminating         0          8m18s
nginx-deployment-5fffc966ff-jwmtt   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-jwmtt   0/1     Pending             0          0s
nginx-deployment-5fffc966ff-jwmtt   0/1     ContainerCreating   0          0s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-5j4fv   0/1     Terminating         0          8m17s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m18s
nginx-deployment-5fffc966ff-jwmtt   1/1     Running             0          1s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-g789c   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   1/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m19s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s
nginx-deployment-59994fb97c-nddlf   0/1     Terminating         0          8m20s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Belirtilen &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; değeri pod özelinde tanımlanmaktadır. Default değeri &lt;strong&gt;30s&lt;/strong&gt;'dir.&lt;/p&gt;

&lt;p&gt;Sidecar container'lara &lt;code&gt;SIGTERM&lt;/code&gt; sinyali gönderilmeden önce aynı pod içerisinde bulunan main container terminate edilip sonrasında sidecar container'lara tanımlandıkları sıranın tersi yönde &lt;code&gt;SIGTERM&lt;/code&gt; sinyali gönderilmektedir. Bu şekilde pod içerisinde sidecar container'a ihtiyaç kalmadığı durumda sonlandırılması sağlanmış olur&lt;/p&gt;

&lt;p&gt;Deployment içerisinde yer alan nginx uygulaması &lt;code&gt;SIGTERM&lt;/code&gt; sinyali aldığında açık connection'lar da dahil olmak üzere hızlıca process'i sonlandırır. Bu sebeple &lt;strong&gt;graceful shutdown&lt;/strong&gt; edilebilmesi için &lt;code&gt;SIGTERM&lt;/code&gt; sinyali geldiğinde track edilmeli ve &lt;code&gt;SIGQUIT&lt;/code&gt; sinyali verilmelidir. Nginx tarafında graceful shutdown yapılabilmesi için &lt;code&gt;SIGQUIT&lt;/code&gt; sinyali beklemektedir. Bunun için bash ile operasyon gerçekleştirilebilir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  .Net Host Model
&lt;/h2&gt;

&lt;p&gt;.Net Core framework ile dünyamıza gelen yeni &lt;code&gt;Host&lt;/code&gt; model yaklaşımı ile birlikte &lt;code&gt;Host&lt;/code&gt; objesi içerisinde uygulamanın ihtiyaç duyacağı kaynaklarının ve hayat döngüsünde olan fonksiyonlarının sarmalanması amaçlanmıştır. Belirtilen yapı ile de aynı zamanda default template'ler içerisinde yer alan bir çok boilerplate kodun da çıkarılması amaçlanmıştır. Bu obje üzerinde belli düzenlemeler yapılarak uygulama türüne göre aşağıda belirtilen fonksiyonaliteler default'da hazır gelmekte ve ihtiyaca binaen düzenlenebilmektedir;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependency Injection (DI) yapısı&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;App Shutdown süreci&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService&lt;/code&gt; implementasyonu&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Belirtilen &lt;code&gt;Host&lt;/code&gt; model yaklaşımı .Net framework versiyonları değiştikçe uygulama templatelerinde de farklılık göstermiştir. Aşağıda 3 farklı yaklaşım .Net versiyonları ile belirtilmiştir;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.NET Core 2.x&lt;/code&gt; sürümü ile birlikte &lt;code&gt;WebHost&lt;/code&gt; sınıfı altında yer alan &lt;code&gt;CreateDefaultBuilder&lt;/code&gt; method'u ile &lt;code&gt;Host&lt;/code&gt; model oluşturulmakta ve configüre edilmektedir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateWebHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IWebHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateWebHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;WebHost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıda &lt;code&gt;dotnet&lt;/code&gt; cli'ı ile belirtilen sürümde bir &lt;code&gt;ASP.Net Core&lt;/code&gt; projesi sıfırdan oluşturulduğunda &lt;code&gt;Program.cs&lt;/code&gt; dosyasında yer alan kod bloğu aktarılmıştır.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.NET Core 3.x&lt;/code&gt; ile &lt;code&gt;.NET 5&lt;/code&gt; versiyonları arasında &lt;code&gt;Host&lt;/code&gt; model yaklaşımında büyük değişiklik sağlanarak web projelerinin de generic &lt;code&gt;Host&lt;/code&gt; üzerinden oluşturulması için yaklaşım değiştirilmiştir. Bu değişim ile beraber aynı base kod kullanılarak &lt;code&gt;Host&lt;/code&gt; model üzerinden worker servisler, gRPC servisler, Windows servisler geliştirilebilir hale gelmiştir. Bu yöntem ile &lt;code&gt;IWebHostBuilder&lt;/code&gt; interface'i yerine &lt;code&gt;IHostBuilder&lt;/code&gt; interface'i üzerinde &lt;code&gt;Host&lt;/code&gt; model kurgulanmıştır.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureWebHostDefaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;webBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıda &lt;code&gt;.NET Core 3.x&lt;/code&gt; ile &lt;code&gt;.NET 5&lt;/code&gt; versiyonları arasında &lt;code&gt;dotnet&lt;/code&gt; cli ile sıfırdan oluşturulan &lt;code&gt;ASP.NET&lt;/code&gt; projesinin &lt;code&gt;Program.cs&lt;/code&gt; dosyasında yer alan kod bloğu paylaşılmıştır.&lt;/p&gt;

&lt;p&gt;Yukarıda paylaşılan iki yaklaşımda da &lt;code&gt;Startup&lt;/code&gt; sınıfının ayrılmaz bir şekilde web uygulamasına bağımlı olduğu gözden kaçırılmamalıdır fakat &lt;code&gt;IHostBuilder&lt;/code&gt; interface'i üzerinde konumlanan &lt;code&gt;Host&lt;/code&gt; model yaklaşımında web uygulamaları dışında farklı uygulamalarında geliştirilebileceğini aktarmıştık. Bu uygulamalarda &lt;code&gt;Startup&lt;/code&gt; sınıfına ihtiyaç bulunmayabilmektedir. (Örneğin &lt;code&gt;Configure&lt;/code&gt; adlı method uygulama içerisinde yer alan middleware'leri ayarlamak için kullanılmaktadır fakat worker service'ler için böyle bir configürasyona ihtiyaç bulunmamaktadır.) Bu sebeple framework'ü geliştirenler &lt;code&gt;ConfigureWebHostDefaults&lt;/code&gt; extension method'u ile bu durumu aşmışlardır.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.NET 6&lt;/code&gt; ile birlikte iki farklı dosya üzerinde yapılan configürasyonlar (&lt;code&gt;Startup.cs&lt;/code&gt; ve &lt;code&gt;Program.cs&lt;/code&gt;) tek dosya üzerinde birleştirilmiş ve &lt;code&gt;Host&lt;/code&gt; model &lt;code&gt;IHostApplicationBuilder&lt;/code&gt; sınıfı üzerine konumlandırılmıştır. &lt;code&gt;dotnet&lt;/code&gt; ekibi Migration notlarında bu yaklaşımı &lt;code&gt;Minimal Hosting&lt;/code&gt; olarak ifade etmişler ve &lt;code&gt;Minimal API&lt;/code&gt;'ı default web template olarak konumlandırmışlardır. &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-8.0&amp;amp;tabs=visual-studio#new-hosting-model" rel="noopener noreferrer"&gt;ref&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Example.Processor.Api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSwaggerGen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwagger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSwaggerUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıda &lt;code&gt;.NET 6&lt;/code&gt; versiyonu ile &lt;code&gt;dotnet&lt;/code&gt; cli'da sıfırdan oluşturulan &lt;code&gt;ASP.NET&lt;/code&gt; projesinin &lt;code&gt;Program.cs&lt;/code&gt; dosyasında yer alan kod bloğu paylaşılmıştır. Görüldüğü gibi bütün configürasyonlar tek bir dosya içerisinde konumlandırılıyor ve &lt;code&gt;Startup&lt;/code&gt; sınıfı bulunmuyor. Ek olarak bu yaklaşım ile beraber &lt;code&gt;Host.CreateDefaultBuilder&lt;/code&gt; method'u yerine &lt;code&gt;WebApplication.CreateBuilder&lt;/code&gt; method'u kullanmakta ve &lt;code&gt;IHostBuilder&lt;/code&gt; yerine &lt;code&gt;IHostApplicationBuilder&lt;/code&gt; dönülmektedir. &lt;code&gt;.NET&lt;/code&gt; geliştiricileri &lt;code&gt;.NET 7&lt;/code&gt; ile birlikte de &lt;code&gt;Host.CreateApplicationBuilder&lt;/code&gt; method'u tanıtmış ve yaklaşım olarak Web ve Non-Web uygulamalar için &lt;code&gt;Host&lt;/code&gt; model yaklaşımını aşağıda belirtildiği gibi sürdürülmesini tavsiye etmiştir. Bu konuda David Fowler'n &lt;a href="https://github.com/dotnet/runtime/discussions/81090#discussioncomment-4784551" rel="noopener noreferrer"&gt;yorumuna&lt;/a&gt; ulaşabilirsiniz.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Application'lar için örnek yaklaşım
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;BindConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyConfig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyWorker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Non-Web Application'lar için örnek yaklaşım
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateApplicationBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;BindConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyConfig"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyWorker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;WebApplication&lt;/code&gt; sınıfı web uygulaması için gerekli olan 3 interface'i implemente etmiştir;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IHost&lt;/code&gt; - Host'un başlatılması ve sonlandırılmasından sorumludur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IApplicationBuilder&lt;/code&gt; - Middleware pipeline'ları oluşturmak için kullanılır&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IEndpointRouteBuilder&lt;/code&gt; - Endpoint'ler için kullanılır&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aynı zamanda aşağıda belirtilen 3 service'i de &lt;code&gt;HostApplicationBuilder.Build()&lt;/code&gt; methodu çağrıldığı an DI container'a otomatik olarak register edilmektedir;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime&lt;/code&gt; - Herhangi bir sınıfa inject edilerek graceful shutdown ve başlatma sonrası operasyonları handle etmek için kullanılır&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostLifetime&lt;/code&gt; - Uygulamanın ne zaman başlayacağını ya da sonlanacağını kontrol eder.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostEnvironment&lt;/code&gt; - Uygulama ismi, Root Path, Environment Name vb. bilgiler almak için kullanılır. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;IHostApplicationLifetime&lt;/code&gt;, &lt;code&gt;IHostLifecycleService&lt;/code&gt;, &lt;code&gt;IHostedService&lt;/code&gt; Interface'lerinin İncelenmesi
&lt;/h2&gt;

&lt;p&gt;Belirtilen interface'leri ve bu interface'ler ile implemente edilen Lifetime event'lerini kavrayabilmek için aşağıda örnek bir &lt;code&gt;IHostedService&lt;/code&gt; implementasyonu aktarılmıştır;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;BackgroundService&lt;/code&gt; bir &lt;code&gt;abstract&lt;/code&gt; sınıftır ve background service'ler oluşturmak için kullanılır. &lt;code&gt;IHostedService&lt;/code&gt; ise &lt;code&gt;BackgroundService&lt;/code&gt; tarafından implemente edilen bir interface'dir. İçerisinde &lt;code&gt;Host&lt;/code&gt;'u yönetmek için method'lar barındırır. &lt;code&gt;Worker Service&lt;/code&gt; ise background service oluşturmak için bir template'dir. &lt;code&gt;dotnet new worker&lt;/code&gt; command'ı ile oluşturulur. &lt;/p&gt;

&lt;p&gt;Sadece &lt;code&gt;IHostedService&lt;/code&gt; implemente edilerek de background processing gerçekleştirilebilecek service'ler oluşturmak mümkündür fakat burada uygulamanın lifetime event'leri dinlenerek service'de graceful shutdown operasyonunun manuel implemente edilmesi gerekmektedir. &lt;code&gt;BackgroundService&lt;/code&gt;'de ise override edilen &lt;code&gt;ExecuteAsync&lt;/code&gt; method'na parametre olarak geçilen &lt;code&gt;CancellationToken&lt;/code&gt; yapılan operasyonlarda kontrol edilerek graceful shutdown operasyonu daha rahat bir şekilde gerçekleştirilebilir.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHostedLifecycleService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStarted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStarted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStopping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStopping&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStopped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnStopped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedService StartAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartedAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StartedAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StartingAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StopAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedService StopAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StoppedAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StoppedAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StoppingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostedLifecycleService StoppingAsync has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStarted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStarted has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStopped&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStopped has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnStopping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"IHostApplicationLifetime OnStopping has been called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bir background processing yapmak istediğim için &lt;code&gt;IHostedService&lt;/code&gt;'i implemente etmek gerektiğini iletmiştim. Burada &lt;code&gt;IHostedLifecycleService&lt;/code&gt; kullanmamın sebebi ise zaten bu interface'in &lt;code&gt;IHostedService&lt;/code&gt;'den kalıtım alıyor olmasıdır. Bu interface &lt;code&gt;.Net 8&lt;/code&gt; ile beraber getirildi. Bu sayede uygulamanın lifecycle döngüsüne daha rahat bir şekilde müdehale edebiliyor ve operasyon gerçekleştirebiliyoruz. İçerisinde 4 yeni method barındırıyor. Bunlar &lt;code&gt;StartingAsync&lt;/code&gt;, &lt;code&gt;StartedAsync&lt;/code&gt;, &lt;code&gt;StoppingAsync&lt;/code&gt; ve &lt;code&gt;StoppedAsync&lt;/code&gt; 'dir. Ek olarak &lt;code&gt;IHostApplicationLifetime&lt;/code&gt;'ın host build edilirken otomatik olarak register edildiğini iletmiştim. Bu sınıf altında bulunan 3 property aslında birer &lt;code&gt;CancellationToken&lt;/code&gt; ve Host'un lifetime'na göre tetikleniyorlar. Bu token'lara yukarıda ilettiğim şekilde register oluyorum.&lt;/p&gt;

&lt;p&gt;Yukarıda oluşturduğum &lt;code&gt;Hosted Service&lt;/code&gt;'i DI container'a aşağıda ilettiğim gibi register ediyorum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Example.Worker.Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateApplicationBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;


&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uygulamayı çalıştırıp ve ardından da &lt;code&gt;CTRL+C&lt;/code&gt; yaparak sonlandırdığımda aşağıdaki console çıktısı karşıma çıkıyor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StartingAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedService StartAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StartedAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStarted has been called
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:&lt;span class="se"&gt;\C&lt;/span&gt;odes&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStopping has been called
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StoppingAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedService StopAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostedLifecycleService StoppedAsync has been called
info: Example.Worker.Service.Worker[0]
      IHostApplicationLifetime OnStopped has been called

C:&lt;span class="se"&gt;\C&lt;/span&gt;odes&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;ebug&lt;span class="se"&gt;\n&lt;/span&gt;et8.0&lt;span class="se"&gt;\E&lt;/span&gt;xample.Worker.Service.exe &lt;span class="o"&gt;(&lt;/span&gt;process 35456&lt;span class="o"&gt;)&lt;/span&gt; exited with code 0.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Çıktıyı kontrol ettiğimizde sıranın aşağıdaki gibi olduğu görünmektedir;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StartingAsync&lt;/code&gt; çağrıldığı görülmüştür. Uygulama başlamadan önce çağrılan method'dur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService.StartAsync&lt;/code&gt; çağrılmıştır.  Host'un service'i başlatmaya hazır olduğunda çağrılan method'dur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StartedAsync&lt;/code&gt; çağrılmıştır. &lt;code&gt;IHostedService.StartAsync&lt;/code&gt; hemen sonra yani başlatma işlemi bittikten sonra çağrılır.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStarted&lt;/code&gt; Host'un tamamen başladığını ifade eder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Uygulama stop edildikten sonra aşağıdaki sıralamanın gerçekleştiği gözlemlenmiştir;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStopping&lt;/code&gt; uygulama graceful shutdown operasyonu gerçekleştirmeye başladığında tetiklenir.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StoppingAsync&lt;/code&gt; uygulama sonlandırılmaya başlanırken öncesinde çağrılır. &lt;code&gt;IHostedService.StopAsync&lt;/code&gt; operasyonunun hemen öncesinde yer alır.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedService.StopAsync&lt;/code&gt; uygulama graceful shutdown operasyonu gerçekleştirir.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostedLifecycleService.StoppedAsync&lt;/code&gt; uygulamanın graceful shutdown operasyonunu tamamlandığında çağrılır.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHostApplicationLifetime.ApplicationStopped&lt;/code&gt; uygulamanın graceful shutdown operasyonunu tamamlandığını ifade eder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Burada yer alan diğer önemli bir nokta ise uygulamanın &lt;code&gt;CTRL+C&lt;/code&gt; kombinasyonu ile sonlandırılıyor olmasıdır. Host default'da otomatik olarak &lt;code&gt;IHostLifetime&lt;/code&gt; interface'ni &lt;code&gt;ConsoleLifetime&lt;/code&gt; olarak register etmiştir. Web ve Background Service için de bu geçerlidir. &lt;code&gt;IHostLifetime&lt;/code&gt; interface'de uygulamanın ne zaman başlayacağını ve sonlanacağını kontrol ettiğini ifade etmiştim. &lt;code&gt;ConsoleLifetime&lt;/code&gt; içerisinde de yukarıda ilettiğim kombinasyon ile tuşlara basılarak uygulamaya &lt;code&gt;SIGINT&lt;/code&gt; sinyali vermiş oluyoruz. Kubernetes'de ilk bölümde anlattığım nedenlerden dolayı pod'un sonlandırılması için container'a &lt;code&gt;SIGTERM&lt;/code&gt; sinyali göndermektedir. Bu belirtilen sinyaller neticesinde graceful shutdown operasyonu gerçekleştirilir.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;.Net 6&lt;/code&gt; öncesinde posix signal'ler desteklenip signal tipine göre handle edilmiyordu. &lt;code&gt;.Net 6&lt;/code&gt; sonrası &lt;code&gt;ConsoleLifetime&lt;/code&gt;, &lt;code&gt;SIGINT&lt;/code&gt;, &lt;code&gt;SIGQUIT&lt;/code&gt;, &lt;code&gt;SIGTERM&lt;/code&gt; sinyallerini dinleyerek graceful shutdown operasyonunu gerçekleştirebilir hale geldi.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Host'un Shutdown Süreci
&lt;/h2&gt;

&lt;p&gt;Default'da &lt;code&gt;.Net 6&lt;/code&gt; ve sonrasında generic host'un &lt;code&gt;IHostLifetime&lt;/code&gt; interface'ni &lt;code&gt;ConsoleLifetime&lt;/code&gt; olarak implemente edildiğini aktarmıştım. Host'un da gracefully olarak sonlandırılması için &lt;code&gt;ConsoleLifetime&lt;/code&gt;'a aşağıdaki sinyaller gönderilerek bu operasyon gerçekleştirilebilir;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SIGINT&lt;/code&gt; ya da &lt;code&gt;CTRL+C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SIGQUIT&lt;/code&gt; ya da &lt;code&gt;CTRL+BREAK&lt;/code&gt; (Windows)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SIGTERM&lt;/code&gt; (Kubernetes tarafında pod'un sonlandırılması için container'a gönderilen sinyal &lt;code&gt;docker stop&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;.Net 6&lt;/code&gt; öncesinde &lt;code&gt;SIGTERM&lt;/code&gt; sinyali geldiğinde gracefully olarak shut down operasyonu gerçekleştirilemiyordu. Bu durum ile alakalı work around olarak &lt;code&gt;ConsoleLifetime&lt;/code&gt; tarafında, &lt;code&gt;System.AppDomain.ProcessExit&lt;/code&gt; event'ni dinlenerek &lt;code&gt;ProcessExit&lt;/code&gt; thread'i stop edilir ve host'un durması beklenirdi.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdytobe7u5lsi1j4tzf8x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdytobe7u5lsi1j4tzf8x.PNG" alt="Host shut down süreci" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yukarıda gracefully shut down operasyonu sırasında gerçekleşen süreç aktarılmıştır. Sırasıyla;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kubernetes'den ya da kullanıcıdan &lt;code&gt;SIGTERM&lt;/code&gt; sinyali geliyor. Bu sinyal neticesinde de &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; altında bulunan &lt;code&gt;StopApplication()&lt;/code&gt; method'u tetikleniyor ve &lt;code&gt;ApplicationStopping&lt;/code&gt; event'i fırlatılıyor. Öncesinde &lt;code&gt;IHost.WaitForShutdownAsync&lt;/code&gt; methodu bu belirtilen event'i dinliyor ve event tetiklendiğinden dolayı &lt;code&gt;Main&lt;/code&gt; işletimi ublock'luyor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IHost.StopAsync()&lt;/code&gt; method'u tetikleniyor ve bu method içerisinden de &lt;code&gt;IHostedService.StopAsync()&lt;/code&gt; tetiklenerek her bir hosted service'in stop edilmesini sağlayıp ardından da stop edildiğine dair event'leri fırlatıyor.&lt;/li&gt;
&lt;li&gt;Son olarak &lt;code&gt;IHost.WaitForShutdownAsync&lt;/code&gt; tamamlanıyor ve uygulamanın işletmesi gereken code block'ları yürütülüp gracefully shut-down operasyonu gerçekleştiriliyor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Host tarafında configürasyon gerçekleştirilerek &lt;code&gt;ShutdownTimeout&lt;/code&gt; ayarlanması mümkündür. Bu değer &lt;code&gt;IHost.StopAsync()&lt;/code&gt; method'u için belirtilen timeout süresidir ve default değeri 30 saniyedir.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Kind&lt;/code&gt; İle Kubernetes Cluster'ın Ayağa Kaldırılması
&lt;/h2&gt;

&lt;p&gt;OpenSource olarak geliştirilen &lt;code&gt;Kind&lt;/code&gt; ürünü ile local'de hızlı bir şekilde Kubernetes cluster'ları ayağa kaldırmak mümkündür. Bu makale için de geliştirilen uygulamanın yayınlanacağı Kubernetes cluster'ı &lt;code&gt;Kind&lt;/code&gt; ürünü ile oluşturulmuştur. &lt;/p&gt;

&lt;p&gt;Öncelikle &lt;code&gt;Kind&lt;/code&gt; cli'ı local'e aşağıda belirtilen komut ile yüklüyoruz;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl.exe &lt;span class="nt"&gt;-Lo&lt;/span&gt; kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.23.0/kind-windows-amd64
Move-Item .&lt;span class="se"&gt;\k&lt;/span&gt;ind-windows-amd64.exe c:&lt;span class="se"&gt;\s&lt;/span&gt;ome-dir-in-your-PATH&lt;span class="se"&gt;\k&lt;/span&gt;ind.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Her seferinde cli'ın olduğu dizine gidip işlem yapmamak için belirttiğiniz dizini &lt;code&gt;Path&lt;/code&gt; Environment Variable'ı içerisine eklemeyi unutmayınız.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ardından 3 worker node içeren bir cluster ayağa kaldırmak için aşağıda belirtilen yaml dosyası oluşturulur.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cluster&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kind.x-k8s.io/v1alpha4&lt;/span&gt;
&lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;control-plane&lt;/span&gt;
  &lt;span class="na"&gt;kubeadmConfigPatches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;InitConfiguration&lt;/span&gt;
    &lt;span class="na"&gt;nodeRegistration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kubeletExtraArgs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ingress-ready=true"&lt;/span&gt;    
  &lt;span class="na"&gt;extraPortMappings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8081&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
    &lt;span class="na"&gt;hostPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8443&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıda ilettiğim yaml dosyasını incelediğimizde; her bir node rolü için tanım olduğu ve local'de 8081 ve 8443 port'larına gönderilen isteklerin cluster üzerinde kuracağımız ingress controller'a forward etmek için tanımlandığı gözlenmektedir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind create cluster &lt;span class="nt"&gt;--config&lt;/span&gt; .&lt;span class="se"&gt;\k&lt;/span&gt;ind-cluster.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıda ilettiğim komut ile cluster'ı ayağa kaldırıyorum&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind create cluster &lt;span class="nt"&gt;--config&lt;/span&gt; .&lt;span class="se"&gt;\k&lt;/span&gt;ind-config&lt;span class="se"&gt;\k&lt;/span&gt;ind-cluster.yaml
Creating cluster &lt;span class="s2"&gt;"kind"&lt;/span&gt; ...
 ✓ Ensuring node image &lt;span class="o"&gt;(&lt;/span&gt;kindest/node:v1.30.0&lt;span class="o"&gt;)&lt;/span&gt; 🖼
 ✓ Preparing nodes 📦 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to &lt;span class="s2"&gt;"kind-kind"&lt;/span&gt;
You can now use your cluster with:

kubectl cluster-info &lt;span class="nt"&gt;--context&lt;/span&gt; kind-kind

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ardından aşağıda ilettiğim komut ile ingress controller'ı kuruyorum;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Kind&lt;/code&gt;'a özel hazırlanan bu manifest dosyası içerisinde bazı patch'ler ve forward operasyonu için ayarlamar mevcuttur.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yukarıdaki işlemler tamamlandıktan sonra cluster'ın kullanıma hazır hale gelmiş bulunuyor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web API'ın Oluşturulması
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;.Net 8&lt;/code&gt; ile bir web api projesi oluşturduğumuzda karşıma aşağıda belirtildiği gibi bir &lt;code&gt;Program.cs&lt;/code&gt; dosyası çıkıyor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;İhtiyaç olmayan service'ler kaldırılmıştır&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Controller ve Action isimlerini aşağıda belirtildiği gibi düzenliyorum. Bir önceki bölümde &lt;code&gt;ShutdownTimeout&lt;/code&gt;'un default değerinin 30 saniye olduğu belirtmiştim. Operasyon hata alması için action içerisinde 35 saniye bir bekleme gerçekleştirip response dönecek şekilde düzenleme yapıyorum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PingPongController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PingPongController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ping"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pong"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Kind&lt;/code&gt; ile oluşturduğumuz Kubernetes cluster'a deployment'ın gerçekleştirilebilmesi için aşağıda ilettiğim deployment manifest'i oluşturuyorum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi:0.1&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.5"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;.Net 8&lt;/code&gt; ile birlikte yayınlanan image'larda uygulamanın çalıştığı default port &lt;code&gt;80&lt;/code&gt;'den &lt;code&gt;8080&lt;/code&gt;'e değiştirilmiştir. Bu sebeple manifest'de port bilgisi &lt;code&gt;8080&lt;/code&gt; olarak ayarlanmıştır. &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8/containers" rel="noopener noreferrer"&gt;İlgili doc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;'ı aşağıda belirttiğim gibi basitçe oluşturuyorum;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/aspnet:8.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./Publish .&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["dotnet", "Example.Ping.Api.dll"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Service'in Deploy Edilmesi ve Testin Gerçekleştirilmesi
&lt;/h2&gt;

&lt;p&gt;Öncelikle uygulamamı &lt;code&gt;Publish&lt;/code&gt; dizini altında publish ediyorum&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet publish &lt;span class="nt"&gt;-o&lt;/span&gt; ./Publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ardından image'ı build ediyorum;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; pingapi:0.1 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cluster üzerinde deployment manifest'i apply etmeden önce etiketlediğim image'ı aşağıda belirtilen komut ile her bir node üzerine aktarıyorum, diğer türlü bir image repository'e bu image'ı atmam ve cluster tarafından pull etmem gibi bir ihtiyaç oluşacaktı. Kind burda bize kolaylık sağlıyor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind load docker-image pingapi:0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind load docker-image pingapi:0.1
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker3"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-control-plane"&lt;/span&gt;, loading...
Image: &lt;span class="s2"&gt;"pingapi:0.1"&lt;/span&gt; with ID &lt;span class="s2"&gt;"sha256:2e5cfec8e475ed2d2ccfd0ae9753a7f5feda0e01de0081718ab678203d25edcf"&lt;/span&gt; not yet present on node &lt;span class="s2"&gt;"kind-worker2"&lt;/span&gt;, loading...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deployment'ı aşağıda belirttiğim komutu ile apply ediyorum;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; .&lt;span class="se"&gt;\K&lt;/span&gt;ubernetes&lt;span class="se"&gt;\d&lt;/span&gt;eployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Container'ın &lt;code&gt;8080&lt;/code&gt; portunu aşağıda belirttiğim komut ile forward ediyorum;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward deployment/pingapi-deployment &lt;span class="nt"&gt;-n&lt;/span&gt; default 8080:8080
Forwarding from 127.0.0.1:8080 -&amp;gt; 8080
Forwarding from &lt;span class="o"&gt;[&lt;/span&gt;::1]:8080 -&amp;gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Artık teste başlayabiliriz, öncelikle &lt;code&gt;httpstat http://localhost:8080/pingpong/ping&lt;/code&gt; komutu ile istek atıyorum ardından da pod'u delete etmek için &lt;code&gt;kubectl delete pod/pingapi-deployment-5c78cbdfc-bfd9b&lt;/code&gt; komutunu çalıştırıyorum. Beklediğimiz üzere hem Kubernetes tarafında &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; süresinin deployment manifest'de belirtmediğimiz için default değer olan 30 saniye olmasından hem de &lt;code&gt;.Net&lt;/code&gt; tarafında &lt;code&gt;Host&lt;/code&gt; objesinin &lt;code&gt;ShutdownTimeout&lt;/code&gt; belirtmediğimiz için default değer olan 30 saniye olmasından dolayı attığımız istek için hatada da göründüğü üzere bağlantının sonlandırıldığı görünmektedir.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yeni bir image versiyonu ile deploy çıkılarak da benzer senaryo test edilebilir buradaki amaç pod'a &lt;code&gt;SIGTERM&lt;/code&gt; sinyali göndermek olduğu için pod silme operasyonu ile test işlemi gerçekleştirilmiştir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl374dafbokgwbegg5ef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffl374dafbokgwbegg5ef.png" alt="Terminal görünümü" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bu durumu aşmak için öncelikle uygulama tarafında &lt;code&gt;Host&lt;/code&gt;'u configüre ediyorum ardından da deployment manifest altında &lt;code&gt;spec.terminationGracePeriodSeconds&lt;/code&gt; adlı değeri güncelliyorum.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Program.cs&lt;/code&gt; dosyasının yeni hali aşağıda belirtildiği gibi oluşturulmuştur;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Example.Ping.Api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHostOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShutdownTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;

        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;deployment.yaml&lt;/code&gt; dosyasının da yeni hali aşağıdaki gibidir;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi-deployment&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pingapi:0.2&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.5"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;150Mi"&lt;/span&gt;
      &lt;span class="na"&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;deployment manifest içerisinde yeni build ettiğimiz image'ı &lt;code&gt;pingapi:0.2&lt;/code&gt; olarak update ediyoruz.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Belirtilen günceleme yapıldıktan sonra testi tekrar uyguladığımızda bir problem ile karşılaşılmadığı gözlemlenmektedir;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqawvrsv01mc2j03gy8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqawvrsv01mc2j03gy8m.png" alt="Terminal logları" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes Ingress  ile Control Plane Arasındaki Gecikme
&lt;/h2&gt;

&lt;p&gt;Yukarıda yaptığımız ayarlamalara rağmen yoğun kullanılan service'ler özelinde &lt;code&gt;RollingUpdate&lt;/code&gt; aşamasında birkaç istek özelinde de olsa hata alma ihtimalleri bulunmaktadır. Bunun sebebi ingress ve control plane arasındaki gecikmeden kaynaklanmaktadır.&lt;/p&gt;

&lt;p&gt;Bunun sebebi Kubernetes içerisinde ingress ve Kubernetes control plane farklı entity'lerdir ve bağımsız olarak operasyonlarını gerçekleştirmektedir. Kubernetes bir pod'un sonlandırmak istediğinde control plane sonlandırılacak pod'ları Service'den kaldırır ve ingress'de bundan haberdar olur ve sonlandırlacak pod'lara request'leri yönlendirmeyi sonlandırır. Bu iki operasyon arasında bir gecikme mevcuttur çünkü ingress belli aralıklarla Service'lerde yapılan bu değişiklikleri kendi tarafında güncellemektedir. Bu durum da &lt;code&gt;terminating&lt;/code&gt; status içerisinde bulunan pod'lara az bir request özelinde isteklerin iletilebilmesine sebep olmaktadır.&lt;/p&gt;

&lt;p&gt;.&lt;code&gt;.Net&lt;/code&gt; tarafında uygulama &lt;code&gt;IHost.StopAsync()&lt;/code&gt; çağrıldıktan sonra hali hazırda açık olan connection'lar üzerinden yeni requestlerin gelmesi ve aynı zamanda da yeni bir connection açılmasına izin vermez. Bu sebeple de bu aradaki gecikme &lt;code&gt;IHost.StopAsync()&lt;/code&gt; işlemi başladığında yeni isteklerin gelebileceği anlamına gelmektedir. Bu durum istek atan taraf için hata almasına neden olacaktır.&lt;/p&gt;

&lt;p&gt;Bu duruma bir çözüm olarak aşağıda ileteceğim yöntem dotnet ekibi tarafından tavsiye edilmiştir. &lt;a href="https://github.com/dotnet/dotnet-docker/blob/main/samples/kubernetes/graceful-shutdown/graceful-shutdown.md#adding-a-shutdown-delay" rel="noopener noreferrer"&gt;ref&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Önceki bölümlerde &lt;code&gt;IHostLifetime&lt;/code&gt;'ın uygulamanın ne zaman başlayacağını ya da durdurulacağını kontrol ettiği aktarılmıştı. Bu sebeple öncelikle yeni bir &lt;code&gt;IHostLifetime&lt;/code&gt; implementasyonu gerçekleştiriyoruz.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.InteropServices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DelayedShutdownHostLifetime&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHostLifetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;_delay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;_disposables&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DelayedShutdownHostLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_delay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StopAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;WaitForStartAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_disposables&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGQUIT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;PosixSignalRegistration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HandleSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PosixSignalContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cancel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delay&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ContinueWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_applicationLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StopApplication&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;disposable&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_disposables&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="n"&gt;Enumerable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDisposable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;())&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yapılan işlem incelendiğinde uygulama en başta ayağa kalkarken belli &lt;code&gt;POSIX&lt;/code&gt; sinyalleri için registration operasyonu gerçekleştirilmiştir. Bu sayede uygulama tarafına bu sinyallerden biri geldiğinde &lt;code&gt;IHostApplicationLifetime.StopApplication()&lt;/code&gt; operasyonunu başlatmadan önce &lt;code&gt;Task.Delay&lt;/code&gt; ile bir gecikme tanımlanmıştır. Bu gecikme sayesinde gracefully shut-down işlemi belirtilen sinyaller geldiği an başlamayacak ve belirtilen gecikme zarfında da pod'a gelen yeni istekler karşılanabilecektir.&lt;/p&gt;

&lt;p&gt;Son aşama olarak &lt;code&gt;Program.cs&lt;/code&gt; altında yeni oluşturduğum &lt;code&gt;IHostLifetime&lt;/code&gt; implementasyonunu register ediyorum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHostOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShutdownTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEndpointsApiExplorer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IHostLifetime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DelayedShutdownHostLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IHostApplicationLifetime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(),&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;HostApplicationBuilder.Build()&lt;/code&gt; method'u içerisinde &lt;code&gt;IHostApplicationLifetime&lt;/code&gt; ve &lt;code&gt;IHostLifetime&lt;/code&gt; 'ın service olarak register edildiği aktarılmıştı. Burada &lt;code&gt;IHostLifetime&lt;/code&gt; tekrar register edilerek belirtilen &lt;code&gt;DelayedShutdownHostLifetime&lt;/code&gt; implementasyonu ile kullanılması sağlanmıştır.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Son yapılan işlemle beraber Kubernetes tarafında kesintisiz bir deployment işlemi sağlanmış bulunmaktadır. Okuduğunuz için teşekkürler :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Referanslar
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/workers" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/core/extensions/workers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#host-shutdown" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host?tabs=appbuilder#host-shutdown&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/webapplication?view=aspnetcore-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/webapplication?view=aspnetcore-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostlifetime?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostlifetime?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-6.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice?view=net-6.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime?view=net-8.0" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime?view=net-8.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.sebastian-daschner.com/entries/zero-downtime-updates-kubernetes" rel="noopener noreferrer"&gt;https://blog.sebastian-daschner.com/entries/zero-downtime-updates-kubernetes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-8.0#ihostlifetime" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-8.0#ihostlifetime&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>dotnet</category>
      <category>api</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
