Kubernetes(简称K8s)已经成为容器编排的事实标准。从2014年Google开源Kubernetes到现在,它已经发展成为一个功能强大、生态完善的容器编排平台,越来越多的团队在生产环境中使用K8s来部署和管理应用。

我们团队从2016年开始在生产环境中使用Kubernetes,从最初的1.4版本用到现在的1.9版本,踩过不少坑,也积累了一些经验。很多团队在使用K8s的时候,只是用了最基本的功能,比如用Deployment部署服务、用Service暴露端口,并没有充分利用K8s的强大能力。今天就来分享一些K8s生产环境中的进阶技巧,希望能帮助大家更好地使用Kubernetes。

一、资源管理:合理设置requests和limits

资源管理是K8s最基础也是最重要的功能之一。通过为容器设置CPU和内存的requests和limits,K8s可以根据资源需求进行调度,保证服务的稳定运行。但是很多人在设置requests和limits的时候比较随意,要么设置得太大浪费资源,要么设置得太小导致服务被OOMKill或者CPU节流。

requests和limits的区别

首先要搞清楚requests和limits的区别:

  • requests:调度时使用的资源请求量。K8s调度器会根据节点上的可用资源(已经减去所有Pod的requests之和)来决定Pod可以调度到哪个节点。requests也是资源保证的基础,K8s会保证Pod至少能获得requests指定的资源量。
  • limits:资源使用的上限。容器使用的资源不能超过limits指定的量。如果内存使用超过limits,容器会被OOMKill;如果CPU使用超过limits,CPU会被节流(throttled),但是不会被杀掉。

一个常见的误解是,limits必须大于等于requests。实际上,limits可以等于requests,也可以大于requests,甚至可以不设置limits(但是不推荐)。当limits等于requests时,称为" Guaranteed QoS",K8s会保证这个Pod的资源,优先级最高。当limits大于requests时,称为"Burstable QoS",Pod可以在requests和limits之间弹性使用资源。当没有设置requests和limits时,称为"BestEffort QoS",优先级最低,资源紧张时最先被杀掉。

生产环境的建议

在生产环境中,我建议:

  1. 所有容器都要设置requests和limits。不要留空,否则Pod的QoS等级是BestEffort,资源紧张时会最先被杀掉,而且调度器也无法准确判断节点资源是否足够。
  1. CPU的requests和limits可以不一样,内存的requests和limits建议设成一样。CPU是可压缩资源,超过limits只是被节流,不会被杀掉,所以可以设置limits大于requests,允许服务在高峰期多使用一些CPU。但是内存是不可压缩资源,超过limits就会被OOMKill,所以如果limits大于requests,服务可能在内存使用超过requests但还没到limits的时候,因为节点内存不足而被杀掉(因为调度时只考虑了requests)。为了避免这种情况,建议把内存的requests和limits设成一样的值。
  1. 根据实际监控数据来设置,不要拍脑袋。很多人设置requests和limits的时候都是凭感觉,比如CPU设成1核、内存设成1Gi,但是实际上服务可能只需要0.1核CPU和200Mi内存。这样会造成大量的资源浪费。正确的做法是,先不设置limits(或者设大一点),让服务运行一段时间,通过监控(比如Heapster、Prometheus + Grafana)观察服务的实际资源使用情况,然后根据P95或者P99的使用量来设置requests和limits。
  1. 为系统组件预留资源。在节点上,除了运行我们的业务Pod,还要运行K8s的系统组件(比如kube-proxy、docker、kubelet等)以及操作系统本身。如果不预留资源,业务Pod可能会把节点资源占满,导致系统组件无法正常运行,整个节点出问题。可以通过kubelet的--system-reserved和--kube-reserved参数来为系统和K8s组件预留资源。

二、健康检查:livenessProbe和readinessProbe的正确使用

