VMware vCenter Converter Standalone でconvert出来ないsoftware raid(mdadm)のlinuxをddかssh+tarでP2Vする

タイトルの通りvcenter converterではmdadmをsupportしてないのでdeviceを見つけられず、p2v出来ない。

例えば/bootが見つけられなくてエラーが出るなどで。

There is no '/boot' directory mounted on the source machine. 
It is required to create a bootable virtual machine. 
Mount the '/boot' directory on the source machine.

/bootだけ/dev/sda1で他がmdadmだっだとしても、/bootしか見えずにrootが持ってこれないとか。


対処方法はざっくり3つ?
1. cdからresuce bootしてmdadmを削除して物理デバイスをmountするように修正してからconverterを使う
- メンテナンスで停止できるならこっちで良い
2. ddでhddのrawイメージを吸い出し&vmdkに変換して仮想マシンのディスクとして利用する
- ddで読み出すIO負荷、network転送をするので多少影響は出るけど無停止でいける。
- ただし、静止点のようなものは考慮されないので、disk書き込みが続いて、ファイルに差分が出るような場合は
p2v後に別途rsyncや、DBをdump/restoreなどをする必要はある。
3. #パーティション構成が変更になっても良い場合
移行先の仮想マシンをcdブートで起動してdiskを/mnt/sysimageなどでmountしておく
移行元のサーバからssh+tarで移行先のdiskに書き込む

ddでp2v テスト

コピーするのは/dev/sda とする。

hogem.hatenablog.com

基本的には前にkvmで試したこのエントリと同じことをする。

ddでrawイメージで吸い出す

ddを使うので出来上がるファイルサイズ使用量ではなくHDDのサイズと同じになる。

1 network越しに直接remote hostに送る
2. /dev/sda以外でraidにも使用してない別diskをmountしてそこに書き込む
3. nfs mountした場所に書き込む

など。今回は1を使う。
吸い出すHDDの容量+vmdkに変換などを行うので容量に余裕のあるサーバで。

ファイル拾い上げるサーバでnetcatで適当なportでlisten

$ nc -l 10000 > sda.img


吸い出すサーバ
ddをパイプで繋いでnetcatで送信する。

$ dd if=/dev/sda bs=100M | nc remote.server.addr 10000

qemu-img でvmdkに変換

rawイメージのままだとvmwareで使用できないので
適当なlinuxサーバで変換。qemu-imgなかったらyumで入れる。

# yum install qemu-img


qemu-imgに-pつけると進捗が表示される。

$ qemu-img convert -p -f raw sda.img -O vmdk sda.vmdk

あとは出来上がったvmdkを使ってデプロイ。

ssh+tar

p2v先のサーバはcd/isoイメージからlinux rescue sshd でbootする。
(linux rescueだとsshd用の鍵がないので手動で作らないといけない)

diskをmountしておく。(ここでは/mnt/sysimage)
あと、proc, sysなどは実データはなくてsshで送らないのでディレクトリだけ作っておく。

# mkdir /mnt/sysimage
# mount /dev/sda1 /mnt/sysimage
# cd /mnt/sysimage
# mkdir sys dev cgroup srv selinux net proc boot

あとはproc、sysなどの一部パーティションを除外してtarで固めたものをsshで送る



あとはproc、sysなどの一部パーティションを除外してtarで固めたものをsshで送る

ルートパーティションのコピー
(/boot、/home などを別パーティションでわけている場合は、それも除外して個別でコピーする)

# cd /
# tar zcf - \
--exclude /sys \
--exclude /dev \
--exclude /cgroup \
--exclude /srv \
--exclude /selinux \
--exclude /lost+found \
--exclude /net \
--exclude /proc \  | ssh root@192.168.0.1 "(cd /mnt/sysimage && tar zxf -)"

big-ip APMのセッション数 取得

GUI

Access Policy - Manage Sessions

SNMP

https://support.f5.com/kb/en-us/solutions/public/15000/000/sol15032.html
1.3.6.1.4.1.3375.2.6.1.4.3.0

F5-BIGIP-APM-MIB::apmAccessStatCurrentActiveSessions.0 = Counter64: 16

ただ、手元の環境だとGUIのManage Sessionsの数と一致しないんだけどなんでだろ

CLI

https://devcentral.f5.com/questions/apm-session-managemet
sessiondump コマンド

sessiondump -list
sessiondump -allkeys

