Skip to content

1. 如何调试 Kubernetes 集群中的网络连接问题,比如 Pod 间通信失败的情况?

  1. 状态检查:使用 kubectl get podskubectl describe pod 确认 Pod 状态及事件。
  2. 网络策略审查:检查是否有NetworkPolicy阻止通信。
  3. DNS验证:在 Pod 内执行 nslookup 检查服务名称解析。
  4. 连通性测试:使用 pingnc 测试到目标 Pod IP 的连通性。
  5. 网络插件检查:确保网络插件(如Calico, Flannel)运行正常,检查其 Pod 状态。
  6. 接口与路由:检查节点上的网络接口配置和路由规则。
  7. 抓包分析:必要时,在 Pod 或节点层面使用 tcpdump 抓包。
  8. 日志审查:分析 kubelet、网络插件及 API Server 日志。
  9. 外部因素:检查防火墙规则、安全组及外部 DNS 配置。

2. 阐述 Kubernetes 中的资源配额(ResourceQuota)和 LimitRange,它们是如何帮助集群资源管理?

ResourceQuota: ResourceQuota 允许咱们在命名空间级别设置资源使用上限,包括CPU、内存、存储、Pod数量、服务数量等多种资源类型。这有助于控制单个团队或项目的资源消耗,确保集群资源不会被个别用户过度占用,从而保持集群的稳定性和整体效率。

案例

假设有一个多租户平台,不同部门或项目分别有自己的命名空间。为了防止某个部门的大量应用消耗所有资源,影响其他部门的服务,可以为每个命名空间设置 ResourceQuota。例如,为 “研发部” 命名空间设置最大CPU使用量为4核,内存为8GiB,这样即使该部门的应用激增,也不会影响到 “市场部” 的资源需求。

LimitRange: LimitRange 在命名空间内部起作用,它为 Pod 或容器定义资源使用的默认值、最小值和最大值,确保每个 Pod 的资源请求和限制落在合理的范围内。这有助于规范资源配置,避免因配置不当导致的资源浪费或应用运行问题。

案例

在一个教育机构的 Kubernetes 集群中,教师和学生频繁部署实验应用。为了防止资源滥用和保证所有应用都能公平地获取资源,管理员在 “教学实验室” 命名空间设置了 LimitRange。规定所有 Pod 的 CPU 请求至少为 0.1 核,最大不超过 2 核,内存请求至少为 100MiB,最大不超过 1GiB 。这样既保证了每个应用有足够的资源启动,也限制了个别应用占用过多资源,导致其他应用无法运行的情况。

3. 设计一个 Kubernetes 高可用集群的架构,并解释每个组件的冗余策略?

  1. 控制面组件冗余
    • API Server: 使用多实例部署,通常至少三个,后面跟着负载均衡器(如HAProxy或云提供商的负载均衡服务),实现请求分发和故障转移。
    • etcd: 集群化部署,至少三个成员以形成多数派(quorum),确保数据的一致性和高可用性。etcd 成员之间采用 Raft 协议进行共识。
    • Controller Manager & Scheduler(可选): 同样采用多实例部署,通过Leader选举机制确保高可用,通常与API Server配合使用相同的负载均衡策略。
  2. 网络通讯
    • 选择活跃度较高且较为成熟的网络插件,如 Calico、Flannel 等,并确保其跨节点配置一致,支持多主机间冗余。
    • 对于外部访问的服务,使用云提供商的高可用负载均衡器或自建高可用 Ingress 控制器(如 Ingress-nginx Controller),确保入口流量的可靠分发。
  3. 节点和工作负载冗余
    • 节点分布:确保节点分布在不同的可用区(AZ),以防止单一区域故障导致整个集群不可用。
    • Pod副本集: 利用Deployment/StatefulSet管理应用,使用调度规则自动化将 Pod 打散到多可用区;
  4. 存储高可用
    • 持久卷: 选择支持高可用的存储解决方案,如分布式存储系统(Ceph、GlusterFS、MiniO)、云提供商的块存储服务,并使用动态卷供给(Dynamic Volume Provisioning)简化管理。
    • 备份与恢复: 定期备份 etcd 数据和其他关键应用数据,使用工具如 Velero 实现灾难恢复策略。
  5. 监控与日志
    • 监控系统: 部署高可用的 Prometheus 集群,采用联邦机制,结合 PrometheusAlert 进行精确告警,Grafana 展示仪表盘,确保能够持续监控集群状态。
    • 日志收集: 使用如 Fluentd 或 EFK(Elasticsearch, Fluentd, Kibana)堆栈集中收集和分析日志,确保日志系统的可靠性。
  6. 安全措施
    • 网络策略: 使用 Network Policies 限制 Pod 间通信,增强安全性。
    • RBAC: 细粒度的访问控制,确保只有授权用户和进程能访问和操作资源。
    • 安全扫描与补丁管理: 定期进行容器镜像的安全扫描,及时应用系统和软件更新。

