github.com/bigcommerce/nomad@v0.9.3-bc/scheduler/stack_oss.go (about)

     1  // +build !pro,!ent
     2  
     3  package scheduler
     4  
     5  // NewGenericStack constructs a stack used for selecting service placements
     6  func NewGenericStack(batch bool, ctx Context) *GenericStack {
     7  	// Create a new stack
     8  	s := &GenericStack{
     9  		batch: batch,
    10  		ctx:   ctx,
    11  	}
    12  
    13  	// Create the source iterator. We randomize the order we visit nodes
    14  	// to reduce collisions between schedulers and to do a basic load
    15  	// balancing across eligible nodes.
    16  	s.source = NewRandomIterator(ctx, nil)
    17  
    18  	// Create the quota iterator to determine if placements would result in the
    19  	// quota attached to the namespace of the job to go over.
    20  	s.quota = NewQuotaIterator(ctx, s.source)
    21  
    22  	// Attach the job constraints. The job is filled in later.
    23  	s.jobConstraint = NewConstraintChecker(ctx, nil)
    24  
    25  	// Filter on task group drivers first as they are faster
    26  	s.taskGroupDrivers = NewDriverChecker(ctx, nil)
    27  
    28  	// Filter on task group constraints second
    29  	s.taskGroupConstraint = NewConstraintChecker(ctx, nil)
    30  
    31  	// Filter on task group devices
    32  	s.taskGroupDevices = NewDeviceChecker(ctx)
    33  
    34  	// Create the feasibility wrapper which wraps all feasibility checks in
    35  	// which feasibility checking can be skipped if the computed node class has
    36  	// previously been marked as eligible or ineligible. Generally this will be
    37  	// checks that only needs to examine the single node to determine feasibility.
    38  	jobs := []FeasibilityChecker{s.jobConstraint}
    39  	tgs := []FeasibilityChecker{s.taskGroupDrivers, s.taskGroupConstraint, s.taskGroupDevices}
    40  	s.wrappedChecks = NewFeasibilityWrapper(ctx, s.quota, jobs, tgs)
    41  
    42  	// Filter on distinct host constraints.
    43  	s.distinctHostsConstraint = NewDistinctHostsIterator(ctx, s.wrappedChecks)
    44  
    45  	// Filter on distinct property constraints.
    46  	s.distinctPropertyConstraint = NewDistinctPropertyIterator(ctx, s.distinctHostsConstraint)
    47  
    48  	// Upgrade from feasible to rank iterator
    49  	rankSource := NewFeasibleRankIterator(ctx, s.distinctPropertyConstraint)
    50  
    51  	// Apply the bin packing, this depends on the resources needed
    52  	// by a particular task group.
    53  	s.binPack = NewBinPackIterator(ctx, rankSource, false, 0)
    54  
    55  	// Apply the job anti-affinity iterator. This is to avoid placing
    56  	// multiple allocations on the same node for this job.
    57  	s.jobAntiAff = NewJobAntiAffinityIterator(ctx, s.binPack, "")
    58  
    59  	// Apply node rescheduling penalty. This tries to avoid placing on a
    60  	// node where the allocation failed previously
    61  	s.nodeReschedulingPenalty = NewNodeReschedulingPenaltyIterator(ctx, s.jobAntiAff)
    62  
    63  	// Apply scores based on affinity stanza
    64  	s.nodeAffinity = NewNodeAffinityIterator(ctx, s.nodeReschedulingPenalty)
    65  
    66  	// Apply scores based on spread stanza
    67  	s.spread = NewSpreadIterator(ctx, s.nodeAffinity)
    68  
    69  	// Normalizes scores by averaging them across various scorers
    70  	s.scoreNorm = NewScoreNormalizationIterator(ctx, s.spread)
    71  
    72  	// Apply a limit function. This is to avoid scanning *every* possible node.
    73  	s.limit = NewLimitIterator(ctx, s.scoreNorm, 2, skipScoreThreshold, maxSkip)
    74  
    75  	// Select the node with the maximum score for placement
    76  	s.maxScore = NewMaxScoreIterator(ctx, s.limit)
    77  	return s
    78  }