четверг, 5 ноября 2015 г.

Имя хоста

Имена бывают трех типов:

  • статическое (static) — то, которое задает пользователь, хранится в /etc/hostname;
  • временное (transient) — имя,  полученное посредством DHCP или mDNS, если статическое имя установлено и оно отлично от localhost, то будет использоваться статическое имя;
  • прелестное (pretty) — имя, которое можно использовать для описания хоста, к примеру «Super duper server», хранится в /etc/machine-info. Может быть полезно, когда имена машин однотипны. Больше всего умиляет, что названия как в физике, типа «прелестный кварк».

Статическое и временное имена должны состоять из символов: a-z, A-Z, 0-9, дефиса, подчеркивания и точки, длина не должна превышать 64 символа.
Посмотреть текущие имена можно следующим образом:

$ hostnamectl status

Установить все имена сразу можно командой:

# hostnamectl set-hostname имя

Если нужно изменить определенное имя, то нужно добавить --pretty, --static или --transient, к примеру:

# hostnamectl set-hostname "Super duper server" --pretty

Заметки о RHEL7



Друзья/коллеги/читатели, пишу ряд статей об использовании RHEL7. Я сознательно не рассматриваю абсолютно все возможные пути конфигурирования или выполнения базовых операций. К примеру, в статьях точно не будут рассмотрены варианты конфигурирования с помощью графической оболочки NetworkManager. Источники данных, в большинстве своем, официальные документы с сайта вендора.
Ниже будут ссылки на статьи для удобства.

Имя хоста
Имя сетевого устройства

пятница, 10 июля 2015 г.

Балансировщик трафика для Exchange 2013

Продолжим рассматривать балансировку, отказоустойчивость и масштабирование приложений. Поскольку используется все тот же keepalived вместе с ipvs, то я не буду расписывать все подробно и рекомендую обратится к предыдущим статьям 1 и 2.
Цель задачи состоит в замене Windows Network Load Balancing(WNLB) для балансировки соединений к Exchange. Почему не устраивает WNLB?
  1. Не отслеживает доступность сервиса.
  2. Не обеспечивает равномерную балансировку
  3. Повышенная нагрузка на сетевую инфраструктуру
  4. Работает не устойчиво при нагрузке на сервера Exchange.
IP адреса нод кластера балансировки пусть будут 192.168.3.10 и 192.168.3.11. Для минимизации изменений в существующей инфраструктуре наш балансир должен иметь IP ранее принадлежащий WNLB (192.168.3.110). Следовательно, чтобы соединение прошло от клиента к кластеру Exchange (четыре сервера 192.168.3.111 - 192.168.3.114), необходимо осуществить трансляцию адреса назначения - Destination NAT. А чтобы ответные пакеты от Exchange серверов не ушли напрямую к клиенту, нужен Source NAT. Последняя ремарка: в отличие от уже упомянутых статей - это исключительно выделенный кластер для балансировки, который состоит из двух серверов (активный и резервный), в моем случае ОС это OEL6 с ядром UEK R2, это важно, поскольку более старое ядро не позволит реализовать задуманное, т.е. ядро из rhel6 не подойдет.

Итак, конфигурационный файл keepalived:

! Configuration File for keepalived

global_defs {
   notification_email {
      unix_adm@domain.ru
   }
   notification_email_from exchange_balancer01.domain.ru
   smtp_server 192.168.3.1
   smtp_connect_timeout 30
   router_id exchange_balancer01.domain.ru
}

vrrp_instance exchange_relay {
    state MASTER
    interface eth0
    virtual_router_id 117
    priority 100
    lvs_sync_daemon_interface eth0
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass mrelay
    }
    virtual_ipaddress {
        192.168.3.110
    }
    preempt
    notify_master "/etc/keepalived/snat.py -a 192.168.3.111 -a 192.168.3.112 -a 192.168.3.113 -a 192.168.3.114 -s 192.168.3.110"
    notify_backup "/etc/keepalived/snat.py -r 192.168.3.111 -r 192.168.3.112 -r 192.168.3.113 -r 192.168.3.114 -s 192.168.3.110"
    notify_fault "/etc/keepalived/snat.py -r 192.168.3.111 -r 192.168.3.112 -r 192.168.3.113 -r 192.168.3.114 -s 192.168.3.110"
}

virtual_server 192.168.3.110 443 {
    delay_loop 20
    lb_algo wlc
    lb_kind NAT
    protocol TCP

    real_server 192.168.3.111 443 {
        weight 1
          MISC_CHECK {
            misc_path "/etc/keepalived/check_exchange.sh 192.168.3.111"
            misc_timeout 18
          }
        }
    
    #Идентичные описания Exchange серверов
}

