k8s 控制器:controller-manager ,是部署、管理pod 的。常见的控制器类型有deployment、Job 、statefulset 、daemonset 等等。deployment 是最常见的控制器,它是部署静态服务用的控制器。控制器是通过标签来关联查找pod 的
deployment
介绍
deployment 功能与应用场景
关于版本迭代和升级
1、下线旧的服务,上线新的服务,此方式适用于新旧应用不能同时提供服务,弊端就是可能造成服务短暂不可用。
2、滚动更新,下线一个旧的再上一个新的,依次逐个更新,直至所有旧的下线新的上线,此过程新旧程序同时提供服务。
针对滚动更新,k8s 中的两种方式
方式一
kubectl + rc 方式滚动升级,通过rc或rs 创建pod 应用,再通过kubectl rolling-update 命令升级。整个过程如下:
通过yaml新建资源rc和service,pod 模板绑定标签,rc和svc 通过标签选择器关联Pod ,kubectl 命令来新建一个rc并且制定新镜像版本,发送命令到api ,每次删除一个旧的pod ,就新建一个新的pod ,直至旧的pod 完全消失新pod全部建立,整个过程service 可以访问在线的新旧pod 提供服务。
方式二
deployment 声明式的方式实现滚动升级,而不是kubectl 命令式的方式,本文后面会有详细介绍。
两者比较
方式一 中整个过程一直是通过kubectl 客户端命令与api 通信,如果客户端与api 网络故障容易导致升级中断,而且此过程中还添加了新的标签。
方式二 声明式的,而不是kubectl 命令式的方式;deployment 方式升级可以有两种方式(滚动升级,删除旧的上新的),而且升级出错可以回退。deployment 方式升级实现过程与kubectl rollling-update 过程相似也是新建一个副本控制器,整个过程是由deployment 协调维护两个副本控制器的状态的,但是旧的rs 不会删除,记录所有升级记录,可以回退。
相关操作
部署应用程序
创建资源deployment
kubectl create deployment --help kubectl create deployment dep-name --image=naginx --dry-run -o yaml > a.yaml # --dry-run不实际生效只是测试,-o yaml把此命令转换成yaml 格式 vi a.yaml #再编辑配置此文件自定义要配置的pod 参数。 kubectl create -f a.yaml --record #根据文件创建资源,record 参数为了记录历史版本号 kubectl get deploy -n namespace #查看通过 deployment 部署的pod kubectl describe deploy,pods -n namespace #查看详情 kubectl rollout status deployment kubia #查看部署状态 kubectl get pod #查看部署的pod,由Deployment创建的三个pod 名称中均包含一个额外的数字,这个数字实际上对应 Deployment 和 Repli caSet 中的 pod 模板的哈希值 kubectl get replicasets #查看创建的rc ,ReplicaSet的名称中也包含了其 pod 模板的哈希值。Deployment 会创建多个 ReplicaSet, 用来对应和管 理一个版本的pod模板。像这样使用pod模板的哈希值,可以让 Deployment 始终对给定版本的pod模板创建相同的(或使用已有的) ReplicaSet。
创建service 发布应用
kubectl expose --help kubectl expose --named=service-name deployment dep-name --port=80 --target-port=8080 --type=NodePort 代理的名称 为哪个dep创建代理 代理对外端口 pod 中内部端口 端口暴露类型 kubectl get service #查看创建的代理
升级/回滚/扩容
升级
分为两种升级策略,默认是滚动更新(策略名为 RollingUpdate)升级过程中pod数量可以在期望副本数的一定区间内浮动, 并且其上限和下限是可配置的。 如果应用能够支持多个版本同时对外提供服务, 则推荐使用这个策略来升级应用;
另一种策略为 Recreate, 它会一次性删除所有旧版本的 pod, 然后创建新的pod使用这种策略的话, 会导致应用程序出现短暂的不可用。
在线更改deployment 的配置的命令一般都会引发升级(kubectl apply/kubectl edit /kubectl set image等)
回滚
升级 kubectl patch deployment kubia-p '{"spec": {"minReadySeconds": 10}}' #减慢升级速度 kubectl set image deployment web old-defined-image-name=image-name #升级/更新(原理:通过指定原Pod 对应的镜像来实现更新pod。升级过程:滚动升级,先创建一个新镜像容器,运行成功后再删除旧的容器) kubectl edit svc/web #如果新镜像里面服务端口有变化,此命令更新service 映射端口 关于滚动升级有两个重要的策略属性:maxSurge和maxUnavailable ,具体查看官网根据实际情况设置 回滚Deployment kubectl rollout undo deployment kubia #会被回滚到上个版本。 kubectl rollout hist ry deployment kubia #查看升级的历史版本 kubectl rollout undo deployment kubia- -to-revision=l #会滚到特定一个版本 暂停滚动升级/恢复暂停的滚动升级 kubect1 rollout pause deployment kubia kubect1 rollout resume deployment kubia 阻止出错版本的滚动升级策略配置(minReadySeconds + 就绪探针+progressDeadlineSeconds) 升级部署第一个pod的时候通过就绪探针检测正常的时间达到minReadySeconds值后k8s 就认为此pod 可用,只有pod 可用以后才会继续升级下一个pod ,否则会停止升级错误的pod 如果达到了progressDeadlineSeconds指定的时间, 则滚动升级过程会自动取消。 vi a.yam. apiVersion: apps/vlbetal kind: Deployment metadata: name: kubia spec: replicas: 3 minReadySeconds: 10 #设置minReadySeconds的值为10 strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate template: metadata: name: kubia labels: app: kubia spec: containers: -image: luksa/kubia:v3 name: nodejs readinessProbe: #定义一个就绪探针每隔一秒执行一次,就绪探针发送http get请求 periodSeconds: 1 httpGet: path:/ port: 8080 kubectl apply -f a.yaml
扩/缩容
升级相关的几个重要配置属性
决定了 Deployment 配置中期望的副本数之外,最多允许超出的 od 实例的数量。默认值为 25% ,所以 pod 实例最多可以比期望数量多 25 如果期望副本数被设置为 4.那么在滚动列级知 间,不会运行超 pod 实例。当把百分数转换成绝对值时将数字四舍五入 这个值也可以不是百分数 是绝对值 例如,可以允许最多多个成两个pod决定了在滚动升级
决定了在滚动升级期间 ,相对于期望副本数能够允许有多少 实例处于不可用状态。默认值也是 25% 所以可用 od 实例的数量不能低于期望副本数的 75 。百分数转换成绝对值时这个数字也会四舍五入 如果期望副本数设置为 ,并且百分比为 25 %.那么只能有 pod 于不可用状态。在整个发布过程中 ,总是保持至少有三个实例处于可用状态来提供服务 maxSurge 样,也可以 定绝对值而不是百分比
minReadySeconds属性指定新创建的pod至少要成功运行多久之后 , 才能将其视为可用。 在pod可用之前, 滚动升级的过程不会继续(还记得 maxUnava辽- able属性吗?)。 当所有容器的就绪探针返回成功时 , pod 就被标记为就绪状态。如果一个新的pod运行出错, 就绪探针返回失败, 如果一个新的pod 运行出错, 并且在minReadySeconds时间内它的就绪探针出现了失败, 那么新版本的滚动升级将被阻止。
类似于健康检查,设定一个检查频率,根据检查返回结果判定pod 是否处于就绪状态,例如每隔1s 发送一个get 请求,返回200则认为pod 是就绪状态,配合minReadySeconds使用,就绪状态达到 minReadySeconds值后认为pod 可以,可以就绪升级下一个。当pod 为非就绪状态那么service 也不会转发请求到该pod,然后也会停止部署升级下一个,直至返回就绪状态且达到设定时间才会继续部署
如果达到了progressDeadlineSeconds指定的时间, 则滚动升级过程会自动取消。默认情况下, 在10分钟内不能完成滚动升级的话, 将被视为失败。注意extensions/vlbetal版本不会设置默认的deadline。
FAQ
关于升级过程的镜像问题
使用同样的Tag推送更新过后的镜像虽然在开发过程中经常推送修改后的应用到同一个镜像tag, 但是这种做法并不可取。 如果修改了latest的tag的话是可行的, 但如果使用一个不同的
tag名(比如是vl而不是lastest), 等计算节点拉取过镜像之后, 便会将镜像存储在节点上 。 如果使用该镜像启动新的pod, 便不会重新拉取镜像(至少这是默认的拉取镜像策略)。
这也意味着, 如果将对更改过后的镜像推到相同的tag, 会导致镜像不被重新拉取。 如果一个新的pod被调度到同一个节点上, Kubelet直接使用旧的镜像版本来启动pod。 另一方面, 没有运行过旧版本的节点将拉取并运行新镜像, 因此最后可能有两个不同版本的pod同时运行。 为了确保这种情况不会发生, 需要将容器的imagePullPo巨cy属性设置为Always
另外默认的imagePullPo巨cy 策略也依赖于镜像的tag。如果容器使用latest的tag (显式指定或者不指定),则imagePullPolicy默认为Always,但是如果容器指定了其他标记,则策略 默认为IfNotPresent。当使用非latest的tag时,如果对镜像进行更改而不更改tag, 则需要正确设置imagePullPolicy。当然最好使用一个新的tag来更新镜像。
修改 Deployment 或其他资源的不同方式
kubectl edit #使用默认编辑器在线打开资源配置。修改保存并退出编辑器,资源对象会被更新例子: kubectl edit deployment asdf kubectl patch #修改单个资源属性,例子: kubectl patch deployment kubia-p'{"spec":{"template": {"spec": {"containers": [ {"name":"nodejs","im age":"luksa/kubia:v2"}]}}}}' kubectl apply #通过一个完整的YAML或JSON文件,应用其中新的值来修改对象。如果YAML/JSON中指定对象不存在,则会被创建。该文件需要包含资源的完整定义(不能像kube ctl patch那样只包含想要更新的字段)例子 : kubec七1 apply-f kubia-deployment-v2.yaml kubectl replace #将原有对象替换为YAML/JSON文件中定义的新对象。与apply命令相反,运行这个命令前要求对象必须存在,否则会打印错误例子: kubectl replace-f kubi a-deployment一v2.yaml。 kubectl setimage #修改Pod、ReplicationController、Deployment、DernonSet、Job或ReplicaSet内镜像例子:kubectl set image deployment kubia nodejs=l uksa/kubia:v2
相关命令
Tips:k8s 中所有的对象操作都需要指定命名空间,否则就是在默认的命名空间
列出所有存在的命名空间 kubectl get ns 新建的pod 查看 kubectl get pods -n namespace #注意如果不指定命名空间,默认就是default命名空间。pod 状态异常,日志查看 pod 状态异常,日志查看 kubectl logs -f pod-name -n namespace #同样需要指定命名空间,否则在默认命名空间如果没有,会提示not found 查看一个deployment 配置(如果通过deployment 部署了pod,想知道相关配置) kubectl get deployment -n kzf #先在控制器所在命名空间查看所有的deployment NAME READY UP-TO-DATE AVAILABLE AGE usercenter 2/2 2 2 6d5h kubectl describe deployment app1 -n kzf #指定控制器名称,查看该控制器的配置 kubectl get deployment nginx -n kzf -o yaml #获取控制器的yaml格式配置,可以使用此配置创建新的控制器 当不知道一个pod 是通过哪种控制器部署的时候可以查看pod 信息获取控制器信息 kubectl describe pod pay-c6f6fdd-mk6f2 -n kzf #查看Controlled By: xxxx/xxxx 项 kubectl describe replicaset replicaset-name -n kzf #如果Controlled: 为ReplicaSet/xxx ,可以进一步查看replicaset信息得知replicaset 由谁创建的