1.2kubernetes模型设计_kubernetes生产化实践之路

1.2.1、对象的通用设计原则

kubernetes在设计对象时遵循如下原则:

  • 1、kubernetes 将业务模型化,对象的操作都是以API的形式发布出来的,因此API 设计都是声明式
  • 2、控制器的行为应该是可重入和幂等的,通过幂等的控制器使得系统一致朝用户期望状态努力,且结果稳定。(可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。)
  • 3、所有对象应该是互补和可组合的,而不是简单的封装,通过组合关系构建的系统,通常能保持很好的高内聚,松耦合特性
  • 4、API操作负责度应该与对象数量成线性或者接近线性比例。如果是成指数比例,那随着对象的增加,复杂度会上升到用户无法接受的程度
  • 5、API对象状态不能依赖于网络连接状态,因为网络不稳定的情况很常见。
  • 6、避免让操作机制依赖于全局状态,在分布式系统中要保证全局状态的同步是非常困难的。

1.2.2、模型设计

1.2.2.1、TypeMeta

TypeMeta 是kubernetes 对象的最基本定义,它通过引入GKV(group、Kinx、Version)模型定义了一个对象的类型。

1、Group
将对象依据其功能归入不同的分组,比如把智齿最基本功能的对象归入到 core 组,把与应用部署有关的对象归入 apps 组。 会使得这些对象的可维护性和可理解性更高。

2、Kind
定义一个对象的基本类型,比如Node、Pod、Deployment

3、Version

随着对象的成熟,版本会从 v1alpha1 到 v1alpha2,或者到v1beta1,最终变成生产就绪版本v1 。

kubernetes 通过Version 属性来控制版本,当不同版本的对象定义发生变更时,有可能会涉及数据迁移,kubernetes API Server 允许通过Conversion 方法转换不同版本的对象属性。

这是一种自动数据迁移的机制,当集群版本升级以后,已经创建的老版本对象会被自动转换为新版本。

这里的版本是对外版本(External Version),即用户通过API 能够看到的版本。 事实上资源定义都有对内版本(Internal Version),在 Kubernetes API Server 先将对外版本转换成对内版本,再进行持久化。

1.2.2.2、Metadata

TypeMeta 定义了“我是什么”,Metadata定义了“我是谁”

Metadata 有两个重要属性 Namespace和Name,分别定义了对象的Namespace归属及名字,这两个属性唯一定义了某个对象实例。

Typemeta、Namespace、Name 唯一确定了该对象所在的API 访问路径,该路径也会被自动生成并保存在对象 Metadata 属性的 selfLink 中

在这里插入图片描述

Metadata 中还有 Label、Annotation、Finalizer、ResourceVersion 四个字段,可用作资源对象的配置管理。

1、Label

传统的面向对象设计中,对象组合的方法通常是内嵌或者引用。对象可能是一对多的关系,如果一个发生变化,系统需要遍历所有关联的对象并做修改。

kubernetes 采用松耦合的关系管理对象。依赖Label和Selector。
Label 就是给对象打标签,一个对象可以有任意对标签,存在形式是键值对。不需要独一无二,可以重复,一个对象也可以有多个标签。

Label 定义了这些对象的可识别属性,Kubernetes API 支持以Label 作为过滤条件查询对象。因此Label 通常用最简单的形式定义:

在这里插入图片描述

其他对象只需要定义 Label Selector 就可以按条件查询出需要关联的对象。
Label 的查询可以基于等式,如app=web或者app!=db,或基于集合 app in (web,db)。
可以只查询Label 键,如app。 对多个条件只支持与操作,如app=web,tier=front。

2、Annotation

Annotation 作为属性扩展,在开发新功能时保存一些信息。
也是键值来定义,功能同Label 不一样,API 不支持只用 Annotation 做条件过滤。

比如为POD 标记 Annotation 以告知Prometheus 为其抓取系统指标

在这里插入图片描述

3、Finalizer

