"为啥我的服务连不上"、"网络延迟怎么这么高"、"防火墙规则怎么配"...每次都要解释半天。想想我刚入行那会儿,对Linux网络也是一头雾水,踩过的坑能绕地球三圈。今天就把这些年积累的经验整理出来,希望能帮到正在网络问题中挣扎的朋友们。
说起Linux网络,很多人第一反应就是ifconfig、ping这些命令。但实际上,要真正理解网络问题,你得先搞清楚数据包在系统里是怎么流转的。
我记得有次线上服务突然访问不了,所有人都在群里炸锅。我用tcpdump抓包发现数据包根本没到应用层,卡在了iptables那里。原来是运维同事更新防火墙规则时手抖了,把正常流量也给拦截了。这种问题如果不了解网络栈的工作原理,真的很难快速定位。
Linux的网络栈大概是这样的:网卡接收数据包 → 内核网络栈处理 → iptables规则过滤 → 路由决策 → 应用程序接收。每一层都可能出问题,所以排查网络故障时要有层次感。
image-20250921210341360
现在很多发行版都在推ip命令替代ifconfig,但说实话,我到现在还是两个都在用。习惯这东西真的很难改...
# 查看网络接口
ip addr show
# 或者老式的
ifconfig -a
# 添加IP地址(注意这个添加是临时的,重启后会失效)
ip addr add 192.168.1.100/24 dev eth0
# 删除IP地址
ip addr del 192.168.1.100/24 dev eth0
image-20250921212304394
# 网络接口列表输出
# 回环接口(loopback),用于本地通信
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # 回环接口MAC地址
inet 127.0.0.1/8 scope host lo # IPv4地址,本地回环
valid_lft forever preferred_lft forever # 地址永久有效
inet6 ::1/128 scope host # IPv6回环地址
valid_lft forever preferred_lft forever # 地址永久有效
# 物理网卡接口,这里是虚拟机中的网卡
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 00:0c:29:1f:90:5a brd ff:ff:ff:ff:ff:ff # 网卡MAC地址
altname enp2s1 # 网卡的替代名称
# 网桥接口,用于连接物理和虚拟网络接口(前几天做实验配置的)
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:1f:90:5a brd ff:ff:ff:ff:ff:ff # 与ens33相同的MAC地址
inet 192.168.198.130/24 brd 192.168.198.255 scope global dynamic noprefixroute br0 # 动态分配的IPv4地址
valid_lft 1703sec preferred_lft 1703sec # 地址租约剩余时间
inet6 fe80::f8b:84f0:7d10:3521/64 scope link noprefixroute # IPv6本地链路地址
valid_lft forever preferred_lft forever # 地址永久有效
# 虚拟网桥,由libvirt创建用于虚拟机网络(未连接状态)
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:61:85:e7 brd ff:ff:ff:ff:ff:ff # 虚拟网桥MAC地址
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 # libvirt默认NAT网络地址
valid_lft forever preferred_lft forever # 地址永久有效
<BROADCAST,MULTICAST,UP,LOWER_UP>
BROADCAST
: 支持广播数据包MULTICAST
: 支持多播UP
: 接口已启用(逻辑上)LOWER_UP
: 底层物理链路已连接(物理层已启用)mtu 1500
qdisc fq_codel
master br0
state UP
group default
qlen 1000
接下来来讲讲路由,路由配置这块经常让人头疼。我见过太多因为路由配置错误导致的网络问题了。
# 查看路由表
ip route show
route -n
# 添加静态路由
ip route add 10.0.0.0/8 via 192.168.1.1
# 添加默认路由
ip route add default via 192.168.1.1
image-20250921212801503
有个小技巧,如果你要临时测试路由,可以用ip route add,重启后就失效了。要永久生效的话,不同发行版配置文件位置不一样,CentOS是在/etc/sysconfig/network-scripts/,Ubuntu在/etc/netplan/。
说到网络配置,不得不提NetworkManager这个工具。以前我也是抗拒的,觉得直接改配置文件多直接啊,为啥要用这么复杂的东西?但用久了发现,NetworkManager确实解决了很多传统网络配置的痛点,特别是在桌面环境和复杂网络场景下。
nmcli是NetworkManager的命令行工具,功能相当强大。刚开始用的时候语法有点绕,但熟悉了之后效率很高。
# 查看所有网络连接
nmcli connection show
# 查看活动连接
nmcli connection show --active
# 查看设备状态
nmcli device status
# 查看具体设备信息
nmcli device show eth0
我记得有次服务器网卡配置乱了,用nmcli一看就清楚了哪些连接是活动的,哪些是配置了但没启用的。比直接看配置文件直观多了。
image-20250921212921936
创建静态IP连接:
# 创建静态IP连接
nmcli connection add type ethernet con-name static-eth0 ifname eth0 \
ip4 192.168.1.100/24 gw4 192.168.1.1
# 设置DNS
nmcli connection modify static-eth0 ipv4.dns "8.8.8.8 8.8.4.4"
# 启用连接
nmcli connection up static-eth0
创建DHCP连接就更简单了:
nmcli connection add type ethernet con-name dhcp-eth0 ifname eth0
nmcli connection up dhcp-eth0
修改现有连接也很方便:
# 修改IP地址
nmcli connection modify eth0 ipv4.addresses 192.168.1.200/24
# 修改网关
nmcli connection modify eth0 ipv4.gateway 192.168.1.1
# 重新激活连接使配置生效
nmcli connection up eth0
虽然服务器一般不用无线,但有时候临时测试环境或者边缘设备可能会用到:
# 扫描无线网络
nmcli device wifi list
# 连接无线网络
nmcli device wifi connect "SSID" password "password"
# 连接隐藏网络
nmcli device wifi connect "SSID" password "password" hidden yes
NetworkManager的配置文件在/etc/NetworkManager/system-connections/目录下,但一般不建议直接编辑。用nmcli修改后会自动更新配置文件,而且语法检查更严格。
# 重新加载配置
nmcli connection reload
# 重启NetworkManager服务
systemctl restart NetworkManager
有个小技巧,如果你想临时禁用NetworkManager管理某个网卡,可以这样:
# 设置设备为unmanaged状态
nmcli device set ens33 managed no
# 恢复管理
nmcli device set ens33 managed yes
NetworkManager还支持一些高级功能,比如网络绑定(bonding):
# 创建bond连接
nmcli connection add type bond con-name bond0 ifname bond0 mode active-backup
# 添加slave接口
nmcli connection add type ethernet slave-type bond con-name bond0-slave1 ifname eth0 master bond0
nmcli connection add type ethernet slave-type bond con-name bond0-slave2 ifname eth1 master bond0
# 配置bond0的IP
nmcli connection modify bond0 ipv4.addresses 192.168.1.100/24
nmcli connection modify bond0 ipv4.gateway 192.168.1.1
nmcli connection modify bond0 ipv4.method manual
# 启用连接
nmcli connection up bond0-slave1
nmcli connection up bond0-slave2
nmcli connection up bond0
VLAN配置也很简单:
# 创建VLAN接口
nmcli connection add type vlan con-name vlan100 ifname eth0.100 dev eth0 id 100
# 配置VLAN的IP
nmcli connection modify vlan100 ipv4.addresses 192.168.100.10/24
nmcli connection modify vlan100 ipv4.method manual
nmcli connection up vlan100
nmcli在故障排查时也很有用:
# 查看连接详细信息
nmcli -f all connection show ens33
# 查看设备详细信息
nmcli -f all device show ens33
# 监控连接状态变化
nmcli monitor
我遇到过网络间歇性断开的问题,用nmcli monitor实时监控发现是NetworkManager在自动重连,原来是网线接触不良导致的。
批量操作时可以用脚本:
#!/bin/bash
# 批量配置多个网卡
for i in {1..4}; do
nmcli connection add type ethernet con-name eth$i ifname eth$i \
ip4 192.168.$i.10/24 gw4 192.168.$i.1
nmcli connection up eth$i
done
如果你习惯了传统的网络配置方式,也可以禁用NetworkManager:
systemctl stop NetworkManager
systemctl disable NetworkManager
# 然后用传统方式配置网络
但我建议还是拥抱新工具,NetworkManager确实在很多场景下更方便,特别是需要频繁切换网络配置的时候。
说实话,刚开始用nmcli时我也觉得命令太长太复杂,但用熟了发现确实比手动编辑配置文件效率高。而且NetworkManager会自动处理很多细节,比如DNS配置、路由更新等,减少了出错的可能性。
ping命令谁都会用,但你知道ping的工作原理吗?它发送的是ICMP Echo Request包,如果对方禁用了ICMP响应,ping就会失败,但这不代表网络不通。
# 基本ping测试
ping -c 4 8.8.8.8
# 指定包大小测试MTU
ping -s 1472 8.8.8.8
# 不进行DNS解析,加快速度
ping -n 8.8.8.8
traceroute能显示数据包的路径,对于排查网络路由问题特别有用:
# 跟踪路由路径
traceroute google.com
# 使用TCP而不是UDP
traceroute -T -p 80 google.com
netstat虽然老,但功能强大。现在推荐用ss命令,速度更快(下次来讲讲他们两个的区别):
# 查看所有监听端口
ss -tuln
netstat -tuln
# 查看特定端口的连接
ss -an | grep :80
# 查看进程信息
ss -tulnp
image-20250921213318677
iptables这东西,说复杂也复杂,说简单也简单。关键是要理解它的工作流程:表(table) → 链(chain) → 规则(rule)。关于iptables可以看我之前的文章别再被iptables搞懵了!一文彻底搞懂Linux防火墙的底层逻辑
# 查看当前规则
iptables -L -n -v
# 允许SSH连接
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许HTTP和HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
# 默认拒绝所有入站连接
iptables -P INPUT DROP
image-20250921213338141
不过现在很多系统都在用firewalld了,语法相对简单一些:
# 查看当前状态
firewall-cmd --state
# 查看活动区域
firewall-cmd --get-active-zones
# 开放端口
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
# 添加服务
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
我个人建议,生产环境还是用iptables,控制更精细。开发环境用firewalld就够了,配置简单。
网络性能问题经常让人抓狂。我遇到过一个案例,应用响应时间突然变慢,CPU和内存都正常,最后发现是网络参数配置不当导致的。
TCP参数调优是个大学问:
# 查看当前TCP参数
sysctl -a | grep net.ipv4.tcp
# 常用的优化参数
echo 'net.core.rmem_max = 16777216' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 16777216' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_rmem = 4096 65536 16777216' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_wmem = 4096 65536 16777216' >> /etc/sysctl.conf
# 应用配置
sysctl -p
image-20250921213505433
网络队列长度也很重要,特别是高并发场景:
# 查看网络队列统计
cat /proc/net/softnet_stat
# 调整网络队列长度
echo 'net.core.netdev_max_backlog = 5000' >> /etc/sysctl.conf
tcpdump和wireshark是网络排查的神器。我记得有次数据库连接池耗尽,用tcpdump抓包发现大量TIME_WAIT状态的连接,原来是应用没有正确关闭数据库连接。
# 基本抓包
tcpdump -i eth33 -n
# 抓取特定端口
tcpdump -i ens33 port 80
# 抓取特定主机
tcpdump -i ens33 host 192.168.1.100
# 保存到文件供wireshark分析
tcpdump -i ens33 -w capture.pcap
# 只抓取TCP SYN包
tcpdump -i ens33 'tcp[tcpflags] & tcp-syn != 0'
抓包时要注意几个点:一是抓包会消耗系统资源,生产环境要谨慎;二是要选择合适的过滤条件,避免产生过大的文件;三是涉及敏感数据时要注意安全。
光会排查问题还不够,更重要的是要能提前发现问题。网络监控这块我推荐几个工具:
iftop可以实时查看网络流量:
# 安装iftop
yum install iftop # CentOS
apt install iftop # Ubuntu
# 监控特定网卡
iftop -i ens33
# 不进行DNS解析
iftop -n
image-20250921213807761
对于更复杂的监控需求,可以考虑用Zabbix、Prometheus这些监控系统。我们公司就是用Prometheus + Grafana的组合,效果不错。
网络问题千奇百怪,但排查思路基本是固定的。我总结了一个简单的流程:
我遇到过一个奇葩问题,服务器间歇性断网,ping有时通有时不通。折腾了半天发现是网线接触不良...所以排查问题时,简单的原因往往最容易被忽略。
还有个经验就是,网络问题很多时候不是单一原因造成的。比如DNS解析慢 + 连接池配置不当 + 网络延迟高,三个问题叠加就可能导致服务不可用。
网络配置时安全问题不能忽视。我见过因为iptables配置错误导致服务器被入侵的案例,损失惨重。
几个基本的安全原则:
# 检查监听端口
ss -tuln | grep LISTEN
# 检查可疑连接
ss -an | grep ESTABLISHED | wc -l
分享几个我平时用得比较多的小技巧:
用nc命令测试端口连通性:
# 测试TCP端口
nc -zv 192.168.1.100 80
# 测试UDP端口
nc -zuv 192.168.1.100 53
临时启动一个HTTP服务器:
# Python 3
python3 -m http.server 8000
# Python 2
python -m SimpleHTTPServer 8000
快速查看网络连接状态统计:
ss -s
netstat -s
这些小工具在应急情况下特别有用,建议都掌握一下。
网络这块的知识确实比较庞杂,我这里只是抛砖引玉,分享了一些实战中比较常用的内容。每个环境都有自己的特点,具体问题还得具体分析。重要的是要多实践,多总结,慢慢就能形成自己的知识体系。
记住一点:网络问题排查需要耐心和系统性思维,不要急于求成。有时候看似复杂的问题,可能就是一个很简单的配置错误。保持冷静,按部就班地排查,总能找到问题所在。
希望这些内容对大家有帮助,网络运维这条路虽然虽然坎坷,但每解决一个问题都会让你成长不少。
现在容器化部署越来越普及,Docker网络又是另一套体系。刚开始接触时我也是懵的,容器之间怎么通信?容器怎么访问外网?外网怎么访问容器?
Docker默认会创建几种网络模式:
# 查看Docker网络
docker network ls
# 查看默认bridge网络详情
docker network inspect bridge
image-20250921214226183
最常用的就是bridge模式,Docker会创建一个docker0网桥,容器通过veth pair连接到这个网桥上。听起来复杂,其实就是虚拟交换机的概念。
image-20250921214244774
# 创建自定义网络
docker network create --driver bridge my-network
# 运行容器时指定网络
docker run -d --network my-network --name web nginx
docker run -d --network my-network --name db mysql
容器间通信有个坑,就是IP地址会变化。所以最好用容器名或者服务名来通信,Docker内置了DNS解析。
端口映射也是个常见问题:
# 映射端口
docker run -d -p 8080:80 nginx
# 查看端口映射
docker port container_name
image-20250921214337293
我遇到过端口映射不生效的情况,后来发现是iptables规则冲突。Docker会自动添加iptables规则,如果你手动修改了相关规则,可能会出问题。
如果说Docker网络已经够复杂了,那Kubernetes网络简直是噩梦级别。Pod网络、Service网络、Ingress...每一层都有自己的逻辑。
Pod是Kubernetes的最小调度单元,每个Pod都有自己的IP地址:
# 查看Pod IP
kubectl get pods -o wide
# 进入Pod查看网络配置
kubectl exec -it pod-name -- ip addr show
Service提供了稳定的访问入口,通过标签选择器关联Pod:
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Service有几种类型:ClusterIP(集群内访问)、NodePort(节点端口访问)、LoadBalancer(负载均衡器)。选择哪种要看具体需求。
CNI插件负责实际的网络实现,常见的有Flannel、Calico、Weave等。我们用的是Calico,支持网络策略,安全性更好:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
生产环境必须要有完善的监控体系。我们用的是Prometheus + Grafana + AlertManager的组合:
# prometheus配置示例
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'nginx'
static_configs:
- targets: ['localhost:9113']
关键指标包括:
告警规则要设置合理的阈值,太敏感会产生告警风暴,太迟钝又发现不了问题。这个需要根据业务特点来调整。
网络优化是个系统工程,不是调几个参数就能解决的。我总结几个要点:
我见过有人一口气改了十几个内核参数,结果系统直接崩了,排查问题花了一整天。所以优化要谨慎,特别是生产环境。
最后分享几个我踩过的坑,希望大家能避免:
还有个血泪教训,千万不要在生产环境直接修改网络配置。我见过有人改错了路由表,直接把服务器改"失联"了,只能机房跑一趟。
网络运维这行,经验真的很重要。书本上的知识只是基础,实际环境中的问题千奇百怪,需要不断学习和积累。
记住一句话:网络问题90%都是配置问题,剩下10%是硬件问题。所以排查时先检查配置,再考虑硬件。
好了,今天就分享这么多。网络这块的内容确实很多,我这里只是抛砖引玉。如果大家在实际工作中遇到网络问题,欢迎留言讨论,一起学习进步。
运维这条路不好走,但每解决一个问题都是成长。希望我的分享能帮到正在路上的朋友们。记得关注@运维躬行录,我会持续分享更多实战经验和技术干货,让我们一起在运维的道路上躬行致远!
如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!
公众号:运维躬行录
个人博客:躬行笔记