Итак, предыдущий пост прочитан. Ящик валерьянки закуплен. Можно двигаться дальше.

Балансировщики и общая схема

В качестве подготовительного шага немного добавим правил на существующий балансировщик нагрузки. Предыдущая конфигурация балансировщика на примере Kemp VLM описана здесь. Помимо штатных правил я добавил новый VIP для HTTPS-трафика для Exchange 2010, чтобы избежать проблемы с Ambiguous URLs, а так же добавил новый VIP для HTTPS-трафика сервера Exchange 2016. Табличка с адресами получается следующая:

FQDN VIP Тип трафика
outlook.o365lab.pro 192.168.1.106 RPC
webmail.o365lab.pro 192.168.1.110 2010 HTTPS
192.168.1.108 2016 HTTPS

Картинка с правилами на балансировщике:

ex20161

Сама схема тестовой лабы выглядит примерно следующим образом:

ex20162

Имея эту схему на руках можно приступать к установке серверов Exchange 2016.

Установка пререквизитов

Ставить будем на Windows Server 2012R2. Список поддерживаемых ОС можно посмотреть тут. Предварительно ставим все необходимые компоненты операционной системы:

Install-WindowsFeature AS-HTTP-Activation, Desktop-Experience, NET-Framework-45-Features, 
RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, 
RSAT-Clustering-PowerShell, Web-Mgmt-Console, WAS-Process-Model, Web-Asp-Net45, 
Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, 
Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, 
Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, 
Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, 
Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation

После чего устанавливаются .NET Framework 4.5.2 и Microsoft Unified Communications Managed API 4.0.

После установки всех сопутствующих обновлений и перезагрузки сервера можно начинать устанавливать сам сервер Exchange 2016.

Установка сервера Exchange 2016

В процессе установки сервер подготовит схему, раздел конфигурации и доменные разделы. Более подробно процедуру подготовки со всеми требуемыми правами я описывал тут. Со стороны установщика поменялось только одно – все команды требуют использования ключа /IAcceptExchangeServerLicenseTerms. Таким образом, нам нужно будет запускать следующую последовательность команд:

setup.exe /PrepareSchema /IAcceptExchangeServerLicenseTerms
setup.exe /PrepareAD /IAcceptExchangeServerLicenseTerms
setup.exe /PrepareAllDomains /IAcceptExchangeServerLicenseTerms

Можно отдельно этого не делать и запускать установщик от учётной записи, входящей в группы Schema Admins и Enterprise Admins. Проверить готовность можно по версиям обновлённых объектов. Список версий можно посмотреть тут.

Сама установка запускается следующим образом:

setup.exe /Mode:Install /Roles:Mailbox   /IAcceptExchangeServerLicenseTerms

Сразу по завершении установки необходимо будет через EMS на новом сервере исправить настройку автообнаружения нового сервера. По умолчанию, служба автообнаружения будет отправлять клиентов на себя, а при отсутствии нормального сертификата, который мы ещё не успели выписать, клиент будет получать предупреждение о том, что источник данных службы автообнаружения использует не доверенный сертификат:

Set-ClientAccessService -Identity mbx161 
-AutodiscoverServiceInternalURI https://webmail.o365lab.pro/Autodiscover/Autodiscover.xml

После установки второго сервера:

Set-ClientAccessService -Identity mbx162 
-AutodiscoverServiceInternalURI https://webmail.o365lab.pro/Autodiscover/Autodiscover.xml

Серверы можно перегружать.

Полезные ссылки:
Миграция на Exchange 2016: вводные данные и подготовка
Kemp VLM: настраиваем Exchange 2010
Ambiguous URLs and their effect on Exchange 2010 to Exchange 2013 Migrations
Exchange 2016 system requirements
Exchange 2016 prerequisites
Миграция на Exchange 2010: подготовка домена
Prepare Active Directory and domains

Очередная встреча UC² будет совмещена со встречей сообщества IT Pro. В связи с этим встречаемся не в последний вторник месяца, а в последний четверг месяца, то есть 23 июня с 19-00 до 21-30. Встреча будет проходить в Технологическом Центре Microsoft (MTC) и транслироваться средствами Skype for Business Online. А вот кто будет выступать:

  1. Вадим Поданс, “Миграция с SHA1 на SHA2, мифы и реальность”

    В процессе доклада Вадимс опишет проблематику (уязвимость SHA1 на предмет коллизий) и политику вендоров в отношении SHA1. Обозначит стратегии миграции (обновление существующей инфраструктуры или миграция в новый PKI) и какие критерии будут влиять на выбор. А так же расскажет, как планировать и производить миграцию при обновлении существующей инфраструктуры с использованием демонстрации.

  2. Олег Крылов, “Управление Exchange Server с помощью Desired State Configuration”

    В докладе будет рассмотрена концепция применения декларативных конфигураций на базе технологии Desired State Configuration с использованием кастомного модуля PowerShell в условиях on-premise инсталляций. Будут разобраны как технические, так и архитектурные моменты. И все это с живой демонстрацией работы данной концепции.
    Это доклад, который Олег по техническим причинам не успел подготовить для MVP Community Roadshow, проходившем в Санкт-Петербурге 7 июня.