只看社区实现没有存在感,实际落地过程中是个很重要的属性。
因为kubernetes 不是独立存在的系统,最终会跟企业资源和系统整合,意味着kubernetes会操作外部系统。

例如一个场景:
创建了一个kubernetes 对象,假设对应的控制器需要从外部系统获取资源,当用户删除该对象时,控制器接收删除事件后,会尝试释放该资源。可是此时外部系统无法连通,并且同时控制器发生了重启,会有何后果? 答案是该对象永远泄露了。

Finalizer 本质是一个资源锁。
kubernetes 在接收某对象的删除请求时,会检查Finalizer 是否为空,如果为空则只对其做逻辑删除,即只会更新对象中的metadata.deletionTimestamp 字段。
具有 Finalizer 的对象,不会立刻删除,需等到Finalizer 列表中所有字段被删除后,也就是只有该对象相关的所有外部资源已被删除,这个对象才会被最终删除。

因此如果控制器需要操作集群外部资源,则一定要在操作外部资源之前为对象添加 Finalizer,确保资源不会因对象被删除而泄露。
同时控制器需要监听对象的更新时间,当对象的 deletionTimestamp 不为空时,处理对象删除逻辑,回收外部资源,并情况自己之前添加的Finalizer。

4、ResourceVersion

多线程操作相同资源时,为保障数据一致性,需要在对对象访问的时候加锁,以确保同一时间只能有一个线程修改对象,这时其他线程只能等待锁,这样降低了系统的效率。

ResourceVersion 可以看作是一种乐观锁。
每个对象在任意时刻都有其ResourceVersion,当kubernetes对象被客户端读取以后,ResourceVersion 信息也一并读取。 客户端更改对象并回写API Server时,ResourceVersion 会增加,同时API Server 需要确保回写的版本比服务端的当前版本高,在回写成功后服务端的版本会更新为新的ResourceVersion。

在kubernetes中,当同时修改对象时,在回写时会判断ResourceVersion 是否高于当前版本,如果不高于,则回写失败,需要读取新的版本信息。

此机制确保了分布式系统中的任意多线程能够无锁并发访问对象,极大地提高了系统的整理效率。

1.2.2.3 Spec 和 Status

spec和status 才是对象的核心。

spec 是用户端定义的期望的对象状态
status 是对象的实际状态,由控制器收集实际状态并更新。

所以kubectl get 出来的deployment,比手写的yaml多了status 那一段的信息。
对照文末的yaml信息阅读。

与TypeMeta 和 Metadata 等通用属性不同,spec和status 是每个对象独有的。

鼓励API 对象尽量面向对象设计时的要求,即高内聚,松耦合,提高分解出来的业务对象的可重用性。

高层API 对象设计一定是从业务触发的,低层API 对象能够被高层API 对象所使用,减少冗余,提高重用性。

在这里插入图片描述

1.2.3、核心对象概览

kubernetes中不同的资源对象,都有独立的API对象来定义它们。
这样便于维护。

在这里插入图片描述

1、Namespace

不同对象被划分到不同的Namespace后,可以通过权限来限制用户以何种权限访问哪些Namespace的哪些对象,进而构建一个多租户、彼此隔离的通用集群。

2、Pod

Pod 是kubernetes 应用程序的基本执行单元,即它是kubernetes 对象模型中创建和部署的最小和最简单的单元。

POD 是一个或者多个容器镜像的组合,同一个pod中的所有容器中的进程默认公用同一个网络Namespace,并且共用同一网络标识。

应用运行在Pod中,还需要的配置文件,需要明文读写或者权限控制加密等。

configmap和secret 没有本质区别,与persistVolumeClaim 类似,都可以作为卷加载给运行的Pod,Pod中的进程可以像访问本地文件一样访问它们。

secret 只是将内容进行base64 编码(对称加密算法),可以轻松解密。

3、ServiceAccount

pod 中运行的进程有时需要与 kubernetes api 通信,在启用了安全配置的集群里,pod 一定要以某种身份与 kubernetes 通信,这个身份就是 系统账户(serviceAccount)。

