当前位置:首页 > VMware > 正文内容

PowerShell一键自动化部署ESXI及VSAN

邓鹏9个月前 (01-24)VMware579

    脚本自动化部署vSphere和配置VSAN集群环境,可以完成以下一些操作:

    1 部署嵌套的 ESXi 主机:通过 OVA 文件导入和配置多个嵌套 ESXi 主机,设置其网络信息、CPU、内存和磁盘大小,并将其加入到指定的集群中。

    2 部署 vCenter Server Appliance(VCSA):根据预定义的 JSON 配置文件,部署 VCSA 并进行相应的配置,包括网络设置、存储、部署规模、主机名、SSO 配置等。

    3 创建新的数据中心和集群:连接到新部署的 vCenter Server,创建新的数据中心和集群,并根据需要配置 vSAN 磁盘组。

    4 添加 ESXi 主机到 vCenter:将嵌套的 ESXi 主机添加到新创建的集群中,也可以选择使用 DNS 名称来添加主机。

    5 清除 vSAN 告警和进行最终配置:清除 vSAN 告警并进行额外的配置,例如开启 vMotion、退出维护模式等。

使用时需要注意以下几点:

  • 脚本中使用了一些默认值和硬编码的路径,需要根据实际情况进行修改,比如 OVA 存储路径、vCenter 安装镜像解压后的文件夹路径等。

  • 在执行脚本之前,需要确保目标环境已经满足一定的条件,比如网络设置、存储准备等。

  • 需要对脚本中的用户名、密码等敏感信息进行适当的保护和管理,避免泄露。

  • 在执行脚本时,建议先在测试环境进行验证,确保脚本的正确性和稳定性。

此脚本仅用于测试学习使用,代码如下:

#######################################################################
# 函数列表                                                            #
#######################################################################
# 日志记录
Function logRecord(){
    [cmdletbinding()]
    Param (
        # 参数列表,参数属性
        # 具体日志信息
        [parameter(Mandatory=$True)]
        [string] $logString,
        # 日志存储路径,包括路径和文件名称全路径
        [parameter(Mandatory=$False)]
        [string] $logPath="",
        [Parameter(Mandatory=$True)]
        [ValidateSet('INFO','ERROR')]
        [string] $logLevel
    )

    $time = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'

    if($logPath){
        echo "$time $logLevel $logString" >> $logPath
    }else{
        if($logLevel -eq "INFO"){
            write-host -ForegroundColor Green "$time $logLevel $logString"
        }else{
            write-host -ForegroundColor red "$time $logLevel $logString"
        }
    }
}


#######################################################################
# 参数列表                                                            #
#######################################################################
# 第一层 vCenter Server 信息
$vCenterIp = "172.17.3.110"
$vCenterUsername = "administrator@vsphere.local"
$vCenterPassword = "P@ssw0rd"

# 部署的组件
$deployNestedESXiVMs = 1       # 部署 ESXi
$deployVCSA = 1                # 部署 VCSA
$setupNewVC = 1                # 创建数据中心、集群
$configureVSANDiskGroup = 1    # 配置磁盘组
$addESXiHostsToVC = 1          # 添加主机到VC
$addHostByDnsName = 0          # 添加主机到VC使用DNS名称
$clearVSANHealthCheckAlarm = 1 # 清除vSAN告警

# 嵌套ESXi#############################################################
# 嵌套ESXi OVA存储路径
# $nestedESXiApplianceOVA = "‪D:\test-vm.ova"  ESXI主机模板位置
# 嵌套ESXi网络信息,以及需要部署的嵌套ESXi数量
$nestedESXiHostnameToIPs = @{
    "Lab-esxi-113" = "172.17.3.70"
    "Lab-esxi-114" = "172.17.3.71"
    "Lab-esxi-115" = "172.17.3.72"
}
# 嵌套ESXi资源配置
$NestedESXivCPU = "4"
$NestedESXivMEM = "16"           # GB
$NestedESXiCachingvDisk = "8"    # GB
$NestedESXiCapacityvDisk = "100" # GB

