<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Establishing a secure and dedicated connection to Azure OpenAI in Technical Blog</title>
    <link>https://community.databricks.com/t5/technical-blog/establishing-a-secure-and-dedicated-connection-to-azure-openai/ba-p/73719</link>
    <description>&lt;P&gt;&lt;SPAN&gt;With Databricks serverless networking, our goal is to make connectivity secure and simple, with minimal configuration. In turn, you can focus on the data and AI use-cases that matter most to you.&amp;nbsp; One area that we’ve heard a lot of asks around is for keeping a workspace locked down from access to unauthorized resources, while still enabling in-cloud or sometimes even cross-cloud secure connectivity to sanctioned resources.&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;In this blog post, we will address one of the popular customer requests for such a cross-cloud scenario: locking down access to the internet from your serverless workloads on AWS, but enabling access to Azure Open AI through a dedicated, per-customer connection. &lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Architecture Diagram&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Serverless Model Azure Private Connectivity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8177iF4FE3CECFAC2684B/image-size/large?v=v2&amp;amp;px=999" role="button" title="Serverless Model Azure Private Connectivity.png" alt="Serverless Model Azure Private Connectivity.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Design Walkthrough&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;To control access to the internet from your serverless workloads, we're enhancing egress control capabilities.&amp;nbsp; P&lt;/SPAN&gt;&lt;SPAN&gt;lease use&amp;nbsp;&lt;A href="https://docs.google.com/forms/d/e/1FAIpQLSdTsFj01Y7b3WWKUSK9X6Tj75wMJLGfgd-S6UobUZOgatXDjQ/viewform" target="_blank" rel="noopener"&gt;this form&lt;/A&gt; to join our previews, or contact your account team to learn more.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;To establish a dedicated connection through the model serving endpoint to Azure OpenAI, two critical connections are required: the connection between the model serving endpoint and the customer's VPC in AWS, and the connection from the customer's VPC to Azure OpenAI.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;1: Connection between model serving endpoint and customer VPC.&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Databricks' serverless compute plane networking is managed by &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/en/security/network/serverless-network-security/index.html#what-is-a-network-connectivity-configuration-ncc" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Network Connectivity Configuration (NCC)&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. Each NCC container currently offers two options:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Stable IPs:&lt;/STRONG&gt;&lt;SPAN&gt; Public IPs that provide access to your resources (public preview)&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Private Endpoint Service:&lt;/STRONG&gt;&lt;SPAN&gt; VPC endpoints that facilitate PrivateLink connections (private preview)&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;For maximum security, we recommend using AWS PrivateLink from serverless, which is also the approach we adopt in our example configuration.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;2:&amp;nbsp;Connection between customer VPC to Azure OpenAI.&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s take a closer look at the architecture:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Serverless Model Private Connectivity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8178i7F2D5FBF39DF6CC3/image-size/large?v=v2&amp;amp;px=999" role="button" title="Serverless Model Private Connectivity.png" alt="Serverless Model Private Connectivity.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;At the heart of the setup, we deployed HAProxy on EC2 instances as a Layer 4 forwarding mechanism. Requests from the model serving nodes are routed through PrivateLink to HAProxy servers, which then forward these requests directly to Azure OpenAI. To enhance the enterprise-readiness of the solution, we implement several features:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;On AWS:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Autoscaling for HAProxy Servers:&lt;/STRONG&gt;&lt;SPAN&gt; This introduces better fault tolerance and availability. Our solution is configured to use multiple availability zones and based on your access pattern, you have the flexibility to configure the scaling criteria so that it always has the right amount of capacity.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Automated stable IP Assignment and Recycle:&lt;/STRONG&gt;&lt;SPAN&gt; This is implemented via&lt;A href="https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html" target="_blank" rel="noopener"&gt; Autoscaling lifecycle hooks&lt;/A&gt; and AWS Lambda to minimize operational overhead. We will only pick the IPs that are allowed in Azure OpenAI firewall. Each scale-out event triggers a Lambda function that assigns an unassigned IP from the pool to the new instance. If no IP is available, the instance launch is aborted to maintain uninterrupted service.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;On Azure:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Azure OpenAI Firewall:&lt;/STRONG&gt;&lt;SPAN&gt; This restricts access to only authorized IP addresses for greater security. We establish an Elastic IP (EIP) pool for all HAProxy servers and configure Azure OpenAI service to permit access solely from this IP pool.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;Constructing a VPN connection between Amazon VPC and Azure VNet is possible for those wishing to eliminate public access entirely. Please reach out to your account team for guidance if you would like to go this route.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Implementation Walkthrough&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;This section describes the detailed steps to configure a dedicated and secured connection to Azure Open AI service for your workspace.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 1 - Create and deploy an Azure OpenAI Service resource in your Azure subscription&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Follow the Azure documentation to &lt;/SPAN&gt;&lt;A href="https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource?pivots=web-portal" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;create an Azure OpenAI service&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; and deploy a model.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="CreateAOAI_3.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8537i9FE4C2A25F4409A7/image-size/large?v=v2&amp;amp;px=999" role="button" title="CreateAOAI_3.png" alt="CreateAOAI_3.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_DeployModel.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8540i4B8069F9EB15CA46/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_DeployModel.png" alt="AOAI_DeployModel.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Endpoint.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8541iF9367CE6AEF80327/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Endpoint.png" alt="AOAI_Endpoint.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Once Azure Open AI service is available, please note down the deployment name and endpoint. This will be used later to configure the proxy server backend and construct the API URL when registering your MLFlow model in Databricks model registry.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 2 - Create all the AWS resources required for the VPC endpoint service in your AWS account&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;The following AWS resources are required to build the VPC endpoint service:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;One &lt;STRONG&gt;VPC&lt;/STRONG&gt; with multiple &lt;STRONG&gt;private subnets&lt;/STRONG&gt; (for the network load balancer (NLB)) and &lt;STRONG&gt;public subnets&lt;/STRONG&gt; (for proxy servers), and &lt;STRONG&gt;two security groups&lt;/STRONG&gt;, one for NLB and one for the Launch Template&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCCreation.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8558i9D207F64DF88E027/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCCreation.png" alt="VPCCreation.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NLB_SG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8559iD910C3A4DC66E4CC/image-size/large?v=v2&amp;amp;px=999" role="button" title="NLB_SG.png" alt="NLB_SG.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate_SG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8560iF3A33ABCFC48F2CE/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate_SG.png" alt="LaunchTemplate_SG.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A pool of &lt;STRONG&gt;Elastic IPs (EIP)&lt;/STRONG&gt; that will be attached to the proxy servers and used for Azure Open AI firewall whitelisting&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EIP.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8546i2DEFD43735B89FAC/image-size/large?v=v2&amp;amp;px=999" role="button" title="EIP.png" alt="EIP.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EIP_Pool.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8547i69BF41C876DFFB30/image-size/large?v=v2&amp;amp;px=999" role="button" title="EIP_Pool.png" alt="EIP_Pool.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Please tag the EIPs properly as the tag &lt;/EM&gt;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;key&lt;/STRONG&gt; (not tag value) will be used to identify the EIP pool in the Lambda function. In our example, only the EIPs with tag key “dais24_eip” will be assigned to the proxy servers.&lt;/EM&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;&lt;STRONG&gt;A Launch Template&lt;/STRONG&gt; that specifies the instance configuration for the proxy server&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8561i7E75A4D2A9C5FBC1/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate.png" alt="LaunchTemplate.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Optionally, you can write a shell script to install the proxy server and put it in the user data field in Advanced details section of Launch Template.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate_UserData.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8474i536A621F45DEF747/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate_UserData.png" alt="LaunchTemplate_UserData.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Below is a sample user data shell script:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;#!/bin/bash

