0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraformを利用したAD+FSx for NetApp ONTAPの移動ユーザプロファイル環境構築

Last updated at Posted at 2025-06-26

移動ユーザプロファイルをFSx for Netapp ONTAPに保存する以下構成を構築します
各EC2やFSx for Netapp ONTAPの作成、ネットワーク作成にTerraformを利用

FSx for Netapp ONTAPのドメイン参加やクライアントのドメイン参加、ADの設定など
手動でコマンドを投入している部分があります

ontap.drawio.png
※ 図は draw.io で作成

TerraformのコードはGithubで公開しています
※ コードの無断利用・転載はご遠慮ください

以下解説です。

細かいリソース書式についての仕様などは以下の公式レジストリをご確認願います

コード構造

roaming_user_profile_with_AD_and_ONTAP/
│
├─ dev/                          # ★ルートモジュール
│   ├── main.tf                   # module呼び出し
│   ├── provider.tf               # provider定義
│   ├── terraform.tfvars          # 環境ごとの変数
│   └── variables.tf              # main.tfが使う変数定義
│
└─modules/                       # ★各モジュール
     ├─ ad/                       # AD用Windows Server EC2など
     │   ├── main.tf
     │   ├── variables.tf
     │   └── outputs.tf
     │
     ├─ network/                  # VPC, Subnet, SGなどのネットワーク関連 
     │   ├── main.tf
     │   ├── variables.tf
     │   └── outputs.tf
     │
     └─ ontap/                    # FSx for Netapp ONTAP構築
         ├── main.tf
         ├── variables.tf
         └── outputs.tf

ルートモジュール

ルートモジュールは dev/ 配下に格納しています

main.tf

子モジュールの呼び出しを実施
以下はADモジュールの呼び出し部分を抜粋しています

#adモジュール読み込み
module "ad" {
  source = "../modules/ad"

  #networkモジュールから呼び出し
  public_subnet_id     = module.network.public_subnet_id
  private_subnet_id    = module.network.private_subnet_id
  vpc_id               = module.network.vpc_id

  #terraform.tfvarsで定義
  ad_domain_name       = var.ad_domain_name
  ad_netbios_name      = var.ad_netbios_name
  ad_sg_cidr           = var.ad_sg_cidr
  ad_safemode_password = var.ad_safemode_password
  bastion_sg_cidr      = var.bastion_sg_cidr
}

[source = ]部分で呼び出すモジュールを定義

public_subnet_id などは network モジュール内で作成されたリソース(例:サブネット)のIDを、他のリソース定義で再利用しています

networkモジュールの outputs.tf で以下のように出力変数を定義

#パブリックサブネットのID
output "public_subnet_id" {
  value       = aws_subnet.public_subnet.id
  description = "Public Subnet ID"
}

これにより、モジュールの呼び出し元では module.<モジュール名>.public_subnet_id の形式で参照できます

ad_domain_name などは子モジュール(今回は ad モジュール)で定義のみ実施した変数にルートモジュール側で値を決めて代入しています

ルートモジュール側の variables.tf でも同じように変数を定義して、変数の値は terraform.tfvars に記載

各子モジュールの variables.tf で値を設定すると再利用する際に変更が面倒になるため、
値が変わる可能性があるものは全てルートモジュールの terraform.tfvars に記載する構成にしています

provider.tf

プロバイダーのバージョンやAWSのリージョン、プロファイルなどを設定

terraform.tfvars

上述した通り、変数の値を定義しています

以下ONTAP部分の抜粋ですが、構成に応じて変更する可能性がある項目については
子モジュールでは変数の定義のみ実施して、値はここで定義する構成にしています

#ontap
fsx_admin_password        = "xxxxxxxxx"        #fsx_adminユーザーのパスワードを指定
ontap_sg_cidr             = "xx.xx.xx.xx/xx"   #ONTAPへのアクセスを許可するセグメントを指定
deployment_type           = "xxxxxxxxx"        #ONTAPのAZ設定 SINGLE_AZ_2 だとシングルAZ マルチにしたい場合は MULTI_AZ_2
storage_capacity          = xxxx               #ストレージ容量 最小 1,024 GiB、最大 524,288 GiB (512 TiB)
ha_pairs                  = x                  #デプロイするHA-pairの数 デプロイメントタイプが MULTI_AZ_2 だと 1、SINGLE_AZ_2 だと1から12まで可能
throughput_capacity       = xxx                #ファイルシステムをホストしているファイルサーバーがデータを提供できる持続速度

なお、今回各パスワードは平文で記載していますが、
セキュリティ要件によっては事前にAWS Secrets Managerへ登録した情報を使うなど要検討

