Kubernetesの健全な管理を学ぶ

すべての人に良い一日を!



私たちは愛する伝統、つまり私たちが収集し、コースの一部として研究するユーティリティの配布に戻ります。 本日、 DevOpsコースとそのツールの1つであるKubernetesがアジェンダにあります。



最近、コンテナオーケストレーション用の新しいエキサイティングなプラットフォームであるKubernetesに基づく分散cronジョブプランニングシステムを作成しました。 Kubernetesはますます人気が高まっており、多くの約束があります。たとえば、エンジニアがアプリケーションを実行しているデバイスを心配する必要はありません。



分散システムはそれ自体が複雑であり、分散システムでのサービスの管理は、管理チームが直面する最も困難な問題の1つです。 新しいソフトウェアの生産への導入と、信頼性の高い管理のトレーニングを非常に真剣に受け止めています。 Kubernetesを管理することの重要性の例(およびなぜそれが非常に複雑なのか!)として、Kubernetesのバグによって引き起こされる事後の優れた1時間ごとの停止を確認してください。



この投稿では、Kubernetesが選ばれた理由を説明します。 既存のインフラストラクチャへの統合プロセス、Kubernetesクラスターの信頼性の構築(および改善)方法、およびKubernetesに基づいて作成された抽象化について検討します。







Kubernetesとは何ですか?



Kubernetesは、クラスターで実行するプログラムを計画するための分散システムです。 Kubernetesにプログラムの5つのコピーを実行するように指示すると、作業ノードでそれらを動的にスケジュールします。 コンテナは使用率を高め、それによりコストを削減し、強力な展開プリミティブにより新しいコードを徐々に展開できます。 セキュリティコンテキストネットワークポリシーにより、マルチテナントワークロードを安全に実行できます。



Kubernetesには、さまざまなスケジューリングオプションが組み込まれています。 長時間実行されるHTTPサービス、クラスター内のすべてのマシンで実行されるデーモンセット 、1時間ごとに実行されるタスクなどをスケジュールできます。 Kubernetesはさらに優れています。 知りたい場合は、Kelsey Hightowerの優れたパフォーマンスを確認してください。 システム管理者とhealthz 向けのKubernetesから始めることができます。 Slackの良いコミュニティを忘れないでください。



Kubernetesを選ぶ理由



各インフラストラクチャプロジェクト(願っています!)はビジネスのニーズから始まります。私たちのタスクは、既存のcronジョブプランニングシステムの信頼性とセキュリティを改善することです。 要件は次のとおりです。





そして、Kubernetesを選んだ理由はいくつかあります。





以前は、タスクスケジューラとしてCronosを使用していましたが、信頼性の要件を満たすのをやめ、現在ほとんどサポートされていません(過去9か月で1コミット、2016年3月にプルリクエストが最後に追加されたとき)。 したがって、既存のクラスターの改善に投資することはもう決めませんでした。



Kubernetesを検討している場合は、他の会社がKubernetesを使用しているという理由だけでKubernetesを使用しないでください。 信頼性の高いクラスターを作成するには、膨大な時間が必要であり、ビジネスでの使用方法は必ずしも明らかではありません。 時間を賢く投資してください。



信頼性とはどういう意味ですか?



サービス管理に関しては、「信頼できる」という言葉自体は意味がありません。 信頼性について話すには、最初にSLO(サービスレベル目標、つまりサービスの目標レベル)をインストールする必要があります。



3つの主なタスクがありました。



  1. タスクの99.99%を計画し、計画時間の20分以内に実行する必要があります。 20分というのはかなり長い時間ですが、社内のクライアントにインタビューしたので、これ以上正確性を要求する人はいませんでした。
  2. 割り当ては、ケースの99.99%で完了する必要があります(中断することなく)。
  3. Kubernetesへの移行により、クライアント側のインシデントが発生することはありません。


これにはいくつかの意味があります。





Kubernetesクラスターの作成



最初のKubernetesクラスターを作成する基本的なアプローチは、 kubeadmkopsなどのツールを使用せずにクラスターをゼロから作成することでした 。 標準の構成管理ツールであるPuppetを使用して構成を作成しました。 ゼロから作成することには2つの理由があります。Kubernetesをアーキテクチャに深く統合できることと、その内部構造に関する幅広い知識を得たことです。



