34
Automated SQL Server 2017 Installation and Configuration Using PowerShell & JSON

Automated SQL Server 2017 Installation and Configuration ...€¦ · Installing SQL Server: Install .NET Feature. Note: Install media location option -Source D: \Sources\SxS\ Import-Module

  • Upload
    others

  • View
    30

  • Download
    0

Embed Size (px)

Citation preview

Automated SQL Server 2017Installation and Configuration

Using PowerShell & JSON

http://www.pass.org/summit/2019

November 3rd – 8th in Seattle, WA

Richmond SQL Server Users Group

http://rva.sqlpass.org/

Second Thursday at Markel Plaza (Glen Allen)

Personal DetailsWork

Education

Community

Photography

Agenda• SQL Server (setup)

• PowerShellSyntax & Commandlets

• JSON

• Creating PowerShell Scripts

• Automation ExamplesClustering (WSFC)Managed Service AccountsConfigurationFile.ini

Automation

Why automate your SQL Server deployment?

• Time savings

• Server build standardization

• Documentation

• Setup.exe has over 70 parameters

• SQL Server has 100’s of configuration options

Installation&

Configurationof

SQL Server(what we’re trying to do…)

SQL Server Setup

What should go into all of your SQL installs?

Question:

Answer:Umm….

Let me go find that Checklist.

SQL Setup Checklist

• .NET 4.6 feature ←Automatic install for Win2016/SQL2016+• SQL configuration file (for unattended installs)

• C:\Program Files\Microsoft SQL Server\...\ConfigurationFile.ini• Service Accounts (MSA SQL2012) ← gMSA supported in SQL2016• Firewall exceptions

Requirements for SQL installs

Port UseTCP 1433 Database Engine default installUDP 1434 SQL Server Browser ServiceTCP 1434 Dedicated Admin Connection (DAC)TCP 80 & 443 HTTP/HTTPS for SSRSTCP 139 & 445 SQL Filestream & FiletablesTCP 2383 Analysis ServicesTCP 135 MS Distributed Transaction Coordinator

SQL Setup Checklist cont.

Post Install Configurations• Add Admin Users/Groups ←• Enable the SQL Agent service ←• Instant File Initialization (IFI) ←• Add TempDB files ←• Rename/Disable the SA account• Service Provider Name (SPN)• Operators• DBMail• Trace Flags (3226, 4199, 8152)• Import Custom SQL procedures• Filestream & File Tables• Auditing• Management Policies (PBM)• Encryption Certificates← SQL 2016+ ConfigurationFile.ini

Alerts• Severity 19-25• ID 18456 - Login Error• ID 15247 - Permission Error• ID 9002 - Log Full• ID 825 - Disk I/O Error

Maintenance Jobs• Backups• Reindex• CheckDB

FREE Maintenance Solutionshttp://minionware.nethttp://ola.hallengren.com

JSON

• Open standard designed for data interchange

• PowerShell import using ConvertFrom-JSON

• Key:Value pairs

• Objects {}

• Arrays []

JavaScript Object Notation

https://blog.wicktech.net/powershell-json/

PowerShell• Shell and Integrated Scripting Environment (ISE)

• SQL Server module for PowerShellSQLPS

SQL Server (2008-2016)SQLSERVER

SQLServer 20 - SSMS 16.3 – 16.5 (July 2016 release)SQLServer 21

PowerShell IntegrationPS Windows SQL PSv1 2008 SQLPS

mini-shellv2 2008 R2 SQLPS

v3 2012 SQLPS

v4 2012 R2 SQLPSSqlServer 20

v5 2016 SqlServer 21(PS Gallery)

SQL SSMS SQL PS2008 2008 SQLPS

2008 R2 2008 R2 SQLPS

2012 2012 SQLPS

2012 R2 2012 R2 SQLPS2014 2014 SQLPS2016 16.3-16.5 SqlServer 202017 17.0 –

17.3SqlServer 21(PS Gallery)Core OS SQL PS

v6 WindowsMacOSLinux

SqlServer 21(PS Gallery)

EOL July 2019

Powershell Basics:Syntax:

$xxxxxxx – variable name

[string]$xxxx - variable with string data type

“ (double quote) - string expands/replaces variables

‘ (single quote) - literal string (does not expand variables)

@” - here string (multi-line string w/ variable replacement)

# - comment out remainder of line

