前言
在 Kubernetes 集群中,通过陈述式和声明式资源管理是确保应用程序高效运行的关键。认识这两种管理方法,能够更好地掌握 Kubernetes 集群的运维和管理。
目录
[一、K8s 资源管理操作分类](#一、K8s 资源管理操作分类)
[1. 陈述式](#1. 陈述式)
[2. 声明式](#2. 声明式)
[3. K8s 集群管理常用命令概览](#3. K8s 集群管理常用命令概览)
[二、 kubectl 命令实例](#二、 kubectl 命令实例)
[1. 基本信息查看](#1. 基本信息查看)
[1.1 基本格式](#1.1 基本格式)
[1.2 查看 master 节点状态](#1.2 查看 master 节点状态)
[1.3 查看命名空间](#1.3 查看命名空间)
[1.4 查看 default 命名空间的所有资源](#1.4 查看 default 命名空间的所有资源)
[1.5 创建命名空间 fql](#1.5 创建命名空间 fql)
[1.6 删除命名空间](#1.6 删除命名空间)
[1.7 在命名空间 fql 创建副本控制器(deployment)来启动Pod(nginx-01)](#1.7 在命名空间 fql 创建副本控制器(deployment)来启动Pod(nginx-01))
[1.8 描述资源的详细信息](#1.8 描述资源的详细信息)
[1.9 查看命名空间 fql 中的 pod 信息](#1.9 查看命名空间 fql 中的 pod 信息)
[1.10 登录容器](#1.10 登录容器)
[1.11 删除(重启)pod 资源](#1.11 删除(重启)pod 资源)
[1.12 扩缩容](#1.12 扩缩容)
[1.13 删除副本控制器](#1.13 删除副本控制器)
[1. 创建 kubectl create 命令](#1. 创建 kubectl create 命令)
[2. 发布 kubectl expose 命令](#2. 发布 kubectl expose 命令)
[2.1 将资源暴露为新的 Service](#2.1 将资源暴露为新的 Service)
[2.1.1 Kubernetes 之所以需要 Service](#2.1.1 Kubernetes 之所以需要 Service)
[2.1.2 service 的 type 类型](#2.1.2 service 的 type 类型)
[2.1.3 无头模式 headless clusterIP](#2.1.3 无头模式 headless clusterIP)
[2.1.4 端口类型](#2.1.4 端口类型)
[2.2 查看 pod 网络状态详细信息和 Service 暴露的端口](#2.2 查看 pod 网络状态详细信息和 Service 暴露的端口)
[2.3 查看关联后端的节点](#2.3 查看关联后端的节点)
[2.4 查看 service 的描述信息](#2.4 查看 service 的描述信息)
[2.5 查看负载均衡端口](#2.5 查看负载均衡端口)
[3. 更新版本 kubectl set](#3. 更新版本 kubectl set)
[3.1 查看当前 nginx 的版本号](#3.1 查看当前 nginx 的版本号)
[3.2 获取修改模板](#3.2 获取修改模板)
[3.3 滚动更新](#3.3 滚动更新)
[4. 回滚 kubectl rollout](#4. 回滚 kubectl rollout)
[4.1 查看回滚指令帮助说明](#4.1 查看回滚指令帮助说明)
[4.2 查看历史版本](#4.2 查看历史版本)
[4.3 执行回滚到上一个版本](#4.3 执行回滚到上一个版本)
[4.4 执行回滚到指定版本](#4.4 执行回滚到指定版本)
[4.5 检查回滚状态](#4.5 检查回滚状态)
[5. 删除 kubectl delete](#5. 删除 kubectl delete)
[5.1 删除副本控制器](#5.1 删除副本控制器)
[5.2 删除 service](#5.2 删除 service)
[6. 金丝雀发布(灰度发布)](#6. 金丝雀发布(灰度发布))
[6.1 更新 deployment 的版本,并配置暂停 deployment](#6.1 更新 deployment 的版本,并配置暂停 deployment)
[6.2 开启另一个窗口查看 pod 信息](#6.2 开启另一个窗口查看 pod 信息)
[6.3 确保更新的 pod 没问题,继续更新](#6.3 确保更新的 pod 没问题,继续更新)
[6.4 查看最后的更新情况](#6.4 查看最后的更新情况)
[6.5 分阶段访问](#6.5 分阶段访问)
[7. 蓝绿发布](#7. 蓝绿发布)
[8. 发布方式总结](#8. 发布方式总结)
一、K8s 资源管理操作分类
1. 陈述式
通过 kubectl 命令的方式来实现对资源进行管理,简而言之,就是通过一条命令来实现操作,如查看节点信息等;对资源的增、删、查操作比较方便,但对改的操作就不容易了。
kubectl 是官方的 CLI 命令行工具,用于与 apiserver 进行通信,将用户在命令行输入的命令,组织并转化为 apiserver 能识别的信息,进而实现管理 k8s 各种资源的一种有效途径。
kubectl 的命令大全
k8s中文文档:Kubernetes kubectl 命令表 _ Kubernetes(K8S)中文文档_Kubernetes中文社区
2. 声明式
通过使用 yaml 或 josn 文件对资源配置,然后再实现对资源的管理。
3. K8s 集群管理常用命令概览
① 查看版本信息
bash
[root@master01 ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.11", GitCommit:"27522a29febbcc4badac257763044d0d90c11abd", GitTreeState:"clean", BuildDate:"2021-09-15T19:21:44Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.11", GitCommit:"27522a29febbcc4badac257763044d0d90c11abd", GitTreeState:"clean", BuildDate:"2021-09-15T19:16:25Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
② 查看资源对象简写
bash
[root@master01 ~]# kubectl api-resources
③ 查看集群信息
bash
[root@master01 ~]# kubectl cluster-info
Kubernetes control plane is running at https://192.168.190.100:6443
KubeDNS is running at https://192.168.190.100:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
④ 配置 kubectl 自动补全
bash
[root@master01 ~]# source <(kubectl completion bash)
⑤ node 节点查看日志
bash
[root@node01 ~]# journalctl -u kubelet -f
-- Logs begin at 四 2024-05-16 14:11:00 CST. --
5月 16 23:10:52 node01 kubelet[40583]: I0516 23:10:52.598264 40583 topology_manager.go:187] [topologymanager] Topology Admit Handler
5月 16 23:10:52 node01 kubelet[40583]: I0516 23:10:52.722290 40583 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "default-token-n27bv" (UniqueName: "kubernetes.io/secret/7df6ee9c-aca5-4195-8611-43684869cee9-default-token-n27bv") pod "nginx-deployment-7dc776dfc6-nt2px" (UID: "7df6ee9c-aca5-4195-8611-43684869cee9")
错误日志实例:
bash
节点 192.168.190.102 的 kubelet 服务无法更新节点状态,因为无法连接到 192.168.190.200:6443:
[root@node01 ~]# journalctl -f -u kubelet.service
-- Logs begin at 一 2024-05-13 10:23:14 CST. --
5月 16 10:53:04 node01 kubelet[59283]: E0516 10:53:04.821047 59283 kubelet_node_status.go:470] Error updating node status, will retry: error getting node "192.168.190.102": Get "https://192.168.190.200:6443/api/v1/nodes/192.168.190.102?timeout=10s": dial tcp 192.168.190.200:6443: connect: no route to host
5月 16 10:53:07 node01 kubelet[59283]: E0516 10:53:07.825185 59283 kubelet_node_status.go:470] Error updating node status, will retry: error getting node "192.168.190.102": Get "https://192.168.190.200:6443/api/v1/nodes/192.168.190.102?timeout=10s": dial tcp 192.168.190.200:6443: connect: no route to host
# journalctl: 是 Systemd 系统日志查询工具,用于查看和管理 systemd 初始化系统产生的日志。
# -f: 参数表示跟随模式,即在终端上持续显示新的日志条目,这对于监视服务的实时运行状况非常有用。
# -u kubelet.service: 指定查看 kubelet.service 这个 Systemd 单元的服务日志。kubelet 是 Kubernetes 的核心组件之一,负责在每个节点上运行容器,管理 pod 状态并与 Kubernetes 主控进行通信。
二、 kubectl 命令实例
1. 基本信息查看
1.1 基本格式
bash
获取资源的相关信息:
kubectl get <resource> [-o wide|json|yaml] [-n namespace]
# -n 指定命令空间
# -o 指定输出格式
# resource可以是具体资源名称,如:pod nginx-xxx;也可以是资源类型,如pod:或者all等
# --all-namespaces 或 -A:表示显示所有命令空间
# --show-labels:显示所有标签
# -l app:仅显示标签为app的资源
# -l app=nginx:仅显示包含app标签,且值为nginx的资源
1.2 查看 master 节点状态
bash
[root@master01 ~]# kubectl get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
简写:
kubectl get cs
1.3 查看命名空间
在 K8s 中,命名空间(Namespace)是用来将集群中的资源进行逻辑隔离的一种方式。通过命名空间,可以将集群中的资源划分为不同的逻辑单元,允许不同命名空间相同类型的资源重名。
bash
[root@master01 ~]# kubectl get namespaces 简写:kubectl get ns
NAME STATUS AGE
default Active 22h # 默认空间
kube-flannel Active 21h
kube-node-lease Active 22h
kube-public Active 22h
kube-system Active 22h
kubernetes-dashboard Active 20h
[root@master01 ~]# kubectl get pod -n kube-flannel
# 获取命名空间kube-flannel中的所有Pod资源的信息
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-bctwm 1/1 Running 1 21h
kube-flannel-ds-w8zmz 1/1 Running 0 21h
kube-flannel-ds-wz8p2 1/1 Running 3 21h
[root@master01 ~]# kubectl get pod -n kube-flannel -o wide
# -o wide参数来显示更多关于Pod资源的详细信息,包括IP地址、Node名称、状态等
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-bctwm 1/1 Running 1 21h 192.168.190.102 node02 <none> <none>
kube-flannel-ds-w8zmz 1/1 Running 0 22h 192.168.190.100 master01 <none> <none>
kube-flannel-ds-wz8p2 1/1 Running 3 21h 192.168.190.101 node01 <none> <none>
[root@master01 ~]# kubectl get node
# 获取所有Node资源的信息
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,master 23h v1.20.11
node01 Ready <none> 21h v1.20.11
node02 Ready <none> 21h v1.20.11
注意:
- 在Kubernetes中,Node资源是全局资源,不属于任何特定的命名空间
- 无论是否使用-n kube-flannel参数,获取Node资源的信息都将是相同的
- 因为Node资源是集群级别的资源,而不是特定于某个命名空间的资源
1.4 查看 default 命名空间的所有资源
bash
格式:
kubectl get all [-n default]
[root@master01 ~]# kubectl get all -n kube-flannel
NAME READY STATUS RESTARTS AGE
pod/kube-flannel-ds-bctwm 1/1 Running 1 21h
pod/kube-flannel-ds-w8zmz 1/1 Running 0 22h
pod/kube-flannel-ds-wz8p2 1/1 Running 3 21h
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/kube-flannel-ds 3 3 3 3 3 <none> 22h
# 这个DaemonSet的期望副本数(DESIRED)是3
# 当前副本数(CURRENT)是3
# 所有的副本都处于Ready状态(READY=3)并且都是最新版本(UP-TO-DATE=3)
# 所有的副本都是可用的(AVAILABLE=3)
# 这个DaemonSet没有指定Node选择器(NODE SELECTOR为)
1.5 创建命名空间 fql
bash
[root@master01 ~]# kubectl create ns fql
namespace/fql created
[root@master01 ~]# kubectl get ns | grep fql
fql Active 7s
1.6 删除命名空间
bash
格式:
kubectl delete namespace <namespace_name>
kubectl delete ns <namespace_name>
注意:
删除命名空间将删除该命名空间中的所有资源,包括Pods、Services、Deployments等
Deployment是Kubernetes中用于管理Pod部署和更新的重要资源对象
1.7 在命名空间 fql 创建副本控制器(deployment)来启动Pod(nginx-01)
bash
[root@master01 ~]# kubectl create deployment nginx-01 --image=nginx -n fql
deployment.apps/nginx-01 created
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 57s
1.8 描述资源的详细信息
bash
描述位于fql命名空间中,名为nginx-01的Deployment资源对象的详细信息:
[root@master01 ~]# kubectl describe deployment nginx-01 -n fql
描述位于fql命名空间中,名为nginx-01-796cd9986d-7j8kd的Pod资源对象的详细信息:
[root@master01 ~]# kubectl describe pod nginx-01-796cd9986d-7j8kd -n fql
查看具有标签app=nginx-01的所有Pod的日志信息,这些Pod位于fql命名空间中:
[root@master01 ~]# kubectl logs -l app=nginx-01 -n fql
查看名为nginx-01-796cd9986d-7j8kd的特定Pod的日志信息,该Pod位于fql命名空间中:
[root@master01 ~]# kubectl logs nginx-01-796cd9986d-7j8kd -n fql
1.9 查看命名空间 fql 中的 pod 信息
bash
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 69m
1.10 登录容器
kubectl exec 可以跨主机登录容器,docker exec 只能在容器所在主机上登录
bash
[root@master01 ~]# kubectl exec -it nginx-01-796cd9986d-7j8kd -n fql bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-01-796cd9986d-7j8kd:/# exit
exit
1.11 删除(重启)pod 资源
由于存在 deployment/rc 之类的副本控制器,删除 pod 也会重新拉起来
bash
创建pod副本:
[root@master01 ~]# kubectl create deployment nginx-02 --image=nginx -n fql --replicas=3
deployment.apps/nginx-02 created
查看pod状态:
[root@master01 ~]# kubectl get pod -o wide -n fql
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h 10.244.2.7 node02 <none> <none>
nginx-02-5d68d7dd6c-7dwk4 1/1 Running 0 2m6s 10.244.2.8 node02 <none> <none>
nginx-02-5d68d7dd6c-kq2bn 1/1 Running 0 2m6s 10.244.1.13 node01 <none> <none>
nginx-02-5d68d7dd6c-rg9np 1/1 Running 0 2m6s 10.244.1.12 node01 <none> <none>
删除一个pod,再次查看 pod ip 信息:
[root@master01 ~]# kubectl delete pod nginx-02-5d68d7dd6c-rg9np -n fql
pod "nginx-02-5d68d7dd6c-rg9np" deleted
[root@master01 ~]# kubectl get pod -o wide -n fql
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h 10.244.2.7 node02 <none> <none>
nginx-02-5d68d7dd6c-7dwk4 1/1 Running 0 3m25s 10.244.2.8 node02 <none> <none>
nginx-02-5d68d7dd6c-kkbd5 1/1 Running 0 28s 10.244.2.9 node02 <none> <none>
nginx-02-5d68d7dd6c-kq2bn 1/1 Running 0 3m25s 10.244.1.13 node01 <none> <none>
若 pod 无法删除,总是处于 terminate 状态,则要强行删除 pod
bash
kubectl delete pod <pod-name> -n <namespace> --force --grace-period=0
# grace-period表示过渡存活期,默认30s,在删除pod之前允许POD慢慢终止其上的容器进程,从而优雅退出
# 0表示立即终止pod
1.12 扩缩容
扩容:
bash
[root@master01 ~]# kubectl scale deployment nginx-01 --replicas=2 -n fql
deployment.apps/nginx-01 scaled
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h
nginx-01-796cd9986d-c98q2 1/1 Running 0 18s
nginx-02-5d68d7dd6c-7dwk4 1/1 Running 0 13m
nginx-02-5d68d7dd6c-kkbd5 1/1 Running 0 10m
nginx-02-5d68d7dd6c-kq2bn 1/1 Running 0 13m
缩容:
bash
[root@master01 ~]# kubectl scale deployment nginx-02 --replicas=1 -n fql
deployment.apps/nginx-02 scaled
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h
nginx-01-796cd9986d-c98q2 1/1 Running 0 48s
nginx-02-5d68d7dd6c-kq2bn 1/1 Running 0 14m
1.13 删除副本控制器
删除副本控制器将同时删除由该副本控制器管理的所有Pod副本
bash
[root@master01 ~]# kubectl delete deployment nginx-02 -n fql
deployment.apps "nginx-02" deleted
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h
nginx-01-796cd9986d-c98q2 1/1 Running 0 2m28s
nginx-02-5d68d7dd6c-kq2bn 0/1 Terminating 0 16m # 正在被删除
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-796cd9986d-7j8kd 1/1 Running 0 3d3h
nginx-01-796cd9986d-c98q2 1/1 Running 0 3m43s
三、项目的生命周期
Kubernetes 项目的生命周期包括设计、开发、部署、运行和维护等阶段。在设计和开发阶段,需要定义应用程序的架构和容器镜像,以及创建 Kubernetes 资源对象。在部署和运行阶段,需要使用 kubectl 命令将应用程序部署到 Kubernetes 集群中,并进行监控和维护。即:创建-->发布-->更新-->回滚-->删除。
1. 创建 kubectl create 命令
- 创建并运行一个或多个容器镜像
- 创建一个 deployment 或 job 来管理容器
启动 nginx 实例,暴露容器端口 80,设置副本数 3
bash
[root@master01 ~]# kubectl create deployment nginx-01 --image=nginx:1.14 --port=80 --replicas=3 -n fql
deployment.apps/nginx-01 created
[root@master01 ~]# kubectl get pod -o wide -n fql
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-799fb6fb65-296dl 1/1 Running 0 24s 10.244.1.18 node01 <none> <none>
nginx-01-799fb6fb65-jhqt2 1/1 Running 0 24s 10.244.1.19 node01 <none> <none>
nginx-01-799fb6fb65-kqbc2 1/1 Running 0 24s 10.244.2.13 node02 <none> <none>
2. 发布 kubectl expose 命令
2.1 将资源暴露为新的 Service
为 deployment 的 nginx 创建 service,并通过 Service 的80端口转发至容器的80端口上,Service的名称为 nginx-service,类型为 NodePort。
bash
[root@master01 ~]# kubectl expose deployment nginx-01 -n fql --port=80 --target-port=80 --name=nginx-server --type=NodePort
service/nginx-server exposed
2.1.1 Kubernetes 之所以需要 Service
- 一方面是因为 Pod 的 IP 不是固定的(Pod可能会重建)
- 另一方面则是因为一组 Pod 实例之间总会有负载均衡的需求
- 对于容器应用而言,Kubernetes 提供了基于 VIP(虚拟IP) 的网桥的方式访问 Service,再由 Service 重定向到相应的 Pod
2.1.2 service 的 type 类型
- ClusterIP:提供一个集群内部的虚拟IP以供Pod访问(service默认类型)
- NodePort:在每个Node上打开一个端口以供外部访问,Kubernetes将会在每个Node上打开一个端口并且每个Node的端口都是一样的,通过 NodeIp:NodePort 的方式Kubernetes集群外部的程序可以访问Service
- 每个端口只能是一种服务,端口范围只能是 30000-32767
- LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置Service的场景。通过外部的负载均衡器来访问,通常在云平台部署LoadBalancer还需要额外的费用
- 在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端
- externalName:将service名称映射到一个DNS域名上,相当于DNS服务的CNAME记录,用于让Pod去访问集群外部的资源,它本身没有绑定任何的资源。 tgc.benet.com www.benet.com
2.1.3 无头模式 headless clusterIP
- 是Kubernetes中一种特殊类型的服务,它不会为服务创建ClusterIP,而是直接将DNS解析指向服务的每个Pod的IP地址。这种模式适用于需要直接与每个Pod进行通信的场景,而不需要负载均衡或代理。
2.1.4 端口类型
① port
- port 是 k8s 集群内部访问 service 的端口,即通过 clusterIP: port 可以从 Pod 所在的 Node 上访问到 service(四层)
② nodePort
- nodePort 是外部访问 k8s 集群中 service 的端口,通过 nodeIP: nodePort 可以从外部访问到某个 service
③ targetPort
- targetPort 是 Pod 的端口,从 port 或 nodePort 来的流量经过 kube-proxy 反向代理负载均衡转发到后端 Pod 的 targetPort 上,最后进入容器
④ containerPort
- containerPort 是 Pod 内部容器的端口,targetPort 映射到 containerPort
2.2 查看 pod 网络状态详细信息和 Service 暴露的端口
bash
[root@master01 ~]# kubectl get pod,svc -o wide -n fql
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-01-799fb6fb65-296dl 1/1 Running 0 90s 10.244.1.18 node01 <none> <none>
pod/nginx-01-799fb6fb65-jhqt2 1/1 Running 0 90s 10.244.1.19 node01 <none> <none>
pod/nginx-01-799fb6fb65-kqbc2 1/1 Running 0 90s 10.244.2.13 node02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/nginx-server NodePort 10.96.153.145 <none> 80:32591/TCP 32s app=nginx-01
使用客户端浏览器访问任意一个节点ip的32591端口,都可以访问到nginx的pod实例
bash
[root@master01 ~]# curl 192.168.190.101:32591
<title>Welcome to nginx!</title>
[root@master01 ~]# curl 192.168.190.102:32591
<title>Welcome to nginx!</title>
2.3 查看关联后端的节点
bash
[root@master01 ~]# kubectl get endpoints -n fql
NAME ENDPOINTS AGE
nginx-server 10.244.1.18:80,10.244.1.19:80,10.244.2.13:80 75s
2.4 查看 service 的描述信息
bash
[root@master01 ~]# kubectl describe svc nginx -n fql
Name: nginx-server # Service的名称为nginx-server
Namespace: fql # Service位于fql命名空间中
Labels: app=nginx-01 # Service的标签为app=nginx-01
Annotations: <none> # Service没有任何注释信息
Selector: app=nginx-01 # Service通过标签选择器app=nginx-01选择与之匹配的Pod
Type: NodePort # Service的类型为NodePort,表示将Service暴露到集群外部,并使用Node的IP地址和端口号来访问Service
IP Families: <none> # Service没有指定IP地址族
IP: 10.96.153.145 # Service的IP地址为10.96.153.145
IPs: 10.96.153.145 # Service的IP地址为10.96.153.145
Port: <unset> 80/TCP # Service暴露的端口号为80,使用TCP协议
TargetPort: 80/TCP # Service将请求转发到Pod的端口号为80,使用TCP协议
NodePort: <unset> 32591/TCP # Service将使用Node的IP地址和端口号32591来暴露Service,使用TCP协议
Endpoints: 10.244.1.18:80,10.244.1.19:80,10.244.2.13:80 # Service的后端是3个Pod
Session Affinity: None # Service没有启用会话亲和性
External Traffic Policy: Cluster # Service的外部流量策略为Cluster
Events: <none> # Service没有任何事件记录
2.5 查看负载均衡端口
node01 节点上操作
bash
[root@node01 ~]# yum install ipvsadm -y
[root@node01 ~]# ipvsadm -Ln
TCP 172.17.0.1:32591 rr
-> 10.244.1.18:80 Masq 1 0 0
-> 10.244.1.19:80 Masq 1 0 0
-> 10.244.2.13:80 Masq 1 0 0
# docker网桥
TCP 192.168.190.101:32591 rr
-> 10.244.1.18:80 Masq 1 0 0
-> 10.244.1.19:80 Masq 1 0 0
-> 10.244.2.13:80 Masq 1 0 1
# 外部访问的ip和端口
TCP 10.96.153.145:80 rr
-> 10.244.1.18:80 Masq 1 0 0
-> 10.244.1.19:80 Masq 1 0 0
-> 10.244.2.13:80 Masq 1 0 0
# pod集群组内部访问的ip和端口
在 node02 节点上操作,同样方式也可以查看负载均衡端口
修改各pod访问界面为自定义界面:
bash
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-799fb6fb65-296dl 1/1 Running 0 28m
nginx-01-799fb6fb65-jhqt2 1/1 Running 0 28m
nginx-01-799fb6fb65-kqbc2 1/1 Running 0 28m
[root@master01 ~]# kubectl exec -it nginx-01-799fb6fb65-296dl bash -n fql
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-01-799fb6fb65-296dl:/# echo web01 > /usr/share/nginx/html/index.html
[root@master01 ~]# kubectl exec -it nginx-01-799fb6fb65-jhqt2 bash -n fql
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-01-799fb6fb65-jhqt2:/# echo web02 > /usr/share/nginx/html/index.html
[root@master01 ~]# kubectl exec -it nginx-01-799fb6fb65-kqbc2 bash -n fql
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-01-799fb6fb65-kqbc2:/# echo web03 > /usr/share/nginx/html/index.html
验证负载均衡:
bash
[root@master01 ~]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server NodePort 10.96.153.145 <none> 80:32591/TCP 30m
[root@master01 ~]# curl 10.96.153.145
web03
[root@master01 ~]# curl 10.96.153.145
web02
[root@master01 ~]# curl 10.96.153.145
web01
3. 更新版本 kubectl set
Kubernetes 更新版本通常会涉及 kubectl set 命令的功能改进和参数扩展,以便更方便地管理和更新资源的字段,如扩展副本数量、更改镜像标签等。
3.1 查看当前 nginx 的版本号
bash
[root@master01 ~]# curl 10.96.153.145 -I
Server: nginx/1.14.2
3.2 获取修改模板
bash
[root@master01 ~]# kubectl set image --help
Examples:
# Set a deployment's nginx container image to 'nginx:1.9.1', and its busybox
container image to 'busybox'.
kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
3.3 滚动更新
将nginx 版本更新为 1.15 版本
bash
[root@master01 ~]# kubectl set image deployment/nginx-01 nginx=nginx:1.15 -n fql
deployment.apps/nginx-01 image updated
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-78cb4c6b78-2h46w 1/1 Running 0 28s
nginx-01-78cb4c6b78-fwvkv 0/1 ContainerCreating 0 10s
nginx-01-799fb6fb65-jhqt2 1/1 Running 0 41m
nginx-01-799fb6fb65-kqbc2 1/1 Running 0 41m
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-78cb4c6b78-2h46w 1/1 Running 0 55s
nginx-01-78cb4c6b78-2ldxl 1/1 Running 0 7s
nginx-01-78cb4c6b78-fwvkv 1/1 Running 0 37s
nginx-01-799fb6fb65-jhqt2 0/1 Terminating 0 41m
......
......
处于动态监听 pod 状态,由于使用的是滚动更新方式,所以会先生成一个新的pod,然后删除一个旧的pod,往后依次类推:
kubectl get pods -w
# 更新好后的Pod的ip会改变
[root@master01 ~]# curl 10.96.153.145 -I
Server: nginx/1.15.12
- 首先在确保正常提供服务的情况下,在三个 pod 实例正常运行的情况下,生成一个新的指定版本的 pod 实例
- 等到新的 pod 实例创建成功后并验证可用性,会删除第一个 pod 实例
- 而后再生成第二个新版本的 pod 实例,再删除第二个,依此类推,一直到该 deployment 下的所有 pod 资源全部升级完毕
需要注意的是,资源更新后,其原本 pod 实例中的数据并不会被继承。如果有需要的话,可以先对数据进行备份,等到升级完毕后,再同步数据。
4. 回滚 kubectl rollout
Kubernetes 中的回滚操作通常使用 kubectl rollout 命令,该命令允许用户回退到先前的部署版本,同时保留集群的稳定性。这包括查看历史记录、回滚到特定版本以及监视回滚过程。
4.1 查看回滚指令帮助说明
bash
kubectl rollout --help
4.2 查看历史版本
bash
[root@master01 ~]# kubectl rollout history deployment/nginx-01 -n fql
deployment.apps/nginx-01
REVISION CHANGE-CAUSE
1 <none>
2 <none>
REVISION #显示历史中的每个版本,最多记录三次
CHANGE-CAUSE #显示触发该版本变更的原因。显示为 <none>,表示没有明确的变更原因被记录
# Kubernetes本身不会自动为每次Deployment的更新填充CHANGE-CAUSE字段。
# 这个字段通常是通过设置 Deployment 的注解(annotation)来填充的
# 特别是 kubernetes.io/change-cause 这个注解。
4.3 执行回滚到上一个版本
bash
[root@master01 ~]# kubectl rollout undo deployment/nginx-01 -n fql
deployment.apps/nginx-01 rolled back
4.4 执行回滚到指定版本
bash
格式:
kubectl rollout undo deployment/nginx --to-revision=1
# 将名为nginx的部署回滚到版本1,即撤销最近的更改并还原到特定的先前版本。
4.5 检查回滚状态
bash
[root@master01 ~]# kubectl rollout status deployment/nginx-01 -n fql
deployment "nginx-01" successfully rolled out
[root@master01 ~]# curl 10.96.153.145 -I
Server: nginx/1.14.2
5. 删除 kubectl delete
kubectl delete 命令用于删除 Kubernetes 集群中的资源,可以是 pod、service、deployment 等。用户可以通过指定资源类型和名称来删除特定的资源,也可以使用标签选择器来批量删除符合条件的资源。
5.1 删除副本控制器
bash
[root@master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-7dc776dfc6-4vm79 1/1 Running 0 60m
nginx-deployment-7dc776dfc6-b7qvn 1/1 Running 0 60m
nginx-deployment-7dc776dfc6-lzzvb 1/1 Running 0 60m
[root@master01 ~]# kubectl delete deployment nginx-deployment
deployment.apps "nginx-deployment" deleted
5.2 删除 service
bash
[root@master01 ~]# kubectl get service -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server NodePort 10.96.153.145 <none> 80:32591/TCP 60m
[root@master01 ~]# kubectl delete service nginx-server -n fql
service "nginx-server" deleted
6. 金丝雀发布(灰度发布)
Deployment 控制器支持自定义控制更新过程中的滚动节奏,如"暂停(pause)"或"继续(resume)"更新操作。
- 比如等待第一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本;
- 然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行;
- 确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。
准备工作:
bash
[root@master01 ~]# kubectl delete deployments.apps nginx-01 -n fql
# 删除名为"nginx-01"的部署(Deployment)在命名空间(Namespace)"fql"中的实例
[root@master01 ~]# kubectl delete svc nginx
[root@master01 ~]# kubectl delete svc nginx-deployment
[root@master01 ~]# kubectl delete svc nginx-service -n fql
# 删除 Kubernetes 集群中的服务(Service)
[root@master01 ~]# kubectl create deployment nginx-01 --image=nginx:1.14 --port=80 --replicas=3 -n fql
deployment.apps/nginx-01 created
[root@master01 ~]# kubectl get pod -o wide -n fql
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-799fb6fb65-7c29k 1/1 Running 0 15s 10.244.1.23 node01 <none> <none>
nginx-01-799fb6fb65-b6dvg 1/1 Running 0 15s 10.244.1.24 node01 <none> <none>
nginx-01-799fb6fb65-k2dlz 1/1 Running 0 15s 10.244.2.23 node02 <none> <none>
# 创建了一个名为nginx-01的部署(Deployment),使用了nginx:1.14镜像,并将容器的端口设置为80,创建三个副本
[root@master01 ~]# kubectl expose deployment nginx-01 --port=80 --target-port=80 --name=nginx-service -n fql --type=NodePort
service/nginx-service exposed
[root@master01 ~]# kubectl get svc -n fql -o wide
[root@master01 ~]# kubectl get svc -n fql -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 11s app=nginx-01
[root@master01 ~]# curl -I 10.96.128.93
Server: nginx/1.14.2
6.1 更新 deployment 的版本,并配置暂停 deployment
bash
[root@master01 ~]# kubectl set image deployment nginx-01 nginx=nginx:1.15 -n fql && kubectl rollout pause deployment nginx-01 -n fql
deployment.apps/nginx-01 image updated
deployment.apps/nginx-01 paused
[root@master01 ~]# kubectl rollout status deployment nginx-01 -n fql
Waiting for deployment "nginx-01" rollout to finish: 1 out of 3 new replicas have been updated...
# 更新名为"nginx-01"的部署(Deployment)中的 "nginx" 容器的镜像版本为"nginx:1.15
# 暂停名为"nginx-01"的部署的滚动更新,这意味着在执行这个命令后,将不会继续推进新的副本集,并且当前的副本集将保持不变
6.2 开启另一个窗口查看 pod 信息
监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了 pause 暂停命令
bash
[root@master01 ~]# kubectl get pods -w -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-78cb4c6b78-w6s2l 1/1 Running 0 31s
nginx-01-799fb6fb65-7c29k 1/1 Running 0 2m21s
nginx-01-799fb6fb65-b6dvg 1/1 Running 0 2m21s
nginx-01-799fb6fb65-k2dlz 1/1 Running 0 2m21s
# -w 选项,它会使命令进入监视模式,实时显示资源的变化情况
查看 nginx 版本信息:
bash
[root@master01 ~]# kubectl get pod -n fql -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-78cb4c6b78-w6s2l 1/1 Running 0 106s 10.244.2.24 node02 <none> <none>
nginx-01-799fb6fb65-7c29k 1/1 Running 0 3m36s 10.244.1.23 node01 <none> <none>
nginx-01-799fb6fb65-b6dvg 1/1 Running 0 3m36s 10.244.1.24 node01 <none> <none>
nginx-01-799fb6fb65-k2dlz 1/1 Running 0 3m36s 10.244.2.23 node02 <none> <none>
[root@master01 ~]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 3m12s
[root@master01 ~]# curl -I 10.244.2.24
Server: nginx/1.15.12
[root@master01 ~]# curl -I 10.244.1.23
Server: nginx/1.14.2
[root@master01 ~]# curl -I 10.244.1.24
Server: nginx/1.14.2
[root@master01 ~]# curl -I 10.244.2.23
Server: nginx/1.14.2
6.3 确保更新的 pod 没问题,继续更新
bash
[root@master01 ~]# kubectl rollout resume deployment nginx-01 -n fql
deployment.apps/nginx-01 resumed
6.4 查看最后的更新情况
bash
[root@master01 ~]# kubectl get pod -w -n fql
[root@master01 ~]# kubectl get pod -n fql -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-01-78cb4c6b78-jb5vq 1/1 Running 0 54s 10.244.1.25 node01 <none> <none>
nginx-01-78cb4c6b78-w6s2l 1/1 Running 0 7m27s 10.244.2.24 node02 <none> <none>
nginx-01-78cb4c6b78-xqm9z 1/1 Running 0 52s 10.244.1.26 node01 <none> <none>
6.5 分阶段访问
在金丝雀发布中,将流量分流到新旧版本的这个过程被称为分阶段访问(Staged Access),也可以称为阶段性流量调度(Staged Traffic Shifting)。即将流量逐步引导到新版本的过程,以确保新版本的稳定性和可靠性。
bash
[root@master01 ~]# kubectl set image deployment nginx-01 nginx=nginx:1.16 -n fql && kubectl rollout pause deployment nginx-01 -n fql
[root@master01 ~]# kubectl get pod -n fql
NAME READY STATUS RESTARTS AGE
nginx-01-78cb4c6b78-jb5vq 1/1 Running 0 6h54m
nginx-01-78cb4c6b78-w6s2l 1/1 Running 0 7h1m
nginx-01-78cb4c6b78-xqm9z 1/1 Running 0 6h54m
nginx-01-85c54f54dc-gn67s 1/1 Running 0 36s # 新增实例
默认情况下,访问 server 流量将会负载均衡至4个实例上,新增 server 实现新的实例与旧实例访问分流:
bash
[root@master01 ~]# kubectl expose deployment nginx-01 -n fql --port=80 --target-port=80 --name=new-nginx --type=NodePort
[root@master01 ~]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
new-nginx NodePort 10.96.255.43 <none> 80:31923/TCP 68s
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 7h7m
查看 pod 实例标签名;编辑(查看)位于命名空间 fql 中的名为 new-nginx 的 Service 资源对象,复制文本内容,并创建对应 yaml 文件,修改标签选择器内容:
bash
[root@master01 ~]# kubectl get pod --show-labels -n fql
NAME READY STATUS RESTARTS AGE LABELS
nginx-01-78cb4c6b78-jb5vq 1/1 Running 0 7h9m app=nginx-01,pod-template-hash=78cb4c6b78
nginx-01-78cb4c6b78-w6s2l 1/1 Running 0 7h15m app=nginx-01,pod-template-hash=78cb4c6b78
nginx-01-78cb4c6b78-xqm9z 1/1 Running 0 7h9m app=nginx-01,pod-template-hash=78cb4c6b78
nginx-01-85c54f54dc-gn67s 1/1 Running 0 15m app=nginx-01,pod-template-hash=85c54f54dc
[root@master01 ~]# kubectl edit svc new-nginx -n fql #编辑复制文本
[root@master01 ~]# mkdir yaml;cd yaml
[root@master01 yaml]# vim new-nginx.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-01
name: new-nginx
namespace: fql
spec:
clusterIP: 10.96.255.43
clusterIPs:
- 10.96.255.43
externalTrafficPolicy: Cluster
ports:
- nodePort: 31923
port: 80
protocol: TCP
targetPort: 80
selector:
pod-template-hash: 85c54f54dc # 修改为对应标签
sessionAffinity: None
type: NodePort
删除 Kubernetes svc 资源,并根据配置文件创建或更新资源:
bash
[root@master01 yaml]# kubectl delete svc new-nginx -n fql
service "new-nginx" deleted
[root@master01 yaml]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 7h23m
[root@master01 yaml]# kubectl apply -f new-nginx.yaml -n fql
service/new-nginx created
[root@master01 yaml]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
new-nginx NodePort 10.96.255.43 <none> 80:31923/TCP 2s
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 7h24m
[root@master01 yaml]# kubectl get endpoints new-nginx -n fql
NAME ENDPOINTS AGE
new-nginx 10.244.1.27:80 75s # 对应的后端节点ip为10.244.1.27:80
访问升级版本 pod,查看流量调度是否正确:
bash
[root@master01 yaml]# curl -I 10.244.1.27
Server: nginx/1.16.1
同样的,编辑(查看)位于命名空间 fql 中的名为 nginx-server 的 Service 资源对象,复制文本内容,并创建对应 yaml 文件,修改标签选择器内容:
bash
[root@master01 yaml]# vim nginx-server.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-01
name: nginx-service
namespace: fql
spec:
clusterIP: 10.96.128.93
clusterIPs:
- 10.96.128.93
externalTrafficPolicy: Cluster
ports:
- nodePort: 31217
port: 80
protocol: TCP
targetPort: 80
selector:
pod-template-hash: 78cb4c6b78
sessionAffinity: None
type: NodePort
[root@master01 yaml]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
new-nginx NodePort 10.96.255.43 <none> 80:31923/TCP 10m
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 7h35m
[root@master01 yaml]# kubectl delete svc nginx-service -n fql
service "nginx-service" deleted
[root@master01 yaml]# kubectl apply -f nginx-server.yaml -n fql
service/nginx-service created
[root@master01 yaml]# kubectl get svc -n fql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
new-nginx NodePort 10.96.255.43 <none> 80:31923/TCP 11m
nginx-service NodePort 10.96.128.93 <none> 80:31217/TCP 2s
[root@master01 yaml]# kubectl get endpoints nginx-service -n fql
NAME ENDPOINTS AGE
nginx-service 10.244.1.25:80,10.244.1.26:80,10.244.2.24:80 3m33s
访问旧版本 pod,查看流量调度是否正确:
bash
[root@master01 yaml]# curl 10.96.128.93 -I
Server: nginx/1.15.12
[root@master01 yaml]# curl 10.96.128.93 -I
Server: nginx/1.15.12
[root@master01 yaml]# curl 10.96.128.93 -I
Server: nginx/1.15.12
至此,通过不同 server 对应标签,完成金丝雀发布中,将流量分流到新旧版本的过程。
7. 蓝绿发布
蓝绿发布是一种部署新版本应用程序的策略,旨在减少对用户造成的影响。在蓝绿发布中,两个相同的生产环境并行存在,一个被标记为"蓝色"(Blue),另一个被标记为"绿色"(Green)。
- 蓝色环境:当前稳定的生产环境
- 绿色环境:新版本的生产环境
在初始阶段,所有的用户流量都会指向蓝色环境。当新版本准备就绪时,流量可以逐渐转移到绿色环境。这种逐步迁移流量的方式允许进行实时监控,并在出现问题时快速回滚到蓝色环境。一旦绿色环境被验证为稳定可靠,蓝色环境可以被废弃或者保留作为备份。
8. 发布方式总结
① 滚动发布
按照比例一部分一部分的滚动更新;创建一定比例的 pod,先创建再删除旧的 pod。
② 金丝雀发布(灰度发布)
先更新一部分 pod,然后暂停更新;
安排一小部分的用户流量取访问更新的 pod 来进行测试;
当测试没有问题后再扩大比例,直到全部更新完成为止。
③ 蓝绿发布
蓝:正在运行的稳定版本
绿:新版本的副本
进行新旧版本的切换,用户无感知、业务稳定;但是需要大量的资源、成本高。