ARTS-WEEK3

2019-04-01

本周ARTS

本周ARTS打卡内容:

  1. Algorithm 来源 LeetCode18
  2. Review 分享 kubernetes调度的文档
  3. Tip 分享几条AIX的命令
  4. Share 分享go的设计模式

Algorithm

LeetCode的18题,4个整数和的问题:

https://leetcode.com/problems/4sum/submissions/

想到了之前的三数之和的问题,遍历整个数组nums,得到当前值,计算后续数组的值是否为target-nums[i],代码如下:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
func fourSum(nums []int, target int) [][]int {
results := [][]int{}
n := len(nums)
if n < 4 {
return results
}
sort.Ints(nums)
for k:=0; k<n-3; k++ {
if k>0 && nums[k] == nums[k-1] {
continue
}
threes := threeSum(nums[k+1:], target-nums[k])
if len(threes) == 0 {
continue
}
for _, i := range threes{
t := append(i, nums[k])
results = append(results, t)
}
}
return results
}

func threeSum(nums []int, want int) [][]int {
results := [][]int{}
n := len(nums)
if n == 0 || n < 3 {
return results
}
sort.Ints(nums)
for i := 0; i < n-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
target := want-nums[i]
left := i + 1
right := n - 1
for left < right {
sum := nums[left] + nums[right]
if sum == target {
results = append(results, []int{nums[left], nums[right], nums[i]})
left++
right--
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
} else if sum > target {
right--
} else if sum < target {
left++
}
}
}
return results
}

当然也可以合并到一个函数中。

Review

本周的内容是:
kubernetes community的文档,介绍kubernetes scheduler

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-scheduling/scheduler.md

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-scheduling/scheduler_algorithm.md

scheduler.md

主要介绍了三个方面的内容:

代码结构

调度器的代码主要分为三个部分:

  1. cmd/kube-scheduler/scheduler.go 中是整个调度器的入口,包含调度器的一些初始化工作
  2. pkg/scheduler/scheduler.go 调度的框架
  3. pkg/scheduler/core/generic_scheduler.go 调度pod到节点的算法

调度算法

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
37
38
39
40
41
对于给定节点:

+---------------------------------------------+
| 可用的调度节点: |
| |
| +--------+ +--------+ +--------+ |
| | node 1 | | node 2 | | node 3 | |
| +--------+ +--------+ +--------+ |
| |
+-------------------+-------------------------+
|
|
v
+-------------------+-------------------------+

过滤: node 3 没有足够的资源

+-------------------+-------------------------+
|
|
v
+-------------------+-------------------------+
| 保留节点: |
| +--------+ +--------+ |
| | node 1 | | node 2 | |
| +--------+ +--------+ |
| |
+-------------------+-------------------------+
|
|
v
+-------------------+-------------------------+

优先级计算: node 1: p=2
node 2: p=5

+-------------------+-------------------------+
|
|
v
选择优先级最大的节点: node 2

调度器每次为每个pod找到一个节点。

  • 首先,通过一系列的断言筛选出适合调度的节点。比如根据PodSpec中申明的资源请求,提出没有这么多资源的节点。
  • 其次,通过一系列优先级函数来给选出的节点打分。调度器尝试把Pod放到各个节点上,并据此打分,资源压力小,分更高。
  • 最后,选择优先级分数最高的。

调度器延展

调度器是可扩展的,集群管理员可以选择哪些预定义的调度策略使用,也可以自己添加新的调度策略。

修改策略

默认的调度策略是通过pkg/scheduler/algorithmprovider/defaults/defaults.go中的defaultPredicates() and defaultPriorities()选定的。另外,调度策略也可以通过命令行--policy-config-file+JSON文件的方式来指定。因此,增加一个新的调度策略,可以修改pkg/scheduler/algorithm/predicates/predicates.go或者加到pkg/scheduler/algorithm/priorities目录中,然后在defaultPredicates()defaultPriorities()注册策略。

scheduler_algorithm

对于每个未调度的Pod,kubernetes调度器都会尝试通过一些列的算法,来给它找到合适的节点。这个过程主要分为两步。第一步过滤节点,第二步给过滤后的节点打分来找到最合适Pod的节点。

筛选节点

