前言

环境:centos7.9 docker-ce-20.10.9 kubernetes-version v1.22.6

deployment资源对象

deployment是企业中用的最多的pod控制器。
Deployment为Pod和Replica Set提供声明式更新,只需要在 Deployment 中描述想要的目标状态是什么,,比如pod副本数等,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。

Deployment、ReplicaSet、Pod三者的关系图

通过下面这张图我们可以看得出来,deployment创建/管理ReplicaSet,ReplicaSet创建/管理pod。replicaset的名字其实就deployment的名字+pod模板的哈希值,而pod的名字就是replicaset的名字+随机字符串构成的,这样我们从一个pod的名称就很明显的知道该pod由哪个replicaset创建的以及对应的deployment是哪个:

注意:Deployment滚动更新的实现,依赖的是Kubernetes中的ReplicaSet,Deployment控制器实际操纵的,就是Replicas对象,而不是Pod对象。

创建一个deployment资源

deployment创建/管理ReplicaSet,ReplicaSet创建/管理pod,即deployment不能直接管理pod,它创建了ReplicaSet管理pod

[root@master deployment]# cat deplyment_nginx.yaml  #编写yaml资源文件
apiVersion: apps/v1
kind: Deployment                                    #创建一个deployment对象
metadata: name: deployment-nginxlabels: env: devtiar: frontnamespace: default
spec:replicas: 3                                        #3个pod副本selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- image: nginx:1.7.9name: nginx-containerimagePullPolicy: IfNotPresentports:- name: http containerPort: 80
[root@master deployment]# kubectl create -f deplyment_nginx.yaml --record  #创建deployment
[root@master deployment]# kubectl get deployments.apps deployment-nginx        #查看deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
deployment-nginx   3/3     3            3           29d
[root@master deployment]# kubectl get rs deployment-nginx-79c59dd6d8       #查看rs
NAME                          DESIRED   CURRENT   READY   AGE
deployment-nginx-79c59dd6d8   3         3         3       29d
[root@master deployment]# kubectl describe rs deployment-nginx-79c59dd6d8  #查看rs的详细信息
Name:           deployment-nginx-79c59dd6d8
Namespace:      default
Selector:       app=nginx,pod-template-hash=79c59dd6d8
Labels:         app=nginxpod-template-hash=79c59dd6d8
Annotations:    deployment.kubernetes.io/desired-replicas: 3deployment.kubernetes.io/max-replicas: 4deployment.kubernetes.io/revision: 1
Controlled By:  Deployment/deployment-nginx                 #这里看得出rs是由Deployment/deployment-nginx创建的
Replicas:       3 current / 3 desired
Pods Status:    3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:Labels:  app=nginxpod-template-hash=79c59dd6d8                       #pod模板的哈希值Containers:nginx-container:Image:        nginx:1.7.9Port:         80/TCPHost Port:    0/TCPReadiness:    exec [ls /var/ready] delay=5s timeout=2s period=10s #success=1 #failure=3Environment:  <none>Mounts:       <none>Volumes:        <none>
Events:           <none>
[root@master deployment]#
[root@master deployment]# kubectl get pods -l app=nginx
NAME                                 READY   STATUS    RESTARTS      AGE
deployment-nginx-79c59dd6d8-5cfzp    1/1     Running   1 (24h ago)   29d
deployment-nginx-79c59dd6d8-cm2k7    1/1     Running   1 (24h ago)   27d
deployment-nginx-79c59dd6d8-cqjtr    1/1     Running   1 (24h ago)   27d#查看pod的详细信息也可以看得出来pod是由ReplicaSet创建的
[root@master deployment]# kubectl describe  pods deployment-nginx-79c59dd6d8-5cfzp | grep 'Controlled By'
Controlled By:  ReplicaSet/deployment-nginx-79c59dd6d8
[root@master deployment]#

deployment的升级更新策略

Deployment更新一般是指更新镜像版本,deployment支持两种镜像更新策略:重建更新和滚动更新,可以通过strategy参数进行配置,strategy参数用于指定更新的策略,其主要支持两个属性:

1、RollingUpdate 滚动更新,默认策略就是滚动更新,RollingUpdate策略会渐进的删除旧的pod,与此同时创建新的pod,使应用在整个升级的过程中处于可用的状态,并确保其处理请求的能力没有因为升级而有所影响,这就是deployment默认使用的升级策略,升级过程中pod的数量可以在期望副本数的一定区间内浮动,其上限和下线是可配置的,如果应用能够支撑多个版本同时对外提供服务,则推荐使用这个策略升级应用。
2、Recreate,这种策略会一次性删除旧的pod,然后创建新的pod,Recreate策略会在删除旧的pod之后才创建新的pod,如果应用程序不支持多个版本同时在线,那么合适使用这种策略,不过这种策略到导致应用短暂的不可用。
下面这两个参数是对滚动更新而言,即更新策略的type=RollingUpdate生效:maxUnavailable:用来指定在升级过程中不可用pod的最大数量,默认是25%。maxSurge:用来指定在升级过程中可以超过预期的pod的最大数量,默认是25%。

deployment的升级方式、使用 kubectl set image 命令升级

deployment升级,无法就是修改pod模板的镜像版本,而修改pod模板镜像版本有很多命令可以直接操作,如下:

[root@master ~]# kubectl edit deployments.apps deployment-nginx     #使用edit命令在线编辑镜像名称版本
[root@master ~]# kubectl apply  -f deplyment_nginx.yaml            #编辑yaml文件里的镜像名称版本后再apply

但是,我们这次来讲一个更专业的更新镜像版本的命令,即kubectl set image命令。kubectl set image命令主要用于更新一个资源对象里的容器镜像。比如更新 pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), statefulset (sts), cronjob (cj), replicaset
(rs)的等资源的镜像版本。

语法:kubectl set image (-f filename | type name) container_name_1=container_image_1 ...
范例:

 # Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox container image to 'busybox'kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1# Update all deployments' and rc's nginx container's image to 'nginx:1.9.1'kubectl set image deployments,rc nginx=nginx:1.9.1 --all# Update image of all containers of daemonset abc to 'nginx:1.9.1'kubectl set image daemonset abc *=nginx:1.9.1# Print result (in yaml format) of updating nginx container image from local file, without hitting the serverkubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml#升级deloymentkubectl set image deployment/deployment-nginx nginx-container=nginx:1.8kubectl set image deployment/deployment-nginx nginx-container=nginx:1.14kubectl set image deployment/deployment-nginx nginx-container=nginx:latest

kubectl rollout 命令

kubectl rollout 命令主要是针对控制器资源进行管理,比如 在升级过程中进行暂停、继续、版本回退、查看状态、查看历史版本等操作 , kubectl rollout可以操作的资源对象如下:

  • deployments
  • daemonsets
  • statefulsets
语法:  kubectl rollout SUBCOMMAND [options]
 kubectl rollout可使用下面的子命令:history     显示升级历史版本记录pause       暂停版本升级过程restart     重启版本升级过程resume      继续已经暂停的版本升级过程status      查看当前升级状态undo        回滚到上一版本,可以使用--to-revision回滚到指定的版本示例:# 查看deployment的版本历史kubectl rollout history deployment deployment-nginx# 查看deployment的指定的第1版本信息kubectl rollout history deployment/deployment-nginx --revision=1# 回滚deployment到上一次的版本kubectl rollout undo deployment/deployment-nginx# 回滚deployment到指定的第2版本kubectl rollout undo deployment/deployment-nginx --to-revision=2# 查看daemonset的滚动更新状态kubectl rollout status daemonset/foo# 查看deployment的滚动更新状态kubectl rollout status deployment/deployment-nginx

deployment的升级、回滚原理、使用kubectl rollout undo 命令进行回滚

deployment升级之后,其实背后升级原理是deployment是创建了一个新的ReplicaSet来替代旧的ReplicaSet,这样由新版本ReplicaSet创建的pod就运行了新的应用程序从而实现了版本升级,而回滚原理也是,就是将原来新的ReplicaSet创建的pod删掉,pod数量变成0,然后将指定版本的ReplicaSet重新创建pod,这样就成功实现回滚了。