` (back tick) - escape character

{} - script block

$_ - current object (iterative loops, ForEach)

Powershell Basics: (cont.)

Commandlets: (Verb-noun naming convention)

Set-ExecutionPolicy [Restricted, AllSigned, RemoteSigned, Unrestricted, Bypass]

Enable-PSRemoting –forceImport-Module [ServerManager, SQLPS, SQLSERVER]

Invoke-Command -Computername -ScriptBlock {}Invoke-Sqlcmd -ServerInstance [-Query or -InputFile]

Invoke-Expression [$variable]

Start-Process [path\file.exe]

Write-Output

Powershell Comparators:

SQL PowerShell= or <> -eq or -ne> or < -gt or -lt

>= or <= -ge or -leLIKE -like

NOT LIKE -notlikeIS NULL !$variable

-contains

SQLIF (@variable = 15)

BEGINDo this

END

PowerShellIF ($variable -eq 15) {

Do this}

Powershell Scripts:

• .ps1 (script) • .psm1 (script module), .psd1 (manifest file), .ps1xml (formatting file)

• Double-click <> Execute.\script.ps1 -ServerName “SQL01” -Path “C:\temp”

• Set-ExecutionPolicy to allow unsigned scripts to be run• Parameters

Param ([string]$ServerName = “.”,[string]$Path = “C:\”)

Creating PowerShell Scripts:Design ConsiderationsExecute script(s) locally or remote?

• Locally – copy script(s) to server• Remote – run script(s) from a single repository

Single Script or Script Set?• Single - 1 big script containing all configuration items• Set - 1 primary script that calls sub scripts

Script Users• Internal use – doesn’t have to be PERFECT, document for usability• External use – better documentation, allow for env variability

Installing SQL Server:Install .NET Feature

Note: Install media location option -Source D:\Sources\SxS\

Import-Module ServerManager;# Get Windows Server Version$WindowsVersion = [environment]::OSVersion.Version

# Add .NET 3.5 to Windows Server 2008R2 and earlierIf (($WindowsVersion.Major -eq 6) -And ($WindowsVersion.Minor -lt 2)) {

Add-WindowsFeature AS-Net-Framework;}

# Add .NET 3.5 to Windows Server 2012 and 2012R2If (($WindowsVersion.Major -eq 6) -And ($WindowsVersion.Minor -ge 2)) {

Add-WindowsFeature Net-Framework-Core;}

# Add .NET 4.6 to Windows Server 2016If ($WindowsVersion.Major -eq 10) {

Add-WindowsFeature Net-Framework-45-Core;}

Create Directories

Open Firewall Ports

Installing SQL Server:

Run SQL install as administrator, specifying config file

New-Item -ItemType directory -Path E:\SQL

netsh advfirewall firewall add rule name="SQL Instances"dir=in action=allow protocol=TCP localport=1433;

$install = 'Start-Process -verb runas -FilePath "' +$SQLInstaller + '" -ArgumentList /ConfigurationFile="' +$ScriptPath + '\Config_Scripts\ConfigurationFile.ini" -Wait';Invoke-Expression $install;

Enable-NetFirewallRule -DisplayName "Remote Desktop -User Mode (TCP-In)”

New-NetFirewallRule -DisplayName "SQL" -Profile "Domain"-Direction Inbound -Action Allow -Protocol TCP -LocalPort"1433" –RemoteAddress @(10.3.20.0/24",“10.1.1.100");

Configuring SQL Server:

Import SQL PowerShell Module

Set Script Parameters

SQL Server 2012-2014

SQL Server 2016 & 2017*

Import-Module SQLPS -DisableNameChecking;

Import-Module Sqlserver -DisableNameChecking;

Param ([string]$SQLServer = ".",[string]$SQLInstaller = "D:\setup.exe",[switch]$CreateMSA = $True,[string]$ScriptPath = $PSScriptRoot

)

* SSMS & PowerShell modules separated as of 2017.

Configuring SQL Server: (cont.)

Execute SQL Query (single line)

Invoke-Sqlcmd -ServerInstance $SQLServer-Query "CREATE DATABASE [Mgmt];";

Execute SQL Query (multi-line ‘here’ string)

$query = @"EXEC sys.sp_configure N'contained database authentication', N'1'GORECONFIGURE WITH OVERRIDE;"@;

Invoke-Sqlcmd -ServerInstance $SQLServer-Query $query;

Configuring SQL Server: (cont.)

Invoke-Sqlcmd -ServerInstance $SQLServer -InputFile"$ScriptPath\Alerts_Triggers.sql";

Execute SQL Script File

Execute Multiple SQL Script Files In Order$ScriptList = Get-Content InstallOrder.txt;$ScriptList | %{ $currScript = $_;Invoke-Sqlcmd -ServerInstance $SQLServer-InputFile $currScript;}

Execute PowerShell Script File./PowerShellScript.ps1 -Parameter1 "Value"-Parameter2 $variable;

Variables & JSON:

$Config = ConvertFrom-Json -InputObject (Get-Content -Path “FileName” -Raw);

[array]$gMSANames = ((($Config).Accounts).Services).Where{$_.AccountType -eq“gMSA”};

ForEach ($Server in $ServerList) {$IP = ((($Config).Servers) | Where-Object {$_.ServerName -eq $Server}).IP; }

[array]$ServerList = (($Config).Servers).ServerName

Group Managed Service Accounts:

$gMSANames = ((($Config).Accounts).Services).Where{$_.AccountType -eq“gMSA”};

ForEach ($Name in $gMSANames) {$Acct = $Name.Username;$AcctDNS = “$Acct.$DomainName”$gMSA_HostNames = $ServerList | ForEach-Object { Get-ADComputer -Identity $_ };

New-ADServiceAccount -Name $Acct -DNSHostName $AcctDNS -PrincipalsAllowedToRetrieveManagedPassword $gMSA_HostNames;

Set-ADServiceAccount -Identity $Acct -TrustedForDelegation$true;

}

https://blog.wicktech.net/powershell-install-gmsa/

Create AD Objects

Group Managed Service Accounts:

$pscred = Get-Credential;

ForEach ($Server in $ServerList) {

ForEach ($Name in $gMSANames) {$Acct = ($Name).Username;

$MSAblock = @”Add-WindowsFeature RSAT-AD-Powershell;Import-Module ActiveDirectory; Install-ADServiceAccount $Acct;“@;

Invoke-Command -ComputerName $Server -ScriptBlock{$MSAblock} -Credential $pscred;

}}

https://blog.wicktech.net/powershell-install-gmsa/

Install Accounts On Servers

WSFC - Clusters & Availability Groups:

ForEach ($Server in $Nodes) {Invoke-Command -ComputerName $Server -ScriptBlock {Import-Module ServerManager;Add-WindowsFeature Failover-Clustering -

IncludeManagementTools;}}

• Cluster Name• Cluster IP Address• Cluster Nodes • Subnets To Ignore • Quorum Mode

• Remote Server Administration Tools (RSAT)https://docs.microsoft.com/en-us/windows-server/remote/remote-server-administration-tools

More Info - https://blog.wicktech.net/powershell-wsfc/

WSFC - Clusters & Availability Groups:Test-Cluster -Node $ClusterList;

New-Cluster -Name $ClusterName -Node $ClusterList -NoStorage -StaticAddress $ClusterIPAddress -IgnoreNetwork$IgnoreIPRange”;

Set-ClusterQuorum -Cluster “$ClusterFQDN”• -NodeMajority;• -NodeAndDiskMajority;• -FileShareWitness $FileShareWitness;• -DiskOnly “Cluster Disk 1”;

Start-Cluster -Name “$ClusterFQDN”;

More Info - https://blog.wicktech.net/powershell-wsfc/

Unattended Setup.exe:

Setup.exe /Q /IACCEPTSQLSERVERLICENSETERMS /FEATURES=AS,RS,IS /INSTANCENAME=“MSSQLSERVER” /INSTANCEDIR=“E:\Path” /INSTALLSHAREDDIR=“F:\Path” /AGTSVCACCOUNT=“Domain\AgentSvc” /AGTSVCPASSWORD=“P@ssW0rd”/SQLSVCACCOUNT=“Domain\SQLSvc”/SQLSVCPASSWORD=“P@ssW0rd”

… (over 70 possible parameters)

• Runtime Parameters • ConfigurationFile.ini

More Info - https://docs.microsoft.com/en-us/sql/database-engine/install-windows/install-sql-server-from-the-command-promp

Runtime Parameters

Unattended Setup.exe:

$ConfigFilename = (($Config).SQLMedia).ConfigFile;$BaseConfigFilename = (($Config).SQLMedia).ConfigFileTemplate;

(Get-Content $BaseConfigFilename) | ForEach-Object {switch -regex($_) {

('INSTANCEDIR=') {$InstanceDir = ((($Config).Folders).Where{$_.Use -eq

"Instance"}).Path;'INSTANCEDIR="' + $InstanceDir + '"'}

('SQLUSERDBDIR=') {…}('SQLUSERDBLOGDIR=') {…}

# Keep unaltered linesDefault {$_};}

} | Set-Content -Path "$ConfigFilename" -Force;

Create ConfigurationFile.ini

Setup.exe – Local or Remote:

$install = 'Start-Process -verb runas -FilePath "' + $SQLInstaller + '" -ArgumentList /ConfigurationFile="' + $ScriptPath + '\ConfigurationFile.ini" -Wait';

Invoke-Expression $install;

$SQLInstaller = (($Config).SQLMedia).Installer;

Copy-Item $ConfigFilename "\\$Server\c$\Temp\" -Force;

$Install = '"' + $SQLInstaller + '“ /ConfigurationFile="C:\Temp\' + (Split-Path $ConfigFilename -Leaf) + '"‘

# Invoke-Command to remote server doesn't work with setup.exe (DCOM error). Using WMI instead.

([WMICLASS]"\\$Server\ROOT\CIMV2:Win32_Process").Create($Install)

Local

Remote

Additional Resources:

SQL Server PowerShell Modulehttps://docs.microsoft.com/en-us/sql/ssms/download-sql-server-

ps-module

PowerShell Galleryhttps://www.powershellgallery.com/

http://powershell.sqlpass.org/

Presentation Scriptshttps://blog.wicktech.net/sql-ps-install-scripts/

Questions?