健康检查是K8s保证服务稳定运行的重要机制。通过livenessProbe(存活探针)和readinessProbe(就绪探针),K8s可以检测容器的健康状态,并采取相应的措施。但是很多人对这两个探针的理解不够深入,使用不当反而会造成问题。

livenessProbe和readinessProbe的区别

  • livenessProbe:检测容器是否还活着。如果livenessProbe失败,K8s会杀掉容器,然后根据重启策略决定是否重启。livenessProbe的目的是检测那些无法自动恢复的故障,比如死锁、程序卡死等,通过重启来恢复服务。
  • readinessProbe:检测容器是否准备好接收流量。如果readinessProbe失败,K8s会把这个Pod从Service的后端列表中移除,不再转发请求给它,但是不会杀掉容器。readinessProbe的目的是在服务还没准备好的时候(比如启动加载中、依赖服务不可用),不让它接收请求,避免返回错误。

常见的错误用法

  1. 用同一个探针同时做liveness和readiness。很多人图省事,把livenessProbe和readinessProbe设成一样的。这是不对的。livenessProbe应该检测服务是否还活着,只要进程没卡死就应该返回成功,条件可以宽松一些。readinessProbe应该检测服务是否真的准备好接收请求,条件要严格一些,比如依赖的服务是否可用、缓存是否加载完成等。如果两个探针一样,可能会导致服务在依赖暂时不可用时被频繁重启,反而更不稳定。
  1. livenessProbe设置得太严格。如果livenessProbe的条件太严格,比如要求依赖服务必须可用,那么当依赖服务暂时不可用时,livenessProbe会失败,导致容器被重启。但是重启之后,依赖服务还是不可用,livenessProbe还是失败,容器又被重启,形成恶性循环。所以livenessProbe只应该检测容器自身的健康状态,不要依赖外部服务。
  1. 没有设置initialDelaySeconds。initialDelaySeconds是探针开始检测前等待的时间,给容器启动留出时间。如果没有设置,容器刚启动,服务还没准备好,探针就开始检测了,可能会导致livenessProbe失败,容器被频繁重启。应该根据服务的启动时间来设置initialDelaySeconds,比如服务启动需要30秒,就设成30或者更大的值。
  1. readinessProbe失败后不恢复。readinessProbe失败后,Pod会被从Service中移除,但是如果之后服务恢复了,readinessProbe成功了,Pod会自动重新加入Service。这是正常的行为,不需要手动干预。但是有些人不知道这一点,看到Pod不在Service中就以为出问题了,手动重启Pod,其实没必要。

生产环境的建议

  1. livenessProbe用简单的检测方式,比如HTTP检测一个/healthz接口,这个接口只检查进程是否正常,不依赖外部服务。
  2. readinessProbe可以严格一些,检查依赖服务是否可用、数据是否加载完成等。
  3. 合理设置initialDelaySeconds、periodSeconds、timeoutSeconds、failureThreshold等参数。
  4. 对于启动慢的服务,可以用startupProbe(K8s 1.18+引入,2018年还没有,可以用较长的initialDelaySeconds替代)。

三、滚动更新:优雅地发布新版本

Deployment的滚动更新是K8s最常用的功能之一,它可以在不中断服务的情况下,逐步把旧版本替换成新版本。但是要实现真正的"零停机"滚动更新,需要注意很多细节。

滚动更新的参数

Deployment的滚动更新主要有两个参数:

  • maxUnavailable:滚动更新过程中,最多可以有多少个Pod不可用。可以是绝对值(比如2),也可以是百分比(比如25%)。
  • maxSurge:滚动更新过程中,最多可以比期望副本数多多少个Pod。同样可以是绝对值或百分比。

默认值是maxUnavailable=25%,maxSurge=25%。这意味着在滚动更新时,最多有25%的Pod会被替换,同时最多会多创建25%的Pod。

实现零停机的关键

