learn-tech/专栏/Kubernetes入门实战课/32实战演练:玩转Kubernetes(3).md
2024-10-16 06:37:41 +08:00

18 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        32 实战演练玩转Kubernetes3
                        你好我是Chrono。

到今天我们的“高级篇”课程也要结束了。比起前面的“初级篇”“中级篇”来说这里的知识点比较多难度也要高一些。如果你能够一篇不漏地学习下来相信一定对Kubernetes有更深层次的认识和理解。

今天的这节课还是来对前面的知识做回顾与总结,提炼出文章里的学习要点和重点,你也可以顺便检验一下自己的掌握程度,试试在不回看课程的情况下,自己能不能流畅说出关联的操作细节。

复习之后我们就来进行最后一次实战演练了。首先会继续改进贯穿课程始终的WordPress网站把MariaDB改成StatefulSet加上NFS持久化存储然后我们会在Kubernetes集群里安装Dashboard综合实践Ingress、namespace的用法。

要点回顾一API对象

“高级篇”可以分成三个部分第一部分讲的是PersistentVolume、StatefulSet等API对象。

[24讲]PersistentVolume简称PV是Kubernetes对持久化存储的抽象代表了LocalDisk、NFS、Ceph等存储设备和CPU、内存一样属于集群的公共资源。

因为不同存储设备之间的差异很大为了更好地描述PV特征就出现了StorageClass它的作用是分类存储设备让我们更容易去选择PV对象。

PV一般由系统管理员来创建我们如果要使用PV就要用PVCPersistentVolumeClaim去申请说清楚需求的容量、访问模式等参数然后Kubernetes就会查找最合适的PV分配给我们使用。

[25讲]手动创建PV的工作量很大麻烦而且容易出错所以就有了“动态存储卷”的概念需要在StorageClass里绑定一个Provisioner对象由它来代替人工根据PVC自动创建出符合要求的PV。

有了PV和PVC我们就可以在Pod里用“persistentVolumeClaim”来引用PVC创建出可供容器使用的Volume然后在容器里用“volumeMounts”把它挂载到某个路径上这样容器就可以读写PV实现数据的持久化存储了。

[26讲]持久化存储的一个重要应用领域就是保存应用的状态数据管理有状态的应用就要使用新的对象StatefulSet可以认为它是管理无状态应用对象Deployment的一个特例。

StatefulSet对象的YAML描述和Deployment非常像“spec”里只是多了一个“serviceName”字段但它部署应用的方式却与Deployment差距很大。

Deployment创建的Pod是随机的名字而StatefulSet会对Pod顺序编号、顺序创建保证应用有一个确定的启动先后次序这样就可以实现主从、主备等关系。

在使用Service为StatefulSet创建服务的时候它也会为每个Pod单独创建域名同样也是顺序编号保证Pod有稳定的网络标识外部用户就可以用这个域名来准确地访问到某个具体的Pod。

StatefulSet还使用“volumeClaimTemplates”字段来定义持久化存储里面其实就是一个PVC每个Pod可以用这个模板来生成自己的PVC去申请PV实现存储卷与Pod的独立绑定。

通过启动顺序、稳定域名和存储模板这三个关键能力StatefulSet就可以很好地处理Redis、MySQL等有状态应用了。

要点回顾二:应用管理

“高级篇”第二部分讲的是应用管理,包括滚动更新、资源配额和健康检查等内容。

[27讲]在Kubernetes里部署好应用后我们还需要对它做持续的运维管理其中一项任务是版本的更新和回退。

版本更新很简单只要编写一个新的YAMLDeployment、DaemonSet、StatefulSet再用 kubectl apply 应用就可以了。Kubernetes采用的是“滚动更新”策略实际上是两个同步进行的“扩容”和“缩容”动作这样在更新的过程中始终会有Pod处于可用状态能够平稳地对外提供服务。

应用的更新历史可以用命令 kubectl rollout history 查看,如果有什么意外,就可以用 kubectl rollout undo 来回退。这两个命令相当于给我们的更新流程上了一个保险可以放心大胆操作失败就用“S/L大法”。

[28讲]为了让Pod里的容器能够稳定运行我们可以采用资源配额和检查探针这两种手段。

资源配额能够限制容器申请的CPU和内存数量不至于过多或者过少保持在一个合理的程度更有利于Kubernetes调度。

检查探针是Kubernetes内置的应用监控工具有Startup、Liveness、Readiness三种分别探测启动、存活、就绪状态探测的方式也有exec、tcpSocket、httpGet三种。组合运用这些就可以灵活地检查容器的状态Kubernetes发现不可用就会重启容器让应用在总体上处于健康水平。

要点回顾三:集群管理

“高级篇”第三部分讲的是集群管理,有名字空间、系统监控和网络通信等知识点。

[29讲]Kubernetes的集群里虽然有很多计算资源但毕竟是有限的除了要给Pod加上资源配额我们也要为集群加上资源配额方法就是用名字空间把整体的资源池切分成多个小块按需分配给不同的用户使用。

