Lesson Learned #454:Optimizing Connection Pooling for Application Workloads: Active Connections

This article is contributed. See the original author and article here.

A few days ago, a customer asked us to find out details about the active connections of a connection pooling, how many connection poolings their application has, etc. In this article, I would like to share the lessons learned to see these details.


 


As our customer is using .NET Core, we will rely on the following article to gather all this information Event counters in SqlClient – ADO.NET Provider for SQL Server | Microsoft Learn


 


We will continue with the same script that we are using in the previous article Lesson Learned #453:Optimizing Connection Pooling for Application Workloads: A single journey – Microsoft Community Hub, and once the link is implemented Event counters in SqlClient – ADO.NET Provider for SQL Server | Microsoft Learn, we will see what information we obtain.


 


Once we executed our application we started seeing the following information:


 

2023-11-26 09:38:18.998: Actual active connections currently made to servers		0
2023-11-26 09:38:19.143: Active connections retrieved from the connection pool		0
2023-11-26 09:38:19.167: Number of connections not using connection pooling		0
2023-11-26 09:38:19.176: Number of connections managed by the connection pool		0
2023-11-26 09:38:19.181: Number of active unique connection strings		1
2023-11-26 09:38:19.234: Number of unique connection strings waiting for pruning		0
2023-11-26 09:38:19.236: Number of active connection pools		1
2023-11-26 09:38:19.239: Number of inactive connection pools		0
2023-11-26 09:38:19.242: Number of active connections		0
2023-11-26 09:38:19.245: Number of ready connections in the connection pool		0
2023-11-26 09:38:19.272: Number of connections currently waiting to be ready		0

 


 


As our application is using a single connection string and using a single connection pooler, the details that appear below are stable and understandable. But let’s make a couple of changes to the code to see how the numbers change.


 


Our first change will be to open 100 connections and once we reach those 100, we will close and reopen them to see how the counters fluctuat. The details we observe while our application is running indicate that connections are being opened but not closed. Which is expected.


 

2023-11-26 09:49:01.606: Actual active connections currently made to servers		13
2023-11-26 09:49:01.606: Active connections retrieved from the connection pool		13
2023-11-26 09:49:01.607: Number of connections not using connection pooling		0
2023-11-26 09:49:01.607: Number of connections managed by the connection pool		13
2023-11-26 09:49:01.608: Number of active unique connection strings		1
2023-11-26 09:49:01.608: Number of unique connection strings waiting for pruning		0
2023-11-26 09:49:01.609: Number of active connection pools		1
2023-11-26 09:49:01.609: Number of inactive connection pools		0
2023-11-26 09:49:01.610: Number of active connections		13
2023-11-26 09:49:01.610: Number of ready connections in the connection pool		0
2023-11-26 09:49:01.611: Number of connections currently waiting to be ready		0

 


 


But as we keep closing and opening new ones, we start to see how our connection pooling is functioning


 

2023-11-26 09:50:08.600: Actual active connections currently made to servers		58
2023-11-26 09:50:08.601: Active connections retrieved from the connection pool		50
2023-11-26 09:50:08.601: Number of connections not using connection pooling		0
2023-11-26 09:50:08.602: Number of connections managed by the connection pool		58
2023-11-26 09:50:08.602: Number of active unique connection strings		1
2023-11-26 09:50:08.603: Number of unique connection strings waiting for pruning		0
2023-11-26 09:50:08.603: Number of active connection pools		1
2023-11-26 09:50:08.604: Number of inactive connection pools		0
2023-11-26 09:50:08.604: Number of active connections		50
2023-11-26 09:50:08.605: Number of ready connections in the connection pool		8
2023-11-26 09:50:08.605: Number of connections currently waiting to be ready		0

 


 


In the following example, we can see how once we have reached our 100 connections, the connection pooler is serving our application the necessary connection.


 

2023-11-26 09:53:27.602: Actual active connections currently made to servers		100
2023-11-26 09:53:27.602: Active connections retrieved from the connection pool		92
2023-11-26 09:53:27.603: Number of connections not using connection pooling		0
2023-11-26 09:53:27.603: Number of connections managed by the connection pool		100
2023-11-26 09:53:27.604: Number of active unique connection strings		1
2023-11-26 09:53:27.604: Number of unique connection strings waiting for pruning		0
2023-11-26 09:53:27.605: Number of active connection pools		1
2023-11-26 09:53:27.606: Number of inactive connection pools		0
2023-11-26 09:53:27.606: Number of active connections		92
2023-11-26 09:53:27.606: Number of ready connections in the connection pool		8
2023-11-26 09:53:27.607: Number of connections currently waiting to be ready		0

 


 


