2017-08-21 17:44:43 +08:00
<!DOCTYPE HTML>
< html lang = "zh-cn" >
< head >
< meta charset = "UTF-8" >
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< title > 2.2.6 Deployment · Kubernetes Handbook< / title >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" / >
< meta name = "description" content = "" >
< meta name = "generator" content = "GitBook 3.2.2" >
< meta name = "author" content = "Jimmy Song" >
< link rel = "stylesheet" href = "../gitbook/style.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-splitter/splitter.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-page-toc-button/plugin.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-image-captions/image-captions.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-page-footer-ex/style/plugin.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-search-plus/search.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-highlight/website.css" >
< link rel = "stylesheet" href = "../gitbook/gitbook-plugin-fontsettings/website.css" >
< meta name = "HandheldFriendly" content = "true" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1, user-scalable=no" >
< meta name = "apple-mobile-web-app-capable" content = "yes" >
< meta name = "apple-mobile-web-app-status-bar-style" content = "black" >
< link rel = "apple-touch-icon-precomposed" sizes = "152x152" href = "../gitbook/images/apple-touch-icon-precomposed-152.png" >
< link rel = "shortcut icon" href = "../gitbook/images/favicon.ico" type = "image/x-icon" >
< link rel = "next" href = "secret.html" / >
< link rel = "prev" href = "volume.html" / >
< / head >
< body >
< div class = "book" >
< div class = "book-summary" >
< div id = "book-search-input" role = "search" >
< input type = "text" placeholder = "輸入並搜尋" / >
< / div >
< nav role = "navigation" >
< ul class = "summary" >
< li class = "chapter " data-level = "1.1" data-path = "../" >
< a href = "../" >
1. 前言
< / a >
< / li >
< li class = "chapter " data-level = "1.2" data-path = "./" >
< a href = "./" >
2. 概念原理
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.2.1" data-path = "concepts.html" >
< a href = "concepts.html" >
2.1 设计理念
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2" data-path = "objects.html" >
< a href = "objects.html" >
2.2 主要概念
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.2.2.1" data-path = "pod-overview.html" >
< a href = "pod-overview.html" >
2.2.1 Pod
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.2.2.1.1" data-path = "pod.html" >
< a href = "pod.html" >
2.2.1.1 Pod解析
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.2.2.2" data-path = "node.html" >
< a href = "node.html" >
2.2.2 Node
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.3" data-path = "namespace.html" >
< a href = "namespace.html" >
2.2.3 Namespace
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.4" data-path = "service.html" >
< a href = "service.html" >
2.2.4 Service
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.5" data-path = "volume.html" >
< a href = "volume.html" >
2.2.5 Volume和Persistent Volume
< / a >
< / li >
< li class = "chapter active" data-level = "1.2.2.6" data-path = "deployment.html" >
< a href = "deployment.html" >
2.2.6 Deployment
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.7" data-path = "secret.html" >
< a href = "secret.html" >
2.2.7 Secret
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.8" data-path = "statefulset.html" >
< a href = "statefulset.html" >
2.2.8 StatefulSet
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.9" data-path = "daemonset.html" >
< a href = "daemonset.html" >
2.2.9 DaemonSet
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.10" data-path = "serviceaccount.html" >
< a href = "serviceaccount.html" >
2.2.10 ServiceAccount
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.11" data-path = "replicaset.html" >
< a href = "replicaset.html" >
2.2.11 ReplicationController和ReplicaSet
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.12" data-path = "job.html" >
< a href = "job.html" >
2.2.12 Job
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.13" data-path = "cronjob.html" >
< a href = "cronjob.html" >
2.2.13 CronJob
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.14" data-path = "ingress.html" >
< a href = "ingress.html" >
2.2.14 Ingress
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.15" data-path = "configmap.html" >
< a href = "configmap.html" >
2.2.15 ConfigMap
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.16" data-path = "horizontal-pod-autoscaling.html" >
< a href = "horizontal-pod-autoscaling.html" >
2.2.16 Horizontal Pod Autoscaling
< / a >
< / li >
< li class = "chapter " data-level = "1.2.2.17" data-path = "label.html" >
< a href = "label.html" >
2.2.17 Label
< / a >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3" data-path = "../guide/" >
< a href = "../guide/" >
3. 用户指南
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.1" data-path = "../guide/resource-configuration.html" >
< a href = "../guide/resource-configuration.html" >
3.1 资源配置
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.1.1" data-path = "../guide/configure-liveness-readiness-probes.html" >
< a href = "../guide/configure-liveness-readiness-probes.html" >
3.1.1 配置Pod的liveness和readiness探针
< / a >
< / li >
< li class = "chapter " data-level = "1.3.1.2" data-path = "../guide/configure-pod-service-account.html" >
< a href = "../guide/configure-pod-service-account.html" >
3.1.2 配置Pod的Service Account
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3.2" data-path = "../guide/command-usage.html" >
< a href = "../guide/command-usage.html" >
3.2 命令使用
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.2.1" data-path = "../guide/using-kubectl.html" >
< a href = "../guide/using-kubectl.html" >
3.2.1 使用kubectl
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3.3" data-path = "../guide/cluster-management.html" >
< a href = "../guide/cluster-management.html" >
3.3 集群管理
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.3.1" data-path = "../guide/managing-tls-in-a-cluster.html" >
< a href = "../guide/managing-tls-in-a-cluster.html" >
3.3.1 管理集群中的TLS
< / a >
2017-08-21 18:44:34 +08:00
< / li >
< li class = "chapter " data-level = "1.3.3.2" data-path = "../guide/kubelet-authentication-authorization.html" >
< a href = "../guide/kubelet-authentication-authorization.html" >
3.3.2 kubelet的认证授权
< / a >
< / li >
< li class = "chapter " data-level = "1.3.3.3" data-path = "../guide/tls-bootstrapping.html" >
< a href = "../guide/tls-bootstrapping.html" >
3.3.3 TLS bootstrap
< / a >
2017-08-21 17:44:43 +08:00
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3.4" data-path = "../guide/access-kubernetes-cluster.html" >
< a href = "../guide/access-kubernetes-cluster.html" >
3.4 访问 Kubernetes 集群
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.4.1" data-path = "../guide/access-cluster.html" >
< a href = "../guide/access-cluster.html" >
3.4.1 访问集群
< / a >
< / li >
< li class = "chapter " data-level = "1.3.4.2" data-path = "../guide/authenticate-across-clusters-kubeconfig.html" >
< a href = "../guide/authenticate-across-clusters-kubeconfig.html" >
3.4.2 使用 kubeconfig 文件配置跨集群认证
< / a >
< / li >
< li class = "chapter " data-level = "1.3.4.3" data-path = "../guide/connecting-to-applications-port-forward.html" >
< a href = "../guide/connecting-to-applications-port-forward.html" >
3.4.3 通过端口转发访问集群中的应用程序
< / a >
< / li >
< li class = "chapter " data-level = "1.3.4.4" data-path = "../guide/service-access-application-cluster.html" >
< a href = "../guide/service-access-application-cluster.html" >
3.4.4 使用 service 访问群集中的应用程序
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.3.5" data-path = "../guide/application-development-deployment-flow.html" >
< a href = "../guide/application-development-deployment-flow.html" >
3.5 在kubernetes中开发部署应用
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.3.5.1" data-path = "../guide/deploy-applications-in-kubernetes.html" >
< a href = "../guide/deploy-applications-in-kubernetes.html" >
3.5.1 适用于kubernetes的应用开发部署流程
< / a >
2017-08-21 18:44:34 +08:00
< / li >
< li class = "chapter " data-level = "1.3.5.2" data-path = "../guide/migrating-hadoop-yarn-to-kubernetes.html" >
< a href = "../guide/migrating-hadoop-yarn-to-kubernetes.html" >
3.5.2 迁移传统应用到kubernetes中——以Hadoop YARN为例
< / a >
2017-08-21 17:44:43 +08:00
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.4" data-path = "../practice/" >
< a href = "../practice/" >
4. 最佳实践
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.1" data-path = "../practice/install-kbernetes1.6-on-centos.html" >
< a href = "../practice/install-kbernetes1.6-on-centos.html" >
4.1 在CentOS上部署kubernetes1.6集群
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.1.1" data-path = "../practice/create-tls-and-secret-key.html" >
< a href = "../practice/create-tls-and-secret-key.html" >
4.1.1 创建TLS证书和秘钥
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.2" data-path = "../practice/create-kubeconfig.html" >
< a href = "../practice/create-kubeconfig.html" >
4.1.2 创建kubeconfig文件
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.3" data-path = "../practice/etcd-cluster-installation.html" >
< a href = "../practice/etcd-cluster-installation.html" >
4.1.3 创建高可用etcd集群
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.4" data-path = "../practice/kubectl-installation.html" >
< a href = "../practice/kubectl-installation.html" >
4.1.4 安装kubectl命令行工具
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.5" data-path = "../practice/master-installation.html" >
< a href = "../practice/master-installation.html" >
4.1.5 部署master节点
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.6" data-path = "../practice/node-installation.html" >
< a href = "../practice/node-installation.html" >
4.1.6 部署node节点
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.7" data-path = "../practice/kubedns-addon-installation.html" >
< a href = "../practice/kubedns-addon-installation.html" >
4.1.7 安装kubedns插件
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.8" data-path = "../practice/dashboard-addon-installation.html" >
< a href = "../practice/dashboard-addon-installation.html" >
4.1.8 安装dashboard插件
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.9" data-path = "../practice/heapster-addon-installation.html" >
< a href = "../practice/heapster-addon-installation.html" >
4.1.9 安装heapster插件
< / a >
< / li >
< li class = "chapter " data-level = "1.4.1.10" data-path = "../practice/efk-addon-installation.html" >
< a href = "../practice/efk-addon-installation.html" >
4.1.10 安装EFK插件
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.4.2" data-path = "../practice/service-discovery-and-loadbalancing.html" >
< a href = "../practice/service-discovery-and-loadbalancing.html" >
4.2 服务发现与负载均衡
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.2.1" data-path = "../practice/traefik-ingress-installation.html" >
< a href = "../practice/traefik-ingress-installation.html" >
4.2.1 安装Traefik ingress
< / a >
< / li >
< li class = "chapter " data-level = "1.4.2.2" data-path = "../practice/distributed-load-test.html" >
< a href = "../practice/distributed-load-test.html" >
4.2.2 分布式负载测试
< / a >
< / li >
< li class = "chapter " data-level = "1.4.2.3" data-path = "../practice/network-and-cluster-perfermance-test.html" >
< a href = "../practice/network-and-cluster-perfermance-test.html" >
4.2.3 网络和集群性能测试
< / a >
< / li >
< li class = "chapter " data-level = "1.4.2.4" data-path = "../practice/edge-node-configuration.html" >
< a href = "../practice/edge-node-configuration.html" >
4.2.4 边缘节点配置
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.4.3" data-path = "../practice/operation.html" >
< a href = "../practice/operation.html" >
4.3 运维管理
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.3.1" data-path = "../practice/service-rolling-update.html" >
< a href = "../practice/service-rolling-update.html" >
4.3.1 服务滚动升级
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3.2" data-path = "../practice/app-log-collection.html" >
< a href = "../practice/app-log-collection.html" >
4.3.2 应用日志收集
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3.3" data-path = "../practice/configuration-best-practice.html" >
< a href = "../practice/configuration-best-practice.html" >
4.3.3 配置最佳实践
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3.4" data-path = "../practice/monitor.html" >
< a href = "../practice/monitor.html" >
4.3.4 集群及应用监控
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3.5" data-path = "../practice/jenkins-ci-cd.html" >
< a href = "../practice/jenkins-ci-cd.html" >
4.3.5 使用Jenkins进行持续构建与发布
< / a >
< / li >
< li class = "chapter " data-level = "1.4.3.6" data-path = "../practice/data-persistence-problem.html" >
< a href = "../practice/data-persistence-problem.html" >
4.3.6 数据持久化问题
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.4.4" data-path = "../practice/storage.html" >
< a href = "../practice/storage.html" >
4.4 存储管理
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.4.1" data-path = "../practice/glusterfs.html" >
< a href = "../practice/glusterfs.html" >
4.4.1 GlusterFS
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.4.4.1.1" data-path = "../practice/using-glusterfs-for-persistent-storage.html" >
< a href = "../practice/using-glusterfs-for-persistent-storage.html" >
4.4.1.1 使用GlusterFS做持久化存储
< / a >
< / li >
< li class = "chapter " data-level = "1.4.4.1.2" data-path = "../practice/storage-for-containers-using-glusterfs-with-openshift.html" >
< a href = "../practice/storage-for-containers-using-glusterfs-with-openshift.html" >
4.4.1.2 在OpenShift中使用GlusterFS做持久化存储
< / a >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.5" data-path = "../usecases/" >
< a href = "../usecases/" >
5. 领域应用
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.1" data-path = "../usecases/microservices.html" >
< a href = "../usecases/microservices.html" >
5.1 微服务架构
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.1.1" data-path = "../usecases/istio.html" >
< a href = "../usecases/istio.html" >
5.1.1 Istio
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.1.1.1" data-path = "../usecases/istio-installation.html" >
< a href = "../usecases/istio-installation.html" >
5.1.1.1 安装istio
< / a >
< / li >
< li class = "chapter " data-level = "1.5.1.1.2" data-path = "../usecases/configuring-request-routing.html" >
< a href = "../usecases/configuring-request-routing.html" >
5.1.1.2 配置请求的路由规则
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.5.1.2" data-path = "../usecases/linkerd.html" >
< a href = "../usecases/linkerd.html" >
5.1.2 Linkerd
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.1.2.1" data-path = "../usecases/linkerd-user-guide.html" >
< a href = "../usecases/linkerd-user-guide.html" >
5.1.2.1 Linkerd 使用指南
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.5.1.3" data-path = "../usecases/service-discovery-in-microservices.html" >
< a href = "../usecases/service-discovery-in-microservices.html" >
5.1.3 微服务中的服务发现
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.5.2" data-path = "../usecases/big-data.html" >
< a href = "../usecases/big-data.html" >
5.2 大数据
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.5.2.1" data-path = "../usecases/spark-on-kubernetes.html" >
< a href = "../usecases/spark-on-kubernetes.html" >
5.2.1 Spark on Kubernetes
< / a >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.6" data-path = "../develop/" >
< a href = "../develop/" >
6. 开发指南
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.6.1" data-path = "../develop/developing-environment.html" >
< a href = "../develop/developing-environment.html" >
6.1 开发环境搭建
< / a >
< / li >
< li class = "chapter " data-level = "1.6.2" data-path = "../develop/testing.html" >
< a href = "../develop/testing.html" >
6.2 单元测试和集成测试
< / a >
< / li >
< li class = "chapter " data-level = "1.6.3" data-path = "../develop/client-go-sample.html" >
< a href = "../develop/client-go-sample.html" >
6.3 client-go示例
< / a >
< / li >
< li class = "chapter " data-level = "1.6.4" data-path = "../develop/contribute.html" >
< a href = "../develop/contribute.html" >
6.4 社区贡献
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1.7" data-path = "../appendix/" >
< a href = "../appendix/" >
7. 附录
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.7.1" data-path = "../appendix/docker-best-practice.html" >
< a href = "../appendix/docker-best-practice.html" >
7.1 Docker最佳实践
< / a >
< / li >
< li class = "chapter " data-level = "1.7.2" data-path = "../appendix/issues.html" >
< a href = "../appendix/issues.html" >
7.2 问题记录
< / a >
< / li >
< li class = "chapter " data-level = "1.7.3" data-path = "../appendix/tricks.html" >
< a href = "../appendix/tricks.html" >
7.3 使用技巧
< / a >
< / li >
< / ul >
< / li >
< li class = "divider" > < / li >
< li >
< a href = "https://www.gitbook.com" target = "blank" class = "gitbook-link" >
本書使用 GitBook 釋出
< / a >
< / li >
< / ul >
< / nav >
< / div >
< div class = "book-body" >
< div class = "body-inner" >
< div class = "book-header" role = "navigation" >
<!-- Title -->
< h1 >
< i class = "fa fa-circle-o-notch fa-spin" > < / i >
< a href = ".." > 2.2.6 Deployment< / a >
< / h1 >
< / div >
< div class = "page-wrapper" tabindex = "-1" role = "main" >
< div class = "page-inner" >
< div class = "search-plus" id = "book-search-results" >
< div class = "search-noresults" >
< section class = "normal markdown-section" >
< h1 id = "deployment" > Deployment< / h1 >
< p > [TOC]< / p >
< h2 id = "简述" > 简 述 < / h2 >
< p > Deployment 为 Pod 和 ReplicaSet 提 供 了 一 个 声 明 式 定 义 (declarative)方 法 , 用 来 替 代 以 前 的 ReplicationController 来 方 便 的 管 理 应 用 。 典 型 的 应 用 场 景 包 括 : < / p >
< ul >
< li > 定 义 Deployment来 创 建 Pod和 ReplicaSet< / li >
< li > 滚 动 升 级 和 回 滚 应 用 < / li >
< li > 扩 容 和 缩 容 < / li >
< li > 暂 停 和 继 续 Deployment< / li >
< / ul >
< p > 比 如 一 个 简 单 的 nginx应 用 可 以 定 义 为 < / p >
< pre > < code class = "lang-yaml" > < span class = "hljs-attr" > apiVersion:< / span > extensions/v1beta1
< span class = "hljs-attr" > kind:< / span > Deployment
< span class = "hljs-attr" > metadata:< / span >
< span class = "hljs-attr" > name:< / span > nginx-deployment
< span class = "hljs-attr" > spec:< / span >
< span class = "hljs-attr" > replicas:< / span > < span class = "hljs-number" > 3< / span >
< span class = "hljs-attr" > template:< / span >
< span class = "hljs-attr" > metadata:< / span >
< span class = "hljs-attr" > labels:< / span >
< span class = "hljs-attr" > app:< / span > nginx
< span class = "hljs-attr" > spec:< / span >
< span class = "hljs-attr" > containers:< / span >
< span class = "hljs-attr" > - name:< / span > nginx
< span class = "hljs-attr" > image:< / span > nginx:< span class = "hljs-number" > 1.7< / span > < span class = "hljs-number" > .9< / span >
< span class = "hljs-attr" > ports:< / span >
< span class = "hljs-attr" > - containerPort:< / span > < span class = "hljs-number" > 80< / span >
< / code > < / pre >
< p > 扩 容 : < / p >
< pre > < code > kubectl scale deployment nginx-deployment --replicas 10
< / code > < / pre > < p > 如 果 集 群 支 持 horizontal pod autoscaling 的 话 , 还 可 以 为 Deployment设 置 自 动 扩 展 : < / p >
< pre > < code > kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
< / code > < / pre > < p > 更 新 镜 像 也 比 较 简 单 :< / p >
< pre > < code > kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
< / code > < / pre > < p > 回 滚 : < / p >
< pre > < code > kubectl rollout undo deployment/nginx-deployment
< / code > < / pre > < h2 id = "deployment-结构示意图" > Deployment 结 构 示 意 图 < / h2 >
< p > 参 考 : < a href = "https://kubernetes.io/docs/api-reference/v1.6/#deploymentspec-v1beta1-apps" target = "_blank" > https://kubernetes.io/docs/api-reference/v1.6/#deploymentspec-v1beta1-apps< / a > < / p >
< figure id = "fig1.2.2.6.1" > < img src = "../images/deployment-cheatsheet.png" alt = "kubernetes deployment cheatsheet" > < figcaption > Figure: kubernetes deployment cheatsheet< / figcaption > < / figure >
< h2 id = "deployment-概念详细解析" > Deployment 概 念 详 细 解 析 < / h2 >
< p > 本 文 翻 译 自 kubernetes官 方 文 档 : < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md" target = "_blank" > https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md< / a > < / p >
< p > 根 据 2017年 5月 10日 的 Commit 8481c02 翻 译 。 < / p >
< h2 id = "deployment-是什么?" > Deployment 是 什 么 ? < / h2 >
< p > Deployment为 Pod和 Replica Set( 下 一 代 Replication Controller) 提 供 声 明 式 更 新 。 < / p >
< p > 您 只 需 要 在 Deployment 中 描 述 您 想 要 的 目 标 状 态 是 什 么 , Deployment controller 就 会 帮 您 将 Pod 和 ReplicaSet 的 实 际 状 态 改 变 到 您 的 目 标 状 态 。 您 可 以 定 义 一 个 全 新 的 Deployment 来 创 建 ReplicaSet 或 者 删 除 已 有 的 Deployment 并 创 建 一 个 新 的 来 替 换 。 < / p >
< p > < strong > 注 意 < / strong > : 您 不 该 手 动 管 理 由 Deployment 创 建 的 ReplicaSet, 否 则 您 就 篡 越 了 Deployment controller 的 职 责 ! 下 文 罗 列 了 Deployment 对 象 中 已 经 覆 盖 了 所 有 的 用 例 。 如 果 未 有 覆 盖 您 所 有 需 要 的 用 例 , 请 直 接 在 Kubernetes 的 代 码 库 中 提 issue。 < / p >
< p > 典 型 的 用 例 如 下 : < / p >
< ul >
< li > 使 用 Deployment来 创 建 ReplicaSet。 ReplicaSet在 后 台 创 建 pod。 检 查 启 动 状 态 , 看 它 是 成 功 还 是 失 败 。 < / li >
< li > 然 后 , 通 过 更 新 Deployment的 PodTemplateSpec字 段 来 声 明 Pod的 新 状 态 。 这 会 创 建 一 个 新 的 ReplicaSet, Deployment会 按 照 控 制 的 速 率 将 pod从 旧 的 ReplicaSet移 动 到 新 的 ReplicaSet中 。 < / li >
< li > 如 果 当 前 状 态 不 稳 定 , 回 滚 到 之 前 的 Deployment revision。 每 次 回 滚 都 会 更 新 Deployment的 revision。 < / li >
< li > 扩 容 Deployment以 满 足 更 高 的 负 载 。 < / li >
< li > 暂 停 Deployment来 应 用 PodTemplateSpec的 多 个 修 复 , 然 后 恢 复 上 线 。 < / li >
< li > 根 据 Deployment 的 状 态 判 断 上 线 是 否 hang住 了 。 < / li >
< li > 清 除 旧 的 不 必 要 的 ReplicaSet。 < / li >
< / ul >
< h2 id = "创建-deployment" > 创 建 Deployment< / h2 >
< p > 下 面 是 一 个 Deployment 示 例 , 它 创 建 了 一 个 ReplicaSet 来 启 动 3个 nginx pod。 < / p >
< p > 下 载 示 例 文 件 并 执 行 命 令 : < / p >
< pre > < code class = "lang-shell" > $ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
deployment " nginx-deployment" created
< / code > < / pre >
< p > 将 kubectl的 < code > --record< / code > 的 flag 设 置 为 < code > true< / code > 可 以 在 annotation 中 记 录 当 前 命 令 创 建 或 者 升 级 了 该 资 源 。 这 在 未 来 会 很 有 用 , 例 如 , 查 看 在 每 个 Deployment revision 中 执 行 了 哪 些 命 令 。 < / p >
< p > 然 后 立 即 执 行 < code > get< / code > 将 获 得 如 下 结 果 : < / p >
< pre > < code class = "lang-shell" > $ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 0 0 0 1s
< / code > < / pre >
< p > 输 出 结 果 表 明 我 们 希 望 的 repalica数 是 3( 根 据 deployment中 的 < code > .spec.replicas< / code > 配 置 ) 当 前 replica数 ( < code > .status.replicas< / code > ) 是 0, 最 新 的 replica数 ( < code > .status.updatedReplicas< / code > ) 是 0, 可 用 的 replica数 ( < code > .status.availableReplicas< / code > ) 是 0。 < / p >
< p > 过 几 秒 后 再 执 行 < code > get< / code > 命 令 , 将 获 得 如 下 输 出 : < / p >
< pre > < code class = "lang-shell" > $ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s
< / code > < / pre >
< p > 我 们 可 以 看 到 Deployment已 经 创 建 了 3个 replica, 所 有 的 replica 都 已 经 是 最 新 的 了 ( 包 含 最 新 的 pod template) , 可 用 的 ( 根 据 Deployment中 的 < code > .spec.minReadySeconds< / code > 声 明 , 处 于 已 就 绪 状 态 的 pod的 最 少 个 数 ) 。 执 行 < code > kubectl get rs< / code > 和 < code > kubectl get pods< / code > 会 显 示 Replica Set( RS) 和 Pod已 创 建 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-2035384211 3 3 0 18s
< / code > < / pre >
< p > 您 可 能 会 注 意 到 ReplicaSet 的 名 字 总 是 < code > < Deployment的 名 字 > -< pod template的 hash值 > < / code > 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-2035384211-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
< / code > < / pre >
< p > 刚 创 建 的 Replica Set将 保 证 总 是 有 3个 nginx 的 pod 存 在 。 < / p >
< p > < strong > 注 意 : < / strong > 您 必 须 在 Deployment 中 的 selector 指 定 正 确 的 pod template label( 在 该 示 例 中 是 < code > app = nginx< / code > ) , 不 要 跟 其 他 的 controller 的 selector 中 指 定 的 pod template label 搞 混 了 ( 包 括 Deployment、 Replica Set、 Replication Controller 等 ) 。 < strong > Kubernetes 本 身 并 不 会 阻 止 您 任 意 指 定 pod template label < / strong > , 但 是 如 果 您 真 的 这 么 做 了 , 这 些 controller 之 间 会 相 互 打 架 , 并 可 能 导 致 不 正 确 的 行 为 。 < / p >
< h3 id = "pod-template-hash-label" > Pod-template-hash label< / h3 >
< p > < strong > 注 意 < / strong > : 这 个 label 不 是 用 户 指 定 的 ! < / p >
< p > 注 意 上 面 示 例 输 出 中 的 pod label 里 的 pod-template-hash label。 当 Deployment 创 建 或 者 接 管 ReplicaSet 时 , Deployment controller 会 自 动 为 Pod 添 加 pod-template-hash label。 这 样 做 的 目 的 是 防 止 Deployment 的 子 ReplicaSet 的 pod 名 字 重 复 。 通 过 将 ReplicaSet 的 PodTemplate 进 行 哈 希 散 列 , 使 用 生 成 的 哈 希 值 作 为 label 的 值 , 并 添 加 到 ReplicaSet selector 里 、 pod template label 和 ReplicaSet 管 理 中 的 Pod 上 。 < / p >
< h2 id = "更新deployment" > 更 新 Deployment< / h2 >
< p > < strong > 注 意 : < / strong > Deployment 的 rollout 当 且 仅 当 Deployment 的 pod template( 例 如 < code > .spec.template< / code > ) 中 的 label更 新 或 者 镜 像 更 改 时 被 触 发 。 其 他 更 新 , 例 如 扩 容 Deployment不 会 触 发 rollout。 < / p >
< p > 假 如 我 们 现 在 想 要 让 nginx pod 使 用 < code > nginx:1.9.1< / code > 的 镜 像 来 代 替 原 来 的 < code > nginx:1.7.9< / code > 的 镜 像 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment " nginx-deployment" image updated
< / code > < / pre >
< p > 我 们 可 以 使 用 < code > edit< / code > 命 令 来 编 辑 Deployment, 修 改 < code > .spec.template.spec.containers[0].image< / code > , 将 < code > nginx:1.7.9< / code > 改 写 成 < code > nginx:1.9.1< / code > 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl edit deployment/nginx-deployment
deployment " nginx-deployment" edited
< / code > < / pre >
< p > 查 看 rollout 的 状 态 , 只 要 执 行 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment " nginx-deployment" successfully rolled out
< / code > < / pre >
< p > Rollout 成 功 后 , < code > get< / code > Deployment: < / p >
< pre > < code class = "lang-shell" > $ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 36s
< / code > < / pre >
< p > UP-TO-DATE 的 replica 的 数 目 已 经 达 到 了 配 置 中 要 求 的 数 目 。 < / p >
< p > CURRENT 的 replica 数 表 示 Deployment 管 理 的 replica 数 量 , AVAILABLE 的 replica 数 是 当 前 可 用 的 replica数 量 。 < / p >
< p > 我 们 通 过 执 行 < code > kubectl get rs< / code > 可 以 看 到 Deployment 更 新 了 Pod, 通 过 创 建 一 个 新 的 ReplicaSet 并 扩 容 了 3个 replica, 同 时 将 原 来 的 ReplicaSet 缩 容 到 了 0个 replica。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 0 6s
nginx-deployment-2035384211 0 0 0 36s
< / code > < / pre >
< p > 执 行 < code > get pods< / code > 只 会 看 到 当 前 的 新 的 pod:< / p >
< pre > < code class = "lang-shell" > $ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-khku8 1/1 Running 0 14s
nginx-deployment-1564180365-nacti 1/1 Running 0 14s
nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
< / code > < / pre >
< p > 下 次 更 新 这 些 pod 的 时 候 , 只 需 要 更 新 Deployment 中 的 pod 的 template 即 可 。 < / p >
< p > Deployment 可 以 保 证 在 升 级 时 只 有 一 定 数 量 的 Pod 是 down 的 。 默 认 的 , 它 会 确 保 至 少 有 比 期 望 的 Pod数 量 少 一 个 是 up状 态 ( 最 多 一 个 不 可 用 ) 。 < / p >
< p > Deployment 同 时 也 可 以 确 保 只 创 建 出 超 过 期 望 数 量 的 一 定 数 量 的 Pod。 默 认 的 , 它 会 确 保 最 多 比 期 望 的 Pod数 量 多 一 个 的 Pod 是 up 的 ( 最 多 1个 surge ) 。 < / p >
< p > < strong > 在 未 来 的 Kuberentes 版 本 中 , 将 从 1-1变 成 25%-25%。 < / strong > < / p >
< p > 例 如 , 如 果 您 自 己 看 下 上 面 的 Deployment, 您 会 发 现 , 开 始 创 建 一 个 新 的 Pod, 然 后 删 除 一 些 旧 的 Pod 再 创 建 一 个 新 的 。 当 新 的 Pod创 建 出 来 之 前 不 会 杀 掉 旧 的 Pod。 这 样 能 够 确 保 可 用 的 Pod 数 量 至 少 有 2个 , Pod的 总 数 最 多 4个 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl describe deployments
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 12:01:06 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: < none>
NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
36s 36s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
< / code > < / pre >
< p > 我 们 可 以 看 到 当 我 们 刚 开 始 创 建 这 个 Deployment 的 时 候 , 创 建 了 一 个 ReplicaSet( nginx-deployment-2035384211) , 并 直 接 扩 容 到 了 3个 replica。 < / p >
< p > 当 我 们 更 新 这 个 Deployment 的 时 候 , 它 会 创 建 一 个 新 的 ReplicaSet( nginx-deployment-1564180365) , 将 它 扩 容 到 1个 replica, 然 后 缩 容 原 先 的 ReplicaSet 到 2个 replica, 此 时 满 足 至 少 2个 Pod 是 可 用 状 态 , 同 一 时 刻 最 多 有 4个 Pod 处 于 创 建 的 状 态 。 < / p >
< p > 接 着 继 续 使 用 相 同 的 rolling update 策 略 扩 容 新 的 ReplicaSet 和 缩 容 旧 的 ReplicaSet。 最 终 , 将 会 在 新 的 ReplicaSet 中 有 3个 可 用 的 replica, 旧 的 ReplicaSet 的 replica 数 目 变 成 0。 < / p >
< h3 id = "rollover(多个rollout并行)" > Rollover( 多 个 rollout并 行 ) < / h3 >
< p > 每 当 Deployment controller 观 测 到 有 新 的 deployment 被 创 建 时 , 如 果 没 有 已 存 在 的 ReplicaSet 来 创 建 期 望 个 数 的 Pod 的 话 , 就 会 创 建 出 一 个 新 的 ReplicaSet 来 做 这 件 事 。 已 存 在 的 ReplicaSet 控 制 label 与 < code > .spec.selector< / code > 匹 配 但 是 template 跟 < code > .spec.template< / code > 不 匹 配 的 Pod 缩 容 。 最 终 , 新 的 ReplicaSet 将 会 扩 容 出 < code > .spec.replicas< / code > 指 定 数 目 的 Pod, 旧 的 ReplicaSet 会 缩 容 到 0。 < / p >
< p > 如 果 您 更 新 了 一 个 的 已 存 在 并 正 在 进 行 中 的 Deployment, 每 次 更 新 Deployment都 会 创 建 一 个 新 的 ReplicaSet并 扩 容 它 , 同 时 回 滚 之 前 扩 容 的 ReplicaSet — — 将 它 添 加 到 旧 的 ReplicaSet 列 表 中 , 开 始 缩 容 。 < / p >
< p > 例 如 , 假 如 您 创 建 了 一 个 有 5个 < code > niginx:1.7.9< / code > replica的 Deployment, 但 是 当 还 只 有 3个 < code > nginx:1.7.9< / code > 的 replica 创 建 出 来 的 时 候 您 就 开 始 更 新 含 有 5个 < code > nginx:1.9.1< / code > replica 的 Deployment。 在 这 种 情 况 下 , Deployment 会 立 即 杀 掉 已 创 建 的 3个 < code > nginx:1.7.9< / code > 的 Pod, 并 开 始 创 建 < code > nginx:1.9.1< / code > 的 Pod。 它 不 会 等 到 所 有 的 5个 < code > nginx:1.7.9< / code > 的 Pod 都 创 建 完 成 后 才 开 始 改 变 航 道 。 < / p >
< h3 id = "label-selector-更新" > Label selector 更 新 < / h3 >
< p > 我 们 通 常 不 鼓 励 更 新 label selector, 我 们 建 议 实 现 规 划 好 您 的 selector。 < / p >
< p > 任 何 情 况 下 , 只 要 您 想 要 执 行 label selector 的 更 新 , 请 一 定 要 谨 慎 并 确 认 您 已 经 预 料 到 所 有 可 能 因 此 导 致 的 后 果 。 < / p >
< ul >
< li > 增 添 selector 需 要 同 时 在 Deployment 的 spec 中 更 新 新 的 label, 否 则 将 返 回 校 验 错 误 。 此 更 改 是 不 可 覆 盖 的 , 这 意 味 着 新 的 selector 不 会 选 择 使 用 旧 selector 创 建 的 ReplicaSet 和 Pod, 从 而 导 致 所 有 旧 版 本 的 ReplicaSet 都 被 丢 弃 , 并 创 建 新 的 ReplicaSet。 < / li >
< li > 更 新 selector, 即 更 改 selector key 的 当 前 值 , 将 导 致 跟 增 添 selector 同 样 的 后 果 。 < / li >
< li > 删 除 selector, 即 删 除 Deployment selector 中 的 已 有 的 key, 不 需 要 对 Pod template label 做 任 何 更 改 , 现 有 的 ReplicaSet 也 不 会 成 为 孤 儿 , 但 是 请 注 意 , 删 除 的 label 仍 然 存 在 于 现 有 的 Pod 和 ReplicaSet 中 。 < / li >
< / ul >
< h2 id = "回退deployment" > 回 退 Deployment< / h2 >
< p > 有 时 候 您 可 能 想 回 退 一 个 Deployment, 例 如 , 当 Deployment 不 稳 定 时 , 比 如 一 直 crash looping。 < / p >
< p > 默 认 情 况 下 , kubernetes 会 在 系 统 中 保 存 前 两 次 的 Deployment 的 rollout 历 史 记 录 , 以 便 您 可 以 随 时 回 退 ( 您 可 以 修 改 < code > revision history limit< / code > 来 更 改 保 存 的 revision数 ) 。 < / p >
< p > < strong > 注 意 : < / strong > 只 要 Deployment 的 rollout 被 触 发 就 会 创 建 一 个 revision。 也 就 是 说 当 且 仅 当 Deployment 的 Pod template( 如 < code > .spec.template< / code > ) 被 更 改 , 例 如 更 新 template 中 的 label 和 容 器 镜 像 时 , 就 会 创 建 出 一 个 新 的 revision。 < / p >
< p > 其 他 的 更 新 , 比 如 扩 容 Deployment 不 会 创 建 revision— — 因 此 我 们 可 以 很 方 便 的 手 动 或 者 自 动 扩 容 。 这 意 味 着 当 您 回 退 到 历 史 revision 是 , 直 有 Deployment 中 的 Pod template 部 分 才 会 回 退 。 < / p >
< p > 假 设 我 们 在 更 新 Deployment 的 时 候 犯 了 一 个 拼 写 错 误 , 将 镜 像 的 名 字 写 成 了 < code > nginx:1.91< / code > , 而 正 确 的 名 字 应 该 是 < code > nginx:1.9.1< / code > : < / p >
< pre > < code class = "lang-shell" > $ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
deployment " nginx-deployment" image updated
< / code > < / pre >
< p > Rollout 将 会 卡 住 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout status deployments nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
< / code > < / pre >
< p > 按 住 Ctrl-C 停 止 上 面 的 rollout 状 态 监 控 。 < / p >
< p > 您 会 看 到 旧 的 replica( nginx-deployment-1564180365 和 nginx-deployment-2035384211) 和 新 的 replica ( nginx-deployment-3066724191) 数 目 都 是 2个 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 2 2 0 25s
nginx-deployment-2035384211 0 0 0 36s
nginx-deployment-3066724191 2 2 2 6s
< / code > < / pre >
< p > 看 下 创 建 Pod, 您 会 看 到 有 两 个 新 的 ReplicaSet 创 建 的 Pod 处 于 ImagePullBackOff 状 态 , 循 环 拉 取 镜 像 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
nginx-deployment-3066724191-eocby 0/1 ImagePullBackOff 0 6s
< / code > < / pre >
< p > 注 意 , Deployment controller会 自 动 停 止 坏 的 rollout, 并 停 止 扩 容 新 的 ReplicaSet。 < / p >
< pre > < code class = "lang-shell" > $ kubectl describe deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 2 updated | 3 total | 2 available | 2 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: nginx-deployment-1564180365 (2/2 replicas created)
NewReplicaSet: nginx-deployment-3066724191 (2/2 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2
< / code > < / pre >
< p > 为 了 修 复 这 个 问 题 , 我 们 需 要 回 退 到 稳 定 的 Deployment revision。 < / p >
< h3 id = "检查-deployment-升级的历史记录" > 检 查 Deployment 升 级 的 历 史 记 录 < / h3 >
< p > 首 先 , 检 查 下 Deployment 的 revision: < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout history deployment/nginx-deployment
deployments " nginx-deployment" :
REVISION CHANGE-CAUSE
1 kubectl create -f https://kubernetes.io/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
< / code > < / pre >
< p > 因 为 我 们 创 建 Deployment 的 时 候 使 用 了 < code > --recored< / code > 参 数 可 以 记 录 命 令 , 我 们 可 以 很 方 便 的 查 看 每 次 revision 的 变 化 。 < / p >
< p > 查 看 单 个 revision 的 详 细 信 息 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout history deployment/nginx-deployment --revision=2
deployments " nginx-deployment" revision 2
Labels: app=nginx
pod-template-hash=1159050644
Annotations: kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
QoS Tier:
cpu: BestEffort
memory: BestEffort
Environment Variables: < none>
No volumes.
< / code > < / pre >
< h3 id = "回退到历史版本" > 回 退 到 历 史 版 本 < / h3 >
< p > 现 在 , 我 们 可 以 决 定 回 退 当 前 的 rollout 到 之 前 的 版 本 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout undo deployment/nginx-deployment
deployment " nginx-deployment" rolled back
< / code > < / pre >
< p > 也 可 以 使 用 < code > --revision< / code > 参 数 指 定 某 个 历 史 版 本 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment " nginx-deployment" rolled back
< / code > < / pre >
< p > 与 rollout 相 关 的 命 令 详 细 文 档 见 < a href = "https://kubernetes.io/docs/user-guide/kubectl/v1.6/#rollout" target = "_blank" > kubectl rollout< / a > 。 < / p >
< p > 该 Deployment 现 在 已 经 回 退 到 了 先 前 的 稳 定 版 本 。 如 您 所 见 , Deployment controller产 生 了 一 个 回 退 到 revison 2的 < code > DeploymentRollback< / code > 的 event。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 30m
$ kubectl describe deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: < none>
NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
30m 30m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2
2m 2m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-3066724191 to 0
2m 2m 1 {deployment-controller } Normal DeploymentRollback Rolled back deployment " nginx-deployment" to revision 2
29m 2m 2 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
< / code > < / pre >
< h3 id = "清理-policy" > 清 理 Policy< / h3 >
< p > 您 可 以 通 过 设 置 < code > .spec.revisonHistoryLimit< / code > 项 来 指 定 deployment 最 多 保 留 多 少 revision 历 史 记 录 。 默 认 的 会 保 留 所 有 的 revision; 如 果 将 该 项 设 置 为 0, Deployment就 不 允 许 回 退 了 。 < / p >
< h2 id = "deployment-扩容" > Deployment 扩 容 < / h2 >
< p > 您 可 以 使 用 以 下 命 令 扩 容 Deployment: < / p >
< pre > < code class = "lang-shell" > $ kubectl scale deployment nginx-deployment --replicas 10
deployment " nginx-deployment" scaled
< / code > < / pre >
< p > 假 设 您 的 集 群 中 启 用 了 < a href = "https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough" target = "_blank" > horizontal pod autoscaling< / a > , 您 可 以 给 Deployment 设 置 一 个 autoscaler, 基 于 当 前 Pod的 CPU 利 用 率 选 择 最 少 和 最 多 的 Pod 数 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment " nginx-deployment" autoscaled
< / code > < / pre >
< h3 id = "比例扩容" > 比 例 扩 容 < / h3 >
< p > RollingUpdate Deployment 支 持 同 时 运 行 一 个 应 用 的 多 个 版 本 。 或 者 autoscaler 扩 容 RollingUpdate Deployment 的 时 候 , 正 在 中 途 的 rollout( 进 行 中 或 者 已 经 暂 停 的 ) , 为 了 降 低 风 险 , Deployment controller 将 会 平 衡 已 存 在 的 活 动 中 的 ReplicaSet( 有 Pod 的 ReplicaSet) 和 新 加 入 的 replica。 这 被 称 为 比 例 扩 容 。 < / p >
< p > 例 如 , 您 正 在 运 行 中 含 有 10个 replica 的 Deployment。 maxSurge=3, maxUnavailable=2。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
< / code > < / pre >
< p > 您 更 新 了 一 个 镜 像 , 而 在 集 群 内 部 无 法 解 析 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl set image deploy/nginx-deployment nginx=nginx:sometag
deployment " nginx-deployment" image updated
< / code > < / pre >
< p > 镜 像 更 新 启 动 了 一 个 包 含 ReplicaSet nginx-deployment-1989198191的 新 的 rollout, 但 是 它 被 阻 塞 了 , 因 为 我 们 上 面 提 到 的 maxUnavailable。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m
< / code > < / pre >
< p > 然 后 发 起 了 一 个 新 的 Deployment扩 容 请 求 。 autoscaler将 Deployment的 repllica数 目 增 加 到 了 15个 。 Deployment controller需 要 判 断 在 哪 里 增 加 这 5个 新 的 replica。 如 果 我 们 没 有 谁 用 比 例 扩 容 , 所 有 的 5个 replica都 会 加 到 一 个 新 的 ReplicaSet中 。 如 果 使 用 比 例 扩 容 , 新 添 加 的 replica将 传 播 到 所 有 的 ReplicaSet中 。 大 的 部 分 加 入 replica数 最 多 的 ReplicaSet中 , 小 的 部 分 加 入 到 replica数 少 的 ReplciaSet中 。 0个 replica的 ReplicaSet不 会 被 扩 容 。 < / p >
< p > 在 我 们 上 面 的 例 子 中 , 3个 replica将 添 加 到 旧 的 ReplicaSet中 , 2个 replica将 添 加 到 新 的 ReplicaSet中 。 rollout进 程 最 终 会 将 所 有 的 replica移 动 到 新 的 ReplicaSet中 , 假 设 新 的 replica成 为 健 康 状 态 。 < / p >
< pre > < code class = "lang-shell" > $ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
< / code > < / pre >
< h2 id = "暂停和恢复deployment" > 暂 停 和 恢 复 Deployment< / h2 >
< p > 您 可 以 在 发 出 一 次 或 多 次 更 新 前 暂 停 一 个 Deployment, 然 后 再 恢 复 它 。 这 样 您 就 能 多 次 暂 停 和 恢 复 Deployment, 在 此 期 间 进 行 一 些 修 复 工 作 , 而 不 会 发 出 不 必 要 的 rollout。 < / p >
< p > 例 如 使 用 刚 刚 创 建 Deployment: < / p >
< pre > < code class = "lang-shell" > $ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 1m
[mkargaki@dhcp129-211 kubernetes]$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 1m
< / code > < / pre >
< p > 使 用 以 下 命 令 暂 停 Deployment: < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout pause deployment/nginx-deployment
deployment " nginx-deployment" paused
< / code > < / pre >
< p > 然 后 更 新 Deplyment中 的 镜 像 : < / p >
< pre > < code class = "lang-shell" > $ kubectl set image deploy/nginx nginx=nginx:1.9.1
deployment " nginx-deployment" image updated
< / code > < / pre >
< p > 注 意 新 的 rollout 启 动 了 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout history deploy/nginx
deployments " nginx"
REVISION CHANGE-CAUSE
1 < none>
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 2m
< / code > < / pre >
< p > 您 可 以 进 行 任 意 多 次 更 新 , 例 如 更 新 使 用 的 资 源 : < / p >
< pre > < code class = "lang-shell" > $ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
deployment " nginx" resource requirements updated
< / code > < / pre >
< p > Deployment 暂 停 前 的 初 始 状 态 将 继 续 它 的 功 能 , 而 不 会 对 Deployment 的 更 新 产 生 任 何 影 响 , 只 要 Deployment是 暂 停 的 。 < / p >
< p > 最 后 , 恢 复 这 个 Deployment, 观 察 完 成 更 新 的 ReplicaSet 已 经 创 建 出 来 了 : < / p >
< pre > < code class = "lang-shell" > $ kubectl rollout resume deploy nginx
deployment " nginx" resumed
$ KUBECTL get rs -w
NAME DESIRED CURRENT READY AGE
nginx-2142116321 2 2 2 2m
nginx-3926361531 2 2 0 6s
nginx-3926361531 2 2 1 18s
nginx-2142116321 1 2 2 2m
nginx-2142116321 1 2 2 2m
nginx-3926361531 3 2 1 18s
nginx-3926361531 3 2 1 18s
nginx-2142116321 1 1 1 2m
nginx-3926361531 3 3 1 18s
nginx-3926361531 3 3 2 19s
nginx-2142116321 0 1 1 2m
nginx-2142116321 0 1 1 2m
nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 20s
^C
$ KUBECTL get rs
NAME DESIRED CURRENT READY AGE
nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 28s
< / code > < / pre >
< p > < strong > 注 意 : < / strong > 在 恢 复 Deployment 之 前 您 无 法 回 退 一 个 已 经 暂 停 的 Deployment。 < / p >
< h2 id = "deployment-状态" > Deployment 状 态 < / h2 >
< p > Deployment 在 生 命 周 期 中 有 多 种 状 态 。 在 创 建 一 个 新 的 ReplicaSet 的 时 候 它 可 以 是 < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#progressing-deployment" target = "_blank" > progressing< / a > 状 态 , < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#complete-deployment" target = "_blank" > complete< / a > 状 态 , 或 者 < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#failed-deployment" target = "_blank" > fail to progress < / a > 状 态 。 < / p >
< h3 id = "进行中的-deployment" > 进 行 中 的 Deployment< / h3 >
< p > Kubernetes 将 执 行 过 下 列 任 务 之 一 的 Deployment 标 记 为 < em > progressing< / em > 状 态 : < / p >
< ul >
< li > Deployment 正 在 创 建 新 的 ReplicaSet过 程 中 。 < / li >
< li > Deployment 正 在 扩 容 一 个 已 有 的 ReplicaSet。 < / li >
< li > Deployment 正 在 缩 容 一 个 已 有 的 ReplicaSet。 < / li >
< li > 有 新 的 可 用 的 pod 出 现 。 < / li >
< / ul >
< p > 您 可 以 使 用 < code > kubectl rollout status< / code > 命 令 监 控 Deployment 的 进 度 。 < / p >
< h3 id = "完成的-deployment" > 完 成 的 Deployment< / h3 >
< p > Kubernetes 将 包 括 以 下 特 性 的 Deployment 标 记 为 < em > complete< / em > 状 态 : < / p >
< ul >
< li > Deployment 最 小 可 用 。 最 小 可 用 意 味 着 Deployment 的 可 用 replica 个 数 等 于 或 者 超 过 Deployment 策 略 中 的 期 望 个 数 。 < / li >
< li > 所 有 与 该 Deployment 相 关 的 replica都 被 更 新 到 了 您 指 定 版 本 , 也 就 说 更 新 完 成 。 < / li >
< li > 该 Deployment 中 没 有 旧 的 Pod 存 在 。 < / li >
< / ul >
< p > 您 可 以 用 < code > kubectl rollout status< / code > 命 令 查 看 Deployment 是 否 完 成 。 如 果 rollout 成 功 完 成 , < code > kubectl rollout status< / code > 将 返 回 一 个 0值 的 Exit Code。 < / p >
< pre > < code > $ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment " nginx" successfully rolled out
$ echo $?
0
< / code > < / pre > < h3 id = "失败的-deployment" > 失 败 的 Deployment< / h3 >
< p > 您 的 Deployment 在 尝 试 部 署 新 的 ReplicaSet 的 时 候 可 能 卡 住 , 用 于 也 不 会 完 成 。 这 可 能 是 因 为 以 下 几 个 因 素 引 起 的 : < / p >
< ul >
< li > 无 效 的 引 用 < / li >
< li > 不 可 读 的 probe failure< / li >
< li > 镜 像 拉 取 错 误 < / li >
< li > 权 限 不 够 < / li >
< li > 范 围 限 制 < / li >
< li > 程 序 运 行 时 配 置 错 误 < / li >
< / ul >
< p > 探 测 这 种 情 况 的 一 种 方 式 是 , 在 您 的 Deployment spec 中 指 定 < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#progress-deadline-seconds" target = "_blank" > < code > spec.progressDeadlineSeconds< / code > < / a > 。 < code > spec.progressDeadlineSeconds< / code > 表 示 Deployment controller 等 待 多 少 秒 才 能 确 定 ( 通 过 Deployment status) Deployment进 程 是 卡 住 的 。 < / p >
< p > 下 面 的 < code > kubectl< / code > 命 令 设 置 < code > progressDeadlineSeconds< / code > 使 controller 在 Deployment 在 进 度 卡 住 10分 钟 后 报 告 : < / p >
< pre > < code > $ kubectl patch deployment/nginx-deployment -p ' {" spec" :{" progressDeadlineSeconds" :600}}'
" nginx-deployment" patched
< / code > < / pre > < p > 当 超 过 截 止 时 间 后 , Deployment controller 会 在 Deployment 的 < code > status.conditions< / code > 中 增 加 一 条 DeploymentCondition, 它 包 括 如 下 属 性 : < / p >
< ul >
< li > Type=Progressing< / li >
< li > Status=False< / li >
< li > Reason=ProgressDeadlineExceeded< / li >
< / ul >
< p > 浏 览 < a href = "https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties" target = "_blank" > Kubernetes API conventions< / a > 查 看 关 于 status conditions的 更 多 信 息 。 < / p >
< p > < strong > 注 意 : < / strong > kubernetes除 了 报 告 < code > Reason=ProgressDeadlineExceeded< / code > 状 态 信 息 外 不 会 对 卡 住 的 Deployment 做 任 何 操 作 。 更 高 层 次 的 协 调 器 可 以 利 用 它 并 采 取 相 应 行 动 , 例 如 , 回 滚 Deployment 到 之 前 的 版 本 。 < / p >
< p > < strong > 注 意 : < / strong > 如 果 您 暂 停 了 一 个 Deployment, 在 暂 停 的 这 段 时 间 内 kubernetnes不 会 检 查 您 指 定 的 deadline。 您 可 以 在 Deployment 的 rollout 途 中 安 全 的 暂 停 它 , 然 后 再 恢 复 它 , 这 不 会 触 发 超 过 deadline的 状 态 。 < / p >
< p > 您 可 能 在 使 用 Deployment 的 时 候 遇 到 一 些 短 暂 的 错 误 , 这 些 可 能 是 由 于 您 设 置 了 太 短 的 timeout, 也 有 可 能 是 因 为 各 种 其 他 错 误 导 致 的 短 暂 错 误 。 例 如 , 假 设 您 使 用 了 无 效 的 引 用 。 当 您 Describe Deployment 的 时 候 可 能 会 注 意 到 如 下 信 息 : < / p >
< pre > < code > $ kubectl describe deployment nginx-deployment
< ...>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate
< ...>
< / code > < / pre > < p > 执 行 < code > kubectl get deployment nginx-deployment -o yaml< / code > , Deployement 的 状 态 可 能 看 起 来 像 这 个 样 子 : < / p >
< pre > < code class = "lang-yaml" > < span class = "hljs-attr" > status:< / span >
< span class = "hljs-attr" > availableReplicas:< / span > < span class = "hljs-number" > 2< / span >
< span class = "hljs-attr" > conditions:< / span >
< span class = "hljs-attr" > - lastTransitionTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 39< / span > Z
< span class = "hljs-attr" > lastUpdateTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 39< / span > Z
< span class = "hljs-attr" > message:< / span > Replica set < span class = "hljs-string" > " nginx-deployment-4262182780" < / span > is progressing.
< span class = "hljs-attr" > reason:< / span > ReplicaSetUpdated
< span class = "hljs-attr" > status:< / span > < span class = "hljs-string" > " True" < / span >
< span class = "hljs-attr" > type:< / span > Progressing
< span class = "hljs-attr" > - lastTransitionTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 42< / span > Z
< span class = "hljs-attr" > lastUpdateTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 42< / span > Z
< span class = "hljs-attr" > message:< / span > Deployment has minimum availability.
< span class = "hljs-attr" > reason:< / span > MinimumReplicasAvailable
< span class = "hljs-attr" > status:< / span > < span class = "hljs-string" > " True" < / span >
< span class = "hljs-attr" > type:< / span > Available
< span class = "hljs-attr" > - lastTransitionTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 39< / span > Z
< span class = "hljs-attr" > lastUpdateTime:< / span > < span class = "hljs-number" > 2016< / span > < span class = "hljs-bullet" > -10< / span > < span class = "hljs-bullet" > -04< / span > T12:< span class = "hljs-number" > 25< / span > :< span class = "hljs-number" > 39< / span > Z
< span class = "hljs-attr" > message:< / span > < span class = "hljs-string" > ' Error creating: pods " nginx-deployment-4262182780-" is forbidden: exceeded quota:
object-counts, requested: pods=1, used: pods=3, limited: pods=2' < / span >
< span class = "hljs-attr" > reason:< / span > FailedCreate
< span class = "hljs-attr" > status:< / span > < span class = "hljs-string" > " True" < / span >
< span class = "hljs-attr" > type:< / span > ReplicaFailure
< span class = "hljs-attr" > observedGeneration:< / span > < span class = "hljs-number" > 3< / span >
< span class = "hljs-attr" > replicas:< / span > < span class = "hljs-number" > 2< / span >
< span class = "hljs-attr" > unavailableReplicas:< / span > < span class = "hljs-number" > 2< / span >
< / code > < / pre >
< p > 最 终 , 一 旦 超 过 Deployment 进 程 的 deadline, kuberentes 会 更 新 状 态 和 导 致 Progressing 状 态 的 原 因 : < / p >
< pre > < code > Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
< / code > < / pre > < p > 您 可 以 通 过 缩 容 Deployment的 方 式 解 决 配 额 不 足 的 问 题 , 或 者 增 加 您 的 namespace 的 配 额 。 如 果 您 满 足 了 配 额 条 件 后 , Deployment controller 就 会 完 成 您 的 Deployment rollout, 您 将 看 到 Deployment 的 状 态 更 新 为 成 功 状 态 ( < code > Status=True< / code > 并 且 < code > Reason=NewReplicaSetAvailable< / code > ) 。 < / p >
< pre > < code > Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
< / code > < / pre > < p > < code > Type=Available< / code > 、 < code > Status=True< / code > 以 为 这 您 的 Deployment有 最 小 可 用 性 。 最 小 可 用 性 是 在 Deployment策 略 中 指 定 的 参 数 。 < code > Type=Progressing< / code > 、 < code > Status=True< / code > 意 味 着 您 的 Deployment 或 者 在 部 署 过 程 中 , 或 者 已 经 成 功 部 署 , 达 到 了 期 望 的 最 少 的 可 用 replica数 量 ( 查 看 特 定 状 态 的 Reason— — 在 我 们 的 例 子 中 < code > Reason=NewReplicaSetAvailable< / code > 意 味 着 Deployment已 经 完 成 ) 。 < / p >
< p > 您 可 以 使 用 < code > kubectl rollout status< / code > 命 令 查 看 Deployment进 程 是 否 失 败 。 当 Deployment过 程 超 过 了 deadline, < code > kubectl rollout status< / code > 将 返 回 非 0的 exit code。 < / p >
< pre > < code > $ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment " nginx" exceeded its progress deadline
$ echo $?
1
< / code > < / pre > < h3 id = "操作失败的-deployment" > 操 作 失 败 的 Deployment< / h3 >
< p > 所 有 对 完 成 的 Deployment 的 操 作 都 适 用 于 失 败 的 Deployment。 您 可 以 对 它 扩 /缩 容 , 回 退 到 历 史 版 本 , 您 甚 至 可 以 多 次 暂 停 它 来 应 用 Deployment pod template。 < / p >
< h2 id = "清理policy" > 清 理 Policy< / h2 >
< p > 您 可 以 设 置 Deployment 中 的 < code > .spec.revisionHistoryLimit< / code > 项 来 指 定 保 留 多 少 旧 的 ReplicaSet。 余 下 的 将 在 后 台 被 当 作 垃 圾 收 集 。 默 认 的 , 所 有 的 revision 历 史 就 都 会 被 保 留 。 在 未 来 的 版 本 中 , 将 会 更 改 为 2。 < / p >
< p > < strong > 注 意 : < / strong > 将 该 值 设 置 为 0, 将 导 致 所 有 的 Deployment 历 史 记 录 都 会 被 清 除 , 该 Deployment 就 无 法 再 回 退 了 。 < / p >
< h2 id = "用例" > 用 例 < / h2 >
< h3 id = "金丝雀-deployment" > 金 丝 雀 Deployment< / h3 >
< p > 如 果 您 想 要 使 用 Deployment 对 部 分 用 户 或 服 务 器 发 布 release, 您 可 以 创 建 多 个 Deployment, 每 个 Deployment 对 应 一 个 release, 参 照 < a href = "https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments" target = "_blank" > managing resources< / a > 中 对 金 丝 雀 模 式 的 描 述 。 < / p >
< h2 id = "编写-deployment-spec" > 编 写 Deployment Spec< / h2 >
< p > 在 所 有 的 Kubernetes 配 置 中 , Deployment 也 需 要 < code > apiVersion< / code > , < code > kind< / code > 和 < code > metadata< / code > 这 些 配 置 项 。 配 置 文 件 的 通 用 使 用 说 明 查 看 < a href = "https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/" target = "_blank" > 部 署 应 用 < / a > , 配 置 容 器 , 和 < a href = "https://kubernetes.io/docs/tutorials/object-management-kubectl/object-management/" target = "_blank" > 使 用 kubectl 管 理 资 源 < / a > 文 档 。 < / p >
< p > Deployment也 需 要 < a href = "https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status" target = "_blank" > < code > .spec< / code > section< / a > .< / p >
< h3 id = "pod-template" > Pod Template< / h3 >
< p > < code > .spec.template< / code > 是 < code > .spec< / code > 中 唯 一 要 求 的 字 段 。 < / p >
< p > < code > .spec.template< / code > 是 < a href = "https://kubernetes.io/docs/user-guide/replication-controller/#pod-template" target = "_blank" > pod template< / a > . 它 跟 < a href = "https://kubernetes.io/docs/user-guide/pods" target = "_blank" > Pod< / a > 有 一 模 一 样 的 schema, 除 了 它 是 嵌 套 的 并 且 不 需 要 < code > apiVersion< / code > 和 < code > kind< / code > 字 段 。 < / p >
< p > 另 外 为 了 划 分 Pod的 范 围 , Deployment中 的 pod template必 须 指 定 适 当 的 label( 不 要 跟 其 他 controller重 复 了 , 参 考 < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#selector" target = "_blank" > selector< / a > ) 和 适 当 的 重 启 策 略 。 < / p >
< p > < a href = "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle" target = "_blank" > < code > .spec.template.spec.restartPolicy< / code > < / a > 可 以 设 置 为 < code > Always< / code > , 如 果 不 指 定 的 话 这 就 是 默 认 配 置 。 < / p >
< h3 id = "replicas" > Replicas< / h3 >
< p > < code > .spec.replicas< / code > 是 可 以 选 字 段 , 指 定 期 望 的 pod数 量 , 默 认 是 1。 < / p >
< h3 id = "selector" > Selector< / h3 >
< p > < code > .spec.selector< / code > 是 可 选 字 段 , 用 来 指 定 < a href = "https://kubernetes.io/docs/concepts/overview/working-with-objects/labels" target = "_blank" > label selector< / a > , 圈 定 Deployment管 理 的 pod范 围 。 < / p >
< p > 如 果 被 指 定 , < code > .spec.selector< / code > 必 须 匹 配 < code > .spec.template.metadata.labels< / code > , 否 则 它 将 被 API拒 绝 。 如 果 < code > .spec.selector< / code > 没 有 被 指 定 , < code > .spec.selector.matchLabels< / code > 默 认 是 < code > .spec.template.metadata.labels< / code > 。 < / p >
< p > 在 Pod的 template跟 < code > .spec.template< / code > 不 同 或 者 数 量 超 过 了 < code > .spec.replicas< / code > 规 定 的 数 量 的 情 况 下 , Deployment会 杀 掉 label跟 selector不 同 的 Pod。 < / p >
< p > < strong > 注 意 : < / strong > 您 不 应 该 再 创 建 其 他 label跟 这 个 selector匹 配 的 pod, 或 者 通 过 其 他 Deployment, 或 者 通 过 其 他 Controller, 例 如 ReplicaSet和 ReplicationController。 否 则 该 Deployment会 被 把 它 们 当 成 都 是 自 己 创 建 的 。 Kubernetes不 会 阻 止 您 这 么 做 。 < / p >
< p > 如 果 您 有 多 个 controller使 用 了 重 复 的 selector, controller们 就 会 互 相 打 架 并 导 致 不 正 确 的 行 为 。 < / p >
< h3 id = "策略" > 策 略 < / h3 >
< p > < code > .spec.strategy< / code > 指 定 新 的 Pod替 换 旧 的 Pod的 策 略 。 < code > .spec.strategy.type< / code > 可 以 是 " Recreate" 或 者 是 " RollingUpdate" 。 " RollingUpdate" 是 默 认 值 。 < / p >
< h4 id = "recreate-deployment" > Recreate Deployment< / h4 >
< p > < code > .spec.strategy.type==Recreate< / code > 时 , 在 创 建 出 新 的 Pod之 前 会 先 杀 掉 所 有 已 存 在 的 Pod。 < / p >
< h4 id = "rolling-update-deployment" > Rolling Update Deployment< / h4 >
< p > < code > .spec.strategy.type==RollingUpdate< / code > 时 , Deployment使 用 < a href = "https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller" target = "_blank" > rolling update< / a > 的 方 式 更 新 Pod 。 您 可 以 指 定 < code > maxUnavailable< / code > 和 < code > maxSurge< / code > 来 控 制 rolling update 进 程 。 < / p >
< h5 id = "max-unavailable" > Max Unavailable< / h5 >
< p > < code > .spec.strategy.rollingUpdate.maxUnavailable< / code > 是 可 选 配 置 项 , 用 来 指 定 在 升 级 过 程 中 不 可 用 Pod的 最 大 数 量 。 该 值 可 以 是 一 个 绝 对 值 ( 例 如 5) , 也 可 以 是 期 望 Pod数 量 的 百 分 比 ( 例 如 10%) 。 通 过 计 算 百 分 比 的 绝 对 值 向 下 取 整 。 如 果 < code > .spec.strategy.rollingUpdate.maxSurge< / code > 为 0时 , 这 个 值 不 可 以 为 0。 默 认 值 是 1。 < / p >
< p > 例 如 , 该 值 设 置 成 30%, 启 动 rolling update后 旧 的 ReplicatSet将 会 立 即 缩 容 到 期 望 的 Pod数 量 的 70%。 新 的 Pod ready后 , 随 着 新 的 ReplicaSet的 扩 容 , 旧 的 ReplicaSet会 进 一 步 缩 容 , 确 保 在 升 级 的 所 有 时 刻 可 以 用 的 Pod数 量 至 少 是 期 望 Pod数 量 的 70%。 < / p >
< h5 id = "max-surge" > Max Surge< / h5 >
< p > < code > .spec.strategy.rollingUpdate.maxSurge< / code > 是 可 选 配 置 项 , 用 来 指 定 可 以 超 过 期 望 的 Pod数 量 的 最 大 个 数 。 该 值 可 以 是 一 个 绝 对 值 ( 例 如 5) 或 者 是 期 望 的 Pod数 量 的 百 分 比 ( 例 如 10%) 。 当 < code > MaxUnavailable< / code > 为 0时 该 值 不 可 以 为 0。 通 过 百 分 比 计 算 的 绝 对 值 向 上 取 整 。 默 认 值 是 1。 < / p >
< p > 例 如 , 该 值 设 置 成 30%, 启 动 rolling update后 新 的 ReplicatSet将 会 立 即 扩 容 , 新 老 Pod的 总 数 不 能 超 过 期 望 的 Pod数 量 的 130%。 旧 的 Pod被 杀 掉 后 , 新 的 ReplicaSet将 继 续 扩 容 , 旧 的 ReplicaSet会 进 一 步 缩 容 , 确 保 在 升 级 的 所 有 时 刻 所 有 的 Pod数 量 和 不 会 超 过 期 望 Pod数 量 的 130%。 < / p >
< h3 id = "progress-deadline-seconds" > Progress Deadline Seconds< / h3 >
< p > < code > .spec.progressDeadlineSeconds< / code > 是 可 选 配 置 项 , 用 来 指 定 在 系 统 报 告 Deployment的 < a href = "https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md#failed-deployment" target = "_blank" > failed progressing< / a > — — 表 现 为 resource的 状 态 中 < code > type=Progressing< / code > 、 < code > Status=False< / code > 、 < code > Reason=ProgressDeadlineExceeded< / code > 前 可 以 等 待 的 Deployment进 行 的 秒 数 。 Deployment controller会 继 续 重 试 该 Deployment。 未 来 , 在 实 现 了 自 动 回 滚 后 , deployment controller在 观 察 到 这 种 状 态 时 就 会 自 动 回 滚 。 < / p >
< p > 如 果 设 置 该 参 数 , 该 值 必 须 大 于 < code > .spec.minReadySeconds< / code > 。 < / p >
< h3 id = "min-ready-seconds" > Min Ready Seconds< / h3 >
< p > < code > .spec.minReadySeconds< / code > 是 一 个 可 选 配 置 项 , 用 来 指 定 没 有 任 何 容 器 crash的 Pod并 被 认 为 是 可 用 状 态 的 最 小 秒 数 。 默 认 是 0( Pod在 ready后 就 会 被 认 为 是 可 用 状 态 ) 。 进 一 步 了 解 什 么 什 么 后 Pod会 被 认 为 是 ready状 态 , 参 阅 < a href = "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes" target = "_blank" > Container Probes< / a > 。 < / p >
< h3 id = "rollback-to" > Rollback To< / h3 >
< p > < code > .spec.rollbackTo< / code > 是 一 个 可 以 选 配 置 项 , 用 来 配 置 Deployment回 退 的 配 置 。 设 置 该 参 数 将 触 发 回 退 操 作 , 每 次 回 退 完 成 后 , 该 值 就 会 被 清 除 。 < / p >
< h4 id = "revision" > Revision< / h4 >
< p > < code > .spec.rollbackTo.revision< / code > 是 一 个 可 选 配 置 项 , 用 来 指 定 回 退 到 的 revision。 默 认 是 0, 意 味 着 回 退 到 历 史 中 最 老 的 revision。 < / p >
< h3 id = "revision-history-limit" > Revision History Limit< / h3 >
< p > Deployment revision history存 储 在 它 控 制 的 ReplicaSets中 。 < / p >
< p > < code > .spec.revisionHistoryLimit< / code > 是 一 个 可 选 配 置 项 , 用 来 指 定 可 以 保 留 的 旧 的 ReplicaSet数 量 。 该 理 想 值 取 决 于 心 Deployment的 频 率 和 稳 定 性 。 如 果 该 值 没 有 设 置 的 话 , 默 认 所 有 旧 的 Replicaset或 会 被 保 留 , 将 资 源 存 储 在 etcd中 , 是 用 < code > kubectl get rs< / code > 查 看 输 出 。 每 个 Deployment的 该 配 置 都 保 存 在 ReplicaSet中 , 然 而 , 一 旦 您 删 除 的 旧 的 RepelicaSet, 您 的 Deployment就 无 法 再 回 退 到 那 个 revison了 。 < / p >
< p > 如 果 您 将 该 值 设 置 为 0, 所 有 具 有 0个 replica的 ReplicaSet都 会 被 删 除 。 在 这 种 情 况 下 , 新 的 Deployment rollout无 法 撤 销 , 因 为 revision history都 被 清 理 掉 了 。 < / p >
< h3 id = "paused" > Paused< / h3 >
< p > < code > .spec.paused< / code > 是 可 以 可 选 配 置 项 , boolean值 。 用 来 指 定 暂 停 和 恢 复 Deployment。 Paused和 没 有 paused的 Deployment之 间 的 唯 一 区 别 就 是 , 所 有 对 paused deployment中 的 PodTemplateSpec的 修 改 都 不 会 触 发 新 的 rollout。 Deployment被 创 建 之 后 默 认 是 非 paused。 < / p >
< h2 id = "deployment-的替代选择" > Deployment 的 替 代 选 择 < / h2 >
< h3 id = "kubectl-rolling-update" > kubectl rolling update< / h3 >
< p > < a href = "https://kubernetes.io/docs/user-guide/kubectl/v1.6/#rolling-update" target = "_blank" > Kubectl rolling update< / a > 虽 然 使 用 类 似 的 方 式 更 新 Pod和 ReplicationController。 但 是 我 们 推 荐 使 用 Deployment, 因 为 它 是 声 明 式 的 , 客 户 端 侧 , 具 有 附 加 特 性 , 例 如 即 使 滚 动 升 级 结 束 后 也 可 以 回 滚 到 任 何 历 史 版 本 。 < / p >
< footer class = "page-footer-ex" > < span class = "page-footer-ex-copyright" > for GitBook< / span >                       < span class = "page-footer-ex-footer-update" > update
2017-08-21 18:44:34 +08:00
2017-08-21 18:23:34
2017-08-21 17:44:43 +08:00
< / span > < / footer >
< / section >
< / div >
< div class = "search-results" >
< div class = "has-results" >
< h1 class = "search-results-title" > < span class = 'search-results-count' > < / span > results matching "< span class = 'search-query' > < / span > "< / h1 >
< ul class = "search-results-list" > < / ul >
< / div >
< div class = "no-results" >
< h1 class = "search-results-title" > No results matching "< span class = 'search-query' > < / span > "< / h1 >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< a href = "volume.html" class = "navigation navigation-prev " aria-label = "Previous page: 2.2.5 Volume和Persistent Volume" >
< i class = "fa fa-angle-left" > < / i >
< / a >
< a href = "secret.html" class = "navigation navigation-next " aria-label = "Next page: 2.2.7 Secret" >
< i class = "fa fa-angle-right" > < / i >
< / a >
< / div >
< script >
var gitbook = gitbook || [];
gitbook.push(function() {
2017-08-23 17:48:49 +08:00
gitbook.page.hasChanged({"page":{"title":"2.2.6 Deployment","level":"1.2.2.6","depth":3,"next":{"title":"2.2.7 Secret","level":"1.2.2.7","depth":3,"path":"concepts/secret.md","ref":"concepts/secret.md","articles":[]},"previous":{"title":"2.2.5 Volume和Persistent Volume","level":"1.2.2.5","depth":3,"path":"concepts/volume.md","ref":"concepts/volume.md","articles":[]},"dir":"ltr"},"config":{"plugins":["github","codesnippet","splitter","page-toc-button","image-captions","page-footer-ex","editlink","-lunr","-search","search-plus"],"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"github":{"url":"https://github.com/rootsongjc/kubernetes-handbook"},"editlink":{"label":"编辑本页","multilingual":false,"base":"https://github.com/rootsongjc/kubernetes-handbook/blob/master/"},"page-footer-ex":{"copyright":"for GitBook","update_format":"YYYY-MM-DD HH:mm:ss","update_label":"update"},"splitter":{},"codesnippet":{},"fontsettings":{"theme":"white","family":"sans","size":2},"highlight":{},"page-toc-button":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false},"search-plus":{},"image-captions":{"variable_name":"_pictures"}},"page-footer-ex":{"copyright":"Jimmy Song","update_label":"最后更新:","update_format":"YYYY-MM-DD HH:mm:ss"},"theme":"default","author":"Jimmy Song","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{"_pictures":[{"backlink":"index.html#fig1.1.1","level":"1.1","list_caption":"Figure: wercker status","alt":"wercker status","nro":1,"url":"https://app.wercker.com/status/b8b69e593784e17ddcfd1286adfd8f3c/s/master","index":1,"caption_template":"Figure: _CAPTION_","label":"wercker status","attributes":{},"title":"wercker status","skip":false,"key":"1.1.1"},{"backlink":"concepts/index.html#fig1.2.1","level":"1.2","list_caption":"Figure: Borg架构","alt":"Borg架构","nro":2,"url":"../images/borg.png","index":1,"caption_template":"Figure: _CAPTION_","label":"Borg架构","attributes":{},"skip":false,"key":"1.2.1"},{"backlink":"concepts/index.html#fig1.2.2","level":"1.2","list_caption":"Figure: Kubernetes架构","alt":"Kubernetes架构","nro":3,"url":"../images/architecture.png","index":2,"caption_template":"Figure: _CAPTION_","label":"Kubernetes架构","attributes":{},"skip":false,"key":"1.2.2"},{"backlink":"concepts/index.html#fig1.2.3","level":"1.2","list_caption":"Figure: kubernetes整体架构示意图","alt":"kubernetes整体架构示意图","nro":4,"url":"../images/kubernetes-whole-arch.png","index":3,"caption_template":"Figure: _CAPTION_","label":"kubernetes整体架构示意图","attributes":{},"skip":false,"key":"1.2.3"},{"backlink":"concepts/index.html#fig1.2.4","level":"1.2","list_caption":"Figure: Kubernetes master架构示意图","alt":"Kubernetes master架构示意图","nro":5,"url":"../images/kubernetes-master-arch.png","index":4,"caption_template":"Figure: _CAPTION_","label":"Kubernetes master架构示意图","attributes":{},"skip":false,"key":"1.2.4"},{"backlink":"concepts/index.html#fig1.2.5","level":"1.2","list_caption":"Figure: kubernetes node架构示意图","alt":"kubernetes node架构示意图","nro":6,"url":"../images/kubernetes-node-arch.png","index":5,"caption_template":"Figure: _CAPTION_","label":"kubernetes node架构示意图","attributes":{},"skip":false,"key":"1.2.5"},{"backlink":"concepts/index.html#fig1.2.6","level":"1.2","list_caption":"Figure: Kubernetes分层架构示意图","alt":"Kub
2017-08-21 17:44:43 +08:00
});
< / script >
< / div >
< script src = "../gitbook/gitbook.js" > < / script >
< script src = "../gitbook/theme.js" > < / script >
< script src = "../gitbook/gitbook-plugin-github/plugin.js" > < / script >
< script src = "../gitbook/gitbook-plugin-splitter/splitter.js" > < / script >
< script src = "../gitbook/gitbook-plugin-page-toc-button/plugin.js" > < / script >
< script src = "../gitbook/gitbook-plugin-editlink/plugin.js" > < / script >
< script src = "../gitbook/gitbook-plugin-search-plus/jquery.mark.min.js" > < / script >
< script src = "../gitbook/gitbook-plugin-search-plus/search.js" > < / script >
< script src = "../gitbook/gitbook-plugin-sharing/buttons.js" > < / script >
< script src = "../gitbook/gitbook-plugin-fontsettings/fontsettings.js" > < / script >
< / body >
< / html >