понедельник, 21 ноября 2011 г.

Sender Policy Framework

Несложная SPF запись:

domain.local | TXT  | "v=spf1 ip4:<IP_адрес> a mx ~all"


v - используемая версия протокола SPF

ip4:<IP_адрес> - версия IP протокола и IP адрес хоста письма с которого будут считаться легитимными (в рамках протокола SPF), при отправке с домена domain.local

a - разрешает прием писем от хоста, IP-адрес которого совпадает с IP-адресом в A-записи для domain.local

mx - разрешает прием писем, если отправляющий хост указан в одной из MX-записей для domain.local

~all - использование т.н. облегченной политики по отношению к письмам не прошедшим проверку, т.е. такие письма не будут отклоняться сразу же

суббота, 19 ноября 2011 г.

MySQL индексирование таблиц


При низкой производительности MySQL базы данных нет никакого смысла менять параметры в конфиге Mysql сервера, настраивать репликации, переносить файлы базы на размещение в разделах с более быстрой файловой системой или на более быстрый RAID массив и т.д., если в таблицах базы не проставлены индексы. Добавление индексов это первое что требуется выполнить для улучшения производительности базы и только потом все остальное.

Общая информация по индексам

1. Индексы можно проставлять по одному столбцу или по комбинации столбцов
2. Режим содержания для индекса это или режим повторяющихся значений, или режим только уникальных значений
3. Одна таблица может иметь более одного индекса, использующего различные столбцы таблицы
4. Строковый тип, кроме ENUM и SET можно индексировать по первым некотором кол-ве символов слева. Нельзя создавать индексы по столбцам типа BLOB и TEXT, пока не задана длина префикса. Индексирование только префикса столбца позволяет уменьшить индекс и ускорить доступ к нему
5. Индекс таблиц типа InnoDB так же может строиться и на внешних ключах, т.е. значения в индексе должны соответствовать значениям, представленным в другой таблице. MyISAM таблицы не поддерживают внешние ключи, зато можно использовать индекс FULLTEXT, которые нельзя использовать в InnoDB таблицах

Примеры добавления индексов

Добавление обычного индекса (дублирование записей в обычном индексе разрешено):

ALTER TABLE tbl_name ADD INDEX index_name (index_columns);

где tbl_name - имя таблицы, index_name - имя индекса (указывать не обязательно), index_columns - список индексируемых столбцов

Пример добавления обычного индекса к уже имеющейся таблице:

mysql> alter table users add index index_for_name (`name`);
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from users;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users |          1 | index_for_name |            1 | name        | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)

Добавление уникального индекса (соответственно дублирование запрещено):

ALTER TABLE tbl_name ADD UNIQUE index_name (index_columns);
ALTER TABLE tbl_name ADD PRIMARY KEY index_name (index_columns);

Индекс типа PRIMARY KEY не может содержать пустых значений, а индекс UNIQUE пару пустых значений содержать может. Это все связано с тем что нельзя сравнивать между собой два пустых значения.

Пример добавления PRIMARY KEY к уже созданной таблице:

mysql> ALTER TABLE account_access ADD PRIMARY KEY (`id`, `RealmID`);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from account_access;
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table          | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| account_access |          0 | PRIMARY  |            1 | id          | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| account_access |          0 | PRIMARY  |            2 | RealmID     | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

Добавление индексов по префиксу столбца строкового типа

Пример добавления индекса по префиксу при создании таблицы:

mysql> create table users (name char(50) not null, address binary(100) not null, index index_for_name (name(20)), index index_for_address (address(25)));
Query OK, 0 rows affected (0.01 sec)

mysql> show index from users;
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users |          1 | index_for_name    |            1 | name        | A         |        NULL |       20 | NULL   |      | BTREE      |         |
| users |          1 | index_for_address |            1 | address     | A         |        NULL |       25 | NULL   |      | BTREE      |         |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

В итоге создался индекс по первым 20 символам столбца CHAR и первым 25 байтам столбца BINARY

Пример добавления индекса по префиксу к уже созданной таблице:

mysql> alter table users add index index_for_name (`name`(20));
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from users;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users |          1 | index_for_name |            1 | name        | A         |        NULL |       20 | NULL   |      | BTREE      |         |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)

Примеры удаления индексов

Удаление индексов

ALTER TABLE tbl_name DROP INDEX index_name;

Пример удаления обычного индекса

