Kubernetesデザイン

分析し、理解Kubernetesのデザインコンセプトは、私たちはより良いまた、分散システムの設計での経験上に描画するために私達を許可する一方、Kubernetesシステム、分散型の展開を管理し、クラウドネイティブアプリケーションをより有効に利用する、理解することができます。

抽象化する機能

一般的なPaaSのプラットフォームと比較すると、K8Sも展開、自動運転および維持管理、リソースのスケジューリング、容量スケーリング、自己修復、負荷分散、サービスの発見やその他の機能をサポートしていますが、その独自性は、インフラストラクチャ層に多くのためにそのです抽象的に良い能力。K8Sは行うが、インターフェイスのすべての種類を実現するために開始し、抽象化のすべての種類を行うために、ストレージ、ネットワーキング、クラウド何の特定の部分に対処する上でこれらの巨大な違いを持っ​​ていません。そのような容器ランタイムインターフェース(CRI)として、血管ネットワークインターフェース(CNI)、容器のストレージインタフェース(CSI)。これらのインタフェースは、Kubernetesは非常にオープンになることができ、あなたは独自の内部展開と船舶スケジューリングに焦点を当てることができます。

Kubernetesエコロジーにも、このようなサービス・ディスカバリ、負荷分散、システムログ、およびデフォルトのプログラムを提供している他の監視システム、など多くの共通の特徴を持っているだろう、とこれらのプログラムは、オプションのプラグ可能です。これらはまた、高度な柔軟性をユーザーに提供するために、Kubernetes強い強いネクタイピンには何の取引はありません、インフラのPaaSプラットフォームとして表示することができます。

様々な機能は、これらのオブジェクトは、クラスタにEtcdのAPIにより提出することができる定義切っても切れないリソースオブジェクトですKubernetes。定義と実装はHTTP REST APIの形式に沿ったもので、ユーザーが検索を変更するために追加または削除、関連するリソースを標準のHTTP動詞を通じてオブジェクトを完了するために、(POSTを、PUT、GET、DELETE)することができます。こうした展開、DaemonSet、仕事、PVなどの一般的なリソースオブジェクト、。APIの抽象化は、リソースオブジェクトのこの部分を定義することを意味します。達成するための新機能をKubernetes、通常、新しいリソースオブジェクトを作成し、関数は、オブジェクトに頼る達成するために行われています。

階層化アーキテクチャ

以下に示すようにKubernetesは、Linuxのような階層化アーキテクチャを持っています:

インフラストラクチャ層:実行している時間、ネットワーク、ストレージを含む容器。

コア層:Kubernetesコア機能は、内蔵のプラグインアプリケーション実行環境を提供し、高層のアプリケーションを構築するための外部APIを提供しています。

アプリケーション層:展開(ステートレス、ステートフルなアプリケーション、仕事、など)とルート(サービスディスカバリ、負荷分散など)

管理:、自動化(例えば測定インフラ、容器及びネットワーク等)システムメトリックとポリシー管理(例えば自動スケーリング、動的プロビジョニングなど)(RBAC、クォータなどPSP、NetworkPolicy)

インタフェース層:kubectlコマンドラインツール、クライアントSDKおよび連邦クラスタ

 

生態系:、ログ記録、監視、構成管理、CI、CD、ワークフロー、FAAS、OTSアプリケーション、ChatOps及び他の外部生態学的及びCRI:生態系管理および界面層上のディスパッチ巨大容器クラスタは、二つのカテゴリーに分けることができますCNI、CSI、独自の内部エコロジーの倉庫、クラウドプロバイダ、クラスタ構成と管理をミラーリング。

宣言型の設計と閉ループ制御

Kubernetesエクスプローラこのモードでは、次の手順を持つことになります(宣言)宣言型モデルを使用しました:

  • 免責事項:宣言型の構成ファイル(JSON / YAMLなど)を介してユーザがKubernetesに所望のアプリケーションの状態を教えて実現しています。(例:nginxのサービスの2つのコピーを実行しています)

  • 観察:Kubernetesは、ユーザーの宣言を観察し、自動的に運転を分析し、ユーザは、所望のアプリケーションの状態を達成するために実行する必要があります。アクション(たとえば、など、負荷分散ポリシーを設定し、適切なノードを選択します):Kubernetesコントローラは、ユーザが宣言したアプリケーションの状態を達成するために行う具体的な作業を担当する、プロセスが完全に自動化されています。連続観測収束:大規模分散システムの存在は、システムクラッシュ、終了し、他の容器などの異常、種々のにバインドされています。Kubernetes自然のシステムは、例外が発生したときにタイムリーに、リアルタイムのステータスに自己修復する能力を集中していきます。例えば、ユーザは、1つは、nginxのがハングアップしたときに、ホストは、またはぶら下げ、Kubernetesが自動的に検出し、右のノードを検索し、新しいnginxのサービスを実行しますが、達成するためにユーザが所望維持する場合は、2つのnginxのサービスを宣言するアプリケーションの状態。

       

 相对于命令式操作,声明式操作会更稳定且更容易被用户接受,因为该 API 中隐含了用户想要操作的目标对象,而这些对象刚好都是名词性质的,比如 Service、Deployment、PV 等;且声明式的配置文件更贴近“人类语言”,比如 YAML、JSON。

