четверг, 22 ноября 2012 г.

Репликация баз данных в SCCM 2012

Введение.
В этой статье я хотел бы рассказать о новом механизме репликации данных, появившемся в SCCM 2012. Статья не претендует на сверхточность или супердетальность описания этого процесса. Основное внимание будет уделено именно концепции механизма репликации, хотя некоторые детали, который на мой взгляд могут быть полезны, все-таки будут приведены.
В System Center 2012 Configuration Manager появился дополнительный способ репликации данных иерархии SCCM – репликация данных с помощью механизмов SQL Server. Достаточно оправданный ход со стороны Microsoft в сторону упрощения реализации этой задачи. В процессе репликации задействуется два важных механизма: Database Change Tracking и SQL Server Service Broker. Первый появился в SQL Server  2008, второй в SQL Server 2005. Видимо из-за отсутствия Database Change Tracking в SCCM 2007 (или 2007 R2) не было репликации с помощью SQL Server (хотя может и по другим причинам). 

Основные понятия.
Для понимания самого процесса репликации очень важно разобраться в используемых механизмах.
  • Database Change Tracking – механизм, который появился в SQL Server 2008. Предназначен для отслеживания изменений в таблицах SQL Server, предоставляет функции для работы с этими изменениями. Подробнее об этой функции можно почитать здесь - http://msdn.microsoft.com/en-us/library/bb933875.aspx.
  • SQL Server Service Broker – механизм SQL Server, входящий в компонент Database Engine. Предназначен для обмена сообщениями в распределенных приложениях. Механизм пришел на смену MSMQ (Microsoft Message Queuing) и призван упростить задачу межпроцессного обмена информацией. Подробнее о Service Broker можно прочитать здесь - http://msdn.microsoft.com/en-us/library/ms166104(v=sql.100).aspx. Позже мы еще вернемся к Service Broker.
  • Тип данных для репликации: global, site, local, global_proxyЛокальные данные не реплицируются, глобальные данные реплицируются на всю иерархию, данные сайта реплицируются с основного (primary) сайта на центральный (central) сайт. Global_proxy - это подмножество глобальных данных. Тип этой репликации используется только между Primary и Secondary сайтами, поэтому, например, на CAS вы не найдете соответствующий код для репликации.



Service Broker.
Этот сервис пришел на смену MSMQ, упростив задачу межпроцессного обмена данными. Service Broker освобождает вас от рутиной работы и многое далает за вас. Он берет на себя такую работу как авторизация, аутентификация (за счет посредников конечно), доставка данных, хранение, уникальность, очередность и т.д. И причем все эти функции доступные через весьма простые программные интерфейсы и T-SQL.
Для работы с Service Broker (в том числе и в SCCM) используются следующие объекты:
  • Диалог (dialog) – можно сказать что это сессия TCP, не в прямом смысле конечно, но похоже. То есть также есть некоторые две стороны, которые обмениваются сообщениями. При этом обеспечивается гарантированная доставка, подтверждение, очередность. Сторона установившая диалог называется инициатор (initiator), отвечающая сторона – target.
  • Сообщения (Message) – этими объектами просходит обмен. Сообщения могут быть любого типа, от бинарных данных, до «правильного» XML или даже Service Broker может проверять сообщения с помощью XML-схемы.

Для SCCM определены ряд сообщений, такие как, DRS_SyncStart, DRS_SyncEnd, DRS_SyncData и т.д. Всего определено порядка 30 сообщений. Например, определение основного сообщения репликации данных DRS_SyncStart выглядит так:
CREATE MESSAGE TYPE [DRS_SyncData] AUTHORIZATION [dbo] VALIDATION = NONE
  • Контракты (Contracts) – эти объекты определяют типы сообщений, которые можно послать в диалоге, а также разрешенные типы сообщений для обоих сторон диалога. Например, можно ограничить отправку определенных сообщений, которые может послать только инициатор (initiator), тип сообщений которыми может ответить target или указать что сообщение может использоваться обеими сторонами.

Для SCCM определены контракты по приоритетам репликации: CriticalPriority, HighPriority и т.д.
К примеру, для репликации данных с приоритетом ниже среднего определен контракт LowNormalPriority:
CREATE CONTRACT [LowNormalPriority]
AUTHORIZATION [dbo] ([DRS_SchemaChange] SENT BY ANY,[DRS_StartMsgBuilder] SENT BY ANY,[DRS_SyncBinaryData] SENT BY ANY,[DRS_SyncBinaryDataCompressed] SENT BY ANY,[DRS_SyncComplete] SENT BY ANY,[DRS_SyncData] SENT BY ANY,[DRS_SyncDataCompressed] SENT BY ANY,[DRS_SyncEnd] SENT BY ANY,[DRS_SyncStart] SENT BY ANY)
  •  Сервисы (Services) – Диалог между участниками происходит как раз с использованием сервисов. У сервисов есть имена и очереди сообщений. Можно представить что сервисы это почтовые адреса.
