Wener Notes

Kubernates 网络

约 4 分钟阅读

Kubernates Network

网络设计

  • 物理网络 - Phycial Net - OS Net
    • 节点之际网络通信
    • 宿主机实际网络 - 例如 eth0
    • 地址为 node-ip
  • 容器网络 - Pod Net
    • 容器之间互通的网络
    • 每个容器都有唯一独立 IP
    • 通常实现是一个节点一个子网,让给 Pod 分配子网进行通信
    • Pod 网络流量在物理网络上看不到 - 例如 eth0 上看不到
    • CNI - Container Network Interface - 容器网络接口 - 标准化了容器之间网络实现接口
      • JSON 配置 - 插件化
      • kubelet 在每次启动 pod 前都会调用 cni 插件
      • /etc/cni/net.d
      • /opt/cni/bin
      • 常见后端
        • linux-bridge
        • ipvlan
        • macvlan
        • Open vSwitch
    • 有非常多不同的实现
      • flannel - 会在节点上创建 flannel1.1 网卡来通信
  • 服务网络 - Service Net
    • 集群内部服务发现、流量分发
    • 服务发现 - 例如 nginx.default.svc.cluser.local 域名
    • 没有访问控制、没有流量控制
    • 虚拟地址 - VIP - Virtual IP
    • 三种模式
      • ClusterIP
      • LoadBalancer
      • NodePort
    • kube-proxy - 配置 iptables 暴露服务
      • 通过修改 iptables 来实现流量转发
      • iptables 指向每个 endpoint
      • 每个包打随机数用来实现负载 - 但不精确
    • iptables-save 会看到 KUBE-SERVICE 相关的规则
    • service-cird 指定了 ClusterIP 的地址段
    • 服务之下为 Endpoint - 通常为 Pod,也可以直接定义 Endpoint
  • Ingress
    • Kubernates 的网络入口,将服务暴露到外部
    • 直接与 Pod 通信而不是与服务通信
    • 通常为 7 层 HTTP - 部分支持 4 层 TCP
    • 大多实现也支持 CRD 方式,支持更复杂的定义逻辑
  • Egress - 出口流量
    • 使用较少,目前 calico 支持
  • 参考

资源

  • ServiceLoadBalancerClass - v1.22 beta
    • spec.loadBalancerClass
  • IngressClass
    • spec.parameters.scope: Namespace - Namespace 纬度 IngressClass v1.22 beta

集群网络

服务发现

推荐 Annotation

json
{
  "api.service.kubernetes.io/protocol": "REST",
  "api.service.kubernetes.io/scheme": "http",
  "api.service.kubernetes.io/path": "cxfcdi",
  "api.service.kubernetes.io/description-path": "cxfcdi/swagger.json",
  "api.service.kubernetes.io/description-language": "SwaggerJSON"
}

resolv.conf

服务网络

ClusterIP

  • 无外部访问
  • 可通过 kubectl proxy --port=8080 进行访问 - 地址为 http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/
  • 用于调试和暴露内部服务
yaml
apiVersion: v1
kind: Service
metadata:
  name: my-internal-service
spec:
  selector:
    app: my-app
  type: ClusterIP
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP

NodePort

  • 提供外部访问最原始的方法
  • 在所有节点开启相同端口进行转发
  • 缺点
    • 一个服务只能暴露一个端口
    • 端口限定在 30000–32767
    • 需要关注节点地址变化
  • 场景
    • 演示服务
    • 单端口服务 - 例如 DNS
yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  selector:
    app: my-app
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      # 不指定则随机分配
      # 30000-32767
      nodePort: 30036
      protocol: TCP

LoadBalancer

yaml
apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer
bash
# 将某个服务通过负载均衡的方式进行端口暴露
kubectl expose svc web --type=LoadBalancer --port=80 --target-port=8080 --external-ip=192.168.1.2 --name=web-lb

# 查看服务状态包含地址信息
kubectl describe svc ingress-nginx-ingress-controller

Ingress

  • 不是一个服务
  • 应用层路由 - 分为 Ingress 定义和 IngressController 控制器
  • 常见实现 Nginx、Istio、TraefikGitHubcontainous/traefik、ContourGitHubprojectcontour/contour
  • 一般需要配套 cert-manager 使用
  • 能附带其它能力 SSL、鉴权、路由等
  • 场景
    • 使用 HTTP 协议
    • 一个后端暴露多个服务
yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: other
    servicePort: 8080
  rules:
    - host: foo.mydomain.com
      http:
        paths:
          - backend:
              serviceName: foo
              servicePort: 8080
    - host: mydomain.com
      http:
        paths:
          - path: /bar/*
            backend:
              serviceName: bar
              servicePort: 8080

ExternalName

  • 会将 my-service.prod.svc.cluster.local CNAME 为 my.database.example.com
  • 如果使用 SSL 会有证书问题
  • 如果使用的环境 DNS 不互通也会有问题
yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

ExternalIPs

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
  externalIPs:
    - 80.11.12.10

FAQ

NodePort vs HostPort vs HostNetwork

  • 都是为了在虚拟节点上暴露端口
  • TLS 场景如果想要获取到客户端 IP 则需要暴露端口到主机 - 否则使用 tcp proxy - 很麻烦
  • NodePort
    • 推荐方式
    • Kubernetes 管理 - 端口范围 30000–32767
    • 可以转发服务 - 不需要节点运行 POD
  • HostPort
    • 不推荐使用 - 除非不得已 - node daemon
    • Kubernetes 预留端口
    • 节点需要运行 POD
    • 取决于 CNI 实现
    • 会影响 pod 调度 - 因为端口冲突
  • HostNetwork
    • 不依赖 CNI
    • 在宿主机网络空间
    • 能访问 lookback 设备、服务 等
    • 能够获取节点上的网络活动
    • DaemonSet 时可以使用
  • 参考

关联信息

反向链接、本文链接的其他页面和外部资料。

References

GitHub10 条
其他外链8 条
最近更新commit ccdb50fEdit

On this page