名字空间的资源配额使用的是“ResourceQuota”除了基本的CPU和内存它还能够限制存储容量和各种API对象的数量这样就可以避免多用户互相挤占更高效地利用集群资源。

[30讲]系统监控是集群管理的另一个重要方面Kubernetes提供了Metrics Server和Prometheus两个工具

Metrics Server专门用来收集Kubernetes核心资源指标可以用 kubectl top 来查看集群的状态它也是水平自动伸缩对象HorizontalPodAutoscaler的前提条件。 Prometheus继Kubernetes之后的第二个CNCF毕业项目是云原生监控领域的“事实标准”在集群里部署之后就可以用Grafana可视化监控各种指标还可以集成自动报警等功能。

[31讲]对于底层的基础网络设施Kubernetes定义了平坦的网络模型“IP-per-pod”实现它就要符合CNI标准。常用的网络插件有Flannel、Calico、Cilium等Flannel使用Overlay模式性能较低Calico使用Route模式性能较高。

现在,“高级篇”的众多知识要点我们都完整地过了一遍,你是否已经都理解、掌握了它们呢?

搭建WordPress网站

接下来我们就来在[第22讲]的基础上继续优化WordPress网站其中的关键是让数据库MariaDB实现数据持久化。

网站的整体架构图变化不大前面的Nginx、WordPress还是原样只需要修改MariaDB

因为MariaDB由Deployment改成了StatefulSet所以我们要修改YAML添加“serviceName”“volumeClaimTemplates”这两个字段定义网络标识和NFS动态存储卷然后在容器部分用“volumeMounts”挂载到容器里的数据目录“/var/lib/mysql”。

修改后的YAML就是这个样子

apiVersion: apps/v1 kind: StatefulSet metadata: labels: app: maria-sts name: maria-sts

spec:

headless svc

serviceName: maria-svc

pvc

volumeClaimTemplates:

  • metadata: name: maria-100m-pvc spec: storageClassName: nfs-client accessModes: - ReadWriteMany resources: requests: storage: 100Mi

replicas: 1 selector: matchLabels: app: maria-sts

template: metadata: labels: app: maria-sts spec: containers: - image: mariadb:10 name: mariadb imagePullPolicy: IfNotPresent ports: - containerPort: 3306

    envFrom:
    - prefix: 'MARIADB_'
      configMapRef:
        name: maria-cm

    volumeMounts:
    - name: maria-100m-pvc
      mountPath: /var/lib/mysql

改完MariaDB我们还要再对WordPress做一点小修改。

还记得吗StatefulSet管理的每个Pod都有自己的域名所以要把WordPress的环境变量改成MariaDB的新名字也就是“maria-sts-0.maria-svc”

apiVersion: v1 kind: ConfigMap metadata: name: wp-cm

data: HOST: 'maria-sts-0.maria-svc' #注意这里 USER: 'wp' PASSWORD: '123' NAME: 'db'

改完这两个YAML我们就可以逐个创建MariaDB、WordPress、Ingress等对象了。

和之前一样访问NodePort的“30088”端口或者是用Ingress Controller的“wp.test”域名都可以进入WordPress网站

StatefulSet的持久化存储是否生效了呢

你可以把这些对象都删除后重新创建再进入网站看看是否原来的数据依然存在。或者更简单一点直接查看NFS的存储目录应该可以看到MariaDB生成的一些数据库文件

这两种方式都能够证明我们的MariaDB使用StatefulSet部署后数据已经保存在了磁盘上不会因为对象的销毁而丢失。

到这里第一个小实践你就已经完成了给自己鼓鼓劲我们一起来做第二个实践在Kubernetes集群里安装Dashboard。

部署Dashboard