Для SCCM используются такие сервисы как, ConfigMgrDRS_Site<код_сайта> (этот для репликации глобальных данных между сайтами), ConfigMGRDRSSite_Site<код_сайта (для репликации данные с областью site) или, например, ConfigMgrDrsMsgBuilder (используется для запуска репликации).
Например, определение сервиса для репликации глобальных данных (в том числе и global_proxy):
CREATE SERVICE [ConfigMgrDRS_SiteABC]
AUTHORIZATION [dbo]
ON QUEUE [dbo].[ConfigMgrDRSQueue]
([CriticalPriority],[HighPriority],[LowNormalPriority],[LowPriority],[NormalPriority])
  •  Очереди (Queues) – объекты, которые ассоциированы с некоторым сервисом. Сообщение, отправленное на целевой сервис, попадает в его очередь и ждет обработки. Процесс извлечения сообщений может происходить  вручную или с помощью хранимой процедуры, которая вешается на очередь.
Для каждого сервиса созданы очереди. Так выглядит очередь для репликации глобальных данных сайта BCD:
CREATE QUEUE [dbo].[ConfigMgrDRSQueue]WITH STATUS = ON , RETENTION = OFF ,
POISON_MESSAGE_HANDLING (STATUS = ON)  ON [PRIMARY]

А так - очередь для инициации репликации:
CREATE QUEUE [dbo].[ConfigMgrDRSMsgBuilderQueue]
WITH STATUS = ON , RETENTION = OFF ,
ACTIVATION (  STATUS = ON , PROCEDURE_NAME = [dbo].[spDRSMsgBuilderActivation] , MAX_QUEUE_READERS = 5 , EXECUTE AS N'dbo'  ),
POISON_MESSAGE_HANDLING (STATUS = ON)  ON [PRIMARY]
На этой очереди висит процедура spDRSMsgBuilderActivation, которая запускается если в очереди есть сообщения.
  • Маршруты (Routes). С помощью маршрутов определяется расположение целевого сервиса. Можно сравнить данный объект с типом записи SRV в DNS. Если целевой сервис на который отправляется сообщение находится на удаленной системе, то просматривается маршрут, который был создан для этого сервиса и в котором указан сетевой адрес и порт (адрес и порт Service Broker). Точнее сначала просматривается маршрут до целевого сервиса, а потом уже определяется что он на удаленной системе. Если маршрут не найден, то используется маршрут по умолчанию, который указывает на локальный экземпляр SQL Server.

Для каждого сервиса определены маршруты. Например, для удаленного сайта создан маршрут ConfigMgrDRSRoute_SiteBCD, который указывает на удаленную систему:
CREATE ROUTE [ConfigMgrDRSRoute_SiteBCD]
AUTHORIZATION [dbo]
WITH  SERVICE_NAME  = N'ConfigMgrDRS_SiteBCD' ,
ADDRESS  = N'TCP://EF-CM12-02.cm12.local:4022'
Теперь концептуально рассмотрим сам процесс обмена сообщениями в Service Broker.

Диалог между сервисами происходит следующим образом:

1) Приложение-инициатор начинает диалог:
BEGIN DIALOG CONVERSATION @dialog_handle
FROM SERVICE [ConfigMgrDRS_SiteABC]
TO SERVICE 'ConfigMgrDRS_SiteBCD'
ON CONTRACT [NormalPriority]
2) В @dialog_handle возвращается описатель этого диалога. Этот описатель используется для отправки и приема сообщений между участниками.
3) Формируется сообщение. Способ формирования не имеет значение. Как формируются сообщения в SCCM будет описано чуть ниже.
4) Далее, сформированное сообщение отправляется:
SEND
ON CONVERSATION @dialog_handle
MESSAGE TYPE DRS_SyncData (@Message)
5) Диалог и объекты служб (а также контракт) определяется по описателю. По маршруту определяется расположение сервисов.
6) Сообщение отправляется целевому сервису.
7) После приема на целевой стороне, сообщение попадает в очередь, которая привязана к сервису.
8) Далее сообщение, вручную или с помощью ассоциированной с очередью хранимой процедурой, извлекается из очереди. Например, вот такой конструкцией:
WAITFOR (
      RECEIVE TOP(1) @ReceivedMessageType=message_type_name,
                     @ReplicationGroup=message_body,
                     @ConversationHandle=conversation_handle
            FROM dbo.ConfigMgrDRSMsgBuilderQueue
            ), TIMEOUT 5000
9)      Полученное сообщение обрабатывается.
10)   Может быть отправлено ответное сообщение.
11)   Диалог завершается конструкцией END CONVERSATION @DialogHandle

Репликация SCCM
Обсудив принципы работы с Service Broker, можно переходить к принципам функционирования репликации в SCCM.

Инициатор.

1)      Например, мы изменили границы (Boundary) в нашей иерархии. Процесс проходит через SMS-провайдер, попадает в базу, запускается ряд дополнительных потоков, таких как Database Notification Monitor, Hierarchy Manager и т.д. На этом этапе данные зафиксированы в БД (в нашем случае в таблице BoundaryEX). Далее.
2) [SMS_REPLICATION_CONFIGURATION_MONITOR]: Компонент MS_REPLICATION_CONFIGURATION_MONITOR запускает каждую минуту процедуру spDRSInitiateSynchronization (можно увидеть в логе rcmctrl.log).
3)      [spDRSInitiateSynchronization]: Процедура просматривает таблицу ReplicationData и получает все группы объектов репликации, которые не реплицировались определенный интервал времени (SyncInverval*60) и который в данный момент не реплицируются. Для глобальных данных определен интервал в 1 минуту, для данных сайта – 5 минут.