要实现零停机的滚动更新,关键是保证在任何时候都有足够的健康Pod在处理请求。具体来说:

  1. 必须配置readinessProbe。这是最重要的一点。如果没有readinessProbe,K8s会认为容器一启动就准备好了,立即把它加入Service开始转发请求。但是这时候服务可能还没启动完成,请求进来就会失败。有了readinessProbe,K8s会等探针检测成功后,才把Pod加入Service,保证只有真正准备好的Pod才接收请求。
  1. 容器要能优雅地关闭。当K8s要删除一个旧Pod时,它会先给容器发送SIGTERM信号,然后等待terminationGracePeriodSeconds(默认30秒),如果容器还没退出,再发送SIGKILL强制杀掉。容器收到SIGTERM后,应该停止接收新请求,处理完正在处理的请求,然后退出。如果应用没有正确处理SIGTERM,被强制杀掉,正在处理的请求就会失败。

要实现优雅关闭,需要: - 应用监听SIGTERM信号,收到后开始优雅关闭流程。 - 在K8s删除Pod之前,readinessProbe应该先失败,让Pod从Service中移除,不再接收新请求。可以在preStop hook中先sleep几秒,给K8s时间把Pod从Service中移除。 - 处理完正在处理的请求后,退出进程。

  1. 合理设置maxUnavailable和maxSurge。如果服务的副本数比较少(比如只有2个),默认的25% maxUnavailable可能会导致在滚动更新时只有1个Pod在服务,如果这个Pod也出问题,服务就不可用了。对于副本数少的服务,可以把maxUnavailable设成0,maxSurge设成1或者更大,这样滚动更新时会先创建新Pod,等新Pod准备好后再删除旧Pod,保证始终有足够的Pod在服务。
  1. 配置PodDisruptionBudget(PDB)。PDB可以保证在自愿中断(比如滚动更新、节点维护)时,始终有一定数量的Pod在运行。比如设置minAvailable=1,K8s会保证在任何时候至少有1个Pod在运行,不会因为滚动更新或者节点维护而把所有Pod都删掉。PDB是保证服务高可用的重要手段,生产环境建议配置。

四、配置管理:ConfigMap和Secret的最佳实践

K8s提供了ConfigMap和Secret来管理配置信息,把配置和镜像解耦,不需要为了修改配置而重新构建镜像。但是在使用ConfigMap和Secret的时候,有一些需要注意的地方。

ConfigMap的使用方式

ConfigMap可以用来存储非敏感的配置信息,比如配置文件、环境变量、命令行参数等。使用方式有几种:

  1. 作为环境变量注入:通过valueFrom.configMapKeyRef把ConfigMap中的某个key作为环境变量注入容器。这种方式简单直接,但是修改ConfigMap后,已经运行的容器不会自动更新环境变量,需要重启Pod才能生效。
  1. 作为文件挂载到容器:通过volumes.configMap把整个ConfigMap挂载为一个目录,ConfigMap中的每个key成为一个文件。这种方式的好处是,ConfigMap更新后,挂载的文件会自动更新(K8s会定期同步),应用如果支持热加载配置,就能自动生效。但是要注意,有些应用不支持热加载,还是需要重启。
  1. 作为命令行参数:通过$(VAR_NAME)的方式引用环境变量,作为容器启动命令的参数。

Secret的使用方式

Secret和ConfigMap类似,但是用来存储敏感信息,比如密码、密钥、证书等。Secret在存储时是base64编码的(注意不是加密,只是编码,所以不要把Secret提交到代码仓库),在使用时会自动解码。

Secret的使用方式和ConfigMap类似,可以作为环境变量注入,也可以作为文件挂载。另外,还可以用imagePullSecrets来拉取私有镜像仓库的镜像。