Let’s review the counters:


 




  1. Actual active connections currently made to servers (100): This indicates the total number of active connections that have been established with the servers at the given timestamp. In this case, there are 100 active connections.




  2. Active connections retrieved from the connection pool (92): This shows the number of connections that have been taken from the connection pool and are currently in use. Here, 92 out of the 100 active connections are being used from the pool.




  3. Number of connections not using connection pooling (0): This counter shows how many connections are made directly, bypassing the connection pool. A value of 0 means all connections are utilizing the connection pooling mechanism.




  4. Number of connections managed by the connection pool (100): This is the total number of connections, both active and idle, that are managed by the connection pool. In this example, there are 100 connections in the pool.




  5. Number of active unique connection strings (1): This indicates the number of unique connection strings that are currently active. A value of 1 suggests that all connections are using the same connection string.




  6. Number of unique connection strings waiting for pruning (0): This shows how many unique connection strings are inactive and are candidates for removal or pruning from the pool. A value of 0 indicates no pruning is needed.




  7. Number of active connection pools (1): Represents the total number of active connection pools. In this case, there is just one connection pool being used.




  8. Number of inactive connection pools (0): This counter displays the number of connection pools that are not currently in use. A value of 0 indicates that all connection pools are active.




  9. Number of active connections (92): Similar to the second counter, this shows the number of connections currently in use from the pool, which is 92.




  10. Number of ready connections in the connection pool (8): This indicates the number of connections that are in the pool, available, and ready to be used. Here, there are 8 connections ready for use.




  11. Number of connections currently waiting to be ready (0): This shows the number of connections that are in the process of being prepared for use. A value of 0 suggests that there are no connections waiting to be made ready.




These counters provide a comprehensive view of how the connection pooling is performing, indicating the efficiency, usage patterns, and current state of the connections managed by the Microsoft.Data.SqlClient.


 


One thing, that pay my attention is Number of unique connection strings waiting for pruning This means that if there have been no recent accesses to the connection pooler, we might find that if there have been no connections for a certain period, the connection pooler will be eliminated, and the first connection that is made will take some time (seconds) to be recreated, for example, in the night when we might not have active workload:


 




  1. Idle Connection Removal: Connections are removed from the pool after being idle for approximately 4-8 minutes, or if a severed connection with the server is detected​​.




  2. Minimum Pool Size: If the Min Pool Size is not specified or set to zero in the connection string, the connections in the pool will be closed after a period of inactivity. However, if Min Pool Size is greater than zero, the connection pool is not destroyed until the AppDomain is unloaded and the process ends. This implies that as long as the minimum pool size is maintained, the pool itself remains active​​.




 


We could observe in Microsoft.Data.SqlClient in the file SqlClient-mainSqlClient-mainsrcMicrosoft.Data.SqlClientsrcMicrosoftDataProviderBaseDbConnectionPoolGroup.cs useful information about it:


 


Line 50: private const int PoolGroupStateDisabled = 4; // factory pool entry pruning method
Line 268: // Empty pool during pruning indicates zero or low activity, but
Line 293: // must be pruning thread to change state and no connections
Line 294: // otherwise pruning thread risks making entry disabled soon after user calls ClearPool


 


These parameters work together to manage the lifecycle of connection pools and their resources efficiently, balancing the need for ready connections with system resource optimization. The actual removal of an entire connection pool (and its associated resources) depends on these settings and the application’s runtime behavior. The documentation does not specify a fixed interval for the complete removal of an entire connection pool, as it is contingent on these dynamic factors.


 


To conclude this article, I would like to conduct a test to see if each time I request a connection and change something in the connection string, it creates a new connection pooling.


 


For this, I have modified the code so that half of the connections receive a clearpool. As we could see new inactive connection pools shows. 


 


 