セッション数(セッションid 一覧)だけなら-listで。
ipや証明書のsubjectなどまで取得する場合は-allkeys。
ただし、-allkeysは整形されたフォーマットではないので
ごにょごにょする場合は自力でparseする必要がある。

big-ip ltm current connectionをsnmpで取る

昔諦めた気がしたけど、snmpwalk一覧眺めたらあっさり解決した。

virtualserver

F5-BIGIP-LOCAL-MIB::ltmVirtualServStatClientCurConns
.1.3.6.1.4.1.3375.2.2.10.2.3.1.12

pool

F5-BIGIP-LOCAL-MIB::ltmPoolStatServerCurConns
.1.3.6.1.4.1.3375.2.2.5.2.3.1.8

$ snmpwalk -v2c -c public 192.168.0.1 F5-BIGIP-LOCAL-MIB::ltmPoolStatServerCurConns
F5-BIGIP-LOCAL-MIB::ltmPoolStatServerCurConns."/Common/virtual-server-name" = Counter64: 0
(以下ずらずら)

virtualserver,poolともに1つだけピンポイントに指定もできるけど"で囲まれてる文字列のところを
16進数で変換したものにしないといけなくてめんどくさいので
snmpwalkで一覧とってきて名前で取捨選択したほうが簡単かな。

poolの各memberの値
F5-BIGIP-LOCAL-MIB::ltmPoolMemberStatServerCurConns
.1.3.6.1.4.1.3375.2.2.5.4.3.1.11

nginxでproxy_cacheしてもcacheされない条件

backendサーバからExpires、Cache-Controlなど特定のheaderが返ってくるとcacheされない。

Disables processing of certain response header fields from the proxied server. 
The following fields can be ignored: “X-Accel-Redirect”, “X-Accel-Expires”, 
  “X-Accel-Limit-Rate” (1.1.6), “X-Accel-Buffering” (1.1.6), “X-Accel-Charset” (1.1.6), 
	“Expires”, “Cache-Control”, “Set-Cookie” (0.8.44), and “Vary” (1.7.7).

無視したい場合は

proxy_ignore_headers Cache-Control;
## 複数の場合はスペーク区切り
proxy_ignore_headers Cache-Control Expires;

などとする。

big-ip persistence match acrossメモ

virtualserverを跨って同一のnodeに振り分けたいときのpersistenceのoption

cookieでmatch acrossする場合はbig-ipが発行するinsert cookieは使えない。
cookie hashが必要(webアプリケーション側で発行するcookie名を指定)
Cookie Nameは PHPSESSIDなど。

アプリケーションが一意なら問題ないが、/fooはperl、/barはphpのようにわかれていると難しいのでその場合はsource ip persistenceを使うと良さげ。


source ip persistenceの例

前提としてhttp用のpoolとhttps用のpoolで同一のnodeを含んでいること。

同一ipのvirtualserver (http/https)で同nodeに振り分けたい場合

source_addr: match across services

普通はこれでいい

異なるipのvirtualserver 間で同nodeに振り分けたい場合

(これが必要なときあんまりないと思うが。。。)
同一サーバだけどSSLを設定するために別IPでvirtualserverを作った場合とか?

source_addr: match across virtualservers

match across Pools はおそらく通常用途では使わない。

big-ip irule IP::local_addr

使う場所 (event) 次第で結果が変わる。


clientside (CLIENT_ACCEPTED)の場合はdestination addr
serverside (SERVER_CONNECTED)の場合はsource addr

iruleのCLIENT_ACCEPTEDを使っているところでdestination addrを判別したかって、IP::remote_addrを使ってみたけどsource addrが返ってきた。
IP::server_addrを使うと(たぶんCLIENT_ACCEPTEDの時点ではまだサーバに繋がってないから)"no serverside connection established "となってエラーとなった。
で、色々試行錯誤してて、CLIENT_ACCPTEDの時点でdestination addr知りたかったらどないしたらええねん?と行き着いた先が冒頭の結果通り、IP::local_addrを使って解決。

big-ip source nat part2

hogem.hatenablog.com
追記で書いたけど↑は任意のsourceからとあるStandardなVirtualServerへアクセスしたときのsource nat
とはいえ結局はnatなので半分ぐらいかぶってる。


今回は宛先がVirtualServerではなくて、
特定のserverからbig-ipをdefault gatewayとして抜けていって、他のnetworkへアクセスするときの話。

具体的に言うとdmz(or trustでもいいけど)から
internet(untrust)や違うvlan dmz2 などへアクセスする場合

前提

big-ipがルータとなる場合、networkを跨った通信はデフォルトでは許可されない。

