А виноват ли SCCM клиент?


Истории из серии «Почему Windows так медленно работает?» всегда поучительны. Поучительны не только в техническом смысле, но и в социальном.

Любой системный администратор, имеющий за плечами несколько лет опыта, расскажет о пользователях «параноиках», превращающих любую мизерную проблему в глобальную катастрофу, и пользователях абсолютных «флегматиков», которые могут работать в практически разрушенной системе месяцами, но так и не обратятся за помощью.

И те, и другие это «плохие» пользователи. Плохие в том смысле, что если проблема действительно существует, то сообщение от первых могут проигнорировать, а сообщение от вторых никогда не поступит.

Это была присказка :-) Сказака впереди.

После новогодних прадников решили обновить SCCM. Обновили сервер, всё проверили, всё работает. Выдержали паузу и приступили к обновлению клиентов SCCM на компьютерах пользователей. Раскатали новый клиент на тестовую группу — всё работает. Расширили тестовую группу — всё работает. Наконец запустили установку на всех. SCCM автоматически обновляет клиенты очень неспешно. Проходит несколько дней, обновлено уже несколько сотен клиентов, и тут тех. поддержка говорит: «А у пользователей компы тормозят жутко после установки нового клиента.»

Начинаем разбираться. Оказывается не у всех. Тем не менее один проблемный компьютер, второй, третий … Это уже опасно, если учесть «флегматиков». Остановили процесс обновления до выяснения масштабов проблемы и её серьезности.

Пока ковыряли эти три проблемных компьютера, а дело это очень медленное, так как делать это приходится удаленно, а загрузка ЦПУ 100%, и любая операция занимает десятки минут. Так вот пока разбирались с этими тремя, обнаружилось ещё две проблемные системы. Это вызывало нехорошие мысли: при пересчёте процента проблемных компьютеров на несколько тысяч систем, получалось слишком большое число, чтобы можно было просто игнорировать эту проблему — стало ясно, что придется докопаться до истинных причин проблемы и найти лекарство, желательно применимое автоматически и удаленно.

Постепенно накопили определённый опыт. Процесс SCCM клиента — 100% ЦПУ, процесс WMI — 100% ЦПУ. Если их остановить, то пользователь уже мог работать за компьютером. Это облегчило накал страстей, и дало нам время на дальнейшее изучение проблемы.

Перечитали и перепробовали всё, что нашли по проблеме 100% ЦПУ у клиента SCCM и процесса WMI. Ничего не помогло. Запустили восстановление системы — sfc, dism, даже sfcfix. Проблема не решена. Более того восстановление системы даже подвисает.

Тут вспомнилась знаменитая фраза из кинофильма «Иван Васильевич меняет профессию» — «Меня терзают смутные сомнения…». До сего момента мы следовали классическому подходу: что мы такое делали, что могло вызвать проблему? Очевидно это была установка новой версии клиента SCCM. Загрузка его процесса в 100% и множество событий с ошибкми по таймауту в логах WMI, казалось бы, на 100% подтверждали эту теорию. Но если процедура восстановления системы виснет, то это вызывает другие мысли: а может клиент SCCM тут совсем не при чём?

Требовалось удаленно посмотреть, как себя ведут другие процессы на проблемных компьютерах. В логах мы и до этого ничего криминального не видели, а вот что с загрузкой ЦПУ?

Помог PowerShell. Вот запрос, который показывает наиболее нагруженные процессы (CPU > 80%) на удаленном компьютере:

(Get-Counter '\\Computer\Process(*)\% Processor Time').CounterSamples | Where-Object { $_.CookedValue -gt 80 }

И что же мы увидели на проблемных компьютерах? Ещё два процесса с загрузкой 100% ЦПУ — svchost (связанный с Windows Update) и logonui.

Это уже явно говорило о том, что надо исследовать другую теорию — SCCM клиент не является причиной проблемы, но установка новой версии SCCM клиента проявляет уже существующую проблему. Если на компьютере есть 4 логических процессора, и два из них полностью заняты процессами svchost и logonui, то пользователь использует остальные два. Возможно он чувствует, что компьютер притормаживает, но это терпимо и работать можно. После установки новой версии клиента SCCM появляются ещё два процесса с загрузкой 100% двух оставшихся ядер. И вот тут пользователю уже ничего не осталось — компьютер тормозит так, что ничего делать невозможно.