在“初级篇”的实战演练课里([第15讲]我简单介绍了Kubernetes的图形管理界面也就是Dashboard不知道你是否还有印象。当时Dashboard是直接内置在minikube里的不需要安装一个命令启动就能在浏览器里直观地管理Kubernetes集群了非常方便。

那现在我们用kubeadm部署了实际的多节点集群能否也用上Dashboard呢接下来我就带你来一起动手从零开始安装Dashboard。

首先你应该先去Dashboard的项目网站https://github.com/kubernetes/dashboard看一下它的说明文档了解一下它的基本情况

它的安装很简单只需要一个YAML文件可以直接下载

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.0/aio/deploy/recommended.yaml

这个YAML里包含了很多对象虽然文件比较大但现在的你应该基本都能够看懂了要点有这么几个

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

使用命令 kubectl apply 就可以轻松部署Dashboard了

kubectl apply -f dashboard.yaml

部署Ingress/Ingress Controller

不过为了给我们的实战增加一点难度我们可以在前面配一个Ingress入口用反向代理的方式来访问它。

由于Dashboard默认使用的是加密的HTTPS协议拒绝明文HTTP访问所以我们要先生成证书让Ingress也走HTTPS协议。

简单起见我直接用Linux里的命令行工具“openssl”来生成一个自签名的证书如果你有条件也可以考虑找CA网站申请免费证书

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")

openssl的命令比较长我简单解释一下它生成的是一个X509格式的证书有效期365天私钥是RSA2048位摘要算法是SHA256签发的网站是“k8s.test”。

运行命令行后会生成两个文件一个是证书“k8s.test.crt”另一个是私钥“k8s.test.key”我们需要把这两个文件存入Kubernetes里供Ingress使用。

因为这两个文件属于机密信息存储的方式当然就是用Secret了。你仍然可以用命令 kubectl create secret 来自动创建YAML不过类型不是“generic”而是“tls”同时还要用 -n 指定名字空间,用 --cert、--key 指定文件:

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

出来的YAML大概是这个样子

apiVersion: v1 kind: Secret metadata: name: dash-tls namespace: kubernetes-dashboard type: kubernetes.io/tls

data: tls.crt: LS0tLS1CRUdJTiBDRVJU... tls.key: LS0tLS1CRUdJTiBQUklW...

创建这个Secret对象之后你可以再用 kubectl describe 来检查它的状态:

接下来我们就来编写Ingress Class和Ingress对象为了保持名字空间的整齐也把它放在“kubernetes-dashboard”名字空间里。

Ingress Class对象很简单名字是“dash-ink”指定Controller还是我们之前用的Nginx官方的Ingress Controller

apiVersion: networking.k8s.io/v1 kind: IngressClass

metadata: name: dash-ink namespace: kubernetes-dashboard spec: controller: nginx.org/ingress-controller

Ingress对象可以用 kubectl create 命令自动生成,如果你有点忘记的话,可以回头参考一下[第21讲]

kubectl create ing dash-ing --rule="k8s.test/=kubernetes-dashboard:443" --class=dash-ink -n kubernetes-dashboard $out

但这次因为是HTTPS协议所以我们要在Ingress里多加一点东西一个是“annotations”字段指定后端目标是HTTPS服务另一个是“tls”字段指定域名和证书也就是刚才创建的Secret

apiVersion: networking.k8s.io/v1 kind: Ingress

metadata: name: dash-ing namespace: kubernetes-dashboard annotations: nginx.org/ssl-services: "kubernetes-dashboard"

spec: ingressClassName: dash-ink

tls: - hosts: - k8s.test secretName: dash-tls

rules:

  • host: k8s.test http: paths:
    • path: / pathType: Prefix backend: service: name: kubernetes-dashboard port: number: 443

最后一个对象就是Ingress Controller了还是拿现成的模板修改记得要把“args”里的Ingress Class改成我们自己的“dash-ink”

apiVersion: apps/v1 kind: Deployment metadata: name: dash-kic-dep namespace: nginx-ingress

spec: ... args: - -ingress-class=dash-ink

要让我们在外面能够访问Ingress Controller还要为它再定义一个Service类型是“NodePort”端口指定是“30443”

apiVersion: v1 kind: Service metadata: name: dash-kic-svc namespace: nginx-ingress

spec: ports:

  • port: 443 protocol: TCP targetPort: 443 nodePort: 30443

selector: app: dash-kic-dep type: NodePort

把上面的Secret、Ingress Class、Ingress、Ingress Controller、Service都创建好之后我们再来确认一下它们的运行状态

因为这些对象比较多,处于不同的名字空间,关联有点复杂,我画了一个简单的示意图,你可以看一下:

访问Dashboard

到这里Dashboard的部署工作就基本完成了。为了能正常访问我们还要为它创建一个用户才能登录进Dashboard。

Dashboard的网站上有一个简单示例https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md我们直接拿来用就行

apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard


apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects:

  • kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard

这个YAML创建了一个Dashboard的管理员账号名字叫“admin-user”使用的是Kubernetes的RBAC机制就不展开细讲了。

这个账号不能用简单的“用户名+密码”的方式登录需要用到一个Token可以用 kubectl get secret、kubectl describe secret 查到:

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

Token是一个很长的字符串把它拷贝存好再为它的测试域名“k8s.test”加上域名解析修改/etc/hosts然后我们就可以在浏览器里输入网址“https://k8s.test:30443”访问Dashboard了

下面的两张截图就是我查看集群里“kube-system”名字空间的情况由于我们之前安装了Metrics Server所以Dashboard也能够以图形的方式显示CPU和内存状态有那么一点Prometheus + Grafana的意思

小结

好了,今天我们一起回顾了“高级篇”里的要点,下面的这张思维导图就是对这些知识点的全面总结,你可以再认真研究一下:

今天我们有两个实战项目。首先是WordPress把后端的存储服务MariaDB改造成了StatefulSet挂载了NFS网盘这样就实现了一个功能比较完善的网站达到了基本可用的程度。

接着我们又在Kubernetes里安装了Dashboard主要部署在名字空间“kubernetes-dashboard”。Dashboard自身的安装很简单但我们又为它在前面搭建了一个反向代理配上了安全证书进一步实践了Ingress的用法。

不过这两个项目还没有完全覆盖“高级篇”的内容,你可以再接着改进它们,比如加上健康检查、资源配额、自动水平伸缩等,多动手来巩固所学的知识。

课下作业

今天的课下作业时间,我想就留给你自己来操作一下这节课里的两个实战演练吧,如果遇到了什么问题,可以在留言区随时提问。