learn-tech/专栏/Kubernetes入门实战课/33视频:高级篇实操总结.md
2024-10-16 06:37:41 +08:00

17 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        33 视频:高级篇实操总结
                        你好我是Chrono。

在“高级篇”的这段时间里我们学习了PersistentVolume、PersistentVolumeClaim、StatefulSet等API对象具备了部署有状态应用的能力然后还学习了管理运维应用和集群的多种方式包括滚动更新、资源配额、检查探针、名字空间、系统监控等等。

掌握了这些知识现在的你再回想一下三个月前学习第一节课的时候有没有发现其实Kubernetes也没有当初自己想象得那么高深莫测呢

今天也是我们课程的最后一节正课还是会用视频的形式把“高级篇”里的一些重要的部分都实际演示出来结合前面的文字和图片你可以再次加深对Kubernetes的印象。

接下来就一起开始我们的学习吧。

PV和PVC ———-

我们先来创建一个本地存储卷也就是PV。

在Master和Worker节点的“/tmp”目录里先建立一个“host-10m-pv”的目录表示一个只有10MB容量的存储设备

mkdir /tmp/host-10m-pv

然后我们使用YAML来定义这个PV对象

vi host-path-pv.yml

它的kind是PersistentVolume名字是“host-10m-pv”后面“spec”里的字段都很重要描述了PV的基本信息。

因为这个PV是我们手动管理的“storageClassName”的名字你可以任意起这里我写的是“host-test”。 “accessModes”定义了存储设备的访问模式用的是最简单的“ReadWriteOnce”可读可写但只能被这个节点的Pod挂载。 “capacity”定义了存储的容量因为是测试就设置成了10MB。注意定义存储容量使用的是国际标准单位必须要写成Ki/Mi/Gi的形式否则就会出错。 最后一个字段“hostPath”指定了存储卷的本地路径也就是刚才节点上创建的目录“/tmp/host-10m-pv/”。

现在我们用 kubectl apply 创建PV对象

kubectl apply -f host-path-pv.yml

再用 kubectl get 查看状态:

kubectl get pv

就可以看到Kubernetes里已经有这个存储卷了。它的容量是10MB访问模式是RWO状态显示的是“Available”StorageClass是我们自己定义的“host-test”。

接下来我们再来定义PVC对象

vi host-path-pvc.yml

它的名字是“host-5m-pvc”“storageClassName”名字是“host-test”访问模式是“ReadWriteOnce”在“resources”字段里向Kubernetes申请使用5MB的存储。

PVC比较简单不像PV那样包含磁盘路径等存储细节。我们还是用 kubectl apply 创建对象:

kubectl apply -f host-path-pvc.yml

再用 kubectl get 查看PV和PVC的状态

kubectl get pv,pvc

就会发现已经成功分配了存储卷状态是“Bound”。虽然PVC申请的是5MB但系统里只有一个10MB的PV可以用没有更合适的所以Kubernetes也只能把它俩绑定在一起。

下面要做的就是把这个PVC挂载进Pod里了来看这个YAML文件

vi host-path-pod.yml

它在“volumes”里用“persistentVolumeClaim”声明了PVC的名字“host-5m-pvc”这样就把PVC和Pod联系起来了。

后面的“volumeMounts”就是挂载存储卷这个你应该比较熟悉了吧用name指定volume的名字用path指定路径这里就是挂载到了容器里的“/tmp”目录。

现在我们创建这个Pod再查看它的状态

kubectl apply -f host-path-pod.yml kubectl get pod -o wide

可以看到它被Kubernetes调到到了worker节点上让我们用 kubectl exec 进入容器执行Shell命令生成一个文本文件

kubectl exec -it host-pvc-pod -- sh echo aaa > /tmp/a.txt

然后我们登录worker节点看一下PV对应的目录“/tmp/host-10m-pv”

cd /tmp/host-10m-pv ls cat a.txt

输出的内容刚好就是我们在容器里生成的数据这就说明Pod的数据确实已经持久化到了PV定义的存储设备上。

NFS网络存储卷 ————

下面我们来看看在Kubernetes里使用NFS网络存储卷的用法。

NFS服务器和客户端、还有NFS Provisioner的安装过程我就略过了你可以对照着[第25讲]一步步来。