Объекты Boundary относятся к группе 3 (столбец ID) с типом репликации global.
4)      [spDRSInitiateSynchronization]: Для каждой группы репликации формируется сообщение типа DRS_StartMsgBuilder с телом равным наименованию группы репликации (ReplicationGroup). Сообщение отправляется сервису  ConfigMgrDRSMsgBuilder (и от сервиса ConfigMgrDRSMsgBuilder). Это локальный сервис. Отправка сообщения происходит, если репликация инициируется с сервера в Primary сайте или область репликации не равна site. То есть это проверка, что CAS не должен отсылать данные с областью site другим сайтами (Primary).
5)      [Service Broker]: Сообщение попадает в очередь ConfigMgrDRSMsgBuilderQueue (ассоциирована с сервисом ConfigMgrDRSMsgBuilder). На очереде висит процедура spDRSMsgBuilderActivation
6) [spDRSMsgBuilderActivation]: Процедура spDRSMsgBuilderActivation сканирует очередь ConfigMgrDRSMsgBuilderQueue, вытаскивает сообщения с типом DRS_StartMsgBuilder и запускает другую процедуру – spDRSSendChangesForGroup.

7)      [spDRSSendChangesForGroup]: Это основная процедура для отправки изменений. В этой процедуре происходят различные проверки, получение описателей диалогов Service Broker и т.д.
8)      [spDRSSendChangesForGroup]: Определяется максимальная версия данных в базе данных. Версию можно восприниматься как некий USN (Unique Sequence Number), который ассоциируется с изменениями. MaxVersion = CHANGE_TRACKING_CURRENT_VERSION().
9)      [spDRSSendChangesForGroup]: Определяются последние версии (USN) отправленные в целевой сайти (а также полученные). Эти данные извлекаются из таблицы DRS_MessageActivity и DRS_MessageActivity_Sent.
10)      [spDRSSendChangesForGroup]: Дальше происходит определение статей (таблица ArticleData), которые необходимо реплицировать. Статьи в данном случае это таблицы (нас интересует BoundaryEx). У каждой статьи есть группа репликации (в нашем случае 3). С помощью функций Database Change Tracking определяется USN статьи и, если USN статьи больше чем USN последней отправленной репликации, то статья попадает под процесс репликации.
11)      [spDRSSendChangesForGroup]: Сами данные необходимые для репликации  (измененные с момента последней удачной репликации) определяется с помощью хранимой процедуры SCCM_RDS_spGet<Имя статьи>Changes в случае если область репликации равна  site или с помощью функции SCCM_DRS.fnGet<Имя статьи>Changes в ином случае. Процедуры spGet<Имя статьи> существуют только на первичном сайте (не standalone), поскольку CAS не реплицирует данные с областью site. Последнее предложение справедливо и для вторичного сайта.
12)      [fn|spGet<имя статьи>Changes]: В этой функции (или процедуре) используется обычная конструкция T-SQL  from CHANGETABLE(CHANGES <имя таблицы>). Измененные данные возвращаются в формате XML или бинарном виде (после сериализации процедурой spDRSSerializeQuery). Бинарный вид данных используется только для области репликации site. Почему именно так – сказать не могу. Для Secondary-сайта также используются функции формата fnGet<имя статьи>ChangesSec. В этих функциях происходит фильтрация данных, реплицируемых на вторичный сайт или со вторичного сайта. Также на вторичном сайте перед формированием данных из репликации исключаются некоторые статьи (типа global_proxy) (ArticleData.OptionalFlag & 0x2 = 0x2).
13)      [spDRSSendChangesForGroup]: Далее отправляется сообщение типа DRS_StartSync сервису ConfigMgrDRS_Site<код целевого сайта> или ConfigMgrDRSSite_Site<Код целевого сайта> (из процедуры spDRSSendStartMsg). ConfigMgrDRSSite_Site<Код целевого сайта> используется для данных типа site.
14)      [spDRSSendChangesForGroup]: Если есть данные (отличные от данных типа site) для репликации, то далее изменения формируются в сообщения и отправляются с помощью процедуры spDRSSendDataMsg. Если сжатие для группы репликации (ReplicationData.Flags & 1 = 1, в моем случае везде NULL, то есть сжатие не используется) включено и размер сообщения > 2КБ, то происходит сжатие даннных с помощью функции fnCompressData.  Если сжатые данные больше чем изначальные, то сжатие не используется. Если используется сжатие, то тип сообщения DRS_SyncDataCompressed, иначе тип сообщения DRS_SyncData. Служба для отправки ConfigMgrDRS_Site<код-целевого-сайта>.
Вот так выглядит сообщение DRS_SyncData:
<DRS_SyncData BuildNumber="7711" LastSyncVersionToSource="1221127" ThisVersion="77819" SyncID="1B102B82-71B2-4051-8B2A-15C41E430354" ReplicationGroupID="3" MessageID="4D06DD9F-CBE0-4907-8139-C06955926D4B">
<Operation Type="I" TableName="BoundaryEx" Context="">
    <row BoundaryID="8" Name="" CreatedBy="CM12\Administrator" CreatedOn="2012-11-18T20:46:20" ModifiedBy="CM12\Administrator" ModifiedOn="2012-11-18T20:46:20" BoundaryType="0" Flags="0" Value="192.168.59.0" />
  </Operation>