# VCSA#################################################################
# vCenter安装镜像解压后的文件夹
$VCSAInstallerPath = "E:\ISO\VC"
# VCSA部署规模
$vcsaSize2MemoryStorageMap = @{
    "tiny"=@{"cpu"="2";"mem"="12";"disk"="415"};
    "small"=@{"cpu"="4";"mem"="19";"disk"="480"};
    "medium"=@{"cpu"="8";"mem"="28";"disk"="700"};
    "large"=@{"cpu"="16";"mem"="37";"disk"="1065"};
    "xlarge"=@{"cpu"="24";"mem"="56";"disk"="1805"}
}
# VCSA部署配置
$VCSADeploymentSize = "tiny"              # 部署规模
$VCSADisplayName = "Lab-VCSA-112"         # 虚拟机名称
$VCSAIPAddress = "172.17.3.80"          # IP地址
$VCSAHostname = "172.17.3.80"           # 主机名(如果没有DNS解析则使用IP地址)
$VCSAPrefix = "24"                        # 掩码长度
$VCSASSODomainName = "vsphere.local"      # SSO域
$VCSASSOPassword = "P@ssw0rd"             # SSO密码
$VCSARootPassword = "P@ssw0rd"            # ROOT密码
$VCSASSHEnable = "true"                   # SSH
# 嵌套环境配置
$NewVCDatacenterName = "Datacenter"
$NewVCVSANClusterName = "Cluster"

# 公共配置#############################################################
# 使用的存储、端口组等信息
$vmDatacenter = "Datacenter01"    # 数据中心
$vmCluster = "cluster01"  # 集群
$vmNetwork = "VM Network"             # 端口组
$vmDatastore = "Datastore_new"    # 存储
$vmNetmask = "255.255.255.0"           # 掩码
$vmGateway = "172.17.3.254"           # 网关
$vmDNS = "172.17.3.10"                # DNS
$vmNTP = "172.17.3.10"                # NTP
$vmPassword = "P@ssw0rd"               # 密码
$vmDomain = "powershell.com"               # 域
$vmSyslog = "172.17.3.90"             # Syslog


$vCenterConnection = $null
try{
    $vCenterConnection = Connect-VIServer $vCenterIp -User $vCenterUsername -Password $vCenterPassword -WarningAction SilentlyContinue
    logRecord -logLevel INFO -logString "连接 vCenter Server $vCenterIp 成功"
}catch{
    logRecord -logLevel ERROR -logString "连接 vCenter Server $vCenterIp 失败"
    return ;
}

# 获取存储、数据中心、ESXi主机
if(($deployNestedESXiVMs -eq 1) -or ($deployVCSA -eq 1)) {

    try{
        $datastore = Get-Datastore -Server $vCenterConnection -Name $vmDatastore | Select -First 1
        logRecord -logLevel INFO -logString "获取存储 $vmDatastore 成功"
    }catch{
        logRecord -logLevel ERROR -logString "获取存储 $vmDatastore 失败"
    }

    try{
        $cluster = Get-Cluster -Server $viConnection -Name $VMCluster
        logRecord -logLevel INFO -logString "获取集群 $VMCluster 成功"
    }catch{
        logRecord -logLevel ERROR -logString "获取集群 $VMCluster 失败"
    }
    
    try{
        $datacenter = $cluster | Get-Datacenter
        logRecord -logLevel INFO -logString "获取数据中心 $($datacenter.name) 成功"
    }catch{
        logRecord -logLevel ERROR -logString "获取数据中心 $($datacenter.name) 失败"
    }
    
    try{
        $vmHost = $cluster | Get-VMHost | Select -First 1
        logRecord -logLevel INFO -logString "获取主机 $($vmHost.name) 成功"
    }catch{
        logRecord -logLevel ERROR -logString "获取主机 $($vmHost.name) 失败"
    }
    
}


