通过Azure Cloud Shell连接没有public IP的虚拟机

通过Azure Cloud Shell连接没有public IP的虚拟机

Azure的Cloud Shell非常的方便,它提供了一个基于Web的命令行工具,可以通过bash或者powershell去执行一些命令,比如az,git等等。

但是Cloud shell默认是无法直接访问你的subscription里的resource的,特别是当你的resource没有public IP的时候,比如一个只有私有网络的VM,这个时候如果想要cloud shell能够直接访问这台VM,那么需要cloud shell能够连接到VM所在的Virtual Network里,这篇文章我们就一起看看如何操作。

准备工作

打开cloud shell
iShot_2024-06-18_20.56.12.png

以Bash为例,选择No Storage account required,然后选中你的subscription
iShot_2024-06-19_09.17.31.png

等待shell ready后,在shell里执行 az account show

iShot_2024-06-18_21.02.27.png

注册resource provider

确认下面三个provider已经注册

注册方法如下:

创建一个resource group,一个vnet,三个subnet

RESOURCE_GROUP_NAME=rg-demo
VNET_NAME=vnet1


# create resource group
az group create --name $RESOURCE_GROUP_NAME --location westeurope

# create vnet
az network vnet create --resource-group $RESOURCE_GROUP_NAME --name $VNET_NAME --address-prefix 10.0.0.0/16

# create subnet for vm
az network vnet subnet create \
    --name subnet-vm \
    --address-prefixes 10.0.0.0/24 \
    --resource-group $RESOURCE_GROUP_NAME \
    --vnet-name $VNET_NAME   


az network vnet subnet create \
	--name sn-containers-dev \
    --address-prefixes 10.0.1.0/24 \
	--resource-group $RESOURCE_GROUP_NAME \
	--vnet-name $VNET_NAME \
	--delegations Microsoft.ContainerInstance/containerGroups \
    --service-endpoints Microsoft.Storage

# Create Azure Relay subnet
az network vnet subnet create \
	--name sn-relay-dev \
	--address-prefixes 10.0.2.0/24 \
	--resource-group $RESOURCE_GROUP_NAME \
	--vnet-name $VNET_NAME

# Disable private endpoint network policies for Azure Relay subnet
az network vnet subnet update \
	--name sn-relay-dev \
	--resource-group $RESOURCE_GROUP_NAME \
	--vnet-name $VNET_NAME \
	--private-endpoint-network-policies Disabled
    

创建Network Profile

RESOURCE_GROUP_NAME=rg-demo
VNET_NAME=vnet1

# get subnet id
containerSubnet=$(az network vnet subnet show \
	--name sn-containers-dev \
	--resource-group  $RESOURCE_GROUP_NAME \
	--vnet-name $VNET_NAME \
	--query id -o tsv)

# Network profile
az resource create \
    --name anp-cloudshell-westeu \
    --resource-group $RESOURCE_GROUP_NAME \
    --resource-type Microsoft.Network/networkProfiles \
    --properties "{\"containerNetworkInterfaceConfigurations\": \
        [{\"name\": \"sn-containers-dev\",\"properties\": \
        {\"ipConfigurations\":[{\"name\":\"ipconfig01\",\"properties\": \
        {\"subnet\": {\"id\": \"$containerSubnet\"}}}]}}]}"
     

在resource group里选中显示隐藏资源,就可以看到我们创建的network profile
iShot_2024-06-19_09.30.26.png

Get the Azure container instance ID

在搜索框里搜索 Microsoft Entra ID

iShot_2024-06-19_09.39.24.png

点进去后,到overview里搜索 azure container instance service,然后在结果里点击 Azure Container Instance Service

iShot_2024-06-19_09.40.34.png

Azure Container Instance Service的Overview, 找到 Object ID,复制保存好,一会要用

Role assigment

执行命令

containerInstanceId=<前面复制的object ID>

