文档章节

聊聊你可能误解的Kubernetes Deployment滚动更新机制

WaltonWang
 WaltonWang
发布于 2017/08/21 23:13
字数 3392
阅读 54
收藏 0
点赞 0
评论 0

Author: xidianwangtao@gmail.com

定义Deployment时与rolling update的相关项

以下面的frontend Deployment为例,重点关注.spec.minReadySeconds,.spec.strategy.rollingUpdate.maxSurge,.spec.strategy.rollingUpdate. maxUnavailable

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 2
  replicas: 25
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below:
          # value: env
        ports:
        - containerPort: 80
  • .spec.minReadySeconds: 新创建的Pod状态为Ready持续的时间至少为.spec.minReadySeconds才认为Pod Available(Ready)。
  • .spec.strategy.rollingUpdate.maxSurge: specifies the maximum number of Pods that can be created over the desired number of Pods. The value cannot be 0 if MaxUnavailable is 0. 可以为整数或者百分比,默认为desired Pods数的25%. Scale Up新的ReplicaSet时,按照比例计算出允许的MaxSurge,计算时向上取整(比如3.4,取4)。
  • .spec.strategy.rollingUpdate.maxUnavailable: specifies the maximum number of Pods that can be unavailable during the update process. The value cannot be 0 if maxSurge is 0.可以为整数或者百分比,默认为desired Pods数的25%. Scale Down旧的ReplicaSet时,按照比例计算出允许的maxUnavailable,计算时向下取整(比如3.6,取3)。

因此,在Deployment rollout时,需要保证Available(Ready) Pods数不低于 desired pods number - maxUnavailable; 保证所有的Pods数不多于 desired pods number + maxSurge

滚动更新的流程

Note: A Deployment’s rollout is triggered if and only if the Deployment’s pod template (that is, .spec.template) is changed, for example if the labels or container images of the template are updated. Other updates, such as scaling the Deployment, do not trigger a rollout.

我们继续以上面的Deployment为例子,并考虑最常用的情况--更新image(发布新版本):

kubectl set image deploy frontend php-redis=gcr.io/google-samples/gb-frontend:v3 --record

set image之后,导致Deployment's Pod Template发生变化,就会触发rollout。我们只考虑RollingUpdate策略(Kubernetes还支持ReCreate更新策略)。通过kubectl get rs -w来watch ReplicaSet的变化。

[root@master03 ~]# kubectl get rs -w
NAME                  DESIRED   CURRENT   READY     AGE
frontend-3114648124   25        25        25        14m
frontend-3099797709   0         0         0         1h
frontend-3099797709   0         0         0         1h
frontend-3099797709   3         0         0         1h
frontend-3114648124   23        25        25        17m
frontend-3099797709   5         0         0         1h
frontend-3114648124   23        25        25        17m
frontend-3114648124   23        23        23        17m
frontend-3099797709   5         0         0         1h
frontend-3099797709   5         3         0         1h
frontend-3099797709   5         5         0         1h
frontend-3099797709   5         5         1         1h
frontend-3114648124   22        23        23        17m
frontend-3099797709   5         5         2         1h
frontend-3114648124   22        23        23        17m
frontend-3114648124   22        22        22        17m
frontend-3099797709   6         5         2         1h
frontend-3114648124   21        22        22        17m
frontend-3099797709   6         5         2         1h
frontend-3114648124   21        22        22        17m
frontend-3099797709   7         5         2         1h
frontend-3099797709   7         6         2         1h
frontend-3114648124   21        21        21        17m
frontend-3099797709   7         6         2         1h
frontend-3099797709   7         7         2         1h
frontend-3099797709   7         7         2         1h
frontend-3099797709   7         7         3         1h
frontend-3099797709   7         7         4         1h
frontend-3114648124   20        21        21        17m
frontend-3099797709   8         7         4         1h
frontend-3114648124   20        21        21        17m
frontend-3114648124   20        20        20        17m
frontend-3099797709   8         7         4         1h
frontend-3099797709   8         8         4         1h
frontend-3099797709   8         8         5         1h
frontend-3114648124   19        20        20        17m
frontend-3099797709   9         8         5         1h
frontend-3114648124   19        20        20        17m
frontend-3099797709   9         8         5         1h
frontend-3099797709   9         9         5         1h
frontend-3114648124   19        19        19        17m
frontend-3099797709   9         9         5         1h
frontend-3114648124   18        19        19        18m
frontend-3099797709   10        9         5         1h
frontend-3114648124   18        19        19        18m
frontend-3099797709   10        9         5         1h
frontend-3114648124   18        18        18        18m
frontend-3099797709   10        10        5         1h
frontend-3099797709   10        10        5         1h
frontend-3114648124   18        18        18        18m
frontend-3099797709   10        10        6         1h
frontend-3099797709   10        10        6         1h
frontend-3114648124   17        18        18        18m
frontend-3114648124   17        18        18        18m
frontend-3099797709   11        10        6         1h
frontend-3099797709   11        10        6         1h
frontend-3114648124   17        17        17        18m
frontend-3099797709   11        11        6         1h