Регистрация на встречу как обычно тут.

Обновление. Записи доступны по ссылкам:
UC². Встреча №15. Олег Крылов. Управление Exchange Server с помощью Desired State Configuration

Давно я не брал в руки шашку. Поэтому миграция будет между крайними версиями 2010 и 2016 с пропуском версии 2013. Схема миграции в основном совпадает со схемой миграции 2007 → 2010. Кратко выглядит следующим образом:

  • Установка первых серверов, формирование DAG, подготовка точек подключения клиентов
  • Переключение клиентов с точек подключения Exchange 2010 на точки подключения Exchange 2016
  • Миграция пользовательских данных
  • Вывод из эксплуатации серверов Exchange 2010

Перед первой фазой категорически приветствуется ознакомление с документацией и пилотная миграция в изолированной среде.

На текущий момент имеются следующие известные проблемы, которые могут попортить кровь в процессе миграции и которых можно избежать в процессе предварительной подготовки:

  • Имеется известная бага/фича в работе приложения Autodiscover в Exchange 2016. Приложение кеширует данные в течение двух часов. Сразу после миграции ящика Autodiscover продолжит отдавать клиенту закэшированные данные со старыми настройками клиента. Это приводит к тому, что клиент Outlook в течение жизни кэша перенаправляется на старый сервер. Обходных путей решения проблемы ровно два:

– делаем вручную или автоматически recycle пула Autodiscover, это приведёт к сбросу кэша и клиент получит новые данные при следующем обращении
– пересоздаём локальный почтовый профиль пользователя

  • В старых версиях Exchange 2010 в инструкциях по планированию очень невнятно описаны рекомендации по планированию пространства имен для разных типов клиентов. В частности, сильно вскользь затронут момент с совпадением fqdn массива серверов CAS (CAS-Array) и точек подключения веб-клиентов (OA). В общем, это не рекомендуется делать. То есть RPC-клиенты будут обращаться к CAS-Array по одному доменному имени, а веб-сервисы должны быть доступны по другому. Если этого не придерживаться, то при миграции мы получим неработающих клиентов на новых серверах, как это описано тут. Связано это с тем, что Exchange 2016 про RPC-клиентов не знает вообще ничего. Всех клиентов он по умолчанию считает веб-клиентами. Сразу после миграции клиент попытается подключиться к CAS-Array (точка подключения для RPC-клиентов) на новом сервере, который про CAS-Array не знает ничего. На этом в общем то всё для клиента и закончится.

Самым правильным в данной ситуации, с моей точки зрения, будет поменять fqdn точки подключения веб-клиентов. Процедура эта проходит прозрачно для клиентов и не требует перезапуска, в отличие от смены fqdn точки подключения RPC-клиентов. По ссылке выше так же указан вариант с принудительным переключением всех клиентов на OA. Мне он нравится меньше, так как требует предварительных подготовительных работ.

  • При использовании связки Windows Server 2008 R2 + Exchange 2010 после миграции ящика может поломаться авторизация клиента. Подробнее проблема описана в следующей статье базы знаний. Там же ссылка на обновление, которое это исправляет.
  • Обновления, обновления, обновления… Обновляем всё до самых последних обновлений. Операционные системы на серверах и клиентах, серверы Exchange до последнего SP и RU, Outlook на клиентах.

Полезные ссылки:
Ambiguous URLs and their effect on Exchange 2010 to Exchange 2013 Migrations
Outlook Anywhere users prompted for credentials when they try to connect to Exchange Server 2013 or Exchange Server 2016

Задача: имеется список guid-ов объектов в AD, для которых необходимо получить некоторый набор свойств. Объекты могут быть как пользователями, так и группами или контактами. Искать нужно внутри многодоменного леса, объекты могут быть внутри любого домена в лесе. Найти объект, вне зависимости от его типа, можно через командлет Get-ADObject:

Get-ADObject $guid

Небольшое затруднение возникает, если необходимо делать поиск по всем доменам одного леса. Очевидное решение в лоб – взять список доменов и в каждом из них провести поиск:

$Domains = (Get-ADForest).Domains

ForEach ($Domain in $Domains)
{
$Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop
}

Работать будет, но с ошибками. Очевидно, что по-конкретному guid-у объект будет возвращаться только из одного домена. Поиск в остальных доменах вернёт ошибку, так как такого объекта там не будет. Поэтому имеет смысл внести в скрипт try-catch:

$Domains = (Get-ADForest).Domains
$Results = @()
ForEach ($Domain in $Domains)
{
  try
  {
    $Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop
    $Found = $true
  }
  catch
  {
    $Found = $false
  }
  If ($Found)
  {
    $Results += New-Object PSObject -Property @{
    guid = $guid
    Domain = $Domain
    DistinguishedName = $Search.DistinguishedName
    ObjectClass = $Search.ObjectClass
    Found = $Found
    }
  }
}

