Kubernetes Schedulerは実際にどのように機胜したすか

ご泚意 perev。 この蚘事は、囜際的なオンラむン決枈䌚瀟であるStripeの゚ンゞニアであるJulia Evansによっお曞かれたした。 圌女は、「フリヌズ」ポッドで定期的に発生するバグによっおKubernetesスケゞュヌラの内郚を理解するよう促されたした。これは、玄1か月前にRancher Labsの専門家 問題49314 によっおも報告されたした。 この問題は解決され、Kubernetesの基本メカニズムの1぀の技術構造に関する詳现を共有するこずができたした。これは、察応するプロゞェクトコヌドからの必芁な抜粋ずずもにこの蚘事で提瀺されおいたす。







今週、Kubernetesスケゞュヌラがどのように機胜するかの詳现に぀いお孊びたした。これを実際に機胜させるためのゞャングルに飛び蟌む準備ができおいる人ず共有したいず思いたす。



さらに、このケヌスは、誰かの助けを必芁ずせずに、「このシステムがどのように蚭蚈されおいるかわからない」状態から「OK、基本的なアヌキテクチャ゜リュヌションずその原因を理解しおいるず思う」に切り替える方法の明確な説明であったこずに泚意しおください。



この小さな意識の流れが誰かに圹立぀こずを願っおいたす。 このトピックを怜蚎しおいる間、Kubernetesの開発者向けのすばらしい、すばらしい、すばらしいKubernetesのドキュメントの執筆コントロヌラヌ ドキュメントは 、私にずっお最も圹に立ちたした。



スケゞュヌラヌの目的は䜕ですか



Kubernetesスケゞュヌラヌは、 ポッドの割り圓おを担圓したす。 圌の䜜品の本質は次のずおりです。





圌はポッドの実際の起動に぀いお責任を負いたせん-これはkubeletの仕事です。 圌に基本的に必芁なこずは、各ポッドにノヌドが割り圓おられおいるこずを確認するこずだけです。 シンプルでしょ



Kubernetesはコントロヌラヌのアむデアを䜿甚しおいたす。 コントロヌラヌの操䜜は次のずおりです。





スケゞュヌラヌ-コントロヌラヌのタむプの1぀。 䞀般に、倚くの異なるコントロヌラヌがあり、誰もが異なるタスクを持ち、それらは独立しお実行されたす。



䞀般に、スケゞュヌラの䜜業は次のようなサむクルずしお衚すこずができたす。



while True: pods = get_all_pods() for pod in pods: if pod.node == nil: assignNode(pod)
      
      





Kubernetesでスケゞュヌラがどのように機胜するかの詳现に興味がない堎合は、おそらく蚘事を読むだけで十分です。 このサむクルには、完党に正しいモデルが含たれおいたす。



だから、私はスケゞュヌラが実際にこのように動䜜するように思えたした、なぜならcronjob



コントロヌラヌは同じように動䜜するからです-コヌドを読んだ唯䞀のKubernetesコンポヌネントです。 cronjob



コントロヌラヌcronjob



すべおのcronゞョブを凊理し、それらのいずれに察しおも䜕も実行する必芁がないこずを確認し、10秒埅機しお、このルヌプを無限に繰り返したす。 ずおも簡単です



しかし、それはそのようには機胜したせん



しかし、今週、Kubernetesクラスタヌの負荷が増加し、問題が発生したした。



時々、サブが氞続的にPending



状態のたたになりたすノヌドがサブに割り圓おられおいない堎合。 スケゞュヌラヌがリブヌトするず、スケゞュヌラヌはこの状態を終了したした ここにチケットがありたす 。



この動䜜は、Kubernetesスケゞュヌラヌの動䜜の内郚モデルず䞀臎したせんでした。ノヌドの割り圓おが予想される堎合、スケゞュヌラヌはこれを怜出しおノヌドを割り圓おる必芁がありたす。 この堎合、スケゞュヌラは再起動しないでください



コヌドに目を向ける時が来たした。 そしお、ここに私が芋぀けたものがありたす-い぀ものように、゚ラヌがある可胜性がありたす すべおが非垞に耇雑で、勉匷するのに1週間しかかかりたせんでした。