最佳实践

  1. 不要把敏感信息放在ConfigMap中,要用Secret。虽然两者用法类似,但是Secret有专门的权限控制和管理机制,更适合存储敏感信息。
  1. 不要把ConfigMap/Secret提交到代码仓库。应该通过环境变量或者配置文件的方式在部署时注入,或者用Sealed Secrets、Vault等工具来管理加密的Secret。
  1. 挂载ConfigMap/Secret为文件时,注意子路径挂载的问题。如果用subPath挂载ConfigMap中的某个文件到容器的特定路径,ConfigMap更新后,这个文件不会自动更新。这是因为subPath挂载的是文件本身,而不是目录,K8s不会更新subPath挂载的文件。如果需要自动更新,就挂载整个目录,不要用subPath。
  1. 配置变更后触发滚动更新。如果应用不支持热加载配置,修改ConfigMap后需要重启Pod才能生效。可以通过修改Deployment的template.annotations来触发滚动更新,比如加一个annotation记录配置的版本号或更新时间,这样K8s会认为Pod模板变了,触发滚动更新。
  1. 为不同环境创建不同的ConfigMap/Secret。开发、测试、生产环境的配置不一样,应该为每个环境创建独立的ConfigMap/Secret,通过命名空间或者命名规范来区分。不要把所有环境的配置都放在一个ConfigMap里,也不要在镜像中硬编码环境相关的配置。

五、存储:PersistentVolume和StatefulSet

K8s中的存储是一个比较复杂的话题。对于无状态服务,不需要持久化存储,直接用emptyDir或者不需要存储就可以了。但是对于有状态服务(比如数据库、消息队列),就需要持久化存储了。

PV和PVC的概念

  • PersistentVolume(PV):集群中的一块持久化存储资源,由管理员预先创建,或者通过StorageClass动态创建。PV是集群级别的资源,不属于某个命名空间。
  • PersistentVolumeClaim(PVC):用户对持久化存储的请求,比如需要多大的存储、什么访问模式。PVC是命名空间级别的资源,Pod通过挂载PVC来使用持久化存储。

PV和PVC的关系就像Node和Pod的关系:Node提供计算资源,Pod请求计算资源;PV提供存储资源,PVC请求存储资源。K8s会自动把合适的PV绑定到PVC上。

StorageClass动态供给

如果每次需要存储都要管理员手动创建PV,太麻烦了。StorageClass可以实现存储的动态供给:用户创建PVC时指定StorageClass,K8s会自动创建对应的PV,不需要管理员手动创建。

StorageClass通过provisioner来指定使用什么存储后端,比如AWSElasticBlockStore、GCEPersistentDisk、Ceph RBD、NFS等。不同的存储后端有不同的provisioner,需要根据实际环境来配置。

生产环境中建议使用StorageClass动态供给,这样管理起来更方便,也更灵活。

StatefulSet

对于有状态服务,Deployment不太适合,因为Deployment创建的Pod是无状态的,Pod的名字、IP都是随机的,重启后会变。而StatefulSet创建的Pod有稳定的标识:

  • 稳定的Pod名称:按照序号命名,比如web-0、web-1、web-2。
  • 稳定的DNS名称:通过Headless Service为每个Pod提供稳定的DNS地址。
  • 稳定的持久化存储:每个Pod有自己独立的PVC,Pod重启后还是挂载原来的PVC。

StatefulSet适合部署数据库、消息队列、ZooKeeper、etcd等有状态服务。

生产环境的建议

  1. 数据库等有状态服务用StatefulSet部署,不要用Deployment。
  2. 使用StorageClass动态供给PV,不要手动创建PV。
  3. 为重要数据配置定期备份。PV只是提供了持久化存储,但是如果数据误删或者PV损坏,数据还是会丢失。应该定期备份数据,比如用Velero(原Heptio Ark)来备份K8s资源和PV数据。
  4. 注意PV的回收策略。PV的reclaimPolicy可以是Retain(保留,PVC删除后PV和数据都保留,需要手动清理)、Delete(删除,PVC删除后PV和数据都自动删除)、Recycle(回收,已废弃)。生产环境建议用Retain,避免误删PVC导致数据丢失。
  5. 数据库不建议直接跑在K8s上。虽然K8s可以部署有状态服务,但是数据库对性能、稳定性、数据安全的要求很高,跑在K8s上可能会有性能损耗和运维复杂度增加的问题。如果团队的K8s运维经验不够丰富,建议数据库还是跑在专门的虚拟机或者云服务上(比如AWS RDS、阿里云RDS),K8s只跑无状态的应用服务。

六、网络:Service、Ingress和网络策略

K8s的网络是另一个复杂的话题。K8s的网络模型要求:

  1. 所有Pod之间可以直接通信,不需要NAT。
  2. 所有节点和Pod之间可以直接通信,不需要NAT。
  3. Pod看到的自己的IP和其他Pod看到的它的IP是一样的。

为了实现这个网络模型,需要安装网络插件(CNI),比如Flannel、Calico、Weave等。

Service

Service是K8s中用来暴露服务的抽象。因为Pod的IP是不稳定的(重启后会变),所以需要Service来提供一个稳定的访问入口。Service有几种类型:

  • ClusterIP:默认类型,只在集群内部可访问,通过集群内部的IP来访问服务。
  • NodePort:在每个节点上开放一个端口,通过节点IP+端口来访问服务。
  • LoadBalancer:使用云服务商的负载均衡器来暴露服务,需要云服务商支持。
  • ExternalName:通过CNAME把Service映射到外部域名。

Service通过label selector来选择后端Pod,把请求负载均衡到后端Pod上。默认的负载均衡策略是轮询(Round Robin)。

Ingress

Service的NodePort和LoadBalancer类型可以暴露服务到外部,但是NodePort的端口范围有限(30000-32767),而且不支持基于域名和路径的路由。LoadBalancer需要云服务商支持,而且每个服务一个负载均衡器,成本比较高。

Ingress就是为了解决这些问题的。Ingress是K8s中的一个API对象,用来管理集群外部到内部服务的HTTP/HTTPS路由。Ingress支持基于域名和路径的路由、TLS终止、负载均衡等功能。

Ingress本身只是一个配置,需要Ingress Controller来实际执行。常用的Ingress Controller有nginx-ingress、traefik、istio等。生产环境中最常用的是nginx-ingress,它基于Nginx,功能强大,性能也不错。

NetworkPolicy

默认情况下,K8s中所有Pod之间都可以互相通信,没有任何限制。这在生产环境中可能不太安全,因为如果某个Pod被攻破,攻击者可以访问集群内所有的服务。

NetworkPolicy(网络策略)可以用来限制Pod之间的网络访问,实现微服务之间的网络隔离。通过NetworkPolicy,可以指定哪些Pod可以访问哪些Pod、哪些端口,实现白名单机制。

NetworkPolicy需要网络插件支持,比如Calico、Weave等。Flannel默认不支持NetworkPolicy,如果需要网络策略,建议用Calico。

生产环境的建议

  1. 选择合适的网络插件。如果需要NetworkPolicy,用Calico;如果只需要简单的网络,Flannel就够了。Calico的性能和功能都比较强,生产环境推荐使用。
  2. 集群内部用ClusterIP Service,外部访问用Ingress。不要用NodePort暴露服务到生产环境,端口管理麻烦,也不安全。
  3. 配置Ingress的TLS终止,用HTTPS访问服务,不要用HTTP明文传输。
  4. 为重要服务配置NetworkPolicy,限制只有必要的服务可以访问,实现最小权限原则。
  5. 注意Service的sessionAffinity。如果需要会话保持(比如有状态的应用),可以设置Service的sessionAffinity为ClientIP,让同一个客户端的请求总是转发到同一个后端Pod。

七、监控和日志:可观测性的三大支柱

生产环境中的K8s集群,监控和日志是必不可少的。没有监控和日志,出了问题都不知道怎么回事,更别说排查了。可观测性有三大支柱:指标(Metrics)、日志(Logs)、链路追踪(Tracing)。

指标监控

指标是数值型的时间序列数据,比如CPU使用率、内存使用率、请求QPS、响应时间等。K8s的指标监控常用的方案是Prometheus + Grafana:

  • Prometheus:时序数据库,用来收集和存储指标数据。Prometheus通过pull的方式从目标(exporter)拉取指标。
  • Grafana:数据可视化工具,用来展示Prometheus中的指标,制作仪表盘。

需要监控的指标包括:

  • 集群层面:节点的CPU、内存、磁盘、网络使用率,Pod的数量、状态等。
  • 应用层面:服务的QPS、响应时间、错误率、业务指标等。
  • K8s组件层面:kubelet、kube-apiserver、etcd等组件的健康状态和性能指标。

可以用node-exporter收集节点指标,用kube-state-metrics收集K8s资源状态指标,用应用自带的exporter或者Prometheus client库收集应用指标。

日志收集

日志是应用输出的文本信息,用来记录应用的运行状态、错误信息、用户操作等。K8s中的日志收集常用的方案是EFK(Elasticsearch + Fluentd + Kibana)或者ELK(Elasticsearch + Logstash + Kibana):

  • Elasticsearch:搜索引擎,用来存储和检索日志。
  • Fluentd/Logstash:日志收集和处理工具,从各个节点收集容器日志,处理后发送到Elasticsearch。
  • Kibana:日志可视化工具,用来搜索、分析、展示日志。

K8s中容器的日志默认输出到stdout/stderr,Docker会把这些日志保存到节点上的json文件中。Fluentd以DaemonSet的方式运行在每个节点上,读取这些日志文件,收集并发送到Elasticsearch。

日志收集的注意事项:

  • 应用日志要输出到stdout/stderr,不要写文件,这样K8s才能统一收集。
  • 日志要结构化(比如JSON格式),方便后续的检索和分析。
  • 日志要包含必要的信息,比如时间、级别、服务名、traceId等,方便排查问题。
  • 注意Elasticsearch的存储和性能,日志量很大时需要合理配置索引和生命周期管理。

链路追踪

链路追踪用来记录一个请求在分布式系统中的调用链路,包括经过了哪些服务、每个服务的耗时、是否有错误等。在微服务架构中,一个请求可能会经过多个服务,出了问题很难定位是哪个服务的问题,链路追踪可以帮助快速定位。

常用的链路追踪工具是Jaeger和Zipkin,它们都兼容OpenTracing标准。应用需要集成OpenTracing client,在请求入口创建span,在调用下游服务时传递traceId,记录每个服务的调用信息。

链路追踪的注意事项:

  • 要在整个调用链中传递traceId,包括HTTP header、消息队列的message header等。
  • 采样率要合理,100%采样会有性能损耗和存储压力,生产环境可以用较低的采样率(比如1%),出问题时再动态调高。
  • 链路追踪要和日志、指标关联起来,通过traceId可以把同一个请求的日志和指标关联起来,方便排查。

生产环境的建议

  1. 监控和日志要在集群搭建初期就配置好,不要等出了问题才想起来加。
  2. 配置告警规则,当指标异常时(比如错误率升高、响应时间变长、节点资源不足),及时通知运维人员。
  3. 监控要覆盖所有层面:基础设施、K8s组件、应用、业务指标,都要监控。
  4. 日志要合理设置保留时间,不需要永久保存,一般保留7-30天就够了,重要的日志可以归档。
  5. 定期演练故障排查,确保监控和日志真的能帮助定位问题,而不是摆设。

八、安全:K8s集群的安全加固

K8s集群的安全是一个很重要但是经常被忽视的话题。K8s的功能很强大,但是如果配置不当,也会有安全风险。生产环境中的K8s集群需要做好安全加固。

