はじめに
Kubernetesは、分散コンテナの大規模なクラスタを調整するための並外れたレベルの柔軟性を提供します。
利用可能な機能とオプションの膨大な数は、課題を提示する可能性があります。ベストプラクティスを適用することで、潜在的なハードルを回避し、最初から安全で効率的な環境を構築できます。
概説されているKubernetesのベストプラクティスを使用します 最適化されたコンテナを構築し、展開を合理化し、信頼できるサービスを管理し、本格的なクラスターを管理します。
コンテナの保護と最適化
コンテナは、仮想マシンよりもはるかに少ない分離を提供します。常にコンテナイメージを確認し、ユーザー権限を厳密に管理する必要があります。
小さなコンテナイメージを使用すると、効率が向上し、リソースが節約され、潜在的な攻撃者の攻撃対象領域が減少します。
信頼できるコンテナイメージのみを使用
既製のコンテナ画像は非常にアクセスしやすく、非常に便利です。ただし、パブリックイメージはすぐに古くなり、エクスプロイト、バグ、さらには悪意のあるソフトウェアが含まれ、Kubernetesクラスター全体に急速に拡散する可能性があります。
信頼できるリポジトリからのイメージのみを使用し、潜在的な脆弱性について常にイメージをスキャンします。 AnchoreやClairなどの多数のオンラインツールは、コンテナイメージの迅速な静的分析を提供し、潜在的な脅威や問題を通知します。コンテナイメージを展開する前にスキャンし、壊滅的な結果を招く可能性を回避するために、少し時間を取ってください。
非ルートユーザーと読み取り専用ファイルシステム
組み込みのセキュリティコンテキストを変更して、すべてのコンテナをroot以外のユーザーと読み取り専用のファイルシステムでのみ実行するように強制します。
rootユーザーとしてコンテナーを実行することは避けてください。ユーザーが自分自身に追加の権限を付与できる場合、セキュリティ違反はすぐにエスカレートする可能性があります。
ファイルシステムが読み取り専用に設定されている場合、コンテナのコンテンツを改ざんする可能性はほとんどありません。システムファイルを編集する代わりに、コンテナ全体を削除して、新しいコンテナをその場所に配置する必要があります。
小さくてレイヤー化された画像を作成する
小さいイメージはビルドをスピードアップし、必要なストレージが少なくなります。画像を効率的にレイヤー化すると、画像サイズを大幅に縮小できます。最適な結果を得るには、画像を最初から作成してみてください。
多数の異なるコンポーネントが必要な場合は、単一のDockerfileで複数のFROMステートメントを使用してください。この機能は、それぞれが異なるベースイメージを参照するセクションを作成します。最終的なイメージには、前のレイヤーが保存されなくなり、各レイヤーに必要なコンポーネントのみが保存されるため、Dockerコンテナーがはるかにスリムになります。
各レイヤーは、 FROM
に基づいてプルされます デプロイされたコンテナにあるコマンド。
RBACによるユーザーアクセスの制限
ロールベースのアクセス制御(RBAC)により、タスクを完了するために必要な権限を超える権限を持つユーザーがいないことが保証されます。 APIサーバーの起動時に次のフラグを追加することでRBACを有効にできます。
--authorization-mode=RBAC
RBACはrbac.authorization.k8s.ioを使用します KubernetesAPIを介して承認の決定を推進するAPIグループ。
StdoutおよびStderrログ
アプリケーションログをstdoutに送信するのが一般的な方法です。 (標準出力)ストリーム、および stderrへのエラーログ (標準エラー)ストリーム。アプリがstdoutとstderrに書き込むと、DockerなどのコンテナエンジンがレコードをリダイレクトしてJSONファイルに保存します。
Kubernetesコンテナ、ポッド、ノードは動的エンティティです。ログは一貫性があり、永続的に利用可能である必要があります。したがって、クラスタ全体のログを別のバックエンドストレージシステムに保存することをお勧めします。
Kubernetesは、ELKスタックなどのさまざまな既存のロギングソリューションと統合できます。
展開の合理化
Kubernetesデプロイメントは、ポッドが稼働していること、定期的に更新されていること、またはユーザーの定義に従ってロールバックされていることを確認するテンプレートを確立します。
明確なラベル、フラグ、リンクされたコンテナー、およびDaemonSetを使用すると、デプロイメントプロセスをきめ細かく制御できます。
レコードフラグの使用
--record
を追加する場合 フラグ、実行された kubectl
コマンドは注釈として保存されます。展開の展開履歴を調べることで、 CHANGE-CAUSEで更新を簡単に追跡できます。 列。
undoコマンドでリビジョン番号を宣言して、任意のリビジョンにロールバックします。
kubectl rollout undo deployment example-deployment --to-revision=1
--record
なし フラグを立てると、特定のリビジョンを特定するのが困難になります。
説明ラベル
できるだけ多くの説明ラベルを使用してみてください。ラベルは、ユーザーがポッドを意味のあるサブセットにグループ化および編成できるようにするキーと値のペアです。ほとんどの機能、プラグイン、およびサードパーティソリューションには、ポッドを識別して自動化されたプロセスを制御できるようにするためのラベルが必要です。
たとえば、Kubernetes DaemonSetsは、クラスター内のポッドのデプロイを管理するためにラベルとノードセレクターに依存しています。
ポッド内に複数のプロセスを作成する
コンテナ内のすべての問題を解決しようとするのではなく、Kubernetesのコンテナリンク機能を使用します。 1つのKubernetesポッドに複数のコンテナを効果的にデプロイします。良い例は、セキュリティ機能をプロキシサイドカーにアウトソーシングすることです。 コンテナ。
結合されたコンテナは、メインコンテナのコア機能をサポートまたは強化したり、メインコンテナをその展開環境に適応させたりするのに役立ちます。
Initコンテナを使用する
1つ以上のinitコンテナは通常、メインアプリケーションコンテナに含めたくないユーティリティタスクまたはセキュリティチェックを実行します。 initコンテナを使用して、ポッドのメインコンテナを開始する前にサービスの準備ができていることを確認できます。
各initコンテナーは、後続のinitコンテナーが開始する前に、正常に実行されて完了する必要があります。 Initコンテナは、前提条件が満たされるまで、ポッドのメインコンテナの開始を遅らせることができます。この前提条件がない場合、Kubernetesはポッドを再起動します。前提条件が満たされると、initコンテナーは自己終了し、メインコンテナーを開始できるようになります。
最新のタグの使用は避けてください
タグを使用しない、または :latest
を使用しないでください 実稼働環境にコンテナーをデプロイするときのタグ。最新のタグを使用すると、実行中のイメージのバージョンを特定するのが困難になります。
コンテナが常に同じバージョンの画像を使用するようにする効果的な方法は、タグとして一意の画像ダイジェストを使用することです。この例では、Redisイメージバージョンは独自のダイジェストを使用してデプロイされています:
[email protected]:675hgjfn48324cf93ffg43269ee113168c194352dde3eds876677c5cb
ダイジェスト値を変更しない限り、Kubernetesはイメージバージョンを自動的に更新しません。
準備と活気のプローブを設定する
活気 および準備プローブ Kubernetesがアプリケーションの状態を監視および解釈するのに役立ちます。活性チェックを定義し、プロセスが要件を満たしている場合、Kubernetesはコンテナを停止し、代わりに新しいインスタンスを開始します。
準備プローブは、ポッドレベルで監査を実行し、ポッドがトラフィックを受け入れることができるかどうかを評価します。ポッドが応答しない場合、準備プローブがポッドを再起動するプロセスをトリガーします。
準備と活性のプローブを構成するためのドキュメントは、Kubernetesの公式ウェブサイトで入手できます。
さまざまなサービスタイプを試す
さまざまなサービスタイプの利用方法を学ぶことで、内部および外部のポッドトラフィックを効果的に管理できます。目標は、IP、ポート、DNSなどの信頼できるエンドポイントを管理することで安定したネットワーク環境を作成することです。
NodePortを使用した静的ポート
サービスタイプをNodePortに設定して、ポッドを外部ユーザーに公開します。 nodePort
で値を指定した場合 フィールドでは、Kubernetesはすべてのノード間でそのポート番号を予約し、サービスの一部であるポッド向けのすべての着信トラフィックを転送します。このサービスには、内部クラスターIPと予約済みポートを持つノードのIPの両方を使用してアクセスできます。
ユーザーは、次のようにリクエストすることで、クラスターの外部からNodePortサービスに連絡できます。
NodeIP:NodePort
常にNodePort用に設定された範囲内のポート番号(30000-32767)を使用してください。 APIトランザクションが失敗した場合は、ポートの衝突の可能性をトラブルシューティングする必要があります。
Ingress vs LoadBalancer
LoadBalancerタイプは、プロバイダーのロードバランサーを使用してサービスを外部に公開します。 LoadBalancerタイプを使用して公開する各サービスは、そのIPを受け取ります。多くのサービスがある場合、公開されているサービスの数に基づいて、計画外の追加コストが発生する可能性があります。
標準の構成要件は、既存の静的パブリックIPアドレスを入力コントローラーに提供することです。入力コントローラが削除されても、静的パブリックIPアドレスは残ります。このアプローチにより、アプリケーションのライフサイクル全体で現在のDNSレコードとネットワーク構成を一貫して使用できます。
外部サービスをDNSにマッピングする
ExternalNameタイプは、サービスをセレクターにマップしませんが、代わりにDNS名を使用します。 externalNameを使用します CNAMEレコードを使用してサービスをマップするためのパラメーター。 CNAMEレコードは完全修飾ドメイン名であり、数値のIPではありません。
サービスに接続するクライアントは、サービスプロキシをバイパスし、外部リソースに直接接続します。この例では、 pnap-service admin.phoenixnap.comにマップされます 外部リソース。
pnap-serviceへのアクセス 他のサービスと同じように機能します。重要な違いは、リダイレクトがDNSレベルで行われるようになったことです。
アプリケーションの設計
Kubernetesを使用したコンテナの自動デプロイにより、ほとんどの操作が人間の直接入力なしで実行されるようになりました。アプリケーションとコンテナイメージは、互換性があり、継続的なマイクロ管理を必要としないように設計してください。
個々のサービスに焦点を当てる
アプリケーションを複数のサービスに分割し、単一のコンテナーに多くの機能をバンドルしないようにしてください。アプリが1つの機能の実行に重点を置いている場合、アプリを水平方向にスケーリングしてコンテナを再利用する方がはるかに簡単です。
アプリケーションを作成するときは、コンテナが短期間のエンティティであり、定期的に停止および再起動されると想定してください。
ヘルムチャートを使用する
KubernetesアプリケーションパッケージマネージャーであるHelmは、インストールプロセスを合理化し、クラスター全体にリソースを非常に迅速にデプロイできます。 Helmアプリケーションパッケージはチャートと呼ばれます。
MySQL、PostgreSQL、MongoDB、Redis、WordPressなどのアプリケーションは需要の高いソリューションです。いくつかの複雑な構成ファイルを作成および編集する代わりに、すぐに利用できるヘルムチャートを展開できます。
次のコマンドを使用して、クラスターでKafka Managerを実行するために必要なデプロイメント、サービス、PersistentVolumeClaims、およびシークレットを作成します。
helm install --name my-messenger stable/kafka-manager
特定のコンポーネントを分析して、Kafkaを適切に実行するようにコンポーネントを構成する方法を学ぶ必要がなくなりました。
ノードとポッドのアフィニティを利用する
アフィニティ機能は、ノードアフィニティとポッド間アフィニティの両方を定義するために使用されます。ノードアフィニティを使用すると、既存のノードラベルを使用して、ポッドがスケジュールされる資格のあるノードを指定できます。
- requiredDuringSchedulingIgnoredDuringExecution –ポッドをノードにスケジュールするために満たす必要のある必須の制約を確立します。
- PreferredDuringSchedulingIgnoredDuringExecution –スケジューラーが優先するが、保証しない設定を定義します。
実行時にノードラベルが変更され、ポッドのアフィニティルールが満たされない場合、ポッドはノードから削除されません。 nodeSelector
パラメータは、ラベルを使用してポッドを特定のノードに制限します。この例では、Grafanaポッドは ssdを持つノードでのみスケジュールされます。 ラベル。
ポッドアフィニティ/アンチアフィニティ機能は、表現できる制約のタイプを拡張します。ノードラベルを使用する代わりに、既存のポッドラベルを使用して、ポッドをスケジュールできるノードを描くことができます。この機能を使用すると、他のポッドのラベルに基づいて個々のポッドがスケジュールされるようにルールを設定できます。
ノードの汚染と許容範囲
Kubernetesは、ワークロードが最小の場所にポッドを自動的にデプロイしようとします。ノードとポッドのアフィニティを使用すると、ポッドをデプロイするノードを制御できます。汚染は、既存のポッドを変更することなく、特定のノードへのポッドの展開を防ぐことができます。汚染されたノードにデプロイするポッドは、ノードを使用するためにオプトインする必要があります。
- 汚染 –新しいポッドがノードでスケジュールされないようにし、ノードプリファレンスを定義し、ノードから既存のポッドを削除します。
- 許容範囲 –既存の一致する汚染があるノードでのみポッドをスケジュールできるようにします。
汚染と許容範囲を一緒に使用すると、ポッドが適切なノードにスケジュールされるようになり、最適な結果が得られます。
名前空間を使用してリソースをグループ化する
Kubernetes名前空間を使用して、大きなクラスターをより小さく、簡単に識別できるグループに分割します。名前空間を使用すると、個別のテスト、QA、本番、または開発環境を作成し、一意の名前空間内に適切なリソースを割り当てることができます。 Kubernetesリソースの名前は、単一の名前空間内で一意である必要があるだけです。異なる名前空間に同じ名前のリソースを含めることができます。
複数のユーザーが同じクラスターにアクセスできる場合は、ユーザーを制限して、特定の名前空間の範囲内での操作を許可できます。ユーザーを分離することは、リソースを区切り、潜在的な名前付けやバージョンの競合を回避するための優れた方法です。
名前空間はKubernetesリソースであり、作成が非常に簡単です。名前空間名を定義するYAMLファイルを作成し、kubectlを使用してKubernetesAPIサーバーに投稿します。その後、名前空間を使用して、追加のリソースの展開を管理できます。