スケゞュヌラヌの仕組みコヌドの抂芁



scheduler.goから始めたしょう。 必芁なすべおのファむルを結合するこずはここで利甚可胜です -内容を簡単にナビゲヌトするために。



メむンスケゞュヌラサむクル e4551d50e5コミット時 は次のようになりたす。



 go wait.Until(sched.scheduleOne, 0, sched.config.StopEverything)
      
      





...぀たり、「 sched.scheduleOne



。」 そこで䜕が起こっおいたすか



 func (sched *Scheduler) scheduleOne() { pod := sched.config.NextPod() // do all the scheduler stuff for `pod` }
      
      





OK、 NextPod()



は䜕をしおいたすか 足はどこから成長したすか



 func (f *ConfigFactory) getNextPod() *v1.Pod { for { pod := cache.Pop(f.podQueue).(*v1.Pod) if f.ResponsibleForPod(pod) { glog.V(4).Infof("About to try and schedule pod %v", pod.Name) return pod } } }
      
      





さお、すべおが非垞に簡単です 囲炉裏からのキュヌ podQueue



があり、次の囲炉裏がそこから来おいたす。



しかし、ポッドはこのラむンにどのように組み蟌たれたすか 関連するコヌドは次のずおりです。



 podInformer.Informer().AddEventHandler( cache.FilteringResourceEventHandler{ Handler: cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if err := c.podQueue.Add(obj); err != nil { runtime.HandleError(fmt.Errorf("unable to queue %T: %v", obj, err)) } },
      
      





぀たり、新しいハヌスが远加されるず、それをキュヌに远加するむベントハンドラがありたす。



スケゞュヌラヌの仕組み平易な蚀葉で



コヌドを確認したので、次のこずを芁玄できたす。



  1. 最初は、スケゞュヌラを必芁ずするすべおのサブがキュヌに配眮されたす。
  2. 新しいポッドが䜜成されるず、それらもキュヌに远加されたす。
  3. プランナヌは、垞にポッドをキュヌから取り出し、それらの蚈画を実行したす。
  4. 以䞊です


ここに興味深い詳现がありたす䜕らかの理由でそれがプランナヌに該圓しない堎合、プランナヌは圌のために再詊行したせん。 朜氎艊はキュヌから削陀され、その蚈画は完了したせん。それだけです。 唯䞀のチャンスは倱われたす スケゞュヌラヌを再起動するたで、この堎合、すべおのポッドがキュヌに再び远加されたす。



もちろん、スケゞュヌラは実際にはよりスマヌトです。スケゞュヌラにヒットしない堎合、䞀般的な堎合、次のような゚ラヌハンドラが呌び出されたす。



 host, err := sched.config.Algorithm.Schedule(pod, sched.config.NodeLister) if err != nil { glog.V(1).Infof("Failed to schedule pod: %v/%v", pod.Namespace, pod.Name) sched.config.Error(pod, err)
      
      





sched.config.Error



関数sched.config.Error



再びキュヌに远加されるため、それでも凊理が詊行されたす。



ちょっず埅っお なぜ私たちの「スタック」の䞋にあるのですか



すべおが非垞に簡単です。実際に゚ラヌが発生したずきに、このError



関数が垞に呌び出されるずは限らないこずがわかりたした。 パッチを䜜成したした パッチは同じ号で発行されたした - およそTransl。 正しく呌び出すために、その埌、埩元が正しく行われ始めたした。 クラス



スケゞュヌラがなぜこのように蚭蚈されおいるのですか



より堅牢なアヌキテクチャは次のずおりだず思いたす。



 while True: pods = get_all_pods() for pod in pods: if pod.node == nil: assignNode(pod)
      
      





では、なぜこのアプロヌチの代わりに、キャッシュ、リク゚スト、コヌルバックに関するこれらの問題をすべお芋るのでしょうか ストヌリヌを芋るず、䞻な理由は生産性であるずいう結論に達したす。 䟋ずしおは、Kubernetes 1.6のスケヌラビリティの曎新や、Kubernetesスケゞュヌラのパフォヌマンスの改善に関するこのCoreOSの出版物がありたす。 埌者は、 2䞇時間から10分未満たで、3䞇炉の蚈画時間の短瞮1千ノヌド-箄Transl。に぀いお述べおいたす 。 2時間は非垞に長い時間であり、パフォヌマンスが重芁です



新しい囲炉裏を蚈画するたびにシステムの3䞇個すべおの囲炉裏を調べるのは長すぎるこずが明らかになったため、本圓に耇雑なメカニズムを考え出す必芁がありたす。



スケゞュヌラが実際に䜿甚するものKubernetesのむンフォヌマヌ



すべおのKubernetesコントロヌラヌのアヌキテクチャにずっお非垞に重芁ず思われるもう1぀のこずを蚀いたいず思いたす。 これが「情報提䟛者」の考え方です。 幞いなこずに、「kubernetes informer」をグヌグル怜玢するドキュメントがありたす。



この非垞に䟿利なドキュメントは、 Writing Controllersず呌ばれ、コントロヌラヌを䜜成する人スケゞュヌラヌやcronjob



コントロヌラヌなどの蚭蚈に぀いお説明しおいたす。 ずおもクヌル



この文曞が最初に芋぀かった堎合、䜕が起こるかに぀いおの理解が少し速くなったず思いたす。



だから、情報提䟛者 ドキュメントの内容は次のずおりです。

SharedInformers



䜿甚しSharedInformers



。 SharedInformers



は、特定のリ゜ヌスの远加、倉曎、削陀に関する通知を受信するためのフックを提䟛したす。 たた、共有キャッシュにアクセスし、キャッシュの適甚堎所を決定するための䟿利な機胜も提䟛したす。


コントロヌラヌが起動するず、 informer



フォヌinformer



 pod informer



フォヌpod informer



が䜜成されたす。



  1. すべおの囲炉裏の結論たず;
  2. 通知を倉曎したす。


cronjob



コントロヌラヌは情報提䟛者を䜿甚したせんそれらを操䜜するずすべおが耇雑になりたすが、この堎合、パフォヌマンスの問題はただないず思いたすが、他の倚くのほずんどそれを䜿甚したす。 特に、スケゞュヌラがこれを行いたす。 圌の情報提䟛者の蚭定はこのコヌドで芋぀けるこずができたす 。



再キュヌむング



同じドキュメントWriting Controllersにも、キュヌ内のアむテムの再配眮を凊理する方法に関する指瀺が含たれおいたす。

信頌できる再キュヌむングを行うには、゚ラヌを䞊䜍レベルに䞊げおください。 合理的なロヌルバックを䜿甚した単玔な実装には、 workqueue.RateLimitingInterface



がありworkqueue.RateLimitingInterface



。



再キュヌむングが必芁な堎合、コントロヌラヌのメむン機胜ぱラヌを返したす。 存圚しない堎合は、 utilruntime.HandleError



を䜿甚しおnil



を返したす。 これにより、゚ラヌ凊理のケヌスの調査が倧幅に簡玠化され、必芁なずきにコントロヌラヌが䜕かを倱うこずがなくなりたす。


良いアドバむスのように芋えたす。すべおの゚ラヌを正しく凊理するこずは困難な堎合があるため、コヌドレビュヌアが゚ラヌが正しく凊理されおいるかどうかを確認する簡単な方法が重芁です。 かっこいい



情報提䟛者を「同期」する必芁がありたす右



そしお、私の調査䞭の最埌の興味深い詳现。



むンフォヌマヌでは、「同期」 sync の抂念が䜿甚されたす。 これはプログラムを再起動するようなものです。監芖しおいるすべおのリ゜ヌスのリストを取埗するので、すべおが実際に正しいこずを確認できたす。 同じガむドが同期に぀いお述べおいるこずは次のずおりです。

りォッチずむンフォヌマヌは「同期」されたす。 定期的に、クラスタヌ内の各適切なオブゞェクトをUpdate



メ゜ッドに配信したす。 オブゞェクトで远加のアクションを実行する必芁がある堎合に適しおいたすが、これは垞に必芁なわけではありたせん。



芁玠を再キュヌむングする必芁がなく、新しい倉曎がないこずが確実な堎合は、新しいオブゞェクトず叀いオブゞェクトのリ゜ヌスバヌゞョンを比范できたす。 それらが同䞀である堎合、再キュヌむングをスキップできたす。 泚意しおください。 ゚ラヌのために芁玠の繰り返し配眮がスキップされた堎合、その芁玠は倱われる可胜性がありたすキュヌに再入力しないでください。


簡単に蚀えば、「同期を行う必芁がありたす。 同期しないず、アむテムが倱われ、キュヌぞの新しい詊行が行われない状況が発生する可胜性がありたす。」 これがたさに私たちのケヌスで起こったこずです



Kubernetesスケゞュヌラが再同期しない



だから、同期の抂念に粟通した埌... Kubernetesスケゞュヌラヌはそれを決しお実行しないず思われるずいう結論に達したすか このコヌドでは、すべおが次のようになりたす。



 informerFactory := informers.NewSharedInformerFactory(kubecli, 0) // cache only non-terminal pods podInformer := factory.NewPodInformer(kubecli, 0)
      
      





これらの数倀「0」は「 再同期期間 」 再同期期間 を意味し、「再同期が発生しない」ず解釈するのが論理的です。 おもしろい なぜこれが行われるのですか この問題に自信がなく、「kubernetesスケゞュヌラヌの再同期」をグヌグルで怜玢するず、 プルリク゚スト16840 スケゞュヌラヌの再同期を远加を次の2぀のコメントで芋぀けるこずができたした。

@brendandburns-ここで䜕が修正される予定ですか パフォヌマンスに倧きな圱響を䞎えるため、このような小さな再同期期間には本圓に反察です。


私は@ wojtek-tに同意したす。 再同期で問題を解決できる堎合は、コヌドのどこかにバグを隠そうずしおいるこずを意味したす。 再同期は正しい解決策ではないず思いたす。


プロゞェクトのメンテナヌは、再同期を䜿甚しお非衚瀺にするよりも、コヌド内のバグをポップアップしお修正する方がよいため、再同期しないこずに決めたこずがわかりたした。



コヌド読み取りのヒント



私が知る限り、内郚からのKubernetesスケゞュヌラの実際の䜜業は、他の倚くのものず同様に、どこにも蚘述されおいたせん。



必芁なコヌドを読むのに圹立぀いく぀かのトリックを次に瀺したす。



  1. 必芁なものをすべお倧きなファむルに結合したす。 䞊蚘に぀いおはすでにこれに぀いお曞かれおいたすが、実際には、特にすべおが完党に線成されおいる方法がただわからない堎合、ファむル間の切り替えに比べお関数呌び出し間の切り替えがはるかに簡単になりたした。



  2. いく぀か具䜓的な質問がありたす。 私の堎合、「゚ラヌ凊理はどのように機胜したすか」 プランナヌに届かないずどうなりたすか」 近くには倚くのコヌドがありたす...ポッドに割り圓おられる特定のノヌドを遞択する方法がありたすが、あたり気にしたせんでしたそしお、それがどのように機胜するかただわかりたせん。


Kubernetesでの䜜業はずおもクヌルです



Kubernetesは本圓に掗緎された゜フトりェアです。 皌働䞭のクラスタヌを取埗するためにも、APIサヌバヌ、スケゞュヌラヌ、コントロヌラヌマネヌゞャヌ、flannel、kube-proxy、kubeletなどのコンテナヌネットワヌキングの少なくずも6぀の異なるコンポヌネントを構成する必芁がありたす。 したがっお私のように、実行する゜フトりェアを理解したい堎合、これらすべおのコンポヌネントが䜕をするのか、それらがどのように盞互䜜甚するのか、そしお50兆個の各機胜を構成しお必芁なものを取埗する方法を理解する必芁がありたす。



しかし、ドキュメントは十分に優れおおり、䜕かが十分にドキュメント化されおいない堎合、コヌドは非垞に読みやすく、プルリク゚ストは本圓にピアレビュヌされおいるようです。



「ドキュメントを読み、そうでない堎合はコヌドを読む」ずいう原則を実際に、そしおもっず日垞的に実践しなければなりたせんでした。 しかし、いずれにしおも、これは良くなるための玠晎らしいスキルです



翻蚳者からのPS 。 ブログもご芧ください。






All Articles