4. 描述如何实施灾难恢复计划,包括数据备份与恢复策略,以及跨区域多活方案?

  1. 需求分析:在我们公司,我们会针对应用进行分类,核心/非核心/边缘/GPU/计算等指标来识别关键业务,配置RTO/RPO的标准。
  2. 数据备份:使用 Velero 定期备份至异地存储,实施增量/差异备份,备份存储在地理上独立的区域或第三方备份存储服务中,定期验证。
  3. 跨区域多活方案
    • 不同地域部署 K8s 集群,可以采用例如:karmada,可根据集群负载、地域亲和性等条件,自动将工作负载调度到最适合的集群中,实现资源的高效利用和负载均衡。
    • 提供统一的控制平面,这样运维人员能够在一个界面下管理多个地域的K8s集群,简化操作复杂度,提高管理效率。
    • 结合云供应商的跨区域数据库服务或自研数据复制方案,确保应用状态和数据在多集群间保持一致,支撑应用无缝跨越多个区域运行。
    • 可根据业务需求和各集群的实时负载情况,自动扩缩容,实现资源的动态调整,优化成本与性能。
    • 在某区域集群出现故障时,例如 Karmada 可快速重新调度受影响的工作负载至其他健康集群,加速服务恢复,实现高可用性。
    • 利用云提供商的跨区域数据库服务或自建数据同步方案(如MySQL Galera Cluster、Cassandra的多数据中心部署)保持数据实时或近实时同步。
    • 使用全局负载均衡器(如AWS Global Accelerator、阿里云AnyCast、DCDN等)自动就近上车,基于骨干网到达底层 Pod,确保用户体验不受影响。
  4. 故障切换:自动故障检测,实现自动化或半自动化的故障切换脚本,快速将流量切换至备用区域,同时通知 Noc 团队。制定详细恢复流程文档。
  5. 演练优化:定期演练、评估、持续改进计划。确保灾时快速响应,保护业务连续性。

5. 如何监控和优化 Pod 的资源使用,包括 CPU、内存及存储资源?

  1. 使用metrics-server:首先,确保集群部署了metrics-server,这是 Kubernetes 默认的资源使用度量收集器,用于提供 Pod 和 Node 级别的 CPU 及内存使用情况。
  2. 集成监控工具:集成如 Prometheus 和 Grafana 等监控工具。Prometheus 可以通过 Kubernetes 服务发现自动发现 Pod 和 Node,并通过安装 kube-state-metrics 和 node-exporter 来收集更详细的指标。Grafana 则用于可视化展示这些指标,帮助直观理解资源使用趋势和异常。
  3. 日志分析:利用 ELK Stack(Elasticsearch, Logstash, Kibana)或 Fluentd 等日志收集与分析工具,分析 Pod 日志中可能隐藏的资源使用异常信息。
  4. 告警设置:在监控系统中设置合理的资源使用阈值告警,当 Pod 资源使用达到或超过预设阈值时,及时通知运维团队,以便采取相应措施。

优化层面,可以参考如下建议:

  1. 合理设置资源请求与限制:为每个Pod的容器明确设置requestslimits,确保容器能够获得足够的资源运行,同时避免过度消费资源导致其他Pod受到影响。通过LimitRange来引导和强制执行资源请求与限制的最佳实践。
  2. 垂直与水平自动缩放:对于CPU和内存使用波动较大的应用,使用HPA(Horizontal Pod Autoscaler)根据CPU利用率自动增加或减少Pod副本数。对于单个Pod内部,可探索基于资源使用情况的VPA(Vertical Pod Autoscaler)进行自动资源调整。
  3. 优化容器镜像:减小容器镜像大小,减少启动时间,优化基础镜像选择,确保只包含运行应用所必需的库和依赖,减少内存占用。
  4. 使用Init Containers:在主要容器启动前,使用Init Containers预加载数据或执行耗时的初始化任务,避免影响主要容器的资源需求和启动速度。
  5. 存储优化:对于存储资源,采用按需挂载卷(如EmptyDir)处理临时文件,对于持久化存储,合理配置PV/PVC的回收策略,优化数据去重和压缩策略,减少存储空间使用。

6. 解释如何使用密钥管理系统(如 Secrets 和 ConfigMaps)来保护敏感数据,并讨论潜在的风险和最佳实践?

Secrets 用途:Secrets 主要用于存储敏感信息,如密码、API密钥、TLS证书等。Kubernetes会对Secrets中的数据进行加密存储,并在使用时解密,以确保数据的安全性。一般都是通过 volume 或 environment variable 的方式引用 Secret,然后在 Pod 内可用。

ConfigMaps 用途:ConfigMaps用于存储非敏感的配置数据,比如应用的配置文件内容。虽然不是专为敏感数据设计,但在某些场景下也可能包含敏感信息,因此也需谨慎处理。大多数的场景也都是通过 volume 挂载或环境变量引用 ConfigMap 中的数据。

另外几点,在真正的线上,为了避免一些问题,我们可以基于如下几个动作来做一些调整:

  1. 最小权限原则:仅为需要访问 Secrets 和 ConfigMaps 的实体分配最小必要的权限。
  2. 使用自动化工具:利用 CI/CD 管道和工具自动创建、管理和更新 Secrets,减少人为操作失误。
  3. 定期密钥轮换:实施密钥管理策略,定期自动轮换 Secrets 中的密钥。

