swarm源码--strategy和filter

strategy

binpack

binpack策略就是为了避免容器碎片化,意味着将容器尽可能的分配到一个节点上(这样说可能不准确,也就是把资源集中起来,预留出更多闲置的资源),预留出未使用的节点给需要更大空间的容器运行。
这段源码位于swarm/scheduler/strategy.go/binpack.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// BinpackPlacementStrategy places a container onto the most packed node in the cluster.
//空结构体
type BinpackPlacementStrategy struct {
}

// Initialize a BinpackPlacementStrategy.
func (p *BinpackPlacementStrategy) Initialize() error {
return nil
}

// Name returns the name of the strategy.
func (p *BinpackPlacementStrategy) Name() string {
return "binpack"
}

上面用于初始化一个空结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// RankAndSort sorts nodes based on the binpack strategy applied to the container config.
func (p *BinpackPlacementStrategy) RankAndSort(config *cluster.ContainerConfig, nodes []*node.Node) ([]*node.Node, error) {
// for binpack, a healthy node should increase its weight to increase its chance of being selected
// set healthFactor to 10 to make health degree [0, 100] overpower cpu + memory (each in range [0, 100])
const healthFactor int64 = 10
//返回满足条件的节点群,对于节点打上不同的分数(根据cpu,mem和节点健康因子)
weightedNodes, err := weighNodes(config, nodes, healthFactor)
if err != nil {
return nil, err
}

sort.Sort(sort.Reverse(weightedNodes))
output := make([]*node.Node, len(weightedNodes))
for i, n := range weightedNodes {
output[i] = n.Node
}
return output, nil
}

weighNodes函数作用:读取要启动的容器的配置,接着扫描集群中所有的节点,过滤掉那些cpu或者内存不满足的节点,并对满足条件的节点从三个方面进行考核(cpu,mem和节点的健康状况)进行打分,满分一百,组成一个候选队列,从队列中返回三项加起来最大的节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//weighted_node.go
func weighNodes(config *cluster.ContainerConfig, nodes []*node.Node, healthinessFactor int64) (weightedNodeList, error) {
weightedNodes := weightedNodeList{}
//遍历找寻合适的节点(cpu,内存合适的节点)
for _, node := range nodes {
nodeMemory := node.TotalMemory
nodeCpus := node.TotalCpus

// Skip nodes that are smaller than the requested resources.
if nodeMemory < int64(config.HostConfig.Memory) || nodeCpus < config.HostConfig.CPUShares {
continue
}

var (
cpuScore int64 = 100
memoryScore int64 = 100
)

if config.HostConfig.CPUShares > 0 {
cpuScore = (node.UsedCpus + config.HostConfig.CPUShares) * 100 / nodeCpus
}
if config.HostConfig.Memory > 0 {
memoryScore = (node.UsedMemory + config.HostConfig.Memory) * 100 / nodeMemory
}

if cpuScore <= 100 && memoryScore <= 100 {
weightedNodes = append(weightedNodes, &weightedNode{Node: node, Weight: cpuScore + memoryScore + healthinessFactor*node.HealthIndicator})
}
}

if len(weightedNodes) == 0 {
return nil, ErrNoResourcesAvailable
}

return weightedNodes, nil
}