声明式的设计理念有助于实现控制闭环,持续观测、校正,最终将运行状态达到用户期望的状态;感知用户的行为并执行。比如修改 Pod 数量,应用升级/回滚等等。调度器是核心,但它只是负责从集群节点中选择合适的 node 来运行 pods,显然让调度器来实现上诉的功能不太合适,而需要有专门的控制器组件来实现。

Kubernetes 实现了大量的 controllers,它们通过 list-watch etcd 来感知集群数据的更新,然后 24 小时不间断的工作以达到期待的状态,在该过程中它们也会把创建的各类数据反馈回 kube-apiserver & etcd,从而形成了数据流的闭环。kube-controller-manager 不仅完成了 Kubernetes 集群功能的大部分,还提供很强大的扩展能力,可以让用户轻松的实现自己的 controllers。

API 设计原则

Kubernetes 集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的 API 对象,支持对该功能的管理操作,理解掌握的 API,就好比抓住了 Kubernetes 系统的牛鼻子。Kubernetes 系统 API 的设计有以下几条原则:

所有 API 应该是声明式的。正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的 API,同时隐含了所有的 API 对象都是名词性质的,例如 Service、Volume 这些 API 都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。

API 对象是彼此互补而且可组合的。这里面实际是鼓励 API 对象尽量实现面向对象设计时的要求,即“高内聚,松耦合”,对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。事实上,Kubernetes 这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。

高层 API 以操作意图为基础设计。如何能够设计好 API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。因此,针对 Kubernetes 的高层 API 设计,一定是以 Kubernetes 的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。

低层 API 根据高层 API 的控制需要设计。设计实现低层 API 的目的,是为了被高层 API 使用,考虑减少冗余、提高重用性的目的,低层 API 的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。

尽量避免简单封装,不要有在外部 API 无法显式知道的内部隐藏的机制。简单的封装,实际没有提供新的功能,反而增加了对所封装 API 的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如 StatefulSet 和 ReplicaSet,本来就是两种 Pod 集合,那么 Kubernetes 就用不同 API 对象来定义它们,而不会说只用同一个 ReplicaSet,内部通过特殊的算法再来区分这个 ReplicaSet 是有状态的还是无状态。

API 操作复杂度与对象数量成正比。这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是 API 的操作复杂度不能超过 O(N),N 是对象的数量,否则系统就不具备水平伸缩性了。

  • API 对象状态不能依赖于网络连接状态。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证 API 对象状态能应对网络的不稳定,API 对象的状态就不能依赖于网络连接状态。

  • 尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的。

控制机制设计原则

控制逻辑应该只依赖于当前状态。这是为了保证分布式系统的稳定可靠,对于经常出现局部错误的分布式系统,如果控制逻辑只依赖当前状态,那么就非常容易将一个暂时出现故障的系统恢复到正常状态,因为你只要将该系统重置到某个稳定状态,就可以自信的知道系统的所有控制逻辑会开始按照正常方式运行。

假设任何错误的可能,并做容错处理。在一个分布式系统中出现局部和临时错误是大概率事件。错误可能来自于物理系统故障,外部系统故障也可能来自于系统自身的代码错误,依靠自己实现的代码不会出错来保证系统稳定其实也是难以实现的,因此要设计对任何可能错误的容错处理。

尽量避免复杂状态机,控制逻辑不要依赖无法监控的内部状态。因为分布式系统各个子系统都是不能严格通过程序内部保持同步的,所以如果两个子系统的控制逻辑如果互相有影响,那么子系统就一定要能互相访问到影响控制逻辑的状态,否则,就等同于系统里存在不确定的控制逻辑。

假设任何操作都可能被任何操作对象拒绝,甚至被错误解析。由于分布式系统的复杂性以及各子系统的相对独立性,不同子系统经常来自不同的开发团队,所以不能奢望任何操作被另一个子系统以正确的方式处理,要保证出现错误的时候,操作级别的错误不会影响到系统稳定性。

  • 每个模块都可以在出错后自动恢复。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。

  • 每个模块都可以在必要时优雅地降级服务。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,因为不必担心引入高级功能影响原有的基本功能。

 

おすすめ

転載: www.cnblogs.com/jacksonxiao/p/11299046.html
おすすめ