最初から構築することで、Kubernetesを既存のインフラストラクチャに統合できました。 ロギング、証明書管理、シークレット、ネットワークセキュリティ、モニタリング、AWSインスタンス管理、デプロイ、プロキシデータベース、内部DNSサーバー、構成管理など、既存のシステムとのシームレスな統合を望んでいました。 これらすべてのシステムの統合には創造的なアプローチが必要な場合がありましたが、一般に、kubeadm / kopsに必要な処理を強制する試みよりも簡単であることが判明しました。



私たちはすでに既存のシステムを管理する方法を信頼し、知っているので、新しいKubernetesクラスターでそれらを引き続き使用したいと考えました。 たとえば、信頼できる証明書管理は非常に難しい問題ですが、既に解決する方法があります。 有能な統合により、Kubernetes用の新しいCAの作成を回避できました。



Kubernetesのインストールにどのような設定が影響するかを正確に理解する必要がありました。 たとえば、証明書/ CA認証を構成するために12個以上のパラメーターが使用されました。 これらのオプションをすべて理解することで、認証の問題が見つかったときにインストールをデバッグしやすくなりました。



Kubernetesの信頼を築く



Kubernetesの使用開始当初、チーム内の誰も使用していません(ホームプロジェクトのみ)。 「私たちは誰もKubernetesを使用したことがありません」から「本番環境でKubernetesを使用することに自信があります」からどのように来るのでしょうか?







戦略0:他の会社と話す



Kubernetesでの経験について他の企業の何人かに尋ねました。 彼らはすべて、さまざまな方法でさまざまな環境でそれを使用しました(HTTPサービスの開始、ベアメタル、 Google Kubernetes Engineなど)。



Kubernetesのような大規模で複雑なシステムに関しては、アプリケーションのケースについて考え、実験し、環境に自信を持ち、自分で決定することが特に重要です。 たとえば、この投稿を読んだ後は、「KubernetesはStripeで正常に使用されているので、できます!」と決めてはいけません。



Kubernetesのさまざまなクラスター管理会社との会話から学んだことは次のとおりです。





もちろん、他の企業との会話では、Kubernetesが私たちに適しているかどうかについて明確な答えを出していませんでしたが、質問や懸念を提供してくれました。



戦略1:コードを読む



Kubernetesの1つのコンポーネントであるcronジョブコントローラーに大きく依存することを計画しました。 その時、彼はアルファであり、興奮の少しの原因でした。 テストクラスタでテストしましたが、運用環境で適切かどうかを確認するにはどうすればよいでしょうか。 幸いなことに、すべてのコントローラー機能コードは400行で構成されています。 ソースコードをすばやく読むと、次のことがわかりました。



  1. コントローラーはステートレスサービスです(etcdを除く他のKubernetesコンポーネントと同様)。
  2. 10秒ごとに、このコントローラーはsyncAll関数を呼び出します:go wait.Until(jm.syncAll、10 * time.Second、stopCh);
  3. syncAll関数は、Kybernetes APIからすべてのタスクを返し、このリストを調べて、次に開始するタスクを決定してから開始します。


基本的なロジックは簡単に理解できました。 さらに重要なことは、コントローラーでバグが検出された場合、おそらく自分で修正できることです。



戦略2:ストレステストを実行する



クラスターの構築を開始する前に、負荷テストを実施しました。 Kubernetesクラスターが処理できるノードの数については心配していませんでした(約20ノードを展開する予定でした)。Kubernetesが必要な数のタスクに耐えられることを確認することが重要でした(1分あたり約20)。



3日間のクラスターでテストを実施し、1000のcronジョブが作成され、それぞれが1分間に1回起動されました。 すべてのタスクはbash -c 'echo hello world'を実行しただけです。 単純なタスクを選択したのは、全体的なコンピューティング能力ではなく、クラスター計画とオーケストレーションの機能をテストしたかったからです。



テストクラスターは、毎分1000タスクに耐えることができませんでした。 各ノードは1秒あたり最大1つを起動し、クラスターは問題なく1分あたり200タスクを実行できることがわかりました。 1分間に約50のタスクが必要であることを考えると、そのような制限は私たちをブロックしないと判断されました(そして、必要に応じて後で解決できます)。 どうぞ!



戦略3:フェールオーバーetcdクラスターの作成とテストの優先順位付け