kubernetes 会默认为每个Namespace 创建一个 default ServiceAccount ,并且为每个ServiceAccount 生成一个 JWT Token ,这个Token 保存在Secret 中,用户可以在其Pod 定义中 指定 ServiceAccount (默认为default),其 对应的Token 会被挂载在pod中,pod中的进程可以通过该token 与 kubernetes 进行通信。

4、ReplicaSet
pod 只是单个应用实例的抽象,要构建高可用应用,同一个服务需要多个副本。
kubernetes 为此抽象出副本集 ReplicaSet ,其允许用户定义POD的副本数,每个pod都会当作一个无状态的成员进行管理,kubernetes 保证总是有用户期望的数量pod正常运行。 当某个副本宕机以后,控制器将会创建一个新的副本,也可以方便扩容和缩容副本数量。

5、Deployment

Deployment 是一个用来描述发布过程的对象。
当发布新版本时,Deployment 会同时操作两个版本的ReplicaSet,其内置多种滚动升级策略,按照既定策略降低老版本的pod数量,同时创建新版本的pod,总是保证正在运行的pod总数与用户期望的副本数一致。(销毁的数量不会大于新生成的数量)
并依次将该Deployment 中的所有副本都更新至新版本

在这里插入图片描述

由于Deployment 会维护 ReplicaSet,ReplicaSet 会创建pod,所以使用Deployment 维护无状态的应用是第一选择。
Deployment 比pod的好处:

  • 维护一定数量的pod运行,有pod 失败时会再拉起。
  • 按照既定策略滚动升级,是自己暂停,恢复和回滚。
  • 扩容和缩容很方便

6、Service 和 Ingress

service 和 Ingress 是描述负载均衡配置的对象。
允许用户定义服务的协议和端口,定义Selector 选择后端服务的pod。
Selector 本身是一个Label 过滤器,它会选择所有Label 与该Selector 匹配的pod 作为目标。

kubernetes 为service 和选择出来的pod 创建一个关联对象,endpoint 里面记录了所有pod的ip地址和就绪状态,这些信息会被相应组件作为期望状态进行负载均衡配置。

Ingress 在服务的基础上定义API 网关的对象,通过Ingress 用户可以定义七层转发规则、网关证书等高级路由功能。

7、PersistentVolume和PersistentVolumeClaim

PersistentVolume(PV) 是集群中的一块存储卷,可以手动创建
或者 用户创建 PersistentVolumeClaim (PVC)时根据StorageClass 动态设置。

PV PVC 与POD 生命周期无关,pod的变动不会影响pvc中的数据。

不同场景需要不同属性的pvc,比如性能、访问模式,类型由StorageClass 区分(具体的pvc是使用本地磁盘还是nfs、还是别的分布式存储)。集群有默认的StorageClass。

8、CustomResourceDefinition

CustomResourceDefinition :自定义资源定义,即 CRD。允许用户将自己定义的对象添加到 kubernetes 集群中。

创建新的CRD定义时,API Server将为指定的每个版本创建一个新的 RESTFul 资源路径;
当成功创建了CRD时,就可以像原生资源一样使用它,利用k8s 的所有功能,api、rbac等。

CRD的定义是集群范围的。
资源对应的作用域,可以是Namespace 或者 集群。

删除 Namespace 也会删除所有的对象,但是不会删除CRD的定义。

k8s提供了codegen工具(deepcopy-gen、client-gen、lister-gen、informer-gen),能够自动生成该CRD 资源的golang版本的 Clientset、Lister、Informer。

CRD 就像是数据库的开放式表结构,这样可以满足更多种不同的业务需求。
Istio、Knative 就是基于CRD 构建的。

1.2.4、控制器模式

控制器模式,就是声明式系统的核心,通过这种机制确保实际状态与期望状态最终保持一致。

k8s 中定义了一系列的控制器,几乎所有的k8s中的对象都被一个或者多个控制器监听,当对象发生变化时,控制器会捕捉变化并完成配置操作。