[root@master deployment]# kubectl get rs
NAME                                DESIRED   CURRENT   READY   AGE
deployment-nginx-65b57dccf4         0         0         0       39m     #旧版本的rs的pod都是0
deployment-nginx-65f6846d8b         0         0         0       41m     #旧版本的rs的pod都是0
deployment-nginx-7bb7db669d         3         3         3       27m     #当前版本的rs的pod是3
deployment-nginx-7dfd97b4dc         0         0         0       28m     #旧版本的rs的pod都是0
[root@master deployment]#
#查看所有历史升级版本
[root@master deployment]# kubectl rollout history deploment/deployment-nginx
#指定查看第3个版本,有详细信息,能看到镜像的版本
[root@master deployment]# kubectl rollout history deployment/deployment-nginx --revision=3
# 回滚deployment到上一次的版本
[root@master deployment]# kubectl rollout undo deployment/deployment-nginx
# 回滚deployment到指定的第2版本
[root@master deployment]# kubectl rollout undo deployment/deployment-nginx --to-revision=2

kubectl rollout history 查看历史版本信息

[root@master deployment]# kubectl rollout history deployment/deployment-nginx   #看到版本号,但看不出来具体什么变更
deployment.apps/deployment-nginx
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4        <none>
[root@master deployment]# kubectl rollout history deployment/deployment-nginx --revision=3    #指定查看第3个版本,有详细信息
deployment.apps/deployment-nginx with revision #3
Pod Template:Labels:       app=nginxpod-template-hash=7dfd97b4dcContainers:nginx-container:Image:      nginx:1.14Port:       80/TCPHost Port:  0/TCPEnvironment:        <none>Mounts:     <none>Volumes:      <none>
[root@master deployment]# kubectl rollout history deployment/deployment-nginx --revision=4    #指定查看第4个版本,有详细信息
deployment.apps/deployment-nginx with revision #4
Pod Template:Labels:       app=nginxpod-template-hash=7bb7db669dContainers:nginx-container:Image:      nginx:latestPort:       80/TCPHost Port:  0/TCPEnvironment:        <none>Mounts:     <none>Volumes:      <none>

暂停滚动升级、恢复滚动升级

#升级的时候立即暂停升级
[root@master ~]# kubectl set image deployment/deployment-nginx nginx-container=nginx:1.8 && kubectl rollout pause deployment/deployment-nginx
#查看rs的变化
[root@master ~]# kubectl get rs
NAME                                DESIRED   CURRENT   READY   AGE
deployment-nginx-65f6846d8b         3         3         3       39s     #原来的pod数据也没变
deployment-nginx-65b57dccf4         1         1         1       14s     #新产生了一个pod
#查看滚动升级的状态
[root@master ~]# kubectl rollout status  deployment/deployment-nginx
Waiting for deployment "deployment-nginx" rollout to finish: 1 out of 3 new replicas have been updated...# 可以看到,以上使用kubectl rollout pause 命令暂停了升级,而已经产生的新pod 仍然可以接收客户端的请求,这样,一部分流量就会被分流到新
# pod,如果用户用的没有问题,那么就可以继续升级,这就是金丝雀发布。#恢复升级
[root@master deployment]# kubectl rollout resume deployment/deployment-nginx
deployment.apps/deployment-nginx resumed
#可以看到现在升级已经完成,新的rs的pod已经是3个,旧的rs的pod是0个
[root@master ~]# kubectl  get rs
NAME                                DESIRED   CURRENT   READY   AGE
deployment-nginx-65b57dccf4         3         3         3       8m9s
deployment-nginx-65f6846d8b         0         0         0       8m34s
[root@master ~]#

历史版本数量限制,使用revisionHistoryLimit参数

我们知道了deployment升级原理是通过创建新的replicaset实现,回滚原理是通过将当前版本的replicaset创建的pods删掉,然后重新创建指定版本的replicaset的pods来实现回滚,但是当升级的次数越来越多了,就会存在越来越多的replicaset,kubernetes提供revisionHistoryLimit参数来限制历史版本数量,如下:

#使用revisionHistoryLimit参数限制保存的历史版本,当超过设置的数值,旧的replicaset就会被删掉,revisionHistoryLimit默认值是10
[root@master deployment]# kubectl explain deployment.spec.revisionHistoryLimit

