作者: LemonNan

原文地址: https://juejin.im/post/6865672466939150349/

Kubernetes 系列

Deployment

上一篇我们说到如果只是单单的创建 Pod 和 Service 并且将它们关联, 是无法做到宕机自动重新部署, 没错, 这就是这篇要介绍的 Deployment, 不仅能实现 自动维持可用 Pod 数量, 还能实现 水平扩容、灰度发布、不停服更新 等许多重要的线上功能.

操作的基础

最近的文章都是基于 minikube 进行的操作, 所以时不时的需要进入到 minikube 里面进行一些操作的验证, 所以把进入 minikube 的操作记录在这.

# minikube 默认用户名:docker 密码:tcuser , 我的地址是 192.168.99.100
ssh docker@192.168.99.100

演示

配置文件 - yaml

Deployment

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx
spec:
selector:
matchLabels:
name: label-pod-nginx # 将拥有 name=label-pod-nginx 的 pod 纳入管理范围
replicas: 2 # 2个 Pod 实例
template: # 容器(Pod) 模板
metadata:
labels:
name: label-pod-nginx # 跟上面的 matchLabels 对应,才能被上面配置的纳入管理
spec:
containers:
- name: pod-nginx
image: nginx:latest
ports:
- containerPort: 80

Service

service.yaml 还是使用上一篇的 service.yaml

# service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-nginx
namespace: default # 命名空间,不填默认为 default
labels:
name: label-svc-nginx # service 的标签
annotations:
name: anno-nginx
spec:
selector:
name : label-pod-nginx # 管理具有 nginx 标签的 Pod
type: ClusterIP # 不填默认 ClusterIP, 用于集群内部 Pod 访问, 在 Node 上 kube-proxy 通过设置的规则进行转发
# clusterIP: 172.18.0.1 # 虚拟IP, type = ClusterIP 时, 可以不指定,不指定系统自动分发;
# type=LoadBalancer 时, 必须指定
sessionAffinity: ClientIP # 是否支持 session, 默认为空. 可选 ClientIP, 表示将同一个客户端(根据客户端IP决定)请求到一个 Pod 上
ports:
- name: p80 # 端口名称
protocol: TCP # 协议
port: 8080 # service 对外暴露的端口
targetPort: 80 # 后端 Pod 端口
# nodePort: 80 # 当上面的 type = NodePort 的时候, 指定宿主主机的端口
# status: # 当 type=LoadBalancer 的时候, 设置外部负载均衡的信息
# loadBalancer:
# ingress:
# ip: xxx # 外部负载均衡地址
# hostname: xxx # 名称

创建 deployment 和 service

使用上面配置文件 yaml 进行创建

创建 deployment

kubectl create -f deployment.yaml

创建 svc

kubectl create -f service.yaml

创建后查看 deployment 状态, 可以看到跟 deployment 关联的 Pod 的逐渐启动起来.

模拟 Pod 不可用

下面尝模拟一个 Pod 挂掉了, 可能是该Pod所在宿主主机挂掉了导致的.

为了方便查看,开2个终端,一个关闭, 另一个直接查看.

可以看到 sc5gn 这个 Pod在关闭(Terminating) 的时候, 另一个 Pod(6ndvp) 正在创建并启动

一个 Pod 不可用 deployment 将会创建另一个新的 Pod 来代替它



在执行 delete 后, 最终情况如下, 可以看到 最后就剩下了 原来的 k4lcb新创建的 6ndvp, 原来被 delete 的那个 Pod 已经关闭.



从这里可以看出 deployment 的作用是动态维护可用 Pod 的数量, 由于我们 yaml 文件里面配置的 replicas=2 , 所以在我们关闭掉一个 Pod 之后, deployment 会检测到有一个 Pod 不可用, 然后根据 replicas 的数量重新创建一个新的 Pod 用于代替旧的不可用 Pod, 这样的自动运维就实现了"宕机恢复功能". 目前我是用的 minikube, 实际生产集群的话 新的Pod 可能会被分配到其它的 Node 物理机节点上 .