api server 是 k8s的大脑,保存了所有对象及其状态。

开源的client-go 对控制器的编写提供了完备的自动化支持,任何k8s对象 都可以由 client-go 创建供控制器使用的 Informer() 和 Lister() 接口。 控制器的工作流程就是围绕着 这两个接口的。

在这里插入图片描述

  • Informer():接收资源对象变化的event,针对add、update、delete事件,注册相应的 eventhandler。 在 eventhandler 内根据传入的object 调用 controller.keyfunc 计算出字符串 key,并把它加入控制器的队列中。

  • lister():给控制器提供主动查询资源对象的接口,根据lables.selector 来指定筛选条件

控制模式:生产-消费者模式

  • 生产者:控制器启动后,informer()会监听其所关注的对象变化,一旦对象发生了创建、更新、删除等事件,这些事件会由核心组件api server 推送给控制器。 控制器会将对象(期望的)保存在本地缓存中,并将对象的主键推送至消息队列,此为生产者

  • 消费者:控制器会启动多个工作子线程(worker),从队列中依次获取对象主键,并从缓存中读取完整状态,按照期望状态完成配置更改,并将最终状态回写至api server,此为消费者

k8s就是基于此模式保证了整个系统的最终一致性。k8s 运行一组控制器,以使资源当前的状态与所需状态保持匹配。

对于基于事件的体系结构,控制器利用事件去触发相应的自定义代码,这部分都是由 sharedInformer 完成的。

例如 创建Deployment 控制器的核心代码如下:
在这里插入图片描述

具体的:如下图,sharedInformer 有 Reflector 、Informer、Indexer、Thread safe store 四个组件

在这里插入图片描述

  • Reflector: 用于监听特定的k8s api 资源对象,可以是内部的或者自定义的资源。 具体实现是通过 listandwatch 的方法进行的。 首先 reflector 将资源版本号设置为0,使用 list 操作获得指定资源对象,可能会导致本地的缓存相对于etcd里面的内容存在延迟。然后 reflector 通过watch操作监听大 api server 处资源对象的版本号变化,并将最新的数据放入 delta FIFO 队列中,使得本地的缓存数据与etcd的数据保持一致。如果resyncPeriod 不为零,那么reflector 会以resyncPeriod 为周期定期执行 delta FIFO 的Resync 函数,这样可以使Informer 定义处理所有的对象。

  • Informer:内部机制是从Delta FIFO 队列中弹出对象,将对象存入本地存储以供检索,另一方面触发时间以调用资源事件回调函数,控制器后续的典型模式是获取资源对象的key,并将该key 排入工作队列以进一步处理。Indexer 提供对象的索引功能。

  • Indexer 根据多个索引函数维护索引。Indexer使用线程安全的数据存储来存储对象及其键。在store 中定义了一个名为MetaNamespaceKeyFunc的默认函数,该函数生成对象的键的格式是 / 的组合。

1.2.5、控制器的协同工作原理

单个k8s资源对象的变更,会触发多个控制器对该资源对象的变更进行响应,继而还能引发其相关的其他对象发生变更,从而触发其他对象控制器的配置逻辑。 这一模式使得整个系统成为声明式系统。

在这里插入图片描述

除了 api server和etcd外,所有的组件,scheduler、controller manager、kubelet本质都是一致的,都可以被称为调度器。

这些组件中都有一个控制循环,它们监听 api server 中的对象变更,在自己关注的对象发生变更后完成既定的控制逻辑,再将控制逻辑执行完成后的结果更新回api server,并持久化到etcd中。

api server 作为集群的api 网关,接收所有来自用户的请求。

1、 用户创建deployment之后,该请求被发送至api server,经过认证,鉴权和准入三个环境,该deployment 对象被保存到etcd中。

