Pages

Thursday, July 18, 2013

Configure Search on Dedicated APP Server

This blog is part of Series : Comprehensive SharePoint 2013 Development Environment Installation and Configuration

Overview

This blog article discusses how to configure Search Service in SP 2013 such that each of the new sub components of the Search Service can be allocated to run on different APP(s) server.

Based on our initial design we want to run all the Search Service components on SP2013APP2 server.

Steps

Unlike prior SharePoint version, in SharePoint 2013 the Search Service Application topology must be configured via PowerShell only.  Hence I have prepared the following below PowerShell script by referencing this blog.

Substitute following below for your specific environment:

ssaName: Your Search Service Application Name

dbSrv: Your Database name where the Search Service Application related databases will be created

dbNamePrefix: Such as Dev_ or QA_ or Prod etc.  if you desire.

appPoolName : Search Service Application Pool Name

appPoolAccount : Search Service Application Pool  Account

servers : Here you should substitute your Search server name.

See below the script for further instructions:

#---------------------
# Component Type Key:
#---------------------
# Admin: Admin Component
# CC: Crawl Component
# CP: Content Processor
# AP: Analytics Component
# IP: Index Partition Component
# QP: Query Processor
#------------------------------------

$ssaConfig = @{
ssaName = "Search Service Application";
dbSrv = "DC";
dbNamePrefix = "";
appPoolName = "SharePoint Search Application Pool"; # if exists, will just use the existing pool
appPoolAccount = "CORP\SPSearchService";
servers = @{
"SP2013APP2" = @{ components = @{ Admin=$true; CC=$true; CP=$true; AP=$true;IP=$true; QP=$true; };
index = @{ Partition=0; # The index partition number
Path="C:\Program Files\Microsoft Office Servers\15.0\Data\Office Server\Applications\"
# Specified path must exist and be empty
};
};

}
};



$err = $null
#-----------------------
# Create the App Pool(s)
#-----------------------