Что здесь нового:
  • lvs_sync_daemon_interface eth0 - На резервную ноду передается информация об открытых соединениях. Это позволяет оставить рабочими все текущие соединения в случае выхода из строя master ноды. Проверить работоспособность механизма передачи  на резервной ноде можно путем просмотра состояния текущих соединений:
         # ipvsadm -Lnc
  • Скрипт snat.py - в отличие от предыдущих статей, скрипт добавляет правила iptables на активную ноду, чтобы реализовать SNAT, соответственно он же убирает правила на резервной ноде. Правила в виде:
        -A POSTROUTING -d 192.168.3.111/32 -p tcp -j SNAT --to-source 192.168.3.110
  •  lb_kind NAT - Метод передачи пакетов, DNAT.
Чуть подробнее взглянем на скрипт проверки доступности приложения - check_exchange.sh.

#!/bin/sh

error=0
for i in `seq 1 3`
  do
    echo "GET /rpc/healthcheck.htm" | openssl s_client -connect $1:443 -crlf -quiet 2>/dev/null | grep "200 OK" || let error=$error+1
  done
[ $error -lt 3 ] && exit 0 || exit 1

Производится запрос состояния Exchange 2013 Outlook Anywhere путем обращения к странице https://exchange_server/rpc/healthcheck.htm. Если страница содержит 200 OK - состояние рабочее. Скрипт запрашивает три раза, и если хотя бы одна проверка верная, считается что сервис функционирует штатно. Почему так? Сервера exchange, в моем случае, работают под нагрузкой и не всегда успевают выдать страницу проверки. Если есть желание, можете дополнить скрипт на проверку других служб:

owa - Exchange 2013 Outlook Web App
ews - Exchange 2013 Web Services
microsoft-Server-ActiveSync - Exchange 2013 ActiveSync
ecp - Exchange 2013 Control Panel
autodiscover - Exchange 2013 Autodiscover Service
oab - Exchange 2013 Offline Address Book

И последнее, установите переменную ядра:

net.ipv4.vs.conntrack = 1

Без нее не будет работать контроль состояния соединения - это приведет к тому, что правила SNAT и DNAT будут работать не корректно.




воскресенье, 1 марта 2015 г.

Отказоустойчивый, масштабируемый кластер приложения с балансировкой нагрузки, часть 2 (про масштабирование и про ARP Flux)

Возвращаясь к статье Отказоустойчивый, масштабируемый кластер приложения с балансировкой нагрузки, может создаться впечатление, что масштабировать кластер можно, просто добавляя дополнительные ноды. Масштабируемость, на первый взгляд, будет ограничена количеством адресов в сетевом сегменте. Но внимание: чем больше нод, тем больше будет утилизация конечного приложения, и тем больше будет не целевого трафика в сегменте. Этому виной будут перекрестные проверки нод на доступность ресурсов. Следовательно, количество нод, которые могут выполнять функции балансировки, должно быть разумно ограниченным. По моему мнению четыре вполне достаточно. Рассмотрим, как можно преодолеть эту проблему.
Создадите сервер приложения аналогично предыдущим, но keepalived не ставьте. Добавьте интерфейс loopback с общим ip кластера:

# cat /etc/sysconfig/network-scripts/ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.3.100
NETMASK=255.255.255.255
ONBOOT=yes

Не спешите применять настройки. Поговорим вот еще о каком аспекте: по умолчанию linux сервер c несколькими интерфейсами в одной сети будет отвечать на ARP запрос, пришедший на любой локальный интерфейс и содержащий любой целевой локальный ip адрес. Звучит запутанно, покажу на примере: предположим на хосте есть два интерфейса с ip 192.168.3.200 и 192.168.3.201, тогда:

# arping -I eth0 192.168.3.200
ARPING 192.168.3.4 from 192.168.3.102 eth0
Unicast reply from 192.168.3.200 [52:54:00:BD:DF:C2]  1.362ms
Unicast reply from 192.168.3.200 [52:54:00:10:11:35]  1.209ms

Мы получаем два разных ARP ответа, эта проблема называется ARP Flux. Если мы сейчас включим интерфейс lo:0 это, в свою очередь, может стать причиной ARP Poisoning. Для того, чтобы решить эту проблему, необходимо поменять эту модель поведения работы ARP (host based model) на интерфейсо-зависимую (interface based model). Выставите следующие переменные ядра:

# echo -e "net.ipv4.conf.all.arp_ignore = 1 \nnet.ipv4.conf.all.arp_announce = 2" >> /etc/sysctl.d/99-sysctl.conf

