注:
- 此教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure Free Tier 。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间示例值。完成实验室时,请将这些值替换为特定于云环境的那些值。
使用 Terraform 和 cloud-init 脚本将保留的 IP 连接到 Oracle Cloud Infrastructure Compute 实例
简介
在基础设施即代码 (IaC) 的世界中,自动预配和配置计算实例对于高效、可扩展的云部署至关重要。在将保留的 IP 地址连接到 Oracle Cloud Infrastructure (OCI) 计算实例时,Terraform 和云初始化提供了强大的组合。
在 OCI 计算 Terraform 模块中,无法选择在创建实例时将预留 IP 附加到计算实例。我们只能在创建实例后附加预留 IP。在此博客文章中,我们将探讨如何利用 Terraform 和 cloud-init 脚本将预留 IP 无缝连接到 OCI 计算实例。
目标
使用 Terraform 和 cloud-init 脚本将预留 IP 无缝连接到 OCI 计算实例。
什么是保留 IP?
预留 IP 地址是分配给虚拟网络中的计算实例的静态 IP。它可确保需要固定 IP 的应用程序的一致连接并简化网络管理。保留的 IP 通常用于负载平衡、防火墙规则和安全网络通信等情形。
先决条件
首先,您需要访问 OCI 环境。如果没有 Always Free 实例,您可以轻松创建“Always Free(始终免费)”实例,该实例具有大量免费容量和 300 美元的试用储值。
在您有环境时,请确保您的用户已分配到有权管理实例(系列资源和存储)的组。有了安全最佳实践,您可以创建一个用户,而不是使用已分配有权限的控制台用户。如果需要帮助,请查看文档以创建组并向用户授予适当的权限。
- OCI 账户
- Terraform 访问。有关更多信息,请参见此链接。
- 将在其中启动实例的公共子网。这必须连接到 Internet 网关。
- 专用子网,在其中创建辅助 VNIC 并分配保留的 IP。这必须附加到服务网关。
- 组中的资源需要管理网络系列的权限的动态组。
- 必须为实例主用户验证配置策略。
任务 1:设置 Terraform 脚本
在这里,我们将向 OCI Terraform 创建计算实例模块添加一个作为元数据的云初始化脚本。此外,我们还将保留的 IP OCID 和专用子网 OCID 作为自由格式标记传递给计算 VM。
resource "oci_core_public_ip" "pubip" {
# In case of Multiple Instances has to be created, Provide the count in the vars file.
# This block creates a Reserved Public IP from Oracle IP Pool
count = var.instance_count
compartment_id = var.compartment_id
display_name = var.res_ip_display_name
lifetime = "RESERVED"
private_ip_id = ""
}
resource "oci_core_instance" "pubiptest" {
count = var.instance_count
compartment_id = var.compartment_id
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
display_name = var.display_name
shape = var.shape
# We will pass Reserved Public IP OCID and Private Subnet OCID as a freeform tags to the instance
freeform_tags = {
"publicIP" = resource.oci_core_public_ip.pubip[count.index].id
"SubnetId" = var.private_subnet_id
}
create_vnic_details {
display_name = var.vnic_display_name
assign_public_ip = true
subnet_id = var.public_subnet_id
}
source_details {
source_type = var.source_type
source_id = var.source_id
}
metadata = {
ssh_authorized_keys = var.pub_key
user_data = "${base64encode(file("./cloud-init.sh"))}"
}
}
上面的脚本将创建预留 IP(考虑计数变量值),并将启动包含临时 IP 的计算实例,该 IP 将连接到主 VNIC。
在计算元数据中,我们将通过 cloud-init 脚本,该脚本将通过替换现有的临时 IP 来分配保留的 IP。
任务 2:了解 cloud-init 脚本
任务 2.1:安装 OCI CLI 和其他必需的工具
使用以下命令安装 OCI CLI 和 jq(解析 JSON)。
`sudo yum install -y python36-oci-cli jq`
任务 2.2:检索实例元数据
-
使用实例元数据服务,该服务提供有关正在运行的网络、卷等实例的信息。这将使用包含自由格式标记值的实例元数据服务检索实例 OCID、区间 ID、subnetID(作为自由形式标记传递的专用子网 OCID)和 publicIP(作为自由形式标记传递的保留 IPOCID)。
metadata=$(curl -H 'Authorization: Bearer Oracle' http://169.254.169.254/opc/v2/instance) instanceid=$(echo $metadata | jq -r '.id') compartmentid=$(echo $metadata | jq -r '.compartmentId') subnetid=$(echo $metadata | jq -r '.freeformTags.SubnetId') publicIp=$(echo $metadata | jq -r '.freeformTags.publicIP') -
使用
oci-cli检索主 VNIC OCID、专用 IP ID(分配给主 VNIC 的专用 IP 的 OID)、临时公共 IP 和临时公共 IP OCIDprimaryvnicid=$(curl -H 'Authorization: Bearer Oracle' http://169.254.169.254/opc/v1/vnics/ | jq -r '.[].vnicId') privateIpId=$(oci network private-ip list --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data[].id') ephpublicIp=$(oci network vnic get --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data."public-ip"') ephpublicIpId=$( oci network public-ip get --auth instance_principal --public-ip-address $ephpublicIp | jq -r '.data.id')
任务 2.3:附加辅助 VNIC
将辅助 VNIC 连接到计算 VM,该 VM 将通过运行以下命令使用专用子网。
oci compute instance attach-vnic --instance-id $instanceid --subnet-id $subnetid --auth instance_principal --wait
任务 2.4:配置路由
-
创建辅助 VNIC 并将其连接到 VM 后,我们将配置辅助 VNIC 并将其添加到路由中。要配置路由,我们将使用 Oracle 提供的脚本。
wget https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/secondary_vnic_all_configure.sh sudo chmod u+x ./secondary_vnic_all_configure.sh sudo ./secondary_vnic_all_configure.sh -c -
配置完成后,您将看到新路由添加到 VM 路由。可以使用
sudo route -n命令检查相同的操作。
任务 2.5:将辅助 VNIC 路由设为默认路由
-
使用 IDMS 获取辅助 VNIC 的网关 IP。这将被添加到实例路由表。
gatewayIP=$(curl http://169.254.169.254/opc/v1/vnics/ | jq -c '.[] | ( select(.vnicId=="'$secondaryvnicid'" ))' | jq -r '.virtualRouterIp') -
使用以下命令获取默认网络接口。
iname=$(sudo ./secondary_vnic_all_configure.sh | awk '{print $8}' | awk 'END{print}') -
执行以下命令将默认路由添加到辅助 VNIC。
sudo route add default gw $gatewayIP dev $iname -
使用
sudo route -n命令再次确认。
任务 2.6:删除临时公共 IP
-
删除连接到 VM 的临时公共 IP。由于,我们已将辅助 VNIC 设为默认路由,并且存在辅助 VNIC 的子网,因此它关联了服务网关,以便它可以与其他 OCI 服务(在本例中为 VCN)通信。
delpubIp=$(oci network public-ip delete --force --auth instance_principal --public-ip-id $ephpublicIpId --wait-for-state TERMINATED) -
使用以下命令检查是否已成功删除临时 IP。
checkIp=$(oci network vnic get --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data."public-ip"')
任务 2.7:连接保留的 IP
我们具有来自自由格式标记的公共 IP OCID,因此我们已删除了级别 IP,因此可以将保留的 IP 连接到主要 VNIC。以下命令将保留的 IP 连接到实例的主 VNIC。
assign=$(oci network public-ip update --force --auth instance_principal --public-ip-id $publicIp --private-ip-id $privateIpId --wait-for-state ASSIGNED)
任务 2.8:分离辅助 VNIC
-
我们已将预留公共 VNIC 连接到主 VNIC,现在可以分离辅助 VNIC。使用以下命令分离辅助 VNIC 并相应地更新路由规则。
detach=$(oci compute instance detach-vnic --compartment-id $compartmentid --vnic-id $secondaryvnicid --force --auth instance_principal) sudo ./secondary_vnic_all_configure.sh -d -
以下脚本将同时显示所有步骤。如果失败,此脚本最多重试 3 次,我们可以使用 OCI 事件服务设置失败通知。
#!/bin/bash # coding: utf-8 sudo yum install -y python36-oci-cli function getdetails() { # Fetch data using instance principal authentication metadata=$(curl -H 'Authorization: Bearer Oracle' http://169.254.169.254/opc/v2/instance) instanceid=$(echo $metadata | jq -r '.id') compartmentid=$(echo $metadata | jq -r '.compartmentId') subnetid=$(echo $metadata | jq -r '.freeformTags.SubnetId') publicIp=$(echo $metadata | jq -r '.freeformTags.publicIP') primaryvnicid=$(curl -H 'Authorization: Bearer Oracle' http://169.254.169.254/opc/v1/vnics/ | jq -r '.[].vnicId') privateIpId=$(oci network private-ip list --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data[].id') ephpublicIp=$(oci network vnic get --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data."public-ip"') ephpublicIpId=$( oci network public-ip get --auth instance_principal --public-ip-address $ephpublicIp | jq -r '.data.id') if [[ -z "$subnetid" || "$subnetid" == "" || ${#subnetid} == 0 || -z "$publicIp" || ${#publicIp} == 0 || -z "$instanceid" || -z "$compartmentid" || -z "$publicIpData" || -z "$privateIpId" || -z "$primaryvnicid" || -z "$ephpublicIp" || -z "$ephpublicIpId" ]]; then echo "Missing some details, retrying..." return 1 fi return 0 } # Retry the `getdetails` function thrice attachVNIC() { attachvnic=$(oci compute instance attach-vnic --instance-id $instanceid --subnet-id $subnetid --auth instance_principal --wait) } for i in {1..3}; do getdetails if [[ $? -eq 0 ]]; then attachVNIC if [[ -n "$attachvnic" ]]; then secondaryvnicid=$(echo $attachvnic | jq -r '.data.id') echo $secondaryvnicid check2VNICs=$(oci compute instance list-vnics --instance-id $instanceid --auth instance_principal | jq -r '.data[].id') echo $check2VNICs gatewayIP=$(curl http://169.254.169.254/opc/v1/vnics/ | jq -c '.[] | ( select(.vnicId=="'$secondaryvnicid'" ))' | jq -r '.virtualRouterIp') if [[ (-n "$gatewayIP") ]]; then echo $gatewayIP wget https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/secondary_vnic_all_configure.sh sudo chmod u+x ./secondary_vnic_all_configure.sh sudo ./secondary_vnic_all_configure.sh -c iname=$(sudo ./secondary_vnic_all_configure.sh | awk '{print $8}' | awk 'END{print}') echo $iname sudo route add default gw $gatewayIP dev $iname route oci os ns get --auth instance_principal delpubIp=$(oci network public-ip delete --force --auth instance_principal --public-ip-id $ephpublicIpId --wait-for-state TERMINATED) checkIp=$(oci network vnic get --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data."public-ip"') if [[ -z "$checkIp" || "$checkIp" == "null" ]]; then echo "Assigning Reserved IP" assign=$(oci network public-ip update --force --auth instance_principal --public-ip-id $publicIp --private-ip-id $privateIpId --wait-for-state ASSIGNED) detach=$(oci compute instance detach-vnic --compartment-id $compartmentid --vnic-id $secondaryvnicid --force --auth instance_principal) sudo ./secondary_vnic_all_configure.sh -d checkIp2=$(oci network vnic get --vnic-id $primaryvnicid --auth instance_principal | jq -r '.data."public-ip"') echo "Reserved IP $checkIp2" if [[ -z "$checkIp2" ]]; then oci compute instance update --instance-id $instanceid --freeform-tags '{"errorStatus":"Reserved IP Not Assigned","SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal exit; fi else oci compute instance update --instance-id $instanceid --freeform-tags '{"errorStatus":"Ephemeral IP Not Deleted","SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal exit; fi break; else oci compute instance update --instance-id $instanceid --freeform-tags '{"errorStatus":"Gateway IP not fetched","SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal exit; fi else break; fi fi done if [[ -z "$attachvnic" ]]; then echo "Failed" oci compute instance update --instance-id $instanceid --freeform-tags '{"errorStatus":"Secondary VNIC not attached","SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal exit fi checkVNICs2=$(oci compute instance list-vnics --instance-id $instanceid --auth instance_principal | jq -r '.data | length') if [[ "$checkVNICs2" > 1 ]]; then echo "Detaching Secondary VNIC Failed" oci compute instance update --instance-id $instanceid --freeform-tags '{"errorStatus":"Detaching Secondary VNIC Failed","SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal exit fi oci compute instance update --instance-id $instanceid --freeform-tags '{"SubnetId":"'$subnetid'","publicIP":"'$publicIp'"}' --force --auth instance_principal
后续步骤
这是一个实施示例,请在将它用作云初始脚本之前进行相应的更改。这已在 Oracle Linux 8 上进行了测试。
如果选择任何其他 Linux 风格,oci-cli 安装过程将更改。有关更多信息,请参见 Installing the CLI 。
相关链接
确认
作者 - Rithesh Subramanian(OCI 云架构师)
更多学习资源
探索 docs.oracle.com/learn 上的其他实验室,或者访问 Oracle Learning YouTube 频道上的更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Attach a Reserved IP to an Oracle Cloud Infrastructure Compute Instance using Terraform and cloud-init Script
F82850-01
June 2023
Copyright © 2023, Oracle and/or its affiliates.