<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kubernetes on Ash Tewari</title><link>https://www.tewari.info/category/kubernetes/</link><description>Recent content in Kubernetes on Ash Tewari</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sun, 25 Apr 2021 19:40:55 +0000</lastBuildDate><atom:link href="https://www.tewari.info/category/kubernetes/feed.xml" rel="self" type="application/rss+xml"/><item><title>Kusto Queries on AKS Clusters</title><link>https://www.tewari.info/2021/04/25/kusto-queries-on-aks-clusters/</link><pubDate>Sun, 25 Apr 2021 19:40:55 +0000</pubDate><guid>https://www.tewari.info/2021/04/25/kusto-queries-on-aks-clusters/</guid><description>&lt;p&gt;&lt;a class="link" href="https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/" target="_blank" rel="noopener"&#10; &gt;Kusto&lt;/a&gt; query language can be used to get &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/azure-monitor/containers/container-insights-log-search" target="_blank" rel="noopener"&#10; &gt;insights&lt;/a&gt; into Azure Kubernetes Service (&lt;a class="link" href="https://azure.microsoft.com/en-us/services/kubernetes-service/" target="_blank" rel="noopener"&#10; &gt;AKS&lt;/a&gt;) clusters. &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/azure-monitor/containers/container-insights-overview" target="_blank" rel="noopener"&#10; &gt;Container insights&lt;/a&gt; collects data from AKS clusters and forwards it to &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-tutorial" target="_blank" rel="noopener"&#10; &gt;Log Analytics&lt;/a&gt; workspace, if enabled for a cluster. This data is available for querying in the &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/azure-monitor/logs/data-platform-logs" target="_blank" rel="noopener"&#10; &gt;Azure Monitor&lt;/a&gt;. Here is an example of how you can query the pods not in running state in specific namespaces.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KubePodInventory&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where Namespace in (&amp;#34;dv&amp;#34;,&amp;#34;test&amp;#34;,&amp;#34;prod&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where ContainerStatus != &amp;#34;Running&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where ContainerStatusReason !in (&amp;#34;&amp;#34;, &amp;#34;Completed&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| distinct Namespace, Name&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-7.png"&#10;&#9;&#9;&#9;alt="Log Analytics query results listing pods not in running state by namespace"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;The following query includes the name of the AKS cluster and renders the output as a stacked bar chart.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;KubePodInventory&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where Namespace in (&amp;#34;dv&amp;#34;,&amp;#34;test&amp;#34;,&amp;#34;prod&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where ContainerStatus != &amp;#34;Running&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| where ContainerStatusReason !in (&amp;#34;&amp;#34;, &amp;#34;Completed&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| distinct ClusterName, Namespace, Name&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| summarize dcount(Name) by ClusterName, Namespace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| render columnchart kind=stacked100&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-8-1024x582.png"&#10;&#9;&#9;&#9;alt="Stacked column chart of non-running pods by AKS cluster and namespace"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;You can include multiple AKS clusters in the scope in which this query is executed by clicking on [Select scope] hyperlink.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-12.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-15.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;Create an Azure Dashboard panel with this output by clicking on [Pin to dashboard] button.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-13.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-11-1024x676.png"&#10;&#9;&#9;&#9;alt="Azure dashboard showing the pinned AKS pod status chart"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;You can also execute this Kusto query directly using powershell.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$workspaceName = &amp;#34;DefaultWorkspace-6637b095-xxxx-xxxx-xxxx-xxxxxxxxxxx-EUS&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$workspaceRG = &amp;#34;defaultresourcegroup-eus&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$WorkspaceID = (Get-AzOperationalInsightsWorkspace -Name $workspaceName -ResourceGroupName $workspaceRG).CustomerID&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$query = &amp;#39;KubePodInventory | where Namespace in (&amp;#34;dv&amp;#34;,&amp;#34;test&amp;#34;,&amp;#34;prod&amp;#34;) | where ContainerStatus != &amp;#34;Running&amp;#34; | where ContainerStatusReason !in (&amp;#34;&amp;#34;, &amp;#34;Completed&amp;#34;) | distinct ClusterName, Namespace, Name | summarize dcount(Name) by ClusterName, Namespace&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$result = Invoke-AzOperationalInsightsQuery -WorkspaceId $WorkspaceID -Query $query -Timespan (New-TimeSpan -days 1)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$result.results&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows you to include the results of your custom Kusto queries in any reports you might run using Azure Automation Runbooks.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-14-1024x392.png"&#10;&#9;&#9;&#9;alt="PowerShell session running the Kusto query with Invoke-AzOperationalInsightsQuery"&gt;&#10;&lt;/figure&gt;&#10;&#10;</description></item><item><title>AKS - Adding SSH Keys to VMSS Nodes</title><link>https://www.tewari.info/2021/03/27/aks-adding-ssh-keys-to-vmss-nodes/</link><pubDate>Sun, 28 Mar 2021 03:33:11 +0000</pubDate><guid>https://www.tewari.info/2021/03/27/aks-adding-ssh-keys-to-vmss-nodes/</guid><description>&lt;p&gt;You can connect to Azure Kubernetes Service (AKS) nodes using ssh. It is documented here: &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/aks/ssh" target="_blank" rel="noopener"&#10; &gt;Connect with SSH to Azure Kubernetes Service (AKS) cluster nodes for maintenance or troubleshooting&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;I needed to access nodes on the System node pool for collecting some logs recently, but the process documented above was not working for me. It turns out that there were two different issues, both related to adding your SSH keys to the nodes in a virtual machine scale set (VMSS).&lt;/p&gt;&#10;&lt;p&gt;This is the az cli command that adds the ssh keys to the VMSS:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az vmss extension set \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --resource-group $CLUSTER_RESOURCE_GROUP \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --vmss-name $SCALE_SET_NAME \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --name VMAccessForLinux \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --publisher Microsoft.OSTCExtensions \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version 1.4 \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --protected-settings &amp;#34;{\&amp;#34;username\&amp;#34;:\&amp;#34;azureuser\&amp;#34;, \&amp;#34;ssh_key\&amp;#34;:\&amp;#34;$(cat ~/.ssh/id_rsa.pub)\&amp;#34;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was running this command from powershell on a windows host. So, the first modification I needed was to escape the double quotes by doubling them. You can also &lt;a class="link" href="http://www.rlmueller.net/PowerShellEscape.htm" target="_blank" rel="noopener"&#10; &gt;use back ticks&lt;/a&gt; instead of doubling the double quotes.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az vmss extension set \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --resource-group $CLUSTER_RESOURCE_GROUP \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --vmss-name $SCALE_SET_NAME \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --name VMAccessForLinux \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --publisher Microsoft.OSTCExtensions \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version 1.4 \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --protected-settings &amp;#34;{\&amp;#34;&amp;#34;username\&amp;#34;&amp;#34;:\&amp;#34;&amp;#34;azureuser\&amp;#34;&amp;#34;, \&amp;#34;&amp;#34;ssh_key\&amp;#34;&amp;#34;:\&amp;#34;&amp;#34;$(cat ~/.ssh/id_rsa.pub)\&amp;#34;&amp;#34;}&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second issue was due to the fact that ssh-keygen adds a comment to the id_rsa.pub file. By default, it adds username@hostname as the comment at the end of the file . Normally, this comment wouldn&amp;rsquo;t cause any problems, but in this case it was causing an error - &amp;ldquo;Invalid escape sequence \uXXXX&amp;rdquo;.&lt;/p&gt;&#10;&lt;p&gt;The problem was that my domain user name starts with character &amp;lsquo;u&amp;rsquo; and &amp;ldquo;domain\userid1&amp;rdquo; was being interpreted as containing a unicode character &amp;ldquo;\useri&amp;rdquo; which is obviously not a valid unicode character. The workaround here is to either delete the comment from the id_rsa.pub file (it works just fine without it) or to override the default comment when generating the ssh key by specifying your own comment via -C command line option.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-keygen -C mycomment&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, there is another way to execute &lt;a class="link" href="https://docs.microsoft.com/en-us/cli/azure/vmss/extension?view=azure-cli-latest#az_vmss_extension_set" target="_blank" rel="noopener"&#10; &gt;az vmss extension set&lt;/a&gt; command to get around both of these issues by creating a json file and passing that as the value of &amp;ndash;protected-settings argument. Here is how -&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Create a json file, protected_settings.json, with the following content:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&amp;#34;username&amp;#34; : &amp;#34;azureuser&amp;#34;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&amp;#34;ssh_key&amp;#34; : &amp;#34;REPLACE_THIS_WITH_CONTENT_OF_ID_RSA_PUB_FILE&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;Pass this file as the command line argument:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;az vmss extension set \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --resource-group $CLUSTER_RESOURCE_GROUP \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --vmss-name $SCALE_SET_NAME \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --name VMAccessForLinux \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --publisher Microsoft.OSTCExtensions \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --version 1.4 \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --protected-settings protected_settings.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Works like a charm!&lt;/p&gt;&#10;</description></item><item><title>AKS Supported Kubernetes Versions</title><link>https://www.tewari.info/2020/11/08/aks-supported-kubernetes-versions/</link><pubDate>Mon, 09 Nov 2020 03:08:17 +0000</pubDate><guid>https://www.tewari.info/2020/11/08/aks-supported-kubernetes-versions/</guid><description>&lt;p&gt;&lt;a class="link" href="https://docs.microsoft.com/en-us/azure/aks/" target="_blank" rel="noopener"&#10; &gt;Azure Kubernetes Service&lt;/a&gt; (AKS) &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions" target="_blank" rel="noopener"&#10; &gt;supports specific versions&lt;/a&gt; of &lt;a class="link" href="https://kubernetes.io/" target="_blank" rel="noopener"&#10; &gt;Kubernetes&lt;/a&gt;.&lt;br&gt;&#10;It is necessary to regularly monitor the release of new versions and upgrade your AKS clusters to supported versions in order to remain in compliance with &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions#kubernetes-version-support-policy" target="_blank" rel="noopener"&#10; &gt;AKS Kubernetes Version Support Policy&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions#release-and-deprecation-process" target="_blank" rel="noopener"&#10; &gt;AKS announces&lt;/a&gt; the planned date of a new minor version release and corresponding old version deprecation via AKS &lt;a class="link" href="https://github.com/Azure/AKS/releases" target="_blank" rel="noopener"&#10; &gt;Release notes&lt;/a&gt; at least 30 days prior to removal. An email notification is sent to the subscription administrators with the planned version removal dates. You get 30 days from version removal to upgrade to a supported minor version release. Patch versions can be released anytime and you get 30 days from the removal date to upgrade to a supported patch version.&lt;/p&gt;&#10;&lt;p&gt;You should test new target Kubernetes versions and upgrade your AKS clusters in a timely manner. For that, it is necessary to proactively monitor the AKS release notes. This can easily become a chore in a large Enterprise environment. Here is a Powershell script to make it easier to stay on top of Kubernetes version releases in AKS and publish/share it with others: &lt;a class="link" href="https://gist.github.com/ashtewari/31ce67d89b1878db52ca7558dbb3e194" target="_blank" rel="noopener"&#10; &gt;Get-AksSupportedVersions&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$aksVersionsJson = az aks get-versions --location eastus&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$aksVersions = $aksVersionsJson | ConvertFrom-Json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$aksVersions.orchestrators.upgrades.orchestratorVersion&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$data = $aksVersions.orchestrators | Select-Object `&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -Property @{Name=&amp;#34;Version&amp;#34;;Expression={$_.orchestratorVersion}} `&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , @{Name=&amp;#34;Default&amp;#34;;Expression={$_.default}} `&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , @{Name=&amp;#34;Preview&amp;#34;;Expression={$_.isPreview}} `&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , @{Name=&amp;#34;Upgrades&amp;#34;;Expression={$_.upgrades.orchestratorVersion -join &amp;#34;, &amp;#34;}}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$versionTable = $data | ConvertTo-Html -Fragment&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$versionTableString = $versionTable | Out-String&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$html = New-Object -ComObject &amp;#34;HTMLFile&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$html.IHTMLDocument2_write($versionTableString)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$tables = $html.body.getElementsByTagName(&amp;#34;table&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$rptString = &amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ForEach($table in $tables){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach($row in $table.rows){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $cellCount = 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach($cell in $row.cells){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $cellCount++&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if(($cellCount -eq 2) -and ($cell.innertext -eq &amp;#39;True&amp;#39;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $row.className = &amp;#34;OkStatus&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if(($cellCount -eq 3) -and ($cell.innertext -eq &amp;#39;True&amp;#39;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $row.className = &amp;#34;WarningStatus&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $rptString += $table.outerHTML&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$reportDate = $(get-date -DisplayHint DateTime) | Out-String&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$fileTS = $(get-date -Format &amp;#34;yyyyMMdd&amp;#34;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$fileName = &amp;#34;aks-versions-$fileTS.html&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$rptTitle = &amp;#34;&amp;lt;h1&amp;gt;AKS Kubernetes Versions&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;$reportDate&amp;lt;/p&amp;gt;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$report = ConvertTo-Html -Title &amp;#34;AKS Versions&amp;#34; -Body &amp;#34;$rptTitle $rptString&amp;#34; -Head $header&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$report | Out-File &amp;#34;$fileName&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It creates an HTML report of currently supported Kubernetes versions in AKS along with their respective upgrade paths. Here is an example of the report generated by the script referenced above :&lt;/p&gt;&#10;&lt;h1 id="aks-kubernetes-versions"&gt;AKS Kubernetes Versions&#10;&lt;/h1&gt;&lt;p&gt;Sunday, November 8, 2020 8:47:42 PM&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Version&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Default&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Preview&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Upgrades&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.16.13&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.16.15, 1.17.9, 1.17.11&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.16.15&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.17.9, 1.17.11&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.17.9&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.17.11, 1.18.6, 1.18.8&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.17.11&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;True&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.18.6, 1.18.8&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.18.6&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.18.8, 1.19.0&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.18.8&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.19.0&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1.19.0&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;True&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Reference: &lt;a class="link" href="https://adamtheautomator.com/powershell-convertto-html/" target="_blank" rel="noopener"&#10; &gt;How To Create An HTML Report With PowerShell&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>