システム構成
概要
DatabricksをVNETインジェクションで構成し、公衆ネットワーク アクセスを許可せずに内部のプライベートエンドポイント経由でVPNを使用してアクセスを行います。
サブネットは、①VPN作成時に必要なGatewaySubnet、②③はDNS Private Resolverに必要なinboundとoutboundに使用、④はdatabricksに必要なプライベートエンドポイントポイントを置くためにあります。
VPNからポイント対サイトで資格証明書を持っているクライアントPCからのみアクセス出来るようにします。
まとめると、特定の証明書をインストールしたPCからVPNを起動するとDatabricksにアクセス出来る手順を以下に記載させて頂きます。
構築
今回画面操作で構築すると時間が掛かるのでBicepでデプロイを行います。
以下に解説の記事を書いています。
Databricksのデプロイ
databricksのARMはMicrosoftが公開しているものがあるので、Bicepにデコンパイルします。
以下デコンパイルして修正したものになります。
ローカル環境でbicepファイルを作成し内容をコピーします。
//secure cluster connectivity (SCC) を設定
var disablePublicIp = true
var location = 'japaneast'
var nsgName = 'databricks-nsg'
var pricingTier = 'premium'
var privateSubnetCidr = '10.179.0.0/18'
var privateSubnetName = 'private-subnet'
//公共アクセスを無効化
var publicNetworkAccess = 'Disabled'
var publicSubnetCidr = '10.179.64.0/18'
var privateEndpointSubnetCidr = '10.179.128.0/24'
var publicSubnetName = 'public-subnet'
var requiredNsgRules = 'NoAzureDatabricksRules'
var vnetCidr = '10.179.0.0/16'
var vnetName = 'databricks-vnet'
var workspaceName = 'default'
var managedResourceGroupName = 'databricks-rg-${workspaceName}-${uniqueString(workspaceName, resourceGroup().id)}'
var PrivateEndpointSubnetName = 'default'
var private_endpoint_name_ui_api = '${workspaceName}-pvtEndpoint-ui-api'
var private_endpoint_name_browser = '${workspaceName}-pvtEndpoint-broweser'
var privateDnsZoneName = 'privatelink.azuredatabricks.net'
resource nsg 'Microsoft.Network/networkSecurityGroups@2021-03-01' = {
name: nsgName
location: location
properties: {
securityRules: [
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound'
properties: {
description: 'Required for worker nodes communication within a cluster.'
protocol: '*'
sourcePortRange: '*'
destinationPortRange: '*'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'VirtualNetwork'
access: 'Allow'
priority: 100
direction: 'Inbound'
}
}
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-databricks-webapp'
properties: {
description: 'Required for workers communication with Databricks Webapp.'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '443'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'AzureDatabricks'
access: 'Allow'
priority: 100
direction: 'Outbound'
}
}
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql'
properties: {
description: 'Required for workers communication with Azure SQL services.'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '3306'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'Sql'
access: 'Allow'
priority: 101
direction: 'Outbound'
}
}
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage'
properties: {
description: 'Required for workers communication with Azure Storage services.'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '443'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'Storage'
access: 'Allow'
priority: 102
direction: 'Outbound'
}
}
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound'
properties: {
description: 'Required for worker nodes communication within a cluster.'
protocol: '*'
sourcePortRange: '*'
destinationPortRange: '*'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'VirtualNetwork'
access: 'Allow'
priority: 103
direction: 'Outbound'
}
}
{
name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub'
properties: {
description: 'Required for worker communication with Azure Eventhub services.'
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '9093'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: 'EventHub'
access: 'Allow'
priority: 104
direction: 'Outbound'
}
}
]
}
}
resource vnet 'Microsoft.Network/virtualNetworks@2021-08-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
vnetCidr
]
}
subnets: [
{
name: publicSubnetName
properties: {
addressPrefix: publicSubnetCidr
networkSecurityGroup: {
id: nsg.id
}
delegations: [
{
name: 'databricks-del-public'
properties: {
serviceName: 'Microsoft.Databricks/workspaces'
}
}
]
}
}
{
name: privateSubnetName
properties: {
addressPrefix: privateSubnetCidr
networkSecurityGroup: {
id: nsg.id
}
delegations: [
{
name: 'databricks-del-private'
properties: {
serviceName: 'Microsoft.Databricks/workspaces'
}
}
]
}
}
{
name: PrivateEndpointSubnetName
properties: {
addressPrefix: privateEndpointSubnetCidr
privateEndpointNetworkPolicies: 'Disabled'
}
}
]
}
}
resource workspace 'Microsoft.Databricks/workspaces@2021-04-01-preview' = {
name: workspaceName
location: location
sku: {
name: pricingTier
}
properties: {
managedResourceGroupId: subscriptionResourceId('Microsoft.Resources/resourceGroups', managedResourceGroupName)
parameters: {
customVirtualNetworkId: {
value: vnet.id
}
customPublicSubnetName: {
value: publicSubnetName
}
customPrivateSubnetName: {
value: privateSubnetName
}
enableNoPublicIp: {
value: disablePublicIp
}
}
publicNetworkAccess: publicNetworkAccess
requiredNsgRules: requiredNsgRules
}
}
resource pe_ui 'Microsoft.Network/privateEndpoints@2021-08-01' = {
name: private_endpoint_name_ui_api
location: location
properties: {
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, PrivateEndpointSubnetName)
}
privateLinkServiceConnections: [
{
name: private_endpoint_name_ui_api
properties: {
privateLinkServiceId: '${resourceGroup().id}/providers/Microsoft.Databricks/workspaces/${workspaceName}'
groupIds: [
'databricks_ui_api'
]
}
}
]
}
dependsOn: [
workspace
]
}
resource pe_browser 'Microsoft.Network/privateEndpoints@2021-08-01' = {
name: private_endpoint_name_browser
location: location
properties: {
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, PrivateEndpointSubnetName)
}
privateLinkServiceConnections: [
{
name: private_endpoint_name_browser
properties: {
privateLinkServiceId: '${resourceGroup().id}/providers/Microsoft.Databricks/workspaces/${workspaceName}'
groupIds: [
'browser_authentication'
]
}
}
]
}
dependsOn: [
pe_ui
]
}
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: privateDnsZoneName
location: 'global'
dependsOn: [
pe_ui
]
}
resource privateDnsZoneName_privateDnsZoneName_link 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
parent: privateDnsZone
name: '${privateDnsZoneName}-link'
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: vnet.id
}
}
}
resource privateEndpoints_test2_name_default 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-05-01' = {
name: '${pe_ui.name}/default'
properties: {
privateDnsZoneConfigs: [
{
name: 'privatelink_azuredatabricks_net'
properties: {
privateDnsZoneId: privateDnsZone.id
}
}
]
}
dependsOn: [
pe_ui
]
}
resource privateEndpoints_jwits_test_pvtEndpoint_name_mydnsgroupname 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-05-01' = {
name: '${pe_browser.name}/default2'
properties: {
privateDnsZoneConfigs: [
{
name: 'config1'
properties: {
privateDnsZoneId: privateDnsZone.id
}
}
]
}
dependsOn: [
pe_browser
]
}
az login
した後に
az deployment group create --resource-group デプロイリソースグループ --template-file DatabricksDeploy.bicepのファイルパス
を実行します。
デプロイの進捗はリソースグループのデプロイから確認が出来ます。
公共からのアクセスを無効にしているため、アクセス出来ないことが確認できます。
VPNのデプロイ
次にVirtualNetworkGateway(VPN)をデプロイしていきます。
証明書発行
PowerShellで下記コマンドからルート証明書を生成して、ウインドウを閉じないままにしておきます。
$cert = New-SelfSignedCertificate -Type Custom -KeySpec Signature `
-Subject "CN=P2SRootCert" -KeyExportPolicy Exportable `
-HashAlgorithm sha256 -KeyLength 2048 `
-CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign
実行後、検索欄で「certmgr.msc」を検索してクリックします。
「個人」→「証明書」をクリックし、生成された証明書を確認します。
先程のPowerShellを実行した画面で下記コマンドを実行します。
New-SelfSignedCertificate -Type Custom -DnsName P2SChildCert -KeySpec Signature `
-Subject "CN=P2SChildCert" -KeyExportPolicy Exportable `
-HashAlgorithm sha256 -KeyLength 2048 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-Signer $cert -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2")
更新コマンドをクリックし、クライアント証明書が生成されているのを確認します。
PS2RootCertを右クリックし、「すべてのタスク」→「エクスポート」をクリックします。
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
を除く文字列を下記にあるVpnDeploy.bicepのvpn_certification変数にセットします。
セット後、下記のVpnDeploy.bicepをデプロイします。
完了までに時間が掛かるので注意が必要です。
//生成したルート証明書
var vpn_certification = ''
var vnet_name = 'databricks-vnet'
var location = 'japaneast'
var gateway_subnet_cidr = '10.179.255.0/24'
var vpn_gateway_cidr = '172.16.1.0/24'
var vpn_certification_name = 'クライアントルート証明書'
resource vnet 'Microsoft.Network/virtualNetworks@2022-07-01' existing = {
name: vnet_name
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-08-01' = {
name: 'GatewaySubnet'
parent: vnet
properties: {
addressPrefix: gateway_subnet_cidr
delegations: []
}
}
resource public 'Microsoft.Network/publicIPAddresses@2022-07-01' = {
name: 'gateway_ip'
location: location
}
resource gateway 'Microsoft.Network/virtualNetworkGateways@2020-07-01' = {
name: 'vpn'
location: location
properties: {
gatewayType: 'vpn'
vpnGatewayGeneration: 'Generation1'
vpnType: 'RouteBased'
sku: {
name: 'VpnGw1'
tier: 'VpnGw1'
}
ipConfigurations: [
{
name: 'GatewayConfig'
properties: {
subnet: {
id: '${vnet.id}/subnets/GatewaySubnet'
}
publicIPAddress: {
id: public.id
}
}
}
]
vpnClientConfiguration: {
vpnClientAddressPool: {
addressPrefixes: [
vpn_gateway_cidr
]
}
vpnClientProtocols: [
'IkeV2'
]
vpnAuthenticationTypes: [
'Certificate'
]
vpnClientRootCertificates: [
{
name: vpn_certification_name
properties: {
publicCertData: vpn_certification
}
}
]
}
}
dependsOn: [
public
subnet
]
}
VPN設定
デプロイ完了後に、「vpn」という名前の仮想ゲートウェイをクリックします。
左欄から「ポイント対サイトの構成」をクリックし、「VPNクライアントのダウンロード」をクリックします。
VpnSettings.xmlので囲まれている部分を以下のVPN接続情報にセットして作成します。
DNS Private Resolverのデプロイ
最後にdatabricksがDNSを解決出来るように、DNS Private Resolverをデプロイします。
まずリソース一覧から「privatelink.azuredatabricks.net」をクリックします。
画像では「adb-5113875134185442.2」、「10.179.128.4」となっていますが、この部分はdatabricksデプロイ時にランダムで割り当てられます。
下記のResolverDeploy.bicepのDomainName変数に「adb-5113875134185442.2.」、targetDNSのingressに「10.179.128.4」を例としてセットします。
※ドメイン後ろに.を追加してそれぞれの環境で確認した値をセットしてください。
以下ファイルを変数セット後デプロイします。
//Databricksドメイン設定
var DomainName = ''
//DatabricksのプライベートIp設定
var targetDNS = [
{
ipaddress: ''
port: 53
}
]
var resolverVNETName = 'databricks-vnet'
var dnsResolverName = 'dnsResolver'
var location = 'japaneast'
var inboundSubnet = 'inbound'
var inboundAddressPrefix = '10.179.129.0/24'
var outboundSubnet = 'outbound'
var outboundAddressPrefix = '10.179.130.0/24'
var resolvervnetlink = 'vnetlink'
var forwardingRulesetName = 'forwardingRule'
var forwardingRuleName = 'routing_databricks'
resource vnet 'Microsoft.Network/virtualNetworks@2022-07-01' existing = {
name: resolverVNETName
}
resource subnet1 'Microsoft.Network/virtualNetworks/subnets@2021-08-01' = {
name: inboundSubnet
parent: vnet
properties: {
addressPrefix: inboundAddressPrefix
delegations: [
{
name: 'Microsoft.Network.dnsResolvers'
properties: {
serviceName: 'Microsoft.Network/dnsResolvers'
}
type: 'Microsoft.Network/virtualNetworks/subnets/delegations'
}
]
}
dependsOn: [
vnet
]
}
resource subnet2 'Microsoft.Network/virtualNetworks/subnets@2021-08-01' = {
name: outboundSubnet
parent: vnet
properties: {
addressPrefix: outboundAddressPrefix
delegations: [
{
name: 'Microsoft.Network.dnsResolvers'
properties: {
serviceName: 'Microsoft.Network/dnsResolvers'
}
type: 'Microsoft.Network/virtualNetworks/subnets/delegations'
}
]
}
dependsOn: [
vnet
subnet1
]
}
resource resolver 'Microsoft.Network/dnsResolvers@2022-07-01' = {
name: dnsResolverName
location: location
properties: {
virtualNetwork: {
id: vnet.id
}
}
dependsOn: [
vnet
subnet1
subnet2
]
}
resource inEndpoint 'Microsoft.Network/dnsResolvers/inboundEndpoints@2022-07-01' = {
parent: resolver
name: inboundSubnet
location: location
properties: {
ipConfigurations: [
{
privateIpAllocationMethod: 'Dynamic'
subnet: {
id: '${vnet.id}/subnets/${inboundSubnet}'
}
}
]
}
dependsOn: [
vnet
subnet1
subnet2
]
}
resource outEndpoint 'Microsoft.Network/dnsResolvers/outboundEndpoints@2022-07-01' = {
parent: resolver
name: outboundSubnet
location: location
properties: {
subnet: {
id: '${vnet.id}/subnets/${outboundSubnet}'
}
}
dependsOn: [
vnet
subnet1
subnet2
]
}
resource fwruleSet 'Microsoft.Network/dnsForwardingRulesets@2022-07-01' = {
name: forwardingRulesetName
location: location
properties: {
dnsResolverOutboundEndpoints: [
{
id: outEndpoint.id
}
]
}
dependsOn: [
vnet
subnet1
subnet2
]
}
resource resolverLink 'Microsoft.Network/dnsForwardingRulesets/virtualNetworkLinks@2022-07-01' = {
parent: fwruleSet
name: resolvervnetlink
properties: {
virtualNetwork: {
id: vnet.id
}
}
dependsOn: [
vnet
subnet1
subnet2
]
}
resource fwRules 'Microsoft.Network/dnsForwardingRulesets/forwardingRules@2022-07-01' = {
parent: fwruleSet
name: forwardingRuleName
properties: {
domainName: DomainName
targetDnsServers: targetDNS
}
dependsOn: [
vnet
subnet1
subnet2
]
}
DNS設定
問い合わせ先のDNS設定を行います。
ネットワークからdatabricks_vnetを右クリックして「プロパティ」を選択します。
「ネットワーク」から「インターネットプロトコルバージョン4」を選択し、「プロパティ」をクリックします。
下記の優先DNSにデプロイしたDNS Private Resolverの受信エンドポイントのIPを以下に記載します。
Databricks確認
デプロイ完了後、「defafult」のDatabricksをクリックし、画面からURLを選択します。
参考にしたサイト様
これで以上となります。
見て下さりありがとうございました。