</DRS_SyncData>
15)      [spDRSSentDataMsg или spDRSSentBinaryDataMsg]: Для групп 2 и 3 сообщения логируются процедурой spDRSInsertSentMessage в таблицу DRSSentMessage. Можно конечно попробовать изменить текст функции fnISLogDrsMessageDataOn (в тестовой среде конечно) для изучения репликации, но Microsoft позаботился об этом и каждую минуту запускается код, который изменяет текст некоторых объектов на исходный. Если хотите посмотреть на содержимое сообщений, то лучше убрать проверку непосредственно в хранимых процедурах spDRSSentDataMsg и spDRSSentBinaryDataMsg. Также можно вставить некий код логирования в процедуры spDRSSentStartMsg и SpDRSSentEndMsg.
16)      [spDRSSendChangesForGroup]: Если есть данные сайта (site scope) для репликации, то используется отправка бинарных данных. Этот тип данных и тип сообщения используется только для репликации данных сайта и измененные данные извлекаются с помощью процедуры SCCM_DRS.spGet<имя статьи>Changes. Отправка данных происходит в отдельной процедуре spDRSSentBinaryDataMsg.
17)      [spDRSSentBinaryDataMsg]: Отправка бинарных данных происходит по тому же принципу. Проверяется необходимость сжатия для группы данных и отправка сообщения DRS_SyncBinaryDataCompressed или DRS_SyncBinaryData. Теми же самыми механизмами определяется необходимость логирования данных. Сервис используется другой – ConfigMgrDRSSite_Site<код сайта>. Secondary-сайт не реплицирует данные с областью site, поэтому такой сервис отсутствует на сервере баз данных вторичного сайта.
В бинарном виде сообщение не очень презентабельно, а вот после десериализации выглядит как обычная таблица:

Это таблица Summarizer_Components.
18)       [spDRSSendChangesForGroup]: Диалог репликации завершается вызовом процедуры spDRSSentEndMsg, в которой отправляется сообщение типа DRS_SyncEnd.
19)      [spDRSSendChangesForGroup]: Далее происходит очистка различных временных таблиц и обновление статуса репликации в таблице DRS_MessageActivity_Sent. Эта таблица постоянно используется для определения текущего статуса и для обновления статуса по ходу выполнения процесса.

На другой стороне.
Что же происходит на принимающей стороне?
С принимающей стороной немного сложнее, поскольку используется в основном код CRL.
1)      [SMS_REPLICATION_CONFIGURATION_MONITOR]: На стороне приема для обработки используется CRL хранимая процедура – spDRSActivation, которая определена в сборке messagehandlerservice.dll (можно найти в bin каталоге SCCM). Метод для вызова процедуры – ServiceProcedure из класса Microsoft.ConfigurationManager.DataReplicationService.MessageHandlerService.
2)      [messagehandlerservice.dll]: В этой же сборке определены дополнительные классы и их методы для работы с сообщениями репликации.
3)      [messagehandlerservice.dll]: Извлекается сообщение, парсится, определяется его тип, метод кодирования. Из сообщения извлекаются данные для изменения, определяется зависимость данных и выполняется соответствующая хранимая процедура для внесения изменений в целевые таблицы. Для операции Delete вызывается процедура SCCM_DRS.spDelete<имя таблицы>. Для операций Insert или Update вызывается хранимая процедура SCCM_DRS.spUpsert<имя таблицы>.
4)      [spDRSDelete|spDRSUpsert]: В этих процедурах определены дополнительные проверки и методы обнаружения конфликтов. Обнаруженные конфликты логируются в таблицу DRSConflictInfo. Данные для изменения вносятся в целевые таблицы.
5)      [messagehandlerservice.dll]: Из дополнительных полезностей можно отметить логирование сообщений процедурой  spDRSInsertReceivedMessage. Необходимость логирования определяется все той же функцией fnIsLogDrsMessageDataOn (логируются группы 2 и 3). Сообщения на этот раз сохраняются в таблице DRSReceivedMessages.