# Get the network profile resource ID
networkProfile=$(az network profile show \
	--name anp-cloudshell-westeu \
	--resource-group $RESOURCE_GROUP_NAME \
	--query id -o tsv)
# Delegate access to the resource
az role assignment create \
	--role "Network Contributor" \
	--assignee-object-id $containerInstanceId \
	--scope $networkProfile

然后在你的network profile里点击Access Control,选中Role assigments就可以看到Azure Container Instance Service有了Network Contributor的Role

iShot_2024-06-19_09.48.05.png

Azure Relay namespace

接下来创建Azure Relay

AZURE_RELAY_NAME=arn-cloudshell-westeu1234
az relay namespace create \
    --name $AZURE_RELAY_NAME \
    --resource-group $RESOURCE_GROUP_NAME

注意,上面的名字要起一个别人没有用过的名字,最好是搞一些随机字符串在后面

创建 private endpoint, 让我们的azure relay可以和cloud shell container通信

# Get Azure Relay subnet ID
azureRelaySubnetId=$(az network vnet subnet show \
    --name sn-relay-dev \
    --resource-group $RESOURCE_GROUP_NAME \
    --vnet-name $VNET_NAME \
    --query id -o tsv)

# Get Azure Relay namespace ID
azureRelayResourceId=$(az relay namespace show \
    --name $AZURE_RELAY_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --query id -o tsv)

# Create private endpoint
az network private-endpoint create \
    --name pe-cloudshell-westeu \
    --connection-name CloudShellEndpoint \
    --resource-group $RESOURCE_GROUP_NAME \
    --subnet $azureRelaySubnetId \
    --private-connection-resource-id $azureRelayResourceId \
    --group-id namespace
    
# Delegate access to the resource
az role assignment create \
	--role Contributor \
	--assignee-object-id $containerInstanceId \
	--scope $azureRelayResourceId

Storage Account

# Create a storage account
STORAGE_ACCOUNT_NAME=stocloudshellwesteu1234
az storage account create \
    --name $STORAGE_ACCOUNT_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --sku Standard_LRS

# Create file share for Cloud Shell
az storage share create \
    --name profile \
    --account-name $STORAGE_ACCOUNT_NAME \
    --quota 6

# Allow access to storage account from Cloud Shell container
az storage account network-rule add \
    --account-name $STORAGE_ACCOUNT_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --vnet-name $VNET_NAME \
    --subnet sn-containers-dev

# Deny access by default
az storage account update \
    --name $STORAGE_ACCOUNT_NAME \
    --resource-group $RESOURCE_GROUP_NAME \
    --default-action Deny

测试

reload cloud shell

iShot_2024-06-19_10.21.52.png

会重新加载cloud shell,这次我们需要选择

iShot_2024-06-19_10.22.59.png

然后在vnet的configuration里选中我们之前创建好的资源,比如relay,profile等等
iShot_2024-06-19_10.24.11.png

最后开始部署,这个过程需要几分钟。后面ready的时候,我们可以查看我们的shell的ip,这个ip就是我们之前创建的vent1的subnet

iShot_2024-06-19_10.37.01.png

Create Test VM

记得修改下面的ssh密码

RESOURCE_GROUP_NAME=rg-demo
VNET_NAME=vnet1
az vm create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name vm1 \
    --image Ubuntu2204 \
    --admin-username demo \
    --admin-password '**********' \
    --vnet-name $VNET_NAME \
    --subnet subnet-vm \
    --public-ip-address "" \
    --nsg-rule SSH \
    --location westeurope
    

创建完成后,我们可以看到它的private IP,然后我们在cloud shell里就可以通过我们的ssh用户名密码去连接这台VM了

iShot_2024-06-19_10.40.50.png

那最终的连接关系如下

iShot_2024-06-18_16.31.23.png

环境清理

直接删除我们的resource group就可以了
iShot_2024-06-19_10.44.16.png

参考链接

Discussion