Cisco Japan Blog

Terraform を利用した Cisco ACI の管理概要 – パート 2

2 min read



この記事は、Data Centre の Technical Solutions Architect である Conor Murphy によるブログ「Introduction to Terraform with Cisco ACI, Part 2popup_icon」(2021/1/29)の抄訳です。

このブログシリーズのパート 1 をまだ読まれていない方は、ぜひお読みください。このセクションでは、ACI と Terraform について説明します。また、新しいトピックとして、Terraform のインポート機能とデータリソースについても取り上げます。

  1. Terraform の概要
  2. Terraform と ACI
  3. Terraform 設定ファイルの説明
  4. Terraform リモート状態管理とチームでのコラボレーション
  5. Terraform プロバイダーの構築方法

 

コード例

https://github.com/conmurphy/intro-to-terraform-and-acipopup_icon

ラボのインフラストラクチャ

利用している独自の ACI ラボがすでにあるかもしれませんが、ない場合は、DevNet サンドボックスで ACI Simulator を使用できます。

ACI Simulator AlwaysOn – V4popup_icon

Terraform ACI プロバイダーとリソース

前の投稿で説明したように、Terraform プロバイダーは、API を通じたインタラクションを解釈し、リソースを公開する役割を担っています。

Terraform のリソースは、ACI テナント、EPG、コントラクト、BD などのインフラオブジェクトを表したものです。

今回の投稿では、多数のリソースを含む ACI Terraform プロバイダーについて説明します。

利用できるリソースの一覧については、次のリンク先を参照してください。

https://www.terraform.io/docs/providers/aci/index.htmlpopup_icon

Terraform ACI Provider and Resources

800

Terraform リソースとデータソース

これまでは、「aci_tenant」などのプロバイダーリソースのみを見てきました。

 


resource "aci_tenant" "my_terraform_tenant" {

name        = "tenant_for_terraform"

description = "This tenant is created by the Terraform ACI provider"

}

 

一方、Terraform には、データソースと呼ばれる概念もあります。

データソースを利用すれば、Terraform の外部で定義された情報を Terraform の設定に利用したり、別の Terraform 設定ファイルで定義された情報を利用したりすることができます。

https://www.terraform.io/docs/configuration/data-sources.htmlpopup_icon

リソースは読み取り/書き込みが可能ですが、データソースは読み取り専用です。つまり、Terraform で管理していないオブジェクトの情報を設定ファイルに含めることができるということです。

たとえば ACI の場合、おそらく共有テナントで独自のアプリケーション プロファイルと EPG を管理したとしても、Terraform にテナント自体は管理させないでしょう。

共有要素(テナント、BD、VRF、コントラクトなど)はデータソース(読み取り専用)として定義し、ANP/EPG は、Terraform によって作成/削除するリソースとして定義できます。

 



provider "aci" {

# cisco-aci user name

username = "${var.username}"

# cisco-aci password

password = "${var.password}"

# cisco-aci url

url      =  "${var.apic_url}"

insecure = true

}

 

data "aci_tenant" "my_shared_tenant" {

name = "my_shared_tenant"

}

 

data "aci_bridge_domain" "my_shared_bd" {

tenant_dn   = "${data.aci_tenant. my_shared_tenant.id}"

name        = "my_shared_bd"

}

 

resource "aci_application_profile" "terraform_app" {

tenant_dn = "${data.aci_tenant. my_shared_tenant.id}"

name       = "demo_app_profile"

}

 

resource "aci_application_epg" "my_web_epg" {

application_profile_dn  = "${aci_application_profile.terraform_app.id}"

name                            = "db_epg"

description                   = "%s"

annotation                    = "tag_epg"

exception_tag               = "0"

flood_on_encap            = "disabled"

fwd_ctrl                    = "none"

has_mcast_source            = "no"

is_attr_based_e_pg      = "no"

match_t                         = "AtleastOne"

name_alias                  = "alias_epg"

pc_enf_pref                 = "unenforced"

pref_gr_memb                = "exclude"

prio                            = "unspecified"

shutdown                    = "no"

}

 

 

上記の例では、2 つのデータソース(my_shared_tenantmy_shared_bd)を定義しています。この 2 つのデータソースは、aci_application_profile リソース内で「${data.aci_tenant. my_shared_tenant.id}」の形式で参照されます。

ここで使用されている ID などの一部のプロパティは、前回の投稿で、値がハードコーディングされずにバックグラウンドで生成されると説明しました。

注:参照するデータソースが ACI ファブリックにすでに存在していることを確認する必要があります。たとえば、ブリッジドメイン「my_shared_bd」は、ラボのテナント「my_shared_tenant」にすでに存在しています。参照するデータソースが存在しない場合は、エラーが表示されます。

これら 2 つの概念に基づいて、ACI ファブリックに必要な設定を構築できます。一部の Terraform ACI の設定は、上記および前回の投稿ですでに定義されています。ACI ビジネスユニットでは、お客様がすぐに設定を始められるように、多数の設定ファイルのサンプルを作成しています。サンプルは次のリンク先で確認できます。