Kubernetesを設定する場合、etcdを正しく実行することが非常に重要です。 EtcdはKubernetesクラスターの中心であり、クラスターに関するすべてのデータが保存されます。 etcdを除くすべてに状態はありません。 etcdが実行されていない場合、Kubernetesクラスターに変更を加えることはできません(ただし、既存のサービスは引き続き機能します!)。







起動時に、2つの重要な点に留意する必要があります。





レプリケーションの構成-タスクは「忘れられた」カテゴリーではありません。 etcdノードが失われても、クラスターは引き続き正常に復元されることを慎重にテストしました。



etcdクラスターを構成するために実行したタスクの一部を以下に示します。





早めにテストしていただき、大変うれしく思います。 ある金曜日の朝、etcdノードの1つが実稼働クラスターでpingを停止しました。 これに関する警告を受け、ノードを破壊し、新しいノードを作成し、クラスターに追加しました。この間、Kubernetesは中断することなく動作を続けました。 すごい



戦略4:タスクをKubernetesに徐々に転送する



私たちの主な目標の1つは、混乱を引き起こすことなくタスクをKubernetesに転送することでした。 生産移管を成功させる秘secretは、エラーのないプロセス(これは不可能です)ではなく、エラーによる害を減らすような方法でプロセスを設計することにあります。



私たちは新しいクラスターへの移行を必要とする多種多様なタスクの幸せな所有者だったので、その中には影響力の低いものがありました-それらを転送する際のいくつかのエラーは許容できました。



移行を開始する前に、古いシステムと新しいシステム間で5分以内にタスクを移動できる使いやすいツールを作成しました。 このツールはエラーによるダメージを軽減しました-計画していない依存関係を持つタスクを転送した場合、問題ではありません! 単純に元に戻し、問題を修正して再試行できます。



この移行戦略を順守しました。



  1. 重要度に応じてタスクを大まかに分散します。
  2. 複数のタスクをKubernetesに繰り返し転送します。 新しい問題領域が見つかった場合は、すぐにロールバックし、問題を修正して再試行してください。


戦略5:Kubernetesのバグを調査する(および修正する)



プロジェクトの最初に、ルールを設定します。Kubernetesが予期しないことをした場合、理由を理解して修正を提案する必要があります。



各バグの解析には時間がかかりますが、非常に重要です。 Kubernetesの奇妙な動作を単純に却下し、分散システムの複雑さが原因であると判断した場合、新しいバグが発生するたびに、それは私たちのせいだと思われます。



このアプローチをとった後、Kubernetesにいくつかのバグが見つかりました(そして修正されました!)。

これらのテスト中に見つかった問題の一部を次に示します。





これらのバグを修正することで、プロジェクトでのKubernetesの使用との関連性が高まりました。十分に機能するだけでなく、パッチも受け入れられ、優れたPRレビュープロセスが行われました。



Kubernetesには、他のソフトウェアと同様にバグがたくさんあります。 たとえば、スケジューラは頻繁に使用します(タスクは常に新しいポッドを作成するため)。また、スケジューラのキャッシュの使用は、バグ、リグレッション、クラッシュに変わることがあります。 キャッシングは難しいです! しかし、コードベースはアクセス可能であり、遭遇したすべてのバグに対処することができました。



もう1つの注目すべき問題は、Kubernetesの炉床転送ロジックです。 Kubernetesには、ノードコントローラーと呼ばれるコンポーネントがあります。このコンポーネントは、ハースを削除し、応答がない場合に他のノードにハースを移動します。 すべてのノードからの応答がない場合(ネットワークおよび構成の問題など)、Kubernetesはクラスター内のすべてのポッドを破棄できる場合があります。 テストの開始時にこれに直面しました。



大規模なKubernetesクラスターを起動する場合は、ノードコントローラーのドキュメントを注意深く読み、構成を検討し、ハードテストを行います。 ネットワーク制限を作成することにより、この設定の構成(--pod-eviction-timeoutなど)の変更をテストするたびに、驚くべきことが起こりました。 実稼働時の午前3時にではなく、テストからそのような驚きについて学ぶことをお勧めします。



戦略6:Kubernetsクラスターに意図的に問題を作成する



Stripeでのゲーミングデイエクササイズの開始については既に説明しましたが、現在も継続しています。 アイデアは、本番環境で発生する可能性のある状況(たとえば、Kubernetes APIサーバーの損失)を考え出し、それを具体的に作成して(営業日中に警告を表示)、それらを修正できることを確認することです。



