如何在不使用LoadBalancer与Ingress Controller的情况下将域名指向裸金属Kubernetes集群的所有工作节点
嘿,我来给你捋清楚这个事儿。既然你用的是裸金属K8s集群,又不想用LoadBalancer或者Ingress Controller,那核心就是搞定DNS解析到所有工作节点,再保证应用能在每个节点上被访问到这两件事。下面一步步来:
一、先把DNS配置好,让域名指向所有工作节点IP
要让域名能解析到集群里的每一个工作节点,你需要给域名添加多条A记录(IPv6的话用AAAA记录),每条对应一个工作节点的可访问IP(不管是公网还是内网IP,只要用户能连到就行)。
如果你的域名托管在第三方DNS服务商(比如Cloudflare、阿里云DNS这些),直接去后台操作:
比如你的域名是myapp.example.com,工作节点IP是192.168.1.10、192.168.1.11、192.168.1.12,那就添加三条A记录,每条都是myapp.example.com对应一个节点IP。大部分服务商都支持这种“多值A记录”,解析的时候会轮着返回不同的节点IP,相当于做了个简单的负载均衡。如果用的是自己的内部DNS服务器(比如Bind),直接在区域配置文件里加这几行:
myapp.example.com. IN A 192.168.1.10 myapp.example.com. IN A 192.168.1.11 myapp.example.com. IN A 192.168.1.12保存完重启DNS服务就生效了。
二、确保应用能在每个工作节点上被访问到
现在域名能解析到节点了,但还得让应用在每个节点上都能被访问到,这里有两种常用的方法:
方法1:用NodePort Service(推荐)
NodePort Service会在集群的每一个节点上开放一个固定端口,自动把流量转发到后端的Pod,而且不用担心端口冲突的问题(K8s会帮你管理端口范围)。
- 先写一个NodePort Service的YAML文件,比如
myapp-service.yaml:apiVersion: v1 kind: Service metadata: name: myapp-service spec: type: NodePort selector: app: myapp # 这里要和你的Pod标签对应上,不然找不到后端Pod ports: - protocol: TCP port: 80 # Service内部的端口,集群内其他服务用这个访问 targetPort: 8080 # 你的Pod实际监听的端口 nodePort: 30007 # 可选,指定节点上的端口,范围是30000-32767;不写的话K8s会自动分配一个 - 然后应用这个配置:
kubectl apply -f myapp-service.yaml - 这时候你用
http://<任意节点IP>:30007就能访问应用了,结合前面的DNS配置,用户访问myapp.example.com:30007就会被DNS轮询分配到不同的节点IP,从而访问到你的应用。
方法2:直接在Pod上用HostPort绑定节点端口
如果不想用Service,也可以直接在Pod的容器端口里指定hostPort,让Pod直接占用节点上的某个端口。
比如写一个Pod的YAML:
apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: containers: - name: myapp-container image: myapp-image:latest ports: - containerPort: 8080 hostPort: 8080 # 直接绑定节点的8080端口 protocol: TCP
注意哈,这种方式有个小限制:同一个节点上不能有两个Pod绑定同一个hostPort,所以如果要部署多个Pod副本,要么让它们调度到不同节点,要么给每个Pod分配不同的hostPort。另外,要注意别和节点上其他服务的端口冲突了。
三、可选:给DNS加健康检查(提升可靠性)
如果你的DNS服务商支持(比如Cloudflare的健康检查功能),可以给每个节点IP配置健康检查,这样如果某个节点挂了,DNS就不会把流量分配过去,能提升服务的可用性。不过这不是必须的,看你的需求来。
总结一下
整个流程就是:
- 给域名加多条A记录,指向所有工作节点IP;
- 用NodePort Service或者HostPort让应用在每个节点上都能被访问;
- 用户通过
域名:端口就能访问应用,流量会被DNS轮着分配到不同节点。
内容的提问来源于stack exchange,提问作者joe1531

