容器网络实践笔记

这次做 Kubernetes 迁移,从 Docker 的简单网络到 Kubernetes 的 CNI,再到 Service Mesh,网络复杂度上升了好几个档次。

dblocalhostmyservice:80` 访问后端服务。

Docker 网络基础

Bridge 模式

最简单的网络模式,每个容器有自己的网络命名空间,通过 veth pair 连接到宿主机的网桥。

# 创建一个容器,默认使用 bridge 模式
docker run -d --name mycontainer nginx

# 查看网络配置
docker network inspect bridge

优势:简单,不需要额外配置 劣势:跨主机通信麻烦,需要端口映射

Host 模式

容器共享宿主机网络命名空间,直接使用宿主机的网络栈。

docker run -d --network host myapp

优势:性能好,网络开销小 劣势:端口冲突,容器间无隔离

自定义网络

可以创建自定义网络,容器之间通过服务名互相访问。

# 创建自定义网络
docker network create myapp-network

# 启动容器并连接到自定义网络
docker run -d --network myapp-network --name db postgres
docker run -d --network myapp-network --name web myapp

在 web 容器里可以通过 db 直接访问 postgres 容器。

Kubernetes 网络架构

Pod 网络

每个 Pod 都有唯一的 IP 地址,同一个 Pod 内的容器共享网络命名空间。

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: web
    image: nginx
  - name: logging
    image: fluentd

web 容器和 logging 容器可以通过 localhost 互相访问。

Service 网络

Service 为 Pod 提供稳定的访问入口,解决 Pod IP 变化的问题。

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

其他 Pod 可以通过 myservice:80 访问后端服务。

CNI 插件

CNI(Container Network Interface)是 Kubernetes 的网络插件接口,负责配置 Pod 网络。

Flannel

最简单的 CNI 插件,使用 VXLAN 封装实现跨节点通信。

# Flannel 配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
data:
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": "vxlan"
    }

优势:配置简单,上手容易 劣势:性能一般,网络层级多

Calico

基于 BGP 的网络方案,支持网络策略。

# Calico 网络策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

优势:支持网络策略,性能好 劣势:配置复杂,需要 BGP

Cilium

基于 eBPF 的新一代 CNI 插件,性能极强。

# 安装 Cilium
cilium install --version 1.11.0

# 查看网络状态
cilium status

优势:性能极致,支持 Hubble 可观测性 劣势:较新,生态还在发展

Service Mesh 网络

Service Mesh 在服务网格层面处理网络通信,提供了更多高级功能。

Istio 架构

graph TB subgraph Service Mesh架构 A[控制平面<br/>istiod] B[数据平面<br/>Envoy Proxy] subgraph 服务A C[业务容器] D[Sidecar代理] end subgraph 服务B E[业务容器] F[Sidecar代理] end end C --> D D --> F F --> E A --> D A --> F style A fill:#FFD700 style D fill:#90EE90 style F fill:#90EE90

每个服务都有一个 Sidecar 代理,处理所有网络流量。

流量管理

# Istio 虚拟服务配置
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

可以基于 HTTP 头、Cookie 等进行流量路由。

实践中的选择

场景一:简单的容器化应用

Docker 自定义网络就够了,配置简单,维护方便。

场景二:中等规模的 Kubernetes 集群

Flannel 或 Calico 都可以,Flannel 简单,Calico 功能更全。

场景三:大型微服务架构

Istio 这样的 Service Mesh 提供了流量管理、安全、可观测性等功能。

踩过的坑

坑一:DNS 解析延迟

一开始 Pod 之间通过 Service DNS 访问,发现延迟有点高。

解决:使用 CoreDNS 的 NodeLocal 模式,DNS 解询直接在节点上完成,不需要跨节点。

坑二:网络策略配置错误

配置了网络策略,结果把合法流量也挡了。

解决:先测试网络策略,逐步放开,确保不影响合法流量。

坑三:Service Mesh 性能开销

上了 Service Mesh 之后,延迟确实增加了一些。

解决

  • 优化 Envoy 配置
  • 关闭不必要的功能
  • 对延迟敏感的服务 bypass Service Mesh

写在最后

容器网络这东西,从 Docker 的 bridge 到 Kubernetes 的 CNI,再到 Service Mesh,复杂度是逐步上升的。

选择方案的时候,不是选"最先进"的,而是选"最适合项目规模和团队能力"的。

对于小团队,Docker 网络或简单的 CNI 就够用。对于大团队,Service Mesh 提供的能力确实有价值。


这次网络调研下来,最大的收获是:网络不是孤立的问题,它和架构、运维、监控都有关系。设计网络方案的时候,要考虑到整个系统的需求。

可用性说明:本文发布于 2019 年 5 月,距今已超过五年。文中涉及的软件版本、接口、下载地址、命令参数和操作界面可能已经发生变化,部分方案在当前环境下可能失效。请结合官方最新文档核对后再操作,生产环境使用前务必先行验证。

版权声明: 本文首发于 指尖魔法屋-容器网络实践笔记https://blog.thinkmoon.cn/post/53-container-networking-cni-service-mesh/) 转载或引用必须申明原指尖魔法屋来源及源地址!