# Create managed account if it does not exist
if ((Get-SPManagedAccount $ssaConfig.appPoolAccount -ErrorVariable err -ErrorAction SilentlyContinue) -eq $null) {
"
****************************************************** "
"
* Create managed account for " + $ssaConfig.appPoolAccount
"
****************************************************** "
$credential = Get-Credential
if ($credential -eq $null) { "
Terminating script..."; start-sleep 10; exit; }
New-SPManagedAccount -Credential $credential
}

$sqssPool = Get-SPServiceApplicationPool | where {$_.Name -eq $ssaConfig.appPoolName }
if ($sqssPool -ne $null) {
"
-- Search App Pool [" + $ssaConfig.appPoolName + "] already exists... <skipping>"
} else { $sqssPool = New-SPServiceApplicationPool -name $ssaConfig.appPoolName -account $ssaConfig.appPoolAccount }

if ($ssaConfig.adminPoolName -ne $null) {
$adminPool = Get-SPServiceApplicationPool | where {$_.Name -eq $ssaConfig.adminPoolName }
if ($adminPool -ne $null) {
"
-- Search Admin App Pool [" + $ssaConfig.adminPoolName + "] already exists... <skipping>"
} else { $adminPool = New-SPServiceApplicationPool -name $ssaConfig.adminPoolName -account $ssaConfig.adminPoolAccount }
} else {
$adminPool = $sqssPool;
}

$ssaConfig.Add("
sqssPool", $sqssPool)
$ssaConfig.Add("
adminPool", $adminPool)

#---------------------------------------------------------------------------
# start the Search Instances (if not already online) on the relevant servers
#---------------------------------------------------------------------------
"
Starting Search Instances..."
foreach ($netbios in $ssaConfig.servers.keys) {
"
[" + $netbios + "]"
if ((Get-SPServer $netbios -ErrorVariable err -ErrorAction SilentlyContinue) -eq $null) {
"
The server" + $netbios + "is not found in this farm..."
"
Terminating script..."; start-sleep 10; exit;
} else {
if ((Get-SPEnterpriseSearchServiceInstance -identity $netbios).status -ne "
Online") {
Start-SPEnterpriseSearchServiceInstance -identity $netbios
}
}
$ssaConfig.servers[$netbios].instance = Get-SPEnterpriseSearchServiceInstance -identity $netbios
}

#------------------------------------------------------------------------------------------------
# Create the new SSA (which may take a while (~10min) to run...
#------------------------------------------------------------------------------------------------
"
Creating New SSA"
"
- My tests have taken ~10 min to complete this step"
"
- Starting at: " + (Get-Date)

if ($ssaConfig.dbNamePrefix -ne $null) {
$dbPrefix = $ssaConfig.dbNamePrefix
} else { $dbPrefix = $ssaConfig.ssaName }

$SSA = New-SPEnterpriseSearchServiceApplication -name $ssaConfig.ssaName -ApplicationPool $ssaConfig.sqssPool -AdminApplicationPool $ssaConfig.adminPool -DatabaseServer $ssaConfig.dbSrv -DatabaseName $dbPrefix
New-SPEnterpriseSearchServiceApplicationProxy -name $ssaConfig.ssaName -SearchApplication $SSA

"
Cloning the topology..."
$initialTopo = $SSA | Get-SPEnterpriseSearchTopology -Active
$newTopo = $SSA | New-SPEnterpriseSearchTopology

#------------------------------------------
# Create the new components on each server
#------------------------------------------
"
Creating Components on specified server(s)... "
foreach ($netbios in $ssaConfig.servers.keys) {
foreach ($type in $ssaConfig.servers[$netbios].components.keys) {
if ($ssaConfig.servers[$netbios].components[$type]) {
"
[" + $netbios + "] --> " + $type
switch ($type) {
"
Admin" {
New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance
$SSA | Get-SPEnterpriseSearchAdministrationComponent | Set-SPEnterpriseSearchAdministrationComponent -SearchServiceInstance $ssaConfig.servers[$netbios].instance
$SSA | Get-SPEnterpriseSearchAdministrationComponent
}
"
CC" { New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance }
"
CP" { New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance }
"
AP" { New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance }
"
QP" { New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance }
"
IP" { New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopo -SearchServiceInstance $ssaConfig.servers[$netbios].instance -IndexPartition $ssaConfig.servers[$netbios].index.Partition -RootDirectory $ssaConfig.servers[$netbios].index.Path }
}
}
}
}

"
Activating the new topology:"
"
- This also may run for a few minutes..."
$newTopo.Activate()

"
Cleaning up the inactive topology..."
while ($newTopo.State -ne "
Active") { "."; start-sleep 10; }
$SSA | Get-SPEnterpriseSearchTopology | Where {$_.State -eq "
Inactive" } | Remove-SPEnterpriseSearchTopology -Confirm:$false


Ensure that the Search Index path (C:\Program Files\Microsoft Office Servers\15.0\Data\Office Server\Applications\) on SP2013APP1 and SP2013APP2 are empty



Login to APP1 or APP2 with SPSetupAccount



Copy and prepare the powershell script file and save at a location locally



clip_image001



Run the SP 2013 PowerShell command as Administrator



clip_image002



Run the Saved Script



clip_image003



clip_image004



Validate in the CA that the new Search Service Application is started



clip_image005



Click on the Search Service Application to get in to the Search Service Administration page as below.



clip_image006



Click on the link against the Global Search Center URL and set the Search Center that we had previously created:



clip_image007



Update the Search Content Access Account from SPSearch to SPCrawl



clip_image008



clip_image009



clip_image010



clip_image011



At the end now you can see that only APP2 server is running the Search Service



clip_image012


7 comments:

Qx said...

There is a case issue in the word index. In $ssaConfig it is index and when used later on it is Index. Thos fails to create the topology. Please correct for someone else's benefit :)
I had fun with it!

Anonymous said...

Hi,
Thanks for the great post. I've followed the Exact steps as described, and in my case I'm using E drive to deploy search stuff. Under "E:\Program Files\Microsoft Office Servers\15.0\Data\Office Server\" I've created a folder called "Applications" and then I ran the script. The script ran fine until creating the Index part and I'm getting the error "Cannot bind to parameter RootDirectory"
Anything that I could be doing wrong?

Rajesh Agadi said...

@Qamar Zaman,

Thanks for pointing this out. I have corrected the Index to index.


Rajesh Agadi said...

@Anonymous,

Ensure that your Application folder is empty. If you have more than one server, ensure that Application folder has same Drive/Path across all of those servers and that they are all empty before you run this script to configure.

-Rajesh

Nick said...

Hi Rajesh,

Thanks for the script, it did configure as expected.
Can we use different index folder, like E:\Index\Application\

For some reason I after the configuration is completed, the search page does not return any values.
In crawl logs I have like 50 success items.

Thanks,
Nick

Rajesh Agadi said...

Hi Nick,

You can use any location for the Index as long as that path maps to a local drive on the server (and on each App server where you will be configuring the Index).

Well once you have search configured based on this blog, you want to ensure that the same search service application is part of the Web Application and Service Applications association to be able to get result.

-Rajesh

Henry said...

Great script, thanks.

Consider changing the value of dbNamePrefix to $null instead of ""

The subsequent if..else statement will always result to $true as "" is not the same as $null.

if ($ssaConfig.dbNamePrefix -ne $null) {
$dbPrefix = $ssaConfig.dbNamePrefix
} else { $dbPrefix = $ssaConfig.ssaName }

The result is that your databases are named the prefix name and not the prefix followed by the search service name which is what I believe is intended.

I also like having "proxy" appended at the end:
$proxyname=$ssaConfig.ssaName + " Proxy"

New-SPEnterpriseSearchServiceApplicationProxy -name $proxyname -SearchApplication $SSA