Чтобы копнуть глубже в поисках причин проблемы, пришлось воспользоваться утилитой wpr.exe (Windows Performance Recorder). Ранее эта утилита была только в Windows Performance Toolkit (который входит в состав Windows Assessment and Deployment Kit). Это нужно установить для анализа трассировки, но wpr.exe теперь есть штатно в Windows 10. Запускаем получаем трассировку, смотрим анализ в wpa.exe.

wpr -start CPU -start DiskIO -start FileIO

wpr -stop c:\1\gdstp18-1.etl

Для всех проблемных процессов трассировка сходится в одну точку. Это наводит на мысль, что мы на правильном пути — проблема одна, и мы можем её локализовать: либо это какая-то DLL, либо какая-то структура данных (база или реестр).

И тут срабатывает двигатель прогресса — человеческая лень: если мы уже знаем признак, по которому мы можем найти проблемный компьютер до установки новой версии SCCM клиента, то стоит ли нам тратить время на дальнейшие копания в недрах Windows? Тем более что потом нам придется ещё искать способ лечения проблемы.

Идея в том, чтобы просканировать компьютеры и посчитать, сколько из них проблемных. Если мало, то нет смысла тратить время на поиск лекарства (если только из спортивного интереса), а просто переставить системы.

По сути нам надо посмотреть на всех компьютерах загрузку процесса logonui: если близко к 100%, то компьютер проблемный. Сканирование тысяч компьютеров последовательно может занять неделю времени. Тут нам помог PowerShell 7.1 и его новая возможность «Foreach-Object -Parallel», которая позволяет запускать скрипт параллельно. (В Windows PowerShell нам пришлось бы использовать стронний модуль или WorkFlow, что нетривиально.)

$a = Get-ADComputer -Properties OperatingSystem -Filter "OperatingSystem -like 'Windows 10*'"
$b = $a | ForEach-Object -Parallel { $_ | ? {Test-Connection -ComputerName ($_.Name) -Count 1 -Quiet } } -ThrottleLimit 20
$c = $b | ForEach-Object -Parallel { $_ | % { (Get-Counter "\\$($_.Name)\Process(logonui)\% Processor Time" -ErrorAction SilentlyContinue).CounterSamples | Where-Object {$_.CookedValue -gt 80} } } -ThrottleLimit 20
$c.count

Процент проблемных компьютеров на выборке оказался столь мизирным, что в пересчёте на общее количество компьютеров ожидаемое число проблемных компьютеров составило менее 15.

Примечание 1. Вычисление процента нужно было, потому что часть компьютеров выключена из-за того, что пользователи работают удаленно. В этом случае мы сможем выявить проблемный компьютер только после его включения, а это может произойти не скоро.

Примечание 2. Приведённый скрипт игнорирует ошибки. Но они могут быть полезными. Например, ошибка таймаута может говорить о том, что целевой компьютер слишком загружен, и нам стоит изучить его внимательнее. Поэтому пришлось сделать более навороченную версию скрипта, которая выводит все полезные ошибки. Этот скрипт не привожу, так как он не нашёл ни одного нового проблемного компьютера.

Вывод был однозначный: смысла искать лекарство нет, несколько выявленных проблемных компьютеров немедленно отправить на переустановку, как и те несколько, которые будут выявлены в будущем, установку новых клиентов SCCM продолжить немедленно.

Какой урок из этой истории? У меня какое-то двойственное чувство. На современных платформах процессоры имеют много ядер, и если появляется один, два «бешенных» процесса, то может ли обычный пользователь (который не «параноик» и не «флегматик») объективно почувствовать это и обратиться в тех. поддержку? У меня сомнения (помню ещё одну похожую историю, но другой природы). Если пользователь нам тут не помощник, то как нам выявлять подобные проблемы? Собирать все счетчики производительности это не вариант: системы будет сильно тормозить, а объемы данных даже для небольшой компании будут составлять терабайты в неделю, а их ещё анализировать надо. С другой стороны подобные проблемы возникают не так часто, чтобы изобретать средства непрерывного контроля. Наверное самое оптимальное просто внимательней относится к коллегам: что они делают, как, какие проблемы испытывают. Общаясь с ними в таком ключе, неизбежно посмотришь состояние их системы, приложений, оборудования. И безусловно обнаружишь то, что пользователь не в состоянии обнаружить и/или осознать и тем более исправить. Останется только распространить полученный опыт на других при необходимости: настроить политики, запустить скрипты или сделать простую рассылку по почте с разъяснениями.

Ещё один опыт эксплуатации терминальной фермы


Популярность удаленного доступа растет как и нашей локальной терминальной фермы.

Первая неделя эксплуатации выявила некоторые странности в поведении терминальных серверов: иногда они аварийно перегружались, иногда были недоступны по RDP, несмотря на присутствие пинга.

