Friday, April 29, 2016

RegularExpression

URL 분석

정규표현식(기본적인 표현식)
^((http[s]?|ftp):\/\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*?)?(#[\w\-]+)?$

정규표현식(/? 처럼 인덱스 생략까지 표현)
^((http[s]?|ftp):\/\/)?\/?([^:\/\s]+)((\/[\w\-\.]+)*\/)([\w\-\.]+[^#\?\s]+|[\w\-\.]?[^#\?\s]?)(.*?)?(#[\w\-]+)?$

#! /bin/env perl

$uri = "http://example.com/index.php?title=example-release&redirect=no#Packages";

$uri =~ /^((http[s]?|ftp):\/\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*?)?(#[\w\-]+)?$/;

print "PROTOCOL: $2\n";
print "HOST: $3\n";
print "PATH: $4\n";
print "FILE: $6\n";
print "QUERY: $7\n";
print "HASH: $8\n";

$ perl example.pl

PROTOCOL: http
HOST: example.com
PATH: /
FILE: index.php
QUERY: ?title=example-release&redirect=no
HASH: #Packages


RedisTroubleShooting

Redis 데몬의 쿼리 증가에 따른 응답 지연에 대한 원인 분석


문제 발생 서버 정보

Date

2013/11/29

Server

Physical server

OS 정보

CentOS 6.4 | x86_86 | 2.6.32-358.23.2.el6.x86_64

CPU 정보

Architecture:         x86_64
CPU op-mode(s):       32-bit, 64-bit
Byte Order:           Little Endian
CPU(s):               8
On-line CPU(s) list:  0-7
Thread(s) per core:   2
Core(s) per socket:   4
Socket(s):            1
NUMA node(s):         1
Vendor ID:            GenuineIntel
CPU family:           6
Model:                44
Stepping:             2
CPU MHz:              2399.951
BogoMIPS:             4799.90
Virtualization:       VT-x
L1d cache:            32K
L1i cache:            32K
L2 cache:             256K
L3 cache:             12288K
NUMA node0 CPU(s):    0-7

Memory 정보

49381524KB(47G)

문제 분석 필요 사항

  • Redis 데몬 설정
  • Hardware 구성
  • OS 커널 설정
  • Network 구성

문제의 현상

redis 데몬으로 쿼리 증가시 redis 데몬에서 쿼리에 대한 응답 지연 발생.

문제의 원인

  1. 해당 현상 발생시 물리적 자원 사용량은 한계점에 이르지 않았다고 판단됨.

  2. [1] 번의 배제로 OS, SW 상의 구성을 확인.

  3. Redis 에 질의되는 쿼리 값들을 확인 결과 특정쿼리(keys *)실행시에 다른 쿼리(get)들이 지연되는 현상 확인.

  4. [3] 번의 문제(redis 자체 설계 문제)는 현재 해당 문제 발생 시간과 관련 없음을 확인.

  5. Redis 데몬의 source 확인시 listen() 함수의 backlog 는 고정값 511 이지만 문제 발생시 처리에는 충분하다고 판단됨.
    $ vi redis/src/anet.c

    if (listen(s, 511) == -1) {
  6. 실제 SW 상의 backlog 가 적용 되었는지 커널 설정 확인 결과 한가지 설정(net.core.somaxconn)이 누락 된 것을 확인.(man 2 listen)

  7. [6] 번의 문제로 인하여 기본값(128)으로 backlog 설정이 적용되는 것을 커널 소스를 통해 확인.
    $ vi kernel/net/socket.c

    1470 SYSCALL_DEFINE2(listen, int, fd, int, backlog)
    1471 {
    1472     struct socket *sock;
    1473     int err, fput_needed;
    1474     int somaxconn;
    1475 
    1476     sock = sockfd_lookup_light(fd, &err, &fput_needed);
    1477     if (sock) {
    1478         somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
    1479         if ((unsigned)backlog > somaxconn)
    1480             backlog = somaxconn;
    1481 
    1482         err = security_socket_listen(sock, backlog);
    1483         if (!err)
    1484             err = sock->ops->listen(sock, backlog);
    1485 
    1486         fput_light(sock->file, fput_needed);
    1487     }
    1488     return err;
    1489 }
  8. [7] 번으로 kernel의 backlog 수가 너무 낮다는 결론 유추

문제의 재현

재현 코드 작성
$ vi redis_connect_thread.c

OS kernel backlog 감소후 테스트
$ redis_connect {redis_server} {requests} {thread}

문제의 해결

  1. Redis backlog 관련부분 source 수정후 재배포
    $ diff -urNp redis.org/src/anet.c redis/src/anet.c

    -    if (listen(s, 511) == -1) { /* the magic 511 constant is from nginx */
    +    if (listen(s, 30000) == -1) { /* the magic 511 constant is from nginx */
  2. OS kernel 설정 수정후 재배포
    $ diff -urNp /etc/sysctl.conf.org /etc/sysctl.conf

    + net.core.somaxconn  = 30000
  3. 모니터링 프로그램 코드 등록(slowlog get 등등 이용한 코드 작성)
    $ vi redis-slowlog-to-syslog.pl

  4. [1-3] 적용후 문제 해결 확인

기타

Linux kernel 버전 2.6.14 이후로 socket 함수에 NETLINK_INET_DIAG 옵션으로 소켓 모니터링이 가능하다. 그래서 listen 된 port 의 backlog 가 실시간 확인 가능하다. ss 명령어에 해당 기능이 구현 되어 있다.

$ vi iproute2-2.6.31/misc/ss.c

static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
.
.
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
.
.

Redis 다중 포트 사용시 MemoryCache Dump file 의 복구 문제


내용

재시작시 마지막 높은 포트의 메모리 DB로 복구되는 현상

원인

Redis의 메모리 Dump는 dbfilename 설정으로 dir 설정 위치에 저장되는데 dbfilename 이 겹치면 포트를 여러개로 올려도 마지막 높은포트 번호의 파일로 복구 되기 때문이다.

해결

해결법은 다수의 포트로 구동시 dbfilename 이름을 아래처럼 개별 포트 이름으로 구동 하면된다.

$ vi /etc/redis/reids-6379.conf

dbfilename dump-6379.rdb

$ vi /etc/redis/reids-6380.conf

dbfilename dump-6380.rdb

$ redis-cli

redis 127.0.0.1:6379> SET key "values"
OK
redis 127.0.0.1:6379> get key
"values"
redis 127.0.0.1:6379> 

$ service redis restart

Stopping redis-server with /etc/redis/redis-6379.conf:          [  OK  ]
Stopping redis-server with /etc/redis/redis-6380.conf:     [  OK  ]
Starting redis-server with /etc/redis/redis-6379.conf:          [  OK  ]
Starting redis-server with /etc/redis/redis-6380.conf:     [  OK  ]

$ redis-cli

redis 127.0.0.1:6379> get key
"values"
redis 127.0.0.1:6379> 

$ (echo -en "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379

+PONG
+PONG
+PONG


RedHatEnterpriseLinux7

Hostname 변경하기

hostnamectl
$ hostnamectl set-hostname vozlt.com

관련 파일
/etc/hostname

cloud-init 사용시: 맨아래에 내용 추가
$ sudo vim /etc/cloud/cloud.cfg

preserve_hostname: true

Locale 변경하기

현재 Locale 확인
localectl

   System Locale: LANG=en_US.UTF-8
       VC Keymap: us
      X11 Layout: us

Locale 리스트
localectl list-locales

aa_DJ
aa_DJ.iso88591
aa_DJ.utf8
aa_ER
aa_ER.utf8
aa_ER.utf8@saaho
aa_ER@saaho
aa_ET
aa_ET.utf8
.
.
.

Locale 설정
localectl set-locale LANG=ko_KR.UTF-8

변경된 Locale 확인

   System Locale: LANG=ko_KR.UTF-8
       VC Keymap: us
      X11 Layout: us

기타



RedHatEnterpriseLinux6

Sysctl.conf 내용 추가

부팅시에 /etc/rc.d/init.d/functions 의 apply_sysctl() 함수를 /etc/rc.d/rc.sysinit 에서 호출 하는데 아래와 같다.

# Apply sysctl settings, including files in /etc/sysctl.d
apply_sysctl() {
    sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
    for file in /etc/sysctl.d/* ; do
        is_ignored_file "$file" && continue
        test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
    done
}

/etc/sysctl.conf 호출후 /etc/sysctl.d/* 를 읽어 들이기 때문에 /etc/sysctl.d/{name}.conf 식으로 작성해두면 된다. 재시작 시점 부터 적용된다.
$ mkdir /etc/sysctl.d
$ vi /etc/sysctl.d/00_my.conf

# listen() 함수의 backlog 가 somaxconn 보다 크면 listen() 의 backlog는 somaxconn 으로 설정 된다. 
net.core.somaxconn = 65536

Static Routes and the Default Gateway

리부팅시에도 적용 되도록 ”’/etc/sysconfig/network-scripts/route-{interface}”’ 에 추가
$ vi /etc/sysconfig/network-scripts/route-eth0

default via 10.10.10.1 dev eth0
10.0.0.0/8 via 10.10.10.1 dev eth0
192.168.0.0/24 via 10.10.10.1 dev eth0

네트워크 재시작
$ service network restart

$ netstat -nr

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
10.0.0.0        10.10.10.1      255.0.0.0       U         0 0          0 eth0
192.168.0.0     10.10.10.1      255.255.255.0   U         0 0          0 eth0
0.0.0.0         10.10.10.1      0.0.0.0         UG        0 0          0 eth0

기타



Ps

프로세스 리스트 전체 출력

$ ps -efl --forest

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S root      1002     1  0  80   0 - 16029 poll_s Jul18 ?        00:00:17 /usr/sbin/sshd
4 S root     24159  1002  0  80   0 - 23957 unix_s Aug02 ?        00:00:00  \_ sshd: vozlt [priv]
5 S vozlt    24161 24159  0  80   0 - 24257 poll_s Aug02 ?        00:00:43      \_ sshd: vozlt@pts/0
0 S vozlt    24162 24161  0  80   0 - 27083 wait   Aug02 pts/0    00:00:00          \_ -bash
0 S vozlt      481 24162  0  80   0 - 29686 pause  11:06 pts/0    00:00:00              \_ screen -r vozlt0
5 S ntp       1010     1  0  80   0 -  7540 poll_s Jul18 ?        00:00:09 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g
4 S root      1725     1  0  80   0 - 19682 ep_pol Jul18 ?        00:00:12 /usr/libexec/postfix/master
4 S postfix   1734  1725  0  80   0 - 19744 ep_pol Jul18 ?        00:00:01  \_ qmgr -l -t fifo -u
4 S postfix   2003  1725  0  80   0 - 20236 ep_pol 16:29 ?        00:00:00  \_ pickup -l -t fifo -u

옵션 설명

  • –forest
    • 프로세스 트리 형식으로 출력

프로세스 리스트 출력(쓰레드)

$ ps -eflL

F S UID        PID  PPID   LWP  C NLWP PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S root       913     1   913  0    4  80   0 - 62368 poll_s Jul18 ?        00:00:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
1 S root       913     1   914  0    4  80   0 - 62368 futex_ Jul18 ?        00:00:06 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
1 S root       913     1   916  0    4  80   0 - 62368 poll_s Jul18 ?        00:00:06 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
5 S root       913     1   917  0    4  80   0 - 62368 syslog Jul18 ?        00:00:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5

프로세스 사용자 정의 출력

$ ps -eo user,pid,ppid,pcpu,pmem,tty,vsz,rss,size,bsdtime,stime,cmd --sort=-vsz,-rss,-pcpu

USER       PID  PPID %CPU %MEM TT          VSZ   RSS    SZ   TIME STIME CMD
nobody   10245 21161  0.0  7.5 ?        442236 77436 47804   0:51 Aug20 php-fpm: pool www
nobody   10145 21161  0.0  7.4 ?        442028 76276 47580   0:55 Aug20 php-fpm: pool www
root     21161     1  0.0  1.1 ?        404392 11236 12032   1:23 Aug07 php-fpm: master process (/etc/php.d/php-fpm.ini)
root       913     1  0.0  0.4 ?        249472  4708 228212   0:12 Jul18 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5

출력 필드별 설명

코드        헤더        설명

user        USER        사용자이름
pid         PID         프로세스ID
ppid        PPID        부모프로세스ID
pcpu        %CPU        CPU 사용률
pmem        %MEM        물리적 메모리 사용률
tty         TT          터미널
vsz         VSZ         가상 메모리 크기(단위: KB)
rss         RSS         물리 메모리 크기(단위: KB)
size        SZ          스왑 공간 크기(실제 페이지 영역에 쓸 공간이 없다면 옮겨지게되는:/proc/${PID}/status:VmData+VmStk)
bsdtime     TIME        누적된 CPU 시간(user + system)
stime       STIME       프로세스 시작 시간
cmd         CMD         인자를 포함하는 명령

옵션 설명

  • –sort=-vsz,-rss,-pcpu
    • 가상메모리크기,물리메모리크기,CPU사용률이 큰 것부터 출력한다.

기타

pmap

$ pmap -x {PIDS}



Postfix

메일 보내기

$ (echo -en "Content-Type: text/html; charset=\"utf-8\"\r\nSubject: 제목\r\nTo: 받은사람@받을주소\r\n내용"; sleep 1) | sendmail -v 받는사람@받을주소



PerlExamples

구분자로 배열 리턴시 빈값은 제거하기

#! /usr/bin/perl

my $var = '/root:/tmp:/home:/proc::/sys:::::/dev';
my @array = split(':', $var);

for (0..$#array) {
    print "\$array[$_]: $array[$_]\n";
}
print "\n";
# same: @array = grep m/\S/, split(':', $var);
@array = grep {/\S/} split(':', $var);
for (0..$#array) {
    print "\$array[$_]: $array[$_]\n";
}
$array[0]: /root
$array[1]: /tmp
$array[2]: /home
$array[3]: /proc
$array[4]:
$array[5]: /sys
$array[6]:
$array[7]:
$array[8]:
$array[9]:
$array[10]: /dev

$array[0]: /root
$array[1]: /tmp
$array[2]: /home
$array[3]: /proc
$array[4]: /sys
$array[5]: /dev

Perl Daemonize 예제

#! /usr/bin/perl

use POSIX;

local $| = 1; # autoflush

# daemonize run
daemonize();

# 데몬화후 구문들...
while(1) {
 sleep(1);
}

# perl daemonize function
sub daemonize {
    my $_PATH_DEVNULL = "/dev/null";

    my $pid = fork();
    if ($pid > 0) {
        exit(0);
    }
    umask(0);

    POSIX::setsid() or die "POSIX::setsid() : $!";
    chdir('/') or die "chdir() : $!";
    open(STDIN, '/dev/null') or die "STDIN : $!";
    open(STDOUT, '>>/dev/null') or die "STDOUT : $!";
    open(STDERR, '>>/dev/null') or die "STDERR : $!";
}

함수 인자에 배열값 전달

#! /usr/bin/perl

sub array_ref {
    # same: $listp = \@{shift()};
    # same: $listp = shift;
    my $listp = \@{$_[0]};

    my $count = $#$listp;

    for(0..$count){
        print "\$listp->[$_]: " . $listp->[$_] . "\n";
    }

    # same: @list = @$listp
    # same: @list = @{$_[0]};
    my @list = @{shift()};

    print "\$list[$_]: " . $list[$_] . "\n" for(0..$count);
}

my @a = ('one', 'two', 'three', 'four', 'five');
array_ref(\@a);
$listp->[0]: one
$listp->[1]: two
$listp->[2]: three
$listp->[3]: four
$listp->[4]: five
$list[0]: one
$list[1]: two
$list[2]: three
$list[3]: four
$list[4]: five

배열 레퍼런스 만들기

$self->{deny_method} = ["PUT", "TEST"];

해쉬 래퍼런스 만들기

$self->{deny_method} = {"PUT" => 0, "TEST" => 1};

레퍼런스를 배열에 대입하기

my @dm = @{$self->{deny_method}};

래퍼런스를 해쉬에 대입하기

my %dm = %{$self->{deny_method}};
%srvlist = ( $self->{_srvlist} ) ? %{$self->{_srvlist}} : $self->getSrvlist($_c->{srvfile});

Command Line Options



NginxBasicAuth

개요

Basic HTTP 인증

인증 정보

  • 웹루트
    • /home/httpd/vhosts/auth.example.com
  • 인증 절대 경로
    • /home/httpd/vhosts/auth.example.com/auth
  • 인증 접근 URL

Nginx 설정(인증+자동 디렉토리 리스팅)

서버 설정 편집
$ vi /etc/nginx/site-enabled/vhost.conf

server {
    server_name auth.example.com;
    root /home/httpd/vhosts/auth.example.com;

    location /auth {
        auth_basic              "Restricted";
        auth_basic_user_file    $document_root/auth/.htpasswd;
    }
    autoindex on;
    autoindex_exact_size off;
    autoindex_localtime on;
}

htpasswd 설정

.htpasswd 추가 형식

{사용자}:{해쉬된 패스워드}:{설명}

.htpasswd 에 계정 추가

$ echo user1:$(openssl passwd -crypt pwd1234) >> /home/httpd/vhosts/auth.example.com/auth/.htpasswd
$ echo user2:$(openssl passwd -crypt pwd1234):comment >> /home/httpd/vhosts/auth.example.com/auth/.htpasswd

.htpasswd 권한 설정

$ chown root:nobody /home/httpd/vhosts/auth.example.com/auth/.htpasswd
$ chmod 640 /home/httpd/vhosts/auth.example.com/auth/.htpasswd

.htpasswd 추가 확인

$ cat /home/httpd/vhosts/auth.example.com/auth/.htpasswd

user1:DuBYtO9mSH05w
user2:22rSfOA5sGDCE:comment

설명

  • 사용자:user1, 패스워드:pwd1234 로 계정 생성
  • 사용자:user2, 패스워드:pwd1234, 설명:comment 로 계정 생성

Nginx 재시작

$ service nginx restart



Wednesday, April 27, 2016

NfsFirewallConfig

개요

NFS 서버에서 rpcbind 프로그램은 동적으로 port를 할당해서 사용하는데 방화벽 뒤에서 사용하기 위해서는 해당 포트를 고정적으로 변경후 ACL을 설정 하는 것이 수월하다.

NFS 서버 설치

$ yum install nfs-utils nfs-utils-lib
$ chkconfig nfs on
$ service rpcbind start
$ service nfs start

NFS 서버 설정

$ vi /etc/exports

/home /nfs          10.10.10.111(rw,sync,no_root_squash,no_subtree_check)

$ exportfs -a

/etc/sysconfig/nfs 편집

사용할 포트 번호 기입

$ vi /etc/sysconfig/nfs

MOUNTD_PORT=4000
STATD_PORT=4001
LOCKD_TCPPORT=4002
LOCKD_UDPPORT=4003

NFS 재시작

$ service nfs restart

포트 확인

$ rpcinfo -p

[root@mirror sysconfig]# rpcinfo -p
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100005    1   udp   4000  mountd
    100005    1   tcp   4000  mountd
    100005    2   udp   4000  mountd
    100005    2   tcp   4000  mountd
    100005    3   udp   4000  mountd
    100005    3   tcp   4000  mountd
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    2   tcp   2049  nfs_acl
    100227    3   tcp   2049  nfs_acl
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    2   udp   2049  nfs_acl
    100227    3   udp   2049  nfs_acl
    100021    1   udp   4003  nlockmgr
    100021    3   udp   4003  nlockmgr
    100021    4   udp   4003  nlockmgr
    100021    1   tcp   4002  nlockmgr
    100021    3   tcp   4002  nlockmgr
    100021    4   tcp   4002  nlockmgr

ACL 설정

/etc/sysconfig/nfs 에서 지정한 포트로 ACL 설정

서비스 포트 프로토콜
NFS 2049 tcp/udp
PORTMAP 111 tcp/udp
MOUNTD 4000 tcp/udp
STATD 4001 tcp/udp
LOCKD 4002 tcp
LOCKD 4003 udp

기타



Iptables

PREROUTING, OUPUT, POSTROUTING

enter image description here

외부에서 {IP:PORT} 로 오는 패킷을 {IP:PORT} 로

10.10.10.44:80 로 오는 모든 패킷을 16.16.16.16:8080 으로 보내기

$ iptables -A PREROUTING -t nat -p tcp -m tcp -i eth2 -d 10.10.10.44 --dport 80 -j DNAT --to 16.16.16.16:8080

로컬에서 {IP:PORT} 로 오는 패킷을 {IP:PORT} 로

10.10.10.44:80 로 오는 모든 패킷을 16.16.16.16:8080 으로 보내기

$ iptables -A OUTPUT -t nat -p tcp -m tcp -i eth2 -d 10.10.10.44 --dport 80 -j DNAT --to 16.16.16.16:8080

참고

NAT - Network Address Translation



GlusterFS

GlusterFS 구축하기
@문서 작성일 : 2013/02/04
@문서 수정일 : 2013/02/04
@문서 작성자 : YoungJoo.Kim(vozltx@gmail.com)



1. 개요
1.1. GlusterFS 란?
1.2. 구축 시나리오
1.3. 용어들
2. GlusterFS 서버 구성하기
2.1. 패키지 설치 & brick1/{vol0, vol1} 디렉토리 생성
2.2. Gluster pool 등록
2.3. Gluster pool 등록 확인
2.4. Gluster Volume 생성
2.5. 기타 사항
2.5. Gluster Volume 생성 확인
2.6. Gluster Volume 사용 시작
2.7. Gluster Volume 사용 시작 확인
2.8. Gluster Volume ACL 설정
2.9. Client 에서 Gluster Volume 마운트
3. GlusterFS Volume 확장(brick 추가)
3.1. Gluster brick 추가
3.2. Gluster volume Rebalancing
3.3. Gluster volume Rebalancing 상태 확인
4. GlusterFS brick 교체
4.1. 신규 장비 pool 등록
4.2. 신규 장비 기존 volume 에 추가
4.3. 기존 장비 volume 에서 제거 시작
4.4. 제거 상태 확인
4.5. 기존 장비 volume 에서 제거 완료
4.6. 기존 장비 volume 에서 제거 확인
4.7. 기존 장비 pool 에서 제거
5. GlusterFS Geo-replication
5.1. Geo-replication 시작
5.2. Geo-replication 상태 확인
5.3.  에러등으로 인한 재 동기화시
5.4. 기타사항
6. GlusterFS volume 제거
5.1. volume 정지
5.2. volume 제거


1. 개요



1.1. GlusterFS 란?



GlusterFS 란 수천 PetaByte 급의 대용량에, 수천 개의 클라이언트가 접속하여 사용가능한 scale-out 방식의 분산 파일 시스템이다.
GlusterFS is a powerful network/cluster filesystem written in user space which uses FUSE to hook itself with VFS layer. GlusterFS takes a layered approach to the file system, where features are added/removed as per the requirement. Though GlusterFS is a File System, it uses already tried and tested disk file systems like ext3, ext4, xfs, etc. to store the data. It can easily scale up to petabytes of storage which is available to user under a single mount point.


1.2. 구축 시나리오



총 6대의 서버에 한개의 디스크 파티션에 두개의 볼륨을 생성한다. 볼륨 생성(Distributed Volume)후 brick 의 추가 그리고 마이그레이션 및 geo-replication 을 테스트 한다.


Server
Volume
Volume Type
Version
FileSystem
OS
Arch
ts[1-6].vozlt.com
/brick1/vol0
Distributed Volume
3.3.1
XFS
CentOS 6.3
64bit
ts[1-6].vozlt.com
/brick1/vol1
Distributed Volume
3.3.1
XFS
CentOS 6.3
64bit


포맷 옵션


shell> mkfs.xfs -b size=4096 -d sunit=512,swidth=4096 -L gluster /dev/sdb1

1.3. 용어들



brick
The brick is the storage filesystem that has been assigned to a volume.
client
The machine which mounts the volume (this may also be a server).
server
The machine (virtual or bare metal) which hosts the actual filesystem in which data will be stored.
subvolume
a brick after being processed by at least one translator.
volume
The final share after it passes through all the translators.


2. GlusterFS 서버 구성하기



2.1. 패키지 설치 & brick1/{vol0, vol1} 디렉토리 생성



ts[1-2].vozlt.com 서버에 패키지 설치(glusterfs-server, glusterfs-geo-replication) 및 volume 을 구성할 디렉토리를 생성한다.


shell> vi install_package.sh

#! /bin/sh
for i in {1..6}
do
ssh ts$i.vozlt.com "yum install glusterfs-server glusterfs-geo-replication -y; \
/etc/init.d/glusterd start; \
chkconfig glusterd on; \
mkdir -p /brick1/{vol0,vol1};
done

shell> sh install_package.sh


2.2. Gluster pool 등록



shell> gluster peer probe ts2.vozlt.com
shell> gluster peer probe ts3.vozlt.com
shell> gluster peer probe ts4.vozlt.com
shell> gluster peer probe ts5.vozlt.com
shell> gluster peer probe ts6.vozlt.com


2.3. Gluster pool 등록 확인



shell> gluster peer status

Number of Peers: 5

Hostname: ts2.vozlt.com
Uuid: c2f6b805-3090-47f9-8106-bb9318bd5a81
State: Peer in Cluster (Connected)

Hostname: ts3.vozlt.com
Uuid: 4a49c4c5-44f2-4639-ab10-a56cce92bee8
State: Peer in Cluster (Connected)

Hostname: ts4.vozlt.com
Uuid: 886498cf-e2b9-44ef-8ab4-ef4a4fbd5683
State: Peer in Cluster (Connected)

Hostname: ts5.vozlt.com
Uuid: 8c31ebd7-33e9-4cd8-a61d-cde718820678
State: Peer in Cluster (Connected)

Hostname: ts6.vozlt.com
Uuid: 0833bc54-8fdc-46d1-b665-1cbafde3c98e
State: Peer in Cluster (Connected)

2.4. Gluster Volume 생성



shell> gluster volume create vol0 ts1.vozlt.com:/brick1/vol0 \
ts2.vozlt.com:/brick1/vol0 \
ts3.vozlt.com:/brick1/vol0 \
ts4.vozlt.com:/brick1/vol0 \
ts5.vozlt.com:/brick1/vol0 \
ts6.vozlt.com:/brick1/vol0

shell> gluster volume create vol1 ts1.vozlt.com:/brick1/vol1 \
ts2.vozlt.com:/brick1/vol1 \
ts3.vozlt.com:/brick1/vol1 \
ts4.vozlt.com:/brick1/vol1 \
ts5.vozlt.com:/brick1/vol1 \
ts6.vozlt.com:/brick1/vol1


2.5. 기타 사항



에러
볼륨 생성시 아래의 메시지 출력시 기존에 생성 되었던 볼륨이므로 자료 정리(삭제)와 상관 없이 파일에 확장 속성이 걸려 있기 때문에 발생하는 에러이다. (kernel 2.6 에서 부터 파일에 확장 속성을 기록 할 수 있다.)


/brick1/vol0 or a prefix of it is already part of a volume


해결책
아래 명령어으로 확장 속성을 해제 한후 volume create 를 실행 한다.


shell> cd /brick1/vol0
shell> for i in `attr -lq .`; do setfattr -x trusted.$i .; done

2.5. Gluster Volume 생성 확인



shell> gluster volume info all

Volume Name: vol0
Type: Distribute
Status: Created
Number of Bricks: 6
Transport-type: tcp
Bricks:
Brick1: ts1.vozlt.com:/brick1/vol0
Brick2: ts2.vozlt.com:/brick1/vol0
Brick3: ts3.vozlt.com:/brick1/vol0
Brick4: ts4.vozlt.com:/brick1/vol0
Brick5: ts5.vozlt.com:/brick1/vol0
Brick6: ts6.vozlt.com:/brick1/vol0

Volume Name: vol1
Type: Distribute
Status: Created
Number of Bricks: 6
Transport-type: tcp
Bricks:
Brick1: ts1.vozlt.com:/brick1/vol1
Brick2: ts2.vozlt.com:/brick1/vol1
Brick3: ts3.vozlt.com:/brick1/vol1
Brick4: ts4.vozlt.com:/brick1/vol1
Brick5: ts5.vozlt.com:/brick1/vol1
Brick6: ts6.vozlt.com:/brick1/vol1


2.6. Gluster Volume 사용 시작



shell> gluster volume start vol0
shell> gluster volume start vol1


2.7. Gluster Volume 사용 시작 확인



shell> gluster volume info all

Volume Name: vol0
Type: Distribute
Status: Started
Number of Bricks: 6
Transport-type: tcp
Bricks:
Brick1: ts1.vozlt.com:/brick1/vol0
Brick2: ts2.vozlt.com:/brick1/vol0
Brick3: ts3.vozlt.com:/brick1/vol0
Brick4: ts4.vozlt.com:/brick1/vol0
Brick5: ts5.vozlt.com:/brick1/vol0
Brick6: ts6.vozlt.com:/brick1/vol0

Volume Name: vol1
Type: Distribute
Status: Started
Number of Bricks: 6
Transport-type: tcp
Bricks:
Brick1: ts1.vozlt.com:/brick1/vol1
Brick2: ts2.vozlt.com:/brick1/vol1
Brick3: ts3.vozlt.com:/brick1/vol1
Brick4: ts4.vozlt.com:/brick1/vol1
Brick5: ts5.vozlt.com:/brick1/vol1
Brick6: ts6.vozlt.com:/brick1/vol1


2.8. Gluster Volume ACL 설정



shell> gluster volume set vol0 auth.allow 10.*
shell> gluster volume set vol1 auth.allow 10.*


2.9. Client 에서 Gluster Volume 마운트



shell> yum install glusterfs-fuse
shell> mkdir -p /mnt/gluster/{vol0,vol1}
shell> mount -t glusterfs ts1.vozlt.com:vol0 /mnt/gluster/vol0
shell> mount -t glusterfs ts1.vozlt.com:vol1 /mnt/gluster/vol1

3. GlusterFS Volume 확장(brick 추가)





기존에 ts[1-6].vozlt.com 구성에 ts7.vozlt.com 을 추가하여 volume 를 확장하는 과정이다.

3.1. Gluster brick 추가



shell> gluster peer probe ts7.vozlt.com
shell> gluster volume add-brick vol0 ts7.vozlt.com:/brick1/vol0
shell> gluster volume add-brick vol1 ts7.vozlt.com:/brick1/vol1


3.2. Gluster volume Rebalancing



shell> gluster volume rebalance vol0 start
shell> gluster volume rebalance vol1 start


3.3. Gluster volume Rebalancing 상태 확인



shell> gluster volume rebalance vol0 status
shell> gluster volume rebalance vol1 status

4. GlusterFS brick 교체





기존에 ts1.vozlt.com 의 brick 을 신규 장비(ts7.vozlt.com)로 마이그레이션 하는 과정이다. 3.3.0 이상부터는 brick 의 교체 방식이 이전과 다른 방식을 사용하며 여기서는 Distributed Volume 에 대한 교체만 설명 한다. 이전버전과 변경된 자세한 내용은 아래 내용을 참조 하기 바란다.


4.1. 신규 장비 pool 등록



shell> gluster peer probe ts7.vozlt.com


4.2. 신규 장비 기존 volume 에 추가



shell> gluster volume add-brick vol0 ts7.vozlt.com:/brick1/vol0
shell> gluster volume add-brick vol1 ts7.vozlt.com:/brick1/vol1


4.3. 기존 장비 volume 에서 제거 시작



shell> gluster volume remove-brick vol0 ts1.vozlt.com:/brick1/vol0 start
shell> gluster volume remove-brick vol1 ts1.vozlt.com:/brick1/vol1 start


4.4. 제거 상태 확인



상태가 in progress 에서 completed 로 변경되면 기존 서버(ts1.vozlt.com)의 자료는 모두 신규 장비로 이전 완료 된 상태이다.


shell> gluster volume remove-brick vol0 ts1.vozlt.com:/brick1/vol0 status
       Node Rebalanced-files          size       scanned      failures         status
  ---------      -----------   -----------   -----------   -----------   ------------
 ts1.vozlt.com                1        7Bytes             3             0      completed
 ts2.vozlt.com                0        0Bytes             0             0    not started
 ts3.vozlt.com                0        0Bytes             0             0    not started
 ts4.vozlt.com                0        0Bytes             0             0    not started
 ts5.vozlt.com                0        0Bytes             0             0    not started
 ts6.vozlt.com                0        0Bytes             0             0    not started
 ts7.vozlt.com                0        0Bytes             0             0    not started


4.5. 기존 장비 volume 에서 제거 완료



shell> gluster volume remove-brick vol0 ts1.vozlt.com:/brick1/vol0 commit
shell> gluster volume remove-brick vol1 ts1.vozlt.com:/brick1/vol1 commit


4.6. 기존 장비 volume 에서 제거 확인



shell> gluster volume info vol0

Volume Name: vol0
Type: Distribute
Volume ID: 7c20dffd-2f1d-45d8-b610-1f1926cca552
Status: Started
Number of Bricks: 6
Transport-type: tcp
Bricks:
Brick2: ts2.vozlt.com:/brick1/vol0
Brick3: ts3.vozlt.com:/brick1/vol0
Brick4: ts4.vozlt.com:/brick1/vol0
Brick5: ts5.vozlt.com:/brick1/vol0
Brick6: ts6.vozlt.com:/brick1/vol0
Brick7: ts7.vozlt.com:/brick1/vol0


4.7. 기존 장비 pool 에서 제거



shell> gluster peer detach ts1.nwz.kr


5. GlusterFS Geo-replication





LAN, WAN 구간에서 서버간에 비동기 방식의 동기화를 제공하는 기능이다. slave 서버는 GlusterFS volume 이 구성되어 있지 않은 서버라도 상관 없다. 구성후에는 Master 에서 Slave 로 실시간 동기화가 이루어 지며 indexing 을 사용하기 때문에 Slave 서버의 정지시 완벽한 재동기화를 위해서는 옵션 geo-replication.indexing 을 off 후 재 동기화 해야 한다.


Master, Slave 서버는 아래와 같이 정의 된다.


Master
GlusterFS volume


Slave
Local Directory:
file:///path/to/dir (단축형: /path/to/dir)
GlusterFS Volume:
gluster://slave.vozlt.com:volname
(단축형: slave.vozlt.com:volname)
SSH:
ssh://root@slave.vozlt.com:/path/to/dir
(단축형: root@slave.vozlt.com:/path/to/dir)
ssh://root@slave.vozlt.com:gluster://localhost:volname
(단축형: root@slave.vozlt.com::volname)


Example
x : gluster volume geo-replication vol0 slave.vozlt.com:/vol0 start
o : gluster volume geo-replication vol0 slave.vozlt.com:vol0 start
o : gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol0 start
o : gluster volume geo-replication vol0 ssh://root@slave.vozlt.com::vol0 start
o : gluster volume geo-replication vol0 root@slave.vozlt.com:/path/to/dir/ start


기본 환경 구성
- 시간 동기화
Master, Slave 모두 ntp 등을 이용하여 시간 동기화는 꼭 해주어야 한다.


- SSH 사용을 위한 구성(gluster:// 프로토콜 사용시 불필요)
SSH 프로토콜 사용시 Master 서버에서 와 Slave 서버간 통신을 위해 아래와 같은 키 생성 과정이 필요하다.
slave 서버의 타켓은 volume 이거나 일반적인 디렉토리가 될 수 있고 volume 을 구성하지 않고 일반적인 디렉토리에 replication을 수행 하더라도 glusterd 데몬은 구동 되어야 한다.


shell> yum install glusterfs-server
shell> service glusterd start
shell> chkconfig glusterd on
shell> ssh-keygen -f /var/lib/glusterd/geo-replication/secret.pem
shell> ssh-copy-id -i /var/lib/glusterd/geo-replication/secret.pem.pub user@slave.vozlt.com


보안
원격 명령에 대한 제한이나 mountbroker 및 IP 기반의 접근 제어등은 배포되는 관리문서 를 참조 하길 바란다.

5.1. Geo-replication 시작



shell> gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol0 start


5.2. Geo-replication 상태 확인



shell>  gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol1 status
MASTER               SLAVE                                              STATUS
--------------------------------------------------------------------------------
vol0                 gluster://slave.vozlt.com:vol1                        starting...

shell>  gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol1 status
MASTER               SLAVE                                              STATUS
--------------------------------------------------------------------------------
vol0                 gluster://slave.vozlt.com:vol1                        OK


5.3.  에러등으로 인한 재 동기화시



shell> gluster volume set vol0 geo-replication.indexing off
shell> gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol1 start


5.4. 기타사항



gsyncd 경로 문제
glusterfs-3.3.1 은 gsyncd 의 위치가 /usr/local/libexec/glusterfs/gsyncd 로 하드코딩 되어 있어서 gsyncd 경로 에러시 적절하게 변경 해주어야 한다.(http://review.gluster.org/#change,4392)


해결책
아래처럼 gsyncd 경로를 올바르게 재설정 하거나 Patch0 처럼 패치를 가한후 glusterfs 를 빌드 한다. (혹은 gsyncd.conf 수정)


shell> gluster volume geo-replication vol0 gluster://slave.vozlt.com:vol1 config remote_gsyncd /usr/libexec/glusterfs/gsyncd


Patch0: glusterfs-3.3.1.gsyncd.prefix.patch
diff -urNp glusterfs-3.3.1.org/xlators/mgmt/glusterd/src/glusterd.c glusterfs-3.3.1/xlators/mgmt/glusterd/src/glusterd.c
--- glusterfs-3.3.1.org/xlators/mgmt/glusterd/src/glusterd.c    2012-10-12 02:38:25.000000000 +0900
+++ glusterfs-3.3.1/xlators/mgmt/glusterd/src/glusterd.c    2013-02-06 14:49:22.873156172 +0900
@@ -461,8 +461,8 @@ configure_syncdaemon (glusterd_conf_t *c
        RUN_GSYNCD_CMD;

        runinit_gsyncd_setrx (&runner, conf);
-        runner_add_args (&runner, "remote-gsyncd",
-                         "/usr/local/libexec/glusterfs/gsyncd", ".", "^ssh:", NULL);
+       runner_add_args (&runner, "remote-gsyncd", GSYNCD_PREFIX"/gsyncd", ".", "^ssh:", NULL);
+
        RUN_GSYNCD_CMD;

        /* gluster-command-dir */


6. GlusterFS volume 제거



6.1. volume 정지



shell> gluster volume stop vol0
shell> gluster volume stop vol1


6.2. volume 제거



shell> gluster volume delete vol0
shell> gluster volume delete vol1