滚动升级策略的maxSurge和maxUnavailable属性

# maxSurge参数表示允许超过期望副本数最大比例(或最大值)
[root@master deployment]# kubectl explain  deployments.spec.strategy.rollingUpdate.maxSurge
#maxUnavailable参数表示不可用副本数最大比例(或最大值)
[root@master deployment]# kubectl explain  deployments.spec.strategy.rollingUpdate.maxUnavailable

maxSurge:和期望ready的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。
maxUnavailable:和期望ready的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;

minReadySecond参数指定至少要成功运行多久后,才能将pod视为可用

minReadySecond属性指定新创建的pod至少要成功运行多久之后,才能将其视为可用,minReadySecond的主要功能是避免部署出错版本的应用,而不只是单纯的减慢部署速度。

[root@master ~]# kubectl explain  deployment.spec.minReadySeconds       #默认值是0,即只要新pod就绪就认为可用

一般设置就绪探针,如果一个新的pod运行出错,并在minReadySecond时间内它的就绪探针出现失败,那么新版本的滚动更新将被阻止。
通过minReadySecond属性可以让pod就绪之后继续等待n秒,然后继续执行滚动升级,来减缓升级的过程。
如果只定义就绪探针而没有正确设置minReadySecond,那么一旦有一次就绪探针调用成功,变回认为新的pod已经处于可用状态,因此最好适当的设置minReadySecond的值。

progressDeadlineSeconds参数,为滚动升级配置超时失败时间

使用progressDeadlineSeconds可以配置滚动升级的超时时间,默认是600s即10分钟,如果超过该progressDeadlineSeconds设定的时间,滚动升级仍未完成,则升级被视为失败,升级过程自动取消。

[root@master ~]# kubectl explain  deployment.spec.progressDeadlineSeconds

注意:人为使用kubectl rollout pause 命令暂停的升级过程不能被视为超时。

deployment缩容、扩容

1、直接编辑yaml文件里面的replicas字段,然后kubectl apply -f deplyment_nginx.yaml即可;或者在线编辑pod控制器修改replicas字段亦可。

2、使用kubectl scale命令直接缩容、扩容,命令有如下这些:

 # Scale a replica set named 'foo' to 3kubectl scale --replicas=3 rs/foo# Scale a resource identified by type and name specified in "foo.yaml" to 3kubectl scale --replicas=3 -f foo.yaml# If the deployment named mysql's current size is 2, scale mysql to 3kubectl scale --current-replicas=2 --replicas=3 deployment/mysql# Scale multiple replication controllerskubectl scale --replicas=5 rc/foo rc/bar rc/baz# Scale stateful set named 'web' to 3kubectl scale --replicas=3 statefulset/web#对deployment进行扩容、缩容[root@master deployment]# kubectl scale --replicas=5 deployment/deployment-nginx

deployment应用下线

如果确认应用不在提供服务,可将用于下线,如上:
1、如果是yaml部署的,删除yaml文件即可,kubectl delete -f xx.yaml (会把该yaml创建的资源都删除)
2、命令行删除:kubectl delete deployment/deployment-nginx

总结

