metallb
官网: https://metallb.universe.tf/
搭建步骤:
1.
kubectl edit configmap -n kube-system kube-proxy
编辑kube-proxy 的configmap文件
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/namespace.yaml
可以先通过wget 将该yaml文件拿下来,再应用
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/metallb.yaml
应用yaml文件
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
创建一个secret
测试;
- 建立一个地址池
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 172.25.254.110-172.25.254.120
效果:
2. 启动一个简单的服务
apiVersion: v1
kind: Service
metadata:
name: lb-nginx
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
测试效果;
结合ingress:
正常启动ingress,使其能通过节点端口的方式访问后端service,通过修改ingress-nginx-controller 的type为LoadBalancer
- 修改解析,查看测试效果
k8s网络通信
k8s通过CNI接口接入其他插件来实现网络通讯,目前比较流行的插件有flannel,calico
CNI插件的存放位置: /etc/cni/net.d/ 目录下
-
容器间通信:同一个pod内的多个容器间的通信,通过lo即可实现
-
pod之间的通信
- 同一节点的pod之间通过cni网桥转发数据包
- 不同节点的pod之间的通信需要网络插件的支持
-
pod和service通信:通过iptables或ipvs实现通信,ipvs取代不了iptables,因为ipvs没有nat功能
flannel网络通信
各个组件的解释:
- Cni0: 网桥设备,每创建一个pod都会创建一对veth pair。其中一端时pod中的eth0,另一端时Cni0网桥中的端口(网卡)。Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口(网卡)上。
Cni0 设备获得的ip地址是该节点分配到的网段的第一个地址。 - Flannel.1: overlay网络的设备,用来进行vxlan报文的处理(封包和解包)。不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。
Flanneld:flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel.1设备提供封装数据时必要的mac,ip等网络数据信息。
不同node上的pod的通信流程:
- pod中产生数据,根据pod的路由信息,将数据发送到Cni0
- Cni0 根据节点的路由表,将数据发送到隧道设备flannel.1
- Flannel.1查看数据包的目的ip,从flanneld获得对端隧道设备的必要信息,封装数据包。
- Flannel.1将数据包发送到对端设备。对端节点的网卡接收到数据包,发现数据包为overlay数据包,解开外层封装,并发送内层封装到flannel.1设备。
- Flannel.1设备查看数据包,根据路由表匹配,将数据发送给Cni0设备。
- Cni0匹配路由表,发送数据给网桥上对应的端口。
可以通过实验来感受这个过程,用daemonset控制器启动两个pod,默认就会在每一个节点起一个pod。
效果
命令查看:
网络原理:
目前flannel有多种backend管理网络,常用的有三种:hostgw,udp,vxlan,三者差异如下:
特点 | |
---|---|
host-gw | 这种方式就是直接路由 |
vxlan | 是flannel推荐的方式。需要通信的网络设备能够支持vxlan协议 |
udp | 该方式与vxlan很类似,它对ip层网络进行包装。通常用于调试环境或者不支持vxlan协议网络环境中。 |
默认采用vxlan的模式,可以修改为host-gw模式,或者两者并存:
kubectl -n kube-system edit cm kube-flannel-cfg
进入交互模式,进行修改。
- 修改了cm文件,并不会立马生效,可以通过删除flanel pod 的方式,使之生效。
- 修改前后的变化
vxlan模式,traceroute
host-gw模式
calico网络通信
官网: https://docs.projectcalico.org/about/about-calico
calico安装文件: calico.yml和namespace.yml 提取码: je48
镜像:
网络策略
官网: https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
通过deployment控制器,生成标签为app=nginx
的pod。默认情况下,Pod 是非隔离的,它们接受任何来源的流量。可以通过NetworkPolicy来控制访问规则。
networkPolicy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-nginx
spec:
podSelector:
matchLabels:
app: nginx
效果:
默认会禁止入站流量,对出站流量不做限制。
禁止namespace中所有Pod之间的相互访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
禁止其他namespace访问服务
不同namespace的pod是可以直接通行的
禁止其他namespace访问服务的yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-namespace
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
效果:
允许指定namespace访问
限制指定namespace 下匹配的pod 禁止访问