在K8s集群中部署Traefik并验证Python HTTP服务

在K8s集群中部署Traefik并验证Python HTTP服务

一、背景与目标

在个人学习Kubernetes的过程中,我希望搭建一套完整的入口流量管理方案。本文将详细记录在一个3节点的裸金属K8s集群(ubuntu-111/112/113)中,如何部署Traefik作为Ingress Controller(同时运行在ubuntu-111、ubuntu-112节点),并通过一个Python HTTP服务验证整个链路的可用性。

二、环境规划

  • K8s集群:3节点,无MetalLB,使用HAProxy作为外部负载均衡
  • Traefik版本:Helm Chart 39.1.0-ea.2(Traefik 3.x)
  • 核心目标
    1. Traefik仅调度到ubuntu-111、ubuntu-112节点(通过节点亲和性实现)
    2. 启用hostNetwork模式,直接占用节点80/443端口
    3. HAProxy代理两个Traefik节点,增加后端健康检查
    4. 部署Python HTTP服务并通过Traefik Ingress暴露

三、Traefik部署实践

1. 节点标签与亲和性配置

1.1 为多节点打标签

给ubuntu-111、ubuntu-112都打上traefik-work=true标签,作为Traefik调度的目标节点:

# 给ubuntu-111打标签 kubectl label nodes ubuntu-111 traefik-work=true # 给ubuntu-112打标签 kubectl label nodes ubuntu-112 traefik-work=true # 验证标签是否添加成功 kubectl get nodes ubuntu-111 ubuntu-112 --show-labels |grep traefik-work 
1.2 多节点亲和性配置

在Traefik的values.yaml中,配置节点亲和性匹配两个打标签的节点,同时设置Pod反亲和性避免同一节点运行多个Traefik实例:

affinity:# 节点亲和性:匹配traefik-work=true的节点(ubuntu-111/112)nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key: traefik-work operator: In values:-"true"# 必须是字符串类型,避免JSON解析错误# Pod反亲和性:避免同一节点运行多个Traefik PodpodAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:-labelSelector:matchLabels:app.kubernetes.io/name: traefik topologyKey: kubernetes.io/hostname # hostNetwork配置(直接使用节点网络)hostNetwork:truedeployment:replicas:2# 副本数与目标节点数一致(2个)pod:securityContext:capabilities:add:- NET_BIND_SERVICE # 允许绑定80/443端口runAsUser:0# 端口配置(绑定节点80/443)ports:web:port:80hostPort:80websecure:port:443hostPort:443

2. 使用Helm部署Traefik

将上述配置写入traefik-values.yaml,执行以下命令完成部署:

# 添加Traefik Helm仓库 helm repo add traefik https://traefik.github.io/charts helm repo update # 部署Traefik(指定Chart版本,使用自定义配置) helm install traefik traefik/traefik \ --namespace kube-system \ --create-namespace \ --version 39.1.0-ea.2 \ -f traefik-values.yaml # 验证Traefik Pod调度结果(应分别运行在ubuntu-111/112) kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik -o wide 

3. HAProxy配置(多节点代理+健康检查)

3.1 完整HAProxy配置文件

修改HAProxy配置,代理两个Traefik节点的80/443端口,并增加TCP层健康检查(验证Traefik服务可用性):