if($vCenterConnection){
    if($deployNestedESXiVMs -eq 1) {
        # 遍历嵌套ESXi信息
        foreach($nestedESXiHostKey in $nestedESXiHostnameToIPs.keys) {
            $vmName = $nestedESXiHostKey
            $vmIpAddress = $nestedESXiHostnameToIPs[$nestedESXiHostKey]
            
            # 获取OVA配置
            # $ovfconfig = Get-OvfConfiguration $NestedESXiApplianceOVA
             $ovfconfig = Get-OvfConfiguration "D:\test-vm.ova"
            $networkMapLabel = ($ovfconfig.ToHashTable().keys | where {$_ -Match "NetworkMapping"}).replace("NetworkMapping.","").replace("-","_").replace(" ","_")
            # 虚拟机端口组
            $ovfconfig.NetworkMapping.$networkMapLabel.value = $vmNetwork

            # 网络信息
            $ovfconfig.common.guestinfo.hostname.value = $vmName
            $ovfconfig.common.guestinfo.ipaddress.value = $vmIpAddress
            $ovfconfig.common.guestinfo.netmask.value = $vmNetmask
            $ovfconfig.common.guestinfo.gateway.value = $vmGateway
            $ovfconfig.common.guestinfo.dns.value = $vmDNS
            $ovfconfig.common.guestinfo.domain.value = $vmDomain
            $ovfconfig.common.guestinfo.ntp.value = $vmNTP
            $ovfconfig.common.guestinfo.syslog.value = $vmSyslog
            $ovfconfig.common.guestinfo.password.value = $vmPassword
            # SSH
            if($VMSSH -eq "true") {
                $VMSSHVar = $true
            } else {
                $VMSSHVar = $false
            }
            $ovfconfig.common.guestinfo.ssh.value = $VMSSHVar
            # 自动创建datastore1
            $ovfconfig.common.guestinfo.createvmfs.value = $false

            $isExsit = Get-VM -Name $vmName -ErrorAction SilentlyContinue

            if($isExsit){
                logRecord -logLevel INFO -logString "虚拟机 $vmName 已存在,跳过该虚拟机导入"
                continue
            }

            # 导入OVA
            logRecord -logLevel INFO -logString "导入虚拟机 $vmName"
            $vm = Import-VApp -Source "D:\test-vm.ova" -OvfConfiguration $ovfconfig -Name $vmName -Location $cluster -VMHost $vmhost -Datastore $datastore -DiskStorageFormat thin

            # 添加网卡
            New-NetworkAdapter -VM $vm -Type Vmxnet3 -NetworkName $vmNetwork -StartConnected -confirm:$false | Out-Null
            New-NetworkAdapter -VM $vm -Type Vmxnet3 -NetworkName $vmNetwork -StartConnected -confirm:$false | Out-Null
            New-NetworkAdapter -VM $vm -Type Vmxnet3 -NetworkName $vmNetwork -StartConnected -confirm:$false | Out-Null

            $vm | New-AdvancedSetting -name "ethernet2.filter4.name" -value "dvfilter-maclearn" -confirm:$false -ErrorAction SilentlyContinue | out-null
            $vm | New-AdvancedSetting -Name "ethernet2.filter4.onFailure" -value "failOpen" -confirm:$false -ErrorAction SilentlyContinue | out-null

            $vm | New-AdvancedSetting -name "ethernet3.filter4.name" -value "dvfilter-maclearn" -confirm:$false -ErrorAction SilentlyContinue | out-null
            $vm | New-AdvancedSetting -Name "ethernet3.filter4.onFailure" -value "failOpen" -confirm:$false -ErrorAction SilentlyContinue | out-null

            $vm | New-AdvancedSetting -name "ethernet4.filter4.name" -value "dvfilter-maclearn" -confirm:$false -ErrorAction SilentlyContinue | out-null
            $vm | New-AdvancedSetting -Name "ethernet4.filter4.onFailure" -value "failOpen" -confirm:$false -ErrorAction SilentlyContinue | out-null
            
            # 设置CPU和内存大小
            Set-VM -Server $viConnection -VM $vm -NumCpu $NestedESXivCPU -MemoryGB $NestedESXivMEM -Confirm:$false | out-null

            # 设置磁盘大小
            Get-HardDisk -Server $viConnection -VM $vm -Name "Hard disk 2" | Set-HardDisk -CapacityGB $NestedESXiCachingvDisk -Confirm:$false | out-null
            Get-HardDisk -Server $viConnection -VM $vm -Name "Hard disk 3" | Set-HardDisk -CapacityGB $NestedESXiCapacityvDisk -Confirm:$false | out-null

            # 开机
            $vm | Start-Vm -RunAsync | Out-Null
        }
    }

    if($deployVCSA -eq 1) {
        $isExsit = Get-VM -Name $VCSADisplayName -ErrorAction SilentlyContinue

        if($isExsit){
            logRecord -logLevel INFO -logString "虚拟机 $VCSADisplayName 已存在,跳过该虚拟机导入"
            return ;
        }

        $config = (Get-Content -Raw "$($VCSAInstallerPath)\vcsa-cli-installer\templates\install\embedded_vCSA_on_VC.json") | convertfrom-json

        $config.'new_vcsa'.vc.hostname = $vCenterIp                           # 第一层vCenter IP
        $config.'new_vcsa'.vc.username = $vCenterUsername                     # 第一层vCenter 用户
        $config.'new_vcsa'.vc.password = $vCenterPassword                     # 第一层vCenter 密码
        $config.'new_vcsa'.vc.deployment_network = $vmNetwork                 # 端口组
        $config.'new_vcsa'.vc.datastore = $datastore                          # 存储
        $config.'new_vcsa'.vc.datacenter = $datacenter.name                   # 第一层数据中心名称
        $config.'new_vcsa'.vc.target = $VMCluster                             # 第一层集群名称
        $config.'new_vcsa'.appliance.thin_disk_mode = $true                   # 磁盘模式
        $config.'new_vcsa'.appliance.deployment_option = $VCSADeploymentSize  # 部署规模
        $config.'new_vcsa'.appliance.name = $VCSADisplayName                  # 虚拟机名称
        $config.'new_vcsa'.network.ip_family = "ipv4"                         # 网络栈
        $config.'new_vcsa'.network.mode = "static"                            # 网络模式
        $config.'new_vcsa'.network.ip = $VCSAIPAddress                        # IP地址
        $config.'new_vcsa'.network.dns_servers[0] = $VMDNS                    # DNS
        $config.'new_vcsa'.network.prefix = $VCSAPrefix                       # 掩码长度
        $config.'new_vcsa'.network.gateway = $VMGateway                       # 网关
        $config.'new_vcsa'.os.ntp_servers = $VMNTP                            # NTP
        $config.'new_vcsa'.network.system_name = $VCSAHostname                # 计算机名
        $config.'new_vcsa'.os.password = $VCSARootPassword                    # ROOT密码
        if($VCSASSHEnable -eq "true") {
            $VCSASSHEnableVar = $true
        } else {
            $VCSASSHEnableVar = $false
        }
        $config.'new_vcsa'.os.ssh_enable = $VCSASSHEnableVar                  # SSH
        $config.'new_vcsa'.sso.password = $VCSASSOPassword                    # SSO密码
        $config.'new_vcsa'.sso.domain_name = $VCSASSODomainName               # SSO域

        logRecord -logLevel INFO -logString "创建VCSA JSON部署配置文件"
        $config | ConvertTo-Json | Set-Content -Path "$($ENV:Temp)\jsontemplate.json"

        logRecord -logLevel INFO -logString "部署VCSA..."
        # 部署VCSA(Invoke-Expression将字符串解析为命令并执行)
        Invoke-Expression "$($VCSAInstallerPath)\vcsa-cli-installer\win32\vcsa-deploy.exe install --no-esx-ssl-verify --accept-eula --acknowledge-ceip $($ENV:Temp)\jsontemplate.json"
    }

    if($setupNewVC -eq 1) {
        # 连接vCenter
        try{
            $vc = Connect-VIServer $VCSAIPAddress -User "administrator@$VCSASSODomainName" -Password $VCSASSOPassword -WarningAction SilentlyContinue
            logRecord -logLevel INFO -logString "连接 vCenter Server $VCSAIPAddress 成功"
        }catch{
            logRecord -logLevel ERROR -logString "连接 vCenter Server $VCSAIPAddress 失败"
            return ;
        }
        
        # 创建数据中心
        $d = Get-Datacenter -Server $vc $NewVCDatacenterName -ErrorAction Ignore
        if( -Not $d) {
            logRecord -logLevel INFO -logString "创建数据中心 $NewVCDatacenterName"
            New-Datacenter -Server $vc -Name $NewVCDatacenterName -Location (Get-Folder -Type Datacenter -Server $vc) | out-null
        }

        # 创建集群
        $c = Get-Cluster -Server $vc $NewVCVSANClusterName -ErrorAction Ignore
        if( -Not $c) {
            if($configureVSANDiskGroup -eq 1) {
                logRecord -logLevel INFO -logString "创建vSAN集群 $NewVCVSANClusterName"
                New-Cluster -Server $vc -Name $NewVCVSANClusterName -Location (Get-Datacenter -Name $NewVCDatacenterName -Server $vc) -DrsEnabled -HAEnabled -VsanEnabled | out-null
            } else {
                logRecord -logLevel INFO -logString "创建vSphere集群 $NewVCVSANClusterName"
                New-Cluster -Server $vc -Name $NewVCVSANClusterName -Location (Get-Datacenter -Name $NewVCDatacenterName -Server $vc) -DrsEnabled -HAEnabled | out-null
            }
            (Get-Cluster $NewVCVSANClusterName) | New-AdvancedSetting -Name "das.ignoreRedundantNetWarning" -Type ClusterHA -Value $true -Confirm:$false | out-null
        }

        # 添加主机到vCenter
        if($addESXiHostsToVC -eq 1) {
            foreach($nestedESXiHostKey in $nestedESXiHostnameToIPs.keys) {
                $VMName = $nestedESXiHostKey
                $VMIPAddress = $nestedESXiHostnameToIPs[$nestedESXiHostKey]

                $targetVMHost = $VMIPAddress
                if($addHostByDnsName -eq 1) {
                    $targetVMHost = $VMName
                }

                logRecord -logLevel INFO -logString "添加ESXi主机 $targetVMHost 到集群"
                Add-VMHost -Server $vc -Location (Get-Cluster -Name $NewVCVSANClusterName) -User "root" -Password $VMPassword -Name $targetVMHost -Force | out-null
            }
        }

        # 创建磁盘组
        if($configureVSANDiskGroup -eq 1) {
            Get-VsanClusterConfiguration -Server $vc -Cluster $NewVCVSANClusterName | Set-VsanClusterConfiguration -HealthCheckIntervalMinutes 0 | out-null

            foreach ($vmhost in Get-Cluster -Server $vc | Get-VMHost) {
                $luns = $vmhost | Get-ScsiLun | select CanonicalName, CapacityGB

                logRecord -logLevel INFO -logString "主机 $vmhost 查询可用于创建磁盘组的磁盘"
                foreach ($lun in $luns) {
                    if(([int]($lun.CapacityGB)).toString() -eq "$NestedESXiCachingvDisk") {
                        $vsanCacheDisk = $lun.CanonicalName
                    }
                    if(([int]($lun.CapacityGB)).toString() -eq "$NestedESXiCapacityvDisk") {
                        $vsanCapacityDisk = $lun.CanonicalName
                    }
                }

                logRecord -logLevel INFO -logString "主机 $vmhost 创建磁盘组"
                New-VsanDiskGroup -Server $vc -VMHost $vmhost -SsdCanonicalName $vsanCacheDisk -DataDiskCanonicalName $vsanCapacityDisk | out-null
            }
        }

        # 清除vSAN告警
        if($clearVSANHealthCheckAlarm -eq 1) {
            logRecord -logLevel INFO -logString "清除vSAN集群健康检测告警"
            $alarmMgr = Get-View AlarmManager -Server $vc
            Get-Cluster -Server $vc | where {$_.ExtensionData.TriggeredAlarmState} | %{
                $cluster = $_
                $Cluster.ExtensionData.TriggeredAlarmState | %{
                    $alarmMgr.AcknowledgeAlarm($_.Alarm,$cluster.ExtensionData.MoRef)
                }
            }
            $alarmSpec = New-Object VMware.Vim.AlarmFilterSpec
            $alarmMgr.ClearTriggeredAlarms($alarmSpec)
        
            Set-VsanClusterConfiguration -Configuration $NewVCVSANClusterName -AddSilentHealthCheck controlleronhcl,vumconfig,vumrecommendation -PerformanceServiceEnabled $true
        }

        # 最终配置
        foreach ($vmhost in Get-Cluster -Server $vc | Get-VMHost) {
            # 清除告警: 未配置任何 coredump 目标。无法保存主机核心转储
            Get-AdvancedSetting -Entity $vmhost -Name UserVars.SuppressCoredumpWarning | Set-AdvancedSetting -Value 1 -Confirm:$false | out-null

            # 开启vMotion
            $vmhost | Get-VMHostNetworkAdapter -VMKernel | Set-VMHostNetworkAdapter -VMotionEnabled $true -Confirm:$false | out-null

            # 如果主机在维护模式,则退出维护模式
            if($vmhost.ConnectionState -eq "Maintenance") {
                Set-VMHost -VMhost $vmhost -State Connected -RunAsync -Confirm:$false | out-null
            }
        }

        logRecord -logLevel INFO -logString "断开vCenter连接"
        Disconnect-VIServer $vc -Confirm:$false
    }
}

1 如下图,是通过执行脚本后,在现有ESXI主机环境下,自动嵌套部署3台ESXI主机

image.png

2 如下是自动化部署第二层vCenter管理控制台界面,如图可见VSAN已按脚本要求配置完成,

image.png

扫描二维码推送至手机访问

版权声明:本文由PowerShell中文社区发布,如需转载请注明出处。

本文链接:https://www.powershell.com.cn/?id=88

分享给朋友:
返回列表

没有更早的文章了...

下一篇:Powershell导入VMware强大的管理工具-PowerCLI

“PowerShell一键自动化部署ESXI及VSAN” 的相关文章

Powershell导入VMware强大的管理工具-PowerCLI

Powershell导入VMware强大的管理工具-PowerCLI

一、PowerCLI介绍什么是 PowerCLI?PowerCLI 是一个命令行工具,可以用于自动化vSphere管理,包括网络,存储, 虚拟机以及其他很多功能。PowerCLI包含超过700个命令。要安装PowerCLI,你至少需要确保你的PowerShell版本不低于5.1。二、PowerCLI...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。