@@ -22,6 +22,7 @@ import (
2222 "github.com/pingcap/tidb-operator/pkg/controller"
2323 mngerutils "github.com/pingcap/tidb-operator/pkg/manager/utils"
2424 "github.com/pingcap/tidb-operator/pkg/third_party/k8s"
25+ "github.com/pingcap/tidb-operator/pkg/util/cmpver"
2526 apps "k8s.io/api/apps/v1"
2627 "k8s.io/klog/v2"
2728)
@@ -120,12 +121,95 @@ func (u *pdMSUpgrader) gracefulUpgrade(tc *v1alpha1.TidbCluster, oldSet *apps.St
120121 }
121122 continue
122123 }
123- mngerutils . SetUpgradePartition ( newSet , i )
124- return nil
124+
125+ return u . upgradePDMSPod ( tc , i , newSet , curService )
125126 }
126127 return nil
127128}
128129
130+ func (u * pdMSUpgrader ) upgradePDMSPod (tc * v1alpha1.TidbCluster , ordinal int32 , newSet * apps.StatefulSet , curService string ) error {
131+ // Only support after `8.3.0` to keep compatibility.
132+ if check , err := pdMSSupportMicroServicesWithName .Check (tc .PDMSVersion (curService )); check && err == nil {
133+ ns := tc .GetNamespace ()
134+ tcName := tc .GetName ()
135+ upgradePDMSName := PDMSName (tcName , ordinal , tc .Namespace , tc .Spec .ClusterDomain , tc .Spec .AcrossK8s , curService )
136+ upgradePodName := PDMSPodName (tcName , ordinal , curService )
137+
138+ pdClient := controller .GetPDClient (u .deps .PDControl , tc )
139+ primary , err := pdClient .GetMSPrimary (curService )
140+ if err != nil {
141+ return err
142+ }
143+
144+ klog .Infof ("TidbCluster: [%s/%s]' pdms upgrader: check primary: %s, upgradePDMSName: %s, upgradePodName: %s" , ns , tcName ,
145+ primary , upgradePDMSName , upgradePodName )
146+ // If current pdms is primary, transfer primary to other pdms pod
147+ if strings .Contains (primary , upgradePodName ) || strings .Contains (primary , upgradePDMSName ) {
148+ targetName := ""
149+
150+ if tc .PDMSStsActualReplicas (curService ) > 1 {
151+ targetName = choosePDMSToTransferFromMembers (tc , newSet , ordinal )
152+ }
153+
154+ if targetName != "" {
155+ klog .Infof ("TidbCluster: [%s/%s]' pdms upgrader: transfer pdms primary to: %s" , ns , tcName , targetName )
156+ err := controller .GetPDMSClient (u .deps .PDControl , tc , curService ).TransferPrimary (targetName )
157+ if err != nil {
158+ klog .Errorf ("TidbCluster: [%s/%s]' pdms upgrader: failed to transfer pdms primary to: %s, %v" , ns , tcName , targetName , err )
159+ return err
160+ }
161+ klog .Infof ("TidbCluster: [%s/%s]' pdms upgrader: transfer pdms primary to: %s successfully" , ns , tcName , targetName )
162+ } else {
163+ klog .Warningf ("TidbCluster: [%s/%s]' pdms upgrader: skip to transfer pdms primary, because can not find a suitable pd" , ns , tcName )
164+ }
165+ }
166+ }
167+
168+ mngerutils .SetUpgradePartition (newSet , ordinal )
169+ return nil
170+ }
171+
172+ // choosePDMSToTransferFromMembers choose a pdms to transfer primary from members
173+ //
174+ // Assume that current primary ordinal is x, and range is [0, n]
175+ // 1. Find the max suitable ordinal in (x, n], because they have been upgraded
176+ // 2. If no suitable ordinal, find the min suitable ordinal in [0, x) to reduce the count of transfer
177+ func choosePDMSToTransferFromMembers (tc * v1alpha1.TidbCluster , newSet * apps.StatefulSet , ordinal int32 ) string {
178+ ns := tc .GetNamespace ()
179+ tcName := tc .GetName ()
180+ klog .Infof ("Tidbcluster: [%s/%s]' pdms upgrader: start to choose pdms to transfer primary from members" , ns , tcName )
181+ ordinals := helper .GetPodOrdinals (* newSet .Spec .Replicas , newSet )
182+
183+ // set ordinal to max ordinal if ordinal isn't exist
184+ if ! ordinals .Has (ordinal ) {
185+ ordinal = helper .GetMaxPodOrdinal (* newSet .Spec .Replicas , newSet )
186+ }
187+
188+ targetName := ""
189+ list := ordinals .List ()
190+ if len (list ) == 0 {
191+ return ""
192+ }
193+
194+ // just using pods index for now. TODO: add healthy checker for pdms.
195+ // find the maximum ordinal which is larger than ordinal
196+ if len (list ) > int (ordinal )+ 1 {
197+ targetName = PDMSPodName (tcName , list [len (list )- 1 ], controller .PDMSTrimName (newSet .Name ))
198+ }
199+
200+ if targetName == "" && ordinal != 0 {
201+ // find the minimum ordinal which is less than ordinal
202+ targetName = PDMSPodName (tcName , list [0 ], controller .PDMSTrimName (newSet .Name ))
203+ }
204+
205+ klog .Infof ("Tidbcluster: [%s/%s]' pdms upgrader: choose pdms to transfer primary from members, targetName: %s" , ns , tcName , targetName )
206+ return targetName
207+ }
208+
209+ // PDMSSupportMicroServicesWithName returns true if the given version of PDMS supports microservices with name.
210+ // related https://github.com/tikv/pd/pull/8157.
211+ var pdMSSupportMicroServicesWithName , _ = cmpver .NewConstraint (cmpver .GreaterOrEqual , "v8.3.0" )
212+
129213type fakePDMSUpgrader struct {}
130214
131215// NewFakePDMSUpgrader returns a fakePDUpgrader
0 commit comments