https://github.com/terraform-providers/terraform-provider-aci/tree/master/examplespopup_icon

また、お客様が設定する際に参考になるように、次のドキュメントに、ACI プロバイダーで利用可能なリソースの全リストが含まれています。

https://www.terraform.io/docs/providers/aci/index.htmlpopup_icon

これらのリソースを利用すれば、Terraform で ACI を管理しやすくなります。

ただし、ACI プロバイダーに関して、以下のような質問がよく寄せられます。

  • 利用できるのは新たに導入する場合だけですか?
  • すべて Terraform で設定できますか?
  • ACI を手動で設定するとどうなりますか?

 

Terraform へのインポート

Terraform を使用し始めた段階で、多くのお客様環境に ACI がすでに導入されている可能性があります。一方、ACI も Terraform も初めて利用するお客様は、両方を同時に学習できないので、まず ACI を学習してから、設定を Terraform に移行する場合があります。

幸いにも Terraform には、これらの一般的なシナリオに対応するために、既存の設定をインポートする機能があります(一部のプロバイダーが対象)。

terraform import

前回、主に 2 つのファイルを利用することを説明しました。設定ファイル(.tf)と状態管理ファイル(terraform.tfstate)です。

現時点の「terraform import」コマンドは、既存のインフラについて学習した内容を状態管理ファイル(terraform.tfstate)にのみインポートします。設定ファイルには自動的に追加されません。

設定ファイルには手動で追加する必要があります。

https://www.terraform.io/docs/cli/import/index.htmlpopup_icon

ステップ 1:新しいリソースを設定ファイル(.tf)に追加します。

 



resource "aci_tenant" "myTenant" {

}

 

リソースを定義するだけです。

名前などのプロパティを設定した後に既存のリソースからインポートすると、値が上書きされます。

 


resource "aci_tenant" "myTenant" {

name = “myTenant1”

}

 

この例では、ACI テナント名が「myTenant」の場合に Terraform に最初にインポートする際は、状態管理ファイルの「myTenant」が使用されます。設定ファイルはインポート時に更新されないため、「myTenant1」は変更されません。その後、apply コマンドを実行すると、Terraform は、新しい名前「myTenant1」で ACI ファブリックを更新します。

ステップ 2:import コマンドを実行します。

Policy, update the description

Terraform は ACI オブジェクトを識別名(Dn)で識別します。また、Terraform リソース ID は、DMIT 内での ACI オブジェクトの絶対パスです。

たとえば、ACI テナント(myTenant)の ID は、uni/tn-myTenant です。myTenant での ACI VRF(vrf1)の ID は、uni/tn-myTenant/ctx-vrf1 です。

import コマンドは次のように使用します。

terraform import <リソース名> <リソース id>

例:terraform import aci_tenant.myTenant uni/tn-myTenant

ステップ 1 で、aci_tenant.myTenant リソースを設定ファイルに追加しました。このコマンドは、ID である ACI テナントの Dn(uni/tn-myTenant)をリソースに割り当て、既存の設定もインポートします。

ステップ 3:必要なすべてのリソースについて同じ手順を繰り返します。

この例では ACI テナントを取り上げましたが、必要に応じてブリッジドメイン、VRF、EPG、コントラクトなどの他のリソースもインポートします。対象のリソースごとに上記の手順を繰り返します。まず、すべてをリソースとして追加し、リソースの名前と、ID として ACI Dn を指定して import コマンドを実行します。

ACI REST リソース

ACI では多くのプロパティを設定できますが、すべてが ACI プロバイダーの Terraform リソースになるわけではありません。そのため、aci_rest リソースが作成され、REST API を使用して ACI オブジェクトを設定できるようになっています。プロバイダーでサポートされていないモデルオブジェクトはすべて、このリソースを使用して作成/管理できます。

つまり、ACI REST API で設定できるオブジェクトはすべて、Terraform で設定/管理できるということです。ネイティブのリソース(aci_tenant など)を使用するか、API(aci_rest リソース)を使用します。

L3Out の作成例を以下に示します。

 


resource "aci_rest" "rest_l3_ext_out" {

path       = "/api/node/mo/${aci_tenant.tenant_for_rest_example.id}/out-

test_ext.json"

class_name = "l3extOut"

content = {

"name" = "test_ext"

}

}

 

ACI API を直接呼び出す Python スクリプトと同じ設定ですが、Terraform リソースにラップされている点のみ異なっています。

また、aci_tenant id などの既存の変数やプロパティを参照することもできます。

https://www.terraform.io/docs/providers/aci/r/rest.htmlpopup_icon

設定のずれ

「Terraform が管理しているリソースを手動で設定するとどうなるか」

これは、Terraform だけでなく、外部ツールを使用してインフラを管理する場合によくある質問です。

ACI の場合は、テストしてどのようになるかを事前に確認できます。

ステップ 1:まず、my_terraform_tenant というテナントを作成し、description プロパティを以下のように設定します。

 