2、controller manager 中的deployment controller 监听api server 中所有deployment的变更事件,此时其捕获了deployment 的创建事件,并开始执行控制逻辑。
deployment controller 读取deployment 对象的Selector 定义,通过该属性过滤当前Namespace 中的所有ReplicaSet 对象,并判断是否有 ReplicaSet 对象的OwnerReference 属性为此Deployment。
由于此deployment 刚刚创建,没有满足此查询条件的ReplicaSet。 于是Deployment Controller 会读取Deployment 中定义的podTemplate,将其做哈希计算,得到值为 [pod-template-hash] ,并依据如下约定创建新的ReplicaSet。

  • 新的ReplicaSet 的命名格式为 [deployment-name]-[pod-template-hash]
  • 为ReplicaSet 添加label,此label为pod-template-hash:[pod-template-hash]
  • 将deployment的值赋给 ReplicaSet 的 OwnerReference

Deployment Controller 将新的ReplicaSet 创建请求发送至api server,api server 经过认证授权和准入步骤,将该对象保存至etcd。

ReplicaSet Controller 监听api server中所有ReplicaSet 对象的变更,新对象的创建令其唤醒,并开始执行控制逻辑。
ReplicaSet Controller 读取ReplicaSet 对象的Selector 定义,并通过该属性过滤当前Namespace中的所有的pod,并判断是否pod的OwnerReference 为该ReplicaSet。
由于此ReplicaSet 刚刚创建,所以没有满足此查询条件的pod,于是ReplicaSet 会按照如下约定创建pod:

  • 读取ReplicaSet 定义,Replicas 的数量代表需要创建的pod的数量
  • 以ReplicaSet名作为 pod 的GenerateName ,该属性会被当作pod名单 前缀,k8s在此基础上加上一个随机字符串作为pod名。
  • 该ReplicaSet 可以作为pod的OwnerReference使用

ReplicaSet Controller将新建pod的请求发送给api server,api server将pod对象的信息保存到etcd中。
此时调度器被唤醒,其监听 api server 中所有nodeName 为空的pod,即未经过调度的pod。

经过一系列的调度算法,不满足pod需求的节点被过滤。
满足pod需求的节点按照空闲资源,端口占用情况,实际资源利用率等信息被排序,评分最高的节点名被更新到 nodename属性中有,该属性经api server 保存至etcd。

当被选中的node节点上的kubelet 监听到有归属自己节点的新pod时,就开始加载pod清单,下载pod所需的配置信息。
调用容器运行时接口启动容器,调用容器网络接口加载网络,调用容器存储接口挂载存储,并完成pod的启动。

k8s 就是依靠这种联动机制,通过分散的业务控制逻辑满足用户的需求。

用户只是发送了一个创建deployment的请求,k8s 里涉及了多个组件。
优势:各个组件各司其职,巧妙灵活,代码易于维护,解耦
缺点:运维复杂度高,业务流中任何组件故障都会使得k8s不可用。

不能简单的抄写文字。没有意义。

一个运行中的deployment的yaml 如下