7. 你是如何在 Kubernetes 集群中实施日志收集,请具体说明使用的工具和技术?

通常日志收集组件 我们会选择 Fluentd 或者 Filebeat 作为日志收集、处理和转发的工具,通过配置不同的输入插件收集容器日志,然后通过输出插件将日志发送到如Elasticsearch、Splunk等后端存储系统。

在基于 kubernetes 的集群环境下,我们通常会有2种方式去采集日志,例如:

  • DaemonSet:部署日志代理(如Fluentd或Filebeat)作为DaemonSet,确保每个节点上都运行一个代理实例,自动收集该节点上所有 Pod 的日志。
  • Sidecar容器:为每个需要日志收集的应用 Pod 添加一个 sidecar 容器(如 Fluentd 或 Filebeat ),这种方式提供了更细粒度的控制,适合需要单独处理每个应用日志的情况。

另外有时候在做一些日志收集的时候,我们需要针对日志流做一些特殊处理,例如:

  • 日志驱动:在Docker或Container Runtime层配置日志驱动(如json-file、syslog、fluentd等),直接将容器日志发送给日志收集服务。
  • 标签和解析:利用日志代理的标签功能,为日志打上Pod、Namespace等元数据标签,便于后续查询和分析。
  • 数据流处理:在日志收集过程中,可能需要对原始日志进行清洗、解析和结构化处理,以适应后续的存储和分析需求。

通常的日志存储及分析,多数都是采用开源的成熟方案,例如:

  • Elasticsearch:常作为日志数据的存储后端,因其强大的搜索和分析能力,非常适合大规模日志数据的索引和查询。
  • Kibana:提供可视化界面,用于搜索、分析和展示Elasticsearch中的日志数据,帮助快速定位问题和洞察应用行为。
  • Prometheus + Grafana:虽然主要用于指标监控,但也可以与其他工具集成,用于日志监控和报警。

至于在后续的运维管理中,我们也要注意,例如:

  • 安全:确保日志数据传输和存储过程中的加密,使用 RBAC 控制对日志访问权限。
  • 成本控制:根据需要实施日志保留策略和滚动策略,避免无限制的日志增长导致存储成本上升。
  • 监控与报警:设置日志收集和处理流程的健康检查,以及针对特定日志内容的报警规则,确保日志系统本身的高可用性和问题的及时发现。

8. 你是如何在 Kubernetes 集群中落地监控和告警系统的?

通常现在基于 kubernetes 的集群部署方式有 Helm charts 或 Operator,其主要目的还是简化 Prometheus 及其相关组件(如Alertmanager、Pushgateway)的部署与管理。

在数据收集层面,因为设计的维度比较多,我这边给大家一个思路:

按照组件进行分类:

  1. 控制平面组件:
    • kube-apiserver:Kubernetes API Server 的监控包括请求数量、请求延迟、错误率等。
    • kube-controller-manager:监控控制器的副本数、滚动更新状态、故障检测等。
  2. 资源管理组件:
    • kube-scheduler:监控调度算法、节点负载和调度决策等。
  3. 容器运行时组件:
    • kubelet:监控节点上的 Pod 运行状态、资源使用情况、容器启动错误等。
    • container runtime(如Docker、containerd等):监控容器的运行状态、资源使用情况、镜像存储等。
  4. 网络组件:
    • kube-proxy:监控网络规则、服务代理状态、连接数等。
    • CoreDNS:监控域名解析请求、缓存命中率等。

按照不同的维度进行分类:

  1. 节点级监控(node-exporter):Prometheus 可以监控 Kubernetes 集群中每个节点的资源使用情况,如 CPU、内存、磁盘和网络等。它通过与 kubelet 交互,并收集节点级别的指标数据。
  2. Pod 级监控(metrics-server):Prometheus 可以监控每个 Pod 的运行状态和性能指标,如 CPU 使用率、内存使用量、网络流量等。它通过与 kubelet 和 cAdvisor 进行交互,并收集 Pod 级别的指标数据。
  3. 服务级监控(blackbox-exporter):Prometheus 可以监控 Kubernetes 集群中的服务,包括 Service 和 Ingress 等。它可以通过与 kube-proxy 交互,获取服务的请求流量、响应时间和错误率等指标。
  4. 控制器级监控(kube-state-metrics):Prometheus 还可以监控 Kubernetes 集群中的控制器,如 Deployment、StatefulSet 等。它可以获取控制器的副本数、滚动更新状态和故障检测等指标。
  5. 自动服务发现:Prometheus 支持使用 Kubernetes 的服务发现机制自动发现和监控新的 Pod 和服务。它会根据 Kubernetes 的标签和注解信息,动态生成相应的监控配置。

💡 说明

较推荐 PrometheusAlert 去做

Prometheus的监控会随着时间的拉长,产生一系列不需要的脏数据,后续大家可以根据需要调整存储配置、采样率等参数,以优化性能和资源使用

9. 描述一个完整的 Kubernetes CI/CD 流水线,包括代码提交、构建、测试和部署到生产环境的过程

一个完整的 Kubernetes CI/CD 流水线是自动化从代码提交到生产环境部署的整个过程,确保敏捷、快速、可靠地交付。

