6.2. Validation サービスのカスタムルールの作成
Validation
サービスは Open Policy Agent (OPA) ポリシールールを使用して、移行に対する各仮想マシン (VM) の適合性を確認します。Validation
サービスは、各 VM の concerns 一覧を生成します。これは、Provider Inventory
サービスに VM 属性として保存されます。Web コンソールには、プロバイダーインベントリー内の各 VM の concerns が表示されます。
カスタムルールを作成して、Validation
サービスのデフォルトルールセットを拡張することができます。たとえば、VM に複数のディスクがあるかどうかを確認するルールを作成できます。
6.2.1. Rego ファイルについて
検証ルールは、Open Policy Agent (OPA) のネイティブクエリー言語である Rego で記述されます。ルールは、Validation
Pod の /usr/share/opa/policies/io/konveyor/forklift/<provider>
ディレクトリーに .rego
ファイルとして保存されます。
各検証ルールは、個別の .rego
ファイルに定義され、特定の条件をテストします。条件が true
と評価された場合、ルールは {“category", “label", “assessment"}
ハッシュを concerns
に追加します。concerns
のコンテンツは、VM のインベントリーレコードの concerns
キーに追加されます。Web コンソールには、プロバイダーインベントリー内の各 VM の concerns
キーのコンテンツが表示されます。
次の .rego
ファイルの例では、VMware VM のクラスターで有効になっている分散リソーススケジューリングを確認します。
drs_enabled.rego の例
package io.konveyor.forklift.vmware 1 has_drs_enabled { input.host.cluster.drsEnabled 2 } concerns[flag] { has_drs_enabled flag := { "category": "Information", "label": "VM running in a DRS-enabled cluster", "assessment": "Distributed resource scheduling is not currently supported by OpenShift Virtualization. The VM can be migrated but it will not have this feature in the target environment." } }
6.2.2. デフォルトの検証ルールの確認
カスタムルールを作成する前に、Validation
サービスのデフォルトルールを確認して、既存のデフォルト値を再定義するルールを作成しないようにする必要があります。
例: デフォルトのルールに default valid_input = false
の行が含まれていて、default valid_input = true
の行が含まれるカスタムルールを作成した場合、Validation
サービスは起動しません。
手順
Validation
Pod のターミナルに接続します。$ oc rsh <validation_pod>
プロバイダーの OPA ポリシーディレクトリーに移動します。
$ cd /usr/share/opa/policies/io/konveyor/forklift/<provider> 1
- 1
vmware
またはovirt
を指定します。
デフォルトポリシーを検索します。
$ grep -R "default" *
6.2.3. Inventory サービス JSON の取得
Inventory
サービスクエリーを仮想マシン (VM) に送信して Inventory
サービス JSON を取得します。出力には "input"
キーが含まれます。このキーには、Validation
サービスルールによってクエリーされるインベントリー属性が含まれます。
検証ルールは、"input"
キーの任意の属性に基づいて作成できます (例: input.snapshot.kind
)。
手順
Inventory
サービスルートを取得します。$ oc get route <inventory_service> -n openshift-mtv
プロバイダーの
UUID
を取得します。$ GET https://<inventory_service_route>/providers/<provider> 1
- 1
- プロバイダーで使用できる値は
vsphere
およびovirt
です。
プロバイダーの VM を取得します。
$ GET https://<inventory_service_route>/providers/<provider>/<UUID>/vms
VM の詳細を取得します。
$ GET https://<inventory_service_route>/providers/<provider>/<UUID>/workloads/<vm>
出力例
{ "input": { "selfLink": "providers/vsphere/c872d364-d62b-46f0-bd42-16799f40324e/workloads/vm-431", "id": "vm-431", "parent": { "kind": "Folder", "id": "group-v22" }, "revision": 1, "name": "iscsi-target", "revisionValidated": 1, "isTemplate": false, "networks": [ { "kind": "Network", "id": "network-31" }, { "kind": "Network", "id": "network-33" } ], "disks": [ { "key": 2000, "file": "[iSCSI_Datastore] iscsi-target/iscsi-target-000001.vmdk", "datastore": { "kind": "Datastore", "id": "datastore-63" }, "capacity": 17179869184, "shared": false, "rdm": false }, { "key": 2001, "file": "[iSCSI_Datastore] iscsi-target/iscsi-target_1-000001.vmdk", "datastore": { "kind": "Datastore", "id": "datastore-63" }, "capacity": 10737418240, "shared": false, "rdm": false } ], "concerns": [], "policyVersion": 5, "uuid": "42256329-8c3a-2a82-54fd-01d845a8bf49", "firmware": "bios", "powerState": "poweredOn", "connectionState": "connected", "snapshot": { "kind": "VirtualMachineSnapshot", "id": "snapshot-3034" }, "changeTrackingEnabled": false, "cpuAffinity": [ 0, 2 ], "cpuHotAddEnabled": true, "cpuHotRemoveEnabled": false, "memoryHotAddEnabled": false, "faultToleranceEnabled": false, "cpuCount": 2, "coresPerSocket": 1, "memoryMB": 2048, "guestName": "Red Hat Enterprise Linux 7 (64-bit)", "balloonedMemory": 0, "ipAddress": "10.19.2.96", "storageUsed": 30436770129, "numaNodeAffinity": [ "0", "1" ], "devices": [ { "kind": "RealUSBController" } ], "host": { "id": "host-29", "parent": { "kind": "Cluster", "id": "domain-c26" }, "revision": 1, "name": "IP address or host name of the vCenter host or RHV Engine host", "selfLink": "providers/vsphere/c872d364-d62b-46f0-bd42-16799f40324e/hosts/host-29", "status": "green", "inMaintenance": false, "managementServerIp": "10.19.2.96", "thumbprint": <thumbprint>, "timezone": "UTC", "cpuSockets": 2, "cpuCores": 16, "productName": "VMware ESXi", "productVersion": "6.5.0", "networking": { "pNICs": [ { "key": "key-vim.host.PhysicalNic-vmnic0", "linkSpeed": 10000 }, { "key": "key-vim.host.PhysicalNic-vmnic1", "linkSpeed": 10000 }, { "key": "key-vim.host.PhysicalNic-vmnic2", "linkSpeed": 10000 }, { "key": "key-vim.host.PhysicalNic-vmnic3", "linkSpeed": 10000 } ], "vNICs": [ { "key": "key-vim.host.VirtualNic-vmk2", "portGroup": "VM_Migration", "dPortGroup": "", "ipAddress": "192.168.79.13", "subnetMask": "255.255.255.0", "mtu": 9000 }, { "key": "key-vim.host.VirtualNic-vmk0", "portGroup": "Management Network", "dPortGroup": "", "ipAddress": "10.19.2.13", "subnetMask": "255.255.255.128", "mtu": 1500 }, { "key": "key-vim.host.VirtualNic-vmk1", "portGroup": "Storage Network", "dPortGroup": "", "ipAddress": "172.31.2.13", "subnetMask": "255.255.0.0", "mtu": 1500 }, { "key": "key-vim.host.VirtualNic-vmk3", "portGroup": "", "dPortGroup": "dvportgroup-48", "ipAddress": "192.168.61.13", "subnetMask": "255.255.255.0", "mtu": 1500 }, { "key": "key-vim.host.VirtualNic-vmk4", "portGroup": "VM_DHCP_Network", "dPortGroup": "", "ipAddress": "10.19.2.231", "subnetMask": "255.255.255.128", "mtu": 1500 } ], "portGroups": [ { "key": "key-vim.host.PortGroup-VM Network", "name": "VM Network", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch0" }, { "key": "key-vim.host.PortGroup-Management Network", "name": "Management Network", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch0" }, { "key": "key-vim.host.PortGroup-VM_10G_Network", "name": "VM_10G_Network", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch1" }, { "key": "key-vim.host.PortGroup-VM_Storage", "name": "VM_Storage", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch1" }, { "key": "key-vim.host.PortGroup-VM_DHCP_Network", "name": "VM_DHCP_Network", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch1" }, { "key": "key-vim.host.PortGroup-Storage Network", "name": "Storage Network", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch1" }, { "key": "key-vim.host.PortGroup-VM_Isolated_67", "name": "VM_Isolated_67", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch2" }, { "key": "key-vim.host.PortGroup-VM_Migration", "name": "VM_Migration", "vSwitch": "key-vim.host.VirtualSwitch-vSwitch2" } ], "switches": [ { "key": "key-vim.host.VirtualSwitch-vSwitch0", "name": "vSwitch0", "portGroups": [ "key-vim.host.PortGroup-VM Network", "key-vim.host.PortGroup-Management Network" ], "pNICs": [ "key-vim.host.PhysicalNic-vmnic4" ] }, { "key": "key-vim.host.VirtualSwitch-vSwitch1", "name": "vSwitch1", "portGroups": [ "key-vim.host.PortGroup-VM_10G_Network", "key-vim.host.PortGroup-VM_Storage", "key-vim.host.PortGroup-VM_DHCP_Network", "key-vim.host.PortGroup-Storage Network" ], "pNICs": [ "key-vim.host.PhysicalNic-vmnic2", "key-vim.host.PhysicalNic-vmnic0" ] }, { "key": "key-vim.host.VirtualSwitch-vSwitch2", "name": "vSwitch2", "portGroups": [ "key-vim.host.PortGroup-VM_Isolated_67", "key-vim.host.PortGroup-VM_Migration" ], "pNICs": [ "key-vim.host.PhysicalNic-vmnic3", "key-vim.host.PhysicalNic-vmnic1" ] } ] }, "networks": [ { "kind": "Network", "id": "network-31" }, { "kind": "Network", "id": "network-34" }, { "kind": "Network", "id": "network-57" }, { "kind": "Network", "id": "network-33" }, { "kind": "Network", "id": "dvportgroup-47" } ], "datastores": [ { "kind": "Datastore", "id": "datastore-35" }, { "kind": "Datastore", "id": "datastore-63" } ], "vms": null, "networkAdapters": [], "cluster": { "id": "domain-c26", "parent": { "kind": "Folder", "id": "group-h23" }, "revision": 1, "name": "mycluster", "selfLink": "providers/vsphere/c872d364-d62b-46f0-bd42-16799f40324e/clusters/domain-c26", "folder": "group-h23", "networks": [ { "kind": "Network", "id": "network-31" }, { "kind": "Network", "id": "network-34" }, { "kind": "Network", "id": "network-57" }, { "kind": "Network", "id": "network-33" }, { "kind": "Network", "id": "dvportgroup-47" } ], "datastores": [ { "kind": "Datastore", "id": "datastore-35" }, { "kind": "Datastore", "id": "datastore-63" } ], "hosts": [ { "kind": "Host", "id": "host-44" }, { "kind": "Host", "id": "host-29" } ], "dasEnabled": false, "dasVms": [], "drsEnabled": true, "drsBehavior": "fullyAutomated", "drsVms": [], "datacenter": null } } } }
6.2.4. 検証ルールの作成
ルールを含む設定マップカスタムリソース (CR) を Validation
サービスに適用して、検証ルールを作成します。
-
既存のルールと同じ名前でルールを作成すると、
Validation
サービスは、それらのルールでOR
操作を実行します。 -
デフォルトのルールと矛盾するルールを作成すると、
Validation
サービスは開始されません。
検証ルールの例
検証ルールは、Provider Inventory
サービスが収集する仮想マシン (VM) 属性に基づいています。
たとえば、VMware API はこのパス (MOR:Virtual Machine.config.extra Config["numa.node Affinity"]
) を使用して、VMware VM に NUMA ノードアフィニティーが設定されているかどうかを確認します。
Provider Inventory
サービスは、この設定を簡素化し、リスト値を持つテスト可能な属性を返します。
"numaNodeAffinity": [ "0", "1" ],
この属性に基づいて Rego クエリーを作成し、それを forklift-validation-config
設定マップに追加します。
`count(input.numaNodeAffinity) != 0`
手順
以下の例に従って設定マップ CR を作成します。
$ cat << EOF | oc apply -f - apiVersion: v1 kind: ConfigMap metadata: name: <forklift-validation-config> namespace: openshift-mtv data: vmware_multiple_disks.rego: |- package <provider_package> 1 has_multiple_disks { 2 count(input.disks) > 1 } concerns[flag] { has_multiple_disks 3 flag := { "category": "<Information>", 4 "label": "Multiple disks detected", "assessment": "Multiple disks detected on this VM." } } EOF
forklift-controller
デプロイメントを0
にスケーリングして、Validation
Pod を停止します。$ oc scale -n openshift-mtv --replicas=0 deployment/forklift-controller
forklift-controller
デプロイメントを1
にスケーリングして、Validation
Pod を起動します。$ oc scale -n openshift-mtv --replicas=1 deployment/forklift-controller
Validation
Pod ログをチェックして、Pod が起動したことを確認します。$ oc logs -f <validation_pod>
カスタムルールがデフォルトのルールと競合する場合、
Validation
Pod は起動しません。ソースプロバイダーを削除します。
$ oc delete provider <provider> -n openshift-mtv
ソースプロバイダーを追加して、新規ルールを適用します。
$ cat << EOF | oc apply -f - apiVersion: forklift.konveyor.io/v1beta1 kind: Provider metadata: name: <provider> namespace: openshift-mtv spec: type: <provider_type> 1 url: <api_end_point> 2 secret: name: <secret> 3 namespace: openshift-mtv EOF
カスタムルールを作成した後、ルールのバージョンを更新して、Inventory
サービスが変更を検出し、VM を検証できるようにする必要があります。
6.2.5. インベントリールールバージョンの更新
Provider Inventory
サービスが変更を検出して Validation
サービスをトリガーするように、ルールを更新するたびにインベントリールールのバージョンを更新する必要があります。
ルールバージョンは、各プロバイダーの rules_version.rego
ファイルに記録されます。
手順
現在のルールバージョンを取得します。
$ GET https://forklift-validation/v1/data/io/konveyor/forklift/<provider>/rules_version 1
出力例
{ "result": { "rules_version": 5 } }
Validation
Pod のターミナルに接続します。$ oc rsh <validation_pod>
-
/usr/share/opa/policies/io/konveyor/forklift/<provider>/rules_version.rego
ファイルでルールバージョンを更新します。 -
Validation
Pod ターミナルからログアウトします。 更新されたルールバージョンを検証します。
$ GET https://forklift-validation/v1/data/io/konveyor/forklift/<provider>/rules_version 1
出力例
{ "result": { "rules_version": 6 } }