API Server的安全

API Server是K8s的入口,所有的操作都通过API Server进行,所以API Server的安全至关重要。

  1. 启用TLS:API Server必须启用HTTPS,所有通信都要加密。不要用HTTP明文通信。
  2. 启用认证:不要允许匿名访问,所有请求都要经过认证。常用的认证方式有客户端证书、Bearer Token、OpenID Connect等。
  3. 启用授权:认证之后还要授权,确定用户有哪些权限。K8s默认用RBAC(基于角色的访问控制),应该启用RBAC,为不同的用户和服务账号分配最小必要的权限。
  4. 限制API Server的访问:不要把API Server暴露到公网,应该放在内网,通过VPN或者堡垒机访问。如果需要公网访问,要配置防火墙限制来源IP。

容器安全

容器是K8s中运行应用的基本单位,容器安全也很重要。

  1. 不要用root用户运行容器:容器中的应用应该用非root用户运行,在Dockerfile中用USER指令指定用户,或者在Pod的securityContext中设置runAsUser。
  2. 设置安全上下文:通过Pod和容器的securityContext,可以设置很多安全选项,比如runAsNonRoot(禁止用root运行)、readOnlyRootFilesystem(根文件系统只读)、allowPrivilegeEscalation(禁止权限提升)、capabilities(限制Linux capabilities)等。
  3. 不要使用特权容器:特权容器(privileged: true)拥有宿主机的所有权限,非常危险,除非绝对必要,否则不要用。
  4. 镜像安全:使用可信的基础镜像,不要用来源不明的镜像。定期扫描镜像漏洞,及时更新基础镜像。不要把敏感信息(密码、密钥)打包到镜像中。

网络安全

前面提到过NetworkPolicy,可以用来限制Pod之间的网络访问。除此之外,还有一些网络安全的注意事项:

  1. 默认拒绝所有入站流量:先创建一个默认拒绝所有入站流量的NetworkPolicy,然后再为需要的服务单独开放访问权限。这样可以实现白名单机制,更安全。
  2. 敏感服务不要暴露到公网:比如数据库、管理后台等,只允许集群内部或者特定IP访问。
  3. 用Ingress做TLS终止,外部访问用HTTPS,不要用HTTP。

其他安全建议

  1. 定期更新K8s版本:K8s社区会定期发布安全补丁,要及时更新,避免已知的安全漏洞。
  2. 限制节点的直接访问:不要让用户直接登录节点,通过K8s API来操作。如果需要登录节点,用堡垒机,并且记录操作日志。
  3. etcd的安全:etcd存储了K8s集群的所有数据,包括Secret,所以etcd的安全很重要。etcd要启用TLS,限制访问,定期备份。
  4. 审计日志:启用K8s的审计日志,记录所有API Server的操作,方便安全事件的追溯和排查。

九、总结

Kubernetes是一个功能强大但是也很复杂的系统。要在生产环境中用好K8s,需要掌握很多方面的知识,包括资源管理、健康检查、滚动更新、配置管理、存储、网络、监控、安全等。

本文分享了一些K8s生产实践中的进阶技巧,希望能帮助大家更好地使用Kubernetes。但是K8s的知识远不止这些,还有很多内容没有覆盖到,比如调度策略、自定义资源(CRD)、Operator、服务网格(Service Mesh)等。

技术在不断发展,K8s也在不断更新,新的功能和特性层出不穷。作为技术人,我们要保持学习的热情,不断探索和实践,才能跟上技术的发展。

最后想说的是,K8s只是一个工具,最终目的是为了更好地交付和运行应用。不要为了用K8s而用K8s,要根据团队的实际情况和需求来选择合适的技术栈。如果团队规模小、应用简单,可能用Docker Compose或者简单的部署方式就够了,不需要上K8s。技术选型要务实,适合自己的才是最好的。