#!/bin/bashset -euo pipefail # 基础配置HAPROXY_NODE_IP="192.168.56.102"# HAProxy所在节点IPMASTER_NODES=("192.168.56.111""192.168.56.112""192.168.56.113")K8S_API_PORT=6443HAPROXY_PORT=6443# Traefik配置(代理ubuntu-111/112的80/443端口)TRAEFIK_NODES=("192.168.56.111""192.168.56.112")# Traefik运行节点TRAEFIK_HTTP_PORT=80TRAEFIK_HTTPS_PORT=443# 安装haproxyapt update -y &&aptinstall -y haproxy net-tools ||truemv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak$(date +%Y%m%d%H%M%S)||true# 生成haproxy.cfgcat> /etc/haproxy/haproxy.cfg <<EOF global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s user haproxy group haproxy daemon maxconn 2000 defaults log global mode tcp option tcplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http # K8s apiserver代理(原有配置) frontend k8s-api-frontend bind ${HAPROXY_NODE_IP}:${HAPROXY_PORT} default_backend k8s-api-backend backend k8s-api-backend mode tcp balance roundrobin option tcp-check EOF# 添加master节点到apiserver backendformasterin"${MASTER_NODES[@]}";docat>> /etc/haproxy/haproxy.cfg <<EOF server master-${master//./-}${master}:${K8S_API_PORT} check inter 2000 fall 3 rise 2 EOFdone# Traefik HTTP代理(多节点+健康检查)cat>> /etc/haproxy/haproxy.cfg <<EOF # Traefik HTTP代理(hostNetwork模式) frontend traefik-http-frontend bind ${HAPROXY_NODE_IP}:${TRAEFIK_HTTP_PORT} default_backend traefik-http-backend backend traefik-http-backend mode tcp balance roundrobin # TCP健康检查:验证后端80端口是否可连接 option tcp-check tcp-check connect port ${TRAEFIK_HTTP_PORT} tcp-check send GET /ping HTTP/1.1\r\nHost: localhost\r\n\r\n tcp-check expect string 200 OK EOF# 添加两个Traefik节点到HTTP backend(带健康检查)fornodein"${TRAEFIK_NODES[@]}";docat>> /etc/haproxy/haproxy.cfg <<EOF server traefik-node-${node//./-}-http ${node}:${TRAEFIK_HTTP_PORT} check inter 2000 fall 3 rise 2 timeout connect 3s EOFdone# Traefik HTTPS代理(多节点+健康检查)cat>> /etc/haproxy/haproxy.cfg <<EOF # Traefik HTTPS代理(hostNetwork模式) frontend traefik-https-frontend bind ${HAPROXY_NODE_IP}:${TRAEFIK_HTTPS_PORT} default_backend traefik-https-backend backend traefik-https-backend mode tcp balance roundrobin # TCP健康检查:验证后端443端口是否可连接 option tcp-check tcp-check connect port ${TRAEFIK_HTTPS_PORT} EOF# 添加两个Traefik节点到HTTPS backend(带健康检查)fornodein"${TRAEFIK_NODES[@]}";docat>> /etc/haproxy/haproxy.cfg <<EOF server traefik-node-${node//./-}-https ${node}:${TRAEFIK_HTTPS_PORT} check inter 2000 fall 3 rise 2 timeout connect 3s EOFdone# 重启haproxy并验证 systemctl daemon-reload systemctl enable --now haproxy systemctl restart haproxy # 验证HAProxy状态if systemctl is-active --quiet haproxy;thenecho -e "\033[32mHAProxy部署成功:"echo -e " - K8s API: ${HAPROXY_NODE_IP}:${HAPROXY_PORT}"echo -e " - Traefik HTTP: ${HAPROXY_NODE_IP}:${TRAEFIK_HTTP_PORT} (代理到${TRAEFIK_NODES[*]})"echo -e " - Traefik HTTPS: ${HAPROXY_NODE_IP}:${TRAEFIK_HTTPS_PORT} (代理到${TRAEFIK_NODES[*]})\033[0m"elseecho -e "\033[31mHAProxy启动失败\033[0m" systemctl status haproxy --no-pager exit1fi
3.2 健康检查关键配置说明
  • option tcp-check:启用TCP层健康检查,验证后端端口是否存活;
  • tcp-check send GET /ping HTTP/1.1\r\nHost: localhost\r\n\r\n:向Traefik的/ping接口发送请求(Traefik内置健康检查接口);
  • tcp-check expect string 200 OK:期望返回200状态码,确认Traefik服务正常;
  • check inter 2000 fall 3 rise 2:每2秒检查一次,连续3次失败标记为不可用,连续2次成功恢复可用;
  • timeout connect 3s:连接超时时间3秒,避免健康检查阻塞。
3.3 验证HAProxy健康检查
# 查看HAProxy后端状态echo"show stat"| socat /run/haproxy/admin.sock stdio |grep traefik # 查看HAProxy日志(验证健康检查结果)tail -f /var/log/haproxy.log |grep traefik 

四、hostNetwork vs NodePort:差异与优劣对比

