ノート:
- このチュートリアルではOracle Cloudへのアクセスが必要です。無料アカウントにサインアップするには、Oracle Cloud Infrastructure Free Tierの開始を参照してください。
- Oracle Cloud Infrastructure資格証明、テナンシおよびコンパートメントの値の例を使用します。演習を完了する場合は、これらの値をクラウド環境に固有の値に置き換えてください。
Terraformおよびcloud-initスクリプトを使用したOracle Cloud Infrastructure Computeインスタンスへの予約済IPのアタッチ
イントロダクション
Infrastructure as Code (IaC)の世界では、効率的でスケーラブルなクラウド・デプロイメントのために、コンピュート・インスタンスのプロビジョニングと構成を自動化することが不可欠です。予約済IPアドレスをOracle Cloud Infrastructure (OCI) Computeインスタンスにアタッチすると、Terraformとcloud-initは強力な組合せを提供します。
OCI Compute Terraformモジュールでは、インスタンスの作成中に、予約済IPをコンピュート・インスタンスにアタッチするオプションはありません。予約済IPは、インスタンスの作成後にのみアタッチできます。このブログ投稿では、Terraformおよびcloud-initスクリプトを利用して、予約済IPをOCIコンピュート・インスタンスにシームレスにアタッチする方法を学習します。
目標
Terraformおよびcloud-initスクリプトを使用して、予約済IPをOCIコンピュート・インスタンスにシームレスにアタッチします。
予約済IPとは何ですか。
予約済IPアドレスは、仮想ネットワーク内のコンピュート・インスタンスに割り当てられた静的IPです。固定IPを必要とするアプリケーションの一貫した接続を保証し、ネットワーク管理を簡素化します。予約済IPは、ロード・バランシング、ファイアウォール・ルール、セキュアなネットワーク通信などのシナリオで一般的に使用されます。
前提条件
まず、OCI環境にアクセスする必要があります。ない場合は、Always Freeインスタンスを簡単に作成できます。これには、多くの空き容量と300ドルのトライアル・クレジットが付属しています。
環境がある場合は、instance-familyリソースおよびstorage-familyを管理する権限を持つグループにユーザーが割り当てられていることを確認してください。セキュリティ・ベスト・プラクティスでは、すでに権限が割り当てられているコンソール・ユーザーを使用するかわりに、ユーザーを作成します。ヘルプが必要な場合は、ドキュメントをチェックアウトしてグループを作成し、適切な権限をユーザーに付与します。
- OCIアカウント
- Terraformアクセス。詳細は、このリンクを参照してください。
- インスタンスが起動されるパブリック・サブネット。これは、インターネット・ゲートウェイにアタッチする必要があります。
- セカンダリVNICが作成され、予約済IPが割り当てられるプライベート・サブネット。これは、サービス・ゲートウェイにアタッチする必要があります。
- グループ内のリソースがネットワーク・ファミリを管理する権限を必要とする動的グループ。
- Instance Principal認証に対してポリシーを構成する必要があります。
タスク1: Terraformスクリプトの設定
ここでは、Cloud-initスクリプトをメタデータとしてOCI Terraformコンピュート・インスタンスの作成モジュールに追加します。また、予約済IP OCIDとプライベート・サブネットOCIDをフリーフォーム・タグとしてCompute 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を作成し、プライマリVNICにアタッチされるエフェメラルIPを持つコンピュート・インスタンスをスピンアップします。
Compute Metadataでは、cloud-initスクリプトを渡します。これにより、既存のEphemeral IPを置き換えて予約済IPが割り当てられます。
タスク2: cloud-init
スクリプトの理解
タスク2.1: OCI CLIおよびその他の必要なツールのインストール
次のコマンドを使用して、OCI CLIおよびjq (解析JSON)をインストールします。
`sudo yum install -y python36-oci-cli jq`
タスク2.2: インスタンスMetadataの取得
-
ネットワーキング、ボリュームなどから実行中のインスタンスに関する情報を提供するインスタンス・メタデータ・サービスを使用します。これにより、フリーフォーム・タグ値を含むインスタンス・メタデータ・サービスを使用して、インスタンス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のOCID)、一時的パブリックIPおよび一時的パブリックIP OCIDを取得します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')
タスク2.3: セカンダリVNICのアタッチ
次のコマンドを実行して、プライベート・サブネットを使用するCompute VMにセカンダリVNICをアタッチします。
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をデタッチし、それに応じてルート・ルールを更新します。
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
次のステップ
これはサンプル実装で、cloud-initスクリプトとして使用する前に対応する変更を行います。これは、Oracle Linux 8でテストされています。
他のLinuxフレーバを選択すると、oci-cli
インストール手順が変更されます。詳細は、CLIのインストールを参照してください。
関連リンク
謝辞
作成者 - Rithesh Subramanian (OCI Cloud Architect)
その他の学習リソース
docs.oracle.com/learnで他のラボをご覧いただくか、Oracle Learning YouTubeチャネルでより無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスして、Oracle Learning Explorerになります。
製品ドキュメントについては、Oracle Help Centerを参照してください。
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.