文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

2011年作のjavaプロジェクトをAWSに移行 〜 発狂寸前 〜

現在古いプロジェクトをAWS環境に移行すべく奮闘中です。
移行するに当たって色々学んだりイラッとしたりしたので、簡単に書いてみようと思います。


f:id:treeapps:20180418115102p:plain

古いプロジェクトには罠が一杯!!

私はDevOpsでいうところの、DevとOpsを両方やります。
当然デプロイ周りもやります(というか全部私一人でやります)。

しかしこのjavaプロジェクト、2011年に作られただけあって、大変酷い作りです。

前提条件が多すぎる!


旧環境を見て、新環境に同じフォルダ構成を作ろう。

あれ?そもそも初期フォルダってどれ用意したらいいんだ?

はい。そうです。

アプリの正常動作には既に初期フォルダを用意してある前提、しかもどこに何を作ったらいいか不明

最悪です。No Such File Or Directoryの嵐です。
勿論SFTP関連のフォルダも全部最初から用意してある前提。
権限設定も旧環境を見るしかない。


な、なんだこれ・・・

どうやら私は大変な世界に迷い込んでしまったらしい・・・

旧環境から新環境へ移行する際の変更点

旧環境と比較して、新環境では以下のように変更しました。

旧環境 新環境
サーバ環境 オンプレミス AWS
サーバ環境構築 人力 ansible
ビルド ant ant
デプロイ シェルスクリプト fabric
CI 無い jenkins
SCM svn git
JDK 1.6 1.8
apache ver2.2 ver2.2
tomcat ver6 ver7
ruby ver1.8 ver1.8
MySQL ver5.0 ver5.6(AmazonRDS)
サーバ監視 nagios nagios
リソース監視 cacti munin
ログ収集 なにそれ fluentd

この新環境への移行で特に有効なのが以下の点です。

  • デプロイをfabricで行うようにした
  • tomcatを7にアップした
  • MySQLを一気に5.6にアップした

tomcat6はどうもリークしているっぽく、7にする事で大分安定します。MySQLは単純にパフォーマンスアップします。そして最も有用なのがfabricです。このfabricのおかげで、初期フォルダ生成や権限設定が簡単になりました。

fabricについては以下の記事を書き、既に学習済みです。
【python】fabricを触ってみた!【デプロイツール】 - 文系プログラマによるTIPSブログ
【デプロイ】Fabricを学ぶ:Vol.01:基本的な使い方を学ぶ【python】 - 文系プログラマによるTIPSブログ
【デプロイ】Fabricを学ぶ:Vol.02:tomcatの起動完了を監視する【python】 - 文系プログラマによるTIPSブログ

初期フォルダと権限設定はデプロイ時に行う


このデプロイシェルはね〜〜

このフォルダがこういう権限で事前に無いと動かないんだよ〜〜

なんて言って、後任の人に助走をつけて殴られないように、極力自力でなんとかするデプロイスクリプトにしましょう。

今回導入したfabricは、sudoコマンドが非常に簡単に行えます。

sudo('test ! -d /var/app && mkdir -pv /var/app')
sudo('chown -R hoge. /var/app')

こんな感じでsudoメソッドにbashを書くだけで、sudoを実行できます。
これをbashで行おうとすると、expectコマンドで対話を突破するという強攻策しかありません。


sudoのパスワード入力で停止するデプロイスクリプトが許されるのは小学生までだよね〜

fabricとcapistranoでワンクリックデプロイが当たり前だよね〜

パスワード入力でいちいち停止するデプロイシェルは投げ捨てて、パスワードも自動入力してくれるfabtic(python)かcapistrano(ruby)でワンクリックデプロイできるようにすると、デザイナやテスターですらデプロイできるようになります。

apacheだけ何故か手動デプロイ運用である

そうです。古いプロジェクトにありがな、apacheだけ手動デプロイ!
手動デプロイになっている理由は簡単です。apacheは大抵の環境でsudoが必要になるので、bashでパスワード入力無しでbashを書かなくてはいけないのですが、それを書ける時間やスキルが無く、手動運用となっているのです。

fabricならパスワード入力無しにsudoが簡単に行えるので、apacheの起動・終了もsudoメソッドで余裕です。


bashでsudoするのが大変なので、apacheのデプロイは手動なんすよ〜〜

時間あったらスクリプト書くんすけどね〜(絶対書かない)

なんていうしょうもない理由でapacheを手動デプロイする運用ももうやめましょう。
また、