下面我来通过一个大概的主流程来给大家描述下一个典型的 CI/CD 流水线示例:

1. 代码提交

  • 开发者在版本控制系统(如Git)中提交代码变更,并关联到特定的 release 分支或向主分支发起 Push Request。
  • 代码审查团队成员对提交的代码进行审查,确保质量并符合编码规范。

2. 持续集成(CI)阶段

  • 触发构建:代码仓库(如GitHub、GitLab)与CI/CD工具(如Jenkins、GitLab CI/CD、Tekton)集成,一旦有代码提交或PR创建,自动触发构建流程。
  • 静态代码分析:自动执行代码风格检查、安全扫描(如SonarQube)、依赖项分析,确保代码质量和安全性。
  • 构建镜像:使用 Dockerfile 构建应用的 Docker 镜像,或通过 Kaniko、Buildah 等工具在无守护进程环境中构建,确保安全性。
  • 镜像推送:将构建好的镜像推送到私有镜像仓库(如 Harbor、Docker Hub、Google Container Registry)。

3. 持续部署/持续交付(CD)阶段

  • 环境隔离:流水线通常会涉及多个环境,如开发、测试、预发布和生产环境,每个环境配置独立,确保更改不会直接影响生产。
  • 自动化测试
    • 单元测试:运行单元测试,确保代码模块的正确性。
    • 集成测试:在模拟环境下进行服务间交互测试。
    • 端到端测试(E2E):在接近生产环境的测试环境中,模拟用户操作进行全链路测试。
  • 部署准备:基于测试结果决定是否继续部署。通过 GitOps(如 Jenkins、Argo CD、FluxCD)或 Kubernetes Manifests 管理工具,准备部署配置。
  • 蓝绿部署/金丝雀发布/滚动更新:根据策略选择合适的部署策略,将新版本应用逐步或全部替换旧版本,确保服务的平滑过渡。
    • 蓝绿部署:先部署新版本到备用环境,验证无误后切换流量。
    • 金丝雀发布:先将新版本部署到少量实例上,逐步扩大范围。
    • 滚动更新:逐个替换旧Pod,保证服务的连续性。
  • 回滚策略:部署失败时,自动或手动触发回滚操作,恢复到上一稳定版本。

整个CI/CD流程高度自动化,从代码变更到生产环境的部署可以快速完成,同时确保高质量和高可用性,大大缩短了软件迭代周期。

10. 如何利用 Kubernetes 的 Deployment、StatefulSet、DaemonSet 等资源对象来支持不同类型的微服务部署需求?

在 Kubernetes 中,DeploymentStatefulSetDaemonSet是用于部署和管理容器化应用的主要资源对象,每种资源对象都有其特定的使用场景和特点,以满足不同类型的微服务部署需求:

Deployment:

  • 应用场景:适用于无状态服务,如web服务器、API服务器、配置服务等,这些服务的实例之间不保存状态,可以任意替换。
  • 特点
    • 自动化管理 Pod 副本数量,实现滚动更新、自动扩展和回滚等功能。
    • 当 Pod 意外终止时,自动创建新的 Pod 以维持期望的副本数量。
    • 支持标签选择器(label selectors)来确定哪些Pod受其管理。

StatefulSet:

  • 应用场景:面向有状态服务,如数据库(MySQL、PostgreSQL)、消息队列(Kafka)、分布式存储系统等,这些服务需要持久化存储和稳定的网络标识。
  • 特点
    • 为每个 Pod 提供唯一的标识符和稳定的网络名称,保证 Pod 重启或扩展时数据的一致性和顺序性。
    • 集成了存储卷的持久化,确保每个 Pod 绑定到特定的存储卷,即使 Pod 重启也不改变。
    • 支持有序的 Pod 创建和删除,保障服务的顺序性和依赖性。

DaemonSet:

  • 应用场景:确保在每个节点(或满足特定条件的节点)上运行一个Pod实例,适用于节点级的任务,如日志收集(Fluentd)、监控代理(Prometheus Node Exporter)等。
  • 特点
    • 每个节点上最多只有一个 Pod 副本,确保服务的全局分布。
    • 当新的节点加入集群时,自动在新节点上部署 Pod。
    • 当节点被移除时,其上的 DaemonSet 管理的 Pod 也会被清理。

实现不同微服务部署需求:

  • 对于需要水平扩展、频繁更新且不关心实例间状态的应用,使用 Deployment 是最合适的选择。
  • 对于有状态服务,需要保持数据持久性和实例间有固定身份标识的,采用 StatefulSet 来确保数据的连贯性和服务的高可用性。
  • 若服务要求在每个节点上都运行一个实例,以监控或管理节点级资源,DaemonSet 则是最佳实践。

11. 解释 Kubernetes 中的不同存储类(StorageClass)以及动态卷供给(Dynamic Volume Provisioning)的工作原理?

**动态卷供给(Dynamic Volume Provisioning)**是 Kubernetes 的一项功能,它允许根据用户的需求自动创建和管理 Persistent Volumes (PV)。在没有动态供给前,管理员需要手动创建 PV,然后用户才能通过 PVC 绑定到这些 PV 来使用存储。动态供给简化了这个过程,当用户创建 PVC 时,Kubernetes 会检查 PVC 中请求的存储量和访问模式,然后匹配到合适的 StorageClass,接着根据该 StorageClass 的配置自动向底层存储系统请求创建相应的 PV。一旦 PV 创建成功,它会被立即绑定到 PVC 上,使得 Pod 可以使用该存储。