mysql> show index from users;
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users |          1 | index_for_name    |            1 | name        | A         |        NULL |       20 | NULL   |      | BTREE      |         |
| users |          1 | index_for_address |            1 | address     | A         |        NULL |       25 | NULL   |      | BTREE      |         |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

mysql> alter table users drop index index_for_address;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from users;
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| users |          1 | index_for_name |            1 | name        | A         |        NULL |       20 | NULL   |      | BTREE      |         |
+-------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
1 row in set (0.00 sec)

ALTER TABLE tbl_name DROP PRIMARY KEY; 

Пример (имя индекса при удалении PRIMARY KEY не указывается, так как в одной таблице может быть только один первичный ключ и его имя всегда будет PRIMARY) удаления PRIMARY KEY

mysql> show index from account_access;
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table          | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| account_access |          0 | PRIMARY  |            1 | id          | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| account_access |          0 | PRIMARY  |            2 | RealmID     | A         |           0 |     NULL | NULL   |      | BTREE      |         |
+----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

mysql> alter table account_access drop primary key;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from account_access;
Empty set (0.00 sec)

Так же надо помнить что при удалении столбца из таблицы, столбец удалится и из индекса. Удалив все индексируемые столбцы из таблицы удалится и весь индекс.

понедельник, 14 ноября 2011 г.

Nginx + Spawn-fcgi

(ОС: Debian 5.0)


Устанавливаем Nginx, PHP
apt-get install nginx php5-common php5-cli php5-cgi php5-mysql gcc make
Собираем Spawn-fcgi:
cd /usr/src
wget http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz
tar -xf spawn-fcgi-1.6.3.tar.gz
cd spawn-fcgi-1.6.3
./configure --prefix=/opt/spawn-fcgi
make install
Создаем Init скрипт /etc/init.d/spawn-fcgi
#!/bin/bash
case "$1" in
start)
echo "starting..."
/opt/spawn-fcgi/bin/spawn-fcgi -U www-data -G www-data -p 9000 -F 2 -C 3 -f php-cgi
;;
stop)
echo "stopping..."
killall php-cgi
;;
restart)
echo "restarting..."
killall php-cgi
sleep 1
/opt/spawn-fcgi/bin/spawn-fcgi -U www-data -G www-data -p 9000 -F 2 -C 3 -f php-cgi
;;
*)
echo "Usage: $0 [start|stop|restart]"
esac
exit
Выставляем права и добавляем его в автозагрузку
chmod 700 /etc/init.d/spawn-fcgi
update-rc.d spawn-fcgi defaults
В /etc/nginx/sites-enabled/default расскоментируем и корректируем часть конфига
location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                #fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
                fastcgi_param  SCRIPT_FILENAME  /var/www/nginx-default$fastcgi_script_name;
                include fastcgi_params;
        }
Запускаем Spawn-fcgi, Nginx
invoke-rc.d spawn-fcgi start
invoke-rc.d nginx start

Установка Redmine на Apache

(ОС: Debian 5.0 x64, Nginx & Apache2.2, ISPmanager)

в /etc/apt/sources.list включаем backports

deb http://backports.debian.org/debian-backports lenny-backports main contrib non-free

устанавливаем

apt-get update && apt-get install libapache2-mod-passenger redmine-mysql redmine

добавляем вирт.хост Apache (80 порт слушает Nginx который перенаправляет запросы Apache)

<VirtualHost <IP_адрес>:8080>
        ServerName <redmine.local.lan>
        RailsEnv production
        SetEnv X_DEBIAN_SITEID "default"
        Alias "/plugin_assets/" /var/cache/redmine/default/plugin_assets/
        DocumentRoot /usr/share/redmine/public
        SuexecUserGroup user user
        CustomLog /var/www/httpd-logs/redmine.local.lan.access.log combined
        ErrorLog /var/www/httpd-logs/redmine.local.lan.error.log
        ServerAlias www.redmine.local.lan
        ServerAdmin webmaster@redmine.local.lan
        <Directory "/usr/share/redmine/public">
                Order allow,deny
                Allow from all
        </Directory>
</VirtualHost>

Ruby on Rails на сервере при этом тоже должен быть из бэкпортов

Rails-ruby1.8
2.3.5-1~bpo50+1

воскресенье, 13 ноября 2011 г.

PostgreSQL Slony - настройка асинхронной master/slave репликации


(ОС: Debian 6.0 x64, PostgreSQL 8.4, Slony 2.0)


