我们把Kubernetes集群升级到1.22版本之后,踩了很多坑,也总结了很多最佳实践。本文从集群搭建、资源管理、安全、网络、存储、监控、升级等方面,详细介绍了K8s 1.22+的最佳实践。如果你在用Kubernetes,或者打算升级到新版本,希望这些经验能帮到你。
一、背景
先说说我们的情况。
我们的业务跑在Kubernetes集群上,最开始用的是1.18版本,跑了一年多,一直很稳定。后来1.18版本停止维护了,我们决定升级到1.22版本。
升级的过程比想象中顺利,但是升级之后遇到了很多问题。有些API被废弃了,有些默认行为变了,有些新特性需要适配。我们花了大概一个月的时间,才把集群完全稳定下来。
在这个过程中,我们踩了很多坑,也总结了很多最佳实践。本文就来分享这些经验,希望能帮到正在用K8s或者打算升级的你。
二、集群搭建最佳实践
1. 版本选择
K8s的版本更新很快,大概每三四个月发布一个小版本。选择版本的时候,建议选稳定的、经过社区验证的版本,不要追最新版。
1.22版本是一个比较稳定的版本,但是要注意它移除了一些已经废弃的API(比如beta版的Ingress、CertificateSigningRequest等)。如果你的集群里还在用这些API,升级之前要先迁移。
建议选奇数版本还是偶数版本?其实都可以,关键是看社区的支持情况和你的业务需求。
2. 集群规模
集群的规模要根据业务需求来定,不要太大也不要太小。单个集群的节点数建议不要超过500个,Pod数不要超过15万个,否则管理和调度会有压力。
如果业务规模很大,建议用多集群的方案,每个集群负责一部分业务,通过联邦或者服务网格来管理。
3. 高可用
生产环境的集群一定要高可用。控制平面(etcd、kube-apiserver、kube-controller-manager、kube-scheduler)至少部署3个节点,etcd用3节点或者5节点的集群。
工作节点也要分布在不同的可用区,避免单个可用区故障导致服务不可用。
4. 网络插件
网络插件的选择很重要,常用的有Calico、Flannel、Cilium等。
Calico功能强大,支持网络策略、BGP等,适合大多数场景。Flannel简单轻量,适合小规模集群。Cilium基于eBPF,性能好,可观测性强,是未来的趋势。
我们用的是Calico,运行很稳定。如果是新集群,可以考虑Cilium,性能和功能都更好。
三、资源管理最佳实践
1. 资源请求和限制
每个容器都应该设置资源请求(requests)和限制(limits)。资源请求帮助调度器合理分配节点,资源限制防止单个容器占用太多资源影响其他容器。
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"CPU的limits和requests建议设置成一样的,或者limits是requests的2倍以内。如果limits远大于requests,可能会导致节点超卖,影响稳定性。
内存的limits一定要设置,因为内存是不可压缩资源,OOM会直接杀掉容器。
2. 命名空间和资源配额
用命名空间来隔离不同的环境(开发、测试、生产)或者不同的团队。每个命名空间设置资源配额(ResourceQuota),限制可以使用的CPU、内存、存储等资源,防止某个团队或者环境占用太多资源。
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi3. 优先级和抢占
对于重要的服务,设置高优先级(PriorityClass),在节点资源不足的时候,优先保证重要服务的运行。低优先级的Pod会被抢占,为高优先级的Pod腾出资源。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000
globalDefault: false
description: "高优先级服务"但是要注意,不要滥用高优先级,否则会导致低优先级的服务一直被抢占,无法运行。
四、安全最佳实践
1. RBAC权限控制
用RBAC(基于角色的访问控制)来管理权限,遵循最小权限原则。每个服务账号和用户只授予必要的权限,不要给cluster-admin这样的超级权限。
定期审计RBAC权限,清理不需要的权限和服务账号。
2. 镜像安全
使用可信的镜像源,不要用未知来源的镜像。镜像要定期扫描漏洞,及时修复。
用私有镜像仓库,管理镜像的访问权限。镜像要打标签,不要用latest标签,用具体的版本号,方便追溯。
3. Pod安全标准
K8s 1.22引入了Pod安全标准(Pod Security Standards),替代了之前的PodSecurityPolicy。通过命名空间的标签来设置安全策略,限制Pod的特权行为。
apiVersion: v1
kind: Namespace
metadata:
name: restricted
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted建议生产环境用restricted策略,禁止特权容器、禁止以root运行、禁止挂载宿主机路径等。
4. 网络策略
用网络策略(NetworkPolicy)来控制Pod之间的网络访问,默认拒绝所有入站和出站流量,只开放必要的端口和通信。
这样可以防止被入侵的Pod横向移动,提升集群的安全性。
5. 密钥管理
敏感信息(密码、密钥、证书)用Secret来管理,不要写在镜像里或者配置文件里。Secret要加密存储,不要提交到代码仓库。
可以用外部的密钥管理服务(比如Vault、云厂商的KMS)来管理密钥,比K8s原生的Secret更安全。
五、网络最佳实践
1. Service类型选择
Service的类型根据需求选择:
- ClusterIP:集群内部访问,默认类型
- NodePort:通过节点端口访问,适合测试或者有外部负载均衡的场景
- LoadBalancer:通过云厂商的负载均衡器访问,适合生产环境的对外服务
- ExternalName:通过DNS别名访问外部服务
对外服务建议用Ingress或者LoadBalancer,不要直接用NodePort暴露到公网。
2. Ingress配置
用Ingress来管理HTTP/HTTPS的入口,统一管理域名、TLS证书、路由规则。
常用的Ingress控制器有nginx-ingress、traefik、istio等。nginx-ingress最常用,功能稳定。traefik更轻量,配置简单。istio功能最强大,但是复杂度也高。
TLS证书建议用cert-manager自动申请和续期,不要手动管理证书。
3. DNS配置
K8s的DNS(CoreDNS)要配置好,确保服务发现正常。对于大规模集群,可以调整CoreDNS的副本数和缓存配置,提升DNS解析性能。
Pod的DNS策略用默认的ClusterFirst就可以,不需要特殊配置。
六、存储最佳实践
1. StorageClass
用StorageClass来动态管理存储,不要手动创建PV。不同的存储类型(SSD、HDD、网络存储)创建不同的StorageClass,根据业务需求选择。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Delete
allowVolumeExpansion: true2. 有状态服务
有状态服务(数据库、消息队列等)用StatefulSet来部署,保证稳定的网络标识和持久化存储。
重要的有状态服务建议用Operator来管理,比如PostgreSQL Operator、Redis Operator等,比手动管理更方便、更可靠。
3. 数据备份
重要的数据一定要定期备份,不要只依赖K8s的持久化卷。可以用Velero等工具来备份集群资源和持久化数据。
备份要定期验证,确保备份是可用的。不要等出了问题才发现备份不能用。
七、监控和日志最佳实践
1. 监控体系
建立完善的监控体系,包括集群监控、节点监控、Pod监控、应用监控。
常用的监控方案是Prometheus + Grafana。Prometheus负责采集和存储指标,Grafana负责可视化展示。
关键指标要设置告警,比如CPU使用率、内存使用率、Pod重启次数、服务可用性等。告警要分级,严重告警及时通知,一般告警汇总通知。
2. 日志管理
用ELK(Elasticsearch + Logstash + Kibana)或者Loki来收集和管理日志。Pod的日志要集中收集,不要只存在节点上,因为Pod可能会被销毁。
日志要设置合理的保留时间,不要保留太久,否则存储成本很高。重要的日志可以长期归档。
3. 链路追踪
对于微服务架构,建议用链路追踪(比如Jaeger、Zipkin)来追踪请求的完整链路,方便排查性能问题和故障。
八、升级最佳实践
1. 升级前准备
升级之前要做好准备:
- 阅读版本变更说明,了解新特性和破坏性变更
- 检查废弃的API,提前迁移
- 备份集群数据和etcd
- 在测试环境先升级验证
- 制定回滚方案
2. 滚动升级
控制平面的组件逐个升级,先升级etcd,再升级kube-apiserver,然后是kube-controller-manager和kube-scheduler。
工作节点滚动升级,先排空(drain)节点,再升级,最后恢复。一次只升级一个节点,确保服务不受影响。
3. 升级后验证
升级完成之后,要全面验证:
- 集群组件状态正常
- 所有Pod正常运行
- 服务可以正常访问
- 监控和日志正常
- 跑一下核心业务的测试用例
九、常见坑和解决方案
分享一些我们踩过的坑。
坑1:API废弃导致升级失败
K8s 1.22移除了很多beta版的API,比如extensions/v1beta1的Ingress。如果你的集群里还在用这些API,升级之后会报错。
解决方案:升级之前用kubectl api-resources检查,把废弃的API都迁移到稳定版本。
坑2:内存OOM导致Pod被杀
没有设置内存limits,或者limits设置太大,导致节点内存不足,Pod被OOM杀掉。
解决方案:每个容器都设置合理的内存limits,监控节点内存使用率,及时扩容。
坑3:镜像拉取失败
镜像仓库不稳定,或者镜像标签不对,导致Pod启动失败。
解决方案:用私有镜像仓库,镜像用具体的版本标签,设置imagePullPolicy为IfNotPresent。
坑4:PV挂载失败
存储类配置不对,或者节点没有安装存储驱动,导致PV挂载失败。
解决方案:确保StorageClass配置正确,节点安装了对应的存储驱动,测试动态 provisioning 是否正常。
十、写在最后
Kubernetes是一个强大但是复杂的系统,用好它需要不断学习和实践。1.22版本引入了很多新特性,也有一些破坏性变更,升级和使用的时候要注意。
本文总结的最佳实践,是我们在实际使用中踩坑踩出来的经验,希望能帮到你。但是每个集群的情况都不一样,最佳实践也需要根据自己的业务来调整。
K8s的生态还在快速发展,新的工具和最佳实践不断涌现。保持学习,跟上社区的发展,才能用好K8s,让它为业务服务。
最后用一句话结束本文:"K8s不是银弹,但是用好它能大大提升业务的效率和稳定性。"愿每一个运维和开发都能驾驭K8s,让容器编排变得简单可靠。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录