筛选节点的目的是剔除掉那些不满足节点要求的Pod。比如不能满足Pod的资源需求。有以下几种筛选策略:

  • NoDiskConflict:根据pod的磁盘卷要求和节点的挂载情况来估算是否合适。目前支持的卷有:AWS EBS,GCE PD, ISCSI和Ceph RBD。只有被支持的卷的PVC会被检查。PV会被直接加到Pods中,不需要通过这项规则的限制。
  • NoVolumeZoneConflict: 在给定的区域限制中,预估Pod要求的卷是否在节点上可用。
  • PodFitsResources: 检查节点的空闲资源(CPU、Memory)是否满足Pod的需求。空闲资源等于节点的总资源减去节点上所有Pod请求的资源。更多的内容可以查看Kubernetes的QoS机制。
  • PodFitsHostPorts: 检查Pod请求的HostPort在节点上是否可用。
  • HostName: 剔除除了PodSpec的NodeName中申明的所有节点。
  • MatchNodeSelector: 检查节点的labels是否匹配Pod的nodeselector或者现在的nodeAffinity。
  • MaxEBSVolumeCount: 确保连接的AWS EBS卷没有超过最大限度。
  • MaxGCEPDVolumeCount: 确保连接的GCE PD卷没有超出最大限制。
  • CheckNodeMemoryPressure: 检查Pod能否被调度到处于内存压力状态的节点。
  • CheckNodeDiskPressure: 检查Pod能否被调度到处于磁盘压力状态的节点。

以上内容可以在pkg/scheduler/algorithm/predicates/predicates.go中找到。Kubernetes使用了一些,但没有全部使用。可以在pkg/scheduler/algorithmprovider/defaults/defaults.go看到默认选择了哪些

节点评分

通过以上筛选出来的节点是适合Pod运行的,但是通常会筛选出不止一个节点。kubernetes会对这些节点进行排序以筛选出最适合Pod的节点。排序的过程是通过一系列的排序函数实现的。对于每个节点,一个排序函数会给出0-10分,其中10分表示最优解,0分表示最差解。每个排序函数都有一个权重数字,最后将所有排序函数权重乘以得分的结果加起来:

1
最终得分 = (权重1 * 排序函数1)+(权重2 * 排序函数2)

计算出所有节点的得分后,得分最高的节点就是Pod将被调度到的节点。如果最高得分不止一个,将会随机选择其中的一个。

目前,kubernetes调度器提供了一些排序函数:

  • LeastRequestedPriority: 节点的排序是基于空闲资源的比例,CPU和memory是同样权重的。资源空闲度最高的节点是最好的。需要注意的是,这个优先级函数起到了按照资源消耗来跨节点分配pods的作用。
  • BalancedResourceAllocation: 这种排序函数将把Pod调度到节点上,以便在部署Pod后节点的CPU和内存利用率能平衡。
  • SelectorSpreadPriority: 让有相同service,replication controller, replica set的pod尽量少的分配到相同节点上。如果节点上有区域信息,该排序算法将调整使得pods分布跨区域和节点。
  • CalculateAntiAffinityPriority: 使拥有相同service,尽量分散在不同的具有指定标签的主机上。
  • ImageLocalityPriority: 根据pod请求的本地拥有的镜像来排序。本地已安装Pod需要的大镜像的节点,将比本地没有安装,或只安装了小镜像的节点拥有更高分。
  • NodeAffinityPriority: Kubernetes调度中的亲和性机制,具体可查看这里

以上优先级函数在pkg/scheduler/algorithm/priorities中都能找到。kubernetes使用了一些,但不是全部,具体可以在pkg/scheduler/algorithmprovider/defaults/defaults.go中看到默认选择了哪些。

Tip

分享几条AIX的命令

1. 查看占用内存最多的进程
执行svmon -P|grep -p pid;
ps vx|head -1;ps vx|grep -v PID|sort -rn +6|head -100

2. 查看某个进程内存使用变化情况
svmon -P pid -I 1|grep -P Pid

3. 查看系统消息队列、共享内存、信号量
Ipcs
输出内容中q表示消息队列,m表示共享内存段,s表示信号量

4. 清除IPC资源
ipcrm -q MessageID                 清除消息队列
ipcrm -m SharedMemoryID   清除共享内容
ipcrm -s SemaphoreID            清除信号量

5. 查看僵尸进程
ps -ef|grep defunct

6. 查询换页最多的进程
ps vx|head -1;ps vx|grep -v PID|sort -rn +4|head -10


7. 查看通讯是否丢包
netstat -i    ////比较Ierrs/Ipkts和Oerrs/Opkts是否>1%
entstat -d ent0 (lan adapter name)   查看Transmit

8. AIX系统查看线程使用情况
ps -emo THREAD

Share

本次分享:http://tmrts.com/go-patterns/

go语言的各种设计模式实现样例,遵循设计模式能让代码的可读性,可靠性,重用性变的更高。