Терминология:
  • кластер – набор баз данных;
  • нода – база данных, которая может быть распределена;
  • репликационный набор – набор таблиц, которые могут быть реплицированы между нодами кластера;
  • источник (или провайдер) и подписчик – у каждой репликации есть одна нода-источник, остальные ноды могут быть подписчиками;
  • slon – демон, присутствующий на каждой ноде и управляющий ее репликациями;
  • slonik – командная утилита для общего управления нодами.


Устанавливаем ПО на master сервер:

apt-get install postgresql-8.4 slony1-2-bin
(при инсталляции slony1-2-bin как рекомендательный пакет притянет в установку postgresql-8.4-slony1-2)

Устанавливаем ПО на slave сервер:

apt-get install postgresql-8.4 postgresql-8.4-slony1-2

Разрешаем на master сервере сетевые подключения с slave сервера, открываем /etc/postgresql/8.4/main/pg_hba.conf и прописываем

host    all         slony        172.16.0.101/16          md5

где slony это спец.пользователь из под которого будет действовать slony, а 172.16.0.101 это IP адрес slave сервера

Разрешаем на slave сервере сетевые подключения с master сервера, открываем /etc/postgresql/8.4/main/pg_hba.conf и прописываем


host    all         slony        172.16.0.102/16          md5

где slony это спец.пользователь из под которого будет действовать slony, а 172.16.0.102 это IP адрес master сервера

На обоих серверах в /etc/postgresql/8.4/main/postgresql.conf

listen_addresses = '*'


Создаем postgres пользователя slony на обоих серверах и выдаем ему привилегии суперпользователя (такие привилегии это требования самого slony)

postgres=# create user slony with password 'slony_pass';
postgres=# alter user slony createuser;


Создаем целевую базу (ту которую планируем реплицировать) на master сервере и импортируем в нее данные

postgres=# create database of_db;
root@postgresql-1:~# psql -U postgres -f of_db.sql of_db


включаем поддержку pl/pgsql для этой базы

root@postgresql-1:~# createlang -U postgres -d of_db plpgsql


в данном примере будем реплицировать несколько таблиц, ofvcard и ofuserprop вышеозвученной базы, смотрим наличие индексов у этих таблиц


of_db=# \d ofvcard;
            Table "public.ofvcard"
  Column  |         Type          | Modifiers
----------+-----------------------+-----------
 username | character varying(64) | not null
 vcard    | text                  | not null
Indexes:
    "ofvcard_pk" PRIMARY KEY, btree (username)


of_db=# \d ofuserprop;
           Table "public.ofuserprop"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 username  | character varying(64)  | not null
 name      | character varying(100) | not null
 propvalue | text                   | not null
Indexes:
    "ofuserprop_pk" PRIMARY KEY, btree (username, name)


обязательное наличие индексов у таблиц которые будут реплицироваться это требование slony (и любой нормальной базы). Как видим индексы у данных таблиц есть (если индексов нет, то slony можете сам их добавить, хотя его разработчики и не рекомендуют использовать данный функционал slony по понятным причинам)

Теперь на slave сервере создаем базу данных, таблицы которой в дальнейшем будут реплицироваться


postgres=# create database of_db;

включаем поддержку pl/pgsql и для этой базы


root@postgresql-2:~# createlang -U postgres -d of_db plpgsql


на master сервере выполняем экспорт структуры базы и импортируем ее на slave сервер в одноименную базу

root@postgresql-1:~#pg_dump -U postgres -s of_db > of_db.sql
root@postgresql-2:~# psql -U postgres -f of_db.sql of_db



теперь можно с помощью утилиты slonik инициализировать наш кластер, slonik это cli утилита принимающая команды с файла или stdin

создаем аналогичный скрипт и запускаем его на master сервере

#!/bin/bash


slonik <<_EOF_
    cluster name = simple_cluster;
    node 1 admin conninfo = 'dbname=of_db host=172.16.0.102 user=slony password=slony_pass';
    node 2 admin conninfo = 'dbname=of_db host=172.16.0.101 user=slony password=slony_pass';
    
    init cluster ( id=1, comment = 'Master Node');


    create set (id=1, origin=1, comment='of_db replication set');
    set add table (set id=1, origin=1, id=1, fully qualified name = 'public.ofvcard', comment='card');
    set add table (set id=1, origin=1, id=2, fully qualified name = 'public.ofuserprop', comment='prop');
    
    store node (id=2, comment = 'Slave node', event node=1);
    store path (server = 1, client = 2, conninfo='dbname=of_db host=172.16.0.102 user=slony password=slony_pass');
    store path (server = 2, client = 1, conninfo='dbname=of_db host=172.16.0.101 user=slony password=slony_pass');
