Казалось бы, для такого совершенно стандартного желания и решение должно быть совершенно стандартным, особенно уж для такой неновой и распространённой штуки, как общие папки Windows: поставь такую-то фичу, и щёлкни раз-два-три. Ага, щас!
Вариант 1 - shared storage
Но увы! наше облачко такое не предоставляет.
Вариант 2 - репликация
Пускай у каждой из виртуалок будет свой местный диск, а мы будем файлы между ними синхронизировать.
В набор Windows Server для таких дел входит DFS Replication (DFS-R).
- фича входит в стандартный набор в Windows Server, ей сто лет в обед.
- главный - никаких гарантий по части целостности данных. Один клиент может изменять файл на одном сервере, а другой в то же - тот же файл на другом сервере, и пожалуйста: конфликт;
- если файл залочен клиентом, то изменения в нём копироваться не будут, пока клиент замок не снимет; пример - логи. Стало быть, его чтение с другого сервера реальное содержание не покажет;
- очень непрозрачный и недокументированный способ работы. Пример: если файлы синхронизуются более-менее сразу, то вот изменения в NTFS permissions или ownership - со здоровенной задержкой, могущей доходить минут до 20. В чём логика, догадываюсь - такое изменение может переписать ACLs сверху вних по здоровеннейшему дереву, так что лучше подождать, пока юзер закончит их вносить, и лишь затем реплицировать. Но вот не документировано это нигде. В случае накладок, десинхронизации, конфликтов понять, что именно пошло не так, очень тяжело.
Схожий по функциям софт от прочих производителей я не пробовал, но наверняка и у них те же ограничения.
- \\server1.example.org\SharedFolder
- \\server2.example.org\SharedFolder
Фича полезная, но failover достаточно медленный - если сервер вдруг пропадает с горизонта, то клиент сперва пытается посылать пакеты по существующему TCP-соединению, затем - открыть новые на тот же сервер, и лишь затем - пойти на следующий сервер по списку, полученному от DFS namespace. Уходит на это секунд 80.
Ещё возможность: просто определить DNS-имя, указывающее на IP-адреса обоих серверов - к примеру:
Недостаток - не будет работать протокол аутентификации Kerberos, поскольку SMB-служба на каждом сервере привязана к его личному computer account в Active Directory, а аккаунт - к его личному хостнейму. Привязать же общий хостнейм к обоим аккаунтам нельзя. Можно ли запустить SMB-службу не под локальным аккаунтом (SYSTEM), а под доменным - обычным юзерским или gMSA? Не знаю, не пробовал.
Впрочем, всегда есть в запасе старый добрый NTLM.
Ещё возможность: просто определить DNS-имя, указывающее на IP-адреса обоих серверов - к примеру:
- filer.example.org = 192.168.10.100
- filer.example.org = 192.168.20.100
Недостаток - не будет работать протокол аутентификации Kerberos, поскольку SMB-служба на каждом сервере привязана к его личному computer account в Active Directory, а аккаунт - к его личному хостнейму. Привязать же общий хостнейм к обоим аккаунтам нельзя. Можно ли запустить SMB-службу не под локальным аккаунтом (SYSTEM), а под доменным - обычным юзерским или gMSA? Не знаю, не пробовал.
Впрочем, всегда есть в запасе старый добрый NTLM.
Вариант 3 - виртуальный shared storage
Если облако не предоставляет shared storage, давайте построим его сами!
Тут, конечно, напрашивается воткнуть ещё одну виртуалку, которая будет предоставлять диски для наших файлсерверов по протоколу iSCSI - и тогда мы можем построить красивенький Failover Cluster и радоваться. Но это будет, естественно, самообман, потому как тогда наш iSCSI-сервер станет единой точкой отказа - если он рухнет, то всему хана.
Стало быть, надо подымать не одну виртуалку, а пару-тройку и реплицировать между ними на сей раз не файлы, а блоки. Что сразу же сильно усложняет систему: нам-то хотелось всего-навсего, чтобы пара Windows-машинок подменяла друг друга в случае чего, а тут приходится сооружать целый зоопарк.
Можно попытаться функции совместить: а пускай наши файлсервера заодно и работают как virtual SAN - синхронизируют между собой некий виртуальный диск и к нему же и подключаются как iSCSI-клиенты (то, что называется модным словом hyper-converged).
Но:
1. Windows S2D - первый кандидат, поскольку готовая фича в Windows Server 2016. Очень хотелочь бы опробовать, но увы. У неё суровые требования к локальным дискам, которые без хаканья на уровне VMware обойти нельзя. А облачко подобных игр не позволяет.
2. StarWind vSAN - привлёк внимание тем, что написан для Windows и интересной бизнес-моделью: разница между платной и бесплатной версиями лишь в отсутствии в бесплатном варианте техподдержки и графической консоли - управление идёт через PowerShell. Освоить ихний PowerShell совсем несложно, но:
В конце остановился на совмещении вариантов 1 и 2: дублировать файлы с помощью DFS Replication, но при этом использовать плавающий адрес Failover Cluster для доступа к ним.
Иными словами, если у нас есть \\server1.example.org и \\server2.example.org, то для доступа к файлам мы будем использовать некое третье имя - скажем, \\filer.example.org - и оно будет привязано к кластерному IP-адресу, переходящему от одного сервера к другому в случае падения. Или же IP-адресам, в случае если наши сервера сидят в разных сетях.
Строится это следующим образом:
Перенос кластерного IP - очень быстрая операция, прозрачная для клиента: сервер, забирающий его к себе, отсылает ряд пакетов Gratuitous ARP (GARP), прописывающих новый MAC-адрес для этого IP в ARP-таблице подключённых к той же сети раутеров или клиентов. Заодно и свитчи, физические или виртуальные, прописывают у себя, на каком порту сидит этот MAC. Всё, трафик продолжает течь как тёк.
Можно попытаться функции совместить: а пускай наши файлсервера заодно и работают как virtual SAN - синхронизируют между собой некий виртуальный диск и к нему же и подключаются как iSCSI-клиенты (то, что называется модным словом hyper-converged).
Но:
- это повышает риск - надо полагаться на то, что при поломке, падении, перезагрузке не только Failover Cluster отработает как надо, но и virtual SAN.
- вариантов virtual SAN очень много, но большинство из них под Линукс. Стало быть, на наши виртуалочки их не воткнёшь.
- вероятно, что количество виртуалок всё равно придётся повышать до трёх, чтобы избежать возможности split brain.
1. Windows S2D - первый кандидат, поскольку готовая фича в Windows Server 2016. Очень хотелочь бы опробовать, но увы. У неё суровые требования к локальным дискам, которые без хаканья на уровне VMware обойти нельзя. А облачко подобных игр не позволяет.
2. StarWind vSAN - привлёк внимание тем, что написан для Windows и интересной бизнес-моделью: разница между платной и бесплатной версиями лишь в отсутствии в бесплатном варианте техподдержки и графической консоли - управление идёт через PowerShell. Освоить ихний PowerShell совсем несложно, но:
- требует он скрупулёзной внимательности и аккуратности, особенно если создаёшь много дисков; цена опечатки может быть слишком высока.
- увы, багов слишком много. Диски могут рассинхронизироваться навсегда от простой перезагрузки; одни и те же команды могут выполняться раз выполняться, а раз - выдавать совершенно невразумительные ошибки; траблшутить всё это одному - не легче, чем DFS, а то и тяжелее. И привести эти баги могут к очень тяжёлым последствиям.
Конечный вариант - слоноптица
В конце остановился на совмещении вариантов 1 и 2: дублировать файлы с помощью DFS Replication, но при этом использовать плавающий адрес Failover Cluster для доступа к ним.
Иными словами, если у нас есть \\server1.example.org и \\server2.example.org, то для доступа к файлам мы будем использовать некое третье имя - скажем, \\filer.example.org - и оно будет привязано к кластерному IP-адресу, переходящему от одного сервера к другому в случае падения. Или же IP-адресам, в случае если наши сервера сидят в разных сетях.
Строится это следующим образом:
- Определяем DFS-R между двумя машинами.
- Добавляем обе в Failover Cluster. Поскольку shared storage у нас нету, используем какой-нибудь удалённый shared folder как quorum witness - или Azure как cloud witness.
- Создаём в кластере empty role, даём этой роли некое имя, привязываем к IP-адресу, прописываем в DNS. Computer account в Active Directory для этой роли не создаётся - незачем.
- Определяем на каждой машине те же shared folders на основе дерева, синхронизируемого посредством DFS-R.
- все клиенты юзают тот же сервер, который будет предоставлять замок на запись в конкретный файл лишь одному из них. Чтение изменений в файле доступны всем сразу.
- соответственно, нет конфликтов между серверами, все изменения идут в одном направлении.
- очень быстрый graceful failover, если оба сервера в той же сети (не graceful - не очень). См. ниже.
Но стоит учитывать:
- мы лишаемся возможности распределять нагрузку между серверами (нам это особенно и не нужно - она и так мала).
- если файл был открыт на запись, были внесены изменения, записаны на диск, но сервер рухнул перед тем, как замок был снят - значит, реплицированы эти изменения не были. Если рухнувший сервер подымется перед тем, как тот же файл был изменён на втором - репликация произойдёт. Если после - то реплицирована будет версия файла со второго сервера, поскольку у неё будет метка времени посвежее.
Дополнения и уточнения
Свидетель из Фрязино
Тонкий момент - если мы просто подымем два сервера в рамках Failover Cluster и будем ждать, что они будут друг друга взаимно подстраховывать, нас ждёт облом. В тот момент, что один из них отключится, роль файлсервера остановится так же и на втором, прекратит работать наш кластер.
Почему? Для избежания неприятной ситуации под названием "split brain", когда оба сервера считают себя главными и могут, в отсутствии координации друг с другом, искорёжить данные.
Как этого избежать? Есть два варианта:
- Добавить третий сервер в кластер - и заодно в replication group DFS-R, чтобы копия файлов была на всех трёх.
- Добавить так называемого "свидетеля" (witness).
Свидетель этот является не процессом, как сервер, а просто-напросто неким "журналом", куда оба сервера могут писать, отмечаясь, что они живы и указывая, кто из них в активной роли.
- Если сервер обнаруживает, что не слышит второй, но "свидетель" доступен - он продолжает работать.
- Если он обнаруживает, что не может связаться ни со вторым, ни со "свидетелем" - он останавливается.
- Если оба сервера общаются нормально, но "свидетель" отвалился - они продолжают работать как обычно.
В Windows 2016 есть три варианта для witness:
- Либо это shared disk, общий для всех узлов кластера - но мы начали с того, что наше облако таких не предоставляет. Если предоставляет - нам не нужна эта морока с DFS-R, стоит выстроить просто обычный Failover Cluster по рецептам Microsoft.
- Либо эта shared folder на каком-то третьем SMB-сервере - но тогда надо иметь этот сервер. Его не надо подключать в кластер, достаточно, чтобы он был доступен с обоих кластерных узлов. Это может быть контроллер домена, к примеру.
- Либо (новая фишка Win2016) это может быть blob в микрософтовском облаке - в Azure storage account. Но тогда надо располагать подпиской на Azure.
Немного технических потрохов про failover:
Скорость переключения очень зависит от того, происходит ли оно в результате того, что бывший активный сервер сам сдаёт полномочия (graceful failover - по команде админа или из-за "мягкой" перезагрузки) - или же в результате резкого падения сервера или полной потери связи с ним. Если graceful может занять до 5 секунд, то hard failover - до 20-ти. Разница происходит от того, что оставшемуся серверу надо во втором случае установить, что ранее активный признаков жизни не подаёт - ни напрямую, не через witness (см. ниже) - а в первом тот может сообщить и сам.
После того, как второй сервер решает тянуть одеяло на себя, события могут развиваться по следующим сценариям:
Внутри одной сети (VLAN, subnet):
Естественно, TCP-подключения при этом слетят - поскольку новый сервер вдруг получит какие-то TCP-пакеты без SYN-флага. Но поскольку при этом он отошлёт RST, клиент возобновит их сразу же, без попыток повторных передач.
Между разными сетями:
Естественно, перекинуть floating IP из сети в сеть нельзя, да и незачем. Решается эта задача вот как. Наш Failover Cluster в курсе о существовании двух сетей - по каждой на сервер. Мы можем привязать нашу кластерную "роль" к двум IP-адресам - по одному на сеть - и прописать между ними "OR dependancy". Иными словами, для того, чтобы "роль" запустилась на хосте, достаточно, чтобы один из этих адресов был доступен.
Затем мы прописываем оба адреса в DNS на одно и то же имя - к примеру:
- filer.example.org = 192.168.10.100
- filer.example.org = 192.168.20.100
SMB-клиенты при запросе получают из DNS оба адреса и пытаются параллельно подключиться на оба. Лишь один из них ответит (в этом разница со случаем, если бы мы просто приписали к этому имени частные IP-адреса server1 и server2, о чём см. выше).
Если посреди работы с одним из адресов он перестаёт отвечать - Windows пытается в течении 15 секунд повторять (retransmit) запрос на уровне того же TCP-соединения - а затем посылает RST и снова пытается подключиться на оба одновременно. И если наш Failover Cluster отработал как положено - то соединение на второй адрес будет установлено благополучно.
В обоих вариантах, ещё пара секунд уйдёт на аутентификацию клиента против нового сервера - по Kerberos или NTLM.
Какой вариант быстрее? Это, как сказано выше, зависит от того, насколько быстро передадут друг другу роль наши сервера.
В случае graceful failover - переключить IP-адреса между двумя MAC-адресами в той же сети берёт намного меньше времени, чем дождаться, пока SMB-клиент начнёт стучаться по запасному адресу.
В случае же hard failover - наибольшую задержку обеспечит сам кластер.
Но и даже в наихудшем случае оба варианта всё же куда быстрее, чем переключение между двумя UNC-путями, полученными от DFS-N.
Ещё свидетель. Но совсем другой. И сугубо опциональный.
Есть некий способ сократить время, которое SMB-клиент тратит на переподключение. Идея в следующем: подключившись к кластеру по floating IP, клиент получает адреса всех узлов кластера. Затем он устанавливает соединение на один из неактивных узлов, и просит тот сообщить ему по дружески, если активный вдруг отвалится - предполагается, что узлы кластера узнают об этом событии раньше, чем клиенты. Если клиент получит такую подсказку - то начнёт переподключение немедленно, не ожидая, пока существующее TCP-соединение вылетит по таймауту.
Называется этот узел-подсказчик опять таки witness - и он, хотя имеет прямое отношение к Failover Cluster и к shared folders, не имеет ничего общего со "свидетелем" для координации кластера, о котором рассказано выше. Спасибо Микрософту за этот гнусный бардак в терминологии.
Несмотря на то, что звучит эта идея интересно, у себя я это включать большого смысла не вижу, и вот почему:
Впрочем, насколько я понимаю, придуман witness protocol не столько для кластерного файлсервера общего назначения, о котором этот пост, сколько для Scale-Out File Server. А в рамках Scale-Out не существует floating IP - соединения устанавливаются на адреса самих серверов. В этом случае заранее знать, что такой-то адрес отвалился и стучаться к нему незачем, действительно имеет большой смысл. Впрочем, Scale-Out я тут не рассматриваю.
Есть некий способ сократить время, которое SMB-клиент тратит на переподключение. Идея в следующем: подключившись к кластеру по floating IP, клиент получает адреса всех узлов кластера. Затем он устанавливает соединение на один из неактивных узлов, и просит тот сообщить ему по дружески, если активный вдруг отвалится - предполагается, что узлы кластера узнают об этом событии раньше, чем клиенты. Если клиент получит такую подсказку - то начнёт переподключение немедленно, не ожидая, пока существующее TCP-соединение вылетит по таймауту.
Называется этот узел-подсказчик опять таки witness - и он, хотя имеет прямое отношение к Failover Cluster и к shared folders, не имеет ничего общего со "свидетелем" для координации кластера, о котором рассказано выше. Спасибо Микрософту за этот гнусный бардак в терминологии.
Несмотря на то, что звучит эта идея интересно, у себя я это включать большого смысла не вижу, и вот почему:
- в случае переключения между узлами кластера в той же сети IP-адрес остаётся тем же, и клиент будет пытаться переподключиться на него же. Если новый активный узел этот адрес ещё не подобрал - неважно, продолжает ли клиент стучаться по тому же TCP-соединению, или пытается установить новое, один чёрт он в ответ ничего не получит. Если же подобрал - то на попытку retransmission по старому соединению он моментально ответит сегментом RST, после чего клиент тут же откроет новое.
- В случае hard failover между узлами в разных сетях, новому активному узлу возьмёт даже больше времени принять на себя роль, чем клиенту - переподключиться по запасному адресу.
- SMB на адрес fileserver role
- RPС на адрес fileserver role + адреса серверов
Впрочем, насколько я понимаю, придуман witness protocol не столько для кластерного файлсервера общего назначения, о котором этот пост, сколько для Scale-Out File Server. А в рамках Scale-Out не существует floating IP - соединения устанавливаются на адреса самих серверов. В этом случае заранее знать, что такой-то адрес отвалился и стучаться к нему незачем, действительно имеет большой смысл. Впрочем, Scale-Out я тут не рассматриваю.
No comments:
Post a Comment