てくすた

ピクスタ株式会社のエンジニア・デザイナーがつづるよもやまテクニカルブログです

コンテナ運用始めました

新しい日常してますか?

初夏の風もさわやかな日を迎え、木々の緑も日増しに濃くなってまいりました。

「挫折は人生のスパイスだ!!」インフラ担当のShimadaです。

最近、Stay homeのためYouTubeで音楽を聴き続けているのですが、流れてくる曲がどんどん最適化されGoogleの凄さを改めて感じています。

前回まで・・・

以前、コンテナ化に挫折しました。

texta.pixta.jp

今回は何とかproduction環境での運用までたどり着いたお話です。

staging環境(review環境)

弊社サービスは、AWSのOpsWorksでマイクロサービス毎にStackを作成し運用していました。

f:id:r-smd:20200527081834p:plain:w600
OpsWorks

コンテナクラスタ環境は未知の領域だったため、最小の機能単位で移行作業が行えるようにOpsWorksのStackと同様にマイクロサービス単位でクラスタを用意する事にしました。

f:id:r-smd:20200527081915p:plain:w600
Rancher

staging環境を作成する時期には、まだEKSが日本リージョンにリリースされていなかったのでEC2インスタンスでRancherのクラスタを作成しRancher上からマイクロサービス毎のkubernetesクラスタを作成しました。

rancher.com

まず、マイクロサービス別にDockerfileを作成しdocker-composeで動作確認が出来たdockerイメージをRancher上のクラスタに手作業でデプロイしました。

docs.docker.com

Webの管理画面で微調整し動作を確認しながら環境構築できるのはEKSにはないRancherのメリットだと思います。

Rancher上で作成した環境をymlでエクスポートしてhelmのchartパッケージを作成し簡単にデプロイできるようにました。

helm.sh

CI/CD環境

システムをコンテナ環境に移行する時に課題の1つとして「CI/CDをどうするか」という事があると思います。

弊社が運営する家族向けの出張撮影プラットフォームfotowaでは、下記のようにマネージドサービスを連動させています

texta.pixta.jp

今回コンテナ化するシステムは開発拠点が国内外にありメンバー数も少なくありません、コンテナ環境の知識があるメンバーは一部のメンバーのみです。

マネージドサービスのメリットはとても大きいです。

  • 機能の構築/運用管理作業が不要
  • サーバレスで提供されているので使用分のみ課金される
  • 複数機能があり用途に合わせて選択できる

しかしデメリットもあります。

  • 編集やデバッグを行うために作業者のアカウント管理が必要
  • 提供されている機能のため目的に合わせてカスタマイズはできない
  • 複数機能を連動させるためにステータスなどの連携が必要
  • アプリケーションとは別にマネージドサービスを構築するための設定ファイルなどの管理が必要

今回のシステムでは下記の点を考えて必要な機能を実装しているCI/CDツールであるDroneを自前で用意し使用することにしました。

  • Git更新 -> デプロイ処理の間でエラーが起きた場合のデバッグのしやすさ
    • Droneはログが確認できるweb画面が用意されているのでエラー時は結果へのリンクをチャットに送信することで、だれでもエラーの確認が可能
  • build -> デプロイ処理をアプリケーションと同じGitで管理する
    • build/デプロイ処理を記載しているファイルと構成管理用のchartパッケージをアプリケーションと同じリポジトリで管理することでアプリケーションにかかわる処理をインフラメンバーだけではなく開発メンバーも変更が可能
  • 一部のマイクロサービスではデプロイ処理でマイグレーションも実行する
    • マネージドサービスで複数機能を連動する際には前処理のステータスなどを連携する必要があるがDroneは設定ファイルを記載順に前工程のステータスチェックを行いながら実行してくれるので個別にステータス連携などのが不要

drone.io

Drone用にbuild専用クラスタを用意して自前で管理する環境を持つことになりますが、下記のように構成は単純になりました。

  • Github -> Drone -> Rancher(kubernetesクラスタ)

f:id:r-smd:20200527081802p:plain:w600
Builder

production環境

staging環境が問題なく運用出来たのでproduction環境に着手します。

production環境もstaging環境同様にマイクロサービス別のクラスタを用意してDNS、ALB、ターゲットグループで負荷を調整しながら移行する事にしました。

f:id:r-smd:20200527081901p:plain:w600
Production

staging環境で作成したhelmのchartパッケージをproduction環境でも使える様に変更し動作確認を行います。

負荷など影響範囲が小さい機能から順次移行を行いました。

OpsWorks環境と並行稼働しログや負荷を確認しつつリクエストを流す割合を調整しながらコンテナ環境に切り替えていきました。

途中リソースへのアクセス権限の問題など出ましたが、サービスが停止するような障害は出ずに移行する事が出来ました。

弊社ではstaging環境の前段階にreview環境というものを用意しています。

staging、production環境のリリース対象となるmasterブランチへのマージ前に動作確認できるように作業ブランチごとに環境をbuild/デプロイ処理をしています。

一日に複数ブランチの追加/更新が行われるreview環境を構築した後なのでproduction環境の構築は対象のブランチが1つ増えるだけで負荷などを考えなければ単純なものでした。