说明:

  1. frontend-3114648124为原来的RS(成为OldRS),frontend-3099797709为新建的RS(成为NewRS,当然也可能是Old RS,如果之前执行过这个一样的内容)。
  2. maxSurge:3, maxUnavailable=2, desired replicas=25
  • NewRS创建maxSurge(3)个Pods,这时达到pods数的上限值desired replicas + maxSurge (28个)
  • 不会等NewRS创建的Pods Ready,而是马上delete OldRS maxUnavailable(2)个Pods,这时Ready的Pods number最差也能保证desired replicas - maxUnavailable(23个)
  • 接下来的流程是不固定,只要新建的Pods有几个返回Ready,则意味着可以接着删除几个旧的Pods了。只要有几个删除成功的Pods返回,就会创建一定数量的Pods,只要All pods数量与上限值desired replicas + maxSurge有差值空间,就会接着创建新的Pods。
  • 如此进行滚动更新, 直到创建的新Pods个数达到desired replicas,并等待它们都Ready,然后再删除所有剩余的旧的Pods。至此,滚动流程结束。

对同一个Deployment先后触发滚动更新,逻辑如何?

我们考虑这个情况,但用户执行某个滚动更新后,未等待此次滚动更新结束,就继续执行了一次新的滚动更新请求,这时后台滚动流程会怎么样呢?会乱成一锅粥么?

我们继续以这个例子来看:

# deploy frontend 稳定运行在v2(frontend-888714875)时:
[root@master03 ~]# kubectl get rs -w
NAME                DESIRED   CURRENT   READY     AGE

====执行 kubectl set image deploy frontend php-redis=gcr.io/google-samples/gb-frontend:v3 --record
----备注: v3 --> frontend-776431694
frontend-776431694   0         0         0         6h
frontend-776431694   0         0         0         6h
frontend-776431694   3         0         0         6h
frontend-888714875   23        25        25        5h
frontend-776431694   5         0         0         6h
frontend-888714875   23        25        25        5h
frontend-888714875   23        23        23        5h
frontend-776431694   5         0         0         6h
frontend-776431694   5         3         0         6h
frontend-776431694   5         5         0         6h
frontend-776431694   5         5         1         6h
frontend-776431694   5         5         2         6h
frontend-776431694   5         5         3         6h
frontend-776431694   5         5         4         6h
frontend-776431694   5         5         4         6h
frontend-888714875   22        23        23        5h
frontend-776431694   6         5         4         6h
frontend-888714875   22        23        23        5h
frontend-888714875   22        22        22        5h
frontend-776431694   6         5         4         6h
frontend-776431694   6         6         4         6h
frontend-776431694   6         6         4         6h
frontend-888714875   19        22        22        5h
frontend-776431694   9         6         4         6h
frontend-888714875   19        22        22        5h
frontend-776431694   9         6         4         6h
frontend-888714875   19        19        19        5h
frontend-776431694   9         9         4         6h
frontend-888714875   19        19        19        5h

==== 执行 kubectl set image deploy frontend php-redis=gcr.io/google-samples/gb-frontend:v4 --record ====
----- 备注:v4 --> frontend-3099797709 ----

