{"id":1353,"date":"2021-05-27T00:00:00","date_gmt":"2021-05-27T00:00:00","guid":{"rendered":"https:\/\/en.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/"},"modified":"2023-09-11T01:36:33","modified_gmt":"2023-09-11T08:36:33","slug":"tidb-operator-source-code-reading-2-operator-pattern","status":"publish","type":"post","link":"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/","title":{"rendered":"TiDB Operator Source Code Reading (II): Operator Pattern"},"content":{"rendered":"<p><strong>Author:<\/strong> <a href=\"https:\/\/github.com\/handlerww\">Yiwen Chen<\/a> (Committer of TiDB Operator)<\/p>\n\n\n\n<p><strong>Transcreator:<\/strong> <a href=\"https:\/\/github.com\/ran-huang\">Ran Huang<\/a>; <strong>Editor:<\/strong> Tom Dewan<\/p>\n\n\n\n<p>In <a href=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-1-overview\/\">my last article<\/a>, I introduced TiDB Operator&#8217;s architecture and what it is capable of. But how does TiDB Operator code run? How does TiDB Operator manage the lifecycle of each component in the TiDB cluster?<\/p>\n\n\n\n<p>In this post, I&#8217;ll present Kubernetes&#8217;s Operator pattern and how it is implemented in TiDB Operator. More specifically, <strong>we&#8217;ll go through TiDB Operator&#8217;s major control loop, from its entry point to the trigger of the lifecycle management<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"From_Controller_to_Operator\"><\/span>From Controller to Operator<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Because TiDB Operator learns from the <a href=\"https:\/\/kubernetes.io\/docs\/reference\/command-line-tools-reference\/kube-controller-manager\/\">kube-controller-manager<\/a>, understanding the design of <code>kube-controller-manager<\/code> helps you better understand the internal logic of TiDB Operator.<\/p>\n\n\n\n<p>In Kubernetes, various <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/architecture\/controller\/\">controllers<\/a> manage the lifecycle of resources, such as Namespace, Node, Deployment, and StatefulSet. Controllers watch the current state of the cluster resources, compare it with the desired state, and move the cluster towards the desired state. Kubernetes&#8217;s built-in controllers run inside <code>kube-controller-manager<\/code> and are managed by it.<\/p>\n\n\n\n<p>To allow users to customize resource management, Kubernetes put forward the <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/operator\/\">Operator pattern<\/a>. Users can create their own <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/api-extension\/custom-resources\/\">custom resources<\/a> (CRs) by defining a <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/api-extension\/custom-resources\/#customresourcedefinitions\">CustomResourceDefinitions<\/a> (CRDs) object and use custom controllers to watch the state of the corresponding CRs and complete relevant management tasks. The Operator pattern allows users to extend Kubernetes behaviors without modifying its code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_TiDB_controller_manager_works\"><\/span>How TiDB controller manager works<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>As illustrated in <a href=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-1-overview\/#how-tidb-operator-works\">TiDB Operator Source Code Reading (I): Overview<\/a>, TiDB Operator has a core component, <code>tidb-controller-manager<\/code>, which runs a set of custom controllers that manages CRDs for TiDB.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Entry point<\/h3>\n\n\n\n<p>Starting from <code>cmd\/controller-manager\/main.go<\/code>, <code>tidb-controller-manager<\/code> first loads kubeconfig to access the kube-apiserver. It then uses a series of <code>NewController<\/code> functions to load the init function of each controller.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>controllers := &#91;]Controller{\n    tidbcluster.NewController(deps),\n    dmcluster.NewController(deps),\n    backup.NewController(deps),\n    restore.NewController(deps),\n    backupschedule.NewController(deps),\n    tidbinitializer.NewController(deps),\n    tidbmonitor.NewController(deps),\n}\n<\/code><\/pre>\n\n\n\n<p>During the execution of init functions, <code>tidb-controller-manager<\/code> initializes a set of informers, which interact with the kube-apiserver to obtain the changes of CRs and related resources. Taking <code>TidbCluster<\/code> as an example, in the <code>NewController<\/code> function, <code>tidb-controller-manager<\/code> initializes the Informer objects:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tidbClusterInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{\n        AddFunc: c.enqueueTidbCluster,\n        UpdateFunc: func(old, cur interface{}) {\n            c.enqueueTidbCluster(cur)\n        },\n        DeleteFunc: c.enqueueTidbCluster,\n    })\nstatefulsetInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{\n        AddFunc: c.addStatefulSet,\n        UpdateFunc: func(old, cur interface{}) {\n            c.updateStatefulSet(old, cur)\n        },\n        DeleteFunc: c.deleteStatefulSet,\n    })\n<\/code><\/pre>\n\n\n\n<p>EventHandlers that process <code>add<\/code>, <code>update<\/code>, \uadf8\ub9ac\uace0 <code>delete<\/code> events are registered to the Informers. These EventHandlers handle the events and add the relevant CR keys to the queue.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Controller&#8217;s internal logic<\/h3>\n\n\n\n<p>After the initialization, <code>tidb-controller-manager<\/code> launches InformerFactory and waits for cache synchronization to complete:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>informerFactories := &#91;]InformerFactory{\n            deps.InformerFactory,\n            deps.KubeInformerFactory,\n            deps.LabelFilterKubeInformerFactory,\n        }\n        for _, f := range informerFactories {\n            f.Start(ctx.Done())\n            for v, synced := range f.WaitForCacheSync(wait.NeverStop) {\n                if !synced {\n                    klog.Fatalf(\"error syncing informer for %v\", v)\n                }\n            }\n        }\n<\/code><\/pre>\n\n\n\n<p>Next, <code>tidb-controller-manager<\/code> calls the Run function of each controller and executes the internal logic of controllers in a loop:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Start syncLoop for all controllers.\nfor _,controller := range controllers {\n    c := controller\n    go wait.Forever(func() { c.Run(cliCfg.Workers,ctx.Done()) },cliCfg.WaitDuration)\n}\n<\/code><\/pre>\n\n\n\n<p>Again, take the <code>TidbCluster<\/code> controller as an example. The Run function starts the worker queue:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Run runs the tidbcluster controller.\nfunc (c *Controller) Run(workers int, stopCh &lt;-chan struct{}) {\n    defer utilruntime.HandleCrash()\n    defer c.queue.ShutDown()\n\n    klog.Info(\"Starting tidbcluster controller\")\n    defer klog.Info(\"Shutting down tidbcluster controller\")\n\n    for i := 0; i &lt; workers; i++ {\n        go wait.Until(c.worker, time.Second, stopCh)\n    }\n\n    &lt;-stopCh\n}\n<\/code><\/pre>\n\n\n\n<p>The worker calls the <code>processNextWorkItem<\/code> function, dequeues the items, and calls the <code>sync<\/code> function to synchronize the CR:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ worker runs a worker goroutine that invokes processNextWorkItem until the controller's queue is closed.\nfunc (c *Controller) worker() {\n    for c.processNextWorkItem() {\n    }\n}\n\n\/\/ processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never\n\/\/ invoked concurrently with the same key.\nfunc (c *Controller) processNextWorkItem() bool {\n    key, quit := c.queue.Get()\n    if quit {\n        return false\n    }\n    defer c.queue.Done(key)\n    if err := c.sync(key.(string)); err != nil {\n        if perrors.Find(err, controller.IsRequeueError) != nil {\n            klog.Infof(\"TidbCluster: %v, still need sync: %v, requeuing\", key.(string), err)\n        } else {\n            utilruntime.HandleError(fmt.Errorf(\"TidbCluster: %v, sync failed %v, requeuing\", key.(string), err))\n        }\n        c.queue.AddRateLimited(key)\n    } else {\n        c.queue.Forget(key)\n    }\n    return true\n}\n<\/code><\/pre>\n\n\n\n<p>Based on the key, the <code>sync<\/code> function obtains the corresponding CR object (for example, the <code>TidbCluster<\/code> object) and syncs it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ sync syncs the given tidbcluster.\nfunc (c *Controller) sync(key string) error {\n    startTime := time.Now()\n    defer func() {\n        klog.V(4).Infof(\"Finished syncing TidbCluster %q (%v)\", key, time.Since(startTime))\n    }()\n\n    ns, name, err := cache.SplitMetaNamespaceKey(key)\n    if err != nil {\n        return err\n    }\n    tc, err := c.deps.TiDBClusterLister.TidbClusters(ns).Get(name)\n    if errors.IsNotFound(err) {\n        klog.Infof(\"TidbCluster has been deleted %v\", key)\n        return nil\n    }\n    if err != nil {\n        return err\n    }\n\n    return c.syncTidbCluster(tc.DeepCopy())\n}\n\nfunc (c *Controller) syncTidbCluster(tc *v1alpha1.TidbCluster) error {\n    return c.control.UpdateTidbCluster(tc)\n}\n<\/code><\/pre>\n\n\n\n<p>The <code>syncTidbCluster<\/code> function calls the <code>updateTidbCluster<\/code> function, which further invokes a series of component <code>sync<\/code> functions, to complete the management of the whole TiDB cluster.<\/p>\n\n\n\n<p>In <code>pkg\/controller\/tidbcluster\/tidb_cluster_control.go<\/code>, you can check the implementation of the <code>updateTidbCluster<\/code> function, where there are comments that describe the lifecycle management performed by each <code>sync<\/code> function. Through these comments, you can understand what operations are required for reconciling each component. For example, in Placement Driver (PD):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ To make the current state of the pd cluster match the desired state:\n\/\/   - create or update the pd service\n\/\/   - create or update the pd headless service\n\/\/   - create the pd statefulset if it does not exist\n\/\/   - sync pd cluster status from pd to TidbCluster object\n\/\/   - upgrade the pd cluster\n\/\/   - scale out\/in the pd cluster\n\/\/   - failover the pd cluster\nif err := c.pdMemberManager.Sync(tc); err != nil {\n    return err\n}\n<\/code><\/pre>\n\n\n\n<p>That&#8217;s all for now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In this article, <strong>we covered TiDB Operator from its entry point in <code>cmd\/controller-manager\/main.go<\/code> to the implementation of controllers and explained the controllers&#8217; internal logic<\/strong>. Now, you are familiar with how the control loop is triggered. The only question left is how to refine the control loop and instill in it the special operation logic of TiDB. That way, you can deploy TiDB and run it in Kubernetes as desired.<\/p>\n\n\n\n<p>For those who would like to develop a resource management system, we recommend two scaffolding projects: <a href=\"https:\/\/github.com\/kubernetes-sigs\/kubebuilder\">Kubebuilder<\/a> \uadf8\ub9ac\uace0 <a href=\"https:\/\/github.com\/operator-framework\/operator-sdk\">Operator Framework<\/a>. These projects generate the code template based on <a href=\"https:\/\/github.com\/kubernetes-sigs\/controller-runtime\">controller-runtime<\/a>, allowing you to focus on the reconcile loop of your CRD objects.<\/p>\n\n\n\n<p>In the next article, I&#8217;ll discuss <a href=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-3-component-control-loop\/\">how to refine the control loop and implement the component reconcile loop<\/a>. If you have any questions, talk to us via <a href=\"https:\/\/slack.tidb.io\/invite?team=tidb-community&amp;channel=sig-k8s&amp;ref=pingcap-blog\">our Slack channel<\/a> or at <a href=\"https:\/\/github.com\/pingcap\/tidb-operator\">pingcap\/tidb-operator<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Learn about Kubernetes&#8217;s Operator pattern and TiDB Operator&#8217;s major reconcile loop.<\/p>","protected":false},"author":67,"featured_media":1355,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ub_ctt_via":"","footnotes":""},"categories":[6],"tags":[33,84],"class_list":["post-1353","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-kubernetes","tag-tidb-operator"],"acf":[],"featured_image_src":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","author_info":{"display_name":"Yiwen Chen","author_link":"https:\/\/www.pingcap.com\/ko\/blog\/author\/yiwen-chen\/"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>TiDB Operator Source Code Reading (II): Operator Pattern | TiDB<\/title>\n<meta name=\"description\" content=\"In this post, we will share Kubernetes&#039;s Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TiDB Operator Source Code Reading (II): Operator Pattern | TiDB\" \/>\n<meta property=\"og:description\" content=\"In this post, we will share Kubernetes&#039;s Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\" \/>\n<meta property=\"og:site_name\" content=\"TiDB\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/pingcap2015\" \/>\n<meta property=\"article:published_time\" content=\"2021-05-27T00:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-11T08:36:33+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"599\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Yiwen Chen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:site\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yiwen Chen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\"},\"author\":{\"name\":\"Yiwen Chen\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/5e8e0624ab59c4f01eb367e8c9869ab2\"},\"headline\":\"TiDB Operator Source Code Reading (II): Operator Pattern\",\"datePublished\":\"2021-05-27T00:00:00+00:00\",\"dateModified\":\"2023-09-11T08:36:33+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\"},\"wordCount\":646,\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\",\"keywords\":[\"Kubernetes\",\"TiDB Operator\"],\"articleSection\":[\"Engineering\"],\"inLanguage\":\"ko-KR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\",\"url\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\",\"name\":\"TiDB Operator Source Code Reading (II): Operator Pattern | TiDB\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\",\"datePublished\":\"2021-05-27T00:00:00+00:00\",\"dateModified\":\"2023-09-11T08:36:33+00:00\",\"description\":\"In this post, we will share Kubernetes's Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage\",\"url\":\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\",\"width\":1800,\"height\":599},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.pingcap.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TiDB Operator Source Code Reading (II): Operator Pattern\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.pingcap.com\/#website\",\"url\":\"https:\/\/www.pingcap.com\/\",\"name\":\"TiDB\",\"description\":\"TiDB | SQL at Scale\",\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.pingcap.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.pingcap.com\/#organization\",\"name\":\"PingCAP\",\"url\":\"https:\/\/www.pingcap.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"width\":811,\"height\":232,\"caption\":\"PingCAP\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/facebook.com\/pingcap2015\",\"https:\/\/x.com\/PingCAP\",\"https:\/\/linkedin.com\/company\/pingcap\",\"https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/5e8e0624ab59c4f01eb367e8c9869ab2\",\"name\":\"Yiwen Chen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"caption\":\"Yiwen Chen\"},\"url\":\"https:\/\/www.pingcap.com\/ko\/blog\/author\/yiwen-chen\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"TiDB Operator Source Code Reading (II): Operator Pattern | TiDB","description":"In this post, we will share Kubernetes's Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/","og_locale":"ko_KR","og_type":"article","og_title":"TiDB Operator Source Code Reading (II): Operator Pattern | TiDB","og_description":"In this post, we will share Kubernetes's Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.","og_url":"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/","og_site_name":"TiDB","article_publisher":"https:\/\/facebook.com\/pingcap2015","article_published_time":"2021-05-27T00:00:00+00:00","article_modified_time":"2023-09-11T08:36:33+00:00","og_image":[{"width":1800,"height":599,"url":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","type":"image\/png"}],"author":"Yiwen Chen","twitter_card":"summary_large_image","twitter_creator":"@PingCAP","twitter_site":"@PingCAP","twitter_misc":{"Written by":"Yiwen Chen","Est. reading time":"5\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#article","isPartOf":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/"},"author":{"name":"Yiwen Chen","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/5e8e0624ab59c4f01eb367e8c9869ab2"},"headline":"TiDB Operator Source Code Reading (II): Operator Pattern","datePublished":"2021-05-27T00:00:00+00:00","dateModified":"2023-09-11T08:36:33+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/"},"wordCount":646,"publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"image":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage"},"thumbnailUrl":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","keywords":["Kubernetes","TiDB Operator"],"articleSection":["Engineering"],"inLanguage":"ko-KR"},{"@type":"WebPage","@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/","url":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/","name":"TiDB Operator Source Code Reading (II): Operator Pattern | TiDB","isPartOf":{"@id":"https:\/\/www.pingcap.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage"},"image":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage"},"thumbnailUrl":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","datePublished":"2021-05-27T00:00:00+00:00","dateModified":"2023-09-11T08:36:33+00:00","description":"In this post, we will share Kubernetes's Operator pattern and how it is implemented in TiDB Operator, and go through the major control loop.","breadcrumb":{"@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#primaryimage","url":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","contentUrl":"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png","width":1800,"height":599},{"@type":"BreadcrumbList","@id":"https:\/\/www.pingcap.com\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pingcap.com\/"},{"@type":"ListItem","position":2,"name":"TiDB Operator Source Code Reading (II): Operator Pattern"}]},{"@type":"WebSite","@id":"https:\/\/www.pingcap.com\/#website","url":"https:\/\/www.pingcap.com\/","name":"\ud2f0DB","description":"TiDB | SQL at Scale","publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pingcap.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.pingcap.com\/#organization","name":"PingCAP","url":"https:\/\/www.pingcap.com\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/","url":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","contentUrl":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","width":811,"height":232,"caption":"PingCAP"},"image":{"@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/facebook.com\/pingcap2015","https:\/\/x.com\/PingCAP","https:\/\/linkedin.com\/company\/pingcap","https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA"]},{"@type":"Person","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/5e8e0624ab59c4f01eb367e8c9869ab2","name":"Yiwen Chen","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/","url":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","contentUrl":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","caption":"Yiwen Chen"},"url":"https:\/\/www.pingcap.com\/ko\/blog\/author\/yiwen-chen\/"}]}},"grav_blocks":false,"card_markup":"<a class=\"card-resource bg-white\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/tidb-operator-source-code-reading-2-operator-pattern\/\"><div class=\"card-resource__image-container\"><img class=\"card-resource__image\" alt=\"tidb-operator-source-code-reading-2-operator-pattern.png\" src=\"https:\/\/static.pingcap.com\/files\/2021\/05\/tidb-operator-source-code-reading-2-operator-pattern.png\" loading=\"lazy\" width=1800 height=599 \/><\/div><div class=\"card-resource__content-container\"><div class=\"card-resource__content-head\"><div class=\"card-resource__category\">Engineering<\/div><\/div><h5 class=\"card-resource__title\">TiDB Operator Source Code Reading (II): Operator Pattern<\/h5><\/div><\/a>","_links":{"self":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/users\/67"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/comments?post=1353"}],"version-history":[{"count":4,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1353\/revisions"}],"predecessor-version":[{"id":13743,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1353\/revisions\/13743"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/media\/1355"}],"wp:attachment":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/media?parent=1353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/categories?post=1353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/tags?post=1353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}