Kubernetes 里的 API Server,大家最熟的端口大概率是 6443,所有kubectl请求、控制器交互、调度器心跳,默认都走这个 HTTPS 安全端口。但如果你维护过老版本集群,或者翻过早期资料,一定见过另一个端口——8080,也就是官方文档里叫“非安全端口”的东西。它本质上是 API Server 早期提供的 HTTP 明文监听口,不需要任何证书、Token、RBAC 校验,只要能连上端口就等于拿到集群管理权限。在 Kubernetes 1.20 之前,这个端口还可以通过启动参数开起来,之后逐步被官方废弃并移除。
这篇文章适合三类人:还在维护 1.19 及更早版本集群的运维同学,因为业务需要临时给内部工具开放 HTTP API 的工程师,以及纯粹好奇“为什么 Kubernetes 要留一个这么危险的端口”的人。我会把 8080 端口的来历、开启方式、参数含义、验证手段和常见坑一次讲完。先提醒一句:非安全端口不是 production 该用的东西,但很多时候开发环境或者内网工具确实需要它,这不算什么“奇技淫巧”,而是每一个 K8s 运维都可能面对的实操场景。
1. 端口机制与 8080 的定位
1.1 API Server 的“双端口”设计
Kubernetes 的 API Server(kube-apiserver)在早期版本里不是只监听一个端口,而是同时监听两个:一个是安全端口,默认 6443,走 TLS 加密,所有身份认证都在这一层完成;另一个就是非安全端口,默认 8080,直接 HTTP 明文,没有任何认证拦截。你可以把安全端口理解成银行柜台,取号排队、核对身份证、人脸识别齐全;非安全端口则更像自助存取款机背后的维护接口,理论上只有系统维护人员知道,但一旦暴露,谁都能操作。
这两个端口在代码层面有明确分工。安全端口走的是完整的认证链:x509 Client Cert、Token、Basic Auth、Webhook 等,然后再进入授权模块(RBAC、ABAC),最后才触达资源处理器。非安全端口则直接跳过认证和授权两个环节,只绑定到指定的 IP 和端口上,收到请求就执行。这种设计在 K8s 早期是有意为之的——当时 Kubernetes 刚开源,很多内部组件需要通过 HTTP 直接访问 API,省去证书配置的复杂度,让整个系统更容易跑起来。
1.2 非安全端口为什么被默认禁用
现在看这个设计,你可能会觉得“这不是给自己埋雷吗”,事实也确实如此。随着 Kubernetes 从内部调度系统演变成支撑线上业务的核心基础设施,非安全端口的风险越来越明显:第一,它没有认证,任何能访问到该端口的人都可以读取集群全部信息,甚至执行破坏性操作;第二,它走明文 HTTP,如果网络链路不可信,等于把集群的 API 请求裸奔在网络上;第三,如果绑定的地址是 0.0.0.0 或公网 IP,那基本就是把集群管理权限放在互联网上任人摆弄。
所以官方在后续版本中步步收紧:先是在发行版里把非安全默认绑定地址从 0.0.0.0 改成 127.0.0.1,让端口只对本地可见;后来又改成默认完全不监听;到 1.20 版本正式标记为弃用(Deprecated),并在 1.24 中彻底移除了相关启动参数。从我的角度看,这是 Kubernetes 走向成熟必经的一步——早期为了易用性妥协安全,后期再逐步把网关收紧。
1.3 版本演变:从可用到移除
如果你在网络上搜索 8080 端口的资料,会看到很多互相矛盾的说法,根源就是版本差异。我在这里整理一下时间线:
| Kubernetes 版本 | 8080 非安全端口状态 | 主要变化 |
|---|---|---|
| 1.10 及更早 | 默认绑定 127.0.0.1:8080 | 本地访问基本可用 |
| 1.11 ~ 1.19 | 默认不开启,可通过启动参数开启 | 裸奔风险被重视 |
| 1.20 | 标记为弃用(Deprecated) | 官方明确计划移除 |
| 1.24 及以后 | 移除--insecure-port参数 | 无法再通过启动参数开启 |
这个演变过程对实际运维非常重要。你如果手头是 1.20 之前的集群,按本文方法可以正常开启;如果是 1.24 之后的新集群,就别再折腾这个参数了,后面我会讲替代方案。
2. 开启 8080 的三种典型路径
2.1 二进制部署:直接改启动参数
二进制部署是很多自建集群的选择,kube-apiserver 进程由 systemd 或脚本管理。开启 8080 端口的核心参数就两个:
--insecure-port=8080:指定非安全端口号,改端口就改这个值。--insecure-bind-address=0.0.0.0:指定非安全端口监听在哪个地址上,0.0.0.0 表示监听所有网卡,127.0.0.1 表示只监听本机回环。
在 systemd 场景下,需要修改 service 文件中的启动参数,比如常见的/etc/kubernetes/kube-apiserver.service或者/etc/systemd/system/kube-apiserver.service,在ExecStart行添加上面的参数,然后systemctl daemon-reload再重启 kube-apiserver 服务:
systemctl daemon-reload systemctl restart kube-apiserver这里要注意一个细节:如果你同时使用 kubeadm 部署的静态 Pod 方式,就没有 systemd 服务文件可改,需要走下面说的静态 Pod 方案。
2.2 kubeadm 部署:修改静态 Pod 清单
kubeadm 部署的 kube-apiserver 是 static pod,清单文件固定放在/etc/kubernetes/manifests/kube-apiserver.yaml。要开启 8080,需要在这个文件的spec.containers[].command数组里加上两个参数:
spec: containers: - command: - kube-apiserver - --insecure-port=8080 - --insecure-bind-address=127.0.0.1改完后由 kubelet 监听该目录并自动重建 Pod。但这种情况有个常见坑:如果--insecure-bind-address你刻意设成节点 IP 或 0.0.0.0,而节点上有防火墙或安全组策略,外部访问会被挡住,本地curl却一切正常,排查时容易被绕进去。
2.3 环境变量与配置文件的优先级
部分部署方式会把 kube-apiserver 的参数放在环境变量或配置文件中,典型的如/etc/kubernetes/apiserver文件里的KUBE_API_ARGS变量。如果你在部署脚本里看到类似KUBE_API_ARGS="--insecure-port=8080"的写法,也要注意参数重复的情况。比如启动脚本里原本已经写了--insecure-port=8080,配置文件又写了一个,kube-apiserver 启动时会以最后一个参数为准,不同部署方式的行为可能不一致,排查起来很头疼。
我的建议是:无论哪种部署方式,开启后都先看监听状态,确认实际生效的端口、地址和参数值,再去做下一步验证。
3. 实操:从修改配置到验证连通
3.1 准备工作与参数核对
在动手之前,先确认两件事:集群版本在 1.20 以下,以及你清楚这个端口暴露后对集群安全的影响。然后登录到运行 kube-apiserver 的节点(一般是 master/control-plane 节点),检查当前启用的参数:
ps -ef | grep kube-apiserver | grep -v grep看输出里有没有--insecure-port,如果已经是 8080 但没生效,就要检查监听地址是否对。我遇到过一种情况:参数确实加了,但--insecure-bind-address被设置成了节点自身的某个内网 IP,而 eth0 恰好在监听 IP 变更后没刷新,导致端口实际没有落在预期网卡上。
3.2 修改 API Server 启动参数的完整步骤
这里以 kubeadm 部署的 1.18 集群为例,走一遍完整流程。
第一步,备份清单文件:
cp /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.bak第二步,编辑文件,在 command 区域添加参数:
vim /etc/kubernetes/manifests/kube-apiserver.yaml找到类似下面的片段:
spec: containers: - command: - kube-apiserver - --advertise-address=192.168.1.10 - --allow-privileged=true添加两行:
- --insecure-port=8080 - --insecure-bind-address=0.0.0.0保存退出后,kubelet 会自动检测清单变更并重建 Pod。可以执行:
watch -n 1 kubectl get pods -n kube-system -o wide | grep kube-apiserver看到 Pod 状态从 Running 变成 ContainerCreating 再回到 Running,就说明重建完成。
3.3 验证与客户端连接配置
重建后,在节点上先用基础命令确认端口监听:
ss -tlnp | grep 8080如果看到0.0.0.0:8080被 kube-apiserver 进程监听,说明参数生效。接着用 curl 直接验证 HTTP 接口:
curl http://127.0.0.1:8080/version如果返回类似下面的 JSON:
{ "major": "1", "minor": "18", "gitVersion": "v1.18.20" }说明非安全端口工作正常。此时你还可以用 HTTP 方式调用 RESTful API,比如:
curl http://127.0.0.1:8080/api/v1/namespaces如果返回 namespace 列表,说明整个 API 响应链路没问题。客户端如果用 kubectl,可以指定 server 地址来测试:
kubectl --server=http://127.0.0.1:8080 get nodes正常情况下,这个命令不需要任何 kubeconfig 就能直接访问集群。这也是 8080 被人又爱又恨的原因——排查问题方便,但安全问题也直接。
3.4 防火墙和安全组的配套调整
如果你的需求是让集群外部的某个工具访问 8080,那光改 kube-apiserver 还不够。节点上的 iptables/firewalld 以及云平台安全组都要同步放行。
以 CentOS 节点为例,放行端口:
firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload如果你用的是云主机,还要检查对应安全组规则是否允许源 IP 访问 8080。我建议这里做一个缩小范围的访问控制,比如只允许公司某个固定出口 IP 访问,而不是直接对 0.0.0.0/0 放行。这一点下面我会详细说。
4. 常见问题与排查技巧实录
4.1 开启后端口不监听,参数没生效怎么办
这是最常见的坑。参数加了、Pod 也重启了,但ss -tlnp | grep 8080就是没输出。我梳理了几个排查方向:
第一,看 kube-apiserver 容器日志。静态 Pod 场景下用kubectl logs -n kube-system kube-apiserver-<节点名>,二进制部署则看 systemd 日志journalctl -u kube-apiserver -n 100。如果日志里出现unknown flag: --insecure-port,或者类似--insecure-port has been deprecated的 Warning,说明版本已经不支持这个参数。
第二,看参数是否被启动脚本“覆盖”了。有些部署工具会生成完整参数数组,你手改的文件不一定是最终生效的。比如 kubeadm 的清单文件里如果同时又挂载了额外的启动脚本,可能出现参数冲突。最稳妥的方法是直接看进程实际参数:
cat /proc/$(pgrep -f kube-apiserver | head -1)/cmdline | tr '\0' ' '这样看到的是进程真正启动用的参数,而不是你猜测的。
第三,检查端口占用。如果 8080 被其他进程占用,kube-apiserver 会启动失败或降级,表现为端口起不来。用lsof -i:8080或ss -tlnp看看是否有服务占用,有的话换一个端口,比如 18080。
4.2 可以监听但 kubectl 无法访问,权限或网络问题怎么查
端口已经监听,本地 curl 正常,但客户端从外部访问失败,这通常有三种情况。
第一种是防火墙/安全组阻断了访问。在控制节点上用telnet <目标IP> 8080或者nc -vz <目标IP> 8080,如果连接超时或者被拒绝,基本可以断定是网络层的问题。
第二种是--insecure-bind-address绑定地址不对。如果你只填写了127.0.0.1,那外部自然无法访问。特别注意,有些部署模板默认会带--insecure-bind-address=127.0.0.1,你需要在清单文件里显式改成0.0.0.0或指定网卡 IP。
第三种是客户端使用了 HTTPS 访问 HTTP 端口。比如在 kubeconfig 里把 server 地址写成了https://192.168.1.10:8080,协议对不上自然失败。8080 是 HTTP 明文端口,客户端配置必须使用http://前缀。同理,你用 curl 验证时也别写https。
4.3 高版本 K8s 已不支持,替代方案有哪些
如果你用的是 1.24 或更高版本的集群,--insecure-port已经不存在,强行加到启动参数里只会让 kube-apiserver 启动失败。这时候如果你仍然需要通过 HTTP 方式访问 API,我通常建议三个替代方案。
第一个是kubectl proxy。它会在本地启动一个代理端口,把 HTTP 请求转发给 API Server,并且自动注入本地 kubeconfig 的认证信息:
kubectl proxy --port=8080然后curl http://127.0.0.1:8080/api/v1/namespaces就能访问,无需证书。缺点是它只在本地监听,不会被杀进程,适合开发调试。
第二个是kubectl port-forward,但它更常用于访问 Pod 端口,和 API Server 本身的 HTTP 接口场景不太匹配。
第三个是我自己比较推崇的方式:如果你确实需要一个内部服务通过 HTTP 方式访问集群 API,可以在集群内部部署一个反向代理或者 sidecar,终结 TLS 并做认证转发,而不是直接开明文端口。虽然多了点工作量,但至少不会把安全底线彻底放开。
4.4 开启后的安全风险自检与监控建议
既然我们已经把 8080 端口打开了,就要建立配套的监控和防护意识,不能放飞自我。我的实操建议是:
- 绑定地址优先选 127.0.0.1,不要一上来就写 0.0.0.0。大多数场景下,与 API Server 交互的都是同一控制节点上的组件或运维人员,回环地址完全够用。
- 如果确实需要跨节点访问,用防火墙做来源 IP 白名单。比如只允许跳板机的 IP 访问 8080 端口,而不是放行整个网段。
- 开启审计日志。Kubernetes 的审计功能能记录所有到达 API Server 的请求,包括非安全端口。你可以单独为 8080 口的请求增加审计规则,一旦出现异常调用,日志里能马上看到。
- 日常巡检时注意端口状态变化。如果发现 8080 意外开放,优先怀疑是否有人篡改了静态 Pod 清单或者启动脚本,而不是简单重启服务了事。
我在实际操作中的体会是,非安全端口就像一个应急通道,平时不用的时候锁死,真要用了也要加好门禁和摄像头。Kubernetes 从允许到禁用这个端口,走了一段很长的安全演进路线,我们做运维的应该跟上这个节奏,而不是守着旧习惯不放。
最后再分享一个细节:如果你只是临时调试,开完 8080 用完之后记得改回去。我见过不止一次,有人长时间挂着--insecure-port=8080在测试环境,结果其他人扫端口扫到了,顺手就把集群里的部署删了。这个教训不是技术问题,而是流程管理问题,改配置之前先评估清楚,改完之后记得回收。