Вместо заключения.
Вместо заключения хотелось бы перечислить ряд дополнительных методов,  с помощью которых можно получить сведения о репликации баз данных в SCCM 2012:
1)      Область Monitoring консоли управления ConfigManager. С помощью узла Database Replication (и его контекстных команд) можно получить сведения о статуе репликации, запустить диагностику.
2)      Таблицы DRS_MessageActivity, DRS_MessageActivity_Send, DRS_MessageActivity_Receive. Эти таблицы используются в процессе репликации для отслеживания статуса, а также для внесения сведений о ресультатах репликации. В таблицах есть поле для ошибок, возникающих в ходе репликации. Расшифровку этих ошибок можно поискать в соответствующих процедурах или функциях, запускаемых во время репликации. Большую часть сведений из этих таблиц можно получить с помощью консоли управления.
3)      Процедура spDiagDRS. Эта процедура запрашивает данные с разных таблиц (в том числе и с DRS_MessageActivity*) и отображает информацию о статусе (DRS_MessageActivity*), статьях (ArticleData), группах репликации (ReplicationData) и т.д.. Также отображаются сведения о Service Broker.
4)      Стандартный отчет Service Broker. В SQL Management Studio доступен отчет, отображающий статистику Service Broker. Для запуска необходимо открыть контекстное меню папочки Service Broker (в Management Studio) и выбрать Reports > Standard Reports > Service Broker Statistics. Данный отчет отображает различные диаграммы, состояние и статистику сервисов и очередей. Также отображаются базовые сведения о производительности Service Broker.

понедельник, 19 ноября 2012 г.

SCCM 2012: проблема с SQL Native Client от SQL 2008 R2

В SCCM 2012 существует проблема при использовании SQL Native Client 2008 R2 на стороне сайт-сервера. Сам SCCM при установке сайт-сервера не ставит Native Client 2008 R2, а как раз ставит правильный - Native Client 2008.
В моем случае сервер для установки SCCM готовил не я сам. Уидимо кто-то решил помочь и  поставил этот компонент. И что самое интересное, SCCM работал без проблем пару недель. Можно конечно подумать что накатились обновления, но software update для этого сервера отключен и в журналах никаких признаков установки нет.

Симптомы:
1) Консоль управления не цепляется к сайту. В логах SMS-prov следующие ошибки:
*** [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]SSL Provider: The target principal name is incorrect.
*~*~[08001][-2146893022][Microsoft][SQL Server Native Client 10.0]SSL Provider: The target principal name is incorrect.~~     ThreadID : 1256 , DbError: -2146893022 , Sev: 0~*~*
*** [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]Client unable to establish connection
*~*~[08001][-2146893022][Microsoft][SQL Server Native Client 10.0]Client unable to establish connection   [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]SSL Provider: The target principal name is incorrect.~~  ThreadID : 1256 , DbError: -2146893022 , Sev: 0~*~*
*** Failed to connect to the SQL Server.
*~*~e:\nts_sccm_release\sms\siteserver\sdk_provider\smsprov\sspobjectquery.cpp(6194) : SQL Connection attempt timed out~ SQL Error: [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]Client unable to establish connection~*~*
*~*~SQL Connection attempt timed out [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]Client unable to establish connection~*~*
<*><*> CANT CONNECT TO SQL, RETURNING ERROR <*><*>

2) Сервис SMS_Executive пишет следующие ошибки в лог smsexec.log:
*** [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]SSL Provider: The target principal name is incorrect.
*** [08001][-2146893022][Microsoft][SQL Server Native Client 10.0]Client unable to establish connection
*** Failed to connect to the SQL Server.
CSiteControlEx::GetCurrentSiteInfo: Failed to get SQL connection
CSiteControlEx::GetMasterSCF:Failed to read site information from database, retry in 5 seconds ...

3) В системном журнале Windows генерируется множество следующих ошибок:
Source: Schannel
Event ID: 36888
The following fatal alert was generated: 43. The internal error state is 552.

Source: Schannel
Event ID: 36884
The certificate received from the remote server does not contain the expected name. It is therefore not possible to determine whether we are connecting to the correct server. The server name we were expecting is clusql.domain.com. The SSL connection request has failed. The attached data contains the server certificate.

Решение:
1) Удалить SQL Native Client от SQL 2008 R2 на сайт сервере
2) Установить SQL Native Client от SQL 2008 SP3 CU4

После этого сервис SMS_Executive начал подключаться к SQL без ошибок.

Правда появлись дополнительная проблема: сломался .Net framework 4.0. В связи с чем консоль управления начала вылетать с ошибкой:
Faulting application name: Microsoft.ConfigurationManagement.exe, version: 5.0.7711.0, time stamp: 0x4f42f40f
Faulting module name: clr.dll, version: 4.0.30319.237, time stamp: 0x4dd234a8
Exception code: 0xc0000005
Fault offset: 0x00024e38
Faulting process id: 0x748
Faulting application start time: 0x01cdc638010579f4
Faulting application path: C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\Microsoft.ConfigurationManagement.exe
Faulting module path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Report Id: 410b61bf-322b-11e2-b254-005056bf4d9e

Полечилось переустановкой (Repair) Net framework 4.0.

пятница, 16 ноября 2012 г.

Определяем и удаляем клиентов SMS 2003

Небольшой скриптец на VBScript, который я использовал для определения установленного на компьютере SMS 2003 клиента:

'-CheckSMS2003Client.vbs--------------------------------------------

option explicit

Dim Services