frontend-3099797709   0         0         0         6h
frontend-3099797709   0         0         0         6h
frontend-776431694   4         9         4         6h
frontend-3099797709   5         0         0         6h
frontend-3099797709   5         0         0         6h
frontend-3099797709   5         5         0         6h
frontend-776431694   4         9         4         6h
frontend-776431694   4         4         4         6h
frontend-3099797709   5         5         0         6h
frontend-3099797709   5         5         1         6h
frontend-3099797709   5         5         2         6h
frontend-3099797709   5         5         3         6h
frontend-3099797709   5         5         4         6h
frontend-3099797709   5         5         4         6h
frontend-776431694   2         4         4         6h
frontend-3099797709   7         5         4         6h
frontend-776431694   2         4         4         6h
frontend-776431694   2         2         2         6h
frontend-776431694   2         2         2         6h
frontend-3099797709   7         5         4         6h
frontend-776431694   0         2         2         6h
frontend-3099797709   7         7         4         6h
frontend-776431694   0         2         2         6h
frontend-3099797709   9         7         4         6h
frontend-776431694   0         0         0         6h
frontend-3099797709   9         7         4         6h
frontend-3099797709   9         9         4         6h
frontend-776431694   0         0         0         6h
frontend-3099797709   9         9         4         6h
frontend-3099797709   9         9         5         6h
frontend-3099797709   9         9         6         6h
frontend-3099797709   9         9         7         6h
frontend-888714875   17        19        19        5h
frontend-3099797709   11        9         7         6h
frontend-888714875   17        19        19        5h
frontend-888714875   17        17        17        5h
frontend-3099797709   11        9         7         6h
frontend-888714875   16        17        17        5h
frontend-3099797709   11        11        7         6h
frontend-3099797709   12        11        7         6h
frontend-888714875   16        17        17        5h
frontend-888714875   16        16        16        5h
frontend-3099797709   12        11        7         6h
frontend-3099797709   12        12        7         6h
frontend-3099797709   12        12        8         6h
frontend-3099797709   12        12        8         6h
frontend-888714875   15        16        16        5h
frontend-3099797709   13        12        8         6h
frontend-888714875   15        16        16        5h
frontend-888714875   15        15        15        5h
frontend-3099797709   13        12        8         6h
frontend-3099797709   13        13        8         6h
frontend-3099797709   13        13        8         6h
frontend-3099797709   13        13        9         6h
frontend-3099797709   13        13        10        6h
frontend-888714875   14        15        15        5h
frontend-3099797709   14        13        10        6h
frontend-888714875   14        15        15        5h
frontend-888714875   14        14        14        5h
frontend-3099797709   14        13        10        6h
frontend-888714875   14        14        14        5h
frontend-3099797709   14        14        11        6h
frontend-3099797709   14        14        12        6h
frontend-3099797709   14        14        12        6h
frontend-3099797709   14        14        12        6h
frontend-888714875   11        14        14        5h
frontend-3099797709   17        14        12        6h
frontend-888714875   11        14        14        5h
frontend-3099797709   17        14        12        6h
frontend-888714875   11        11        11        5h
frontend-3099797709   17        17        12        6h
frontend-888714875   11        11        11        5h
frontend-3099797709   17        17        12        6h
frontend-3099797709   17        17        13        6h
frontend-3099797709   17        17        14        6h
frontend-3099797709   17        17        14        6h
frontend-888714875   10        11        11        5h
frontend-3099797709   18        17        14        6h
frontend-888714875   10        11        11        5h
frontend-888714875   10        10        10        5h
frontend-3099797709   18        17        14        6h
frontend-3099797709   18        18        14        6h
frontend-3099797709   18        18        15        6h
frontend-888714875   9         10        10        5h
frontend-3099797709   18        18        16        6h
frontend-888714875   9         10        10        5h
frontend-3099797709   19        18        16        6h
frontend-3099797709   19        18        16        6h
frontend-888714875   9         9         9         5h
frontend-888714875   7         9         9         5h
frontend-3099797709   19        18        16        6h
frontend-888714875   7         9         9         5h
frontend-3099797709   21        18        16        6h
frontend-888714875   7         9         9         5h
frontend-3099797709   21        19        16        6h
frontend-888714875   7         7         7         5h
frontend-3099797709   21        21        16        6h
frontend-888714875   7         7         7         5h
frontend-3099797709   21        21        17        6h
frontend-3099797709   21        21        18        6h
frontend-3099797709   21        21        18        6h
frontend-888714875   5         7         7         5h
frontend-888714875   5         7         7         5h
frontend-3099797709   23        21        18        6h
frontend-888714875   5         5         5         5h
frontend-3099797709   23        21        18        6h
frontend-3099797709   23        23        18        6h
frontend-3099797709   23        23        18        6h
frontend-3099797709   23        23        19        6h
frontend-3099797709   23        23        20        6h
frontend-3099797709   23        23        20        6h
frontend-888714875   3         5         5         5h
frontend-3099797709   25        23        20        6h
frontend-888714875   3         5         5         5h
frontend-888714875   3         3         3         5h
frontend-3099797709   25        23        20        6h
frontend-888714875   3         3         3         5h
frontend-3099797709   25        25        20        6h
frontend-3099797709   25        25        21        6h
frontend-3099797709   25        25        22        6h
frontend-3099797709   25        25        22        6h
frontend-888714875   2         3         3         5h
frontend-888714875   2         3         3         5h
frontend-888714875   2         2         2         5h
frontend-888714875   2         2         2         5h
frontend-3099797709   25        25        23        6h
frontend-888714875   1         2         2         5h
frontend-888714875   1         2         2         5h
frontend-888714875   1         1         1         5h
frontend-3099797709   25        25        23        6h
frontend-888714875   0         1         1         5h
frontend-888714875   0         1         1         5h
frontend-888714875   0         0         0         5h
frontend-3099797709   25        25        24        6h
frontend-3099797709   25        25        25        6h
frontend-3099797709   25        25        25        6h

