K8s进阶之外部访问Pod的几种方式
笔记哥 /
05-17 /
35点赞 /
0评论 /
612阅读
## 概述
K8s集群内部的Pod默认是不对外提供访问,只能在集群内部进行访问。这样做是为什么呢?
- 安全性考虑
Kubernetes设计时遵循最小权限原则,即组件仅获得完成其任务所需的最少权限。直接暴露Pod给外部网络可能会引入安全隐患,比如让攻击者更容易定位和攻击运行在Pod内的服务。通过限制Pod的直接访问,Kubernetes鼓励使用更安全的服务暴露机制。
- 可管理性和弹性
Kubernetes设计鼓励使用Service来抽象Pod的访问。Service为一组具有相同功能的Pod提供一个稳定的服务访问入口,并且可以实现负载均衡。即使Pod因为故障重建或扩展,Service依然能够透明地路由流量到新的或现有的Pod实例,从而保证服务的高可用性和弹性。
外部要访问集群内部的Pod常用的有以下几种方式:
- hostNetwork:直接使用宿主机网络的方式
- HostPort:在 Pod 定义中直接将容器端口映射到宿主机端口,绕过 Service 层,外部可通过 `节点 IP + HostPort` 直接访问 Pod。
- port-forward:用于在本地计算机和集群内运行的Pod之间建立临时的网络连接,实现端口转发。通常用于开发或者测试
- service:通过service的nodePort来进行访问
- ingress:通过ingress来进行访问,类似nginx
## HostNetwork方式
这种方式通常用于开发、测试环境,不推荐生产环境使用。
直接使用宿主机网络的方式,使用方式如下:
`hostNetwork ` 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
使用hostNetwork方式不要使用deploy部署的方式,这样会导致所有的Pod的端口都被占用
推荐使用Pod部署的方式
示例:
```csharp
# 定义deploy文件
[root@master01 ~/deploy]# cat deploy-tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-tomcat
namespace: default
spec:
# 定义更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 10
selector:
matchLabels:
app: tomcat
template:
metadata:
name: pod-tomcat
labels:
app: tomcat
spec:
# 使用hostNetwork的方式暴漏端口访问方式
hostNetwork: true
containers:
- name: container-tomcat
image: tomcat:9.0
restartPolicy: Always
# 创建
[root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
deployment.apps/deployment-tomcat created
```
#### 查看Pod的启动状态
```csharp
[root@master01 ~/deploy]# kubectl get po -o wide | grep deployment-tomcat
deployment-tomcat-577bcdbddc-5xvpl 0/1 CrashLoopBackOff 2 (27s ago) 56s 10.0.0.31 node01
deployment-tomcat-577bcdbddc-c7mbs 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.32 node02
deployment-tomcat-577bcdbddc-dn7qb 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.31 node01
deployment-tomcat-577bcdbddc-ffp4f 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.31 node01
deployment-tomcat-577bcdbddc-fpsb5 1/1 Running 0 56s 10.0.0.31 node01
deployment-tomcat-577bcdbddc-gj9wg 1/1 Running 0 56s 10.0.0.32 node02
deployment-tomcat-577bcdbddc-jnvg5 0/1 CrashLoopBackOff 2 (27s ago) 56s 10.0.0.32 node02
deployment-tomcat-577bcdbddc-qsxhj 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.32 node02
deployment-tomcat-577bcdbddc-swts5 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.31 node01
deployment-tomcat-577bcdbddc-x6lb2 0/1 CrashLoopBackOff 2 (21s ago) 56s 10.0.0.32 node02
```
这里有很多Pod未启动成功,即使启动成功了也访问不了,为什么呢?
查看一下日志,发现是对应的端口被占用了,我们上面提到过,hostNetwork是使用宿主机的网络,也会使用宿主机的端口,所以当Pod调度过去之后端口被其它的Pod占用了
那么为什么启动的Pod也访问不了呢?因为deploy部署的时候所有的Pod都是同时创建的,都去争抢宿主机的端口,这就导致谁也抢不到需要绑定的端口
```csharp
[root@master01 ~/deploy]# kubectl logs -f deployment-tomcat-577bcdbddc-qsxhj
16-May-2025 15:46:31.134 SEVERE [main] org.apache.catalina.core.StandardServer.await Failed to create server shutdown socket on address [localhost] and port [8005] (base port [8005] and offset [0])
java.net.BindException: Address already in use
at java.base/sun.nio.ch.Net.bind0(Native Method)
at java.base/sun.nio.ch.Net.bind(Net.java:565)
at java.base/sun.nio.ch.Net.bind(Net.java:554)
at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
at java.base/java.net.ServerSocket.(ServerSocket.java:278)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:537)
at org.apache.catalina.startup.Catalina.await(Catalina.java:829)
at org.apache.catalina.startup.Catalina.start(Catalina.java:777)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
```
### 使用Pod进行部署
```csharp
[root@master01 ~/pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-tomcat
spec:
hostNetwork: true
containers:
- name: container-tomcat
image: tomcat:latest
imagePullPolicy: Always
[root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
pod/pod-tomcat created
# 查看pod调度到哪个节点
[root@master01 ~/pod]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-tomcat 1/1 Running 0 7s 10.0.0.32 node02
```
### 访问一下
查看Pod调度到哪个节点上,用节点IP进行访问,例如我使用10.0.0.32节点的IP进行访问
```csharp
# 验证端口是否存在,tomcat端口为8080
[root@node02 ~]# ss -lntup | grep 8080
tcp LISTEN 0 100 *:8080 *:* users:(("java",pid=2141262,fd=44))
# 在master节点进行curl访问
[root@master01 ~/pod]# curl 10.0.0.32:8080
HTTP Status 404 – Not Found ...
```
## HostPort
在 Pod 定义中直接将容器端口映射到宿主机端口,绕过 Service 层,外部可通过 `节点 IP + HostPort` 直接访问 Pod。
**这种方式在k8s v1.23.17+版本之后不会有端口监听,是采用iptables来进行转发规则。**
示例:
```csharp
# 定义资源文件
[root@master01 ~/pod]# cat pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-tomcat
spec:
containers:
- name: container-tomcat
image: tomcat:latest
imagePullPolicy: Always
ports:
- name: http
# 容器的端口
containerPort: 8080
# 映射到宿主机的端口
hostPort: 8080
# 指定端口协议
protocol: TCP
# 创建Pod
[root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
pod/pod-tomcat created
```
### 访问测试
```csharp
# 查看Pod调度到哪个节点
[root@master01 ~/pod]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-tomcat 1/1 Running 0 28s 100.95.185.255 node02
# 通过分配的IP进行访问
[root@master01 ~/pod]# curl 100.95.185.255:8080
HTTP Status 404 – Not Found ...
# 通过宿主机IP进行访问
[root@master01 ~/pod]# curl 10.0.0.32:8080
HTTP Status 404 – Not Found ...
```
## port-forward方式
`kubectl port-forward `是 Kubernetes 命令行工具 (kubectl) 提供的一个功能,用于在本地计算机和集群内运行的Pod之间建立临时的网络连接,实现端口转发。通常用于开发或者测试
### 基本语法
```csharp
kubectl port-forward POD [LOCAL_PORT:]REMOTE_PORT [-n NAMESPACE] --address IP地址 --pod-running-timeout 300
```
参数解析:
- POD: 需要转发端口的Pod的名称或标签选择器。
- LOCAL\_PORT: 本地计算机上的端口号,可选。如果不指定,Kubernetes会随机选择一个可用的本地端口。
- REMOTE\_PORT: Pod中需要转发的端口号。
- -n NAMESPACE: 指定Pod所在的命名空间,如果不在当前上下文中,则需要指定。
- --address:指定外部访问的地址
- --pod-running-timeout: 参数设置等待Pod运行的最长时间,超过这个时间命令会退出
### 示例
```csharp
# 创建deploy
[root@master01 ~/deploy]# cat deploy-tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-tomcat
namespace: default
spec:
# 定义更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 3
selector:
matchLabels:
app: tomcat
template:
metadata:
name: pod-tomcat
labels:
app: tomcat
spec:
containers:
- name: container-tomcat
image: tomcat:9.0
restartPolicy: Always
[root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
deployment.apps/deployment-tomcat created
```
进行port-forward
```csharp
[root@master01 ~/deploy]# kubectl port-forward deployment-tomcat-7ddf96c4d8-mgqzf 8080:8080 --address 0.0.0.0
Forwarding from 0.0.0.0:8080 -> 8080
```
访问测试
```csharp
# curl访问
[root@node01 ~]# curl 10.0.0.30:8080
HTTP Status 404 – Not Found
```
浏览器访问,这里404只是表示没有资源,但是访问成功了