1、Deployment、ReplicaSet、Pod三者的关系
deployment创建/管理ReplicaSet,ReplicaSet创建/管理pod。replicaset的名字其实就deployment的名字+pod模板的哈希值,而pod的名字就是
replicaset的名字+随机字符串构成的,这样我们从一个pod的名称就很明显的知道该pod由哪个replicaset创建的以及对应的deployment是哪个。2、deployment的升级更新策略
deployment支持两种镜像更新策略:重建更新和滚动更新,可以通过strategy参数进行配置,strategy参数主要支持两个属性:
(1)、RollingUpdate 滚动更新,默认策略就是滚动更新,RollingUpdate策略会渐进的删除旧的pod,与此同时创建新的pod,使应用在整个升级的过
程中处于可用的状态,并确保其处理请求的能力没有因为升级而有所影响,这就是deployment默认使用的升级策略,升级过程中pod的数量可以在期望副
本数的一定区间内浮动,其上限和下线是可配置的,如果应用能够支撑多个版本同时对外提供服务,则推荐使用这个策略升级应用。
(2)、Recreate,这种策略会一次性删除旧的pod,然后创建新的pod,Recreate策略会在删除旧的pod之后才创建新的pod,如果应用程序不支持多个版
本同时在线,那么合适使用这种策略,不过这种策略到导致应用短暂的不可用。下面这两个参数是对滚动更新策略而言,即更新策略的type=RollingUpdate生效:maxUnavailable:用来指定在升级过程中不可用pod的最大数量,默认是25%。maxSurge:用来指定在升级过程中可以超过预期的pod的最大数量,默认是25%。3、deployment的升级方式
[root@master ~]# kubectl edit deployments.apps deployment-nginx        #使用edit命令在线编辑镜像名称版本
[root@master ~]# kubectl apply  -f deplyment_nginx.yaml            #编辑yaml文件里的镜像名称版本后再apply
#使用kubectl set image 命令对镜像进行升级
[root@master ~]# kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.14、kubectl rollout 命令kubectl rollout 可使用下面的子命令:history     显示升级历史版本记录pause       暂停版本升级过程restart     重启版本升级过程resume      继续已经暂停的版本升级过程status      查看当前升级状态undo        回滚到上一版本,可以使用--to-revision回滚到指定的版本# 查看deployment的版本历史
[root@master ~]# kubectl rollout history deployment deployment-nginx
# 查看deployment的指定的第1版本信息
[root@master ~]# kubectl rollout history deployment/deployment-nginx --revision=1
# 回滚deployment到上一次的版本
[root@master ~]# kubectl rollout undo deployment/deployment-nginx
# 回滚deployment到指定的第2版本
[root@master ~]# kubectl rollout undo deployment/deployment-nginx --to-revision=2
# 查看daemonset的滚动更新状态
[root@master ~]# kubectl rollout status daemonset/foo
# 查看deployment的滚动更新状态
[root@master ~]# kubectl rollout status deployment/deployment-nginx5、deployment的升级、回滚原理
deployment升级之后,其实背后升级原理是deployment是创建了一个新的ReplicaSet来替代旧的ReplicaSet,这样由新版本ReplicaSet创建的pod就
运行了新的应用程序从而实现了版本升级,而回滚原理也是,就是将原来新的ReplicaSet创建的pod删掉,pod数量变成0,然后将指定版本ReplicaSet
重新创建pod,这样就成功实现回滚了。6、revisionHistoryLimit、minReadySecond、progressDeadlineSeconds属性
使用revisionHistoryLimit参数限制保存的历史版本,当超过设置的数值,旧的replicaset就会被删掉,revisionHistoryLimit默认值是10
[root@master deployment]# kubectl explain deployment.spec.revisionHistoryLimitminReadySecond参数指定至少要成功运行多久后,才能将pod视为可用
[root@master ~]# kubectl explain  deployment.spec.minReadySeconds      #默认值是0,即只要新pod就绪就认为可用progressDeadlineSeconds参数,为滚动升级配置超时失败时间,默认是600s即10分钟,如果超过该progressDeadlineSeconds设定的时间,滚动
升级仍未完成,则升级被视为失败,升级过程自动取消。
[root@master ~]# kubectl explain  deployment.spec.progressDeadlineSeconds
注意:人为使用kubectl rollout pause 命令暂停的升级过程不能被视为超时。7、deployment的缩容、扩容
直接编辑yaml文件里面的replicas字段,然后`kubectl apply -f deplyment_nginx.yaml`即可;或者在线编辑pod控制器修改replicas字段亦可;
[root@master ~]# kubectl scale --replicas=5 deployment/deployment-nginx                       #对deployment进行扩容、缩容