安装完成之后可以看一下Provisioner的运行状态

kubectl get deploy -n kube-system | grep nfs kubectl get pod -n kube-system | grep nfs

注意一定要配置好NFS Provisioner里的IP地址和目录如果地址错误或者目录不存在那么Pod就无法正常启动需要用 kubectl logs 来查看错误原因。

来看一下NFS默认的StorageClass定义

vi class.yaml

它的名字是“nfs-client”这个很关键我们必须在PVC里写上它才能够找到NFS Provisioner。

现在我们来看PVC和Pod的定义

vi nfs-dynamic-pv.yml

这个PVC申请的是10MB使用的访问模式是“ReadWriteMany”这是因为NFS是网络共享存储支持多个Pod同时挂载。

在Pod里我们还是用“persistentVolumeClaim”声明PVC“volumeMounts”挂载存储卷目标还是容器里的“/tmp”目录。

使用 kubectl apply 应用这个YAML就会创建好PVC和Pod用 kubectl get 查看一下集群里的PV和PVC

kubectl get pv,pvc

就可以看到NFS Provisioner自动为我们创建一个10MB的PV不多也不少。

我们再去NFS服务器上查看共享目录也会找到PV的存储目录名字里第一部分是名字空间default第二部分是这个PVC的名字。在这个目录生成一个文本文件

echo aaa > a.txt

然后我们再用 kubectl exec 进入Pod看看它里面的“/tmp”目录

kubectl exec -it nfs-dyn-pod -- sh cd /tmp ls cat a.txt

会发现NFS磁盘上的文件也出现在了容器里也就是说共享了网络存储卷。

创建使用NFS的对象 ————–

掌握了PV、PVC、NFS的用法之后我们就可以来实验StatefulSet的用法了创建一个使用NFS存储的对象。

看一下StatefulSet对象的YAML描述文件

vi redis-pv-sts.yml

第一个重要的字段是“serviceName”指定了StatefulSet的服务名是“redis-pv-svc”它也必须要和后面定义的Service对象一致。 第二个重要字段是“volumeClaimTemplates”相当于把PVC模板定义直接镶嵌进了对象里storageClass还是“nfs-client”申请了100MB的存储容量。 后面的字段都比较简单和Deployment完全一样比如replicas、selector、containers。

StatefulSet对象下面是它配套的Service定义关键是这个“clusterIP: None”不给Service分配虚IP地址也就是说它是一个“Headless Service”。外部访问StatefulSet不会经过Service的转发而是直接访问Pod。

使用 kubectl apply 创建这两个对象,“有状态应用”就运行起来了:

kubectl apply -f redis-pv-sts.yml

用 kubectl get 来查看StatefulSet对象的状态

kubectl get sts,pod

这两个有状态的Pod名字是顺序编号的从0开始分别被命名为 redis-pv-sts-0、redis-pv-sts-1运行的顺序是0号Pod启动成功后才会启动1号Pod。

我们再用 kubectl exec 进入Pod内部

kubectl exec -it redis-pv-sts-0 -- sh

看它的hostname和Pod名字是一样的

hostname

再来用试验一下两个Pod的独立域名应该都可以正常访问

ping redis-pv-sts-0.redis-svc ping redis-pv-sts-1.redis-svc

使用命令 kubectl get pvc 来查看StatefulSet关联的存储卷状态

kubectl get pv,pvc

可以看到StatefulSet使用PVC模板自动创建了两个PV并且绑定了。

为了验证持久化存储的效果,我们用 kubectl exec 运行Redis客户端添加一些KV数据

kubectl exec -it redis-pv-sts-0 -- redis-cli set a 111 set b 222 quit

然后删除这个Pod

kubectl delete pod redis-pv-sts-0

StatefulSet会监控Pod的运行情况发现数量不对会重新拉起这个Pod。我们再用Redis客户端登录去检查一下

kubectl exec -it redis-pv-sts-0 -- redis-cli get a get b keys *

就可以看到Pod挂载了原来的存储卷自动恢复了之前添加的Key-Value数据。

滚动更新 ——–

现在我们来学习一下Kubernetes里滚动更新的用法。

这里有一个V1版本的Nginx应用

