Synergy!のインフラを担当している清水です。今回は半年ほどかけてオンプレミスにKubernetesを導入したお話をしたいと思います。
関西中心にスマートスピーカー開発者コミュニティで活動してます。
あと、ギター弾きます。ブリティッシュロックが好きです。
目次
経緯
当社の主要サービスであるSynergy!のインフラは、ほぼいわゆる「オンプレミス」で動いています。データセンターに物理サーバやネットワーク機器を設置、仮想化基盤ソフトウェアなども使って、構築から運用までをすべて自社で行うというものです。そして、このインフラ上に開発チームが開発したアプリケーションが乗る形で「サービス」として提供しています。
長年蓄積されたノウハウにより、これらのインフラ運用はかなり効率化・自動化されているのですが、ここ数年進めてきたアプリケーションのマイクロサービス化に伴い、システムが複雑化、インフラの運用も徐々に追いつかなくなり、開発サイクルにも影響が出てきているというのが課題となっていました。そのあたりは以下でもご紹介しています。
TECHSCORE BLOG マイクロサービスを数年間実践して見えた課題とその対策
上記の記事でも、この課題に対する1つの解として「コンテナ化」を挙げていますが、一部の社内向けシステムではAWS上でKubernetesの構築・運用を既に行っており、十分な運用ノウハウが溜まりつつあるということで、昨年末に本格的なオンプレミスへのKubernetes導入が決まりました。
導入に向けた課題
昨今一般的に語られているKubernetesの導入・運用は、パブリッククラウドのマネージドサービスを使うというものが主流かと思いますが、当社の場合、BtoBtoCのサービスであり、当社サービスをご利用いただいているお客様の顧客データを取り扱う以上、「オンプレミスでやる」というのが大前提になります。
したがって以下の点が課題となります。
- External Load Balancerをどうするか?
- どの構築ツールを選ぶべきか?
External Load Balancerをどうするか?
パブリッククラウドでマネージドKubernetesを選ぶことのメリットの1つに、外部のロードバランサーと連携してpodへのルーティングをよしなにやってくれることがありますが、オンプレミスの場合はそうはいきません。
オンプレミスの場合は、MetalLBを使うのが主流のようです。当社の現在の環境では商用ロードバランサーを使っているのですが、このロードバランサーの機能をかなり深いところまで使い込んでおり、MetalLBにリプレースした場合に現在と同じことが実現できるのか、また、サービスへの影響はないのか、が大きな懸念でした。
これ以外にも、移行するアプリケーションの構成にあまり変更を加えたくないということもあり、安定性重視の観点から一旦MetalLBは諦めて、現行のロードバランサーをそのまま使って実現することとしました。つまり、
- 各サービスごとにNodePortを振る
- NodePortに対してロードバランサーでバランシングする
という、type: LoadBalancer がやってくれることを人の管理でやるということです。管理上煩雑にはなるので泣く泣くというところはありますが、NodePortの管理をきちんと管理できれば問題ないだろうということ、NodePortの場合、ノードに割り当てられたIPアドレスがエンドポイントとなるためノード故障時にSPOFになるということについても、商用ロードバランサー側のヘルスチェックできちんと対応できる、ということで今回はこの結論に至っています。
Kubernetesへの移行がある程度落ち着いたタイミングで再度検討していければと思っています。
構築ツールの選定とノウハウの偏り
次に構築ツールです。最初に述べた、社内向けに利用しているKubernetes環境はAWS上で構築・運用しており、これはkopsを使って構築しています。そこでkopsを含めて以下のツールを候補としてリストアップしました。
ツール名 | 提供元 | 特徴 |
---|---|---|
kops | Kubernetes SIG(公式のサブプロジェクト) |
|
Kubeadm | Kubernetes公式 |
|
Rancher | RancherLabs ※2020/7/8にSUSEが買収 |
|
どのツールを選ぶか?は現在・将来のノウハウの蓄積という点にも左右されます。社内向けにAWSでKubernetes環境をこれまで運用してきたものの、これらの構築・運用に携わっているメンバーは特定のメンバーに偏っており、今後は他のメンバーにも広く展開していく必要があります。
既に利用しているkopsをそのまま使えれば、これまでのノウハウを活かせる形になるので一番理想的だったのですが、残念ながらkopsは現状ほぼAWS専用であり、オンプレミスでは利用できません。
Rancherは、GUIで操作・管理ができ、カタログを使った機能追加もかんたんという点から、社内に広く展開していく上でハードルが低く、非常に魅力的に見えたのですが、
- 当社が使用している仮想化基盤ソフトウェアとの連携で一部動作しない点があり、これを解決できなかった
- かんたんに使えそうな反面、障害やトラブルが起きた場合のトラブルシューティングに懸念があった
という点で残念ながら今回は外しました(あくまでも当社の現在の状況にあわなかっただけで、Rancher自体はとても良いソフトウェアだと思っています。機会があればまたお話したいと思います。)
Kubeadmについては、少し手数が多くなる感はあるものの、逆に仕組みの理解がしやすいこと、ドキュメントが揃っていることなどから、今後のノウハウ蓄積を考えた場合、現時点では好ましいと判断しました。Kubernetes公式であり、実績があるということについては言うまでもありません。
実際の構築と導入
ロードバランサーの実装や構築ツールの選定方針も固まったので、いよいよKubernetesクラスタの構築に入ります。Kubeadmを使ったKubernetesクラスタ構築については、世の中に情報も多く出回っており、特筆すべき点はありません。
また周辺ツールについても同様で、いわゆるベストプラクティスに近いのではないかなと考えています。
コンポーネント | 選定したツール |
---|---|
監視 | Prometheus / AlertManager / Grafana |
ログ | fluentd |
CI/CD | GitLab / Gitlab Runnner |
Dockerレジストリ | Amazon ECR |
少し話が逸れますが、「オンプレミスのKubernetesは運用が大変」という話がよくあります。最初に述べたような外部ロードバランサーとの連携ももちろんありますし、プロビジョニング・スケーリング・バージョンアップなどがを考えるのは大変、ということはもちろん理由としてあるのですが、実はこういった「周辺ツール」も含めて全てを整備していかないといけない、という点も大きいのではないかなと思っています。
パブリッククラウドの場合はこういったものもサービスとして提供されており、連携がしやすくなっていたりしますが、オンプレの場合に、もしゼロからこれら全てを構築するとなるとさすがに難しかったと思います。また、インフラチーム寄りのツール(監視やログ)もあれば開発チーム寄り(CI/CD)のツールもあるため、チーム間の連携体制も必要になります。
当社の場合、実はこれらの周辺ツールを現行のオンプレミス環境でも利用しており、開発チーム・インフラチームでこの辺のノウハウが共有されています。これらをそのまま活用できたので、実質的にKubernetesに集中できたというのは大きかったと思っています。私個人としても、Kubernetesを本格的にやったのは今回が初めてで、周辺ツールも触ったことがないものがあったのですが、先輩・同僚エンジニアの知見やノウハウに非常に助けてもらいました。
導入については、まずはスモールスタートということで、一部の社内向けアプリの移行から、一発で導入完了!
・・・というわけにはさすがにいかず、いろいろな紆余曲折もあるにはあったのですが、それらについては地道に対応を進めて、最終的には5月にひとまず導入完了しました!
導入後
導入後2ヶ月経過し、現在も既存サービスの移行を徐々に進めている最中です。今のところは大きな障害もなく、安定しているようですが、1つだけ、障害ではないものの、想定していなかった事象がありました。
上で記載した構成のうち、Dockerレジストリだけが「Amazon ECR」になっている点に違和感を感じた方もいるのではないかと思います。元々オンプレミスの環境にもDockerレジストリが存在しておらず、現行のビルドフローでAmazon ECRを使っているので、そのまま利用する形にしていました。
当初は何も問題なかったのですが、たまにpodのデプロイに非常に時間がかかるということがありました。ただ、発生頻度はそれほど高くなくスムーズにデプロイが出来る場合もあり、サービス的にも問題が起きてない、ということで、当初は様子見していたのですが、徐々に発生頻度が高くなり、これはなにかおかしいと。調査を進めていくと、どうもAmazon ECRからのdockerイメージの初回pullに限り時間がかかっているようです。
実は、今回構築したKubernetes環境のアクセス部分は、サービス用とシステム内部処理用で以下のように回線を分けています。
- サービス
- インターネットからのpod、つまり お客様からのサービスへのアクセス
- データセンターのインターネット接続サービスを利用
- システム内部処理
- システム内部処理で使用、例えばOSパッケージのダウンロードなど
- 別途契約したビジネス向け光回線を使用
Kubernetes導入の目的の1つに開発サイクルのスピード化があります。つまり、各podのDockerイメージの更新頻度が高くなり、デプロイ回数も増えるというわけです。一つ一つはそれほど大きなトラフィックが発生するわけではありませんが、worker nodeの数が増えればその台数分だけ発生しますし、マイクロサービス化されているとサービスの数だけ発生することになります。これらの処理によりサービスに影響を与えるというわけにはいきません。 また、Kubernetesでは、nodeやpodに障害が問題が起こった場合に自動で検知・podの修復を行う、セルフヒーリングの機能がありますが、サービス側のトラフィック状況でこの処理が遅延する、ということになってしまうと、セルフヒーリング自体の意味がなくなってしまいます。
お互いの処理が影響しあわないようにという意図から回線を分けていたのですが、Amazon ECRからのdocker pullは後者を利用しており、どうやら内部処理側回線を使用した場合にのみ発生するようです。
回線側起因の可能性も頭に浮かんだのですが、ビジネス用の回線を契約しており一般回線に比べれば帯域や収容率にも余裕があるはずです。ちょっと考えにくいと思いつつも、念のためということでプロバイダに問い合わせてみたところ、
原因はなんと「新型コロナ」でした!
・・・ちょっと語弊がある書き方ですみません。正しくは「新型コロナ対策による、リモートワークの増加による、トラフィックの増加による、プロバイダ側設備の混雑」が原因です(長い)。
当社もそうなのですが、昨今、コロナ対策としての「リモートワーク」が増加しています。これにより、一般回線だけでなくビジネス用回線の利用率やトラフィックも増加しており、プロバイダ側設備で輻輳が発生しているということだそうです。巡り巡ってまさかこんなところで影響を受けるとは思っていませんでした・・・。内部処理用途であり「現時点」ではそれほどトラフィックも想定しておらず、コストの観点からもベストエフォートタイプを選択していたのも一因です。また、回線状況に左右されるため必ずしも発生しない、一旦node側にpullされてしまうとキャッシュされてしまい問題が発生しなくなることから、問題検知から原因特定まで時間がかかってしまったことも反省すべき点です。
現在の情勢からは回線状況の改善は当面見込めそうにないことを踏まえ、Dockerレジストリを、Amazon ECRから、CI/CDで使っている内部のGitLab上のContainer Registryに変更することで、少なくともKubernetesクラスタからのpullについてはローカルのネットワークで完結させることで対応しました。ただ、これについてもあくまでも暫定的な対応であり、GitLab Container Registryへのpushは今も同じ内部用回線で行っているので、ビルドからのデプロイは依然として遅い場合があります。今後は回線契約の見直し等も検討していきたいと思っています。
原因としては至って単純なのですが、昨今の状況を踏まえて紹介しておきます。
まとめ
なんとか導入までこぎつけることができてホッとしているところですが、これからも移行は続きますし、今後も想定しない事象が起きることもあるでしょう。再度、気を引き締めつつ、ひとつずつコツコツと進めていきたいと思っています。
今回 Kubernetes導入に携わってみて良かったと思うのは、
- 今後のコンテナプラットフォームのデファクトスタンダードとも言えるKubernetesそのものについての知見やノウハウを得られた
- インフラやシステムだけではなく、アプリケーションの開発フローだったり、それを支える周辺ツールなどのエコシステムも含めた、現時点でのプロダクト開発・運用のベストプラクティスの1つを知ることができた
です。
逆に言うと、これらを全部をやっていくことになるのでその分大変な面もありますが、当社にはそれを助けてくれる強いエンジニアがたくさんいます。今後、社内でも知見やノウハウを展開してKubernetesエンジニアを増やしていきたいと思っていますし、また、Kubernetesガッツリやってみたいというエンジニアを募集しています。一緒にやっていきましょう!ご興味があればぜひお気軽にお声がけください。