Kubernetes(k8s) 网络策略及排错
文章目录k8s 网络策略k8s 网络故障定位指南IP 转发和桥接IP 转发桥接hairpin查看 pod ip 地址故障排查工具为什么不推荐使用SNATk8s 网络策略k8s 网络策略采用了比较严格的单向控制{} 表示允许所有,[] 表示拒绝所有# 所有pod允许所有流量进入apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:na
·
k8s 网络策略
- k8s 网络策略采用了比较严格的单向控制
- {} 表示允许所有,[] 表示拒绝所有
# 所有pod允许所有流量进入
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
# 筛选 pod 应用下面规则
podSelector:
matchLabels:
role: db
policyTypes: # 不写,默认为 Ingress
- Ingress
- Egress
# 管理进入流量 下面的规则都是独立的 不是和的关系
ingress:
- from:
- ipBlock: # 在此ip范围,但不包含172.17.1.0/24的ip可与上述筛选的pod的80端口建立连接
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector: # 符合条件的 namespace 可与上述 pod 的 80 端口建立 tcp 连接
matchLabels:
project: myproject
- podSelector: # default namespace 下,满足条件的 pod 可与上述 pod 建立连接 80 tcp
matchLabels:
role: frontend
- ports:
- protocol: TCP
port: 80 # 指的是筛选出的 pod 端口
# 管理出去流量
egress:
- to:
- ipBlock: # 允许上述筛选出的 pod 访问网段为 10.0.0.0/24 的 5978 端口
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978 # 指的是目的端口
k8s 网络故障定位指南
IP 转发和桥接
linux 内核设置低级别的集群 IP 负载均衡,除了 iptables 和 IPVS,还需要用到两个关键的模块:IP转发(IP forward)和桥接
IP 转发
- 是一种内核态设置,允许将一个接口的流量转发到另一个接口
- 该配置是内核将流量从容器路由到外部所必需的
- 没有启动的话,会出现网络访问失败的情况。如,访问 Pod 服务连接超时
# 检查 ipv4 forwarding 是否开启
sysctl net.ipv4.ip_forward
# 0 意味着未开启
net.ipv4.ip_forward = 0
# 进行修复
sysctl -w net.ipv4.ip_forward=1
echo net.ipv4.ip_forward=1 >> /etc/sysconf.d/10-ipv4-forwarding-on.conf
# 验证并生效
sysctl -p
桥接
- k8s 通过 bridge-netfilter 配置使 iptables 规则应用在 linux 网桥上
- 该配置对内核进行宿主机和容器之间数据包的地址转换是必需的
- 否则,Pod 进行外部服务网络请求使会出现,目标主机不可达或连接拒绝等错误
# 检查 bridge netfilter 是否开启
sysctl net.bridge.bridge-nf-call-iptables
# 0 表示未开启
net.bridge.bridge-nf-call-iptables = 0
# 开启这个 iptables 配置
sysctl -w net.bridge.bridge-nf-call-iptables=1
echo net.bridge.bridge-nf-call-iptables=1 >> /etc/sysconf.d/10-bridhe-nf-call-iptables.conf
sysctl -p
##Pod CIDR 冲突
- 容器与容器之间通信建立了一层特殊的 overlay 网络(虚拟ip)
- 若 Pod 子网和宿主机网络出现冲突是,就会产生问题,导致无法访问
- 将主机 IP 范围和 API Server 中指定的子网进行比较
- 可在 CNI 插件 或 kubelet 的 pod-cidr 参数中指定 IP 地址范围,避免冲突
hairpin
- 就是 自己访问自己
- 有时 Pod 无法通过 Service IP 访问自己,这就有可能是 hairpin 的配置问题了
- 通常,当 kube-proxy 以 iptables 或 IPVS 模式运行,并且 Pod 与桥接网络连接时,就会发生这种情况
- kubelet 的启动参数提供了一个 --hairpin-mode 标志,支持的值有 hairpin-veth 和 promiscuous-bridge
- –hairpin-mode 被 kubelet 设置成 hairpin-veth 并且生效后,底层其实是在修改宿主机 /sys/devices/virtual/net 目录下设备文件 hairpin_mode de 值
# 查看是否修改成功
for intf in /sys/devices/virtual/net/cbr0/brif/; do cat $intf/hairpin_mode; done
查看 pod ip 地址
# 从外面看
kubectl get pod
kubectl describe pod
# 进入容器查看 假设Pod的pause容器名称为abc
# 获得容器 id 假设结果返回32166
docker inspect abc --format '{{ .State.Pid}}'
# 进入容器查看
nsenter --target 32166 --net
ip addr
故障排查工具
-
tcpdump 捕获网络流量
-
容器镜像内置常用网络工具
-
FROM library/python:3.3 RUN apt-get update && apt-get -y install iptoute2 net-tools ethtool nano
-
为什么不推荐使用SNAT
- 因为内核需要修改源地址和端口,并记录到表中,并发多时,会导致记录覆盖,因此产生丢包
- SNAT导致内核丢包原因在于其conntrack的实现
- 容器端口映射到主机端口,会从上次分配的主机端口,向下顺次搜索,返回可用端口,当高并发时,可能将一个端口返回给多个容器,并记录到了表中,导致之后的丢包
- 因此之后产生了随机探测宿主机可用端口,来避免冲突,缓解此问题
- NF_NAT_RANGE_PROTO_RANDOM 部分随机
- NF_NAT_RANGE_PROTO_RANDOM_FULLY 完全随机
- iptables 已经支持 --random-fully 这个 flag
- 虽然缓解了此问题,但不表示根治,因此不推荐生产环境上使用 NodePort
更多推荐
已为社区贡献41条内容
所有评论(0)