<p>Our team wants to be able to run the Visual Studio debugger against deployed instances of our ASP.NET application to our internal Kubernetes cluster.  I need to figure out how to finish the puzzle but I'm not very familiar with Visual Studio 2019.</p>

<ul>
<li>The Docker image is compiled with the official .NET Core images and has /vsdbg populated with the latest version (which does not support --attach).</li>
<li>Visual Studio works with my Docker Desktop.</li>
<li>Kubectl is correctly configured.  I can use either the kubernetes cluster included with Docker Desktop or our internal kubernetes cluster for testing.</li>
<li>Azure is currently not an option.  I understand from the documentation that this is what Microsoft prefers me to do.</li>
</ul>

<p>How should I configure Visual Studio to be able to do this?    </p>

<p>Ok. Let’s get it started. First of all make sure that you have published your app in Debug mode! I prefer to use a new Docker feature multi-stage build for building my images so I would write something like this in the end of a build stage in Dockerfile:</p>

<pre><code>RUN dotnet publish -c Debug -o ./results
</code></pre>

<p>To push images to Minikube I do use the local container registry as described here. But you can do it as you usually do.
When you have your container up and running we can start hacking to it. I will use Powershell for that purpose but the same can be easily rewritten in any other terminal language. You can follow tutorial step by step and execute commands in your terminal one by one checking var’s values with echo command when necessary.
In your *.yml file you should have a selector described something like this:</p>

<pre><code>selector:
  matchLabels:
    app: mywebapp
</code></pre>

<p>Grab it and use to define a $Selector var in your Powershell terminal:</p>

<pre><code>$Selector = 'app=mywebapp'
</code></pre>

<p>You need to find a pod where your containerized application is running by its selector:</p>

<pre><code>$pod = kubectl get pods --selector=$Selector -o jsonpath='{.items[0].metadata.name}';
</code></pre>

<p>Assuming that you have only one container on the pod now you can execute commands on that container. By default container does not have vsdbg installed so go ahead and install it:</p>

<pre><code>kubectl exec $pod -i -- apt-get update;
kubectl exec $pod -i -- apt-get install -y unzip;
kubectl exec $pod -i -- curl -sSL https://aka.ms/getvsdbgsh -o '/root/getvsdbg.sh';
kubectl exec $pod -i -- bash /root/getvsdbg.sh -v latest -l /vsdbg;
</code></pre>

<p>Next, you need to find PID of your app inside of the container:</p>

<pre><code>$prid = kubectl exec $pod -i -- pidof -s dotnet;
</code></pre>

<p>Normally it is equal to 1 but it is better to make fewer assumptions.
That’s it. Now you can start a debugger:</p>

<pre><code>kubectl exec $pod -i -- /vsdbg/vsdbg --interpreter=mi --attach $prid;
</code></pre>

<p>Don’t forget to execute the following commands before you close the window otherwise your app will stuck forever:</p>

<pre><code>-target-detach
-gdb-exit
</code></pre>

<p>Let’s put everything together, create a reusable script and save it somewhere near to the roots since you can use it with all your ASP.NET Core projects:</p>

<pre><code>param(
    # the selector from your yml file
    #  selector:
    #    matchLabels:
    #      app: myweb
    # -Selector app=myweb
    [Parameter(Mandatory=$true)][string]$Selector
)

Write-Host '1. searching pod by selector:' $Selector '...';
$pod = kubectl get pods --selector=$Selector -o jsonpath='{.items[0].metadata.name}';

Write-Host '2. installing updates ...';
kubectl exec $pod -i -- apt-get update;

Write-Host '3. installing unzip ...';
kubectl exec $pod -i -- apt-get install -y --no-install-recommends unzip;

Write-Host '4. downloading getvsdbgsh ...';
kubectl exec $pod -i -- curl -sSL https://aka.ms/getvsdbgsh -o '/root/getvsdbg.sh';

Write-Host '5. installing vsdbg ...';
kubectl exec $pod -i -- bash /root/getvsdbg.sh -v latest -l /vsdbg;

$cmd = 'dotnet';
Write-Host '6. seaching for' $cmd 'process PID in pod:' $pod '...';
$prid = kubectl exec $pod -i -- pidof -s $cmd;

Write-Host '7. attaching debugger to process with PID:' $pid 'in pod:' $pod '...';
kubectl exec $pod -i -- /vsdbg/vsdbg --interpreter=mi --attach $prid;
</code></pre>

<p>Now you can execute this script like this when the terminal is running from the script folder:</p>

<pre><code>powershell -ExecutionPolicy Bypass -File kubedbg.ps1 -Selector app=mywebapp
</code></pre>

<p>But aren’t we supposed to be debugging from Visual Studio? Yes! Let’s go further and launch our terminal process from Visual Studio MIEngine.
Open your project in Visual Studio. Add new XML file with the following content and name it kubedbg.xml:</p>

<pre class="lang-xml prettyprint-override"><code>
&lt;PipeLaunchOptions xmlns="http://schemas.microsoft.com/vstudio/MDDDebuggerOptions/2014"
    PipePath="powershell" TargetArchitecture="x64" MIMode="clrdbg"
    PipeArguments="
      -ExecutionPolicy Bypass
      -File C:\kube\kubedbg.ps1
      -Selector app=mywebapp"&gt;
  &lt;LaunchCompleteCommand&gt;None&lt;/LaunchCompleteCommand&gt;
&lt;/PipeLaunchOptions&gt;
</code></pre>

<p>In <code>-File</code> parameter you need to specify absolute path to the script file we created before. Then press Ctrl+Alt+A to open Command Window and run the following command:
<code>
Debug.MIDebugLaunch /Executable:dotnet /OptionsFile:absolute_path_to_kubedbg_xml
</code>
This command will start the debugging process inside Visual Studio with all standard benefits you would expect. But don’t stop debugging any other way than by pressing Detach All from Debug menu!
Although this command is not very convenient to write all the time. Luckily in Visual Studio, you can specify aliases for commands with parameters. Eventually, you would need a new <code>kubedbg.xml</code> file for each project. With this in mind go ahead and create your first alias by typing the following command in Command Window:</p>

<pre><code>alias kubedbg.mywebapp Debug.MIDebugLaunch /Executable:dotnet 
/OptionsFile:absolute_path_to_kubedbg.xml
</code></pre>

<p>After that, you can start debugging just by executing kubedbg.mywebapp in Command Window. Even better you can run the same command from the Find toolbar Combobox but with prefix: <code>&gt;kubedbg.mywebapp.</code> That’s not difficult since there is a text completion too. You can read more about command aliases here.
Happy debugging!
PS: As a bonus absolutely the same way you can debug your app even when running inside a public cloud. When kubectl is assigned to a cluster in the public cloud it just works with the same script and making fewer assumptions paid back since inside real cluster process ID is not equal to 1</p>

<p>Original author: <a href="https://medium.com/@pavel.agarkov/debugging-asp-net-core-app-running-in-kubernetes-minikube-from-visual-studio-2017-on-windows-6671ddc23d93" rel="noreferrer">https://medium.com/@pavel.agarkov/debugging-asp-net-core-app-running-in-kubernetes-minikube-from-visual-studio-2017-on-windows-6671ddc23d93</a></p>