工作原理概括如下:

  1. 用户定义PersistentVolumeClaim (PVC):用户根据应用需求定义PVC,指定所需的存储大小、访问模式(如ReadWriteOnce、ReadOnlyMany等)和希望使用的 StorageClass(可选,若未指定且集群有默认存储类,则使用默认)。
  2. Kubernetes查找StorageClass:Kubernetes 检查 PVC 中指定的 StorageClass,如果没有指定,则尝试使用默认存储类。
  3. 动态创建PersistentVolume (PV):Kubernetes 根据 StorageClass 的配置,调用对应的存储插件(如NFS插件、云提供商的API等)来创建实际的存储资源。这一步骤完全是自动化的,无需人工干预。
  4. PV与PVC绑定:新创建的PV与PVC自动绑定,此时,PV的状态变为Bound,PVC也变为Bound,表示存储资源已经准备好供Pod使用。
  5. Pod使用存储:Pod通过引用绑定到PVC,间接使用PV提供的存储空间。当Pod不再需要存储时,PVC可以被删除,如果配置得当,相应的PV也会被回收,释放存储资源。

12. 分享一次 Kubernetes 集群性能瓶颈的识别和解决经历,包括诊断工具和方法?

在一次线上生产环境中,遇到过一个节点频繁进入 NotReady 状态的故障案例。此故障直接导致部分 Pod 无法调度,影响了服务的正常运行。

以下是排查与解决的详细过程:

1)通过 Prometheus 告警,发现某节点标记为 NotReady,通过命令或界面检查节点状态;

2)对于Linux节点,可以通过SSH登录到故障节点,检查系统日志(如/var/log/messagesjournalctl -u kubelet)以寻找错误信息;

3)根据容器运行时检查对应日志,寻找容器启动失败或异常退出的记录;

4)检查基础例如磁盘,网络(ping, curl) 检查网络连通性,以及检查网络插件(如Calico, Flannel)的状态及日志。

5)通过上述步骤,发现该节点的 kubelet 日志中频繁出现关于 cAdvisor(Kubernetes资源使用统计组件)无法启动的错误,进一步调查得知是由于节点上缺少必要的 cAdvisor 依赖库文件,导致 kubelet 服务启动失败。

**问题解决:**登录问题节点,安装或重新配置缺失的依赖库,确保cAdvisor可以正常运行,修复依赖后,重启 kubelet 服务(systemctl restart kubelet),观察节点状态是否恢复正常,使用 kubectl describe nodekubectl get nodes 确认节点状态,持续监控节点健康状况,确保问题彻底解决.

13. 当遇到 Kubernetes 核心节点故障时,你的排查步骤是什么?如何快速定位并恢复服务?

当遇到 Kubernetes 核心节点(特别是控制平面节点,如apiserver、etcd、controller-manager、scheduler)故障时,问题的严重性和处理方式与普通工作节点有所不同,因为控制平面节点的稳定性直接影响到整个集群的管理和运行。

下面我来针对这类故障的排查和恢复步骤给出一些建议,为了方便大家记忆,我这边按照几个层面来展示:

确认故障状态:

  • 首先查看集群的监控工具(如Prometheus、Grafana)是否有控制平面组件相关的报警;
  • 直接访问或通过 kubectl cluster-info 检查apiserver、etcd等组件的可达性和状态;

通过日志分析:

  • 获取故障组件的日志(如apiserver的日志通常位于/var/log/kubernetes/目录下),通过日志查找错误信息;
  • 检查系统层面的日志,如/var/log/messages或使用journalctl,以发现潜在的系统级问题;

检查资源与网络:

  • 确认是否有资源耗尽问题,如CPU、内存或磁盘空间不足;
  • 检查网络配置,确保内部通信和外部访问(如apiserver的端口)未受阻;

快速恢复服务:

  • 备份与恢复:对于 etcd 等关键组件,如果之前有做数据备份,可以考虑使用备份恢复数据。
  • 紧急恢复措施:对于单点故障(如 apiserver 只有一台),考虑临时启动备用实例或使用云服务商的高可用特性快速恢复服务。
  • 重启或替换:对于因软件异常导致的问题,尝试重启服务或在故障排查无果后,考虑在新节点上重建故障组件。

当然如果有条件,可以定期对如上核心组件做故障演练,编写详细的故障处理报告,包括故障现象、处理过程、根本原因及最终解决方案。这样出现问题后也会游刃有余的按照手册操作即可

14. 请解释自定义资源定义 (Custom Resource Definitions) 的概念,以及它们如何扩展 Kubernetes API?

自定义资源定义(Custom Resource Definitions,简称 CRDs)是Kubernetes 提供的一种核心扩展机制,它允许用户在 Kubernetes API 中定义新的资源类型,这些资源类型并非 Kubernetes 原生内置的(比如Pods、Services、Deployments等)。通过 CRDs,用户能够根据自己的应用场景创建符合特定需求的资源对象,从而扩展 Kubernetes 的功能和适用范围,使之更加灵活和强大。