2023-11-26 10:34:18.564: Actual active connections currently made to servers		16
2023-11-26 10:34:18.565: Active connections retrieved from the connection pool		11
2023-11-26 10:34:18.566: Number of connections not using connection pooling		0
2023-11-26 10:34:18.566: Number of connections managed by the connection pool		16
2023-11-26 10:34:18.567: Number of active unique connection strings		99
2023-11-26 10:34:18.567: Number of unique connection strings waiting for pruning		0
2023-11-26 10:34:18.568: Number of active connection pools		55
2023-11-26 10:34:18.568: Number of inactive connection pools		150
2023-11-26 10:34:18.569: Number of active connections		11
2023-11-26 10:34:18.569: Number of ready connections in the connection pool		5
2023-11-26 10:34:18.570: Number of connections currently waiting to be ready		0

 


 


Source code


 


 

using System;
using Microsoft.Data.SqlClient;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace HealthCheck
{
    class ClsCheck
    {
        const string LogFolder = "c:tempMydata";
        const string LogFilePath = LogFolder + "logCheck.log";

        public void Main(Boolean bSingle=true, Boolean bDifferentConnectionString=false)
        {
            int lMaxConn = 100;
            int lMinConn = 0;
            if(bSingle)
            {
                lMaxConn = 1;
                lMinConn = 1;
            }
            string connectionString = "Server=tcp:servername.database.windows.net,1433;User Id=username@microsoft.com;Password=Pwd!;Initial Catalog=test;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=5;Pooling=true;Max Pool size=" + lMaxConn.ToString() + ";Min Pool Size=" + lMinConn.ToString() + ";ConnectRetryCount=3;ConnectRetryInterval=10;Authentication=Active Directory Password;PoolBlockingPeriod=NeverBlock;Connection Lifetime=5;Application Name=ConnTest";
            Stopwatch stopWatch = new Stopwatch();
            SqlConnection[] oConnection = new SqlConnection[lMaxConn];
            int lActivePool = -1;
            string sConnectionStringDummy = connectionString;

            DeleteDirectoryIfExists(LogFolder);
            ClsEvents.EventCounterListener oClsEvents = new ClsEvents.EventCounterListener();
            //ClsEvents.SqlClientListener olistener = new ClsEvents.SqlClientListener();
            while (true)
            {
                if (bSingle)
                {
                    lActivePool = 0;
                    sConnectionStringDummy = connectionString;
                }
                else
                {
                    lActivePool++;
                    if (lActivePool == (lMaxConn-1))
                    {
                        lActivePool = 0;

                        for (int i = 0; i = 5)
                    {
                        Log($"Maximum number of retries reached. Error: " + ex.Message);
                        break;
                    }
                    Log($"Error connecting to the database. Retrying in " + retries + " seconds...");
                    Thread.Sleep(retries * 1000);
                }
            }
            return connection;
        }

        static void Log(string message)
        {
            var ahora = DateTime.Now;
            string logMessage = $"{ahora.ToString("yyyy-MM-dd HH:mm:ss.fff")}: {message}";
            //Console.WriteLine(logMessage);
            try
            {
                using (FileStream stream = new FileStream(LogFilePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                {
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.WriteLine(logMessage);
                    }
                }
            }
            catch (IOException ex)
            {
                Console.WriteLine($"Error writing in the log file: {ex.Message}");
            }
        }

        static void ExecuteQuery(SqlConnection connection)
        {
            int retries = 0;
            while (true)
            {
                try
                {
                    using (SqlCommand command = new SqlCommand("SELECT 1", connection))
                    {
                        command.CommandTimeout = 5;
                        object result = command.ExecuteScalar();
                    }
                    break;
                }
                catch (Exception ex)
                {
                    retries++;
                    if (retries >= 5)
                    {
                        Log($"Maximum number of retries reached. Error: " + ex.Message);
                        break;
                    }
                    Log($"Error executing the query. Retrying in " + retries + " seconds...");
                    Thread.Sleep(retries * 1000);
                }
            }
        }

        static void LogExecutionTime(Stopwatch stopWatch, string action)
        {
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
               ts.Hours, ts.Minutes, ts.Seconds,
               ts.Milliseconds / 10);
            Log($"{action} - {elapsedTime}");
            stopWatch.Reset();
        }

        public static void DeleteDirectoryIfExists(string path)
        {
            try
            {
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
                Directory.CreateDirectory(path);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error deleting the folder: {ex.Message}");
            }
        }
    }

}

 


 


Enjoy!

A Practical Guide for Beginners: Azure OpenAI with JavaScript and TypeScript (Part 01)

A Practical Guide for Beginners: Azure OpenAI with JavaScript and TypeScript (Part 01)

This article is contributed. See the original author and article here.

Introduction


 


A Practical Guide for Beginners: Azure OpenAI with JavaScript and TypeScript is an essential starting point for exploring Artificial Intelligence in the Azure cloud. This guide will be divided into 3 parts, covering: ‘How to create the Azure OpenAI Service resource,’ How to implement the model created in Azure OpenAI Studio, and finally, how to consume this resource in a Node.js/TypeScript application. This series will help you learn the fundamentals so that you can start developing your applications with Azure OpenAI Service. Whether you are a beginner or an experienced developer, discover how to create intelligent applications and unlock the potential of AI with ease.


Responsible AI


 


Before we start discussing Azure OpenAI Service, it’s crucial to talk about Microsoft’s strong commitment to the entire field of Artificial Intelligence. Microsoft is deeply dedicated to this topic. Therefore, Microsoft is committed to ensuring that AI is used in a responsible and ethical manner. Furthermore, Microsoft is working with the AI community to develop and share best practices and tools to help ensure that AI is used in a responsible and ethical way, thereby incorporating the six core principles, which are:



  • Fairness

  • Inclusivity

  • Reliability and Safety

  • Transparency

  • Security and Privacy

  • Accountability


If you want to learn more about Microsoft’s commitment to Responsible AI, you can access the link Microsoft AI Principles.


Now, we can proceed with the article!


 


Understand Azure OpenAI Service


 


Azure OpenAI Service provides access to advanced OpenAI language models such as GPT-4, GPT-3.5-Turbo, and Embeddings via a REST API. The GPT-4 and GPT-3.5-Turbo models are now available for general use, allowing adaptation for tasks such as content generation, summarization, semantic search, and natural language translation to code. Users can access the service through REST APIs, Python SDK, or Azure OpenAI Studio.


To learn more about the models available in Azure OpenAI Service, you can access them through the link Azure OpenAI Service models.


 


Create the Azure OpenAI Service Resource


 



The use of Azure OpenAI Service is limited. Therefore, it is necessary to request access to the service at Azure OpenAI Service. Once you have approval, you can start using and testing the service!



Once your access is approved, go to the Azure Portal and let’s create the Azure OpenAI resource. To do this, follow the steps below:


 



  • Step 01: Click on the Create a resource button.


azure-openai-01.png


 


 



  • Step 02: In the search box, type Azure OpenAI and then click Create.


azure-openai-02.png


 


 


azure-openai-03.png


 


 



  • Step 03: On the resource creation screen, fill in the fields as follows:


azure-openai-04.png


 


 


Note that in the Pricing tier field, you can test Azure OpenAI Service for free but with some limitations. To access all features, you should choose a paid plan. For more pricing information, access the link Azure OpenAI Service pricing.




  • Step 04: Under the Network tab, choose the option: All networks, including the internet, can access this resource. and then click Next.




  • Step 05: After completing all the steps, click the Create button to create the resource.




azure-openai-05.png


 


 



  • Step 06: Wait a few minutes for the resource to be created.


 


azure-openai-06.png


 


Next steps


 


In the next article, we will learn how to deploy a model on the Azure OpenAI Service. This model will allow us to consume the Azure OpenAI Service directly in our code.


Oh, I almost forgot to mention! Don’t forget to subscribe to my YouTube Channel! In 2023/2024, there will be many exciting new things on the channel!


Some of the upcoming content includes:



  • Microsoft Learn Live Sessions

  • Weekly Tutorials on Node.js, TypeScript, & JavaScript

  • And much more!


If you enjoy this kind of content, be sure to subscribe and hit the notification bell to be notified when new videos are released. We already have an amazing new series coming up on the YouTube channel this week.


 


Captura de tela 2023-11-24 125740.png


 


See you in the next article! 

MVP’s Favorite Content: SQL Server and Power Apps

MVP’s Favorite Content: SQL Server and Power Apps

This article is contributed. See the original author and article here.

In this blog series dedicated to Microsoft’s technical articles, we’ll highlight our MVPs’ favorite article along with their personal insights.


 


Jungsun Kim, Data Platform MVP, Korea


Jungsun Kim.jpg


SQL Server technical documentation – SQL Server | Microsoft Learn


“This article introduces various DB technologies ranging from the latest version of SQL Server, Azure SQL, Business Intelligence, to Machine Learning.”


(In Korean: SQL Server 최신 버전, Azure SQL, Business Intelligence, Machine Learning에 이르기까지 다양한 DB기술을 소개합니다.)


*Relevant Activity: I have been writing a series of articles about new features of SQL Server 2022 on my website: 김정선의 Data 이야기 (visualdb.net)


 


Sergio Govoni, Data Platform MVP, Italy


Sergio Govoni.jpg


SQL Server encryption – SQL Server | Microsoft Learn


“Databases in a company are the place where information is stored to drive the company’s production processes. Tera of data, dozens of databases, millions of rows, the entire activity depends on this, and information security can no longer be an option, we have to think about security by design and security by default.”


*Relevant Blog:


Encryption in your SQL Server backup strategy! | by Sergio Govoni | CodeX | Medium


Database encryption becomes transparent with SQL Server TDE! | by Sergio Govoni | CodeX | Medium


Advanced database encryption with SQL Server Always Encrypted! | by Sergio Govoni | CodeX | Medium


How to manage Always Encrypted columns from a Delphi application! | by Sergio Govoni | CodeX | Medium


 


James Hickey, Developer Technologies MVP, Canada


James Hickey.jpg


SQL Server and Azure SQL index architecture and design guide – SQL Server | Microsoft Learn


“If you work with SQL Server, it’s really helpful to understand advanced information about how indexing works, memory management, etc. You’ll find tips about creating better indexes & queries and how to debug issues better.”


 


Inhee LEE, Business Applications MVP, Korea


LEE Inhee.jpg


Create a machine ordering app with Power Apps – Online Workshop – Training | Microsoft Learn


“This is a practical course that enables you to understand the power platform comprehensively and organically. Through the practical course, you can learn each element systematically while covering various practical aspects, making it a very suitable course for beginners and intermediate learners. I recommend this course.”


(In Korean: 파워플랫폼에 대한 전체적인 이해를 종합적이고 유기적으로 가능하게 하는 실습과정입니다. 실습과정을 통해서 실무적인 요소를 두루 다루면서도 체계적으로 하나하나 익힐 수 있어서 초보자와 중급자 모두에게 매우 적절한 실습과정이어서 추천했습니다.)


*Relevant Activity: I shared this content with a group of Facebook: Power Platform | Facebook

Breaking changes November 2023

This article is contributed. See the original author and article here.

Description


Report CreateFile operations during Event Grid ingestion from Adlsv2 as errors


 


When uploading a file with Azure Data Lake SDK, there is an initial CreateFile event with size of 0.


Another FlushAndClose event is sent to Azure Data Explorer when setting the close parameter to ‘true’ on the SDK’s file upload option.


This event indicates that the final update has been made and the file stream is ready for ingestion.


 


Current Behavior:


Azure Data Explorer ignores the CreateFile event during data ingestion and no monitoring of these errors is reflected to users.


 


Expected behavior:


Azure Data Explorer will treat CreateFile events as an error of empty blob.


As a result, users are expected to get the following permanent errors for these events:



  • Failure ingestion metrics:

    • “IngestionResult” of permanent bad request

    • “BlobsDropped” from the relevant event grid data connection.

    • “EventsDropped” from the relevant event grid data connection.



  • Failed ingestion logs in case of turning on the failed ingestion diagnostic logs


 


Required Change:


Filter out CreateFile events from the event grid subscription.


This filtering reduces the traffic coming from Event Grid and optimizes the ingestion of events into Azure Data Explorer.


You can read more about how to use the SDK correctly and avoid empty file errors here.


 


Schedule & plan 


Step 1: Existing clusters which do not use the functionality today will get the change immediately.


Step 2: Clusters created after end of December 2023 will get the change.


Step 3: Current flow users as well as new clusters created until end of December 2023 will receive the changes after end of February 2024.


 



  1. Deprecating the metric “Events Processed (for Event/IoT Hubs)”


 


This metric represents the total number of events read from Event Hubs/ IoT hub and processed by the cluster. These events can be split by the status: Received, Rejected, Processed.


 


Required Change


Users can use the metrics “Event received”, “Events processed” and “Event dropped” to get the number of events that were received, processed, or dropped from each data connection respectively.


You can read more about these metrics here.


To ensure continuity of monitoring, please move any automated process that uses the old metric to use the new metrics instead.


 


Schedule & plan 


The changes above are planned to take place at the end of February 2024.

Submit Apache Spark and Apache Flink jobs with Azure Logic Apps on HDInsight on AKS

Submit Apache Spark and Apache Flink jobs with Azure Logic Apps on HDInsight on AKS

This article is contributed. See the original author and article here.

Author(s): Arun Sethia is a Program manager in Azure HDInsight Customer Success Engineering (CSE) team.


Co-Author: Sairam is a Product manager for Azure HDInsight on AKS.


 


Introduction


Azure Logic Apps allows you to create and run automated workflows with little to no code. These workflows can be stateful or stateless. Each workflow starts with a single trigger, after which you must add one or more actions. An Action specifies a task to perform. Trigger specifies the condition for running any further steps in that workflow, for example when a blob is added or updated, when  http request is received, checks for new data in an SQL database table, etc. These workflows can be stateful or stateless, based on your Azure Logic App plan (Standard and Consumption).


 


Using workflows, you can orchestrate complex workflow with multiple processing steps, triggers, and interdependencies. These steps can involve certain Apache Spark and Apache Flink jobs, and integration with Azure services.


The blog is focused on how you can add an action to trigger Apache Spark or Apache Flink job on HDInsight on AKS from a workflow.


 


Azure Logic App –  Orchestrate Apache Spark Job on HDInsight on AKS


In our previous blog, we discussed about different options to submit Apache Spark jobs to HDInsight on AKS cluster.  The Azure Logic Apps workflow will make use of Livy Batch Job API to submit Apache Spark job.


The following diagram shows interaction between Azure Logic Apps, Apache Spark cluster on HDInsight on AKS, Azure Active Directory and Azure Key Vault. You can always use the other cluster shapes like Apache Flink or Trino for the same, with the Azure management endpoints.


spark_logic_app.png


HDInsight on AKS allows you to access Apache Spark Livy REST APIs using OAuth token. It would require a Microsoft Entra service principal  and  Grant access to the cluster for the same service principal to the HDInsight on AKS cluster (RBAC support is coming soon). The client id (appId) and secret (password) of this principal can be stored in Azure Key Vault (you can use  various design pattern’s to rotate secrets).


 


Based on your business scenario, you can start (trigger) your workflow; in this example we are using “Http request is received.”  The workflow connects to Key Vault using System managed (or you can use User Managed identities) to retrieve secrets and client id for a service principal created to access HDInsight on AKS cluster. The workflow retrieves OAuth token using client credential (secret, client id, and scope as https://hilo.azurehdinsight.net/.default).


 


The invocation to the Apache Spark Livy REST APIs on HDInsight is done with Bearer token and Livy Batch (POST /batches) payload


The final workflow is as follows, the source code and sample payload are available on this GitHub


spark_workflow.png


Azure Logic App –  Orchestrate Apache Flink Job on HDInsight on AKS


HDInsight on AKS provides user friendly ARM Rest APIs to submit and manage Flink jobs. Users can submit Apache Flink jobs from any Azure service using these Rest APIs. Using ARM REST API, you can orchestrate the data pipeline with Azure Data Factory Managed Airflow. Similarly, you can use Azure Logic Apps workflow to manage complex business workflow.


 


The following diagram shows interaction between Azure Logic Apps, Apache Flink cluster on HDInsight on AKS, Azure Active Directory and Azure Key Vault.


Flink_LogicApp.png


To invoke ARM REST APIs, we would require a Microsoft Entra service principal  and configure its access to specific Apache Flink cluster on HDInsight on AKS with Contributor role. (resource id can be retrieved from the portal, go to cluster page, click on JSON view, value for “id” is resource id).


 

az ad sp create-for-rbac -n  --role Contributor --scopes 

 


The client id (appId) and secret (password) of this principal can be stored in Azure Key Vault (you can use  various design pattern’s to rotate secrets).


 


The workflow connects to Key Vault using System managed (or you can use User Managed identities) to retrieve secrets and client id for a service principal created to access HDInsight on AKS cluster. The workflow retrieves OAuth token using client credential (secret, client id, and scope as https://management.azure.com/.default).


 


The final workflow is as follows, the source code and sample payload is available on GitHub


flink_workflow.png


Summary


HDInsight on AKS REST APIs lets you automate, orchestrate, schedule  and allows you to monitor workflows with your choice of framework. Such automation reduces complexity, reduces development cycles and completes tasks with fewer errors.


 


You can choose what works best for your organization, let us know your feedback or any other integration from Azure services to automate and orchestrate your workload on HDInsight on AKS.


References



We are super excited to get you started: