首页 / 资讯中心 / 文章详情

K8s生产实践:Dashboard可视化、HPA自动扩缩容与Helm部署管理详解

K8s生产实践:Dashboard可视化、HPA自动扩缩容与Helm部署管理详解 ★ FEATURED ARTICLE
这个k8s系列写到第十篇了今天一次性把三个经常一起出现的家伙聊透Dashboard、HPA、Helm。这三样东西表面上互不相干一个给你图形界面、一个让应用学会自动扩缩容、另一个管部署包但组合起来正好覆盖了从“能把容器跑起来”到“能上生产、能运维、能重复发布”的三块关键拼图。如果你已经会写Deployment、Service但还没体验过Web界面、还在半夜手动扩容、还在用一长串kubectl apply维护几十个YAML那么这篇就是给你准备的。老规矩我按自己的实操顺序讲包括踩过的坑、临时救急的命令、以及真正上生产时怎么取舍。1. 先理清这三兄弟在集群里的分工1.1 Dashboard不是必需品但是体验提升器Kubernetes本身没有官方默认的Web控制台所有操作都通过kubectl命令行完成。能力上没有任何问题但不代表人就能适应。大多数新同学接触集群一脸懵的原因并不是概念难而是“看不见”——Pod到底起没起来为什么重启日志刷了一屏看不懂此时一个Dashboard就能让你从“盲人摸象”变成“打开监控屏幕”。Dashboard是Kubernetes社区维护的官方Web界面组件部署后可以用浏览器访问看到集群里的节点、命名空间、工作负载、服务、配置、存储、日志和事件流。它真正的价值不是替代kubectl而是降低观察成本和排障成本。尤其是排查“一个Pod反复崩溃”这种问题时在Dashboard上切换容器组、点开日志和事件比一条条敲命令直观得多。需要明确的是它确实不是集群运行必需组件。但在测试环境、团队教学、以及非K8s专业人员需要查看业务状态时装一个很值。1.2 HPA让集群学会自己呼吸HPAHorizontal Pod Autoscaler即水平Pod自动扩缩容。它的工作方式很简单盯着Pod的CPU、内存等指标看指标高了就自动增加副本数指标降了就自动减少副本数。整个过程不需要人干预相当于给应用装了一个根据流量自动呼气的肺。手工扩容的问题不是“能不能扩”而是“反应速度”和“资源感知”。深夜流量突增人不一定马上发现测试环境短时间高并发手忙脚乱敲命令也容易扩错。HPA解决的正是“让副本数跟着真实用量走”这件事。配合资源请求requests和限制limits它能让集群用最少的空闲副本兜住足够的突发流量。想让它工作集群里必须先有可用的“指标管道”。这就是metrics-server的活。稍后会具体演示。1.3 Helm把“散装YAML”变成“安装包”一个完整的应用部署往往不是单个Deployment而是Deployment、Service、ConfigMap、Secret、Ingress、PVC一串文件。三个环境三套参数手改的话每次发布都是一次灾难现场。Helm就是来解决这个问题的它把应用打包成一个Chart安装包通过values.yaml管理不同环境的差异用一句helm install完成整组资源的安装还能随时升级和回滚。打个比方Helm之于Kubernetes类似于安装包管理器之于Linux只是它面向的是“一个应用的所有K8s资源”。这个说法不算夸张凡是经历过“把维护十几个YAML的任务交给新人”的人都会明白模板化和版本化的重要性。这三块内容有个先后依赖Dashboard让你看得见集群HPA让集群有弹性Helm让部署过程可复制。下面我逐一讲操作。2. 用Dashboard打开集群的“仪表盘”2.1 安装官方YAML一行下去剩下的看PodDashboard的安装方式一直很简单下载官方打包好的YAMLapply进去就行。我这里用的版本是v2.7.0这是目前比较成熟稳定的一个大版本部署命令如下kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml这个recommended.yaml就是把所有组件打包好的完整清单包含命名空间kubernetes-dashboard、ServiceAccount、ConfigMap、Deployment、Service等。执行完以后检查一下Pod状态kubectl -n kubernetes-dashboard get pod -o wide正常情况下你会看到类似dashboard-web和dashboard-api的Pod状态最终变为Running。如果一直ContainerCreating多半是拉镜像慢国内网络环境可以用Node节点上手动拉取或配置镜像加速器这个老生常谈就不展开了。访问Dashboard有两种常用方式。第一种是kubectl proxy它会启动一个到API Server的本地代理然后通过一个长路径访问。第二种是把dashboard的Service改成NodePort类型用节点IP端口直接访问。我建议本地调试用proxy固定环境用NodePort或Ingresskubectl -n kubernetes-dashboard edit svc kubernetes-dashboard # 把 type: ClusterIP 改为 type: NodePort # 改完以后查看对外端口通常是30000以上 kubectl -n kubernetes-dashboard get svc改NodePort时注意防火墙要放行对应端口浏览器访问是https协议因为Dashboard默认自签名证书浏览器会提示风险点击继续即可。提示如果只是临时看两眼kubectl proxy最省事因为它不需要暴露任何节点端口安全性上更稳。2.2 登录与授权Token、Kubeconfig和权限边界Dashboard装好只是第一步登录才是新手翻车最多的地方。新版Dashboard默认开启了登录页提供两种方式Token和Kubeconfig。这里重点说Token。默认情况下Dashboard会自动创建一个名叫kubernetes-dashboard的ServiceAccount但这个账号权限很低基本只能看到些无关紧要的信息。你要想拿到管理员的浏览权限需要手动建立一个高权限账号再绑定角色。我平时测试环境这样建apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard保存为dashboard-admin-user.yaml先apply这个ServiceAccountkubectl apply -f dashboard-admin-user.yaml然后创建ClusterRoleBinding把admin-user绑定到cluster-admin这个集群角色上apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboardapply后获取登录Tokenkubectl -n kubernetes-dashboard create token admin-user把输出的那长串Token复制粘贴到Dashboard登录页即可。这里必须强调权限边界cluster-admin是集群超级管理员它能看到所有命名空间、所有Secret、所有资源甚至能删除任意工作负载。如果这是生产环境我真不建议直接给所有人cluster-admin。Dashboard是按“人”授权不是按“环境”授权一旦凭据泄露整个集群就裸奔了。更稳妥的做法是按照团队需要建View或Edit角色或者用命名空间级别的RoleBinding把权限控制到具体项目范围。第二种登录方式是Kubeconfig文件。Dashboard支持直接上传本地kubeconfig文件完成鉴权适合已经有Kubernetes本地访问配置的使用者。需要注意文件里的token或client-certificate数据必须具有足够权限否则登录后页面会显示一堆Forbidden。2.3 我平时在Dashboard上最常干的四件事装上Dashboard后我实际使用频率最高的是这么几个功能第一看事件Events。如果一个Pod卡在Pending或者老是ImagePullBackOff普通日志看不出所以然事件里会直接写调度失败原因或拉镜像报错。这是排障的第一入口。第二看资源用量图。Dashboard会展示每个Pod的CPU和内存历史曲线配合HPA调参时非常有用。看曲线能直观判断目标阈值设置是否合理不用反复kubectl top。第三在线看容器日志。多容器Pod默认只显示第一个容器的日志在Dashboard上可以在容器下拉框里切换比kubectl logs -c方便不少。第四快速伸缩。直接在Deployment详情页里改副本数几秒钟生效。这在临时压测、应急扩容场景下很顺手也不用记住YAML字段。注意Dashboard上的编辑能力本质还是修改K8s资源如果你有GitOps流程只在应急时用别把它当作日常发布工具。3. HPA从“半夜手动扩容”到“流量自己控副本”3.1 先装metrics-server确认top命令有数据HPA依赖Pod的CPU/内存指标做决策而这些指标来自Metrics API。Kubernetes集群默认没有这个数据源你需要安装metrics-server。它是CNCF社区的项目简单说就是每个节点上一个轻量采集组件从kubelet拿到Pod和Node的用量再暴露给API Server的聚合层。安装命令也很简单kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml装完以后验证是否生效kubectl top node kubectl top pod如果两条命令都能正常输出CPU和内存数值说明Metrics API通了。如果kubectl top node报错最常见的原因是节点证书或非安全端口问题。私有集群里常常因为AKS/EKS这类托管的kubelet证书不被metrics-server信任导致采集失败。此时可以给metrics-server的Deployment加一个启动参数当然是在自己集群环境里按需调整- --kubelet-insecure-tls这个参数的意思是“不校验kubelet证书”仅适合证书我们自己可控的内部集群。生产环境如果已经有合规的PKI体系不建议直接开这个开关。3.2 HPA配置拆解autoscaling/v2的那些参数HPA本身也是K8s里的一个资源对象用YAML描述。现代Kubernetes版本推荐的API版本是autoscaling/v2。以v1.23为例一个最简单的CPU型HPA长这样apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: hpa-demo spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: web-demo minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50关键点在几个地方。scaleTargetRef告诉HPA管的是哪个DeploymentminReplicas和maxReplicas是副本数的上下限这俩必须根据应用实际情况设太窄没弹性太宽会浪费资源metrics里声明了盯什么指标这里是CPU平均利用率50%。理解“平均利用率”很重要。它表示当前副本的CPU实际使用量除以该副本的requests里声明的CPU值。比如你的Pod在resources.requests.cpu里写了500m50%就意味着当每个Pod平均CPU到250m就该扩容低于125m就该缩容注意这里是平均值与目标值的比值不是绝对数值。复制数的扩缩容计算逻辑可以概括为一个公式期望副本数 ceil(当前副本数 × (当前指标值 / 目标指标值))举个例子当前1个副本CPU用量200m这个Pod的requests.cpu是100m那么当前指标值是200%目标是50%期望副本数ceil(1 × 200% / 50%)ceil(4)4于是HPA会把副本数调到4。如果后续负载降到50m计算结果是ceil(1×50%)1就缩回1个。提示HPA里的target分为Utilization和AverageValue两种。Utilization是按“相对requests的百分比”算AverageValue是按“每个副本的绝对用量”算。线上环境我多数用Utilization因为每个Pod的规格比较统一时更直观。另外autoscaling/v2还支持behavior字段可以精细控制扩容和缩容行为。比如缩容不要太快避免流量一抖副本就砍掉造成响应变慢behavior: scaleDown: stabilizationWindowSeconds: 300这个stabilizationWindowSeconds是缩容稳定窗口表示指标低于目标值后需要持续等待多久才真正执行缩容。默认值就是300秒我一般会保持默认。扩容方向一般不加延迟因为流量上来时等不起。3.3 压测演示看着Pod数量自己长起来光看定义不够我直接带大家跑一遍完整流程。先准备一个测试用Deployment和Servicekubectl create deployment web-demo --imagenginx:latest kubectl set resources deployment web-demo -cweb-demo --requestscpu100m kubectl expose deployment web-demo --port80注意我故意把requests.cpu设为100m这样在低流量下CPU很容易超过50%方便演示。然后创建HPAkubectl apply -f hpa-demo.yaml kubectl get hpa正常情况下输出里会有一行TARGETS比如“0%/50%”或“1%/50%”说明HPA已经能读到指标了。接着我用一个循环请求的负载Pod去制造CPU压力kubectl run -it load-generator --imagebusybox -- /bin/sh -c while true; do wget -q -O- http://web-demo.default.svc.cluster.local; done这个busybox容器会不停访问web-demo服务制造持续的连接和CPU消耗。过一两分钟再看HPA状态kubectl get hpa -w你会看到REPLICAS那一列从1变成2、变成3TARGETS里的百分比也会逐渐靠近50%。这个过程可能比想象中慢一点因为metrics-server的采集周期默认30秒左右HPA默认同步周期是15秒所以指标变化有个延迟。此时再看Pod列表kubectl get pod -l appweb-demo副本数已经自己涨上来了。停止负载时把busybox这个Pod删掉kubectl delete pod load-generator流量消失后CPU回落HPA并不会立刻缩容因为缩容稳定窗口默认5分钟防止抖动的设计。耐心等几分钟副本数会自己降回去。整个过程看起来很简单但真正部署到生产时有几个点一定不能忽略。HPA只能保证“有副本数弹性”不能保证容器本身正确地声明了资源requests。如果Deployment里的Pod没有写requestsHPA根本读取不到利用率目标值甚至会一直报错Unknown。其次HPA仅基于指标数据做决策如果指标采集断流HPA会保持当前副本数不再伸缩所以metrics-server的稳定运行同样重要。4. Helm把多个YAML打包成一个Release4.1 Chart、Release、Repository三件套理解Helm先记住三个词Chart、Release、Repository。Chart是Helm的应用打包单元一个Chart就是一个包含应用K8s资源模板的目录里面写着Deployment怎么写、Service怎么写以及哪些参数可以在部署时动态覆盖。Release是Chart部署到集群后生成的一个具体实例同一个Chart可以部署多次每次部署都是一个独立Release可以有不同参数和不同版本。Repository则是存放Chart的远程仓库类似你在Linux下配置的软件源方便下载别人做好的Chart或上传自己的Chart。这三个概念串起来的完整流程是从Repository拉Chart根据配置渲染成一组K8s资源安装到集群形成Release。之后可以用Helm统一升级或回滚整个Release。4.2 用helm create生成并部署第一个ChartHelm客户端安装不再赘述装好后执行helm version确认版本然后我会用一个练习目录演示。先初始化一个名为my-app的Charthelm create my-app tree my-app生成的目录结构大概是这样的Chart.yaml描述Chart名称和版本values.yaml集中管理所有可配置参数templates/目录存放各种资源模板还有charts/和crds/目录分别用来放依赖子Chart和自定义资源定义。先看Chart.yamlapiVersion: v2 name: my-app description: A Helm chart for Kubernetes type: application version: 0.1.0 appVersion: 1.16.0values.yaml里可以看到默认的镜像、副本数、Service端口等信息。部署前我想先看看这个Chart渲染出来到底是什么样用template命令只渲染不部署helm template my-app ./my-app屏幕上会输出所有YAML文件的合并结果。这一步是核对模板的关键相当于告诉你在说“我接下来要apply这些资源”。觉得没问题就实际安装helm install my-release ./my-app -n demo --create-namespace这里my-release是Release名字./my-app指定本地Chart路径-n指定命名空间。执行成功后helm list -A能看到这个Release。这时候我想换一个镜像版本用--set临时覆盖helm upgrade my-release ./my-app --set image.tag1.20.0再检查一次部署状态helm status my-release假如刚才那次升级引入了一个问题需要快速回退到上一个版本。Helm会把每次变更记录为一个Version号直接回滚即可helm history my-release helm rollback my-release 1这条命令会撤销刚才的升级让集群恢复上一个版本的资源。能看到实测时像这样反复演练升级回滚比任何理论都更有记忆点。4.3 升级、回滚与多环境复用讲完基本操作深入说说为什么Helm能真正解决多环境复用问题。利用模板语法你可以把镜像地址、副本数、资源限制、探针参数全部变量化。不同环境只需要提供不同values文件比如helm install my-app-prod ./my-app -f values-prod.yaml这样一份Chart可以同时部署到开发、测试、预发、生产多个环境只要区分Release名和values文件。模板中最常用的语法有两个一个是.values.xxx读取值另一个是模板函数。例如想在deployment中引用副本数replicas: {{ .Values.replicaCount }}想处理缩进问题多用nindent比如在env或containers列表里嵌套模板时env: {{- range .Values.env }} - name: {{ .name }} value: {{ .value }} {{- end }}这里range循环和缩进处理在刚开始写模板时最容易出错。我在最初踩过不少坑后来养成了一个习惯写完模板先helm template渲染肉眼检查格式再实际安装。不要直接用helm install盲发很多YAML解析错误都是渲染阶段才暴露的。升级回滚方面还有一个小技巧回滚前先查看某个版本的values到底是什么。helm get values my-release --revision 1它能输出该版本使用的values配置帮你快速定位“上一次到底改了什么参数导致出问题”。注意helm upgrade --set适合临时微调但它不会留下完整的values文件副本不方便追溯。生产环境建议把每个环境的values文件提交到Git仓库一切以文件为准。5. 问题自查表Dashboard、HPA、Helm的经典坑5.1 现象、原因、排查命令对照表我在实际使用中整理过一份速查表这几种问题出现频率最高照着查能节省不少时间。现象常见原因排查/处理命令Dashboard页面打不开NodePort端口被防火墙拦截或服务类型改错kubectl -n kubernetes-dashboard get svc检查安全组/防火墙对端口的放行Dashboard登录提示403Token对应的ServiceAccount缺少RBAC权限确认是否正确创建ClusterRoleBinding并绑定cluster-adminkubectl top node显示errormetrics-server未安装或kubelet证书校验失败kubectl get pod -n kube-system | grep metrics必要时配置--kubelet-insecure-tlsHPA状态一直显示UnknownPod没有声明resources.requests打开Deployment YAML检查每类容器是否定义了requests.cpuHPA副本不缩容缩容稳定窗口未到或metrics指标未恢复kubectl describe hpa查看Conditions和Eventshelm install卡住仓库不可达或Chart解析失败helm repo listhelm search repohelm lint本地检查helm upgrade后服务异常模板参数覆盖错误或镜像tag没有更新helm get values release --revision 版本号再helm rollback表格只列现象与方向具体怎么处理还要结合原来的YAML看。这里想强调一个通用排查思路K8s里任何“自动”行为出问题第一步永远是用describe查看资源状态和事件而不是瞎猜配置。HPA的describe输出里包含指标、稳定窗口、建议副本数等详细信息比只看get hpa有用得多。5.2 三个容易被忽略的“软细节”第一Dashboard的Token有效期问题。新版Dashboard生成的ServiceAccount token默认带时间戳不像以前的long-lived token能一直用。每次登录可能都要重新create token可能有些人会觉得麻烦但这是安全设计。如果觉得频繁可以使用Kubeconfig方式登录把kubeconfig文件交给有需要的人。第二HPA与Deployment版本升级之间的关系。直接对Deployment执行kubectl rollout restart或镜像升级时HPA所追踪的Pod实例会全部替换指标自然也会从零开始积累。如果你同时修改了单Pod的requests资源量HPA的扩容基准也会跟着变化。线上调优时先改requests再调HPA目标否则会出现副本数异常跳变。第三Helm的Release命名空间问题。如果你在helm install时没有指定命名空间默认会装到default后续helm upgrade如果不是在同样的命名空间或上下文操作很可能找不到Release或影响到错误环境。我的习惯是每个项目固定一个命名空间helm命令总是带上-n和--namespace这会省掉很多环境串台的坑。这些细节并不晦涩都是操作中会真实遇到的状况。把这些坑填平以后你会发现Dashboard、HPA、Helm三个组件其实承接的是一个生产闭环可视化观察集群、按量伸缩应用、可重复地发布和回滚代码。我个人在实际操作中的体会是这三块内容不必一口气全部上生产。先在自己的测试集群里把Dashboard和Helm用熟再逐步用HPA管理一两个不重要但流量波动明显的服务等完全掌握了扩缩容行为再推广到核心业务。不然一上来几个组件一起开出了问题都不知道找谁。最后再分享一个小技巧在HPA和Helm配合使用时可以把replica数写进values.yaml再把HPA的minReplicas和maxReplicas也参数化。这样每次调整副本范围时只需改values文件不用再跑到集群里单独edit HPA。毕竟能用声明式文件和参数解决的问题就不要靠命令行临时改。
阅读完成 · 觉得有帮助?
咨询建站