特性hostNetwork模式NodePort模式
网络模型Pod直接使用节点的网络命名空间,监听节点IP和端口。Service在节点上打开一个端口(NodePort),流量通过kube-proxy转发到Pod。
端口占用直接占用节点的80/443等标准端口,同一节点上的多个Pod不能监听同一端口。使用30000-32767范围内的端口,避免与主机服务冲突。
性能性能最优,无额外的NAT和转发开销。存在kube-proxy的转发开销,性能略低。
隔离性差,Pod可以看到节点上的所有网络接口和连接。好,Pod的网络栈与节点隔离。
高可用需要通过Pod反亲和性确保每个节点只运行一个Pod,配合HAProxy健康检查实现高可用。自动负载均衡到所有节点的NodePort,高可用更简单,但依赖kube-proxy。
适用场景对性能要求极高的Ingress Controller、网络插件等。通用的服务暴露方式,适合大多数应用。

五、Python HTTP服务部署

1. 服务代码(新增容器信息获取)

from http.server import BaseHTTPRequestHandler, HTTPServer import os, socket, json classHandler(BaseHTTPRequestHandler):defdo_GET(self): self.send_response(200) self.send_header('Content-type','text/html; charset=utf-8') self.end_headers()# 获取容器与Pod元数据 pod_name = os.getenv("POD_NAME", socket.gethostname()) node_name = os.getenv("NODE_NAME","unknown-node") app_info ={"app":"python-http-server","container": os.getenv("CONTAINER_NAME","python-http-server")} response =f""" <h1>✅ Python HTTP Server</h1> <p>Pod: {pod_name}</p> <p>Node: {node_name}</p> <p>App Info: {json.dumps(app_info, indent=2)}</p> """ self.wfile.write(response.encode('utf-8'))defrun(server_class=HTTPServer, handler_class=Handler, port=8080): server_address =('0.0.0.0', port) httpd = server_class(server_address, handler_class)print(f"🚀 Python HTTP服务器启动: 0.0.0.0:{port}")try: httpd.serve_forever()except KeyboardInterrupt: httpd.server_close()print("🛑 服务器已停止")if __name__ =='__main__': run()

2. K8s资源配置

apiVersion: apps/v1 kind: Deployment metadata:name: python-http-server namespace: default spec:replicas:2selector:matchLabels:app: python-http-server template:metadata:labels:app: python-http-server spec:containers:-name: python-http-server image: 192.168.56.102/library/python-http-server:v1 ports:-containerPort:8080name: http env:-name: NODE_NAME valueFrom:fieldRef:fieldPath: spec.nodeName -name: POD_NAME valueFrom:fieldRef:fieldPath: metadata.name -name: CONTAINER_NAME value:"python-http-server"---apiVersion: v1 kind: Service metadata:name: python-http-server namespace: default spec:selector:app: python-http-server ports:-port:80targetPort:8080protocol: TCP name: http type: ClusterIP ---apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: python-http-ingress namespace: default annotations:kubernetes.io/ingress.class:"traefik"spec:rules:-host: python-http.example.com http:paths:-path: / pathType: Prefix backend:service:name: python-http-server port:number:80

六、整体验证流程

1. 验证Traefik调度

kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik -o wide # 预期结果:两个Traefik Pod分别运行在ubuntu-111、ubuntu-112

2. 验证HAProxy健康检查

# 查看Traefik后端状态(STATUS列为UP表示正常)echo"show stat"| socat /run/haproxy/admin.sock stdio |grep traefik |awk'{print $1,$2,$18}'

3. 验证Python服务访问

# 配置本地hostsecho"192.168.56.102 python-http.example.com">> /etc/hosts # 多次访问验证负载均衡(会轮询到两个Traefik节点)curl http://python-http.example.com curl http://python-http.example.com 

4. 故障模拟验证

# 停止ubuntu-111上的Traefik Pod kubectl delete pod -n kube-system $(kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik -o name |grep ubuntu-111 |cut -d/ -f2)# 查看HAProxy后端状态(ubuntu-111节点会被标记为DOWN,流量自动切换到ubuntu-112)echo"show stat"| socat /run/haproxy/admin.sock stdio |grep traefik 

七、总结

