CNI
CNI 定义的是容器运行环境与网络插件之间的简单接口规范,通过一个 JSON Schema 定义 CNI 插件提供的输入和输出参数。一个容器可以通过绑定多个网络插件加入多个网络中。
Kubenetes 网络汇总
- Pod 内各自都会有个 network namespace,拥有唯一 IP(经典网络 IP), Pod 会创建一个 pasue 容器(沙箱容器)来持有一个 network namespace,而容器内所有的 docker 共享这个 net ns.
- Node 上面有一个 root netns, Pod 通过桥接的方式连接到 Node 的 docker 网卡
- Node 内的 Pod 通过 cbr0(center bridge) 来访问;
- Node 之间的 Pod 访问,通过 eth0 走路由到另一台的 Node
- Overlay 的网络,通过 flannel0 网卡来封装数据包,走路由到经典网络。 flannel 网卡与 kube apiserver ,etcd 保持联系,所以知道所有节点的信息
Pasue
每一个 Pod 里运行着一个特殊的 Pause 容器,和其他业务容器,这些业务容器共享 Pause 容器的网络栈和 Volume 挂载卷。
Pasue 容器为每个业务容器提供:PID ns, Net ns, IPC ns, UTS ns
flannel
flanneld 启动参数中会增加 —kube-subnet-mgr 参数,flanneld 会初始化一个 kubernetes client 获取本地 node 的 pod-cidr。这个 pod-cidr 会作为 flannel 为 node 本地容器规划的 IP 网段,记录到 /run/flannel/subnet.env 中。
udp/vxlan
每个 node 都有一个 flanneld 进程,和 flannel0 网桥,容器网络与 flannel0 网桥互联,并经由 flannel0 发出。根据不同的协议要求封装 UDP 或者 Vxlan 协议头部
host-gw
flannel 的三层路由方案,每个 node 节点上都会记录其他节点容器 IP 段的路由,通过路由, node A 上的容器发给 node B 上的容器数据,就能在 node A 上进行转发。
Calico
pod 与 Service 之间的访问
因为 Pod 经常变化(自动调度机制),所以 pod 的ip 地址也会发生变化,不能提供一个稳定的访问。所以 kubernetes 的解决方案是 Service,每个 Service 固定一个虚拟 IP 地址(cluster ip),自动且动态绑定后面的 Pod。Service 除了提供稳定的对外访问方式外,还能起到负载均衡的功能。而提供这个能力的关键是 kube proxy。
Cluster IP
- 仅用于 kubernetes Service 这个对象,并由 Kubernetes 管理和分配 IP 地址;
- cluster ip 无法被ping ,它没有一个“实体网络对象”响应
- cluster ip 只能结合 Service Port 组合成一个具体的通信端口,单独 ClusterIP 不具备通信的基础,并且他们属于 kubernetes 集群这样一个封闭的空间。
cluster ip 的方式:
- 普通 Service : 通过为 Kubernetes 的 Service 分配一个集群内部可访问的固定虚拟 IP,实现集群内的访问;- Headless Service:不分配 cluster ip,通过 dns 提供稳定的网络 ID 来访问,dns 会将 headless service 的后端直接解析为 pod IP,主要供 statefulSet 使用
kubectl -n 命名空间 get Service 可以查看到 Cluster IP

