Skip to content

Commit 1f68cb0

Browse files
committed
internal/pool: move the kubernetes buildlet pool into a pool package
This is a set in a series of steps which will move everything buildlet pool related into a pool package. Updates golang/go#36841 Change-Id: I8efb1f94c7b929be559004d9f455bca0370c7800 Reviewed-on: https://go-review.googlesource.com/c/build/+/227768 Run-TryBot: Carlos Amedee <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Alexander Rakoczy <[email protected]>
1 parent 02e10ad commit 1f68cb0

File tree

3 files changed

+66
-35
lines changed

3 files changed

+66
-35
lines changed

cmd/coordinator/coordinator.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,9 @@ func main() {
283283
}
284284

285285
// TODO(evanbrown: disable kubePool if init fails)
286-
err = initKube()
286+
err = pool.InitKube(monitorGitMirror)
287287
if err != nil {
288-
kubeErr = err
288+
pool.KubeSetErr(err)
289289
log.Printf("Kube support disabled due to error initializing Kubernetes: %v", err)
290290
}
291291

@@ -346,8 +346,8 @@ func main() {
346346
pool.GetGCEBuildletPool().SetEnabled(*devEnableGCE)
347347
} else {
348348
go pool.GetGCEBuildletPool().CleanUpOldVMs()
349-
if kubeErr == nil {
350-
go kubePool.cleanUpOldPodsLoop(context.Background())
349+
if pool.KubeErr() == nil {
350+
go pool.KubePool().CleanUpOldPodsLoop(context.Background())
351351
}
352352

353353
if pool.GCEInStaging() {
@@ -1628,10 +1628,10 @@ func poolForConf(conf *dashboard.HostConfig) pool.Buildlet {
16281628
case conf.IsVM():
16291629
return pool.GetGCEBuildletPool()
16301630
case conf.IsContainer():
1631-
if pool.GCEBuildEnv().PreferContainersOnCOS || kubeErr != nil {
1631+
if pool.GCEBuildEnv().PreferContainersOnCOS || pool.KubeErr() != nil {
16321632
return pool.GetGCEBuildletPool() // it also knows how to do containers.
16331633
} else {
1634-
return kubePool
1634+
return pool.KubePool()
16351635
}
16361636
case conf.IsReverse:
16371637
return reversePool
@@ -1820,7 +1820,7 @@ func (st *buildStatus) forceSnapshotUsage() {
18201820
}
18211821

18221822
func (st *buildStatus) getCrossCompileConfig() *dashboard.CrossCompileConfig {
1823-
if kubeErr != nil {
1823+
if pool.KubeErr() != nil {
18241824
return nil
18251825
}
18261826
config := st.conf.CrossCompileConfig

cmd/coordinator/status.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func monitorGitMirror() {
184184
func gitMirrorErrors() (errs []string) {
185185
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
186186
defer cancel()
187-
pods, err := goKubeClient.GetPods(ctx)
187+
pods, err := pool.KubeGoClient().GetPods(ctx)
188188
if err != nil {
189189
log.Println("gitMirrorErrors: goKubeClient.GetPods:", err)
190190
return []string{"failed to get pods; can't query gitmirror status"}
@@ -662,7 +662,7 @@ func handleStatus(w http.ResponseWriter, r *http.Request) {
662662
data.GCEPoolStatus = template.HTML(buf.String())
663663
buf.Reset()
664664

665-
kubePool.WriteHTMLStatus(&buf)
665+
pool.KubePool().WriteHTMLStatus(&buf)
666666
data.KubePoolStatus = template.HTML(buf.String())
667667
buf.Reset()
668668

cmd/coordinator/kube.go renamed to internal/coordinator/pool/kube.go

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// +build go1.13
66
// +build linux darwin
77

8-
package main
8+
package pool
99

1010
import (
1111
"context"
@@ -22,7 +22,6 @@ import (
2222

2323
"golang.org/x/build/buildlet"
2424
"golang.org/x/build/dashboard"
25-
"golang.org/x/build/internal/coordinator/pool"
2625
"golang.org/x/build/internal/sourcecache"
2726
"golang.org/x/build/kubernetes"
2827
"golang.org/x/build/kubernetes/api"
@@ -34,6 +33,15 @@ import (
3433
This file implements the Kubernetes-based buildlet pool.
3534
*/
3635

36+
const (
37+
// podDeleteTimeout is how long before we delete a VM.
38+
// In practice this need only be as long as the slowest
39+
// builder (plan9 currently), because on startup this program
40+
// already deletes all buildlets it doesn't know about
41+
// (i.e. ones from a previous instance of the coordinator).
42+
podDeleteTimeout = 45 * time.Minute
43+
)
44+
3745
// Initialized by initKube:
3846
var (
3947
buildletsKubeClient *kubernetes.Client // for "buildlets" cluster
@@ -43,14 +51,17 @@ var (
4351
kubeCluster *container.Cluster
4452
)
4553

46-
// initGCE must be called before initKube
47-
func initKube() error {
48-
if pool.GCEBuildEnv().KubeBuild.MaxNodes == 0 {
54+
// MonitorGitMirrorFunc defines a function used to monitor gitmirror.
55+
type MonitorGitMirrorFunc func()
56+
57+
// InitGCE must be called before initKube
58+
func InitKube(monitorGitMirror MonitorGitMirrorFunc) error {
59+
if GCEBuildEnv().KubeBuild.MaxNodes == 0 {
4960
return errors.New("Kubernetes builders disabled due to KubeBuild.MaxNodes == 0")
5061
}
5162

5263
// projectID was set by initGCE
53-
registryPrefix += "/" + pool.GCEBuildEnv().ProjectName
64+
registryPrefix += "/" + GCEBuildEnv().ProjectName
5465
if !hasCloudPlatformScope() {
5566
return errors.New("coordinator not running with access to the Cloud Platform scope.")
5667
}
@@ -59,19 +70,19 @@ func initKube() error {
5970
defer cancel() // ctx is only used for discovery and connect; not retained.
6071
var err error
6172
buildletsKubeClient, err = gke.NewClient(ctx,
62-
pool.GCEBuildEnv().KubeBuild.Name,
63-
gke.OptZone(pool.GCEBuildEnv().ControlZone),
64-
gke.OptProject(pool.GCEBuildEnv().ProjectName),
65-
gke.OptTokenSource(pool.GCPCredentials().TokenSource))
73+
GCEBuildEnv().KubeBuild.Name,
74+
gke.OptZone(GCEBuildEnv().ControlZone),
75+
gke.OptProject(GCEBuildEnv().ProjectName),
76+
gke.OptTokenSource(GCPCredentials().TokenSource))
6677
if err != nil {
6778
return err
6879
}
6980

7081
goKubeClient, err = gke.NewClient(ctx,
71-
pool.GCEBuildEnv().KubeTools.Name,
72-
gke.OptZone(pool.GCEBuildEnv().ControlZone),
73-
gke.OptProject(pool.GCEBuildEnv().ProjectName),
74-
gke.OptTokenSource(pool.GCPCredentials().TokenSource))
82+
GCEBuildEnv().KubeTools.Name,
83+
gke.OptZone(GCEBuildEnv().ControlZone),
84+
gke.OptProject(GCEBuildEnv().ProjectName),
85+
gke.OptTokenSource(GCPCredentials().TokenSource))
7586
if err != nil {
7687
return err
7788
}
@@ -85,6 +96,26 @@ func initKube() error {
8596
return nil
8697
}
8798

99+
// KubeSetErr sets the kube error to passed in value.
100+
func KubeSetErr(err error) {
101+
kubeErr = err
102+
}
103+
104+
// KubeErr retrieves the kube error value.
105+
func KubeErr() error {
106+
return kubeErr
107+
}
108+
109+
// KubePool returns the kube buildlet pool.
110+
func KubePool() *kubeBuildletPool {
111+
return kubePool
112+
}
113+
114+
// KubeGoClient retrieves a kube client for the go cluster.
115+
func KubeGoClient() *kubernetes.Client {
116+
return goKubeClient
117+
}
118+
88119
// kubeBuildletPool is the Kubernetes buildlet pool.
89120
type kubeBuildletPool struct {
90121
mu sync.Mutex // guards all following
@@ -136,12 +167,12 @@ func (p *kubeBuildletPool) pollCapacityLoop() {
136167
func (p *kubeBuildletPool) pollCapacity(ctx context.Context) {
137168
nodes, err := buildletsKubeClient.GetNodes(ctx)
138169
if err != nil {
139-
log.Printf("failed to retrieve nodes to calculate cluster capacity for %s/%s: %v", pool.GCEBuildEnv().ProjectName, pool.GCEBuildEnv().Region(), err)
170+
log.Printf("failed to retrieve nodes to calculate cluster capacity for %s/%s: %v", GCEBuildEnv().ProjectName, GCEBuildEnv().Region(), err)
140171
return
141172
}
142173
pods, err := buildletsKubeClient.GetPods(ctx)
143174
if err != nil {
144-
log.Printf("failed to retrieve pods to calculate cluster capacity for %s/%s: %v", pool.GCEBuildEnv().ProjectName, pool.GCEBuildEnv().Region(), err)
175+
log.Printf("failed to retrieve pods to calculate cluster capacity for %s/%s: %v", GCEBuildEnv().ProjectName, GCEBuildEnv().Region(), err)
145176
return
146177
}
147178

@@ -210,7 +241,7 @@ func (p *kubeBuildletPool) pollCapacity(ctx context.Context) {
210241

211242
}
212243

213-
func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, hostType string, lg pool.Logger) (*buildlet.Client, error) {
244+
func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, hostType string, lg Logger) (*buildlet.Client, error) {
214245
hconf, ok := dashboard.Hosts[hostType]
215246
if !ok || !hconf.IsContainer() {
216247
return nil, fmt.Errorf("kubepool: invalid host type %q", hostType)
@@ -222,7 +253,7 @@ func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, hostType string, lg
222253
panic("expect non-nil buildletsKubeClient")
223254
}
224255

225-
deleteIn, ok := ctx.Value(pool.BuildletTimeoutOpt{}).(time.Duration)
256+
deleteIn, ok := ctx.Value(BuildletTimeoutOpt{}).(time.Duration)
226257
if !ok {
227258
deleteIn = podDeleteTimeout
228259
}
@@ -237,7 +268,7 @@ func (p *kubeBuildletPool) GetBuildlet(ctx context.Context, hostType string, lg
237268
log.Printf("Creating Kubernetes pod %q for %s", podName, hostType)
238269

239270
bc, err := buildlet.StartPod(ctx, buildletsKubeClient, podName, hostType, buildlet.PodOpts{
240-
ProjectID: pool.GCEBuildEnv().ProjectName,
271+
ProjectID: GCEBuildEnv().ProjectName,
241272
ImageRegistry: registryPrefix,
242273
Description: fmt.Sprintf("Go Builder for %s", hostType),
243274
DeleteIn: deleteIn,
@@ -354,16 +385,16 @@ func (p *kubeBuildletPool) podUsed(podName string) bool {
354385
return ok
355386
}
356387

357-
func (p *kubeBuildletPool) podsActive() (ret []pool.ResourceTime) {
388+
func (p *kubeBuildletPool) podsActive() (ret []ResourceTime) {
358389
p.mu.Lock()
359390
defer p.mu.Unlock()
360391
for name, ph := range p.pods {
361-
ret = append(ret, pool.ResourceTime{
392+
ret = append(ret, ResourceTime{
362393
Name: name,
363394
Creation: ph.requestedAt,
364395
})
365396
}
366-
sort.Sort(pool.ByCreationTime(ret))
397+
sort.Sort(ByCreationTime(ret))
367398
return ret
368399
}
369400

@@ -376,7 +407,7 @@ func (p *kubeBuildletPool) String() string {
376407
return fmt.Sprintf("Kubernetes pool capacity: %d/%d", inUse, total)
377408
}
378409

379-
// cleanUpOldPods loops forever and periodically enumerates pods
410+
// CleanUpOldPods loops forever and periodically enumerates pods
380411
// and deletes those which have expired.
381412
//
382413
// A Pod is considered expired if it has a "delete-at" metadata
@@ -389,7 +420,7 @@ func (p *kubeBuildletPool) String() string {
389420
// stranded and wasting resources forever, we instead set the
390421
// "delete-at" metadata attribute on them when created to some time
391422
// that's well beyond their expected lifetime.
392-
func (p *kubeBuildletPool) cleanUpOldPodsLoop(ctx context.Context) {
423+
func (p *kubeBuildletPool) CleanUpOldPodsLoop(ctx context.Context) {
393424
if buildletsKubeClient == nil {
394425
log.Printf("cleanUpOldPods: no buildletsKubeClient configured; aborting.")
395426
return
@@ -438,7 +469,7 @@ func (p *kubeBuildletPool) cleanUpOldPods(ctx context.Context) {
438469
}
439470
if err == nil && time.Now().Unix() > unixDeadline {
440471
stats.DeletedOld++
441-
log.Printf("cleanUpOldPods: Deleting expired pod %q in zone %q ...", pod.Name, pool.GCEBuildEnv().ControlZone)
472+
log.Printf("cleanUpOldPods: Deleting expired pod %q in zone %q ...", pod.Name, GCEBuildEnv().ControlZone)
442473
err = buildletsKubeClient.DeletePod(ctx, pod.Name)
443474
if err != nil {
444475
log.Printf("cleanUpOldPods: problem deleting old pod %q: %v", pod.Name, err)
@@ -468,5 +499,5 @@ func (p *kubeBuildletPool) cleanUpOldPods(ctx context.Context) {
468499
}
469500

470501
func hasCloudPlatformScope() bool {
471-
return pool.HasScope(container.CloudPlatformScope)
502+
return HasScope(container.CloudPlatformScope)
472503
}

0 commit comments

Comments
 (0)