Kubernetes 网络与服务发现面试题详解

一、网络模型基础

1. Kubernetes的网络模型有哪些基本要求?

答案:

Kubernetes网络模型基于以下核心原则:

所有Pod可以相互通信

  • 不使用NAT,Pod之间可以直接通过IP通信
  • 跨节点的Pod也能直接访问
  • 简化了网络拓扑,避免端口映射复杂性

所有节点可以与所有Pod通信

  • 节点可以直接访问任何Pod的IP
  • Pod也可以直接访问节点
  • 双向通信无需NAT转换

Pod看到的IP就是其他Pod看到的IP

  • Pod具有真实的IP地址
  • 不存在IP伪装或地址转换
  • 简化了服务发现和负载均衡

网络隔离通过NetworkPolicy实现

  • 默认所有Pod可以相互访问
  • 通过NetworkPolicy实现细粒度控制
  • 支持入站和出站流量规则

实现原理示意:

复制代码
Node1 (10.0.1.0/24)              Node2 (10.0.2.0/24)
  ├── Pod A (10.244.1.5)           ├── Pod C (10.244.2.8)
  └── Pod B (10.244.1.6)           └── Pod D (10.244.2.9)
  
Pod A可以直接访问10.244.2.8 (Pod C)
无需通过Node IP或端口映射

常见CNI插件实现方式:

Flannel

  • 使用Overlay网络(VXLAN/UDP)
  • 简单易用,适合小规模集群
  • 性能相对较低

Calico

  • 使用BGP路由协议
  • 性能优秀,支持NetworkPolicy
  • 适合大规模生产环境

Weave Net

  • 使用网状路由
  • 支持加密通信
  • 配置简单

Cilium

  • 基于eBPF技术
  • 高性能,支持L7策略
  • 可观测性强

2. Service的工作原理是什么?有哪些类型?

答案:

Service是Kubernetes提供的抽象层,为一组Pod提供稳定的网络访问入口。

核心工作机制:

虚拟IP(ClusterIP)

  • Service被分配一个集群内部的虚拟IP
  • 该IP在Service生命周期内保持不变
  • 请求发送到ClusterIP会被负载均衡到后端Pod

Endpoint控制器

  • 监控符合Selector的Pod
  • 动态维护Endpoints列表
  • Pod变化时自动更新Endpoint

kube-proxy实现

复制代码
Client Request → Service ClusterIP → kube-proxy规则 → 后端Pod

Service类型详解:

1. ClusterIP(默认类型)

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - protocol: TCP
    port: 80        # Service暴露的端口
    targetPort: 8080  # Pod监听的端口

特点:

  • 仅集群内部可访问
  • 分配集群内唯一的虚拟IP
  • 适合内部服务间调用

2. NodePort

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
    nodePort: 30080  # 可选,不指定则自动分配30000-32767范围内端口

特点:

  • 在每个节点上开放指定端口
  • 外部可通过 <NodeIP>:<NodePort> 访问
  • 适合开发测试环境

访问方式:

复制代码
外部请求 → 任意节点IP:30080 → Service → Pod

3. LoadBalancer

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

特点:

  • 在云平台上自动创建外部负载均衡器
  • 分配外部可访问的IP地址
  • 适合生产环境对外暴露服务

工作流程:

复制代码
外部请求 → 云LB外部IP → NodePort → Service → Pod

4. ExternalName

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: mysql.external.com

特点:

  • 返回CNAME记录
  • 用于引用外部服务
  • 无需创建Endpoint

Headless Service(无头服务)

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None  # 关键:设置为None
  selector:
    app: mysql
  ports:
  - port: 3306

使用场景:

  • StatefulSet的网络标识
  • 客户端需要直接连接特定Pod
  • DNS返回所有Pod的IP地址列表

负载均衡算法:

kube-proxy支持的代理模式:

iptables模式(默认)

  • 使用iptables规则实现负载均衡
  • 随机选择后端Pod
  • 性能较好,但规则数量过多时性能下降

