移動ユーザプロファイルをFSx for Netapp ONTAPに保存する以下構成を構築します
各EC2やFSx for Netapp ONTAPの作成、ネットワーク作成にTerraformを利用
FSx for Netapp ONTAPのドメイン参加やクライアントのドメイン参加、ADの設定など
手動でコマンドを投入している部分があります
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を作成してドメイン参加実施
ボリュームも作成
共有作成については、Netapp社はAD側からMMCで共有を作成する方法を想定しているようでした
MMCから接続し
共有を作成
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 フォルダが自動的に作られていて
中を見るとプロファイルが確認できた
作業終了後は 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からのようですので
上記コマンドでの操作を実行する場合は自己責任でお願いします