Что эти переменные означают:
net.ipv4.conf.all.arp_ignore - определяет различные режимы ответа, на входящие ARP запросы, которые производят разрешение локальных IP адресов. Возможные значения:
  • 0 - установлено по умолчанию. Ответ производится на ARP запрос, пришедший на любой сетевой интерфейс системы, на разрешение любого целевого локального IP адреса.
  • 1 - ответ производится в случае, если ARP запрос на разрешение IP адреса пришел на интерфейс, содержащий этот IP адрес.
  • 2 - ответ производится в случае, если ARP запрос на разрешение IP адреса пришел на интерфейс, содержащий этот IP адрес, причем IP адрес отправителя должен находится в одной подсети целевым IP адресом.
  • 3 - не отвечать, если IP адрес источника находится в той же сети.
  • 4-7 - зарезервированы.
  • 8 - не отвечать на запросы.
net.ipv4.conf.all.arp_announce - определяет, каким образом будет анонсироваться локальный IP адрес в исходящих ARP запросах:
  • 0 - установлено по умолчанию. Используется любой локальный адрес, настроенный на любом интерфейсе.
  • 1 - попытаться исключить локальные адреса, которые не принадлежат к подсети. в которой находится целевой IP адрес. В случае отсутствия такого локального IP адреса будет использоваться поведение за номером 2.
  • 2 - Всегда использовать лучший локальный адрес, с которого нам удобно посылать запрос в целевую подсеть. Такой IP адрес выбирается из первичных IP адресов, находящихся в той же подсети, что и целевой IP адрес, на всех локальных интерфейсах. Если ничего подходящего нет, то будет использован первый ip адрес на интерфейсе, с которого будет произведен запрос или на всех других интерфейсах.
Теперь можно применить изменения и добавить новый сервер приложения в конфигурацию keepalived на всех нодах балансировщиках.

четверг, 26 февраля 2015 г.

Курсы Java/Android

Всем интересующимся программированием на java: проводятся курсы, доп. информация по ссылке. Автор курса мой знакомый - Лигай Виталий, гуру программирования, как я считаю.

понедельник, 23 февраля 2015 г.

Отказоустойчивый, масштабируемый кластер приложения с балансировкой нагрузки, часть 1

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

Мне нужен почтовый релей, забегая вперед, скажу, что с таким же успехом это может быть любое другое приложение, например, web сервер. Могу показаться банальным занудой, но хочу еще раз повторить: каждый сервис требует отдельного анализа, и не факт, что желаемое удастся реализовать. Далее отразим заголовок статьи: релей должен быть отказоустойчивым и иметь возможность масштабирования. Читатель статьи может возразить, что для почтового релея все вышесказанное можно реализовать, добавив несколько MX записей в доменной зоне. К сожалению, я ограничен одним, уже существующим ip адресом релея, таким образом, вариант с MX не годится. Подведем итог: нужно несколько почтовых релеев, обеспечивающих отказоустойчивость сервиса, разделяющих нагрузку и использующих один ip адрес.

В плане выбора ПО все просто и традиционно - я буду использовать дистрибутив oracle linux 7 (почти аналогичны ему centos 7 или rhel 7), в качестве smtp сервиса - postfix. Для балансировки будет использоваться решение LVS, поскольку ее частью является подсистема linux ядра - ipvs, быстрый и надежный вариант балансировки трафика на 4-м уровне сетевой модели OSI. 

В качестве управляющего ПО кластером используется keepalived. Данное ПО использует протокол VRRP для обеспечения высокой доступности (high avialability) нод кластера, а также позволяет организовать мониторинг доступности приложения.

Оставшиеся вводные данные:
Используемая сеть: 192.168.3.0/24
IP серверов по порядку: 192.168.3.[101-105]
Общий IP: 192.168.3.100

Обычно в стандартной практике делают отдельный кластер балансировки и группу серверов приложения, к примеру, рекомендуемое решение от Red Hat. Особенность данной реализации заключается в том, что каждый сервер является сервером приложения и балансировщиком трафика одновременно. Один из балансировщиков является активным, остальные резервные. В моем случае используются четыре релея, расположенные по два в двух географически разнесенных ЦОДах. Ниже приведен рисунок, иллюстрирующий прохождение трафика в кластере, к которому мы будем возвращаться при описании процесса работы.


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

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

# grep "inet_interfaces" /etc/postfix/main.cf | grep -v "^#"
inet_interfaces = all

Отключим firewalld, его можно будет настроить позднее, после того как будете твердо уверены, что кластер функционирует должным образом:

# systemctl disable firewalld.service
# systemctl stop firewalld.service

Установим keepalived, ipvsadm и модуль python ipaddr, модуль нужен для скрипта:

# yum -y install keepalived ipvsadm python-ipaddr

Разберем конфигурационный файл keepalived:

# Секция определения общих параметров
global_defs {
   notification_email {
      # Список почтовых адресов, по которым будут приходить оповещения о
      # недоступности нод или сервисов
      unix_adm@domain.ru
   }
   # Email от которого будет рассылаться почта
   notification_email_from keepalived@domain.ru
   # Адрес smtp сервера и время, в течение которого будет производится попытка
   # отправки почты
   smtp_server 192.168.3.1
   smtp_connect_timeout 30
   # Идентификатор сервера
   router_id server01.domain.ru
}

# Секция описания экземпляров VRRP (перемещаемые IP)
vrrp_instance mail_relay {
    # Начальное состояние при запуске, на остальных серверах должно быть BACKUP
    state MASTER
    # Интерфейс, на котором будет работать экземпляр VRRP
    interface eth0
    # Идентификатор экземпляра VRRP, должен быть идентичен на всех нодах.
    virtual_router_id 11
    # Приоритет при выборе MASTER'а, нода с большим приоритетом становится
    # активной.
    priority 100
    # Интервал уведомлений о состоянии, которые рассылает MASTER нода.
    # При отсутствии уведомлений произойдут перевыборы.
    advert_int 2
    # Секция аутентификации, пароль должен быть идентичен на всех нодах,
    # используется первые 8 символов.
    authentication {
        auth_type PASS
        auth_pass mrelay
    }
    # Список адресов, которые будут добавлены на ноду при выборе ее MASTER
    virtual_ipaddress {
        192.168.3.100
    }
    # Произвести миграцию состояния MASTER при появлении ноды с более высоким
    # приоритетом. В случае установки опции в nopreempt при появлении ноды с 
    # более высоким приоритетом MASTER нодой останется прежняя нода.
    preempt
    # Скрипт, который надо выполнить при событии, когда нода становится MASTER
    notify_master "/etc/keepalived/bypass_ipvs.py -r 192.168.3.100"
    # Скрипт, который надо выполнить при событии, когда нода становится SLAVE
    notify_backup "/etc/keepalived/bypass_ipvs.py -a 192.168.3.100"
    # Скрипт, который надо выполнить при событии ошибки смены роли ноды
    notify_fault "/etc/keepalived/bypass_ipvs.py -a 192.168.3.100"
}

Что выполняет скрипт: при установке состояния BACKUP на ноде он добавляет правило в iptables, которое заменяет (NAT) общий IP в пакетах входящего трафика на локальный IP ноды, и наоборот - для ответного трафика:

-A PREROUTING -t nat -d 192.168.3.100/32 -p tcp -j REDIRECT

Таким образом реализуется совместная обработка трафика всеми нодами, посмотрите еще раз рисунок вверху. В случае, когда нода становится MASTER, скрипт убирает правило натирования, поскольку общий IP принадлежит этой ноде. Скачать скрипт можно здесь.

Несколько замечаний: 
  • state - если вы уверены в качестве сети, можно на всех нодах кластера выставить BACKUP, в этом случае мастер определится в результате выборов. 
  • priority - в случае равных приоритетов побеждает нода с большим IP.
  • nopreempt - при данной опции state должен быть установлен в BACKUP.
  • если установить опции state BACKUP, одинаковый priority и nopreempt на все ноды, мы получим идентичный конфигурационный файл, что очень удобно в системах централизованного сопровождения серверов. Но вместе с тем шансы возникновения ситуации "split brain" в результате каких либо проблем также увеличиваются.
Продолжим далее рассматривать keepalived.conf:

# Секция конфигурации политики балансировки (LVS) и описание серверов приложения
virtual_server 192.168.3.100 25 {
    # Период опроса серверов приложения
    delay_loop 2
    # Планировщик балансировки, wlc - Weighted Least-Connections Scheduling.
    lb_algo wlc
    # Метод передачи пакетов на сервера приложений, dr - Direct Routing
    lb_kind DR
    protocol TCP

    # Секция описание сервера приложения 192.168.3.101
    real_server 192.168.3.101 25 {
        # Вес сервера
        weight 1
        # Секция проверки доступности приложения, в данном случае выполняется
        # проверка доступности smtp приложения. 
        SMTP_CHECK {
            connect_timeout 5
            retry 3
            # Имя в команде smtp helo
            helo_name smtpchecker.domain.ru
        }
    }
    # Далее однотипные описания серверов для 192.168.3.102 и т.д.
}