# Fetch the token required for IMDSv2
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Fetch the public IP address of the instance using the token
PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4)

# Check if the public IP address is not empty
if [ -n "$PUBLIC_IP" ]; then
  echo "Public IP found: $PUBLIC_IP"
  echo "Installing HAProxy..."

  # Update the package repository and install HAProxy
  sudo yum update -y
  sudo yum install haproxy -y

  # Enable and start the HAProxy service
  # systemctl enable haproxy
  # systemctl start haproxy

  echo "HAProxy installation completed."

else
  echo "No public IP assigned to this instance. Skipping HAProxy installation."
fi
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;NLB&lt;/STRONG&gt; target group&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8577i8AC27E3FF2BDBB17/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup.png" alt="TargetGroup.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: When creating the NLB, please select TCP port 443 in Basic configuration section and TCP protocol in Health checks section&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup_HealthCheck.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8563iE6B84A49CE684BFB/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup_HealthCheck.png" alt="TargetGroup_HealthCheck.png" /&gt;&lt;/span&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;NLB&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NLB.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8581iC8C6A462F8118BA4/image-size/large?v=v2&amp;amp;px=999" role="button" title="NLB.png" alt="NLB.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An &lt;STRONG&gt;Auto Scaling group&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8565iFCA3D3F1CAA15D79/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG.png" alt="ASG.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;EM&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;NOTE: Please set the initial desired capacity and minimum capacity to 0 when creating the Auto Scaling group. If these two parameters are not set to 0, the EC2 proxy servers will be launched immediately but no EIPs will be assigned. The reason is that the lifecycle hook does not exist at this point and the Lambda function that is used to assign EIPs will not be triggered. You need to manually update them to the actual values once the lifecycle hook is created.&lt;/EM&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An execution &lt;STRONG&gt;IAM role&lt;/STRONG&gt; of the Lambda function&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;The following IAM permissions need to be granted to the role:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "autoscaling:CompleteLifecycleAction"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": [
        "ec2:AssociateAddress",
        "ec2:DisassociateAddress",
        "ec2:DescribeInstances",
        "ec2:DescribeAddresses",
        "ec2:CreateTags"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": "logs:CreateLogGroup",
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;Lambda function&lt;/STRONG&gt; that is used to assign EIPs to the proxy servers&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Lambda.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8566iFE3AC389EB2A4BD6/image-size/large?v=v2&amp;amp;px=999" role="button" title="Lambda.png" alt="Lambda.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;Below is a sample Python code of the Lambda function:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import boto3

def lambda_handler(event, context):
    # Create a new EC2 client
    ec2_client = boto3.client('ec2')
    as_client = boto3.client('autoscaling')

    # Get the list of all available Elastic IPs from EIP pool where tag-key filter needs to match the EIP tag key
    eips = ec2_client.describe_addresses(Filters=[{'Name': 'tag-key', 'Values': ['dais24_eip']}])
    aval_eips = [eip for eip in eips['Addresses'] if 'AssociationId' not in eip]

    if not aval_eips:
        raise Exception('No free EIPs available')

    instance_id = event['detail']["EC2InstanceId"]
    eip = aval_eips[0]['AllocationId']

    # Associate the EIP with the instance
    ec2_client.associate_address(AllocationId=eip, InstanceId=instance_id)

    # Complete the lifecycle action
    response = as_client.complete_lifecycle_action(
        LifecycleHookName=event['detail']["LifecycleHookName"],
        AutoScalingGroupName=event['detail']['AutoScalingGroupName'],
        LifecycleActionToken=event['detail']['LifecycleActionToken'],
        LifecycleActionResult='CONTINUE',
        InstanceId=instance_id
    )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: The Lambda function's timeout should be set to 10 seconds.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL class="lia-list-style-type-disc"&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An &lt;STRONG&gt;EventBridge rule&lt;/STRONG&gt; with the source as the Auto Scaling group lifecycle hook and target as the Lambda function.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EventBridgeRule.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8482i73E242EB85C53688/image-size/large?v=v2&amp;amp;px=999" role="button" title="EventBridgeRule.png" alt="EventBridgeRule.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;An &lt;STRONG&gt;Auto Scaling group lifecycle hook&lt;/STRONG&gt; that reacts to the scale out event.&lt;BR /&gt;&lt;/SPAN&gt;Go back to the Auto Scaling group -&amp;gt; Instance management -&amp;gt; Create lifecycle hook:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LifecycleHook.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8483i83D5DF4C710454B3/image-size/large?v=v2&amp;amp;px=999" role="button" title="LifecycleHook.png" alt="LifecycleHook.png" /&gt;&lt;/span&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Go back to the Auto Scaling group and change the desired capacity and minimum capacity from 0 to the desired capacity, such as 2.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG_UpdatedCapacity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8568iF5134A3EF31CFFF8/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG_UpdatedCapacity.png" alt="ASG_UpdatedCapacity.png" /&gt;&lt;/span&gt;&lt;BR /&gt;&lt;/SPAN&gt;Now go to Instance management tab and two EC2 proxy servers are launched:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG_InstanceManagement.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8570i24AB50E5620682A0/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG_InstanceManagement.png" alt="ASG_InstanceManagement.png" /&gt;&lt;/span&gt;&lt;BR /&gt;Wait for a few minutes and verify EIP has been assigned to each proxy server&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Proxy_EC2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8488i68EC54489BAFB1D4/image-size/large?v=v2&amp;amp;px=999" role="button" title="Proxy_EC2.png" alt="Proxy_EC2.png" /&gt;&lt;/span&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;SSH into each proxy server separately and configure the Azure Open AI endpoint. In this example, we are using HAProxy server 2.8.3 and below is a sample configuration file at /etc/haproxy/haproxy.cfg:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;global
    log /dev/log local0
    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
    # utilize system-wide crypto-policies
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor except 127.0.0.0/8
    option redispatch
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 3000

frontend main
    bind *:443
    mode tcp
    option tcplog
    default_backend aoai

backend aoai
    mode tcp
    server azure_openai dais24-aoai-demo.openai.azure.com:443 check
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now you can start HAProxy service on each EC2 instance and they should show healthy status on the target group page:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup_HealthyEC2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8491iDFE86EEB52E8AA60/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup_HealthyEC2.png" alt="TargetGroup_HealthyEC2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 4 - Create a VPC endpoint service&lt;/STRONG&gt;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EndPointService.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8492iFB1611F51EA2F6E8/image-size/large?v=v2&amp;amp;px=999" role="button" title="EndPointService.png" alt="EndPointService.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;When creating the VPC endpoint service, check the box “&lt;/SPAN&gt;&lt;STRONG&gt;Acceptance required&lt;/STRONG&gt;&lt;SPAN&gt;” for “Required acceptance for endpoint”:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCE_AcceptanceRequired.png" style="width: 807px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8493iDB46652F2BC4A068/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCE_AcceptanceRequired.png" alt="VPCE_AcceptanceRequired.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;After your VPC endpoint service is created, please allow the Databricks Serverless stable IAM role in the “Allow principals” tab. This will allow Databricks to create one VPC endpoint to link to your VPC endpoint service. &lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Databricks serverless stable IAM role has the format &lt;/SPAN&gt;
&lt;PRE&gt;arn:aws:iam::565502421330:role/private-connectivity-role-&amp;lt;region&amp;gt; &lt;/PRE&gt;
&lt;SPAN&gt;For example, if your VPC endpoint service is in region us-east-1, allowlist &lt;/SPAN&gt;
&lt;PRE&gt;arn:aws:iam::565502421330:role/private-connectivity-role-us-east-1&lt;/PRE&gt;
&lt;SPAN&gt;Alternatively, you could also allowlist * since the network security of your VPC endpoint service is also guaranteed by manually accepting only the VPC endpoint Databricks created for your VPC endpoint service.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EndpointService_AllowPrincipals.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8571i2D59C1FB1BB34F56/image-size/large?v=v2&amp;amp;px=999" role="button" title="EndpointService_AllowPrincipals.png" alt="EndpointService_AllowPrincipals.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 5 - In the Databricks Account console, create a Network Connectivity Config (NCC) object [preview] and a Network Policy object [preview]&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;You can skip this step if there is an existing NCC object and a Network Policy (with restricted access) object that you wish to use for your workspace.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;STRONG&gt;Please contact your account team to be enrolled in both previews&lt;/STRONG&gt;. Once enrolled, you can:&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Log in as a Databricks admin. On the left pane of the Accounts console, navigate to Cloud resources -&amp;gt; Network -&amp;gt; Network Connectivity Configurations, click “Add Network Connectivity Configuration,” enter the NCC name and region, and click “Add” to create the NCC.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_Add.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8495i7C8689CBC1CB6637/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_Add.png" alt="NCC_Add.png" /&gt;&lt;/span&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Go back to the Cloud resources -&amp;gt; Network -&amp;gt; Network Policies, click “Add Network Policy” to open Create new network policy page, enter the policy name, select “Restricted access” for Serverless Internet Access, click Create button to create the network policy.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NetworkPolicy.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8496i3C108CFB16957207/image-size/large?v=v2&amp;amp;px=999" role="button" title="NetworkPolicy.png" alt="NetworkPolicy.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 6 - Create a private endpoint rule in the NCC&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Select the NCC you created in Step 4, navigate to Private endpoint rules, click “Add private endpoint rule”, enter Endpoint service and Domain names, and click “Add” to create the private endpoint rule in the NCC.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;STRONG&gt;Endpoint service&lt;/STRONG&gt;&lt;SPAN&gt; is the service name of the VPC endpoint service that you created in Step 4. In our case, it is &lt;STRONG&gt;&lt;EM&gt;com.amazonaws.vpce.us-east-1.vpce-svc-090fa8dfc6922d838.&lt;BR /&gt;&lt;BR /&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;STRONG&gt;Domain names&lt;/STRONG&gt;&lt;SPAN&gt; is the FQDN of the destination resource. In our case, it is &lt;EM&gt;&lt;STRONG&gt;dais24-aoai-demo.openai.azure.com&lt;/STRONG&gt;&lt;/EM&gt;, the Azure Open AI service you created in Step 1. Please note that it doesn’t include the prefix “https://” of the endpoint.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint1.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8497iFA9BFCA86D86AD5C/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint1.png" alt="NCC_PrivateEndpoint1.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now the private endpoint rule shows PENDING status.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8498i885D6280108DAE29/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint2.png" alt="NCC_PrivateEndpoint2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 7 - Approve the VPC endpoint connection request on the VPC endpoint service in your AWS account&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Go to the VPC endpoint service you created in Step 4, navigate to Endpoint connections, confirm the Endpoint ID matches the VPC endpoint that you created in Step 6, click Actions drop-down menu, select Accept endpoint connection request, and click Accept button on the pop-up window to approve the connection request.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCE_ConnectionRequest_1.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8499i4EB698F0078522B5/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCE_ConnectionRequest_1.png" alt="VPCE_ConnectionRequest_1.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Go back to Private endpoint rules page on Databricks Accounts console, wait for a minute, refresh the page, and now &lt;/SPAN&gt;&lt;SPAN&gt;the private endpoint rule shows ESTABLISHED status.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint3.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8500iF630749E63993650/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint3.png" alt="NCC_PrivateEndpoint3.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 8 - Attach the NCC object and Network Policy object to your workspace and&amp;nbsp; on Databricks Accounts console&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;On Databricks Accounts console, navigate to “Workspaces” on the left pane, select an existing workspace, click Update workspace to open Update workspace page, click Network Connectivity Configuration drop-down menu, select the NCC you created in Step 5, and click Update button to attach NCC object to the workspace.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="UpdateWorkspace.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8501iED2EA8C6E14D844B/image-size/large?v=v2&amp;amp;px=999" role="button" title="UpdateWorkspace.png" alt="UpdateWorkspace.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;On the workspace configuration tab, click “Update network policy” button in the Network Policy box to open “Update workspace network policy” pop-up window, select the Network Policy you created in Step 5, and click Apply policy button to attach the Network Policy object to the workspace.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Attach_Network_Policy.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8502i0CAE46A311A45630/image-size/large?v=v2&amp;amp;px=999" role="button" title="Attach_Network_Policy.png" alt="Attach_Network_Policy.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 9 - Configure Azure Open AI firewall to allow the pool of EIPs attached to the proxy servers&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;On Azure Open AI service you created in step 1, navigate to “Networking” on the left pane, select “Selected Networks and Private Endpoints”, enter the EIPs you created in step 2, and click Save button.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Firewall.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8503iE5196620A1B44CB7/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Firewall.png" alt="AOAI_Firewall.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 10 - Verify the Model Serving endpoint can access Azure Open AI service through the Private endpoint rule in NCC&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Log in to the workspace as a workspace admin and verify if the NCC and Network Policy are applied properly:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Run a Python notebook on an interactive ML cluster to register a model in your workspace model registry which attempts to access the Azure Open AI service. The following Python notebook will register a model named “dais24-aoai-model”:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import mlflow
import mlflow.pyfunc
import requests
import json

class TestSEGModel(mlflow.pyfunc.PythonModel):
    def load_context(self, context):
        pass

    def predict(self, _, model_input):
        first_row = model_input.iloc[0]
        api_key = "xxx"  # Please store the API key in Databricks secret and reference it from the notebook using dbutils.secrets.get
        api_url = "https://dais24-aoai-demo.openai.azure.com/openai/deployments/gpt35-demo/completions?api-version=2024..."
        prompt = first_row['prompt']
        headers = {'api-key': f'{api_key}', 'Content-Type': 'application/json'}
        json_data = {
            "prompt": prompt,
            "max_tokens": 128
        }
        try:
            response = requests.post(api_url, json=json_data, headers=headers)
        except requests.exceptions.RequestException as e:
            # Return the error details as text
            return f"Error: An error occurred - {e}"
        return [response.json()]

with mlflow.start_run(run_name='dais24-aoai-run'):
    wrappedModel = TestSEGModel()
    mlflow.pyfunc.log_model(
        artifact_path="dais24-aoai",
        python_model=wrappedModel,
        registered_model_name="dais24-aoai-model"
    )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Create a Model Serving endpoint serving the model you registered previously&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;SPAN&gt;Go to "Machine Learning" -&amp;gt; "Serving" in the navigation bar on the left side of the screen&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Click "Create serving endpoint" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Name the serving endpoint&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;In "Entity details", choose "Model registry model"&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Select Model "dais24-aoai-model" and click "Confirm" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Select "Compute type" and "Compute scale-out" and click "Create" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Wait for the serving endpoint until the state shows "Ready"&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ModelServingEndpoint_2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8504iE29F9FE8A901A515/image-size/large?v=v2&amp;amp;px=999" role="button" title="ModelServingEndpoint_2.png" alt="ModelServingEndpoint_2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Query the endpoint and verify the Azure Open AI connectivity&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;Request body:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;{
  "dataframe_records": [
    {
      "prompt": "Write 3 reasons why you should train an AI model on domain specific data sets?"
    }
  ]
}
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Since the Azure Open AI firewall whitelisted all EIPs attached to the proxy servers, the query should succeed with the following response:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MLQuery_Good.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8505iDD69645E55692B6F/image-size/large?v=v2&amp;amp;px=999" role="button" title="MLQuery_Good.png" alt="MLQuery_Good.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now intentionally change to the wrong IPs in Azure Open AI firewall:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Firewall_WrongEIP.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8506i0EDA372C05EBBEF5/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Firewall_WrongEIP.png" alt="AOAI_Firewall_WrongEIP.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Query the endpoint again and it should respond with the 403 access denied error:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MLQuery_Bad.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8508iA6237470993AFCD5/image-size/large?v=v2&amp;amp;px=999" role="button" title="MLQuery_Bad.png" alt="MLQuery_Bad.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Terraform Automation&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;We provided the Terraform &lt;A href="https://github.com/huamingliu-db/databricks-aoai-vpce/" target="_self"&gt;code&lt;/A&gt; to help you quickly deploy all the AWS resources mentioned in Step 2 through Step 4. You just need to adjust the environment variables in myvars.auto.tfvars and run “&lt;/SPAN&gt;&lt;SPAN&gt;terraform apply --auto-approve&lt;/SPAN&gt;&lt;SPAN&gt;”.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;STRONG&gt;Disclaimer&lt;/STRONG&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;The Terraform code is provided as a sample for reference and testing purposes only. Please review, modify the code according to your needs, and fully test it before using it in your production environment.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Please keep in mind the following notes for the Terraform code:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;For the proxy server, we use HAProxy as an example. You can choose other proxy services such as &lt;/SPAN&gt;&lt;A href="https://www.squid-cache.org/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;squid&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;A href="https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;nginx&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;If you have existing EIPs in your AWS account, you can remove the “aws_eip” resource and manually add the tag key that is specified in the environment variable “eip_tag_key”.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Based on your workloads, please choose the instance type and auto scaling group maximum size for the best price and performance.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Summary&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;In this post, we presented a sample solution for establishing a secure and dedicated connection between Databricks' serverless model serving endpoint and the Azure OpenAI service. We explored the key design principles underpinning this solution and provided a Terraform template to facilitate immediate testing.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Thu, 13 Jun 2024 22:24:07 GMT</pubDate>
    <dc:creator>HuamingLiu</dc:creator>
    <dc:date>2024-06-13T22:24:07Z</dc:date>
    <item>
      <title>Establishing a secure and dedicated connection to Azure OpenAI</title>
      <link>https://community.databricks.com/t5/technical-blog/establishing-a-secure-and-dedicated-connection-to-azure-openai/ba-p/73719</link>
      <description>&lt;P&gt;&lt;SPAN&gt;With Databricks serverless networking, our goal is to make connectivity secure and simple, with minimal configuration. In turn, you can focus on the data and AI use-cases that matter most to you.&amp;nbsp; One area that we’ve heard a lot of asks around is for keeping a workspace locked down from access to unauthorized resources, while still enabling in-cloud or sometimes even cross-cloud secure connectivity to sanctioned resources.&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;In this blog post, we will address one of the popular customer requests for such a cross-cloud scenario: locking down access to the internet from your serverless workloads on AWS, but enabling access to Azure Open AI through a dedicated, per-customer connection. &lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Architecture Diagram&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Serverless Model Azure Private Connectivity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8177iF4FE3CECFAC2684B/image-size/large?v=v2&amp;amp;px=999" role="button" title="Serverless Model Azure Private Connectivity.png" alt="Serverless Model Azure Private Connectivity.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Design Walkthrough&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;To control access to the internet from your serverless workloads, we're enhancing egress control capabilities.&amp;nbsp; P&lt;/SPAN&gt;&lt;SPAN&gt;lease use&amp;nbsp;&lt;A href="https://docs.google.com/forms/d/e/1FAIpQLSdTsFj01Y7b3WWKUSK9X6Tj75wMJLGfgd-S6UobUZOgatXDjQ/viewform" target="_blank" rel="noopener"&gt;this form&lt;/A&gt; to join our previews, or contact your account team to learn more.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;To establish a dedicated connection through the model serving endpoint to Azure OpenAI, two critical connections are required: the connection between the model serving endpoint and the customer's VPC in AWS, and the connection from the customer's VPC to Azure OpenAI.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;1: Connection between model serving endpoint and customer VPC.&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Databricks' serverless compute plane networking is managed by &lt;/SPAN&gt;&lt;A href="https://docs.databricks.com/en/security/network/serverless-network-security/index.html#what-is-a-network-connectivity-configuration-ncc" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;Network Connectivity Configuration (NCC)&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;. Each NCC container currently offers two options:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Stable IPs:&lt;/STRONG&gt;&lt;SPAN&gt; Public IPs that provide access to your resources (public preview)&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Private Endpoint Service:&lt;/STRONG&gt;&lt;SPAN&gt; VPC endpoints that facilitate PrivateLink connections (private preview)&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;For maximum security, we recommend using AWS PrivateLink from serverless, which is also the approach we adopt in our example configuration.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN&gt;2:&amp;nbsp;Connection between customer VPC to Azure OpenAI.&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Let’s take a closer look at the architecture:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Serverless Model Private Connectivity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8178i7F2D5FBF39DF6CC3/image-size/large?v=v2&amp;amp;px=999" role="button" title="Serverless Model Private Connectivity.png" alt="Serverless Model Private Connectivity.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;At the heart of the setup, we deployed HAProxy on EC2 instances as a Layer 4 forwarding mechanism. Requests from the model serving nodes are routed through PrivateLink to HAProxy servers, which then forward these requests directly to Azure OpenAI. To enhance the enterprise-readiness of the solution, we implement several features:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;On AWS:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Autoscaling for HAProxy Servers:&lt;/STRONG&gt;&lt;SPAN&gt; This introduces better fault tolerance and availability. Our solution is configured to use multiple availability zones and based on your access pattern, you have the flexibility to configure the scaling criteria so that it always has the right amount of capacity.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Automated stable IP Assignment and Recycle:&lt;/STRONG&gt;&lt;SPAN&gt; This is implemented via&lt;A href="https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html" target="_blank" rel="noopener"&gt; Autoscaling lifecycle hooks&lt;/A&gt; and AWS Lambda to minimize operational overhead. We will only pick the IPs that are allowed in Azure OpenAI firewall. Each scale-out event triggers a Lambda function that assigns an unassigned IP from the pool to the new instance. If no IP is available, the instance launch is aborted to maintain uninterrupted service.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;On Azure:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;STRONG&gt;Azure OpenAI Firewall:&lt;/STRONG&gt;&lt;SPAN&gt; This restricts access to only authorized IP addresses for greater security. We establish an Elastic IP (EIP) pool for all HAProxy servers and configure Azure OpenAI service to permit access solely from this IP pool.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;Constructing a VPN connection between Amazon VPC and Azure VNet is possible for those wishing to eliminate public access entirely. Please reach out to your account team for guidance if you would like to go this route.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Implementation Walkthrough&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;This section describes the detailed steps to configure a dedicated and secured connection to Azure Open AI service for your workspace.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 1 - Create and deploy an Azure OpenAI Service resource in your Azure subscription&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Follow the Azure documentation to &lt;/SPAN&gt;&lt;A href="https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource?pivots=web-portal" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;create an Azure OpenAI service&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; and deploy a model.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="CreateAOAI_3.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8537i9FE4C2A25F4409A7/image-size/large?v=v2&amp;amp;px=999" role="button" title="CreateAOAI_3.png" alt="CreateAOAI_3.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_DeployModel.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8540i4B8069F9EB15CA46/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_DeployModel.png" alt="AOAI_DeployModel.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Endpoint.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8541iF9367CE6AEF80327/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Endpoint.png" alt="AOAI_Endpoint.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Once Azure Open AI service is available, please note down the deployment name and endpoint. This will be used later to configure the proxy server backend and construct the API URL when registering your MLFlow model in Databricks model registry.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 2 - Create all the AWS resources required for the VPC endpoint service in your AWS account&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;The following AWS resources are required to build the VPC endpoint service:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;One &lt;STRONG&gt;VPC&lt;/STRONG&gt; with multiple &lt;STRONG&gt;private subnets&lt;/STRONG&gt; (for the network load balancer (NLB)) and &lt;STRONG&gt;public subnets&lt;/STRONG&gt; (for proxy servers), and &lt;STRONG&gt;two security groups&lt;/STRONG&gt;, one for NLB and one for the Launch Template&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCCreation.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8558i9D207F64DF88E027/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCCreation.png" alt="VPCCreation.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NLB_SG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8559iD910C3A4DC66E4CC/image-size/large?v=v2&amp;amp;px=999" role="button" title="NLB_SG.png" alt="NLB_SG.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate_SG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8560iF3A33ABCFC48F2CE/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate_SG.png" alt="LaunchTemplate_SG.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A pool of &lt;STRONG&gt;Elastic IPs (EIP)&lt;/STRONG&gt; that will be attached to the proxy servers and used for Azure Open AI firewall whitelisting&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EIP.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8546i2DEFD43735B89FAC/image-size/large?v=v2&amp;amp;px=999" role="button" title="EIP.png" alt="EIP.png" /&gt;&lt;/span&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EIP_Pool.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8547i69BF41C876DFFB30/image-size/large?v=v2&amp;amp;px=999" role="button" title="EIP_Pool.png" alt="EIP_Pool.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Please tag the EIPs properly as the tag &lt;/EM&gt;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;key&lt;/STRONG&gt; (not tag value) will be used to identify the EIP pool in the Lambda function. In our example, only the EIPs with tag key “dais24_eip” will be assigned to the proxy servers.&lt;/EM&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;&lt;STRONG&gt;A Launch Template&lt;/STRONG&gt; that specifies the instance configuration for the proxy server&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8561i7E75A4D2A9C5FBC1/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate.png" alt="LaunchTemplate.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: Optionally, you can write a shell script to install the proxy server and put it in the user data field in Advanced details section of Launch Template.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LaunchTemplate_UserData.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8474i536A621F45DEF747/image-size/large?v=v2&amp;amp;px=999" role="button" title="LaunchTemplate_UserData.png" alt="LaunchTemplate_UserData.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Below is a sample user data shell script:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;#!/bin/bash

# Fetch the token required for IMDSv2
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Fetch the public IP address of the instance using the token
PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4)