更新

更新这里讲滚动更新, 滚动更新是 deployment 的默认更新, 逐渐的替换旧的pod, 启动一个新的Pod 就会关掉一个旧的 Pod, 直到最后全部都替换成新的 Pod, 滚动更新就算完成.

老规矩, 进入到 minikube

查看 nginx 版本.说明在后面.



1.进入到 minikube 里面先查找 nginx 相关的容器, 因为我们用的是 docker, 所以使用 docker 命令查找, 找到4个 nginx 相关的容器, 但是yaml里面设置的 replicates 不是2个吗? 看这4行的信息, 有2行带有 pause, 这个是 pod 的根容器, 用来确认 Pod 代表状态的, 所以实际上我们的业务容器就只有2个.

2.进入其中一个nginx 容器, 使用 docker 命令

# 进入 docker 容器, ${container} 就是第一列的数据
docker exec -it ${container} /bin/bash

3.输出 nginx 容器的版本信息

# nginx 版本信息
nginx -v

这里输出是 nginx/1.19.2

滚动更新

deployment 更新的话, 默认是滚动更新, 就是逐个用新的 Pod 去替换旧的 Pod

接下来更新 deployment, 输入命令进入编辑

# 编辑 deployment
kubectl edit deployment.v1.apps/deployment-nginx

修改 image 为模拟的新版本 1.17.9 , wq 保存退出.

接下来查看 Pod 的状态

解读

1.刚保存(更新)的时候可以看到正在新建一个新的容器(Pod) (新建 5hd9c)

2.在新的容器(Pod)创建成功后, 停掉原来旧的容器(Pod) (停止 6ndvp)

3.其实接下来应该是看到另一个 Pod 也是类似上面步骤1、2的流程, 但由于过去的时间太久, 第三次查看, 新的容器已经全都创建成功了, 旧的都被删掉了, 最终呈现出2个新的 Pod(5hd9c 和 g4kt9).

到此, 更新 deployment 已经完成.

更新成功后查看 nginx 的版本.



可以看到 nginx 的版本已经变成了 1.17.9 , 代表此次更新已经成功了.

几个重要的参数

  • minReadySeconds : 这个参数控制在新的 Pod 启动后多久被认为是可用的, 被认为是可用之后才会开始停止掉旧的 Pod, 默认是0. 很多不像 nginx 这样秒开的进程, 在 Pod 启动后, 还需要执行启动 Pod 后的命令, 而这个命令往往是启动业务进程. 假如命令是执行一个 Java 进程, 像我们平时业务多一点的 Java 进程, 启动需要十几秒, 多的甚至需要几分钟(emm, 我的老古董mac就是..), 而 在 Pod 启动后, Java(业务) 进程启动完成前的这段时间里, 就是这个参数存在的意义, 为了让服务尽可能的不断供, 需要在新的 Java(业务)进程启动完之后, 再停止旧的 Pod, 才能达到服务不断, 所以这个参数设置的好 能一定程度上提高系统的可用性. (简单来说就是 Pod 启动完了不代表对应的业务进程启动完了)

  • minReplicasmaxReplicas : 这两个参数代表最小和最大的副本数量, 用于水平缩/扩容,水平缩/扩容 按照一定的规则进行,这个涉及到了另一个资源对象 HorizontalPodAutoscaler,所以暂时不过多的描述它.

  • 资源限制 resources.requestresources.limits : 这两个参数用于 Pod, CPU 和 内存。

    # 用于 Pod 的详细信息
    spec:
    containers:
    - name: pod-nginx
    image: nginx:latest
    resources:
    requests:
    memory: "50Mi" # 内存初始值 50M
    cpu: "1" # CPU初始值 1核
    limits:
    memory: "100Mi" # 最大 100M
    cpu: "2" # 最大 2核

回滚