apacheをデプロイしたいからsudoersでapacheだけパス無しで再起動できるんすよ(キリ

なんていう特殊事情も排除できます。

環境変数に事前に値を設定しておかないと動かないバッチ

もううんざりですね。

for f in ${HOGE_DIRS[@]}; do
    tar cvfz f.tgz $f
done

例えばこんなスクリプトがあって、HOGE_DIRSは何かしらの方法で環境変数に設定しておかないと動かないのです。別ファイルに定数が定義してあるのかな?と思ったら見つからない。全ファイルgrepしてみると、どうも定義している箇所が見つからない。試しにサーバにsshして「echo ${HOGE_DIRS}」したら値が表示される。ああ・・・これは環境変数だな・・・と。

一体どこで定義しているのか探ると、「/etc/profile.d/env.sh」に記述してありました。
「/etc/profile.d」配下にスクリプトを配置すると、全てのユーザのログイン時に読み込んでくれるので、全ユーザ共通の変数を設定する事ができます。

しかしroot権限が必要なので、これもsudoでデプロイするのが大変だからやっていなかったのでしょう・・・


やらないお「/etc/profile.d配下にアプリに依存する設定書くなっていったろ!!」

 

やるお「ず、ずびばぜん」

標準出力・エラー出力を全部捨てるcron

例えばこんなcronです。

0 1 * * * /var/app/batch/hoge.sh >/dev/null 2>&1

何故か全てのcronで標準出力・エラー出力を破棄しているのです。
この破棄を消してみると・・・


あれ?これしょっぱなからエラー出てるぞおい・・・

というかこれ、リリース以来ずっとエラーで動いてないんすけど・・・

という衝撃の事実が発覚し、何故か私が怒られるという・・・

cronが手動デプロイ

これもsudoの問題ですね。
しかしfabricを使えば簡単です。

cronのテキストファイルをgitで管理し、/var/spool/cron 配下にユーザ毎に配置するなり、/etc/crontabを編集するなりして、cronもデプロイできるようにしましょう。


「crontab -e」を「crontab -r」とtypoしてcrontabを初期化してしまい、cronが復元できなくなる場合もあるので、git等で管理しfabric等でデプロイできるようにしておく事をお勧めします。

ansible側でやりすぎてfabricと処理が被った

ansibleは最近一気に勉強したもので、以下の記事を書きました。

ansibleがあまりにも簡単で便利だったので、ついついansible側でやりすぎてしまい、「これはfabric側でやった方がよかったな」という部分が結構ありました。

ansibleとfabricの担当範囲は事前に決めておいた方がよいです。

結局

結局ほとんどの問題はsudoが絡んでいるように思えました。
しかしfabricで全部解決できるので、これを機に全部直しています。

AWSについての知識不足

話は代わりますが、私は保守の担当が多く、あまり最先端な環境に触れる機会がありません。
従ってAWS関連の知識もほとんどありませんでした。
それが原因で以下の問題に直面し、インスタンスを生成するまでに時間がかかりました。

数ヶ月前の料金シミュレーションが役に立たない

awsは活発にサービスが変わります。
価格や新サービスの追加等があっという間に行われます。

私でない人が数ヶ月前に見積もった金額が、なんといま見積もり直すと半額になっていました。

PV(ParaVirtual)とHVM(Hardware-assited VM)の仮想化方式の違いを知らない

AMIの仮想化方式には、PVとHVMの2種類があります。
PVは準仮想化で、HVMは完全仮想化です。

準仮想化は高速だが制限がつく、完全仮想化は低速だが制限はほぼない、(であってる?)となります。昔は完全仮想化はパフォーマンスが出ないので敬遠されていましたが、現在はハードウェアレベルで仮想化支援が進んでいるので、完全仮想化でも十分なパフォーマンスがでます。

m1.small等の旧世代のインスタイプはHVMに対応しておらず、PVにせざるを得ない事も知りました。m3.medium等の現行の世代はHVMに対応しています。


PVとHVMを理解してないと、ec2インスタンスを作成する最初の一歩目で躓いてしまいます。HVM(完全仮想化)を優先して選ぶといいです。既にPVを選択できるAMiが減ってるので、将来的に全てHVMになる可能性もあります。

EBSを使わない

EBSは付け外しが可能な外付けハードディスク的なもので、サーバを再起動しても、インスタンスを停止・削除しても、EBSのデータは残り続け、別のサーバにアタッチする事ができる優れものです。

しかしEBSは有料です。課金されます。
このEBSは実は必須ではなく、インスタンスに無料で付属するエフェメラルディスク(揮発性ディスク)だけでも運用できます。

しかしですね・・・
エフェメラルディスクをroot volume「/」に割り当てるディスク容量指定方法が不明
なのです。多分私が知らないだけですが。
というかそもそもエフェメラルのみで始められる無料のAMIが、コミュニティにしかないという・・
EBSは価格もどんどん下がり、大した料金ではないから使えや!って事でしょうかね。
コミュニティにあったAMIを起動してみても「/」が7Gしかなく、ちょっとソフトをインストールするとすぐディスクが一杯になります。

更にいうと、Magneticディスク(IDE?)とSSDの価格の違いもそれ程無いので、理由が無い限りSSDでいいでしょう。

ELBはスパイクに対応できない

ELB、いわゆるロードバランサーは、突発的な急激なアクセス増(スパイク)に対応していません。していないというか、オートスケールする速度が遅いので、オートスケールが働くまで時間がかかり、スパイクが終わった頃にスケールアップするという悲しい事が起こります。従って基本的にプレワーニング(事前申請)し、事前にスケールアップする必要があるようです。例えばCMをうつ前日にプレワーニングをするといいのでしょう。

これと同様に、インスタンスのオートスケールも遅いです。当然スパイクに対応しきれません。

このスパイク問題、実はGoogleのGoogle Compute Engineのロードバランサーは高速でスケールアップするので、対応できるとのことです。


ELBに紐付けるEC2インスタンスはスクリプトで制御できます。つまり片系をバランサから切り離して動作確認し、OKならバランサに追加。もう片系を切り離して・・・といった感じに安全にアプリを公開する事も可能です。

SSL証明書はELBに設定する

旧来のようにapacheでSSL証明書を設定するのでなく、ELBに設定する事ができます。
すると、設定箇所も格段に減り、証明書の更新もAWSのコンソールから簡単に行えます。


是非ELBに証明書を登録してみて下さい。証明書更新時はAWSコンソールから更新でき、特に再起動も無く反映されます。

SSLの処理をELBに任せる事ができる

SSLのエンコード・デコード処理を全てELBに押し付け、アプリは全てhttp(port:80)で処理する事が可能です。

ELBに押し付けると、今までapacheが行っていたSSL処理(エンコード・デコード)のCPU負荷をELBに肩代わりさせる事ができます。ELBは負荷がかかると勝手にスケールアップするので、負荷はあまり気にしなくてよいです。

しかしデメリットもあり、場合によってはアプリ側の修正が必要になります。
SSLのリクエストが来ても、apacheにはhttpで処理が渡ってきてしまうので、SSLアクセス以外の時は403にする、といった処理は絶対に403になってしまいます。こういった「SSLリクエストの時だけ◯◯する」系の処理に影響があります。

ec2インスタンスは夜間は停止する

ec2インスタンスは起動しているだけで課金されるので、本番環境以外は夜間は停止し、出社前くらいに起動するようなスクリプトを仕込むとよいです。

ここで注意なのが、インスタンスを停止するので、本番環境のバッチとそれ以外の環境のバッチの実行時間を変える必要が出てきます。なんかログファイルの世代管理がされないな、と思ったら夜間のcronが動いてなかった、なんてことになります。

iptablesとselinuxはもう使わない

本当に使わなくていいのか自信ありませんが、基本的にiptablesは停止して、セキュリティグループでアクセスの管理をします。その証拠に?配布されているAMIもiptablesはOS起動時に自動起動しません。selinuxもオフです。

このセキュリティグループが非常に優秀で、ポートの制限等が本当に簡単に行えました。
例えば、クライアントにSFTPアカウントを渡し、特定フォルダにhtmlをアップロードするとクライアントが静的ページを管理する事ができる、といった仕組みを作ったとして、SFTPの許可IPの追加も簡単です。以下のようなやりとりがあっても安心!!


もしもしやるおさん?

SFTPなんですが、xxx.xxx.xxx.xxxっていうIPを追加して下さい。

1時間以内に頼みますよ〜〜ガチャッ


ふ〜、危ない危ない。

セキュリティグループが無ければ即死だったぜ・・(iptablesの書き方を知らない)

ハードウェア障害はほぼ無い

AWSのサービスのほとんどがSLA99.95%を保証するというとんでも仕様のため、ハードウェア障害にお目にかかる機会はまずありません。極稀にAWS自体の障害でポロッとインスタンスが停止があるようですが、ほぼ障害は無いので、今までオンプレミスで頻発していたハードウェア障害と無縁になりました。

単純なオンプレミスからクラウドへの置き換えは危険

例えば「オンプレミスだが、営業時間内に限り有人監視がつく」等、「有人監視オプション」は実はありがたいのです。単純にAWSに移行するだけだと、メールサーバの構築等、今までデータセンターの中の人達がやってくれていた面倒な事を全部自分たちでやらないといけなくなるようなデメリットもあります。

雑感

まだAWS移行が始まったばかりなのですが、もう既にこれだけの問題に遭遇しました。


なんか「くらうど」とかっつーのがすんげーらしいぜ!!

やろうぜ!!うぇーーーいwwwwww

なーんて軽い気持ちで始めると、


PV?HMV?AMI?IAM?ELB?

変な英語ばっかで全然意味わかんねーよ・・・

なんていう大恥をかくので、事前に勉強しておいた方がいいでしょう。
ということで、私のAWS移行はこれからだ!!(実は既にAWSの環境構築は経験済みですが、よく解ってない事が多かったです)


俺、このAWS移行が終わったら休暇取るんだ


(露骨過ぎるフラグ・・・・生きて帰れよ・・・!!)

古いプロジェクトの再生って大変だよな。頑張れ!!