# Check if the public IP address is not empty
if [ -n "$PUBLIC_IP" ]; then
  echo "Public IP found: $PUBLIC_IP"
  echo "Installing HAProxy..."

  # Update the package repository and install HAProxy
  sudo yum update -y
  sudo yum install haproxy -y

  # Enable and start the HAProxy service
  # systemctl enable haproxy
  # systemctl start haproxy

  echo "HAProxy installation completed."

else
  echo "No public IP assigned to this instance. Skipping HAProxy installation."
fi
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;NLB&lt;/STRONG&gt; target group&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8577i8AC27E3FF2BDBB17/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup.png" alt="TargetGroup.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: When creating the NLB, please select TCP port 443 in Basic configuration section and TCP protocol in Health checks section&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup_HealthCheck.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8563iE6B84A49CE684BFB/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup_HealthCheck.png" alt="TargetGroup_HealthCheck.png" /&gt;&lt;/span&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;NLB&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NLB.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8581iC8C6A462F8118BA4/image-size/large?v=v2&amp;amp;px=999" role="button" title="NLB.png" alt="NLB.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An &lt;STRONG&gt;Auto Scaling group&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8565iFCA3D3F1CAA15D79/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG.png" alt="ASG.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;EM&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;NOTE: Please set the initial desired capacity and minimum capacity to 0 when creating the Auto Scaling group. If these two parameters are not set to 0, the EC2 proxy servers will be launched immediately but no EIPs will be assigned. The reason is that the lifecycle hook does not exist at this point and the Lambda function that is used to assign EIPs will not be triggered. You need to manually update them to the actual values once the lifecycle hook is created.&lt;/EM&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An execution &lt;STRONG&gt;IAM role&lt;/STRONG&gt; of the Lambda function&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;The following IAM permissions need to be granted to the role:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "autoscaling:CompleteLifecycleAction"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": [
        "ec2:AssociateAddress",
        "ec2:DisassociateAddress",
        "ec2:DescribeInstances",
        "ec2:DescribeAddresses",
        "ec2:CreateTags"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": "logs:CreateLogGroup",
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;A &lt;STRONG&gt;Lambda function&lt;/STRONG&gt; that is used to assign EIPs to the proxy servers&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Lambda.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8566iFE3AC389EB2A4BD6/image-size/large?v=v2&amp;amp;px=999" role="button" title="Lambda.png" alt="Lambda.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;Below is a sample Python code of the Lambda function:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import boto3

def lambda_handler(event, context):
    # Create a new EC2 client
    ec2_client = boto3.client('ec2')
    as_client = boto3.client('autoscaling')

    # Get the list of all available Elastic IPs from EIP pool where tag-key filter needs to match the EIP tag key
    eips = ec2_client.describe_addresses(Filters=[{'Name': 'tag-key', 'Values': ['dais24_eip']}])
    aval_eips = [eip for eip in eips['Addresses'] if 'AssociationId' not in eip]

    if not aval_eips:
        raise Exception('No free EIPs available')

    instance_id = event['detail']["EC2InstanceId"]
    eip = aval_eips[0]['AllocationId']

    # Associate the EIP with the instance
    ec2_client.associate_address(AllocationId=eip, InstanceId=instance_id)

    # Complete the lifecycle action
    response = as_client.complete_lifecycle_action(
        LifecycleHookName=event['detail']["LifecycleHookName"],
        AutoScalingGroupName=event['detail']['AutoScalingGroupName'],
        LifecycleActionToken=event['detail']['LifecycleActionToken'],
        LifecycleActionResult='CONTINUE',
        InstanceId=instance_id
    )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":warning:"&gt;⚠️&lt;/span&gt;&lt;EM&gt;NOTE: The Lambda function's timeout should be set to 10 seconds.&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL class="lia-list-style-type-disc"&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;An &lt;STRONG&gt;EventBridge rule&lt;/STRONG&gt; with the source as the Auto Scaling group lifecycle hook and target as the Lambda function.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EventBridgeRule.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8482i73E242EB85C53688/image-size/large?v=v2&amp;amp;px=999" role="button" title="EventBridgeRule.png" alt="EventBridgeRule.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;An &lt;STRONG&gt;Auto Scaling group lifecycle hook&lt;/STRONG&gt; that reacts to the scale out event.&lt;BR /&gt;&lt;/SPAN&gt;Go back to the Auto Scaling group -&amp;gt; Instance management -&amp;gt; Create lifecycle hook:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="LifecycleHook.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8483i83D5DF4C710454B3/image-size/large?v=v2&amp;amp;px=999" role="button" title="LifecycleHook.png" alt="LifecycleHook.png" /&gt;&lt;/span&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Go back to the Auto Scaling group and change the desired capacity and minimum capacity from 0 to the desired capacity, such as 2.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG_UpdatedCapacity.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8568iF5134A3EF31CFFF8/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG_UpdatedCapacity.png" alt="ASG_UpdatedCapacity.png" /&gt;&lt;/span&gt;&lt;BR /&gt;&lt;/SPAN&gt;Now go to Instance management tab and two EC2 proxy servers are launched:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ASG_InstanceManagement.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8570i24AB50E5620682A0/image-size/large?v=v2&amp;amp;px=999" role="button" title="ASG_InstanceManagement.png" alt="ASG_InstanceManagement.png" /&gt;&lt;/span&gt;&lt;BR /&gt;Wait for a few minutes and verify EIP has been assigned to each proxy server&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Proxy_EC2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8488i68EC54489BAFB1D4/image-size/large?v=v2&amp;amp;px=999" role="button" title="Proxy_EC2.png" alt="Proxy_EC2.png" /&gt;&lt;/span&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;SSH into each proxy server separately and configure the Azure Open AI endpoint. In this example, we are using HAProxy server 2.8.3 and below is a sample configuration file at /etc/haproxy/haproxy.cfg:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;global
    log /dev/log local0
    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
    # utilize system-wide crypto-policies
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor except 127.0.0.0/8
    option redispatch
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 3000

frontend main
    bind *:443
    mode tcp
    option tcplog
    default_backend aoai

backend aoai
    mode tcp
    server azure_openai dais24-aoai-demo.openai.azure.com:443 check
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now you can start HAProxy service on each EC2 instance and they should show healthy status on the target group page:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TargetGroup_HealthyEC2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8491iDFE86EEB52E8AA60/image-size/large?v=v2&amp;amp;px=999" role="button" title="TargetGroup_HealthyEC2.png" alt="TargetGroup_HealthyEC2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 4 - Create a VPC endpoint service&lt;/STRONG&gt;&lt;/H3&gt;
&lt;H3&gt;&lt;STRONG&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EndPointService.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8492iFB1611F51EA2F6E8/image-size/large?v=v2&amp;amp;px=999" role="button" title="EndPointService.png" alt="EndPointService.png" /&gt;&lt;/span&gt;&lt;/STRONG&gt;&lt;/H3&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;When creating the VPC endpoint service, check the box “&lt;/SPAN&gt;&lt;STRONG&gt;Acceptance required&lt;/STRONG&gt;&lt;SPAN&gt;” for “Required acceptance for endpoint”:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCE_AcceptanceRequired.png" style="width: 807px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8493iDB46652F2BC4A068/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCE_AcceptanceRequired.png" alt="VPCE_AcceptanceRequired.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;After your VPC endpoint service is created, please allow the Databricks Serverless stable IAM role in the “Allow principals” tab. This will allow Databricks to create one VPC endpoint to link to your VPC endpoint service. &lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Databricks serverless stable IAM role has the format &lt;/SPAN&gt;
&lt;PRE&gt;arn:aws:iam::565502421330:role/private-connectivity-role-&amp;lt;region&amp;gt; &lt;/PRE&gt;
&lt;SPAN&gt;For example, if your VPC endpoint service is in region us-east-1, allowlist &lt;/SPAN&gt;
&lt;PRE&gt;arn:aws:iam::565502421330:role/private-connectivity-role-us-east-1&lt;/PRE&gt;
&lt;SPAN&gt;Alternatively, you could also allowlist * since the network security of your VPC endpoint service is also guaranteed by manually accepting only the VPC endpoint Databricks created for your VPC endpoint service.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="EndpointService_AllowPrincipals.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8571i2D59C1FB1BB34F56/image-size/large?v=v2&amp;amp;px=999" role="button" title="EndpointService_AllowPrincipals.png" alt="EndpointService_AllowPrincipals.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 5 - In the Databricks Account console, create a Network Connectivity Config (NCC) object [preview] and a Network Policy object [preview]&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;You can skip this step if there is an existing NCC object and a Network Policy (with restricted access) object that you wish to use for your workspace.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;STRONG&gt;Please contact your account team to be enrolled in both previews&lt;/STRONG&gt;. Once enrolled, you can:&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;Log in as a Databricks admin. On the left pane of the Accounts console, navigate to Cloud resources -&amp;gt; Network -&amp;gt; Network Connectivity Configurations, click “Add Network Connectivity Configuration,” enter the NCC name and region, and click “Add” to create the NCC.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_Add.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8495i7C8689CBC1CB6637/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_Add.png" alt="NCC_Add.png" /&gt;&lt;/span&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Go back to the Cloud resources -&amp;gt; Network -&amp;gt; Network Policies, click “Add Network Policy” to open Create new network policy page, enter the policy name, select “Restricted access” for Serverless Internet Access, click Create button to create the network policy.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NetworkPolicy.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8496i3C108CFB16957207/image-size/large?v=v2&amp;amp;px=999" role="button" title="NetworkPolicy.png" alt="NetworkPolicy.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 6 - Create a private endpoint rule in the NCC&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Select the NCC you created in Step 4, navigate to Private endpoint rules, click “Add private endpoint rule”, enter Endpoint service and Domain names, and click “Add” to create the private endpoint rule in the NCC.&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;STRONG&gt;Endpoint service&lt;/STRONG&gt;&lt;SPAN&gt; is the service name of the VPC endpoint service that you created in Step 4. In our case, it is &lt;STRONG&gt;&lt;EM&gt;com.amazonaws.vpce.us-east-1.vpce-svc-090fa8dfc6922d838.&lt;BR /&gt;&lt;BR /&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;The &lt;/SPAN&gt;&lt;STRONG&gt;Domain names&lt;/STRONG&gt;&lt;SPAN&gt; is the FQDN of the destination resource. In our case, it is &lt;EM&gt;&lt;STRONG&gt;dais24-aoai-demo.openai.azure.com&lt;/STRONG&gt;&lt;/EM&gt;, the Azure Open AI service you created in Step 1. Please note that it doesn’t include the prefix “https://” of the endpoint.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint1.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8497iFA9BFCA86D86AD5C/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint1.png" alt="NCC_PrivateEndpoint1.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now the private endpoint rule shows PENDING status.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8498i885D6280108DAE29/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint2.png" alt="NCC_PrivateEndpoint2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 7 - Approve the VPC endpoint connection request on the VPC endpoint service in your AWS account&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Go to the VPC endpoint service you created in Step 4, navigate to Endpoint connections, confirm the Endpoint ID matches the VPC endpoint that you created in Step 6, click Actions drop-down menu, select Accept endpoint connection request, and click Accept button on the pop-up window to approve the connection request.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="VPCE_ConnectionRequest_1.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8499i4EB698F0078522B5/image-size/large?v=v2&amp;amp;px=999" role="button" title="VPCE_ConnectionRequest_1.png" alt="VPCE_ConnectionRequest_1.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Go back to Private endpoint rules page on Databricks Accounts console, wait for a minute, refresh the page, and now &lt;/SPAN&gt;&lt;SPAN&gt;the private endpoint rule shows ESTABLISHED status.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="NCC_PrivateEndpoint3.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8500iF630749E63993650/image-size/large?v=v2&amp;amp;px=999" role="button" title="NCC_PrivateEndpoint3.png" alt="NCC_PrivateEndpoint3.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 8 - Attach the NCC object and Network Policy object to your workspace and&amp;nbsp; on Databricks Accounts console&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;On Databricks Accounts console, navigate to “Workspaces” on the left pane, select an existing workspace, click Update workspace to open Update workspace page, click Network Connectivity Configuration drop-down menu, select the NCC you created in Step 5, and click Update button to attach NCC object to the workspace.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="UpdateWorkspace.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8501iED2EA8C6E14D844B/image-size/large?v=v2&amp;amp;px=999" role="button" title="UpdateWorkspace.png" alt="UpdateWorkspace.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;On the workspace configuration tab, click “Update network policy” button in the Network Policy box to open “Update workspace network policy” pop-up window, select the Network Policy you created in Step 5, and click Apply policy button to attach the Network Policy object to the workspace.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Attach_Network_Policy.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8502i0CAE46A311A45630/image-size/large?v=v2&amp;amp;px=999" role="button" title="Attach_Network_Policy.png" alt="Attach_Network_Policy.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 9 - Configure Azure Open AI firewall to allow the pool of EIPs attached to the proxy servers&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;On Azure Open AI service you created in step 1, navigate to “Networking” on the left pane, select “Selected Networks and Private Endpoints”, enter the EIPs you created in step 2, and click Save button.&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Firewall.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8503iE5196620A1B44CB7/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Firewall.png" alt="AOAI_Firewall.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;Step 10 - Verify the Model Serving endpoint can access Azure Open AI service through the Private endpoint rule in NCC&lt;/STRONG&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN&gt;Log in to the workspace as a workspace admin and verify if the NCC and Network Policy are applied properly:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Run a Python notebook on an interactive ML cluster to register a model in your workspace model registry which attempts to access the Azure Open AI service. The following Python notebook will register a model named “dais24-aoai-model”:&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import mlflow
import mlflow.pyfunc
import requests
import json

class TestSEGModel(mlflow.pyfunc.PythonModel):
    def load_context(self, context):
        pass

    def predict(self, _, model_input):
        first_row = model_input.iloc[0]
        api_key = "xxx"  # Please store the API key in Databricks secret and reference it from the notebook using dbutils.secrets.get
        api_url = "https://dais24-aoai-demo.openai.azure.com/openai/deployments/gpt35-demo/completions?api-version=2024..."
        prompt = first_row['prompt']
        headers = {'api-key': f'{api_key}', 'Content-Type': 'application/json'}
        json_data = {
            "prompt": prompt,
            "max_tokens": 128
        }
        try:
            response = requests.post(api_url, json=json_data, headers=headers)
        except requests.exceptions.RequestException as e:
            # Return the error details as text
            return f"Error: An error occurred - {e}"
        return [response.json()]

with mlflow.start_run(run_name='dais24-aoai-run'):
    wrappedModel = TestSEGModel()
    mlflow.pyfunc.log_model(
        artifact_path="dais24-aoai",
        python_model=wrappedModel,
        registered_model_name="dais24-aoai-model"
    )
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Create a Model Serving endpoint serving the model you registered previously&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;SPAN&gt;Go to "Machine Learning" -&amp;gt; "Serving" in the navigation bar on the left side of the screen&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Click "Create serving endpoint" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Name the serving endpoint&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;In "Entity details", choose "Model registry model"&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Select Model "dais24-aoai-model" and click "Confirm" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Select "Compute type" and "Compute scale-out" and click "Create" button&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN&gt;Wait for the serving endpoint until the state shows "Ready"&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ModelServingEndpoint_2.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8504iE29F9FE8A901A515/image-size/large?v=v2&amp;amp;px=999" role="button" title="ModelServingEndpoint_2.png" alt="ModelServingEndpoint_2.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Query the endpoint and verify the Azure Open AI connectivity&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN&gt;Request body:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;{
  "dataframe_records": [
    {
      "prompt": "Write 3 reasons why you should train an AI model on domain specific data sets?"
    }
  ]
}
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Since the Azure Open AI firewall whitelisted all EIPs attached to the proxy servers, the query should succeed with the following response:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MLQuery_Good.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8505iDD69645E55692B6F/image-size/large?v=v2&amp;amp;px=999" role="button" title="MLQuery_Good.png" alt="MLQuery_Good.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Now intentionally change to the wrong IPs in Azure Open AI firewall:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AOAI_Firewall_WrongEIP.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8506i0EDA372C05EBBEF5/image-size/large?v=v2&amp;amp;px=999" role="button" title="AOAI_Firewall_WrongEIP.png" alt="AOAI_Firewall_WrongEIP.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Query the endpoint again and it should respond with the 403 access denied error:&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MLQuery_Bad.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/8508iA6237470993AFCD5/image-size/large?v=v2&amp;amp;px=999" role="button" title="MLQuery_Bad.png" alt="MLQuery_Bad.png" /&gt;&lt;/span&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;&lt;SPAN&gt;Terraform Automation&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;We provided the Terraform &lt;A href="https://github.com/huamingliu-db/databricks-aoai-vpce/" target="_self"&gt;code&lt;/A&gt; to help you quickly deploy all the AWS resources mentioned in Step 2 through Step 4. You just need to adjust the environment variables in myvars.auto.tfvars and run “&lt;/SPAN&gt;&lt;SPAN&gt;terraform apply --auto-approve&lt;/SPAN&gt;&lt;SPAN&gt;”.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H4&gt;&lt;STRONG&gt;Disclaimer&lt;/STRONG&gt;&lt;/H4&gt;
&lt;P&gt;&lt;SPAN&gt;The Terraform code is provided as a sample for reference and testing purposes only. Please review, modify the code according to your needs, and fully test it before using it in your production environment.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Please keep in mind the following notes for the Terraform code:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;For the proxy server, we use HAProxy as an example. You can choose other proxy services such as &lt;/SPAN&gt;&lt;A href="https://www.squid-cache.org/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;squid&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;A href="https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/" target="_blank" rel="noopener"&gt;&lt;SPAN&gt;nginx&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;If you have existing EIPs in your AWS account, you can remove the “aws_eip” resource and manually add the tag key that is specified in the environment variable “eip_tag_key”.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="font-weight: 400;" aria-level="1"&gt;&lt;SPAN&gt;Based on your workloads, please choose the instance type and auto scaling group maximum size for the best price and performance.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;&lt;SPAN&gt;Summary&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN&gt;In this post, we presented a sample solution for establishing a secure and dedicated connection between Databricks' serverless model serving endpoint and the Azure OpenAI service. We explored the key design principles underpinning this solution and provided a Terraform template to facilitate immediate testing.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 13 Jun 2024 22:24:07 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/establishing-a-secure-and-dedicated-connection-to-azure-openai/ba-p/73719</guid>
      <dc:creator>HuamingLiu</dc:creator>
      <dc:date>2024-06-13T22:24:07Z</dc:date>
    </item>
  </channel>
</rss>