[root@jyzx-tower1 ~]# kubectl get deployments ummp-activity-deployment -n cmsc -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "945"
    field.cattle.io/publicEndpoints: '[{"addresses":["10.71.164.29"],"port":31597,"protocol":"TCP","serviceName":"cmsc:ummp-activity-service","allNodes":true},{"addresses":["10.71.164.29"],"port":31208,"protocol":"TCP","serviceName":"cmsc:ummp-activity-service","allNodes":true},{"addresses":["10.71.164.29"],"port":31628,"protocol":"TCP","serviceName":"cmsc:java-debug-ummp-activity-service","allNodes":true}]'
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"cmsc":"ummp-activity-deployment"},"name":"ummp-activity-deployment","namespace":"cmsc"},"spec":{"replicas":1,"selector":{"matchLabels":{"cmsc":"ummp-activity-deployment"}},"strategy":{"type":"Recreate"},"template":{"metadata":{"labels":{"cmsc":"ummp-activity-deployment"}},"spec":{"containers":[{"env":[{"name":"JAVA_OPTS","value":"-server -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n -Dproject.name=ummp-activity -Dcsp.sentinel.config.file=classpath:sentinel-dev.properties"},{"name":"APP_PROPS","value":"--spring.profiles.active=dev"},{"name":"UPDATE-UUID","value":"38102"}],"image":"10.71.164.28:5000/com-cmcc-coc-ummp-activity-parent:1.0.66-SNAPSHOT","imagePullPolicy":"Always","name":"ummp-activity-deployment","ports":[{"containerPort":8080,"protocol":"TCP"}],"volumeMounts":[{"mountPath":"/root/ummp-activity","name":"nfs-logs"}]}],"volumes":[{"name":"nfs-logs","nfs":{"path":"/var/nfs/k8s_storage/ummp-activity","server":"10.71.164.28"}}]}}}}
  creationTimestamp: "2019-10-18T02:39:44Z"
  generation: 958
  labels:
    cmsc: ummp-activity-deployment
  name: ummp-activity-deployment
  namespace: cmsc
  resourceVersion: "159989560"
  selfLink: /apis/extensions/v1beta1/namespaces/cmsc/deployments/ummp-activity-deployment
  uid: 8b49322d-f150-11e9-ae22-c8d9d2254422
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      cmsc: ummp-activity-deployment
  strategy:
    type: Recreate
  template:
    metadata:
      creationTimestamp: null
      labels:
        cmsc: ummp-activity-deployment
    spec:
      containers:
      - env:
        - name: JAVA_OPTS
          value: -server -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n
            -Dproject.name=ummp-activity -Dcsp.sentinel.config.file=classpath:sentinel-dev.properties
        - name: APP_PROPS
          value: --spring.profiles.active=dev
        - name: UPDATE-UUID
          value: "38102"
        image: 10.71.164.28:5000/com-cmcc-coc-ummp-activity-parent:1.0.66-SNAPSHOT
        imagePullPolicy: Always
        name: ummp-activity-deployment
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /root/ummp-activity
          name: nfs-logs
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: nfs-logs
        nfs:
          path: /var/nfs/k8s_storage/ummp-activity
          server: 10.71.164.28
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: "2019-10-18T02:50:04Z"
    lastUpdateTime: "2021-10-22T06:36:26Z"
    message: ReplicaSet "ummp-activity-deployment-767547f9d5" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  - lastTransitionTime: "2021-10-25T10:52:56Z"
    lastUpdateTime: "2021-10-25T10:52:56Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 958
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1
[root@jyzx-tower1 ~]# 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DevOps 五大理念及其落地实践 研发运维一体(DevOps)成熟度模型 中国DevOps现状调查报告及解读 构建企业DevOps的度量体系 DevOps实践指南精要 分布式敏捷和DevOps实践案例 AWS DevOps 助力爱乐奇大规模业务扩展 AWS 云上的 DevOps 实践简介 多云环境下的 DevOps 实践 DevOps中如何系统开展微服务性能测试 “神兵”天降 - 揭秘平安 DevOps 的核心实践 大型Scrum实践银行产品敏捷转型与DevOps实践经验分享 如何基于 Jenkins 支撑腾讯上千产品的CICD SecDevOps工具链 券商DevOps转型—平安证券容器实践之路 招行如何基于 K8S 容器技术打造 DevOps 流水线 民生银行的DevOps实践之旅 以自动先行的 DevOps 落地实践经验 东方明珠集团基于 AWS 的 DevOps 实战分享 中小银行的DevOps 实践之路 让DevOps生产线加速的敏捷之道 云原生时代的 DevOps 新实践 新场景高效能快交付腾讯敏捷研发平台 DevOps 解决方案 中小金融企业如何开心玩DevOps DevOps 变革的剖析与实践 猎豹移动基于 AWS 构建 DevOps 实践分享 DevOps在联通IT系统的落地实施 DevOpsMadeByGoogle 流水线3.0打造DevOps落地工具链 混合云下的DevOps在vivo互联网的探索落地 大型企业实施 DevOps 的三个阶段 DevOps最佳实践之海量资源技术运营 诺基亚 DevOps 演进-大数据推动流程优与高效执行 苏宁 AIOps 实践之路 金融云业务网络 智能采集与一体分析实战 如何构建新一代智能运维平台 CMDB - 企业一体运维平台的基石 用友方法+之-YSDP 研发交付平台实践之路 顺丰云计算和运维自动团队从0到1的DevOps之旅 诺基亚的转身:数字时代的 DevOps 转型之路 大型主机核心银行系统的 DevOps 践行之路 DevOps标准认证评估权威指南及案例解读. 浙江移动的DevOps实践 携程持续交付与构建系统实践 每天万次触发的持续交付工具链实践 Android 超大型代码的快速集成之路 基于猪齿鱼构建企业研发体系 大型制造业实践DevOps团队之路
Kubernetes指南-倪朋飞.pptx 1-唐继元Kubernetes Master High Availability 高级实践.pdf 2、刘淼-基于 DevOps、微服务及k8s的高可用架构探索与实现.pdf ArchSummit北京2016-《网易蜂巢基于万节点Kubernets支撑大规模云应用实践》-刘超.pdf Azure Service Broker_cn - Rita Zhang.pdf google/ HPE李志霄 Kubernetes企业级容器云:加速数字创新-20170407.pdf IBM马达:Kubernetes 中基于策略的资源分配.pdf k8s资料.rar Kubernetes Cookbook-Packt Publishing(2016).pdf Kubernetes Microservices with Docker-Apress2016.pdf Kubernetes on Azure - Gabe Monroy.pdf Kubernetes1.6集群部署完全指南——二进制文件部署开启TLS基于CentOS7.pdf Kubernetes1-4版本新增加功能介绍.pdf Kubernetes监控与日志.pdf kubernetes容器云平台实践-李志伟v1.0.pdf Kubernetes生态系统现状报告.pdf Kubernetes下API网关的微服务实践 长虹集团-李玮演讲PPT.pdf Kubernetes与EcOS的碰撞结合 成都精灵云-张行才演讲PPT.pdf Kubernetes与OpenStack融合支撑企业级微服务架构.pdf Kubernetes在华为全球IT系统中的实践.pdf Kubernetes在企业中的场景运用及管理实践.pdf Kubernetes指南-倪朋飞.pdf Kubernetes指南-倪朋飞.pptx l.txt Lessons+learned+and+challenges+faced+while+running+Kubernetes+at+scale.pdf rkt与Kubernetes的深度融合.pdf rkt与Kubernetes的深度融合.pptx SACC2017FabricOnKubernetesChinese.pdf ThoughtWorks林帆-白话Kubernetes网络.pdf 百度云PaddlePaddle on kubernetes-周倜.pdf 从Borg到Kubernetes-PaaS产品设计-华为-钟成.pdf 改造Kuberntetes打造SAE容器云.pdf 跟谁学-基于容器的持续集成平台建设.pdf 谷歌深度学习在Kubernetes上的实践.pptx 惠普基于Kubernetes的容器私有云平台实践.pdf 基于Kubernetes的模板应用编排.pdf 基于kubernetes的容器云平台设计实践-邓德源.pdf 基于Kubernetes的私有容器云建设实践-易宝支付.pdf 基于Kubernetes构建AI业务生态.pdf 李波:小米生态云应用引擎实践.pdf 魅族容器云平台基于 k8s 的自动运维实践-曾彬.pdf 欧昌华-基于 Nginx 的负载均衡器在 K8S 中的实践.pdf 彭超:瓜子云的落地.pdf 如何落地TensorFlow on Kubernetes.pdf 如何用OpenStack和Kubernetes快速搭建一个容器和虚拟机组合服务的云平台.pptx 孙杰:大型企业云平台架构演进的实践之路.pdf 微服务道与术-敖小剑.pdf 微软Azure云助力微服务-赵文婧.pdf 颜卫-腾讯云容器服务基于kubernetes的应用编排实践-final-v1.0.pptx 有容云邓绍军-Kubernetes落地实践.pptx 折800如何用Docker&Kubernetes;构建自动测环境.pdf

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值