variables.tf

利用する変数定義を記載

ルートモジュールで使うものだけでなく、子モジュールで設定した定義についても
terraform.tfvars で値を設定したものや別モジュールが参照しているものは
ここに子モジュールで設定した定義と同じ内容の記載が必要

ADモジュール

main.tf

最初にEC2用のSSHキーペアを自動生成し、AWSに登録し、秘密鍵をローカルに保存しています
RDP時にもマネジメントコンソールからパスワードを復元するのに秘密鍵を使います

その次はAD用のセキュリティグループを設定
許可したポートは以下を参照しました

また、RDP用に TCP 3389 も許可しています

#RDP許可(VPC内部用)
resource "aws_vpc_security_group_ingress_rule" "rdp_vpc" {
  security_group_id = aws_security_group.ad_sg.id
  from_port         = 3389
  to_port           = 3389
  ip_protocol       = "tcp"
  cidr_ipv4         = var.ad_sg_cidr
  description       = "Allow RDP (TCP 3389) for vpc"
}

#RDP許可(踏み台用)
resource "aws_vpc_security_group_ingress_rule" "rdp_bastion" {
  security_group_id = aws_security_group.ad_sg.id
  from_port         = 3389
  to_port           = 3389
  ip_protocol       = "tcp"
  cidr_ipv4         = var.bastion_sg_cidr
  description       = "Allow RDP (TCP 3389) for bastion"
}

2つに分けているのは「踏み台 → プライベートサブネットのAD」のRDP用にVPC内のセグメント指定、
そして「ローカルPC → 踏み台」のRDP用にローカル側のIP指定、と2つの種類の許可が必要なためです。

その次にEC2で利用する Windows Server 2019 の最新 AMI ID を検索

AMIについて、今回は「Windows Server 2019 日本語版」で固定させています
可変にしたい場合は filter の name 部分の 2019 としている部分を変数にするなどやり方はあると思います

最後にAD用のWindows Server、踏み台/クライアント用のWindows Serverの作成

AMI ID や instance_type などを指定
パブリックアドレスは踏み台のみ設定しています

また、ADとして使う Windows Server では user_data にドメイン構築のコマンドを投入
起動後、自動でAD/DNSとして使えるようにしています

variables.tf

ADモジュールで利用する変数の定義
ルートモジュールのterraform.tfvarsで定義したいので定義のみ実施

更にnetworkモジュールから参照している情報についても変数を定義

outputs.tf

AD用に作成したセキュリティグループのID情報のみ確認用に記載

networkモジュール

main.tf

VPC、インターネットゲートウェイ、サブネット、ルートテーブルを作成しサブネットとルートテーブルの紐付けを実施しています

variables.tf

各セグメントやサブネットのAZなどをルートモジュールのterraform.tfvarsで定義したいので定義のみ実施

outputs.tf

VPCやサブネットのIDは別モジュールでも利用するため記載
ルートテーブルとIGWのIDは確認用に出力させています

ONTAPモジュール

main.tf

まずセキュリティグループを作成して、ポートの許可設定を実施
許可したポートは以下ドキュメントを参照

また、特に記載はなかったですが一時ポートも許可しました

FSx for NetApp ONTAPの作成部分については値はほぼルートモジュールで設定しています
自分はテスト目的なのでシングルAZの最小構成でも充分事足りました

variables.tf

ADモジュールの物と同じですが、ONTAPモジュールで利用する変数の定義
ルートモジュールのterraform.tfvarsで定義したいので定義のみ実施

更にnetworkモジュールから参照している情報についても変数を定義

outputs.tf

エンドポイントについて確認のため出力させています

以下のように管理用LIFのIPとDNS名が出力されます

fsx_endpoints = tolist([
  {
    "intercluster" = tolist([
      {
        "dns_name" = "intercluster.fs-xxxxxxxxxxxx.fsx.xxxxxxxxxx.amazonaws.com"
        "ip_addresses" = toset([
          "10.1.x.xxx",
          "10.1.x.xx",
        ])
      },
    ])
    "management" = tolist([
      {
        "dns_name" = "management.fs-xxxxxxxxxxxx.fsx.xxxxxxxxxx.amazonaws.com"
        "ip_addresses" = toset([
          "10.1.x.xxx",
        ])
      },
    ])
  },
])

構築作業

terraform apply を実行し、作成を開始
FSx for NetApp ONTAP の作成に時間がかかりますが、16分程度で完了しました

作成後、マネジメントコンソールからSVMを作成してドメイン参加実施