クラスタ統合と冗長化

コンテナ環境への移行時はRancher上からマイクロサービス毎に複数のkubernetesクラスタを用意していました、構成的にはOpsWorksで運用していたころとあまり変わりがない状態です。

f:id:r-smd:20200527081834p:plain:w600
OpsWorks

f:id:r-smd:20200527081848p:plain:w600
prod-rancher

Rancherやkubernetesといった基盤部分のメンテナンスや規模が大きなリリースの事前確認が出来る様にblue/greenのクラスタをactive/activeで用意しALBでクラスタを切り離すことが出来る様にしました。

新たに追加するblueクラスタはマイクロサービス毎にあるクラスタをサービスドメインでまとめました。

「サービスドメインでまとめる」と一言になっていますが、ReverseProxyとマイクロサービスのVirtualHostをごにょごにょするという生涯二度と経験することのないようなハイパーリスクテンコ盛りの言葉にできないような突貫工事を施しました。

La,la,la,la,la,la,la~

f:id:r-smd:20200527081713p:plain:w600
blue-green

(サーバラックの前に佇む姿が浮かんできますがクラウドなので問題はありません)

この後、新規追加したblueと同じように既存のgreenもクラスタをまとめました。

オートスケール

クラスタを冗長化したことでインフラ的な構成変更が無停止で容易に出来る様になりました。

kubernetesでの運用経験がある方は「まだだったの?」と思われるかもしれませんが、この時点でオートスケール機能を導入していません。

理由は単純に「怖いの・・・」

  • リリース直後にreplica数が最小数まで落ちないか
  • replica数が無限に増え続けないか
  • worker数がいつの間にか限界突破してしまわないか

などなど懸念点がたくさんありました。

今思えばstaging環境で試してみれば良かったと思いますが、クラスタ冗長化を行ったことでstaging環境x1、production環境x2(blue/green)とproduction環境の方が構成変更しやすい状況になっています。

Rancherクラスタのバージョンを上げたことでHPAの管理画面から確認操作ができるようになりました。

稼働状況を確認しながらレプリカ数を操作できるようになったので待望のオートスケールを導入することになりました。

AWSのASGを設定しcluster-autoscalerをクラスタにデプロイします。

一緒にdeschedulerもデプロイしました。

あとは、アプリケーションデプロイ用のhelmのchartにHorizontalPodAutoscalerの設定を追加するだけです。

と、ここでhelmでのデプロイが出来なくなりました。。。

「まさか」と思われる方もいるかと思いますが、クラスタを切り離せる安心感から一方のクラスタのみRancherを最新のバージョンに上げkubernetesも最新のバージョンを使いました。

この時点で各クラスタのkubernetesバージョンは以下

  • production green:v1.13
  • production blue:v1.17
  • staging:v1.15

導入時のバージョンと勢いに任せて更新した環境が混在していました。

そうですね、初心者丸出しです。エンジニアとしてあるまじき行為です。

helmでのデプロイが出来なくなった原因は下記でアナウンスされています。

kubernetes.io

他にもRancherのIngressバージョンの違いによる初期設定値の違いなどで課金系でちょっとした障害が発生しました。

静かにhelmのchartを修正しリリースノートには目を通そうと心に誓いました。。。。

builderクラスタ統合

この辺りでbuild/デプロイ処理に使用しているDrone(v0.8系)が不調になります。

完走率が5割前後となってしまいました。

バージョンも古くβ版だったのでv1.0以降の最新版に更新することを検討しました。

しかし、v1.0以降の正式リリースバージョンでは、community版でも機能制限があるので移行をあきらめました。

drone.io

Drone用にbuild専用クラスタを用意して使用していたので割り当てるリソースを増やす事で夜間/休日は使用されないbuild専用のコストが増加するため躊躇していましたが、不調なままではリリースもままならなくなってきたので、サービス用のクラスタにDroneを移動して割り当てるリソースを増やしました。

サービス用のクラスタは、それなりのサイズがあるのでDroneを拡張しても隙間のリソースを使うだけでした。

「木を隠すなら森の中」

f:id:r-smd:20200527081808p:plain:w600
forest

保守/運用について

オンプレ/クラウドインスタンスでの運用からコンテナ環境での運用に移行するときに大きく変わる事に以下があります。

  • デーモンが気軽に動かせない

コンテナ環境に慣れてくればdaemonsetsidecarで実装することになると思いますが、構築したての頃は、Linuxで当たり前に動いていた機能が使えないことに戸惑います。

  • メールが送れない
  • crontabが使えない
  • 監視ツールなどのエージェントが起動できない

などなど今まではサーバを起動した時から使えていたり、yumやaptで手軽に稼働させることが出来たことが全くできなくなります。

弊社のシステムでは以下のようにしました。

  • メールが送れない
    • プログラムでローカルのMTAに送りMTAからSMTPサーバに送信していたものをプログラムからSMTPサーバに送る様に変更
  • crontabが使えない
    • 日々増える作業ブランチごとのreview環境やElasticSearchにためているのaccessログを定期的に削除する処理をCronJobで作成
  • 監視ツールなどのエージェントが起動できない
    • 既存のzabbixサーバに向けるzabbixエージェントをdaemonsetで起動