Добавляем загрузку из txt-файла списка guid-ов:

$guids = Import-Csv -Path C:\guids.txt
$Domains = (Get-ADForest).Domains
$Results = @()
ForEach ($guid in $guids)
{
  ForEach ($Domain in $Domains)
  {
    try
    {
      $Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop
      $Found = $true
    }
    catch
    {
      $Found = $false
    }
    If ($Found)
    {
      $Results += New-Object PSObject -Property @{
      guid = $guid
      Domain = $Domain
      DistinguishedName = $Search.DistinguishedName
      ObjectClass = $Search.ObjectClass
      Found = $Found
      }
    }
  }
}
$Results | Where { $_.Found } | Select guid,Domain,DistinguishedName,ObjectClass,Found

Задача решена и можно запускать скрипт и ждать. Если доменов у нас с десяток, объектов для поиска больше сотни, то ждать придётся долго. Что с эти делать? Искать в глобальном каталоге! Правда, стоит помнить, что он содержит не все аттрибуты объектов. Для поиска в глобальном каталоге используем тот же Get-ADObject, но в ключе -Server нужно будет указать любой ближайший глобальный каталог, по-умолчанию доступный при обращении к порту 3268:

$LocalSite = (Get-ADDomainController -Discover).Site
$NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -SiteName $LocalSite
if (!$NewTargetGC)
{ $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -NextClosestSite }
$NewTargetGCHostName = $NewTargetGC.HostName
$LocalGC = "$NewTargetGCHostName" + ":3268"

Try-catch при таком поиске нам будет нужен разве что для обработки поиска несуществующих guid-ов. Скрипт немного упростится:

$guids = Import-Csv -Path C:\guids.txt
$Results = @()
$LocalSite = (Get-ADDomainController -Discover).Site
$NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -SiteName $LocalSite
if (!$NewTargetGC)
{ $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -NextClosestSite }
$NewTargetGCHostName = $NewTargetGC.HostName
$LocalGC = "$NewTargetGCHostName" + ":3268"
ForEach ($guid in $guids) 
{
  Try 
  {
    $Search = Get-ADObject -Identity $guid.guid -Server $LocalGC
  }
  Catch {
  }
  $Results += New-Object PSObject -Property @{
  guid = $guid.guid
  DistinguishedName = $Search.DistinguishedName
  ObjectClass = $Search.ObjectClass
  }
}
$Results | Select guid,DistinguishedName,ObjectClass

Скрипт при этом отрабатывать будет на пару порядков быстрее.

Полезные ссылки:
Powershell Code: Discover a Local Global Catalog for Forest Queries
PowerShell Code: Find User in Active Directory Forest
Get-ADDomainController
Get-ADObject

Вводные данные. Имеется удалённый почтовый ящик, который пока ещё не был вычищен из базы. То есть его видно на вкладке Disconnected Mailbox в EMC. Есть запрос на его выгрузку в pst-файл. Переподключим этот ящик к новой учётке и попробуем выгрузить “новый” ящик в pst-файл. Видим вот такую красоту:

[PS] C:\>New-MailboxExportRequest -Mailbox test_mailbox -FilePath \\servername\pst\test.pst
Couldn't connect to the source mailbox.
+ CategoryInfo : NotSpecified: (0:Int32) [New-MailboxExportRequest], RemotePermanentException
+ FullyQualifiedErrorId : 186244BB,Microsoft.Exchange.Management.RecipientTasks.NewMailboxE...
+ PSComputerName : servername

Добавление ключа -v добавляет дровишек:

VERBOSE: [14:03:35.317 GMT] New-MailboxExportRequest : Couldn't connect to the source mailbox.
MapiExceptionCallFailed: Unable to make connection to the server. (hr=0x80004005, ec=1249)
Diagnostic context:
Lid: 59431 EMSMDB.EcDoConnectEx called [length=147]
Lid: 34855 EMSMDB.EcDoConnectEx returned [ec=0x4E1][length=56][latency=31]
Lid: 59505 StoreEc: 0x4E1
Lid: 52465 StoreEc: 0x4E1
Lid: 60065
Lid: 33777 StoreEc: 0x4E1
Lid: 59805
Lid: 52209 StoreEc: 0x4E1
Lid: 56583
Lid: 52487 StoreEc: 0x4E1
Lid: 19778
Lid: 27970 StoreEc: 0x4E1
Lid: 17730
Lid: 25922 StoreEc: 0x4E1

Судя по MapiExceptionCallFailed что-то у нас не так пошло с подключением к ящику по MAPI. Смотрим свойства ящика:


[PS] C:\>Get-CASMailbox test_mailbox | fl mapi*

MAPIEnabled : True
MAPIBlockOutlookNonCachedMode : True
MAPIBlockOutlookVersions :
MAPIBlockOutlookRpcHttp : 

Блокировка онлайн-режима – нехорошо. Меняем:

[PS] C:\>Set-CASMailbox test_mailbox -MAPIBlockOutlookNonCachedMode:$false

После этого экспорт запускается.