Set Services = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_Service where Name='CCMEXEC'")
if Services.Count = 0 then
Wscript.Echo "CCMEXEC Service не найдена"
Wscript.Quit 1
end if

Dim CMNameSpace
Dim CMobjs
Dim CMobj 

On Error Resume Next
Err.Number = 0
set CMNameSpace = GetObject("winmgmts:\\.\root").ExecQuery("select * from __Namespace where name = 'ccm'")
if Err.Number <> 0 then
WScript.echo Err.Message
Wscript.Quit 2
end if
On error Goto 0

if CMNameSpace.Count = 0 then
Wscript.Echo "CCM namespace не найдено"
Wscript.Quit 1
end if 

On Error Resume next
Err.Clear
set CMObjs = GetObject("winmgmts:\\.\root\ccm").ExecQuery("SELECT * FROM SMS_Client")
if Err.Number <> 0 then
Wscript.Echo Err.Message
WScript.Quit 2
end if 

On Error Goto 0

if CMObjs.Count = 0 then
WScript.Echo "Объекты SMS_Client не найдены"
Wscript.Quit 1
end if 

for each CMObj in CMObjs
if Left(CMObj.ClientVersion, 5) = "2.50." then
Wscript.Echo CMObj.ClientVersion
WScript.Quit 0
end if
next

Wscript.Quit 1


Скрипт после отработки возвращает 0 в случае если обнаружил клиента и все остальное в случае если клиент не найден.

Можно задействовать в скрипте удаления SMS 2003 клиента следующим образом:
cscript.exe CheckSMS2003Client.vbs
if "%ERRORLEVEL%"=="0" ccmclean.exe /q /client

ccmclean.exe входит в SMS 2003 Toolkit2, который можно скачать отсюда > http://www.microsoft.com/en-us/download/details.aspx?id=18153

Текст скрипта на pastebin > http://pastebin.ru/CATdNRhq

среда, 14 ноября 2012 г.

База SCCM 2012 на кластеризованном экземпляре SQL Server

При разворачивании базы SCCM 2012 на кластеризованном экземпляре, генерируется самоподписанный сертификат с отображаемым именем ConfigMgr SQL Server Identification Certificate. Сертификат генерируется на активном в момент установки узле кластера. На других узлах этого сертификата разумеется нет.
В итоге не работает failover экземпляра на узлы, отличные от изначально активного при установке.

В логах (ERRORLOG.x) имеем следующие сообщения об ошибках:
The server could not load the certificate it needs to initiate an ssl connection. It returned the following error: 0x8009030d. Check certificates to make sure they are valid
Error: 26014, Severity:16, State: 1
Unable to load user-specified certificate [Cert Hash(sha1) "certificate_hash"]. Ther server will not accept a connection. You should verify that th certificate ..........
<....>
Error: 17182, Severity: 16, State: 1
<....>
Error: 17182, Severity: 16, State: 1
<....>

Проблему можно решить следующим способом:
1) Экспортировать Self-Sign сертификат с первоначального узла и импортировать на остальные узлы кластера (с приватным ключом, конечно же).
2) Дать разрешение Full Control на приватный ключ для учетной записи из под которой запускается экземпляр кластера. Данное действие также проделывается на всех узлах этого экземпляра.

среда, 7 ноября 2012 г.

SCCM 2012: SSRS not detected as running

После установки роли Reporting Service Point в логах возникает следующая ошибка:

Reporting Services URL from Registry [http://server:80/ReportServer_ConfigMgr/ReportService2005.asmx]
Ther request failed with HTTP status 401: Unauthorized
(!) SRS not detected as running


Лог srsp.log на сайт-сервере.

Оказалось просто забыл обновить SQL Server Reporting Service (2008 R2) до SP2 (а вообще достаточно SP1+CU6).

вторник, 12 июня 2012 г.

Полностью виртуальная инфраструктура в Hyper-V.


Введение.

В этой небольшой статье хотелось бы рассказать про свой опыт использования виртуализации инфраструктуры на базе Hyper-V из состава Windows Server 2008 R2. Статья будет также применима и к Windows Server 2008 (R1). А если конкретно, то хотелось бы рассказать про проблему полной виртуализации инфраструктуры. Под полной виртуальной инфраструктурой я подразумеваю среду, где Hyper-V развернут в конфигурации Failover Cluster и все серверы, включая контроллеры доменов, виртуализируется.

Чтобы было более понятно, рассмотрим следующую инфраструктуру. Есть группа хостов с Windows Server 2008 R2. Вы из этих хостов собрали кластер и хотите перенести всю вашу серверную инфраструктуру из физического состояния в виртуальное. Но встает дилемма. Среди физических серверов, которые вы хотите перенести в среду виртуализации, есть контроллеры доменов. Тут вы вспоминаете, что кластер зависит от службы каталогов и получается, что вам нельзя создавать взаимозависимость: кластер виртуализации от службы каталогов и наоборот.

Вообще данная проблема не нова. Но я ни разу не встречал описание решения данной проблемы, поэтому все-таки надумал поделиться своим опытом (пока это не сделал кто-нибудь другой:)). Возможно данное решение уже где-то описано и просто-напросто я не правильно или невнимательно искал.