至于如何通过 CRDs 去扩展 API,一般对于运维工程师的要求不多,针对二开的同学可能需要更多的关注下:

  1. 定义 CRD:首先,你需要定义 CRD 的 YAML 文件,说明自定义资源的名称、字段、验证规则等信息。这个定义文件描述了自定义资源的结构和行为,然后通过 kubectl apply 命令提交给集群。
  2. 创建自定义资源实例:定义好 CRD 后,就可以开始创建这种类型的资源实例了。这些实例会由 Kubernetes API 服务器管理,并存储在集群的持久化存储(如 etcd)中。
  3. 开发自定义控制器:为了使自定义资源具有实际的功能(比如自动部署应用、配置管理等),通常还需要编写自定义控制器(如 Operator)。控制器监视这些自定义资源的变化,根据资源的状态和定义的逻辑自动执行相应的操作,如创建或修改其他 Kubernetes 资源。
  4. 集成与交互:自定义资源和控制器一起工作,使得用户可以以声明式的方式管理复杂的有状态应用或其他特定于业务的组件,而无需直接操作低级别的 Kubernetes 资源

15. 请描述实现一个基于 Istio 的服务间通信的故障注入演练,简单说明配置及目的?

在 Istio 中,实现服务间通信的故障注入演练是一种常见的混沌工程实践,它主要用于评估系统在模拟故障条件下的健壮性和弹性。

这种方法可以帮助开发者和运维小伙伴提前发现并修复潜在的故障点,增强系统的可靠性。

下面我来通过一个例子的展示来给大家介绍下,基于 Istio 实现服务间通信故障注入的基本配置及目的(直接尬聊貌似看不出效果):

假设我们有一个由两个微服务组成的应用程序:“frontend” 和 “backend”。我们的目标是在 “frontend” 调用 “backend” 服务时,故意引入网络延迟,模拟网络不稳定场景。

步骤:

  1. 确保Istio已安装并启用:首先,确保你的 Kubernetes 集群中已安装了 Istio,并且你的服务都已经被注入到了 Istio 的服务网格中。
  2. 创建 DestinationRule 配置:使用 Istio 的 DestinationRule 资源来定义故障注入的策略。
  3. 以下是一个 YAML 配置示例,用于在调用 “backend” 服务时引入 2秒 的固定延迟:
yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: delay-injection-backend
spec:
  host: backend
  trafficPolicy:
    outlierDetection: {} # 不需要配置,但需存在以激活下面的subset配置
  subsets:
  - name: delayed
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 1
          connectTimeout: 1s
      loadBalancer:
        simple: RANDOM
      timeout: 2s
      retries:
        attempts: 3
        perTryTimeout: 1s
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: delay-injection-backend
spec:
  host: backend
  trafficPolicy:
    outlierDetection: {} # 不需要配置,但需存在以激活下面的subset配置
  subsets:
  - name: delayed
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 1
          connectTimeout: 1s
      loadBalancer:
        simple: RANDOM
      timeout: 2s
      retries:
        attempts: 3
        perTryTimeout: 1s

4.使用 VirtualService 资源指定流量应该如何路由到包含延迟策略的子集。在这个例子中,我们希望所有流量都路由到带有延迟的子集

yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: frontend-to-backend
spec:
  hosts:
  - frontend
  http:
  - route:
    - destination:
        host: backend
        subset: delayed
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: frontend-to-backend
spec:
  hosts:
  - frontend
  http:
  - route:
    - destination:
        host: backend
        subset: delayed

应用上述配置后,所有从 “frontend” 到 “backend” 的请求都会被强制引入2秒的延迟,从而可以观察系统在这种模拟故障下的表现,并据此进行优化。

记得在测试结束后,移除这些配置,以恢复正常服务。

最后再总结下:

  • 评估系统韧性:通过模拟网络延迟,观察前端服务对慢速响应的处理能力,是否会出现雪崩效应,前端是否能够正确处理超时和重试逻辑。
  • 优化用户体验:识别和优化服务之间的依赖关系,确保在真实网络延迟情况下,用户体验不受严重影响。
  • 增强故障恢复能力:通过实际演练,验证系统在面对故障时的自我恢复机制是否有效,以及是否需要调整超时设置、重试策略等来提升稳定性。
  • 团队协作与培训:故障注入演练也是团队之间沟通和协作的一个机会,帮助开发、运维和SRE团队共同理解系统的行为,提升应对突发事件的能力。

16. 解释如何利用 Kubernetes 事件系统进行集群活动的监控和追踪?

我们先来理解下,为什么要做这件事情?首先 Kubernetes 的事件系统记录了集群中发生的各种事件,如 Pod 的创建、删除、更新,以及其他资源(如 Service、Deployment 等)的更改。这些事件为集群管理员或开发者提供了关于集群状态和活动的重要信息。

针对集群的event,我们可以采用很多种方式,其中 kubectl get events 命令来查看集群中的所有事件,但是这种手动的查看明显不是咱们需要的,那么对于更复杂的监控需求,我们一般是通过 日志系统(EFLK)或者 Kubewatch 来满足更多的要求。

