日々精進

aikoと旅行とプログラミング

MSPJマイグレーションコンペティション2019 winter 参加記 #mspj

f:id:bath_poo:20190120225016j:plain

2019年になってから一発目のイベント、MSPJマイグレーションコンテスト2019に参加してきた。

マイグレーションコンペティションとは

そもそもマイグレーションコンペティションって何?という方のほうが多い気がする。

mspj.jp

日本MSP協会(MSPJ: Managed Service Provider's Association Japan)が開催しているコンペティションで、すごく簡単に言ってしまうとシステムをマイグレーションする(移行する)コンテストなのである。タイトルそのままなので説明になっていない気もするが…。

このコンペティションにはある特徴があって、参加するにあたって「開催当日に30歳以下であること」が必須の条件とされていることである。募集ページの言葉を引用させていただくと、

日本MSP協会コンペティショングループは、運用技術を競うコンペティションを開催し、 次代を担う若手運用技術者同士の交流・競争を通して日本のMSP事業者における運用技術の向上を目指します。

ということで、比較的若いエンジニアがターゲットとなっていることが挙げられる。私もまだ比較的若いので(?)参加してみようということに。

このコンペティションの面白いところとして、システムマイグレーションだけではなく顧客とのやり取りや報告書の作成等も含まれるところである。完全に移行し、かつ顧客とスムーズにやり取りする力、資料作成まで見込んだスケジューリング感なども求められるコンペティションになっている。

前日まで

お題については事前に公表されており、

connpass.com

非常にざっくりとではあるもののどのようなシステムを移行する必要があるのかを感じ取ることはできる。お題は

お題:いま動いている文書システムを新しい環境に移行して欲しい

とのこと。システムに関しては、

  • Amazon Web Servicesで動いていそう
  • バージョンが古めのCentOS
  • ミドルウェアApachePythonGitが含まれていること
  • 移行先がMicrosoft Azure

程度の状況はわかっている。バージョン古めのCentOSはどうせCentOS6.xだろうなーとか、 AzureやったことないしVM立てるぐらいはやっておかないとなーと思っていたら、イベントの1週間前ぐらいからひどい風邪を引いてしまいずっと倒れていた。つまり、コンペ当日まで何もできていなかったのである。こういうのは付け焼き刃の知識では良くないので、もっと計画的に前から作戦を練ろうという気持ちになった(来年への課題です)

当日

今回(も?)会場は品川にある日本マイクロソフトだった。品川駅を降りて港南口からでて右折までは成功したものの、その後さまよい続けて結果10分ほどロスをするはめになった。ビル沿いに並んでるのかと思いきや、少しマイクロソフトのビルだけ入り口が奥にあったので気づかずにスルー(伝われ)

f:id:bath_poo:20190120224934j:plain
いい景色

10:00から開会式と聞いていたが、前に書いた通り迷子になっていたので到着が9:50ぐらいになった。すでに会場にはそれなりに人がいて、皆様結構到着が早めなのね…などと思っていた。知り合いがひとり来るのは知っていたがまだ来ていなかったようなのでコミュ障地蔵になって椅子に座っていた。

開会式

開会式が始まる。みんな静か。めっちゃ静か。自分も静かだったので申し訳ない。もうちょっと反応したほうが絶対いいよねって思いました、自分も含め。でもみんなお金が欲しいことだけはすごくわかりました(自分もそう)

今回のお題が発表される。Gitで管理してる文書サイトをAWSからAzureに移行しましょう!というお話だった。また、文書のビルドにはJenkinsを使っているとのことだった。このときJenkinsを使ったことがない、というかCIツールを使ったことがない私は(これやばいんじゃない…?)という気持ちでいっぱいだった。他にも顧客からの要望が来ていて、

  • 今の環境を新しい環境に完全移行して欲しいです。
  • 実施した内容と結果については報告が欲しいです。
  • システムを止めるときは利用者に告知が必要なので連絡が欲しいです。
  • 昔から使っている古い環境なので、バージョンアップして欲しいです。
  • できれば利用者に影響を出さないように切り替えたいです。
  • できればサーバに関する資料があるとありがたいです。
  • できればバックアップを取れるようにしたいです
  • できれば今後は利用者が増えるのでシステムを冗長化したいです。
  • できれば引継ぎするために必要な情報がまとまっていると嬉しいです。
  • 体制変更で、システムが分かる人がいなくなってしまいました。
  • いいタイミングなのでリフレッシュしたいなと思っています。
  • 商売は続いているので、できるだけ利用者さんに影響が少ないと嬉しいです。
  • 本当はいろいろとナウっぽいこともしていい感じにしていきたいんですよ。

と大変盛りだくさん。完全に移行ができた上で、この要件を満たせると+ALPHAの加点となるようだった。

そして最後にチーム分け。今回は実務経験年数が4年以上とそれ未満で分け、4年以上の人たちが各チームに一人以上はいるようにチーム分けが行われた。このコンテスト、参加者がほぼ社会人なので、実務経験が0年の私はとにかくチームメンバーの足を引っ張らないかどうかが心配で胃に穴が開きそうだった。1列に並んで、前から1〜9の番号を読み上げていきまた1〜9まで読み上げるという小学生ぶりのチーム分けを行い、Team5(Tさん(社会人), Oさん(社会人), 私(学生))ということになった。いよいよ10:30から開始である。

コンペティション最中のお話

10:30〜11:30

ここからはTさんのまとめた資料をもとに書いていく。資料をちゃんと書いていると、コンテスト後の参加記が書きやすくなります(そういう用途ではない)

まずは、顧客の要求を「やらなければいけないこと(MUST)」と「やるべきこと(SHOULD)」に分けるところから始まる。上に載せたもののうち、

  • 今の環境を新しい環境に完全移行して欲しいです。
  • 実施した内容と結果については報告が欲しいです。
  • システムを止めるときは利用者に告知が必要なので連絡が欲しいです。
  • 昔から使っている古い環境なので、バージョンアップして欲しいです。

については必ず実施しなければいけない。これが完了した上で、残りの項目を達成できるように行うべきであるという認識を一致させた。これについてはTさんがGoogleSpreadsheetにすべてまとめてくれており、最後までこれを見失わずに進むことができたと思う。

やらなければいけないことがわかった上で、それぞれのスキルや経験等をもとに役割分担を行った。リーダーのTさんは、顧客に提出する資料を書きつつ残りチームの舵取り役、Oさんは移行先環境(Azure)のセットアップ、残る私は現在の環境について調査を行うことになった。

調査をしていくと、

  • 今回は配信しているものに関しては静的コンテンツしかない
    • PHPMySQL等は存在しない
  • OSはCentOS6.9
  • WebサーバはApache
  • GitPythonは予告どおり
  • Apache, Gitリポジトリ, Jenkinsなどがすべて1台のインスタンスで稼働している
  • コンテンツはmkdocsを使ってビルドされている

ことがわかった。これらを調べているうちに、横でOさんがVMを立て終えていて(社会人のお二人手際良すぎでは…)と思うなどしていた。

また、副次的にわかったこととして、

  • Jenkinsのログを見ていると、大量のWARNINGがでている
  • Jenkinsで走っているジョブの動作
    • /var/lib/jenkins/mkdocs/docsへ移動
    • git pullで変更をとってくる
    • /var/lib/jenkins/mkdocs/へ移動
    • mkdocs build
    • ビルドされた/var/lib/jenkins/mkdocs/site//var/www/html/rsync

ということがわかった。どうもmkdocs buildするときに、Markdownファイル内に含まれる外字を表す画像を格納したディレクトリ(以下、外字ディレクトリ)が存在しないのでは?という警告だった。しかしページ自体は普通に表示されているので、とりあえず問題ないとして次に進んだ。

まだ午前中&チームを組んですぐだったので、めっちゃビクビクしながら話しかけていた。

11:30〜12:30

ここまでの状況を一度お互いに報告し、このあとの方向性を決めた。Tさんは現在やっている作業を継続、Oさんはバックアップの設定、私はデータの移行を行うことになった。

旧環境から新環境へは以下のファイルを移行させる必要があった。

  • コンテンツのリポジトリ
  • httpd.confやmkstyle.ymlといったコンフィグファイル
  • Jenkinsの設定ファイル

基本的にインスタンス関連のオペレーションは私とOさんがやっていたので、Oさんと相談しつつ「とりあえず全部rsyncを使って全部コピーしよう」という方針で決まった。Jenkinsの移行は、/var/lib/jenkinsをまるごとコピーした。1[GB]ぐらいあった。

このあたりで、リポジトリの奇妙な点に気づく。先程Jenkinsのログで大量のワーニングが出ていた事に気づいていたが、その原因が「.mdが参照している外字ディレクトリがリポジトリに含まれていないため」であることがわかった。その外字ディレクトリはどこにあるかというと、Apacheのドキュメントルート/var/www/htmlに置かれていた。つまり、人力で旧環境から新環境へ外字ディレクトリをコピーしない限り、いくら新環境でビルドしても外字がNot Foundになってしまうという罠があった。

画像ファイルが含まれていないことにこの段階で気づいたので, /var/www/htmlに関しても新環境にそのまま移行した. ここでこれに気づいていたのはラッキーだったと思う。

12:30〜13:30

ごはんもぐもぐ。ここになってやっとお互いの話を落ち着いてできるようになる。やはりランチ会っていいですね。出身の話をしたりとか、普段どんなことをしているのか、どんな会社なのかいろいろ聞きつつ楽しい時間を過ごすことができた。

13:30〜14:30

とりあえず移行が終わったはずなので、新環境でページが見れるかを確認した。午前の段階で、旧環境の/var/www/htmlの中身をコピーしてあるので, 正しく設定されていれば見れるはずである。結果、正しく表示されていた。このとりあえず動くというのはメンタル的にも大事であると今まで嫌というほど学んできたので、新環境で動いた瞬間を見たときは正直ホッとした。

この段階で,

  • とりあえずVMは稼働している
  • 22, 80ポートの疎通ができる
  • Apacheも動いている
  • 表示も正しそう(画像の欠損がないか、など)

は確認できていた。そして次取り組んだのはJenkinsの設定。まずコンソールを見ようと思って<host>:8080に何もでなかったので,

$ systemctl status jenkins
● jenkins.service - LSB: Jenkins Automation Server
   Loaded: loaded (/etc/rc.d/init.d/jenkins; bad; vendor preset: disabled)
   Active: failed (Result: exit-code) since 土 2019-01-19 02:26:14 UTC; 1h 37min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 864 ExecStart=/etc/rc.d/init.d/jenkins start (code=exited, status=1/FAILURE)

エーン。journalctlでみた結果、Javaが入ってないというだけだった。ログを見て速攻Oさんが気づき爆速でjdkインストールをしてくれた。今回思ったんだけど、私の曖昧な詰まり報告をきいて爆速で課題解決してくれるOさんがめちゃくちゃ頼もしかった。

そんな感じでJenkinsが復活した。旧環境から環境をまるごとコピーしたので、前の環境と同じようにログインし、もともとあったジョブを走らせたらコケてしまった。どうもjenkinsユーザーがssh失敗してるようだった。これは、

$ su -s /bin/bash jenkins
$ ssh admin@localhost

という感じでknown_hostsに突っ込むことで解決した(ビルド実行ユーザーはadminだったのでこんな感じになった)。この日初めて問題解決をし、多少役に立てたかな、という気持ちになった。

次は、mkdocs buildがコケるようになった。どうも使っているテーマ(見た目)がインストールされていないらしい。これまたOさんが爆速でpip installを決めてくれたおかげでビルドも通るようになった🎉

14:30〜15:30

JenkinsのログにBUILD: SUCCESSとでていた私たちは大喜びしていたが、冷静になってみるとその上にエラーが表示されている事に気づいた。どうもメール送信に失敗したらしい…

その後もう一度ジョブを走らせると、そのエラーが表示されなくなった。何だこれは…?と思ったが、とりあえず一度でもメール送信失敗したことは事実なので調査を行うことに。そこでOさんとTさんが「たしかAzureって25番ポートで他のメールアドレスに直接メール送信できなかった気がする」という話が出る。どうもAWSは25番、つまりSMTPサーバへの通信ができるが, GCPAzureはできないとのことだった。これOP25B(Outbound Port 25 Blocking)って言うんですね。だから前の環境ではこれで動いていたのか…となる。

これの解決策としてパッと思いつくのはSendGridを使うことなので、そちらの方針に切り替える。顧客に事情説明とSendGridを使う旨を伝え、移行作業に取り掛かった。またこちらもOさんが爆速でSendGridの環境を整えてくださり、私はJenkinsのConfig画面にユーザーとキーとSMTPサーバのアドレスを書くだけになった。

設定したものの何故かうまくいかない。結果としてはポートが25のままだった。他のポートに変更したら無事にメールが届いたため、メールの設定も無事に終了した🎉

同時に冗長化どうする?というお話にもなった。

15:30〜16:30

冗長化をどうしようかという議論が前の時間から続いていた。可用性セットとか可用性ゾーン、LBWAFとか?という話をしていたが結果どれも断念。LBの下に何台かインスタンスをぶら下げたとき、どうやってコンテンツ類を同期しようかという話になって、残りの時間を考えたときにこの変更は難しいということになって断念した。

また、CDNを入れてサーバの負荷低減や冗長化というところまでやったが、Jenkinsも同一サーバにいるためこちらも断念ということに。

これに加えて、セキュリティ的な対策も考えた。まず、DDoS等の不正アクセスを検知するためにAzure Monitorをつかってモニタリングを行った。5分間の平均CPU使用率が80%を超えるようなときにアラートが飛ぶようになった。この設定はOさんがやってくれていた。

あとこれが対策になるかはわからないものの、Apacheの基本的な設定を行った。どんなものかわからなかったので、とりあえず二人に相談し、「いいんじゃない?やってみよう。」とのことだったので進める。割とよくあるバージョンを隠そうねとかそんなやつなので、

  • ServerTokens ProductOnlyを追記し, レスポンスヘッダーに含まれるApacheのバージョンを非表示に変更
  • ServerSignature Offを追記し, エラー(NotFound)時にシステムの詳細が書かれたフッターを表示しないように変更
  • のOptionsからIndexesを削除し, <URL>にアクセスした際にファイル一覧を表示しないように変更

という感じをやった。これも一応報告書にも載せてもらえた。

このあたりで、顧客に対してDNSの切り替え要請を行った。

  • 16:30頃に切り替えて欲しい 
  • ページがダウンする可能性があるので、ユーザーへの通知を行って欲しい

の2点をお願いした。主にこのあたりのやり取りはTさん中心にOさんも行ってくれて本当に本当に助けられた。特にTさんは、VMいじってる二人がやっていることも気にかけつつ、必要と思われるコミュニケーションはどんどんとっていてありがたかった。

16:30〜17:00

いよいよDNSが切り替わる。見たところ正常に動作してるっぽい。とりあえず移行はできたことが確認された。

そして残りは納品資料の作成。と言ってもこの段階で9割ぐらいはできていて、あとは手直しやtypoの修正というぐらいだった。Tさん有能過ぎでは。

そして1分前ぐらいに提出して終了。こう見るとギリギリだったけど、やっている側としてはそんなに焦ってやってはいなかったので良かったかな。3人共やりきったという感じでした。

懇親会

今回懇親会画像全然撮ってない。大量のアルコールがDeployされましたが、私は病み上がりなので緑茶を無限に決めていた。オードブルとかもでてきていい感じ。懇親会2hあって結構長いなーって思っていたら、その裏でジャッジが行われていたらしい。通りで運営チームの人を見かけないわけである。

一番最初に話しかけてくださった方が、いきなり私のTwitterの話し始めたの本当に面白かった(嫌ではない)。共通のフォロワーが何人かいたからね、しょうがないね。その流れで、その社から来ている方々ともいろいろお話させていただいた。今度ご飯食べいこうねというお話もした。

29人中27人が社会人の方だったので、自分より年上だったりする方がおおかったりした。就活中なんすよ〜〜(ヘラヘラ)というムーブもした。自分も興味があったりする会社の人もいたりしたのでその方ともお話をした。

コミュ力トークスキルが低いので、懇親会は難しい。当日で一番難しかった。

結果発表

いよいよドキドキの結果発表。なぜならば、このイベントは入賞者に賞金が贈られるのである。今回から大幅に増額&受賞者が増えたということでみんなワクワクしていた。具体的に書くと1位が60万, 2位が30万, 3位が10万である。

3位から順に発表された。3位はなんと該当者なし。会場が???となる。まあもしかしたら同率2位とかそういうね、と思う。そして2位。2位もいない。更に???????となる。つまり今回移設成功していたのが1チームしかなかったのである。

この自体にレギュレーションが変更される。なんと1位が100万円全部もっていくことになった。会場がざわざわする。まさか100万円になるとは誰も思っていなかったんだろうね。

そしていよいよ1位の発表である。1位はなんと

f:id:bath_poo:20190120225107j:plain
まさかの
でした。というわけで優勝しました🎉

やはり移行が完全にうまくいっていたところはTeam5だけだったらしい。自分は「多分入っていても3位ぐらいでは」と思っていたので、3位が該当なしの時点ですでにあきらめムードだった。そんな中名前を呼ばれたので、最初は脳が混乱していた。

隣のTeam6は惜しくて移行まで行っていたけど、外字ディレクトリの移行にミスっていたため駄目だったらしい。結構シビアだなあと思うなどした。

感想

MUSTとSHOULDの話

今回は、資料もあまりないシステムが与えられてそれを別のパブリッククラウドに移し替えるというものだった。それに加えて、顧客からの要求もきており、そちらもできる限り実現して欲しいというものだった。

最初にも書いたが、やらなければいけないMUSTなことと、やってほしいSHOULDなことをしっかりと見極め、それをブレずに実践することの大切さを感じた。今回の課題に関しては、旧環境が新環境で完全に再現されている必要があった。これはMUSTな条件である。ナウいシステム構成にするのもいいが、それよりもまず満たすべきところをしっかりと満たせたのが我々の良かったところだと思う。チームメンバーの3人とも、同じ方向を向いて取り組めていたところも大変よかったと思う。

チームでうまいことやるのって難しい

f:id:bath_poo:20190120230531p:plain 今回は時間も結構限られていた。6h30mぐらいの中で、求められていることを確実にこなして資料まで作り上げなければならない。意外と時間があるようでなかったりするので、そのあたりのスケジュール感が適切でないと最後移行失敗ということになってしまいそうだなと思った。

自分はそのあたりが正直全然わからなくて、完全にTさんとOさんに任せっきりという感じだった。次出るときがあったら意見できるぐらいにはなりたいですね。

まとめ

10:30〜17:00という非常に短い時間で移行を行うのは、自分が想像していた以上に難しいものでした。しかし、それによって得られた学びも大きかったように感じられます。実務経験0の私には、得られるものが非常に大きなイベントでした。

あとははじめてのJenkins, はじめてのAzureって感じで。慣れないながらも試行錯誤できたかな、と。まだまだ精進が必要ですね。

まだ全然U30なので、来年以降も積極的に参加していきたいと思います。チームメンバーのお二方、運営のみなさん、そして参加されたみなさん、ありがとうございました。