vi ngx-v1.yml

注意在“annotations”里我们使用了字段“kubernetes.io/change-cause”标注了版本信息“v1, ngx=1.21”使用的镜像是“nginx:1.21-alpine”。

它后面还有一个配套的Service比较简单用的是NodePort就不多解释了。

然后我们执行命令 kubectl apply 部署这个应用:

kubectl apply -f ngx-v1.yml

用curl发送HTTP请求看看它的运行信息

curl 192.168.10.210:30080

从curl命令的输出中可以看到现在应用的版本是“1.21.6”。

执行 kubectl get pod看名字后的Hash值就是Pod的版本。

再来看第二版的对象“ngx-v2.yml”

vi ngx-v2.yml

它也是在“annotations”里标注了版本信息镜像升级到“nginx:1.22-alpine”还添加了一个字段“minReadySeconds”来方便我们观察应用更新的过程。

现在执行命令 kubectl apply因为改动了镜像名Pod模板变了就会触发“版本更新”kubectl rollout status 来查看应用更新的状态:

kubectl apply -f ngx-v2.yml kubectl rollout status deploy ngx-dep

再执行 kubectl get pod就会看到Pod已经全部替换成了新版本用curl访问Nginx输出的信息也变成了“1.22.0”:

kubectl get pod curl 192.168.10.210:30080

命令 kubectl describe 可以更清楚地看到Pod的变化情况是两个同步进行的扩容和缩容动作

kubectl describe deploy ngx-dep

那我们再来查看更新历史,命令是 kubectl rollout history

kubectl rollout history deploy ngx-dep

可以看到在“CHANGE-CAUSE”列里有刚才两个版本的更新信息。

我们最后用 kubectl rollout undo 来回退到上一个版本:

kubectl rollout undo deploy ngx-dep

再来看更新历史 kubectl rollout history会发现又变成了最初的版本用curl发请求试一下

curl 192.168.10.210:30080

Nginx又恢复成了第一版的1.21.6,我们的版本回退也就成功了。

水平伸缩 ——–

接下来看Kubernetes的水平自动伸缩功能也就是对象“HorizontalPodAutoscaler”。

水平自动伸缩功能要求必须有Metrics Server插件它的安装过程我就不演示了来直接看看它的运行状态使用 kubectl get pod

kubectl get pod -n kube-system

可以看到有一个Metrics Server Pod正在运行。

然后我们看一下当前的系统指标:

kubectl top node kubectl top pod -n kube-system

确认Metrics Server 运行正常,下面我们就可以试验水平自动伸缩功能了。

首先我们来定义一个Deployment对象部署1个Nginx实例

vi ngx-hpa-dep.yml

注意在YAML里我们必须要用“resources”字段明确写出它的资源配额否则HorizontalPodAutoscaler无法获取Pod的指标也就无法实现自动化扩缩容。

kubectl apply 创建对象后,用 kubectl get pod可以看到它现在只有一个实例。

接下来的HPA对象很简单它指定Pod数量最多10个最少2个CPU使用率指标设是5%。使用命令 kubectl apply 创建HPA它会发现Nginx实例只有1个不符合的下限的要求就会扩容到2个

kubectl get pod kubectl get hpa

然后我们启动一个http Pod用里面的压力测试工具ab来给Nginx增加流量压力

kubectl run test -it --image=httpd:alpine -- sh

向Nginx发送一百万个请求持续30秒再用 kubectl get hpa 来观察HorizontalPodAutoscaler的运行状况

ab -c 10 -t 30 -n 1000000 'http://ngx-hpa-svc/'

kubectl get hpa

你可以看到HPA会通过Metrics Server不断地监测Pod的CPU使用率超过设定值就开始扩容一直到数量上限。

Prometheus ————–

我们来看看CNCF的二号项目Prometheus。

首先从GitHub上下载它的源码包最新的版本是0.11然后解压缩得到部署所需的YAML文件。

然后我们修改 prometheus-service.yaml、grafana-service.yaml 这两个文件把Service类型改成NodePort这样就可以直接用节点的IP地址访问。为了方便我们还把Prometheus的节点端口指定成了“30090”Grafana的节点端口指定成了“30030”。