_EOF_

после его выполнения запускаем следующий скрипт, который подпишет slave сервер на репликационный набор

#!/bin/bash


slonik <<_EOF_
     cluster name = simple_cluster;
     node 1 admin conninfo = 'dbname=of_db host=172.16.0.102 user=slony password=slony_pass';
     node 2 admin conninfo = 'dbname=of_db host=172.16.0.101 user=slony password=slony_pass';


     subscribe set ( id = 1, provider = 1, receiver = 2, forward = no);
_EOF_


готово, теперь на master сервере прописываем настройки в конфиг.файлы slony, сначала в /etc/slony1/slon_tools.conf


if ($ENV{"SLONYNODES"}) {
    require $ENV{"SLONYNODES"};
} else {
    $CLUSTER_NAME = 'simple_cluster';
    $LOGDIR = '/var/log/slony1';
    $MASTERNODE = 1;
    $DEBUGLEVEL = 2;
    add_node(node     => 1,
             host     => '172.16.0.102',
             dbname   => 'of_db',
             port     => 5432,
             user     => 'slony',
             password => 'slony_pass');
    add_node(node     => 2,
             host     => '172.16.0.101',
             dbname   => 'of_db',
             port     => 5432,
             user     => 'slony',
             password => 'slony_pass');
}
$SLONY_SETS = {
    "set1" => {
        "set_id"       => 1,
        "table_id"     => 1,
        "pkeyedtables" => ["public.ofvcard", "public.ofuserprop"],
    },
};
if ($ENV{"SLONYSET"}) {
    require $ENV{"SLONYSET"};
}
1;


потом в файл /etc/default/slony1 прописываем ноды

SLON_TOOLS_START_NODES="1 2"

запускаем slon'а

invoke-rc.d slony1 start


Видим что к реплицируемым таблицам добавились триггеры

of_db=# \d ofvcard;
            Table "public.ofvcard"
  Column  |         Type          | Modifiers
----------+-----------------------+-----------
 username | character varying(64) | not null
 vcard    | text                  | not null
Indexes:
    "ofvcard_pk" PRIMARY KEY, btree (username)
Triggers:
    _simple_cluster_logtrigger AFTER INSERT OR DELETE OR UPDATE ON ofvcard FOR EACH ROW EXECUTE PROCEDURE _simple_cluster.logtrigger('_simple_cluster', '1', 'k')
Disabled triggers:
    _simple_cluster_denyaccess BEFORE INSERT OR DELETE OR UPDATE ON ofvcard FOR EACH ROW EXECUTE PROCEDURE _simple_cluster.denyaccess('_simple_cluster')


of_db=# \d ofuserprop;
           Table "public.ofuserprop"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 username  | character varying(64)  | not null
 name      | character varying(100) | not null
 propvalue | text                   | not null
Indexes:
    "ofuserprop_pk" PRIMARY KEY, btree (username, name)
Triggers:
    _simple_cluster_logtrigger AFTER INSERT OR DELETE OR UPDATE ON ofuserprop FOR EACH ROW EXECUTE PROCEDURE _simple_cluster.logtrigger('_simple_cluster', '2', 'kk')
Disabled triggers:
    _simple_cluster_denyaccess BEFORE INSERT OR DELETE OR UPDATE ON ofuserprop FOR EACH ROW EXECUTE PROCEDURE _simple_cluster.denyaccess('_simple_cluster')


Проверяем работу репликации, на master сервере добавляем/удаляем какие нибудь данные в наших целевых таблицах и проверяем чтобы эти данные синхронизировались и в базе на slave сервере. Если все хорошо, то на этом тестовая настройка репликации закончена.

Postfix + Policyd политика для исходящей почты

(ОС: Debian 5.0, настраивалось на сервере с ISPmanager, но это не принципиально, работать будет везде)


