部署metrics-server
Metrics Server 是 Kubernetes 的“实时仪表盘采集器”,它的核心作用是收集集群内 Pod 和 Node 的实时资源使用率(CPU 和内存),并供外部工具(如 HPA 或 kubectl top)读取
有两种部署方式,这里笔者选择yaml文件部署
helm方式
激活metrics-server
vim kubernetes-dashboard/values.yaml
metrics-server:
enabled: true
修改镜像位置
vim kubernetes-dashboard/charts/metrics-server/values.yaml
image:
repository: reg.westos.org/metrics-server/metrics-server
tag: "v0.8.0"
使用helm更新部署
helm upgrade kubernetesui kubernetes-dashboard --namespace kubernetes-dashboard
查看资源
kubectl -n kubernetes-dashboard get all
查看资源使用量
kubectl top node
kubectl top pod
yaml文件部署
下载部署文件
https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
跳过证书验证,修改镜像源
拉取所需镜像,打标签并上传
应用,查看
部署HPA应用
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "php"
spec:
replicas: 1
selector:
matchLabels:
app: "php"
template:
metadata:
labels:
app: "php"
spec:
containers:
- name: "phpapp"
image: "reg.westos.org/metrics-server/hpa-example"
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
# memory: 256Mi
---
apiVersion: "v1"
kind: "Service"
metadata:
name: "php"
spec:
ports:
- name: "http"
protocol: "TCP"
port: 80
selector:
app: "php"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: php
spec:
ingressClassName: nginx
rules:
- host: php.example.com
http:
paths:
- path: /
backend:
service:
name: php
port:
name: http
pathType: ImplementationSpecific
Helmchart包管理
Helm Chart 核心作用
1. 打包整套复杂应用,告别零散 yaml
一个完整应用往往包含:Deployment、Service、Ingress、ConfigMap、Secret、RBAC、CRD、StorageClass、StatefulSet 等几十份 yaml。
- 原生方式:手动维护一堆 yaml,依次
kubectl apply,顺序容易错、漏资源; - Helm Chart:全部打包成一个包,一条命令完成整套安装
2. 模板化 + 配置分离,一套模板多环境复用
资源模板写死在templates,变量抽离到 values.yaml。 不同环境可以写多套 values:values-dev.yaml、values-prod.yaml
3. 版本管理:安装、升级、回滚
Helm 引入Release(版本实例):每一次在集群安装 Chart,生成一个 Release。
helm install:新建 Releasehelm upgrade:升级 Release(修改 values / 换新版 chart)helm rollback <release名> <revision>:一键回滚到上一个版本helm list:查看集群中所有已部署的 Releasehelm uninstall:卸载整套应用,清理所有相关 K8s 资源
原生 kubectl 没有应用级别的版本记录,改 yaml 出错很难一键回滚整套资源。
4. 依赖管理(子 Chart)
Chart 可以声明依赖(在 Chart.yaml 或 requirements.yaml),自动拉取依赖包。 例:业务 Chart 依赖一个存储 Chart(自动部署 CSI+StorageClass),安装业务包时会自动安装存储组件。
5. 仓库机制(Repo)
Chart 可以存放在 Chart 仓库(类似 yum 源),公开仓库:Bitnami、Longhorn、Rook 等。
6. 可复用、标准化、便于 CI/CD
- 团队统一 Chart 规范,所有环境部署逻辑一致,减少人为操作差异;
- CI 流水线可以直接调用 helm 命令做部署,适合 GitOps。
官网: https://helm.sh/zh/docs/intro/quickstart/
https://github.com/helm/helm/releases
配置helm命令补齐
使用helm管理应用
查询官方应用中心
# helm search hub nginx
添加第三方repo源
查询chart
拉取chart
部署chart
global:
imageRegistry: "reg.westos.org"
security:
allowInsecureImages: true
上传所需镜像
查询资源
helm list-n redis
helm -n redis status redis
helm-n redisget manifestredis| kubectl get -f -
更新chart
global:
imageRegistry: "reg.westos.org"
security:
allowInsecureImages: true
redis:
password: "westos"
sentinel:
enabled: true
封装chart包
修改chart
检测语法
打包
部署应用
访问
回收
上传chart到OCI仓库
使用harbor存储和管理chart
复制仓库证书
登录仓库
查看默认缓存信息
提前在harbor仓库创建charts项目,这个仓库专门存放chart包
上传chart
下载chart,默认下载最新版本
安装chart
测试
再次打包上传chart
需要先修改下chart信息,Chart.yaml,appversion也要改为v2
value.yaml
升级
测试
部署历史
回滚
测试
查看历史,多了一条回滚的历史
回收
helm部署storageclass
Helm 一键部署 CSI 存储插件,并自动生成 StorageClass,开启 K8s 集群动态持久化存储,业务 PVC 自动分配存储卷,不用人工维护 PV
删除原有的部署
添加repo
寻找所需chart包
将该文件放在部署了helm的主机
image:
repository: reg.westos.org/sig-storage/nfs-subdir-external-provisioner
nfs:
server: 192.168.154.201
path: /nfsdata
storageClass:
defaultClass: true
reclaimPolicy: Delete
archiveOnDelete: false #这里填写了false,之后的实验中不会自动恢复删除的pvc
创建ns
测试
注意创建时间为28s的条目
没有生成新的data
helm部署ingress-nginx
ingress-nginx 本质是 K8s 的 Ingress 控制器,Helm 是用来一键安装它的包管理工具
Ingress 资源只是规则,ingress-nginx 才是真正的负载 / 反向代理程序:K8s 原生 Ingress 只是路由规则对象,没有控制器不会生效;ingress-nginx 以 Nginx 为内核,监听集群 Ingress 规则,动态更新 Nginx 配置。
对外暴露集群内服务:统一入口,用域名 / 路径区分后端不同 Pod 服务,不用为每个业务单独建 LoadBalancer/NodePort Service,节约端口和公网 IP。
支持 HTTP/HTTPS、域名路由、路径路由、SSL 证书、限流、重写、会话保持等 Nginx 能力。
Helm 的价值:ingress-nginx 组件多(Deployment、ConfigMap、RBAC、Service、IngressClass 等),Helm Chart 打包全套资源,通过 values.yaml 灵活配置(外部访问类型、资源配额、ssl、日志、参数调优),实现一键安装、升级、回滚、卸载,便于多环境统一管理。
回收原有部署
添加repo源
寻找ingress-nginx的chart包
注意镜像私有仓库中是否具备
global:
image:
registry: reg.westos.org
controller:
image:
image: ingress-nginx/controller
tag: "v1.13.3"
digest: ""
digestChroot: ""
ingressClassResource:
name: nginx
default: true
service:
type: LoadBalancer # 需要metallb的支持
admissionWebhooks:
patch:
image:
registry: reg.westos.org
image: ingress-nginx/kube-webhook-certgen
tag: v1.6.3
digest: ""
defaultBackend:
enabled: true
name: defaultbackend
image:
registry: reg.westos.org
image: ingress-nginx/defaultbackend-amd64
tag: "1.5"
测试
回收
k8s调度
nodename
强制固定节点,跳过调度器
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: reg.westos.org/library/nginx:latest
nodeName: k8s3 #找不到节点pod会出现pending,优先级最高
回收
nodeselector
最简单标签匹配;Pod 写标签 KV,只会调度到拥有对应标签的节点;硬约束,不满足就 Pending
Key(键)= 名字;Value(值)= 对应的数据。一一对应的key: value结构,就是 KV 对
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: reg.westos.org/library/nginx:latest
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
为目标节点打上标签后应用yaml文件
查看
回收
这里去除k8s2的标签,重新应用,发现部署在k8s3上
nodeaffinity
两种规则:
requiredDuringSchedulingIgnoredDuringExecution:硬约束,必须满足,不满足不调度
preferredDuringSchedulingIgnoredDuringExecution:软约束,优先选,找不到也可以放其他节点
apiVersion: v1
kind: Pod
metadata:
name: node-affinity
spec:
containers:
- name: nginx
image: reg.westos.org/library/nginx:latest
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- fc
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s3
最后的event里可以看到选择了k8s3(由于没有符合的标签)
回收
podaffinity
吸引,尽量把 Pod 调度到和指定 Pod同一个拓扑域(同节点 / 同机架 / 同可用区),适合服务之间高频通信
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: reg.westos.org/library/nginx:latest
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
回收
podantiaffinity
排斥,避免多个同业务 Pod 落在同一节点,实现高可用(比如多副本分散在不同 node)
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: reg.westos.org/library/nginx:latest
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
回收
pod反亲和倾向满足
"倾向满足"指 Kubernetes 调度器会尽量遵守反亲和规则,但若集群中没有其他符合条件的节点,仍会将 Pod 调度到不满足规则的节点上,属于软约束,不会导致 Pod 调度失败
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-affinity
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
containers:
- name: nginx
image: nginx
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- sata
Taints
Taint 污点:打在 Node 上,节点拒绝不带容忍的 Pod。3 种效应:
NoSchedule:新 Pod 不能调度上去,已有 Pod 继续跑
PreferNoSchedule:尽量不调度,非强制
NoExecute:不仅不调度,还驱逐节点上不匹配的老 Pod
Tolerations 容忍:打在 Pod 上,Pod 声明可以接受节点的污点,才能调度到该节点
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: reg.westos.org/library/nginx:latest
name: nginx
设置taint
增加副本
新增的pod都在k8s2上
更改污点类型
所有的pod转移到k8s2上
回收
设置 tolerations
这里笔者的内存不足,理想情况下应用后pod会被调度到没有污点的node上
回收
kubectl delete -f taint.yaml
容忍所有taints
应用之后可以看到pod被调度到了有污点的k8s3上
回收
回收污点
cordon、drain、delete
cordon:禁止新 Pod 调度到该节点;已经在节点上运行的 Pod 不受影响,继续正常跑
drain:自动执行 cordon + 驱逐节点上所有业务 Pod
delete:把这个 Node 对象从 k8s APIServer 中删掉
新建的都在k8s3上
测试drain
k8s3节点重启kubelet服务重新加入集群