说明:
deployment frontend稳定运行在v2版本(RS:frontend-888714875),然后执行kubectl set image触发滚动更新到v3版本(RS: frontend-776431694), 当v3 RS的desired个数scale up到9个,ready个数为4个时,用户又执行kubectl set image触发滚动更新到v4版本(RS: frontend-3099797709)。

  • v2到v3的滚动流程同上一小节的描述;
  • 当新的滚动流程触发后,最老的v2的RS保持不动,不会继续scale down。
  • 然后v4将通过滚动更新的方式把已经scale up的9个v3 RS的pods替换掉,将所有v3的Pods升级到v4。
  • 最后再接着v4 RS滚动更新把v2的RS所有的旧Pods都升级到v4。
  • 整个完整的滚动流程中,都必须遵守maxSurge和maxUnavailable的约束,不能越雷池半步。

设想一个更复杂的场景:如果在上述v4滚动更新替换到半吊子的v3 RS过程中,用户又触发了一个滚动更新到v5版本,流程会怎么样呢? 不要怕,原理是一样的,Deployment rolling update总是先把最新的RS滚动更新替换掉,然后逐步把旧的RS滚动更新替换掉,直到最最老的那个RS scale down为0,流程就结束了,可以简要概括如下:

  • 剩余的v2, v3停止scale down;
  • v5把v4通过滚动更新的方式替换掉;
  • v5再把剩余v3通过滚动更新的方式替换掉;
  • v5再把剩余v2通过滚动更新的方式替换掉;

最后的RS会按照RS从新到旧排序的方式,逐步把旧的RS Pods scale down to 0, 自己 scale up to desired pods number。

理解rollout pause和resume

或许很多人至今还会这么觉得:整个滚动更新的过程中,一旦用户执行了kubectl rollout pause deploy/frontend后,正在执行的滚动流程就会立刻停止,然后用户执行kubectl rollout resume deploy/frontend就会继续未完成的滚动更新。那你就大错特错了!

kubectl rollout pause只会用来停止触发下一次rollout。什么意思呢? 上面描述的这个场景,正在执行的滚动历程是不会停下来的,而是会继续正常的进行滚动,直到完成。等下一次,用户再次触发rollout时,Deployment就不会真的去启动执行滚动更新了,而是等待用户执行了kubectl rollout resume,流程才会真正启动执行。

ReplicaSet和rollout history的关系

前提,你要知道关于--record
Setting the kubectl flag --record to true allows you to record current command in the annotations of the resources being created or updated.