本次实践完成了Traefik在多节点(ubuntu-111/112)的部署,通过节点标签和亲和性实现精准调度,配合HAProxy的多节点代理和健康检查,保障了入口流量的高可用。对比hostNetwork和NodePort模式,清晰体现了不同网络模式的优劣,也验证了Python HTTP服务通过Traefik Ingress暴露的完整链路,为K8s流量管理的学习打下了坚实基础。

Read more

算法王冠上的明珠——动态规划之斐波那契数列问题

算法王冠上的明珠——动态规划之斐波那契数列问题

目录 1. 什么是动态规划 2. 动态规划步骤 状态表示 状态转移方程 初始化 填表顺序 返回值 3. 例题讲解及具体代码 3.1 LeetCode1137. 第 N 个泰波那契数 这篇文章是我第一篇关于动态规划的,所以我会先从什么是动态规划说起。 1. 什么是动态规划 动态规划是一种通过将复杂问题分解为重叠子问题,并利用子问题的解来高效求解原问题的算法思想。它的核心是避免重复计算,通过存储中间结果(即 “记忆化”)来优化时间复杂度。 其实简单来说就是通过前面的状态来定义后面的状态,比如说我们前面关于前缀和的文章其实就可以被归为动态规划的一种,只不过它比较简单,所以我把它放在了基础算法里面。 2. 动态规划步骤 做动态规划类题目的步骤就是下面这几步。 状态表示 状态表示就是我们数组对应的那个位置的值的含义,简单来说就是那个值代表着什么。比如说我们前面说的前缀和,那他的状态表示就是代表着原数组前面这些数的累加。 状态转移方程 状态转移方程就是根据上面的状态表示来得到的一个公式,比如说我们前面说的前缀和,它的状态转移方程就是dp[i]=dp[i

By Ne0inhk

优选算法——二分查找

👇作者其它专栏 《数据结构与算法》《算法》《C++起始之路》 二分查找相关题解 1.二分查找 算法思路: a.定义left,right指针,分别指向数组的左右区间。 b.找到待查找区间的中间点mid,找到后分三种情况讨论:         i.arr[mid]==target说明正好找到,返回mid的值;         ii.arr[mid]>target说明[mid,right]这段区间都是大于target的,因此舍去右边区间,在左边[left,mid-1]的区间继续查找,即让right=mid-1,然后重复b过程;         iii.arr[mid]<target说明[left,mid]这段区间的值都是小于target的,因此舍去左边区间,在右边区间[mid+1,right]

By Ne0inhk
【2025 最新】 Python 安装教程 以及 Pycharm 安装教程(超详细图文指南,附常见问题解决)

【2025 最新】 Python 安装教程 以及 Pycharm 安装教程(超详细图文指南,附常见问题解决)

前言         Python 作为目前最热门的编程语言之一,在数据分析、人工智能、Web 开发等领域应用广泛。而 PyCharm 作为 JetBrains 推出的 Python 集成开发环境(IDE),以其强大的功能和友好的界面成为开发者的首选工具。         本文针对 2025 年最新版 Python(3.13.x)和 PyCharm(202x.x.x),提供Windows 10或11和macOS Sonoma双系统安装教程,从官网下载到环境配置一步到位,同时整理了安装过程中最常见的 10 类问题及解决方案,确保新手也能顺利完成环境搭建。 一、Python 安装教程(2025 最新版) 1. 下载 Python 安装包 步骤 1:访问 Python 官网

By Ne0inhk
【Python✨】Conda 虚拟环境 & 安装包路径修改:告别 C 盘占用,3 步轻松配置

【Python✨】Conda 虚拟环境 & 安装包路径修改:告别 C 盘占用,3 步轻松配置

在使用 Anaconda 或 Miniconda 时,默认的虚拟环境路径(envs)和安装包缓存路径(pkgs)常位于系统盘(如 C 盘),长期使用易占用过多空间。本文将详细介绍如何修改这两个路径,解决空间不足、权限冲突等问题,适用于 Windows、Linux、macOS 系统。 一、核心概念说明 在修改前,先明确两个关键路径的作用: 路径类型默认位置(以 Windows 为例)作用虚拟环境路径(envs_dirs)C:\Users\用户名\.conda\envs 或 Anaconda安装目录\envs存储通过 conda create 创建的虚拟环境(如 km3.8、glm3)安装包缓存路径(pkgs_

By Ne0inhk