в процессе инсталляции можно будет сразу создать БД mysql для policyd
apt-get install postfix-policyd
/etc/postfix/main.cf добавляем check_policy_service inet:127.0.0.1:10031 в самый конец параметра smtpd_recipient_restrictions
smtpd_recipient_restrictions = permit_sasl_authenticated, check_recipient_access hash:/etc/mail/access, permit_mynetworks, reject_unauth_destination, reject_unlisted_recipient, reject_unverified_recipient, check_policy_service inet:127.0.0.1:60000, check_policy_service inet:127.0.0.1:10031
/etc/postfix-policyd.conf выключаем всё (по дефолту включен только whitelisting) и приводим конфиг к примерно такому виду
SENDERTHROTTLE=1
SENDER_THROTTLE_SASL=1
SENDER_THROTTLE_HOST=0
QUOTA_EXCEEDED_TEMP_REJECT=1 # какую ошибку отдавать при истечении квоты (1=4xx  0=5xx)
SENDER_QUOTA_REJECTION="Quota Exceeded." # какое сообщение получит пользователь при превышении любой из квот
SENDER_SIZE_REJECTION="Message size too big." # сообщение при превышении максим.размера исходящего письма
SENDERMSGLIMIT=50 # кол-во исходящих писем которые может отправить пользователь до истечения SENDERTIMELIMIT
SENDERRCPTLIMIT=150 # кол-во получателей которым можно отправить письмо до истечения SENDERTIMELIMIT
SENDERQUOTALIMIT=250000000 # кол-во исходящей почты в мегабайтах которое может отправить пользователь до истечения SENDERTIMELIMIT (поддерживается максимум до 2Гб)
SENDERTIMELIMIT=2h # время после которого все счетчики сбрасываются обратно до нуля
SENDERMSGSIZE=10240000 # максимальный размер исходящего письма
SENDER_INACTIVE_EXPIRE=31d # время после которого все неактивные пользователи которые хранятся в базе данных будут удалены из нее (нулевое значение позволит хранить все записи)
invoke-rc.d postfix-policyd restart
Пользователи и статистическая информация о них постепенно добавляется в БД mysql (смотрим таблицу throttle) по мере отправки ими писем.
Таким образом можно контролировать кол-во и другие параметры исходящей почты, но только для тех пользователей которые авторизуются на сервере перед отправкой письма (по сути всех кто пытается отправить исходящее письмо через основной сетевой интерфейс почтового сервера).

суббота, 12 ноября 2011 г.

OCFS2 + iSCSI

(ОС: CentOS)


1. Выполняем на всех нодах
Скачиваем и ставим следующие RPM пакеты:
ocfs2 modules - http://oss.oracle.com/projects/ocfs2/files/
ocfs2-tools - http://oss.oracle.com/projects/ocfs2-tools/files/
(обязательно сверяем версии пакетов и убеждаемся что скачали и собираемся ставить пакеты для нашей версии ядра)
После установки пакетов проверяем активировались ли целевые модули ядра:
[root@storage ~]# modprobe -l | grep -i ocfs
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/ocfs2.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/dlm/ocfs2_dlm.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/dlm/ocfs2_dlmfs.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/cluster/ocfs2_nodemanager.ko
Должны подгрузиться все модули из пакета ocfs2 modules:
[root@storage ~]# rpm -ql ocfs2-2.6.18-194.11.1.el5-1.4.7-1.el5
/lib/modules/2.6.18-194.11.1.el5/kernel/fs
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/cluster
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/cluster/ocfs2_nodemanager.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/dlm
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/dlm/ocfs2_dlm.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/dlm/ocfs2_dlmfs.ko
/lib/modules/2.6.18-194.11.1.el5/kernel/fs/ocfs2/ocfs2.ko
Если модули не подхватились сразу, то пытаемся подгрузить из руками с помощью modprobe, пытаемся запустить o2cb:
modprobe <имя_модуля>
service o2cb start
Создаем главный конфигурационный файл /etc/ocfs2/cluster.conf
cluster:
 name = ocfs2
 node_count = 3
node:
 name = storage.ocfs2.lan
 cluster = ocfs2
 number = 0
 ip_address = 172.16.0.150
 ip_port = 7777

node:
 name = node01.ocfs2.lan
 cluster = ocfs2
 number = 1
 ip_address = 172.16.0.160
 ip_port = 7777

node:
 name = node02.ocfs2.lan
 cluster = ocfs2
 number = 2
 ip_address = 172.16.0.161
 ip_port = 7777