默认情况下,所有通过kubectl xxxx --record都会被kubernetes记录到etcd进行持久化,这无疑会占用资源,最重要的是,时间久了,当你kubectl get rs时,会有成百上千的垃圾RS返回给你,那时你可能就眼花缭乱了。

上生产时,我们最好通过设置Deployment的.spec.revisionHistoryLimit来限制最大保留的revision number,比如15个版本,回滚的时候一般只会回滚到最近的几个版本就足够了。

执行下面的命令,可以返回某个Deployment的所有record记录:

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION    CHANGE-CAUSE
1           kubectl create -f docs/user-guide/nginx-deployment.yaml --record
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

然后执行rollout undo命令就可以回滚到to-revision指定的版本。

kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

其实rollout history中记录的revision都和ReplicaSets一一对应。如果手动delete某个ReplicaSet,对应的rollout history就会被删除,也就是还说你无法回滚到这个revison了。

roolout history和ReplicaSet的对应关系,可以在kubectl describe rs $RSNAME返回的revision字段中得到,这里的revision就对应着roolout history返回的revison。

总结

本博文介绍了关于Deployment rolling update那些容易被大家忽略或者误解的特性,如果看完这篇博文,你觉得“我去! 本来就是这样子的啊!”,那说明你对Deployment Controller非常熟悉。

  • 介绍了Deployment时与rolling update的相关项;
  • 说明了滚动更新的流程;
  • 介绍了对同一个Deployment先后触发滚动更新,逻辑如何?
  • 正确理解rollout pause和resume
  • 明白ReplicaSet和rollout history的内在关系

© 著作权归作者所有

共有 人打赏支持
WaltonWang
粉丝 159
博文 88
码字总数 182269
作品 0
深圳
程序员
更新APP-执行滚动更新

目标: 使用kubectl做一次滚动更新 更新一个应用 用户期望应用一直是可用的,而开发者期望一天部署多次新版本。 在k8s里,这是通过滚动更新来实现的。 Rolling updates允许增量更新新的Pods实...

趁你还年轻233 ⋅ 03/12 ⋅ 0

Kubernetes核心概念总结

1、基础架构 1.1 Master   Master节点上面主要由四个模块组成:APIServer、scheduler、controller manager、etcd。     APIServer。APIServer负责对外提供RESTful的Kubernetes API服务...

zwqjoy ⋅ 2017/12/13 ⋅ 0

Kubernetes核心概念总结(转载)

转载一篇不错的文章:https://www.cnblogs.com/WayneZeng/p/7680597.html 1、基础架构 1.1 Master   Master节点上面主要由四个模块组成:APIServer、scheduler、controller manager、etcd。...

yushanjin0767 ⋅ 05/29 ⋅ 0

Kubernetes 核心概念简介

Kubernets 中的Node, Pod,Replication Controller, Service 等都可以看作一种资源对象,这些资源几乎都可以通过使用Kubernetes提供的kubectl 工具执行增删改查,并将其保存在etcd中持久化储...

酥心糖 ⋅ 05/22 ⋅ 0

Kubernetes核心概念之Replication Controller详解

Replication Controller简称RC,它能够保证Pod持续运行,并且在任何时候都有指定数量的Pod副本,在此基础上提供一些高级特性,比如滚动升级和弹性伸缩 它在k8s中的架构如图: RC会在每个节点...

奋斗的寒霜 ⋅ 2017/12/08 ⋅ 0

将项目迁移到Kubernetes上的5个诀窍

我们将在本文中提供5个诀窍帮你将项目迁移到Kubernetes上,这些诀窍来源于过去12个月中OpenFaas社区的经验。下文的内容与Kubernetes 1.8兼容,并且已经应用于OpenFaaS - Serverless Functio...

Docker ⋅ 04/27 ⋅ 0

Kubernetes 编排系统

1.1 Kubernetes简介 1.1.1 什么是Kubernetes Kubernetes (通常称为K8s,K8s是将8个字母“ubernete”替换为“8”的缩写) 是用于自动部署、扩展和管理容器化(containerized)应用程序的开源系...

惨绿少年 ⋅ 03/09 ⋅ 0

伸缩APP-运行多个APP实例