Решение.


Failover-кластеру без службы каталогов очень плохо. Хотя бы по той причине, что служба каталогов используется для аутентификации узлов в кластере.

Вернемся к нашей инфраструктуре. Мы все-таки развернули кластер Hyper-V, перенесли все серверы, в том числе и контроллеры доменов, в виртуальную среду. Физические серверы либо задействовали в качестве узлов кластера, либо полностью вывели из эксплуатации. Виртуальные машины разместили на Cluster Shared Volume (CSV), дабы задействовать замечательную функцию Live Migration. Получилось следующее:



В один прекрасный момент выключается электричество, а вместе с ним через некоторое время выключаются ваши физические хосты и виртуальные машины.

Включают электричество, хосты Hyper-V начинают грузиться, а вот виртуальные машины не стартуют. Это происходит по следующей причине. Виртуальные машины являются ресурсами кластера, служба ClusterSvc должна, в соответствии с зависимостью ресурсов, поочередно их поднять (перевести в online-режим). Но служба кластеров сама зависит от службы каталогов, контроллеры доменов которой являются ресурсами кластера. Получается замкнутый круг.

Есть традиционные способы решения данной проблемы:

Использовать хотя бы один физический сервер для контроллеров доменов. Согласитесь, что при текущей производительности серверов, не совсем целесообразно потратить на контроллер доменов 5-10 тыс. долларов (с последующей утилизацией раз в 3-5 лет). Для инфраструктур, характеризующих себя как централизованные и средние по размерам, хотелось бы максимально утилизировать вычислительные ресурсы, абстрагироваться от аппаратного обеспечения, и все это сделать с минимальными затратами. Децентрализованные инфраструктуры могут такой проблемы не ощущать.

Использовать хост Hyper-V как контроллер доменов. То есть, развертываем роль ADDS на одном из узлов Hyper-V. Это уже лучше, чем первый случай, но все же есть некоторые проблемы:

  • Проблема безопасности и проблема делегирования полномочий. Если развернуть RWDC на Hyper-V хосте, то трудно будет ограничить администратора среды виртуализации от возможности воздействовать на службу каталогов. Сразу скажу, что здесь можно долго спорить на эту тему, поскольку можно сказать, что если есть физический доступ к хосту, то без проблем можно получить доступ к виртуальным машинам. И это верно. Поэтому оставлю тему безопасности за рамками данной статьи. Возьмем за веру, что проблема с безопасностью все же есть в этом случае. Также можно установить RODC и это решит некоторые проблемы с безопасностью, но возникают другие проблемы.  Update: чуть позже накопал, что RODC не поддерживается на узлах кластера http://support.microsoft.com/kb/281662/en-us

  • Проблемы с решением и локализацией проблем. Если вы совмещаете несколько ролей, то не всегда можно быстро определить причину возникновения проблемы в такой системе, а значит и время решения проблемы увеличивается.

  • Проблема с лицензированием. Конечно, с лицензированием проблем здесь нет, но вот у вас проблемы появятся. Если хост Hyper-V выполняет какую-либо роль кроме виртуализации, то вы лишаетесь возможности в полной мере покрыть хостовой лицензией запущенные экземпляры виртуальных машин. Например, в случае с Standard-лицензией вообще лишаетесь возможности использовать хостовую лицензию для лицензирования одной запущенной виртуальной машины, а в случае с Enterprise - одной. То есть с Enterprise-лицензией можете лицензировать запуск не 4х виртуальных машин, а только трех. В оригинале это звучит так: 
* Если запущено максимально разрешенное количество экземпляров, экземпляр в физической операционной среде может использоваться только для запуска программного обеспечения виртуализации устройств, обеспечения служб виртуализации устройств или для запуска программного обеспечения для управления операционными средами и их обслуживания на лицензированном сервере.

А теперь, как я решал данную проблему.


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

Тем самым вы решаете проблему взаимозависимости. Теперь контроллеры доменов живут в виртуальных машинах и эти виртуальные машины не являются ресурсами кластера. При отключении электричества все прекрасно стартует.

Правда в этом случае мы привязываем контроллер домена к конкретному хосту и он (контроллер домена) не может быть перемещен на другой хост с помощью Quick Migration или Live Migration (хотя может быть перемещен другими способами). Но это не беда. Высокая доступность контроллеров доменов достигается совершенно другим способом – избыточностью. На необходимое количество контроллеров доменов могут повлиять многие факторы, здесь мы их обсуждать не будем.

Некоторые рекомендации (и даже требования):

  1. Создавайте виртуальные машины с контроллерами доменов на дисках, не являющихся кластерными ресурсами. Это могут быть как локальные диски (DAS), так и диски с СХД.
  2. Режим запуска виртуальных машин: Always Automatically Turn On The Virtual Machine или Automatically Turn On The Virtual Machine If It Was Running When The Physical Server Was Stopped
  3. Для службы кластеров (ClusterSvc) необходимо произвести настройки восстановления. Те, что на вкладке «Восстановление» свойств службы ClusterSvc оснастки Services.msc. Для всех сбоев необходимо указать перезапуск службы. Не могу сказать какие конкретно значения для «Перезапуск служб через:» вам подойдут, необходимо подбирать их индивидуально. Я использовал 3 минуты.
  4. Сократите интервал отображения меню восстановления. Настроить можно с помощью апплета «Система» панели управления.

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