resource "aci_tenant" "my_terraform_tenant" {

name        = "tenant_for_terraform"

description = "This tenant is created by the Terraform ACI provider"

}

 

ステップ 2:GUI にログインし、[テナント(Tenant)] -> [ポリシー(Policy)] で [説明(Description)] を更新します。

ステップ 3terraform plan コマンドを実行し、結果を確認します。

1 つ変更が発生し、テナントの description が再設定されます。

これで、これまでに学習した内容が正しいことがわかります。Terraform は、意図したインフラの設定(.tf ファイル)と現在の状態(terraform.tfstate ファイル)の整合性を維持しようとします。そのため、状態が変更されたことを検出すると(この例では手動で変更)、インフラが再設定されます。

terraform plan command

800800

属性の変更とリソースの変更の違い

Terraform と ACI を使用する場合、属性の変更とリソースの変更は同じようになるとは限りません。別のテストを実施して、どうなるか確認しましょう。

ステップ 1:以下の設定に基づいて、テナント、BD、サブネットを作成します。

 



resource "aci_tenant" "myTenant" {

name        = "myTenant"

}

 

resource "aci_bridge_domain" "bd_for_subnet" {

tenant_dn   = "${aci_tenant.myTenant.id}"

name        = "bd_for_subnet"

description = "This bridge domain is created by the Terraform ACI

provider"

}

 

resource "aci_subnet" "demosubnet" {

bridge_domain_dn                    = "${aci_bridge_domain.bd_for_

subnet.id}"

ip                                  = "10.1.1.1/24"

scope                               = "private"

description                         = "This subject is created by

Terraform"

}

 

ステップ 2:ACI GUI を使用して、同じブリッジドメインに新しいサブネットを作成します。例として 172.16.1.1/24 を利用しました。

ACI GUI1

ACI GUI2

ステップ 3terraform plan コマンドを再度実行し、結果を確認します。変更はありませんでした。

terraform plan コマンド

ステップ 4:ブリッジドメインから 10.1.1.1/24 サブネットを削除し、新しいサブネットはそのままにします。

サブネットを削除

ステップ 5:もう一度 terraform plan を実行し、結果を確認します。Terraform によって 10.1.1.1/24 サブネットが追加されて戻ったことがわかります。ただし、新しいサブネット(172.16.1.1/24)は Terraform で認識されていないため、そのまま残っています。

Run another plan

つまり、ブリッジドメインに再度 2 つのサブネットが存在しています。

このような状態になった理由

Terraform は、ID と名前でリソースをトラッキングします。リソース(aci_tenant など)のプロパティ(description など)が変更されたことを Terraform が検出すると、設定ファイルの内容と一致するようにインフラが更新されます。これは、description に対して起こったことです。リソースの ID と名前は変更されず、同じ ACI テナントのままでした。

ACI を使用している場合、オブジェクトの名前は変更できません。これは、ACI が情報を保存する方法に起因しています。すべてのオブジェクトには一意の識別名があり、この名前がさまざまなオブジェクトをつなげる際に使用されます。このことは、上記の設定を見ればわかります。サブネットは、自分が存在するブリッジドメインを識別名で示しています。

また前述のように、Terraform ACI プロバイダーは、Dn をリソースの ID として使用します。

ACI の場合、サブネットは識別名を持つオブジェクトです。名前(10.1.1.1/24)は変更できないため、削除して別の名前(172.16.1.1/24)で再作成する必要があります。これにより、新しいオブジェクトと Dn が定義され、新しい Terraform リソースと ID が生成されます。

ただし、古いサブネットリソース(10.1.1.1/24)は、Terraform の状態管理ファイルにそのまま存在し、新しいサブネットリソースはインポートされていません。その結果、Terraform は 10.1.1.1/24 サブネットを再実装し、172.16.1.1/24 サブネットには何も起こらなかったのです。

Terraform の設定ファイルでサブネットを更新すると、Terraform が「名前の変更」をしていることがわかります。最初に古いサブネットを削除してから新しいサブネットを再作成することで、名前が変わったように見せています。

 takes care of the “renaming

最後に

Terraform は非常に強力ながら柔軟なツールですが、これまで見てきたように、予期しない動作が発生する場合もあります。あらゆるシステムを導入する場合と同様に、Terraform を自社の環境でどのように利用するかを常に理解しておくことが重要です。ACI Simulator は、実稼働環境に変更を適用する前に、必要に応じて学習、テスト、計画できる優れた方法です。

参考資料

https://www.ciscolive.com/global/on-demand-library.html?search=terraform#/session/1564426481235001CUfppopup_icon

https://www.terraform.io/docs/import/usage.htmlpopup_icon

https://www.terraform.io/docs/providers/aci/r/rest.htmlpopup_icon

https://developer.cisco.com/site/aci/popup_icon

Authors

Kazumasa Ikuta

業務執行役員 プリンシパルアーキテクト

APJCアーキテクチャ

コメントを書く