主要来讲下 kubewatch:

  • Kubewatch 是一个轻量级的工具,可以实时监听 Kubernetes API 服务器的事件流,并在发生变更时触发预定义的操作。
  • 通过 Kubewatch,咱们可以配置在特定事件发生时发送通知(如 HTTP webhook 调用)。这对于快速响应集群中的关键事件(如 Pod 故障或资源不足)非常有用。

有了顺手的工具,下一步就根据你的分析结果,配置警报规则,以便在关键事件发生时自动发送通知。有助于确保及时响应和解决潜在问题。

17. 分享几个在 Kubernetes 上进行成本优化的策略,比如闲置资源回收、Spot实例的使用?

在成本优化上业界有很多种解决方案,但是基于 kubernetes,更多的咱们需要结合 kubernetes 的一些高级特性去做深度应用,可以从如下几个层面:

  • 自动伸缩(Horizontal Pod Autoscaler, HPA): 根据实际工作负载自动调整应用实例数量,减少不必要的运行实例。
  • Vertical Pod Autoscaler (VPA): 根据 Pod 的实际资源使用情况动态调整 CPU 和内存请求,避免资源过度分配。
  • Pod驱逐策略与优先级: 设置 Pod 的优先级和抢占政策,确保关键服务得到资源保障,非关键服务在资源紧张时被优先驱逐。
  • CronJob清理: 定期检查并清理已完成的 Job 和 CronJob,避免资源占用。

针对 Spot 实例的场景,目前在云上应用的比较多,但是使用的前提,我们需要结合 Spot 的特性和应用的特性来做一个匹配,也需要注意如下几点:

  • 结合按需实例和 Spot 实例,确保基础服务运行在按需实例上,可中断服务或批处理任务运行在 Spot 实例上。
  • 设置 Spot 实例的最大出价,避免成本失控,同时利用 Spot 实例的低成本优势。
  • 利用 Kubernetes 的节点亲和性和污点/容忍机制,确保 Pod 能够在 Spot 实例被回收前自动迁移至其他节点。
  • 使用如 Karpenter(AWS开源项目)工具,自动化管理 Spot 实例的生命周期,包括自动扩容、缩容和中断处理。

另外从优化层面,大家也可以站在这些维度,例如:

  • 优化镜像大小,减少拉取时间,使用多阶段构建减少层的重复,利用缓存;
  • 配置kubelet的垃圾回收策略,定期清理不再使用的镜像和容器;
  • 结合每个应用的特性,为每个 Pod 设置合理的资源请求和限制(QoS),避免资源过度消耗或浪费。
  • 也可以使用一些成本分析工具,利用如 Kubecost、Kubernetes Cost Analyzer 等工具进行细粒度的成本分析,识别成本热点。

18. 阐述 Kubernetes 调度器的工作流程,包括预筛选、打分和绑定阶段,并解释如何自定义调度策略以满足特定业务需求?

1、预筛选(Predicate)阶段

这个阶段的目标是从所有可用节点中过滤掉那些不满足 Pod 运行基本要求的节点。预筛选主要基于硬性约束(Hard Constraints),比如:

  • 资源需求:检查节点是否有足够的 CPU、内存等资源来满足 Pod 的请求和限制。
  • Pod亲和性与反亲和性:确认 Pod 是否能够根据其定义的标签选择或避免特定节点。
  • 污点与容忍度:检查 Pod 是否能够容忍节点上的污点或是否有相应的容忍规则。

不符合任何硬性约束的节点会被立即排除。

2、打分(Scoring)阶段

经过预筛选后,剩余的节点将进入打分阶段。这一阶段主要是基于软性约束(Soft Constraints),为每个节点分配一个分数,反映其对当前 Pod 的适宜程度。Kubernetes 内置了几种打分策略,如:

  • 资源量:节点剩余资源越多,得分越高。
  • 亲和性/反亲和性:符合 Pod 亲和性规则的节点得分更高。
  • 交互性:如果 Pod 与某些 Pod 需要在同一节点上运行(如共享数据卷),则该节点得分更高。

打分阶段的目的是找到理论上最适合运行Pod的节点。

3、绑定(Binding)阶段

最终,得分最高的节点(或达到一定分数阈值的节点)被选中,调度器将 Pod 绑定到该节点上,并在 etcd 中创建一个绑定对象(Binding),通知节点开始下载并运行 Pod。

4、针对自定义调度,主要是为了灵活的机制来定制调度策略,以满足特定业务需求:

1)可以编写自定义的调度插件,通过实现Kubernetes调度框架的接口,插入到预筛选或打分阶段,以增加新的约束条件或评分逻辑。

2)通过在节点上设置特定的污点(Taints 与 Tolerations),并在 Pod 上设置相应的容忍度,可以实现更为精细的调度控制。这适用于需要隔离特定工作负载或确保某些 Pod 仅在特定节点上运行的场景。

3)利用 Pod 亲和性和反亲和性规则,可以确保Pod之间保持或避免特定的部署关系,以满足业务的性能需求或高可用性要求。

