Deploying Scalable Oracle RAC on Amazon EC2 の考察

JPOUG Advent Calender 2015(https://jpoug.doorkeeper.jp/events/33345) の6日目
AWS Advent Calendar 2015 (http://qiita.com/advent-calendar/2015/aws) の6日目

のクロスエントリです。


とうとうAWSからOracle RAC on Amazon EC2の手順が公開されました。
Deploying Scalable Oracle RAC on Amazon EC2


ここ数年 Oracle RAC on Amazon EC2を考え続けてきた身としては、言及しないわけにはまいりません。
本当はかっちり検証したいのですが、時間がとれなかったので、チュートリアルから読み取れる内容を記載します。
実際に検証した訳ではないので、記載内容が正しくない場合がありますのでご承知おきください。


まず、Oracle RAC on Amazon EC2を作る上で障害となるのは以下です。



1.publicネットワークのVIP(仮想IP)
EC2のネットワーク(VPC)は物理ネットワークと異なり、AWS側でARPが管理されており、
設定されたIPでしか通信ができません。
OS(RAC)側で勝手にIPを振っても他マシンからそのIPへ通信をすることができないのです。
つまり、VIPのフェールオーバができません。


2.internalネットワークのマルチキャスト
EC2のネットワーク(VPC)は物理ネットワークと異なり、マルチキャストがサポートされていません。
したがって、Oracle RACのinternalネットワーク要件を満たしません。


3.共有ディスク
現時点では、共有ディスクに相当するものは正式に提供されていません。


では、どうやって1〜3をクリアしているか?



1.publicネットワークのVIP(仮想IP)
AWS API(aws ec2 assign-private-ip-addresses)を実行するスクリプトOracle Clusterwareのリソースとして登録しているようです。
Oracle Clusterwareがノードの障害を検知すると、/etc/oracle/ec2_vip_failover.shを実行し、
その延長でaws ec2 assign-private-ip-addressesが呼ばれ、VIP/Scan VIPが障害が発生していないノードに付与されるようです。<該当部分抜粋>

oracle@myracnode01$ crsctl add resource myrac02-vip.ec2 -type cluster_resource -attr "CHECK_INTERVAL=10,\
ACTION_SCRIPT=/etc/oracle/ec2_vip_failover.sh,PLACEMENT=favored,HOSTING_MEMBERS=myracnode01 myracnode02,\
AUTO_START=always,START_DEPENDENCIES=hard(intermediate:ora.myracnode02.vip),RELOCATE_BY_DEPENDENCY=1,\
STOP_DEPENDENCIES=hard(intermediate:ora.myracnode02.vip)"


以前、aws ec2 assign-private-ip-addressesをうまく使って、RACを作れないか検討したことがあるんですが、
リソース登録までは思いつかず断念したことがあるので、ちょっと悔しいです。。。


2.internalネットワークのマルチキャスト
これは、n2nというVPNソフトウェアを使用し、実現しています。
以前、当ブログで紹介したOpenVPN/tincでの実現と基本は変わりません。
iSCSI ノード#1にsupernode(n2n仮想ネットワークの経路情報を持つサーバ)
DB ノード#1,#2がそれぞれn2nクライアントの構成のようです。
n2nは、通信自体はPeer to Peerで行うとされていますので、VPNソフトウェアの中では比較的パフォーマンスが良いようです。
(とは言っても、実ネットワークの半分程度のスループットですが)
https://www.buckhill.co.uk/blog/how-to-enable-broadcast-and-multicast-on-amazon-aws-ec2


3.共有ディスク
iSCSIを用いています。
以前当ブログで紹介した手順と基本は変わりません。
冗長性?を意識しているのかiSCSIサーバを二つ用意しているようです。


では、この構成は実運用に耐えうるのかというと、冗長性が確保できていないような。。。。
(以下ちょっと自信がないんので、ツッコミお待ちしてます)



n2n・・・・ iSCSI ノード#1がsupernodeであるため、このサーバに障害が起きるとn2nの仮想ネットワーク全体に影響がでるため、ここが単一障害点となると思います。
(n2nは詳しくないので、自信ないですが、、、、)


iSCSI・・・・ 2台構成ではダメなハズです。
Oracle Clusterwareファイルの場合、3つのディスク・デバイスまたは3つの障害グループが標準冗長性のディスク・グループの最小要件です。」(マニュアル抜粋)
なので、3つの障害グループを2つのiSCSIサーバに構成するとなると2,1の分け方になり、2つの障害グループを割り当てたiSCSIサーバに障害が発生すると
Oracle Clusterwareは稼働できません。
2つの障害グループを割り当てたiSCSIサーバが単一障害点になると思います。



以上、実運用には対障害性でもう一歩と言う気がしますが、
AWS API(aws ec2 assign-private-ip-addresses)を実行するスクリプトOracle Clusterwareのリソースの組み合わせは
かなり面白いアイデアなので、もう少し良い構成がないか検討したいなーと思います。

CentOS7でxrdpを使う

CentOS7でxrdp(+Xfce )を使う手順メモ

sudo yum -y install epel-release
#sudo yum -y group install "GNOME Desktop"
sudo yum -y --enablerepo=epel groupinstall Xfce
sudo yum -y install xrdp
sudo systemctl enable xrdp

#https://bugzilla.redhat.com/show_bug.cgi?id=1177202
sudo chcon -t bin_t /usr/sbin/xrdp /usr/sbin/xrdp-sesman

#http://hiroom2.jimdo.com/2015/06/13/xrdp%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95/#sec-3-2

cat > ~/.Xclients <<EOF
#!/bin/bash
exec xfce4-session
EOF
chmod +x ~/.Xclients

Oracle RAC on Docker 解説

記事の内容と直接関係しませんが、まずは、宣伝から


************************
まだ席に余裕がありますので、興味ある方は是非
JPOUG> SET EVENTS 20151017
https://jpoug.doorkeeper.jp/events/30023


夜会(懇親会)もまだ席に余裕があります
https://jpoug.doorkeeper.jp/events/31847
***********************



以前公開したRAC on Docker ですが、
イメージ公開するだけ公開して解説してなかったので、技術的(というかハマりどころ)を記載します。


ちょっと前(docker-1.6)時点で検証したときの情報ですが、現時点でもあまり変わってないと思います。


・共有ディスク
→loopデバイス(/dev/loopXX)を共有デバイスとして使用可能


・ネットワーク
netns機能を使用
参考URL
http://enakai00.hatenablog.com/entry/20140424/1398321672


・AUFSは使わない
AUFSを使うとAlertログが上手く出力されないようなので、aufsは使わない


・getty無効化
コンテナを --privileged=true /sbin/init で起動すると getty/agettyがCPU100%で張り付いてしまいます。
今回の手順では、getty/agettyを無効化しています。


・コンテナ内では直接hostsファイルを弄れない
コンテナ内では直接hostsファイルを弄れないようなので、ローカルにdnsmasqを立てて、そこを参照しています

参考URL
https://github.com/yasushiyy/vagrant-docker-oracle12c-rac


・コンテナ内では、/dev/shm が64MBで固定されている
/dev/shmをマウントしなおせば回避できるので、/dev/shmをマウントしなおすinitscriptを書いて対応しています。

RHEL6/CentOS6/OEL6/Amazon Linuxでvxlanを使う際の注意点

iproute2が最新のカーネルに対応した影響なのか、
RHEL6/CentOS6/OEL6/Amazon Linuxにて
iproute2をソースから持ってきてそのままmakeするとエラーになってしまうようになりました。
v3.17.0 でcheckout すれば良いようなので、記録として残しておきます。



git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
git checkout v3.17.0
./configure
make
make DESTDIR=/usr/share install

RAC on Docker イメージ公開しました

RAC on Docker の手順がある程度確立できたので、Docker image と手順を公開します。
CentOS7/docker-1.5 ubuntu 14.04/docker-1.5,docker-1.6で動作確認しています

なお、コンテナ内で設定できない、RAC要件のカーネルパラメータ(net.core.rmem_default等)が存在するため、今回の手順では -ignoreSysPrereqs -ignorePrereq 付きでインストールします。(要するに動作保証されていません)


https://github.com/s4ragent/rac_on_docker


ベースはOracleLinux7です。

コンテナ番号 コンテナ名(ホスト名) eth0(nouse) eth1(public) eth2(private)
1 node001 172.17.xx.xx 192.168.0.51 192.168.100.51
2 node002 172.17.xx.xx 192.168.0.52 192.168.100.52


<手順>
・gitをインストールしておきます
(Debian/ubuntu apg-get install git、CentOS,OracleLinux yum install git)
Oracleソフトウェアをダウンロードして/docker/mediaに配置します


#mkdir -p /docker/media
#unzip linuxamd64_12102_database_1of2.zip -d /docker/media
#unzip linuxamd64_12102_database_2of2.zip -d /docker/media
#unzip linuxamd64_12102_grid_1of2.zip -d /docker/media
#unzip linuxamd64_12102_grid_2of2.zip -d /docker/media


#ls -al /docker/media
total 16
drwxr-xr-x 4 root root 4096 May 1 21:56 .
drwxr-xr-x 3 root root 4096 May 1 21:53 ..
drwxr-xr-x 7 root root 4096 Jul 7 2014 database
drwxr-xr-x 7 root root 4096 Jul 7 2014 grid


・create_racbase.sh を実行します(必要に応じてパッケージ(docker含む)がインストールされます)

#git clone http://github.com/s4ragent/rac_on_docker/
#cd rac_on_docker
#bash create_racbase.sh all_in_one


これだけで、とりあえず Oracle RAC on Dockerが動きます。


※5/3 追記

インストール後、コンテナ1を停止したい場合
#bash create_racbase.sh stopnode 1


その後、コンテナ1を起動したい場合、
#bash create_racbase.sh startnode 1


ホストをリブート後、再度すべてのコンテナを起動したい場合
#bash create_racbase.sh startall


詳しい解説は後日

RAC on Docker

とりあえず、RAC on Dockerが動いたので記念に
手順はそのうち公開します。

(EC2) vxlanを使ったDockerコンテナ仮想ネットワークオーバーレイ

SoftLayer Summitにて
「DockerとOpenVNetを用いたSoftLayer VLAN上への仮想ネットワークオーバーレイ」
http://www.slideshare.net/cloudconductor/softlayer-summit-2015
を見て、Dockerの仮想ネットワークオーバーレイに興味を持ちました。
似たようなことをvxlan使ってできないかなーと思っていたところに
「Connecting Docker containers between VMs with VXLAN」
http://blog.thestateofme.com/2014/06/08/connecting-docker-containers-between-vms-with-vxlan/
という記事を見つけたので、unicast vxlanを使ってEC2上でDockerコンテナのオーバーレイネットワーク
を実現してみます。


今回の構成は以下の通りです。
(後で自分で使いそうなAmazon Linux/ubuntu/CentOSを網羅する為に、以下の構成になってます)

ホスト名 OS(カーネル ローカルIP 実インターフェース brigde用IP コンテナ用IP
A Amazon linux 2014.09.2.x86_64(3.14.27-25.47.amzn1.x86_64) 172.31.2.203 eth0 192.168.0.11 192.168.0.101
B ubuntu-trusty-14.04-amd64-server-20150123 (3.13.0-44-generic) 172.31.15.69 eth0 192.168.0.12 192.168.0.102
C CentOS 7 x86_64 (2014_09_29) EBS (3.10.0-123.8.1.el7.x86_64) 172.31.4.212 eth0 192.168.0.13 192.168.0.103


ハマりどころとして、brigde fdb append にて自ホストIPアドレスを追加してしまうと
コンテナが他ホスト/コンテナと上手く通信できなくなりますので注意をしてください。


★ブリッジ+vxlanインターフェース作成

###nodeA 172.31.2.203 amazon linux###

sudo su -
yum -y install git bison flex libdb-devel db4-devel gcc docker bridge-utils
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
cd iproute2
./configure
make
make DESTDIR=/usr/share install

service docker start
chkconfig docker on

#delete docker0,vxlan10 if exists
/usr/share/sbin/ip link set docker0 down
brctl delbr docker0
/usr/share/sbin/ip link del vxlan10

#add docker brigde interface
brctl addbr docker0
#create virtual mac addr ref by http://d.ballade.jp/2008/03/vif-and-mac-address.html
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
/usr/share/sbin/ip link set docker0 address $vmac
/usr/share/sbin/ip address add 192.168.0.11/24 dev docker0

#add vxlan interface
/usr/share/sbin/ip link add vxlan10 type vxlan id 10 ttl 4 dev eth0
#get unique mac addr
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
/usr/share/sbin/ip link set vxlan10 address $vmac


brctl addif docker0 vxlan10
/usr/share/sbin/ip link set vxlan10 up
/usr/share/sbin/ip link set docker0 up

#add other hosts VTEP 
/usr/share/sbin/bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.15.69
/usr/share/sbin/bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.4.212


###nodeB 172.31.15.69 ubuntu###

sudo su -
apt-get -y install docker.io bridge-utils


#delete docker0,vxlan10 if exists
ip link set docker0 down
brctl delbr docker0
ip link del vxlan10

brctl addbr docker0

#create virtual mac addr ref by http://d.ballade.jp/2008/03/vif-and-mac-address.html
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip link set docker0 address $vmac
ip address add 192.168.0.12/24 dev docker0

 
ip link add vxlan10 type vxlan id 10 ttl 4 dev eth0
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip link set vxlan10 address $vmac

brctl addif docker0 vxlan10
ip link set vxlan10 up
ip link set docker0 up

bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.2.203
bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.4.212

###nodeC 172.31.4.212 centos ###

sudo su -

#kernel 3.10.0-123.8.1.el7.x86_64では、unicast vxlan使うとカーネルパニック起こすのでupdate
yum -y update kernel
yum -y install git bison flex libdb-devel db4-devel gcc docker bridge-utils
reboot

#リブート後再ログイン
sudo su -
service docker start
chkconfig docker on

#delete docker0,vxlan10 if exists
ip link set docker0 down
brctl delbr docker0
ip link del vxlan10

brctl addbr docker0
#create virtual mac addr ref by http://d.ballade.jp/2008/03/vif-and-mac-address.html
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip link set docker0 address $vmac
ip address add 192.168.0.13/24 dev docker0

ip link add vxlan10 type vxlan id 10 ttl 4 dev eth0
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip link set vxlan10 address $vmac

brctl addif docker0 vxlan10
ip link set vxlan10 up
ip link set docker0 up

bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.2.203
bridge fdb append 00:00:00:00:00:00 dev vxlan10 dst 172.31.15.69

★コンテナ作成+IPアドレスの割り当て

##nodeA 172.31.2.203 amazon###

gateway=`ip addr show docker0 | grep "inet " | awk -F '[/ ]' '{print $6}'`
id=`sudo docker run -i -t -d --net=none centos /bin/bash`
pid=`docker inspect --format {{.State.Pid}} ${id}`

# 起動したDockerコンテナのprocをnetnsにリンク
mkdir -p /var/run/netns
ln -s /proc/${pid}/ns/net /var/run/netns/${pid}

# vethペアを作成
ip link add veth1b type veth peer name veth1c

# vethペアの一方をovsBridgenに設定し起動
brctl addif docker0 veth1b
ip link set veth1b up

# vethペアの残りの一方をDockerコンテナにセットして起動
ip link set veth1c netns ${pid}
ip netns exec ${pid} ip link set dev veth1c name eth0
ip netns exec ${pid} ip link set eth0 up
#uniqueなMACアドレスをコンテナ内のeth0に割り当て
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip netns exec ${pid} ip link set eth0 address $vmac
#IPアドレスの設定
ip netns exec ${pid} ip addr add 192.168.0.101/24 dev eth0
#ゲートウェイの設定
ip netns exec ${pid} ip route add default via $gateway


###nodeB 172.31.15.69 ubuntu###

gateway=`ip addr show docker0 | grep "inet " | awk -F '[/ ]' '{print $6}'`
id=`sudo docker run -i -t -d --net=none centos /bin/bash`
pid=`docker inspect --format {{.State.Pid}} ${id}`


# 起動したDockerコンテナのprocをnetnsにリンク
mkdir -p /var/run/netns
ln -s /proc/${pid}/ns/net /var/run/netns/${pid}

# vethペアを作成
ip link add veth1b type veth peer name veth1c

# vethペアの一方をovsBridgenに設定し起動
brctl addif docker0 veth1b
ip link set veth1b up

# vethペアの残りの一方をDockerコンテナにセットして起動
ip link set veth1c netns ${pid}
ip netns exec ${pid} ip link set dev veth1c name eth0
ip netns exec ${pid} ip link set eth0 up
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip netns exec ${pid} ip link set eth0 address $vmac
ip netns exec ${pid} ip addr add 192.168.0.102/24 dev eth0
ip netns exec ${pid} ip route add default via $gateway

###nodeC 172.31.4.212 centos ###

gateway=`ip addr show docker0 | grep "inet " | awk -F '[/ ]' '{print $6}'`
id=`sudo docker run -i -t -d --net=none centos /bin/bash`
pid=`docker inspect --format {{.State.Pid}} ${id}`

# 起動したDockerコンテナのprocをnetnsにリンク
mkdir -p /var/run/netns
ln -s /proc/${pid}/ns/net /var/run/netns/${pid}

# vethペアを作成
ip link add veth1b type veth peer name veth1c

# vethペアの一方をovsBridgenに設定し起動
brctl addif docker0 veth1b
ip link set veth1b up

# vethペアの残りの一方をDockerコンテナにセットして起動
ip link set veth1c netns ${pid}
ip netns exec ${pid} ip link set dev veth1c name eth0
ip netns exec ${pid} ip link set eth0 up
vmac=`perl -e  'print sprintf("00:16:3e:%2.2x:%2.2x:%2.2x", rand()*255, rand()*255, rand()*255)'`
ip netns exec ${pid} ip link set eth0 address $vmac
ip netns exec ${pid} ip addr add 192.168.0.103/24 dev eth0
ip netns exec ${pid} ip route add default via $gateway

動作確認
docker attach XX後、、、

[root@6653ad538420 /]# ping 192.168.0.101
PING 192.168.0.101 (192.168.0.101) 56(84) bytes of data.
64 bytes from 192.168.0.101: icmp_seq=1 ttl=64 time=0.023 ms
64 bytes from 192.168.0.101: icmp_seq=2 ttl=64 time=0.034 ms
64 bytes from 192.168.0.101: icmp_seq=3 ttl=64 time=0.032 ms

^C

--- 192.168.0.101 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.023/0.029/0.034/0.007 ms

[root@6653ad538420 /]# ping 192.168.0.102
PING 192.168.0.102 (192.168.0.102) 56(84) bytes of data.
64 bytes from 192.168.0.102: icmp_seq=1 ttl=64 time=0.760 ms
64 bytes from 192.168.0.102: icmp_seq=2 ttl=64 time=0.809 ms
64 bytes from 192.168.0.102: icmp_seq=3 ttl=64 time=0.899 ms
64 bytes from 192.168.0.102: icmp_seq=4 ttl=64 time=0.656 ms

^C

--- 192.168.0.102 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.656/0.781/0.899/0.087 ms

 

[root@6653ad538420 /]# ping 192.168.0.103
PING 192.168.0.103 (192.168.0.103) 56(84) bytes of data.
64 bytes from 192.168.0.103: icmp_seq=1 ttl=64 time=0.969 ms
64 bytes from 192.168.0.103: icmp_seq=2 ttl=64 time=0.536 ms
64 bytes from 192.168.0.103: icmp_seq=3 ttl=64 time=0.596 ms
64 bytes from 192.168.0.103: icmp_seq=4 ttl=64 time=0.606 ms

^C

--- 192.168.0.103 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.536/0.676/0.969/0.173 ms

参考URL
https://docs.docker.com/articles/networking/
http://blog.thestateofme.com/2014/06/08/connecting-docker-containers-between-vms-with-vxlan/
http://qiita.com/nmatsui/items/2fee1d4a526a6ba3c887
http://www.slideshare.net/cloudconductor/softlayer-summit-2015