コンテナ環境からは少し離れますが、accessログをfluentdでElasticSearchに溜めていたAmazon Elasticsearch Serviceのドメインが壊れました。

誤解を招く表現なので、正しくは壊しました。(問い合わせたところサポートの方にかる~く怒られました。申し訳ありません)

原因は初期設定値のまま大量のaccessログを長期間溜め過ぎたという事です。

詳しくは下記辺りをご覧ください。(サポートの方から丁寧にご案内頂きました。ありがとうございます)

docs.aws.amazon.com aws.amazon.com

ElasticSearch初心者の過ちでした。

accessログなのでnumber_of_shards=1に変更、保存期間を短くして元気に稼働しています。

日単位に作成しているindexも見直すべきなのですが、fluentdのルールを見直す元気をためているところです。

弊社にもサポートチームがあります、本当に有難いです。

サポートご担当者様、日々のご対応本当にありがとうございます。

コンテナ環境でのサービス運用について

初期の段階からコンテナ環境を使用する場合は、今回のように順次移行/再構成を行う必要はないと思います。

既存の単純ではない小規模ではないサービスをコンテナ環境に移行する場合は、マイクロサービス/機能単位で稼働が保証されている部分を残しつつ、影響範囲を最小の単位に分けて進めるのが安全だと思います。

もちろん、既存の環境での開発/運用に何の支障も不満も課題も懸念もなければ流行に乗ってコンテナ化する必要は全くありません。

コンテナ環境への移行作業のコストや移行後の運用コスト、メンバーのコンテナ知識習得コスト、メリット/デメリットなどなど十分に検討/検証の上実施するべきです。

弊社サービスのコンテナ環境での運用は初期段階で、まだまだkubernetesで運用しているとは言い切れない状態です。

f:id:r-smd:20200527081821p:plain:w600
Improve

(赤丸のサーバラックの前で佇んでしまいそうな当たりの整理が必要そうです)

以前バッチ処理をcrontabからDkronに移行しました。

texta.pixta.jp

現在Dkronからコンテナ上のCronJobに移行中です。

texta.pixta.jp

今後もコンテナ環境への移行と改善を進めて行く事になるでしょう。

足元を固める

ここまでの前書きはいかがでしたでしょうか?

ここからが本題です。

開発のためにDocker環境を稼働させるにはPCパワーが必要になります。

Docker環境を動かしdocker buildを走らせるとPCのファンが唸りを上げ、缶コーヒー程度の保温が出来るくらいの熱を持つようになります。

常に熱い状態で一日中稼働させることを長期間続けていると。。。

そう、バッテリーが膨張しノートPCが膨らんでタッチパッドが浮かんできます。

f:id:r-smd:20200527145255j:plain:w450
浮いたタッチパッド

サポートも切れていて今回買い替えも検討しましたが、使用中の物と同程度のスペックの物しかなく、あまり心に響くものが見つかりませんでした。。。

買い替えはもう少し待つことにしてバッテリー交換をする事にしました。

バッテリー交換は自己責任です

使用中のモデルは「DELL Inspiron13 7000 Series」で交換用のバッテリーを購入しました。

f:id:r-smd:20200527145350j:plain:w450
交換用バッテリー

裏のネジをすべて外し

f:id:r-smd:20200527145417j:plain:w450
ネジを外す

裏蓋を外します

f:id:r-smd:20200527145438j:plain:w450
裏蓋を外す

外したバッテリーは、なんだかボコボコです。。。

f:id:r-smd:20200527145501j:plain:w450
ボコボコ1

分かりにくいですが、机に置くと隙間があります。

f:id:r-smd:20200527145532j:plain:w450
隙間

新しいバッテリーと比べると、やっぱりボコボコです。。。

f:id:r-smd:20200527145629j:plain:w450
ボコボコ2

新しいバッテリーを付け裏蓋を閉じます

f:id:r-smd:20200527145655j:plain:w450
裏蓋を閉じる

見事にタッチパッドが元に戻りました。

f:id:r-smd:20200527145255j:plain:w450
浮いたタッチパッド

f:id:r-smd:20200527145747j:plain:w450
戻ったタッチパッド

ボコボコです。。。

f:id:r-smd:20200527145808j:plain:w450
ボコボコ3

やっぱりボコボコです。。。

f:id:r-smd:20200527145827j:plain:w450
ボコボコ4

今でも元気に唸りを上げています。

おわりに

今回の内容はいかがだったでしょうか。

一度コンテナ化に挫折してからの道のりを簡単にまとめてみましたが、実際は大小さまざまな壁を記憶がないほど沢山乗り越えて何とかproduction環境での運用までたどり着きました。

これまでコンテナ環境にあまり触れてこなかった方も一度開発環境などで使用してみてはいかがでしょうか。

最後に、バッテリー交換は自己責任で行ってください

皆様、本当にありがとうございます!!

* * * * * * * * * *

ピクスタでは、マスクも似合うエンジニアを募集しています。

recruit.pixta.co.jp