**当更新的时候, 如果出现问题了, 需要进行回滚的话怎么办? **

下面就介绍出现问题的时候, 如何进行回滚.

  • 首先是执行回滚的命令
kubectl rollout undo deployment.v1.apps/deployment-nginx

下面是执行回滚后,直观上的体现

可以看到原来2个 "新的Pod" 也被主键的替换掉了, 由两个更新的 Pod 来替换。

验证一下是不是真的回滚成功了, 进入到 docker 容器内查看, 操作跟上面一样,就不重复了, 直接贴结果图



nginx 的版本变回了最开始的 1.19.2 版本, 证明 回滚成功了。

新建 Deployment 实现灰度发布

基于新建 Deployment 实现的灰度发布功能, 是基于不同的业务版本对应不同的 Deployment , 而这不同的 Deployment 管理的 Pod 的 labels 需要有与旧版本的 Pod 相同的 labels, 这样 svc 才能将它们都纳入管理范围, 并且此时的流量是均衡到每一个该 svc 上的 Pod上面, 根据 svc 自身的DNS轮询, 所以这里是 基于网络层面的 TCP/IP 层来实现流量划分.

如果想要实现一些其它更复杂的功能, 比如基于接口的灰度发布功能、根据请求头信息进行流量划分等, 则需要使用其它的组件, istio、ingress、springcloud 这一些

新建 Deployment

基于新建Deployment 实现的灰度发布, 需要每个版本都新建对应的 Deployment, 比如上面的Delpoyment 就可以修改它的内容, 然后使用 kubectl create -f 新建.

kubectl create -f deployment-new.yaml

# 新版本的 deployment-new.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-new-nginx
spec:
selector:
matchLabels:
name: label-pod-nginx # 将拥有 name=label-pod-nginx 的 pod 纳入管理范围
replicas: 2 # 2个 Pod 实例
template: # 容器(Pod) 模板
metadata:
labels:
name: label-pod-nginx # 跟上面的 matchLabels 对应,才能被上面配置的纳入管理
spec:
containers:
- name: pod-nginx
image: nginx:1.17.9 # 这里使用新版本的镜像, 进行新版发布
ports:
- containerPort: 80

总结

本篇介绍了Deployment 在 Kubernetes 平台中的作用, 它能提供一些自动化运维的功能, 有容器被关闭后 自动开启新的容器来继续提供服务 , 基于 新版 Deployment 的灰度发布(实际上用的比较少) , 更新后的回滚 等功能. 水平扩容的暂时没有过多的介绍, 因为我觉得它需要单独拿出来介(水)绍(文).

目前的容器都是 无状态Pod(容器), 也就是关闭重开后, 就是一个完全新的容器, 即使保存了数据, 下次重新创建 Pod 也不会使用之前已经持久化的数据. so, 下一篇的话, 准备介绍 Kubernetes 中的 有状态应用.