Так как обрудование серверов было новым, то первое подозрение касалось драйверов. Взяли последние доступные версии драйверов и тотально обновили все системы. После чего продолжили наблюдение. Первое впечатление было положительное, но спустя несколько дней мы поняли, что пользователи всё-таки испытывают трудности.

Неприятность ситуации заключалась в том, что вроде всё работает, но как-то слегка не так: то утром обнаруживаешь, что сервер ночью перезагрузился, то пользователь пожалуется, что его сессия прерывается, и непонятно то ли у него проблема с каналом или с оборудованим, то ли всё же с фермой. Это самая неприятная ситуация при эксплуатации систем. Гораздо проще, когда если уж не работает, то конкретно не работает, и чинить надо явно видимую проблему или проблемы.

После недели наблюдений пришло понимание, что проблема всё-таки где-то с фермой. Как раз повод установить очередное ежемесячное кумулятивное обновление. Два часа от ночного сна и готово!

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

Однако многолетный опыт сказался, и довольно быстро ниточка привела на вот это обсуждение. Стоило открыть оснастку фаервола, как стало понятно, что у нас эта проблема присутствует, хотя у нас версия 2019, а статья о версии 2016. Неужели до сих пор нет решения?! Оказалось, что надо следовать старому правилу и читать с конца :-) — последний пост в обсуждении содержал ссылку на исправление, а именно на последнее кумулятивное обновление для Windows Server 2019, которое мы только что установили. Можно сказать, что нам повезло.

KB4549949

Addresses an issue that slows server performance or causes the server to stop responding because of numerous Windows firewall rules. To enable this solution, use regedit to modify the following and set it to 1:
Type: “DeleteUserAppContainersOnLogoff” (DWORD)
Path: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy

Почистили системы от дубликатов правил в фаерволе, сделали политику для распространения ключа реестра. Системы стали работать веселее. (Мы поняли, что в нашем случае проблема маскировалась из-за того, что у нас слишком мощные серверы с 72 ядрами.)

Обратите внимание, что скрипты из упомянутого обсуждения работают, но содержат проблему: два раза вычисляется Compare-Object. Поэтому перед запуском исправьте это (запишите результат первой команды в переменную и используйте её вместо второй команды).

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

UsoClient — замена wuauclt


Windows 10 оказалась очень практичной системой. За несколько лет эксплуатации в корпоративной среде мы не имели с ней проблем. И расслабились :-) — как-то разом застряли кумулятивные обновления на всех системах.

По всей видимости через WSUS приехало некачественное обновление и попортило образы систем. В CBS.log на разных компьютерах ошибки на разные компоненты. Будто это не детерминированные компьютеры, а последствия взрыва гранаты — где как пришлось.

Попробовали вылечить несколько систем вручную с помощью sfc и dism. Несколько ошибок они исправили, но не все. Победить проблему удалось только утилитой SFCFix. Но это же не вариант лечить вручную сотни компьютеров, да ещё сторонней утилитой!

Открыли системам доступ в Интернет на сайты Windows Update. Dism сразу стал инициировать загрузку каких-то компонентов, но до конца всё так и не вылечил.

К счастью оказалось, что последние обновления всё-таки ставятся и проблема лечится автоматически: загрузка последних обновлений, пара установок с аварийным завершением (при этом в CBS.log видно исправление ошибок образа системы!) и перезагрузкой — и всё работает. (Иногда правда перезагрузка может зависать надолго на некоторых системах, но это терпимо.)

Попутно выяснилось, что привычная wuauclt утилита не работает. К тому же её можно было запускать только локально.

Если на Windows XP и Windows 7 приходилось из-за ограничений Windows Update клиента прибегать к некоторым ухищрениям, чтобы удаленно инициировать установку обновлений, то на Windows 10 было приятно открыть для себя утилиту UsoClient, которая работает через удаленное подключение PowerShell или PSExec.

С помощью неё можно не только иницировать поиск обновлений, но и их загрузку, установку и перезагрузку системы.

Список параметров от доброго человека:

  • StartScan Used To Start Scan
  • StartDownload Used to Start Download of Patches
  • StartInstall Used to Install Downloaded Patches
  • RefreshSettings Refresh Settings if any changes were made
  • StartInteractiveScan May ask for user input and/or open dialogues to show progress or report errors
  • RestartDevice Restart device to finish installation of updates
  • ScanInstallWait Combined Scan Download Install
  • ResumeUpdate Resume Update Installation On Boot