Еще несколько замечаний:
  • lb_algo wlc - распределяет большее количество запросов серверам с наименьшим количеством активных подключений в соответствии с их весом.
  • lb_kind DR - маршрутизация пакета, в этом случае пакет с активной ноды передается на резервную следующим образом: производится замена MAC адреса в поле destination MAC в ethernet заголовке пакета с MAC адреса активной ноды на MAC адрес сервера приложения. IP адрес остается без изменения. В свою очередь сервер приложения (нода в состоянии BACKUP) получив пакет, натирует общий IP адрес в поле destination IP в свой собственный. 
  • со всеми вариантами балансировки, передачи пакетов, методах проверки доступности приложения можно ознакомиться на сайте проекта LVS.
Ссылка на файл keepalived.conf

Запустим keepalived и проверим что получилось:

# systemctl enable keepalived.service
# systemctl start keepalived.service

$ telnet 192.168.3.100 25
Trying 192.168.3.100...
Connected to 192.168.3.100.
Escape character is '^]'.
220 server01.domain.ru ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.
[valentine@server ~]$ telnet 192.168.3.100 25
Trying 192.168.3.100...
Connected to 192.168.3.100.
Escape character is '^]'.
220 server02.domain.ru ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.

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

Посмотреть логи keepalived:

# journalctl -u keepalived.service

Посмотреть, на какой ноде находится общий IP, привычная команда ifconfig его не показывает:

# ip addr show
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:0d:5a:1a brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.101/24 brd 192.168.3.255 scope global dynamic eth0
       valid_lft 70403sec preferred_lft 70403sec
    inet 192.168.3.100/32 scope global eth0
...

Или более современный вариант:

# nmcli device show eth0
...
IP4.ADDRESS[1]:                         ip = 192.168.3.101/24, gw = 192.168.3.1
IP4.ADDRESS[2]:                         ip = 192.168.3.100/32, gw = 192.168.3.1
...

Посмотреть статистику балансировки:

# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.3.100:25 wlc
  -> 192.168.3.101:25             Route   1      2          14         
  -> 192.168.3.102:25             Route   1      3          9      
...

Посмотреть текущие соединения:

# ipvsadm -Lnc
IPVS connection entries
pro expire state       source             virtual            destination
TCP 13:20  ESTABLISHED 192.168.3.3:59527  192.168.3.100:25   192.168.3.102:25
...

Если в сети несколько vrrp экземпляров, можно проверить номера идентификаторов

# tcpdump -nnn ip proto 112
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:11:36.244824 IP 192.168.3.101 > 224.0.0.18: VRRPv2, Advertisement, vrid 11, prio 100, authtype simple, intvl 1s, length 20

Удачных внедрений!

Upd: продолжение, для тех кому мало будет 4 ноды.

воскресенье, 22 февраля 2015 г.

Настройка соединения мост для использования в Virtual Machine Manager

Коллеги, читатели, сегодня мне понадобилось провести эксперимент с несколькими виртуальными машинами на домашнем PC. Для эксперимента надо было пустить машины напрямую в локальную сеть. Сделать это можно путем создания сетевого моста (бридж), в котором будут находится интерфейсы виртуальных машин и интерфейс гипервизора, в литературе этот вариант настройки также называется "shared physical device"
Несмотря на то, что, начиная с Fedora 20 (у меня Fedora 21) NetworkManager поддерживает создание соединений типа мост, выполнять будем по старинке (я не всегда понимаю логику работы NetworkManager, и собственно, попробовав с наскоку настроить, я получил неудовлетворительный результат).
Создайте конфигурационный файл сетевого моста:

# cat /etc/sysconfig/network-scripts/ifcfg-bridge0 
DEVICE=bridge0
ONBOOT=yes
TYPE=Bridge
BOOTPROTO=dhcp
NM_CONTROLLED=no
DELAY=0

где bridge0 это имя моста.
Соответствующая конфигурация сетевого интерфейса гипервизора:

# cat /etc/sysconfig/network-scripts/ifcfg-eno1 
TYPE=Ethernet
ONBOOT=yes
HWADDR=91:DE:80:B4:5F:0C
DEVICE=eno1
BOOTPROTO=none
NM_CONTROLLED=no
BRIDGE=bridge0

Удалите конфигурацию NetworkManadger, относящуюся к физическому интерфейсу. Далее можете перегрузиться или перезапустить network.service. Перейдем к настройке в Virtual Machine Manager. Зайдите в параметры оборудования виртуальной машины, выберите "Указать имя общего устройства" и соответственно укажите имя сетевого моста, как на рисунке ниже