原文地址:https://kubernetes.io/docs/tutorials/kubernetes-basics/scale-intro/ 目标: 使用kubectl扩展应用 在之前的单元里我们创建了一个Deployment,然后紧接着通过Service公开曝光了出...

趁你还年轻233 ⋅ 03/12 ⋅ 0

Dashboard - Kubernetes的全功能Web界面

编者按:这篇文章是关于Kubernetes 1.3新功能一系列深入文章的一部分,本文是第八篇。 Kubernetes Dashboard(仪表盘)是一个旨在将通用的基于Web的监控和操作界面加入 Kubernetes 的项目。 ...

时速云 ⋅ 2016/08/10 ⋅ 0

Travix是如何部署应用程序到Kubernetes上的

在Travix内部的100个开发好的应用,有差不多一半是运行在谷歌GCE上面。早在2015年5月,Kubernetes还是Alpha版本的时候,Travix就已经开始使用了,从那之后接受它并且将它作为新应用程序的默认...

Caicloud ⋅ 2016/07/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

三步为你的App集成LivePhoto功能

摘要:LivePhoto是iOS9新推出的一种拍照方式,类似于拍摄Gif图或录制视频片段生成图片。如果没有画面感,可以联想《哈利波特》霍格沃茨城堡的壁画,哈哈,很炫酷有木有,但坑爹的是只有iphone6S以...

壹峰 ⋅ 20分钟前 ⋅ 0

centos7 git安装

由于centos中的源仓库中git不是最新版本,需要进行源码安装。 1、查看yum仓库git信息 [root@iZm5e3d4r5i5ml889vh6esZ zh]# yum info gitLoaded plugins: fastestmirrorLoading mirror s...

xixingzhe ⋅ 29分钟前 ⋅ 0

input file 重复上传同一张图片失效的解决办法

解决办法 方法一:来回切换input[type='file']的type属性值,可以是‘text’,'button','button'....,然后再切换回来‘file’ 方法二:每次取消图片预览后,重置input[type='file']的value的...

时刻在奔跑 ⋅ 29分钟前 ⋅ 0

Mahout推荐算法API详解

前言 用Mahout来构建推荐系统,是一件既简单又困难的事情。简单是因为Mahout完整地封装了“协同过滤”算法,并实现了并行化,提供非常简单的API接口;困难是因为我们不了解算法细节,很难去根...

xiaomin0322 ⋅ 34分钟前 ⋅ 0

WampServer默认web服务器根目录位置

安装WampServer之后的web服务器根目录默认位置在WampServer安装目录下的www:

临江仙卜算子 ⋅ 35分钟前 ⋅ 0

Redux的一些手法记录

Redux Redux的基本概念见另一篇文。 这里记录一下Redux在项目中的实际操作的手法。 actions 首先定义action.js,actions的type,可以另起一个action-type.js文件。 action-type.js用来存...

LinearLaw ⋅ 36分钟前 ⋅ 0

android 手势检测(左右滑动、上下滑动)

GestureDetector类可以让我们快速的处理手势事件,如点击,滑动等。 使用GestureDetector分三步: 1. 定义GestureDetector类 2. 初始化手势类,同时设置手势监听 3. 将touch事件交给gesture...

王先森oO ⋅ 51分钟前 ⋅ 0

java 方法的执行时间监控 设置超时(Future 接口)

java 方法的执行时间监控 设置超时(Future 接口) import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor......

青峰Jun19er ⋅ 55分钟前 ⋅ 0

一名开源小白的Apache成长自述

今天收到了来自Apache Vote我成为Serviceomb项目Committer的邮件,代表自己的贡献得到了充分的肯定;除了感谢团队的给力支持,我更希望将自己的成长经历——如何践行Apache Way的心得介绍给大...

微服务框架 ⋅ 57分钟前 ⋅ 0

vim介绍、颜色显示和移动光标、一般模式下复制、剪切和粘贴

1.vim 是 vi 的升级版 vim 是带有颜色显示的 mini安装的系统,一般都不带有vim [root@aminglinux-128 ~]# yum install -y vim-enhanced已加载插件:fastestmirror, langpacksLoading mir...

oschina130111 ⋅ 58分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部