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 }