Kubernetes系列(三) Deployment的更多相关文章

  1. Kubernetes系列三:二进制安装Kubernetes环境

    安装环境: # 三个节点信息 192.168.31.11 主机名:env11 角色:部署Master节点/Node节点/ETCD节点 192.168.31.12 主机名:env12 角色:部署Node ...

  2. 【Kubernetes 系列三】Kubernetes 学习文档推荐

    标题 地址 备注 Kubernetes 官方文档 https://kubernetes.io/docs 英文文档,全面 Kubernetes Handbook ttps://jimmysong.io/ ...

  3. Kubernetes系列(五) Ingress

    作者: LemonNan 原文地址: https://juejin.im/post/6878269825639317517 Kubernetes 系列 Kubernetes系列(一) Pod Kube ...

  4. Kubernetes系列(四) StatefulSet

    作者: LemonNan 原文地址: https://juejin.im/post/6870071267438329869 Kubernetes系列(四) StatefulSet Kubernetes ...

  5. kubernetes系列之ConfigMap使用方式

    作用理解 核心用途就是容器和配置的分离解耦. 如启用一个mysql容器,mysql容器重要的文件有两部分,一部分为存储数据文件,一部分为配置文件my.cnf,存储数据可以用持久存储实现和容器的分离解耦 ...

  6. Kubernetes 系列(四):使用Traefik访问.net core api

    一. 准备 本篇的要求是在前三篇的基础上已经搭建好的本地k8s以及部署了Traefik,我们将会使用Traefik Ingress来访问.net core api,比较简单,做个记录,如果还没有搭建k ...

  7. Istio的流量管理(实操一)(istio 系列三)

    Istio的流量管理(实操一)(istio 系列三) 使用官方的Bookinfo应用进行测试.涵盖官方文档Traffic Management章节中的请求路由,故障注入,流量迁移,TCP流量迁移,请求 ...

  8. 从0到1使用Kubernetes系列(七):网络

    本文是从 0 到 1 使用 Kubernetes 系列第七篇,上一篇<从 0 到 1 使用 Kubernetes 系列(六):数据持久化实战> 介绍了 Kubernetes 中的几种常用储 ...

  9. Kubernetes系列之Helm介绍篇

    本次系列使用的所需部署包版本都使用的目前最新的或最新稳定版,安装包地址请到公众号内回复[K8s实战]获取 介绍 Helm 是 Deis 开发的一个用于 Kubernetes 应用的包管理工具,主要用来 ...

随机推荐

  1. 关于Java的=赋值操作和方法传递对象时的引用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11405920.html 下面通过一段代码和debug结果来展示Java中=操作的赋值改变过程. ...

  2. Apache——网页优化与安全

    Apache--网页优化与安全 1.Apache 网页优化概述 2.网页压缩 3.网页缓存 4.隐藏版本信息 5.Apache 防盗链 1.Apache 网页优化概述: 企业中,部署Apache后只采 ...

  3. 「游记」CSP-S 2021 爆零记

    推荐访问本人自建博客 \(\text{cjwen.top}\) 初赛 之前参加过「难度介于 J 组(基础组)和 S 组(提高组)之间」的 [LGR-(-13) ]SCP 2021 第一轮(初赛)模拟, ...

  4. Ansible playbook实现apache批量部署,并对不同主机提供以各自IP地址为内容的index.html

    1.基于key验证免密授权 1.1 生成kekgen # ssh-keygen Generating public/private rsa key pair. Enter file in which ...

  5. 教你用Elastic Search:运行第一条Hello World搜索命令

    摘要:Elastic Search可实时对数据库进行全文检索.处理同义词.从同样的数据中生成分析和聚合数据. 本文分享自华为云社区<Elastic Search入门(一): 简介,安装,运行第一 ...

  6. Solution -「CF 1025D」Recovering BST

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\),问是否存在一棵二叉搜索树,使得其中序遍历为 \(\{a_n\}\),且相邻接的两点不互素.   ...

  7. C#动态规划法计算文本相似度

    C# 采用动态规划算法,计算两个字符串之间的相似程度. public static double CountTextSimilarity(string textX, string textY, boo ...

  8. Jenkins系列之pipeline语法介绍与案例

    Jenkins Pipeline 的核心概念: Pipeline 是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化. ...

  9. vivo 服务端监控架构设计与实践

    一.业务背景 当今时代处在信息大爆发的时代,信息借助互联网的潮流在全球自由的流动,产生了各式各样的平台系统和软件系统,越来越多的业务也会导致系统的复杂性. 当核心业务出现了问题影响用户体验,开发人员没 ...

  10. 『无为则无心』Python面向对象 — 52、私有成员方法(类中行为的封装)

    Python对于类的成员没有严格的访问控制限制,这与其他面向对象的编程语言是有所区别的. 关于私有方法其实和私有属性差不多,有如下要点: 1.通常我们约定,两个下划线开头的方法是私有方法. 2.类内部 ...