node_count - кол-во нод
ip_address - соответственно IP адреса нод
number - номер в кластере
cluster - имя кластера в котором учавствует нода
name - имя ноды
ip_port - сетевой порт для связи между нодами
Выполняем:
service o2cb configure
Cluster to start on boot (Enter "none" to clear): Ввести имя кластера, который указали в /etc/ocfs2/cluster.conf
2. Выполняем на ноде-сторадже
yum install scsi-target-utils.i386
chkconfig tgtd on
Cоздаем наше целевое устройство
tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.2010-10.lan.node:disk1
Добавляем к целевому устройству свежесозданный раздел:
tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun 1 -b /dev/sdc
Разрешаем доступ ноде с IP-адресом 172.16.0.160 (так же разрешаем доступа для всех остальных нод)
tgtadm --lld iscsi --op bind --mode target --tid 1 -I 172.16.0.160
Проверяем
tgtadm --lld iscsi --op show --mode target
Настраиваем экспорт на постоянной основе:
vi /etc/tgt/targets.conf
<target iqn.2008-09.com.example:server.target1>
    backing-store /dev/sdc
</target>
(/dev/sdc это диск который будет выступать стораджем OCFS2)
Создаем ФС на целевом диске:
mkfs.ocfs2 -b 4K -C 128K -N 2 -L ocfs1 /dev/sdc
3. Выполняем всех остальных нодах (те которые будут импортировать OCFS2 диск с сервера-стораджа)
yum install iscsi-initiator-utils
chkconfig iscsid on
service iscsid start
Ищем таргет:
iscsiadm -m discovery -t sendtargets -p 172.16.0.150:3260
iscsiadm -m node -T iqn.2010-10.lan.node:disk1 -p 172.16.0.150:3260
iscsiadm -m node -T iqn.2010-10.lan.node:disk1 -p 172.16.0.150:3260 -l
(вместо 172.16.0.150 ставим IP сервера выполняющего роль iSCSI target)
Проверяем подключился ли диск:
fdisk -l
Если всё хорошо, то можно монтировать диск:
mount.ocfs2 /dev/sdс /mnt
Послесловие:
Не забываем добавить сервисы в автозапуск:
chkconfig o2cb on
Статус кластера можно посмотреть так:
service o2cb status

OpenVPN c аутентификацией по логину и паролю


OpenVPN в качестве шлюза для VPN клиентов
cd /usr/share/doc/openvpn/examples/easy-rsa/2.0/
source ./vars
./clean-all
./build-ca
./build-key-server server
./build-dh
openvpn --genkey --secret ./keys/ta.key
/etc/openvpn/server.conf
plugin /usr/lib/openvpn/openvpn-auth-pam.so login
local 172.16.0.10 # здесь указываем IP адрес сервера
port 1194
proto tcp
dev tun
ca /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/ca.crt
cert /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/server.crt
key /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/server.key
dh /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/dh1024.pem
client-cert-not-required
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push «route 10.8.0.0 255.255.255.0″
keepalive 10 120
tls-server
tls-auth /usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/ta.key 0
tls-timeout 120
auth MD5
cipher BF-CBC
comp-lzo
max-clients 100
user nobody # для debian'а (для centos - openvpn)
group nogroup # для debian'а (для centos - openvpn)
persist-key
persist-tun
status openvpn-status.log
log /var/log/openvpn/openvpn.log
verb 5
VPN-клиент под Windows: http://openvpn.se/download.html
Копируем с сервера два файла: ca.crt, ta.key на рабочую станцию VPN-клиент в папку c:/program files/openvpn/config
Cоздаем там же файл-конфиг openvpn.ovpn
auth-user-pass
dev tun0
proto tcp
remote 172.16.0.10 # здесь указываем IP адрес VPN сервера
port 1194
redirect-gateway def1
client
resolv-retry infinite
ca ca.crt
tls-client
tls-auth ta.key 1
auth MD5
cipher BF-CBC
ns-cert-type server
comp-lzo
nobind
persist-key
persist-tun
verb 3
Включаем на сервере форвардинг
/etc/sysctl.conf:
net.ipv4.ip_forward = 1

/sbin/sysctl -w net.ipv4.ip_forward=1
Настройка фаерволла
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to-source <внешний IP сервера>
iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -d 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Теперь можно создавать VPN аккаунты, OpenVPN при подключении VPN клиента будет запрашивать пароль и логин системного пользователя
useradd -s /usr/sbin/nologin vpnuser1
passwd vpnuser1
На рабочих станциях с Windows XP учетная запись с которой пользователь работает с OpenVPN должна обязательно состоять в группе "Администраторы"
а на компьютерах с Windows Vista или Windows 7 требуется в клиентский конфиг openvpn.ovpn добавить эти два параметра
route-method exe
route-delay 2