NATするか、typeをForwarding としたVirtualServerの作成が必要。

type: Forwarding (IP)
Source: 通信を許可するsource IP anyの場合は0.0.0.0/0
Destination: 通信を許可するdestination IP
Service Port: 0 (* All Ports)
  (特定portのみに制限することも可能だけど、通常forwardingの場合はall)
VLAN and Tunnel Traffic: 通常は特定の通信だけを設定すると思うのでALL Vlansではなく
   Enabled Onにしてsourceで通すvlan を選択
Source Address Translation: 後述


NATする箇所はおおまかに4通り

  • 双方向通信が必要なNATはNAT List
  • 特定のhost(s)だけSNATするときはSNAT List
  • subnetをまとめてSNATするときはForwarding Virtualserverで、
  • subnetをまとめてSNATするけど、特定のhostだけ個別のIPでSNATさせたい場合はiRuleっていう感じ?


おまけ:
VirtualServerの適用はlonguest matchで適用されるので

  • 特定IP/Portの場合は
  • 特定のtcp profileを適用して (ex: timeoutを伸ばす)
  • NATするIPを変える

というようなことも可能
おまけここまで

http://hogem.hatenablog.com/entry/2015/11/07/233000

Address Translation : NAT List

1:1 NAT 双方向

NAT Address: 172.16.0.1
Origin Address: 10.0.0.1
とすると、10.0.0.1 がbig-ipを抜けて外へ通信する際に172.16.0.1になり、
外のサーバから172.16.0.1へアクセスすると10.0.0.1宛にパケットが届く。

172.16.0.1のアドレスでpingが応答したので双方向NATだと思い込んでたけど
pingはSNATを定義したらbig-ipが応答するようになるだけなので、双方向NATではなかった。

NAT Listで1:1 NATする場合は、forwarding virtual serverの設定しなくても
vlanを跨いで通信は可能になる。

あと、NAT Listで定義してもforwarding virtual server でNAT設定があったら、そちらが有効になるぽい。
(なんしか、big-ipはvirtual serverが最優先されると思っていたらいい?)

Address Translation : SNAT List

N:1 NAT 片方向
複数のprivate IP を特定のgloabal IPにNATする場合など。
Forwarding VirtualServerでまとめてNATするのではなくて
特定のaddress(s)を個別にNATするときに使う。

SNAT Listを設定していてもForwarding VirtualServerでSNATが設定されていた場合、
そちらのでSNATが優先される。

Origin IPを指定する時点で不要な気もするが、送信元をvlanを限定したい場合は
VLAN / Tunnel Traffic をEnabled onにしてVLANを選択する

Forwading VirtualServer 単位でNAT

Source Address TranslationでNoneではなく次の2つのどちらかを選ぶ。
通常はauto mapで良いはず。

  • Auto Map: destinationに適したegressなinterfaceのfloating ipが自動的に選ばれる
  • SNAT: あらかじめ設定しておいたSNAT Poolから選択

例えばdmz の任意のserverがuntrustへ抜けていくときに
まとめてとあるグローバルIPでNATさせたい場合に。

SNAT ListよりもこちらのSNATが優先される。

iRule でNAT

http://hogem.hatenablog.com/entry/20150110/1420894082
これと同じ内容。
条件がマッチした場合はVirtualServerのSNATよりもさらに優先される。

個人的には誤操作による削除防止の観点からも、SNAT Poolを作っておいて
irule内でsnatpool snatpool-hogehoge などとするほうが良い気がする。

# list ltm snatpool snatpool1 one-line
ltm snatpool snatpool1 { members { 192.0.2.11 } }
# list ltm snatpool snatpool2 one-line
ltm snatpool snatpool2 { members { 192.0.2.12 } }
	
### forwarding virtual serverに適用するirule
when CLIENT_ACCEPTED {
  if { [IP::addr [IP::client_addr] equals 10.0.0.11/32] } {
    snatpool snatpool1
  }
  elseif { [IP::addr [IP::client_addr] equals 10.0.0.12/32] } {
    snatpool snatpool2
  }
  else {
    snat automap
  }
}

まとめ

big-ipは仕様上、他で適用されている設定は削除できない。
(virtualhost適用済みのpool/irule、iruleに適用しているsnat poolなど)
ただSNAT Listだけはそうじゃないみたいなので、
特定のhostだけSNATをする場合でも、snat poolを作ってそれをiruleで指定するほうが安全?
その分iruleが複雑になっていくのでどっち選ぶかは運用次第。