K8s之负载均衡

👨‍🎓博主简介

  🏅CSDN博客专家

  🏅云计算领域优质创作者

  🏅华为云开发者社区专家博主

  🏅阿里云开发者社区专家博主

💊交流社区: 运维交流社区 欢迎大家的加入!

🐋 希望大家多多支持,我们一起进步!😄

🎉如果文章对你有帮助的话,欢迎 点赞 👍🏻 评论 💬 收藏 ⭐️ 加关注+💗


文章目录

    • [一、使用DaemontSet方式部署 nginx服务 - 用于测试](#一、使用DaemontSet方式部署 nginx服务 - 用于测试)
      • [1.1 编写yaml文件](#1.1 编写yaml文件)
      • [1.2 创建并部署nginx服务](#1.2 创建并部署nginx服务)
      • [1.3 修改nginx默认内容](#1.3 修改nginx默认内容)
    • [二、按 Service 方式进行负载](#二、按 Service 方式进行负载)
      • [2.1 ClusterIP 方式进行负载](#2.1 ClusterIP 方式进行负载)
      • [2.2 NodePort 方式进行负载](#2.2 NodePort 方式进行负载)
        • [2.2.1 externalTrafficPolicy 对比](#2.2.1 externalTrafficPolicy 对比)
    • [三、按 Ingress 方式进行负载](#三、按 Ingress 方式进行负载)
      • [3.1 编写 Ingress 规则](#3.1 编写 Ingress 规则)
      • [3.2 编写 nginx svc](#3.2 编写 nginx svc)
      • [3.3 创建 Ingress 规则和 svc](#3.3 创建 Ingress 规则和 svc)
      • [3.4 检查 pod 和 svc是否创建成功](#3.4 检查 pod 和 svc是否创建成功)
      • [3.5 检验是否负载成功](#3.5 检验是否负载成功)
        • [3.5.1 页面访问](#3.5.1 页面访问)
        • [3.5.2 脚本测试负载](#3.5.2 脚本测试负载)
    • [四、LoadBalancer + 云厂商 LB](#四、LoadBalancer + 云厂商 LB)
    • 五、三种负载均衡方式的对比总结表

一、使用DaemontSet方式部署 nginx服务 - 用于测试

1.1 编写yaml文件

  • vi nginx-daemonset.yaml
yaml 复制代码
apiVersion: v1
kind: Namespace
metadata: 
  name: nginx
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-daemonset
  namespace: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      tolerations:           # ← 添加容忍度,如果不添加,则不会再有污点的节点上部署
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
          operator: Exists
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule
          operator: Exists
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
        resources:         
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"

1.2 创建并部署nginx服务

bash 复制代码
# 创建并部署nginx服务
kubectl apply -f nginx-daemonset.yaml

# 查看部署的服务状态
kubectl get ds -n nginx
kubectl get pods -n nginx -o wide

主要检查pod的运行状态和node节点就行,每个节点跑一个nginx pod

1.3 修改nginx默认内容

修改nginx默认内容,便于区分是否进行负载;

给三个 nginx pod中的index.html添加内容,内容例如为:This is k8s-master ,内容需要和对应的节点相同,便于区分;

  • 修改nginx podindex.html内容
bash 复制代码
kubectl exec -n nginx nginx-daemonset-sgpzz -- sh -c 'echo "This is k8s-master" > /usr/share/nginx/html/index.html'
kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'echo "This is k8s-node1" > /usr/share/nginx/html/index.html'
kubectl exec -n nginx nginx-daemonset-j46k4 -- sh -c 'echo "This is k8s-node2" > /usr/share/nginx/html/index.html'
  • 查看并确认修改成功
bash 复制代码
[root@k8s-master ~]# kubectl exec -n nginx nginx-daemonset-j46k4 -- sh -c 'cat /usr/share/nginx/html/index.html'
This is k8s-node2
[root@k8s-master ~]# kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'cat /usr/share/nginx/html/index.html'
This is k8s-node1
[root@k8s-master ~]# kubectl exec -n nginx nginx-daemonset-sgpzz -- sh -c 'cat /usr/share/nginx/html/index.html'
This is k8s-master

二、按 Service 方式进行负载

2.1 ClusterIP 方式进行负载

适用场景

  • 集群内部服务互相调用
  • 不需要外部直接访问
  • 创建svc,vim nginx-svc.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx
spec:
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  # 需和daemonset/deployment/StatefulSet写的一致
  selector:
    app: nginx
  # 负载均衡策略:None=轮询,ClientIP=会话保持
  sessionAffinity: None
  # 内部负载均衡由 kube-proxy 实现(iptables/ipvs 随机分发)

默认不写sessionAffinity: None,也会进行轮询,因为ClusterIP方式默认自带的就是None轮询;如果是使用会话保持,这个是需要加此配置的:sessionAffinity: ClientIP
⚠:如果pod服务指定了hostNetwork: true,需要加上dnsPolicy: ClusterFirstWithHostNet,否则无法解析集群 DNS,那么根据域名就找不到此服务进行负载;

  • 创建并运行svc
bash 复制代码
# 创建并运行svc
kubectl apply -f nginx-svc.yaml
# 检查svc运行是否正常
kubectl get svc -n nginx
  • 使用dns域名svc ip进行测试

注意:

使用的ClusterIP模式,仅支持k8s集群內部访问;

使用dns访问需提前安装CoreDNS,如果没有安装,可参考:K8S 部署 CoreDNS 之 DNS 域名获取

先查看后端Pod IP:Port 列表,对比ENDPOINTSpod 的ip是否一致,如果少一个、多个或没有则是Service selector 标签不匹配,或Pod未就绪问题;

bash 复制代码
kubectl get endpoints -n nginx nginx-service

进入任意一个pod,执行如下命令:

bash 复制代码
# svc ip方式
kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'curl -s http://10.0.0.6'

# 域名方式
kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'curl -s http://nginx-service.nginx.svc.cluster.local'

或可以使用脚本来循环跑一下,看看走的哪个节点的nginx

bash 复制代码
# svc ip方式
for i in {1..10}; do
  kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'curl -s http://10.0.0.6'
done

# 域名方式
for i in {1..10}; do
  kubectl exec -n nginx nginx-daemonset-5chs6 -- sh -c 'curl -s http://nginx-service.nginx.svc.cluster.local'
done

这样就可以清晰的看到请求到哪个节点上了;

2.2 NodePort 方式进行负载

适用场景: 需要从集群外部访问

  • 创建svc,vim nginx-svc.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx
spec:
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      # 端口需在30000-32767
      nodePort: 30800
  selector:
    app: nginx              # 匹配 DaemonSet 的 Pod 标签
  externalTrafficPolicy: Cluster
  # Cluster: 全集群负载均衡(可能跨节点转发)
  # Local: 仅转发到本节点 Pod(性能更好,但可能不均)

默认不写externalTrafficPolicy: Cluster,也会进行轮询,因为NodePort方式默认自带的就是Cluster轮询;如果是使用本节点转发,这个是需要加此配置的:externalTrafficPolicy: Local

  • 创建并运行svc
bash 复制代码
# 创建并运行svc
kubectl apply -f nginx-svc.yaml
# 检查svc运行是否正常
kubectl get svc -n nginx
  • 访问ip端口进行测试(页面或服务器访问测试都行)
bash 复制代码
for i in {1..10}; do
  kubectl exec -n nginx nginx-daemonset-lbx9p -- sh -c 'curl -s 172.16.11.230:30800'
done

这样就可以清晰的看到请求到哪个节点上了;

2.2.1 externalTrafficPolicy 对比
策略 流量分配 源 IP 保留 适用场景
Cluster 全集群 Pod 均匀分配 ❌ SNAT 后丢失 需要均匀负载均衡
Local 仅本节点 Pod ✅ 保留真实 IP 需要获取客户端 IP,接收可能不均

三、按 Ingress 方式进行负载

前提:需部署Ingress Controller,如果没部署的,可参考:K8s 之 Ingress 及 Ingress Controller
适用场景:

  • 基于域名/路径路由
  • 需要 SSL 终止、限流、重写等高级功能

3.1 编写 Ingress 规则

  • vi nginx-ingress.yaml
bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  namespace: nginx
spec:
  ingressClassName: nginx    # 对应你安装的 Controller
  # 比如现在安装的是nginx-ingress-controller,可以使用"kubectl get ingressclass"命令查看
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service   # 指向你的后端 Service
            port:
              number: 80		# Service 的端口

3.2 编写 nginx svc

  • vi nginx-svc.yaml
bash 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-service        # ← Ingress 里写的名字
  namespace: nginx        # ← 必须和 Ingress 同一命名空间
spec:
  selector:
    app: nginx              # ← 匹配 Deployment 的 Pod 标签
  ports:
  - port: 80                # ← Ingress 里写的端口
    targetPort: 80          # ← 容器实际端口(对应 containerPort)

3.3 创建 Ingress 规则和 svc

bash 复制代码
kubectl apply -f nginx-ingress.yaml
kubectl apply -f nginx-svc.yaml

3.4 检查 pod 和 svc是否创建成功

bash 复制代码
# 查看nginx daemonset状态
kubectl get ds -n nginx
# 查看nginx pod的状态
kubectl get pods -n nginx 
# 查看nginx service的状态
kubectl get svc -n nginx

3.5 检验是否负载成功

3.5.1 页面访问

使用节点任意IP+ingress-nginx-controller访问端口访问页面:http://172.16.11.230:32465https://172.16.11.231:32483,可以访问到This is k8s-master这种就算成功,访问不止有This is k8s-master算是负载成功;

3.5.2 脚本测试负载
bash 复制代码
# 本机测试
for i in {1..10};do curl 127.0.0.1:32465; done

# 集群任意IP访问测试
for i in {1..10};do curl 172.16.11.230:32465; done

# 集群任意IP访问测试 - https
for i in {1..10};do curl -k https://172.16.11.230:32483; done

四、LoadBalancer + 云厂商 LB

由于没有云服务器测试条件,暂无法进行测试,如果有测试过的,可分享出来,我将添加到其中,同时也感谢您的支持!!!

五、三种负载均衡方式的对比总结表

方式 访问范围 端口范围 适用场景 是否需Controller
ClusterIP 集群内部 任意 服务间调用
NodePort 外部访问 30000-32767 测试/小规模暴露
Ingress 外部访问 80/443(通过Controller) 生产环境、域名路由 是(需部署)
相关推荐
猪脚踏浪21 分钟前
linux 拷贝文件或目录到指定的位置
linux
大树8816 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠16 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质17 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush417 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52017 小时前
Linux 11 动态监控指令top
linux
Inhand陈工18 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智18 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
不会C语言的男孩18 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_18 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化