## service的方式
service有两种方式可以将Pod对外提供访问,分别是NodePort和Loadbanlacer
NodePort可以看这篇文章:[K8s新手系列之Service资源](https://www.cnblogs.com/huangSir-devops/p/18859122 "K8s新手系列之Service资源")
Loadbanlacer可以看这篇文章:[K8s进阶之MetalLB实现LoadBalancer](https://www.cnblogs.com/huangSir-devops/p/18876710 "K8s进阶之MetalLB实现LoadBalancer")
## ingress的方式(生产环境推荐!!!)
Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务
本文来自投稿,不代表本站立场,如若转载,请注明出处:http//www.knowhub.vip/share/2/3471
- 热门的技术博文分享
- 1 . ESP实现Web服务器
- 2 . 从零到一:打造高效的金仓社区 API 集成到 MCP 服务方案
- 3 . 使用C#构建一个同时问多个LLM并总结的小工具
- 4 . .NET 原生驾驭 AI 新基建实战系列Milvus ── 大规模 AI 应用的向量数据库首选
- 5 . 在Avalonia/C#中使用依赖注入过程记录
- 6 . [设计模式/Java] 设计模式之工厂方法模式
- 7 . 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
- 8 . SQL 中的各种连接 JOIN 的区别总结!
- 9 . JavaScript 中防抖和节流的多种实现方式及应用场景
- 10 . SaltStack 远程命令执行中文乱码问题
- 11 . 推荐10个 DeepSeek 神级提示词,建议搜藏起来使用
- 12 . C#基础:枚举、数组、类型、函数等解析
- 13 . VMware平台的Ubuntu部署完全分布式Hadoop环境
- 14 . C# 多项目打包时如何将项目引用转为包依赖
- 15 . Chrome 135 版本开发者工具(DevTools)更新内容
- 16 . 从零创建npm依赖,只需执行一条命令
- 17 . 关于 Newtonsoft.Json 和 System.Text.Json 混用导致的的序列化不识别的问题
- 18 . 大模型微调实战之训练数据集准备的艺术与科学
- 19 . Windows快速安装MongoDB之Mongo实战
- 20 . 探索 C# 14 新功能:实用特性为编程带来便利