スクリーンショット 2025-06-25 191358.png

ボリュームも作成

スクリーンショット 2025-06-25 192814.png

共有作成については、Netapp社はAD側からMMCで共有を作成する方法を想定しているようでした

MMCから接続し

スクリーンショット 2025-06-26 224523.png

共有を作成

スクリーンショット 2025-06-26 224659.png

ADに以下コマンドを投入して新規ユーザー作成と移動ユーザプロファイルの設定、グループ追加を実施

New-ADUser -Name "xx" -SamAccountName "username" -UserPrincipalName username@domain_name -AccountPassword (ConvertTo-SecureString -AsPlainText "password" -force)  -Path "CN=Users,DC=xxxx,DC=xxxx,DC=xxxx" -DisplayName "xx" -Enabled $true
Set-ADUser username -ProfilePath "\\SMB_endpoint\share_name\%username%"
Add-ADGroupMember -Identity "Administrators" -Members "username"

踏み台側で以下コマンドを投入してドメイン参加
Set-DnsClientServerAddress については、デフォルトで設定されているDNSだと
ドメインが見つからないとしてエラーになったため、今回構築したDNSをプライマリに設定

Set-DnsClientServerAddress -InterfaceAlias "イーサネット 3" -ServerAddresses ("10.1.xxx.xxx", "10.1.xxx.xxx")
Add-Computer -DomainName "domain_name" -Credential (Get-Credential) -Restart

これで一旦踏み台からログアウトして作成したユーザでログイン→ログアウトを実施
プロファイルを確認するため、net use でマウント

PS C:\Users\Administrator> net use Y: \\endpoint_ip_address\share_name password /user:Netbios_name\username
コマンドは正常に終了しました。

<ユーザ名>.V6 フォルダが自動的に作られていて

スクリーンショット 2025-06-26 230842.png

中を見るとプロファイルが確認できた

スクリーンショット 2025-06-26 230849.png

作業終了後は terraform destroy でリソース削除実施

リソース削除時、SVMが残っているとエラーになったのでマネジメントコンソールから削除を実施

また、SVM削除時にルートボリューム以外のボリュームがあるとそこでもエラーになるので
ボリュームが残っていればそれも事前に削除が必要です

FSx for Netapp ONTAPについての備考

以下のようにSSHで管理LIFに接続してコマンドでSVMを作ろうとすると権限の問題で拒否されます

FsxId000b5044949441309::> vserver create -vserver svm1 -subtype default -rootvolume svm1_root -rootvolume-security-style ntfs

Error: command failed: not authorized for that command

ただしボリュームはコマンドで作成でき、共有も作成可能、その共有にクライアントからアクセスもできました

FsxId0228511eb30489eb0::> volume create -volume vola -aggregate aggr1
[Job 62] Job succeeded: Successful

FsxId0228511eb30489eb0::> volume show
Vserver   Volume       Aggregate    State      Type       Size  Available Used%
--------- ------------ ------------ ---------- ---- ---------- ---------- -----
svm3      svm3_root    aggr1        online     RW          1GB    972.4MB    0%
svm3      vola         aggr1        online     RW         20MB    18.72MB    1%
2 entries were displayed.

FsxId0228511eb30489eb0::> volume mount -volume vola -junction-path /vola

FsxId0228511eb30489eb0::> vserver cifs share create -share-name nsroot -path /

FsxId0228511eb30489eb0::> vserver cifs share show
Vserver        Share         Path              Properties Comment  ACL
-------------- ------------- ----------------- ---------- -------- -----------
svm3           c$            /                 oplocks    -        BUILTIN\Administrators / Full Control
                                               browsable
                                               changenotify
                                               show-previous-versions
svm3           ipc$          /                 browsable  -        -
svm3           nsroot        /                 oplocks    -        Everyone / Full Control
                                               browsable
                                               changenotify
                                               show-previous-versions
svm3           vol_profile   /vol_profile      oplocks    プロフ   Everyone / Full Control
                                               browsable  ァイル
                                               changenotify
                                               show-previous-versions
4 entries were displayed.

AWSのマネジメントコンソールでボリューム情報を確認するとコマンドで作成した分も反映されました

しかし、以下にもONTAP側のコマンドで作成する流れの記載はされていないので
本来はやはりマネジメントコンソールやAWS CLIから作成するものと思われます

ちなみにCIFSサーバ作成(ドメイン参加)もコマンドは通って参加できました

記載している通り、ベンダーが想定している手順はマネジメントコンソールやAWS CLIからのようですので
上記コマンドでの操作を実行する場合は自己責任でお願いします

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?