什么是deployment 声明式升级应用相关推荐

  1. deployment:声明式的升级应用

    9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2 使用kubia-v2版本应用来替换运行着 ...

  2. 声明式API replica controller vs replica set 对比

    1.在命令式API中,你可以直接发出服务器要执行的命令,例如: "运行容器"."停止容器"等. 在声明性API中,你声明系统要执行的操作,系统将不断向该状态驱动 ...

  3. k8s中kubectl陈述式/声明式资源管理

    k8s陈述资源管理方法的说明 1.kubernetes 集群管理集群资源的唯一入口是通过相应的方法调用 apiserver 的接口 2.kubectl 是官方的CLI命令行工具,用于与 apiserv ...

  4. 27. 代码实例-spring声明式事务

    (1)spring配置文件: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns= ...

  5. 通过 React Hooks 声明式地使用 setInterval

    2019独角兽企业重金招聘Python工程师标准>>> 本文由云+社区发表 作者:Dan Abramov 接触 React Hooks 一定时间的你,也许会碰到一个神奇的问题: se ...

  6. kubernetes(k8s)使用声明式管理与 创建yaml模板文件

    文章目录 一:声明式管理方法 1.1 什么是声明式管理 1.2 查看资源配置 1.2.1 查看资源配置清单 1.2 使用explain 解释资源配置清单 1.3 修改资源配置清单并应用 1.3.1 离 ...

  7. KCL:声明式的云原生配置策略语言

    楔子: 以蚂蚁集团典型的建站场景为例,在接入 Kusion 后,用户侧配置代码减少到 5.5%,用户面对的 4 个平台通过接入统一代码库而消减,在无其他异常的情况下交付时间从 2 天下降到 2 小时- ...

  8. Jenkins Pipeline声明式流水线

    Jenkins是为了顺应以用户的需求进化为核心,采用迭代.循序渐进的方法进行软件开发,也就是敏捷开发模型 传统的瀑布模型 上一个的输出是下一个的输入,没有迭代与反馈,也就代表了没有回头路可以走,对于后 ...

  9. 最实际与高效生成数据库高级声明式SQL脚本神器研发

    一. 简介 1.1前言 1.2作用 二. 实现方式与原理 2.1实现方式 2.2原理 三. 体系与图解 3.1创建表与插数据脚本 3.2添加或修改表脚本 3.3删除表脚本 3.4删除与创建索引脚本 3 ...

  10. 【Java与Python实现】最实际与高效生成数据库高级声明式SQL脚本神器研发

    一. 简介 1.1前言 1.2作用 二. 实现方式与原理 2.1实现方式 2.2原理 三. 体系与图解 3.1创建表与插数据脚本 3.2添加或修改表脚本 3.3删除表脚本 3.4删除与创建索引脚本 3 ...

最新文章

  1. C++ operator操作符重载(++,--,-,+,())
  2. Seata 的AT模式需求实战_04
  3. 华晨集团债务违约65亿 宝马中国:华晨宝马运营不受影响
  4. ansible的delegate_to、connection、和local_action
  5. 17.PHPDoc 规范,PHPDocumenter 生成
  6. zz java compare 接口
  7. Nginx 企业级优化
  8. 日志打印、main函数中代码执行顺序
  9. vc2010下调用miniblink控件实现浏览器简单实例
  10. android webView 全屏播放网络视频
  11. 碧蓝航线经济系统的流程图
  12. 软件项目管理_作业1
  13. 小私企老板的痛病通病
  14. eos安装区块链开发环境
  15. Android中来电号码归属地的显示
  16. teamlab什么意思_普通人如何能更有意义地参观美术馆?
  17. 使用Server酱实现Cobalt Strike主机上线微信提醒
  18. Redux 入门教程,应用的状态管理器
  19. 碉堡了,一个专注于效率的开源编程语言
  20. 制作稳定版本的rootfs

热门文章

  1. lc滤波器是利用电感的感抗_电感器在电路中的应用特性
  2. 计算机与信息安全基本概念和知识,第8章计算机网络应用与信息安全知识.ppt
  3. php session auto_start,PHP出现 Warning: session_start()的解决方法
  4. echarts数据包坐标拾取工具
  5. 解决mySQL数据库锁表问题。
  6. BZOJ 5106 [CodePlus2017]汀博尔
  7. PHP使用Apache中的ab测试网站的压力性能及mpm介绍
  8. mstsc远程桌面全频或自定义窗口
  9. ML~线性代数~python
  10. asp.net 读取导入的project(mpp)文件