一.实施背景
现有环境的k8s集群的ingress控制器,原来使用的是nginx-ingress,现在想替换为traefik ingress,以下是实施步骤
二.实施步骤
1.首先梳理现有 Nginx-Ingress 的关键信息,避免冲突
# 查看 Nginx-Ingress 的命名空间、Ingress Class、端口
kubectl get ingressclasses # 查看集群内的 IngressClass(K8s 1.18+ 支持,1.15 需看注解)
kubectl get pods -A -l app=nginx-ingress # 查看 Nginx Pod 所在命名空间
kubectl get svc -A -l app=nginx-ingress # 查看 Nginx 暴露的端口(如 NodePort: 30080/30443 或 HostPort 80/443)
2.部署traefik
-
创建命名空间
kubectl create namespace traefik
-
traefik依赖的RBAC 权限配置
Traefik 需要访问 K8s API 来监听 Ingress、Service 等资源,创建 traefik-rbac.yaml
# traefik-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: traefik
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
- ingressclasses # K8s 1.20 新增
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: traefik
- 创建traefik的ds
DaemonSet 模式可让 Traefik 运行在每个节点,通过 HostPort 暴露 80/443 端口(如果nginx-ingress已经使用这些端口,修改进行替换其他端口),适合生产环境。创建 traefik-daemonset.yaml
# traefik-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: traefik
namespace: traefik
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
hostNetwork: true # 主机网络,便于后续端口切换
containers:
- name: traefik
image: traefik:v2.9.10 # 适配 K8s 1.20 的稳定版本
args:
- --api.insecure=true # 测试阶段开启仪表盘(生产关闭)
- --accesslog=true
- --entrypoints.web.address=:8080 # 非冲突 HTTP 端口
- --entrypoints.websecure.address=:8443 # 非冲突 HTTPS 端口
- --kubernetesIngress=true
- --kubernetesIngress.ingressClass=traefik # 绑定 IngressClass
- --providers.kubernetesCRD=false # 暂不启用 CRD,仅用 Ingress
- --providers.kubernetesIngress=true
ports:
- name: web
containerPort: 8080
hostPort: 8080 # 主机端口(非冲突)
- name: websecure
containerPort: 8443
hostPort: 8443 # 主机端口(非冲突)
- name: dashboard
containerPort: 8081
hostPort: 8081 # 仪表盘端口
securityContext:
capabilities:
drop: [ALL]
add: [NET_BIND_SERVICE]
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 100m
memory: 64Mi
livenessProbe:
httpGet:
path: /ping
port: 8081
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ping
port: 8081
initialDelaySeconds: 5
periodSeconds: 5
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
---
# Traefik 仪表盘 Service(测试用)
apiVersion: v1
kind: Service
metadata:
name: traefik-dashboard
namespace: traefik
spec:
selector:
app: traefik
ports:
- name: dashboard
port: 8081
targetPort: 8081
nodePort: 30801
type: NodePort
kubectl apply -f traefik.yaml
-
验证部署
kubectl get pods -n traefik
输出示例(每个节点一个 Pod):
traefik-ingress-controller-7f557 1/1 Running 0 5m
在任意节点执行
netstat -tulpn | grep 80
应看到 traefik 进程监听 80/443/8080 端口
-
创建 Traefik IngressClass(K8s 1.20 原生)
traefik-ingressclass.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: traefik
annotations:
ingressclass.kubernetes.io/is-default-class: "false" # 非默认,避免抢占流量
spec:
controller: traefik.containo.us/ingress-controller # Traefik 2.x 标识 -
全量迁移 Ingress
单Ingress 修改(少量),前期测试
kubectl edit ingress <ingress-name> -n <namespace>
# 修改 spec.ingressClassName 为 traefik(替换原 nginx)
批量修改(大量 Ingress)
# 批量更新 default 命名空间所有 Ingress 的 ingressClassName
kubectl get ingress -n default -o name | xargs -I {} kubectl patch {} -n default --type='json' -p='[{"op": "replace", "path": "/spec/ingressClassName", "value":"traefik"}]'
# 跨命名空间批量更新(需 jq)
for ns in $(kubectl get ns -o json | jq -r '.items[].metadata.name'); do
kubectl get ingress -n $ns -o name 2>/dev/null | xargs -I {} kubectl patch {} -n $ns --type='json' -p='[{"op": "replace", "path": "/spec/ingressClassName", "value":"traefik"}]' 2>/dev/null
done
-
待全量迁移完成后,将 Traefik 设为默认控制器,新创建的 Ingress 会自动使用 Traefik
编辑 Traefik IngressClass,添加默认注解
kubectl edit ingressclass traefik
metadata:
annotations:
ingressclass.kubernetes.io/is-default-class: "true" # 设为默认同时将 Nginx IngressClass 的该注解改为 "false"
kubectl edit ingressclass nginx
metadata:
annotations:
ingressclass.kubernetes.io/is-default-class: "false" -
下线 Nginx-Ingress(可选)
待 Traefik 稳定运行 24-72 小时后,逐步下线 Nginx-Ingress
# 缩容 Nginx DaemonSet/Deployment 为 0
kubectl scale daemonset nginx-ingress-controller -n ingress-nginx --replicas=0
# 或 Deployment 模式:
kubectl scale deployment nginx-ingress-controller -n ingress-nginx --replicas=0
#完全删除
# 删除 Nginx-Ingress 相关资源
kubectl delete ns ingress-nginx
kubectl delete ingressclass nginx
kubectl delete clusterrole nginx-ingress-clusterrole
kubectl delete clusterrolebinding nginx-ingress-clusterrolebinding
-
回退(紧急情况)
1. 批量恢复 IngressClassName 为 nginx
for ns in (kubectl get ns -o json | jq -r '.items[].metadata.name'); do kubectl get ingress -n ns -o name 2>/dev/null | xargs -I {} kubectl patch {} -n $ns --type='json' -p='[{"op": "replace", "path": "/spec/ingressClassName", "value":"nginx"}]' 2>/dev/null
done2. 恢复 Nginx 副本数
kubectl scale daemonset nginx-ingress-controller -n ingress-nginx --replicas=3
3. 临时切回 Nginx 端口(按节点恢复 HostPort/LoadBalancer)