记得还要修改 kubeStateMetrics-deployment.yaml、prometheusAdapter-deployment.yaml因为它们里面的镜像放在了gcr.io上拉取很困难改成docker hub上的会容易一些。

修改完之后,执行两个 kubectl create 命令来部署Prometheus。先是“manifests/setup”目录创建名字空间等基本对象然后才是“manifests”目录

kubectl create -f manifests/setup kubectl create -f manifests

Prometheus的对象都在名字空间“monitoring”里创建之后可以用 kubectl get 来查看状态:

kubectl get pod -n monitoring

再来看一下它们的Service对象

kubectl get svc -n monitoring

端口就是刚才我们设置的“30090”和“30030”。

Prometheus启动之后我们在浏览器里输入节点的IP地址再加上端口号“30090”就会看到Prometheus的Web界面。

可以在这个查询框里任意选择指标或者使用PromQL编辑表达式生成可视化图表比如“node_memory_Active_bytes”这个指标就当前正在使用的内存容量。

再来看Grafana访问节点的端口“30030”就会出来Grafana的登录界面默认的用户名和密码都是“admin”。

Grafana内部预置了很多仪表盘我们可以在菜单栏的“Dashboards - Browse”里随意挑选比如选择“Kubernetes / Compute Resources / Namespace (Pods)”这个仪表盘。

Dashboard ————-

现在我们来在Kubernetes集群里部署仪表盘插件Dashboard。

这里使用的是2.6.0版只有一个YAML文件来大概看一下

vi dashboard.yaml

所有的对象都属于“kubernetes-dashboard”名字空间。 Service对象使用的是443端口它映射了Dashboard的8443端口。 Dashboard使用Deployment部署了一个实例端口号是8443。 容器启用了Liveness探针使用HTTPS方式检查存活状态。

使用命令 kubectl apply 就可以一键部署Dashboard

kubectl apply -f dashboard.yaml kubectl get pod -n kubernetes-dashboard

接下来我们给Dashboard配一个Ingress入口用反向代理的方式来访问它。

先要用openssl工具生成一个自签名的证书然后把生成的证书和私钥都转换成Secret对象。因为这操作命令比较长敲键盘很麻烦这里写成了脚本文件。

openssl req -x509 -days 365 -out k8s.test.crt -keyout k8s.test.key
-newkey rsa:2048 -nodes -sha256
-subj '/CN=k8s.test' -extensions EXT -config <(
printf "[dn]\nCN=k8s.test\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:k8s.test\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

export out="--dry-run=client -o yaml" kubectl create secret tls dash-tls -n kubernetes-dashboard --cert=k8s.test.crt --key=k8s.test.key $out > cert.yml

证书的参数是有效期365天私钥是RSA2048位摘要算法是SHA256Secret对象的名字是“dash-tls”。

然后我们来看Ingress Class和Ingress的定义

vi ingress.yml

注意它们也都在名字空间“kubernetes-dashboard”里。Ingress要在“annotations”字段里指定后端目标是HTTPS服务“tls”字段指定域名“k8s.test”和证书Secret对象“dash-tls”。

再来定义Ingress Controller镜像用的是“nginx-ingress:2.2-alpine”注意一定要把“args”里的Ingress Class设置成刚才的“dash-ink”Service对象也改成NodePort端口号是30443。

最后我们还要给Dashboard创建一个用户admin-user

vi admin.yml

这些YAML都准备好了让我们用 kubectl apply 来逐个创建对象:

kubectl apply -f cert.yml kubectl apply -f ingress.yml kubectl apply -f kic.yml kubectl apply -f admin.yml

在用浏览器访问Dashboard之前我们要先获取用户的Token它是以Secret的方式存储的

kubectl get secret -n kubernetes-dashboard kubectl describe secrets -n kubernetes-dashboard admin-user-token-xxxx

把这个Token拷贝一下确保能够解析“k8s.test”这个域名在浏览器里输入网址“https://k8s.test:30443”我们就可以登录Dashboard了

课下作业

不知道今天的参考视频有没有帮你解决一点实操上的小问题,如果你成功做完了所有项目,欢迎在留言区交流经验和新想法,如果遇到了困难,也欢迎描述清楚发上来,我们一起讨论。