IPVS模式

  • 使用Linux IPVS模块
  • 支持多种负载均衡算法:rr(轮询)、lc(最少连接)、sh(源地址哈希)
  • 性能优于iptables,适合大规模集群

3. Ingress是什么?与Service有什么区别?

答案:

Ingress是Kubernetes的API对象,管理外部访问集群服务的HTTP和HTTPS路由。

Ingress vs Service对比:

特性 Service Ingress
层级 L4(传输层) L7(应用层)
协议支持 TCP/UDP HTTP/HTTPS
路由能力 简单端口转发 基于域名和路径的路由
SSL/TLS 需要额外配置 原生支持证书管理
成本 每个Service可能需要LoadBalancer 单个入口可服务多个Service

Ingress架构:

复制代码
Internet
    ↓
Ingress Controller (Nginx/Traefik)
    ↓
Ingress Rules
    ├── foo.example.com/api → Service A → Pod A
    ├── foo.example.com/web → Service B → Pod B
    └── bar.example.com/*   → Service C → Pod C

基础Ingress配置:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: www.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  tls:
  - hosts:
    - www.example.com
    secretName: tls-secret

TLS证书配置:

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: <base64编码的证书>
  tls.key: <base64编码的私钥>

常见Ingress Controller:

Nginx Ingress Controller

  • 最流行的选择
  • 功能丰富,性能稳定
  • 支持丰富的注解配置

Traefik

  • 动态配置,无需重启
  • 原生支持Let's Encrypt
  • 内置监控面板

HAProxy Ingress

  • 高性能
  • 企业级特性
  • 复杂的负载均衡策略

Istio Gateway

  • 服务网格方案
  • 流量管理能力强
  • 可观测性好

高级特性示例:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  annotations:
    # 限流配置
    nginx.ingress.kubernetes.io/limit-rps: "10"
    # 认证配置
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # 跨域配置
    nginx.ingress.kubernetes.io/enable-cors: "true"
    # 会话亲和性
    nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

最佳实践:

  • 使用命名空间隔离不同环境的Ingress
  • 为生产环境配置TLS证书
  • 设置合理的限流和超时参数
  • 使用注解实现高级功能
  • 监控Ingress Controller的性能指标

4. 如何实现Pod之间的网络隔离?

答案:

通过NetworkPolicy实现Pod之间的网络访问控制,类似于防火墙规则。

NetworkPolicy工作原理:

  • 基于Label Selector选择目标Pod
  • 定义允许或拒绝的流量规则
  • 支持入站(Ingress)和出站(Egress)控制
  • 需要CNI插件支持(如Calico、Cilium)

默认拒绝所有入站流量:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: production
spec:
  podSelector: {}  # 空选择器表示应用于所有Pod
  policyTypes:
  - Ingress

允许特定Pod访问:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
      tier: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

允许特定命名空间访问:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-monitoring
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9090

限制出站流量:

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 3306
  - to:  # 允许DNS解析
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53

复杂场景:多层访问控制

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: multi-tier-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    # 允许来自frontend命名空间的frontend Pod
    - namespaceSelector:
        matchLabels:
          env: production
      podSelector:
        matchLabels:
          app: frontend
    # 允许来自API Gateway
    - podSelector:
        matchLabels:
          app: api-gateway
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    # 允许访问数据库
    - podSelector:
        matchLabels:
          app: mysql
    ports:
    - protocol: TCP
      port: 3306
  - to:
    # 允许访问Redis缓存
    - podSelector:
        matchLabels:
          app: redis
    ports:
    - protocol: TCP
      port: 6379
  - to:
    # 允许DNS查询
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

最佳实践:

采用白名单策略

  • 默认拒绝所有流量
  • 显式声明允许的连接
  • 最小权限原则

分层设计

  • 网络隔离与应用架构对齐
  • 前端、后端、数据层分别控制
  • 使用命名空间隔离环境

监控与审计

  • 定期审查NetworkPolicy配置
  • 监控被拒绝的连接尝试
  • 结合日志分析异常流量

测试验证

bash 复制代码
# 测试Pod间连接性
kubectl exec -it frontend-pod -- curl backend-service:8080

# 查看NetworkPolicy应用情况
kubectl describe networkpolicy allow-frontend-to-backend

# 验证规则生效
kubectl get networkpolicy -A

二、DNS与服务发现

5. Kubernetes中的DNS解析是如何工作的?

答案:

Kubernetes通过CoreDNS提供集群内部的DNS服务发现能力。

DNS记录格式:

Service DNS记录

复制代码
<service-name>.<namespace>.svc.cluster.local

示例:

复制代码
# 同命名空间访问
curl http://backend-service

# 跨命名空间访问
curl http://backend-service.production.svc.cluster.local

Pod DNS记录

复制代码
<pod-ip-with-dashes>.<namespace>.pod.cluster.local

示例:

复制代码
# Pod IP: 10.244.1.5
10-244-1-5.default.pod.cluster.local

Headless Service DNS

复制代码
<pod-name>.<service-name>.<namespace>.svc.cluster.local

示例:

复制代码
# StatefulSet Pod
mysql-0.mysql-service.default.svc.cluster.local
mysql-1.mysql-service.default.svc.cluster.local

CoreDNS配置:

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }

DNS解析流程:

复制代码
Pod发起DNS请求
    ↓
kubelet配置的/etc/resolv.conf
    ↓
指向CoreDNS Service (kube-dns)
    ↓
CoreDNS解析
    ├── 集群内部域名 → 返回ClusterIP或Pod IP
    └── 外部域名 → 转发到上游DNS服务器
    ↓
返回解析结果给Pod

Pod DNS配置:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: custom-dns-pod
spec:
  containers:
  - name: app
    image: nginx
  dnsPolicy: "None"  # 自定义DNS配置
  dnsConfig:
    nameservers:
    - 8.8.8.8
    - 8.8.4.4
    searches:
    - custom.local
    - default.svc.cluster.local
    options:
    - name: ndots
      value: "2"

DNS策略类型:

Default

  • 继承节点的DNS配置
  • 适合需要访问集群外部服务的场景

ClusterFirst(默认)

  • 优先使用集群DNS
  • 未匹配的域名转发到节点DNS

ClusterFirstWithHostNet

  • 使用hostNetwork的Pod使用此策略

None

  • 完全自定义DNS配置
  • 需要手动指定nameservers

DNS调试技巧:

bash 复制代码
# 测试DNS解析
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup backend-service

# 查看Pod的DNS配置
kubectl exec -it pod-name -- cat /etc/resolv.conf

# 查看CoreDNS日志
kubectl logs -n kube-system -l k8s-app=kube-dns

# 测试完整域名解析
kubectl exec -it pod-name -- nslookup backend-service.production.svc.cluster.local

性能优化:

  • 调整CoreDNS副本数以应对高负载
  • 配置合理的DNS缓存TTL
  • 使用NodeLocal DNSCache减少跨节点DNS查询
  • 监控CoreDNS的查询延迟和错误率

6. 如何实现服务的灰度发布和蓝绿部署?

答案:

Kubernetes支持多种发布策略,实现零停机更新和风险控制。

1. 滚动更新(RollingUpdate)- 默认策略

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # 最多超出期望副本数2个
      maxUnavailable: 1  # 最多1个副本不可用
  template:
    metadata:
      labels:
        app: web
        version: v2
    spec:
      containers:
      - name: web
        image: web:v2
        readinessProbe:  # 重要:确保新Pod就绪后才接收流量
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

流程:

复制代码
初始状态: v1 Pod x10
步骤1: 创建v2 Pod x2 (maxSurge=2)
步骤2: v2 Pod就绪后,删除v1 Pod x1 (maxUnavailable=1)
步骤3: 重复直到所有Pod更新为v2

2. 蓝绿部署

yaml 复制代码
# 蓝色环境(当前生产)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      version: blue
  template:
    metadata:
      labels:
        app: web
        version: blue
    spec:
      containers:
      - name: web
        image: web:v1
---
# 绿色环境(新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      version: green
  template:
    metadata:
      labels:
        app: web
        version: green
    spec:
      containers:
      - name: web
        image: web:v2
---
# Service初始指向蓝色环境
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
    version: blue  # 切换时改为green
  ports:
  - port: 80
    targetPort: 8080

切换流程:

bash 复制代码
# 1. 部署绿色环境
kubectl apply -f deployment-green.yaml

# 2. 验证绿色环境
kubectl exec -it test-pod -- curl http://web-green:8080

# 3. 切换Service到绿色环境
kubectl patch service web-service -p '{"spec":{"selector":{"version":"green"}}}'

# 4. 验证无误后删除蓝色环境
kubectl delete deployment web-blue

3. 金丝雀发布(Canary Deployment)

yaml 复制代码
# 稳定版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-stable
spec:
  replicas: 9  # 90%流量
  selector:
    matchLabels:
      app: web
      track: stable
  template:
    metadata:
      labels:
        app: web
        track: stable
        version: v1
    spec:
      containers:
      - name: web
        image: web:v1
---
# 金丝雀版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-canary
spec:
  replicas: 1  # 10%流量
  selector:
    matchLabels:
      app: web
      track: canary
  template:
    metadata:
      labels:
        app: web
        track: canary
        version: v2
    spec:
      containers:
      - name: web
        image: web:v2
---
# Service选择所有版本
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web  # 只匹配app标签,包含stable和canary
  ports:
  - port: 80
    targetPort: 8080

基于Istio的精细化金丝雀:

yaml 复制代码
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: web-vs
spec:
  hosts:
  - web-service
  http:
  - match:
    - headers:
        user-type:
          exact: "beta"
    route:
    - destination:
        host: web-service
        subset: canary
  - route:
    - destination:
        host: web-service
        subset: stable
      weight: 95
    - destination:
        host: web-service
        subset: canary
      weight: 5
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: web-dr
spec:
  host: web-service
  subsets:
  - name: stable
    labels:
      version: v1
  - name: canary
    labels:
      version: v2

最佳实践:

监控指标

  • 错误率、延迟、吞吐量
  • 自动化回滚机制
  • 设置合理的观察期

健康检查

  • 配置readinessProbe和livenessProbe
  • 确保新版本就绪后才接收流量

自动化

  • 使用CI/CD工具自动化发布流程
  • 集成Flagger、Argo Rollouts等工具

回滚策略

bash 复制代码
# 查看发布历史
kubectl rollout history deployment/web-app

# 快速回滚到上一版本
kubectl rollout undo deployment/web-app

# 回滚到指定版本
kubectl rollout undo deployment/web-app --to-revision=3

三、总结

本文档深入讲解了Kubernetes网络与服务发现的核心概念:

  • K8S网络模型和CNI插件
  • Service类型及工作原理
  • Ingress高级路由配置
  • NetworkPolicy网络隔离
  • DNS解析机制
  • 灰度发布和蓝绿部署策略

网络是K8S的核心能力之一,掌握这些知识对于架构设计和故障排查至关重要。

相关推荐
噎住佩奇2 小时前
k8s创建测试Pod的流程
云原生·容器·kubernetes
少云清2 小时前
【性能测试】3_Locust _locust实现混合业务实现
网络·性能测试·locust
ζั͡山 ั͡有扶苏 ั͡✾2 小时前
从Rancher崩溃中恢复Kubernetes集群访问权限:完整kubeconfig恢复指南
容器·kubernetes·rancher
venus602 小时前
网络运维之ping与telnet的区别
运维·服务器·网络
WinyQ02 小时前
【DeepStream】整合出现的问题
linux·运维·网络
小魏每天都学习2 小时前
【网络拓扑部署-网络设备-网络安全】
运维·网络
zd8451015002 小时前
CubeMX H743 lwip ETH初始化流程
网络·stm32·单片机
zzh_my2 小时前
tcp 服务端(用于测试)
服务器·网络·tcp/ip
SmartRadio2 小时前
LLCC68 L型与π型匹配网络的调试方法
网络·lora·阻抗匹配·匹配·射频·llcc68