4)Node Affinity 规则允许基于节点的标签来影响调度决策,实现更复杂的节点选择逻辑,比如确保特定应用的 Pod 运行在具有特定硬件或软件配置的节点上。

19. 针对一个具体的微服务架构,设计并解释如何实施服务网格以实现金丝雀发布、故障注入和安全策略?

在设计针对微服务架构的服务网格实施时,我们就以 Istio 为例来规划如何实现金丝雀发布、故障注入以及安全策略,以提升服务的稳定性和安全性。

金丝雀发布:通过 Istio 的 VirtualServiceDestinationRule 配置,轻松划分服务版本(如v1生产与v2金丝雀),并利用流量权重逐步分配用户到新版本,实现无感迭代。过程中,借助 Istio 的监控能力密切观察金丝雀版本性能,确保稳定后再逐步扩大新版本流量,或在问题出现时快速回滚,保证服务连续性。

故障注入:利用 Istio 的 HTTP FaultInjection 功能,在 VirtualService 中配置模拟延迟、超时等故障场景,无需修改服务代码即可测试系统韧性。这有助于识别并优化服务的容错逻辑和恢复策略,增强整体系统的稳定性和故障恢复能力。

安全策略:启用 Istio 的自动 mTLS,实现服务间通信的加密,保障数据传输安全。结合 AuthorizationPolicy,精确定义访问控制规则,确保只有授权的服务或命名空间才能访问敏感资源,同时利用 Istio 的审计与监控能力,持续监督安全态势,即时响应潜在威胁。

20. Kubernetes 安全策略防护是确保集群稳定性和数据安全的基石,请基于你的工作来谈一谈在这方面的经验?

访问控制与身份验证(RBAC):

  • 最小权限原则:每个服务账户、用户或系统组件仅被赋予完成其功能所需的最小权限。通过仔细设计Role和RoleBindings,确保不会有过剩的访问权限。
  • 双因素认证:对于敏感操作或管理界面访问,强制实施双因素认证,以增强身份验证的可靠性。

网络策略:

  • 微隔离:使用 Network Policies 实施严格的网络隔离策略,确保服务间仅开放必要的通信通道,减少攻击面。
  • 服务网格安全:集成 Istio 等服务网格,提供更细粒度的流量控制和安全策略,如 TLS 加密、访问控制列表(ACL)和端到端加密。

容器安全与运行时保护:

  • 镜像扫描与签名:确保使用前所有容器镜像经过安全扫描,并且要求所有镜像从信任的注册表拉取且带有签名,以防篡改。
  • 运行时监控:部署运行时安全工具,如 Falco 或 Aqua Security,监控异常行为,如逃逸企图、非法网络访问等。
  • 安全上下文:配置 Pod Security Policies 或使用 PodSecurity Admission Controller 来限制容器特权,使用非 root 用户运行容器,限制资源使用,以及应用AppArmor或SELinux策略。

密钥与配置管理:

  • 密钥管理系统:集成Vault或KMS服务,用于存储和管理敏感信息,如数据库凭据、API密钥等,确保密钥的生命周期管理及安全传递。
  • 动态密钥注入:利用Kubernetes Secrets或外部密钥管理系统,在Pod启动时动态注入敏感信息,避免明文存储。

审计与监控:

  • 日志与审计:充分利用 Kubernetes 审计日志,跟踪和分析所有 API 活动,及时发现异常行为。
  • 持续监控:集成 Prometheus 和 Grafana 等工具,监控集群资源使用、网络流量及应用性能,结合日志分析,快速定位并响应安全事件。

策略与合规:

  • 合规性检查:定期执行自动化合规性扫描,如使用 Open Policy Agent (OPA) 和 Gatekeeper,确保集群配置符合组织安全策略和行业标准(如 PCI-DSS、GDPR)。
  • 安全意识培训:提升团队的安全意识,定期培训开发和运维人员关于最新安全威胁和最佳实践,确保每个人都了解他们在安全防护中的角色和责任。

21. 说下无状态服务和有状态服务部署的区别

无状态

1.pod命名:pod名由资源名+随机的字符串组成;

2.数据存储:多个实例pod可以共享相同的持久化数据,存储不是必要条件;

3.扩缩容:可以随意扩缩容某个pod,不会指定某个pod进行扩缩容;

4.启停顺序:因为pod名的序号是随机串,无启停顺序之分;

5.无状态k8s资源:ReplicaSet、ReplicationController、Deployment、DaemonSet、Job等资源;

6.无状态服务:tomcat、nginx等;

有状态

1.pod命名:pod名由statefulset资源名+有序的数字组成(0,1,2…N-1),且pod有特定的网络标识;

2.数据存储:有状态的服务对应实例需要有自己的独立持久卷存储;

3.扩缩容:扩缩容不可随意,缩容是从数字最大的开始递减,扩容是在原有pod序号基础上递增1。

4.启停顺序:pod启停是有顺序的,启动时,先启动pod序号为0的,然后依次递增至N-1;停止时,先停止pod序号为最大的N-1,然后依次递减至0;

5.有状态k8s资源:StatefulSet资源;

6.有状态服务:Kafka、ZooKeeper、MySql、MongoDB以及一些需要保存日志的应用等服务;