Port : 提供给集群内部客户访问 service 的入口;
targetPort:是 Pod 上的端口
endpoints: 后端服务
NodePort
Service 的 Port 映射到每个 node 的一个指定内部 port 上: nodeip + nodeport
loadbalance
loadbalance 在 NodePort 基础上,k8s 可以请求底层云平台创建一个负载均衡器,将每个 Node 作为后端,进行服务分发。
提供一个公网的 IP 地址给外部访问,外部 IP 再负载均衡分发给 Node 节点。依然是 Service 为一个单元
Ingress
采用 NodePort 的缺点是,一旦 service 多起来,NodePort 在每个节点上开启的端口会及其庞大,而 loadbalance 则每个服务一个公网 IP,消耗也很大。
Ingress 是管理外部访问集群服务的 API,比如 HTTP。Ingress 可以提供负载,SSL,基于主机的虚拟主机。
Ingress 不会暴露任何一个端口或者协议,暴露服务除 HTTP 或者 HTTPS 之前的内部访问使用 Service.Type=NodePort or Service.Type=LoadBalancer.
ingress 和 ingress-controller 一起完成服务方法控制,如果只是创建 Ingress 资源是无效的。ingress-controller 比如 Ingress-nginx
基本的实现逻辑:每个 Node 节点通过 NodePort 类型的 Service 暴露 80/443 端口,然后转发请求给一个有 Nginx 的 Pod
Ingress 通过 yaml 的创建/更新,实现 Nginx 配置的修改,而完成内部服务的转发。
Ingress Controller 实时监控 Kubernetes API,实时更新 HTTP 代理服务器的转发规则。Ingress Controller 动态获取集群中 Ingress 的变化,然后生成一段 Nginx 配置,在写到 Nginx Pod 里面,最后重新 reload 。
所以 Kubernetes Ingress = 微服务网关,本质是:七层反向代理
Ingress 资源
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-myapp
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules: # 用于定义当前 Ingress 资源的转发规则列表;如果没有匹配到规则会转发给 backend 定义的默认后端
- host: myapp.magedu.com # 不支持使用 Ip 地址定义,也不支持 IP:Port 的方式,字段留空标识匹配所有主机名
http:
paths:
- path: /testpath
pathType: Prefix
backend: # 默认的后端用于服务那些没有匹配到任何规则的请求;rules 和backend 必须有存在一者
serviceName: myapp
servicePort: 80
Ingress 资源类型
单 Service 资源型 ingress
# 只需要指定 backend 就行 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-ingress spec: backend: serviceName: my-svc servicePort: 80基于 Url 路径进行流量转发
- 基于主机名称的虚拟主机
- TLS 类型的 Ingress 资源
ingress controllers
为了 Ingress 正常运行,集群下必须部署一个 ingress controller。它不是 kube-controller-manager 下的,不会自动启动。各个云厂商都有自己的一个项目去支持和维护 ingress controller。
Azure 微软云 AKS https://azure.github.io/application-gateway-kubernetes-ingress/
contour Ingress controller
两部分组成:
- Envoy:提供高性能反向代理
- contour : 充当 Envoy 的控制平面,为 Envoy 的路由配置提供统一的来源;

kube proxy
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程,kube-proxy 负责为 Service 实现一种 VIP (虚拟 IP)的形式。到 Kubernetes v1.8.0-beta.0 版本,添加了 ipvs 代理模式。
kube proxy 运行在每个节点上,监听 API Server 中服务对象的变化,通过管理 iptables 来实现网络的转发。在以前版本可以使用 userspace 用户空间监听端口。
apiVersion: v1
kind: Service
metadata:
labels:
name: whoami
name: whoami
spec:
ports:
- port: 3000
# 虚拟 IP 要绑定的 port,每个 service 会创建出来一个虚拟 IP,cluster ip
targetPort: 3000
# pod 中暴露的 port
protocol: TCP
# 服务类型
# nodePort : int 这个参数如果不指定自动分配(30000-32767)
selector:
# 告知 service 后端的 pod,和所有 pod 的 labels 标签匹配
app: whoami
env: dev

user space 与 kernel space
- user space : 用户程序的运行空间,用户之间隔离,用户程序奔溃不影响内核运行;只能执行简单运行,不能之间调用系统资源
- kernel space: Linux 内核的运行空间;可以执行任意命令,调用一切资源

top 命令中 CPU 的信息说明
- us : user 缩写 , CPU 消耗在 user space 的时间百分比;
- sy : system 缩写,CPU 消耗在 kernel space 的时间百分比
- ni : niceness 缩写,CPU 消耗在 nice 进程(低优先级)的时间百分比
- id : idle 缩写,CPU 消耗在闲置进程的时间百分比,越低越忙
- wa : wait 缩写,CPU 等待外部 I/O 的时间百分比,这段时间 CPU 不能干其他事,但是也没有执行运算,这个值太高就说明外部设备有问题
- hi : hardware interrupt 缩写,CPU 响应硬件终端请求的时间百分比
- si : software interrupt 缩写,CPU 响应软件终端请求的时间百分比
- st : stole time 缩写,该项指标只对虚拟机有效,表示分配给当前虚拟机的 CPU 时间之中,被同一台物理机上的其他虚拟机偷走的时间比