Проблема №2.


Дело в том, что есть еще одна взаимозависимость: служба каталогов от DNS и DNS от службы каталогов.



Возникает она по следующей причине. Контроллер домена, при старте, пытается произвести репликацию своих контекстов именования (это при условии, что контроллер в лесу не один): пока не произведет репликацию, не будет выполнять свои функции. Служба DNS, желая при старте работать с самыми актуальными данными, откладывает загрузку интегрированных в AD зон, до момента, когда служба каталогов реплицирует данные и оповестит об этом службу DNS. Репликация AD, как известно, зависит от DNS: контроллер домена пытается получить IP-адреса своих партнеров по репликации с помощью DNS. А DNS в это время не работает, поскольку ждет AD. AD ждет DNS, DNS ждет AD. В свою очередь от DNS также зависит кластер и аутентификация. Через какое-то время служба каталогов все-таки даст добро службе DNS и та загрузит зоны. Этот timeout зависит от количества разделов, которые обслуживает контроллер доменов и примерно составляет 20 минут для 5 разделов (для контроллеров с 2008 R2 я наблюдал намного меньшую задержку – 5 минут).

20 минут для кого-то могут быть вполне допустимы, а для кого-то нет. Попробуем решить эту проблему.

Способы:

  1. Использовать в качестве DNS сервера сервер с другой площадки. Скорее всего, в этом случае у вас не должно возникнуть и первой проблемы. 
  2. Установить дополнительный физический сервер с ролью DNS. Этот сервер будет обслуживать вторичную зону для _msdcs корневого домена и доменную зону локального домена (главная задача разрешить DSAGUID партнера по репликации в FQDN и FQDN в IP-адрес) Этот способ конечно не подходит. Мы вернулись опять к проблеме с физическим сервером. В этом случае проще сразу развернуть физический контроллер доменов.
  3. Установить роль DNS на хосте Hyper-V? Можно, но получаем те же проблемы, что и обсуждались чуть выше.
  4. Отключить начальную репликацию. Это делается установкой значения Repl Perform Initial Synchronizations в 0 для ключа HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters. Можно, но не рекомендуется. Не рекомендуется хотя бы по той причине, что таким образом происходит попытка решить проблему с существованием в лесу (или домене) нескольких FSMO. Лучше такой способ не использовать.
  5. Использовать не интегрированные в AD зоны (полностью или частично). Знаете да, какие преимущества дает хранение зон в AD? Если вам эти преимущества не нужны, то можете использовать и этот способ.
  6. Сделать так, чтобы имя партнера по репликации разрешалось без участия DNS-сервера. Как это можно сделать? Способов много. Дополнительно стоит сказать, что, начиная с Windows Server 2003 SP1, появилась функция name resolution fallback, на тот случай если не удастся разрешить DSAGUID контроллера домена. Цепочка следующая: GUID -> FQDN -> NETBIOS-имя. То есть, если не удается разрешить CNAME GUID, то происходит попытка разрешить FQDN, если и это не удается сделать, то происходит попытка получить IP по NETBIOS-имени. Поэтому проблему можно решить:
  • Использованием HOSTS-файла. В хост файл можно внести запись о партнере по репликации. Можно добавить как GUID._msdcs.<имя_корневого_домена>, так и FQDN:
<IP-адрес партнера по репликации> <DSA GUID>._mcdcs.<имя корневого домена>
<IP-адрес партнера по репликации> <FQDN партнера по репликации

  • Использованием файла LMHOST. Внести в файл соответствующую запись NETBIOS.
  • Использованием WINS-сервера. Наверное, наиболее предпочтительный способ. 
  • Использованием NETBIOS-широковещания для разрешения имени. Если контроллеры доменов в одном широковещательном домене и Netbios-over-TCPIP не отключен (включен по умолчанию), то с проблемой №2 вы вообще не должны столкнуться.

Внося записи в файлы HOSTS и LMHOSTS, необходимо отдавать себе отчет в том, что такие изменения в скором времени вами забудутся, и, при возникновении проблем с разрешением имен, вы потратите дополнительное время на поиск причины. Поэтому тщательнейшим образом документируйте вносимые изменения. То же самое касается локального изменения реестра: лучше делать изменения централизовано, например, с использованием групповых политик, а иначе концов не сыщете.


Надеюсь, что представленные в этой статье рекомендации, помогут вам.


Полезные ссылки:

Как установить Hyper-V кластер: http://lmgtfy.com/?q=how+to+install+hyper-v+cluster

О первоначальной репликации: http://support.microsoft.com/kb/305476/en-us

О проблеме загрузки DNS-зон: http://support.microsoft.com/kb/2001093/en-us

LMHOSTS: http://support.microsoft.com/kb/101927/en-us