クラスターでいくつかの演習を行うと、ギャップの監視や構成エラーなどの問題が明らかになりました。 6か月後の偶然ではなく、事前に管理された環境でこれらの問題を発見できたことを非常に喜んでいます。



私たちが実施したいくつかのゲーム演習:





Kubernetesが故障に十分耐えられたことを非常に嬉しく思います。 Kubernetesはエラーに耐えるように設計されています-すべての状態を保存するetcdクラスター、データベース用のシンプルなRESTインターフェイスであるAPIサーバー、およびクラスター管理を調整するステートレスコントローラーのセットがあります。



Kubernetesのルートコンポーネント(APIサーバー、コントローラー管理、スケジューラー)のいずれかが中断されて再起動された場合、回復後すぐにetcdから状態を読み取り、動作を継続します。 これは理論的に引き付けられたものの1つであり、実際にはそれ以上に悪化することはありませんでした。



テスト中に見つかった問題の一部を次に示します。





これらのテストを開始した後、見つかった問題を修正しました。監視の改善、見つかった構成設定の修正、Kubernetesのバグの文書化です。



cronジョブを使いやすくします。



Kubernetesベースのシステムをどのように使いやすくしたかについて簡単に説明します。

最初の目標は、チームが自信を持って管理できるタスクを実行するシステムを設計することでした。 Kubernetesに自信を持つようになったとき、エンジニアが新しいcronジョブを簡単に構成して追加することが必要になりました。 ユーザーがシステムを使用するためにKubernetesの内部構造を理解する必要がないように、構成YAML形式を開発しました。 形式は次のとおりです。



name: job-name-here kubernetes: schedule: '15 */2 * * *' command: - ruby - "/path/to/script.rb" resources: requests: cpu: 0.1 memory: 128M limits: memory: 1024M
      
      





複雑なことはありません-この形式を取り cronジョブKubernetes構成に変換するプログラムを作成しました。これをkubectlで使用します。



また、長さ(Kubernetesタスク名は52文字を超えることはできません)およびタスク名の一意性をチェックするためのテストスイートも作成しました。 現在、ほとんどのタスクでcgroupを使用してメモリ量を制限していませんが、これは将来の計画に含まれています。



この形式は使いやすく、Chronos cronジョブとKubernetes cronジョブの両方を自動的に生成したため、2つのシステム間でタスクを移動するのは簡単でした。 これは、段階的移行の優れた作業における重要な要素でした。 Kubernetesへのタスクの転送でエラーが発生した場合、10分以内に簡単な3行の構成変更を行うだけで、タスクを転送できます。



Kubernetesの監視



Kubernetesクラスターの内部状態を監視することは楽しいことが実証されています。 監視にkube -state-metricsパッケージを使用し、 veneur-prometheusと呼ばれる小さなGoプログラムを使用して、 kube -state-metricsが発行するPrometheusメトリックを収集し、監視システムでstatsdメトリックとして公開します。



これは、たとえば、過去1時間のクラスター内の保留中の炉床の数のグラフです。 保留は、作業ノードへの割り当てが開始されるのを待っていることを意味します。 多くのタスクは1時間の0分から始まるため、午前11時にピーク値を確認できます。







さらに、Pending状態で停止しているポッドがないことを確認します。各ポッドが5分間動作ノードで起動することを確認します。そうでない場合は警告が表示されます。



Kubernetesの今後の計画



Kubernetesを構成し、本番コードを起動してcronジョブを新しいクラスターに移行する準備が整うまでに、3人のフルタイムプログラマーで5か月間で3か月かかりました。 Kubernetesの学習に投資した重要な理由の1つは、ストライプでKubernetesをより広く使用することを期待していることです。



Kubernetes(およびその他の複雑な分散システム)を管理するためのガイドラインを次に示します。





これらの原則に重点を置いて、Kubernetesを本番環境で自信を持って使用できます。 Kubernetesの使用は、成長と進化を続けます。たとえば、AWS EKSのリリースを興味を持って見ています。 別の機械学習モデルトレーニングシステムの作業を完了し、一部のHTTPサービスをKubernetesに移行するオプションも検討しています。 また、本番環境でKubernetesを使用する過程で、オープンソースプロジェクトに貢献する予定です。



終わり



いつものように、私たちはあなたのコメント、質問をここで、または私たちの公開日に待っています。



All Articles