K8s进阶之外部访问Pod的几种方式

打印 上一主题 下一主题

主题 1778|帖子 1778|积分 5334

概述

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部署的方式
示例:
  1. # 定义deploy文件
  2. [root@master01 ~/deploy]# cat deploy-tomcat.yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6.   name: deployment-tomcat
  7.   namespace: default
  8. spec:
  9.   # 定义更新策略
  10.   strategy:
  11.     type: RollingUpdate
  12.     rollingUpdate:
  13.       maxSurge: 1
  14.       maxUnavailable: 1
  15.   replicas: 10
  16.   selector:
  17.     matchLabels:
  18.       app: tomcat
  19.   template:
  20.     metadata:
  21.       name: pod-tomcat
  22.       labels:
  23.         app: tomcat
  24.     spec:
  25.       # 使用hostNetwork的方式暴漏端口访问方式
  26.       hostNetwork: true
  27.       containers:
  28.       - name: container-tomcat
  29.         image: tomcat:9.0
  30.       restartPolicy: Always
  31. # 创建
  32. [root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
  33. deployment.apps/deployment-tomcat created
复制代码
查看Pod的启动状态
  1. [root@master01 ~/deploy]# kubectl get po -o wide | grep deployment-tomcat
  2. deployment-tomcat-577bcdbddc-5xvpl   0/1     CrashLoopBackOff   2 (27s ago)       56s     10.0.0.31         node01   <none>           <none>
  3. deployment-tomcat-577bcdbddc-c7mbs   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.32         node02   <none>           <none>
  4. deployment-tomcat-577bcdbddc-dn7qb   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.31         node01   <none>           <none>
  5. deployment-tomcat-577bcdbddc-ffp4f   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.31         node01   <none>           <none>
  6. deployment-tomcat-577bcdbddc-fpsb5   1/1     Running            0                 56s     10.0.0.31         node01   <none>           <none>
  7. deployment-tomcat-577bcdbddc-gj9wg   1/1     Running            0                 56s     10.0.0.32         node02   <none>           <none>
  8. deployment-tomcat-577bcdbddc-jnvg5   0/1     CrashLoopBackOff   2 (27s ago)       56s     10.0.0.32         node02   <none>           <none>
  9. deployment-tomcat-577bcdbddc-qsxhj   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.32         node02   <none>           <none>
  10. deployment-tomcat-577bcdbddc-swts5   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.31         node01   <none>           <none>
  11. deployment-tomcat-577bcdbddc-x6lb2   0/1     CrashLoopBackOff   2 (21s ago)       56s     10.0.0.32         node02   <none>           <none>
复制代码
这里有很多Pod未启动成功,即使启动成功了也访问不了,为什么呢?
查看一下日志,发现是对应的端口被占用了,我们上面提到过,hostNetwork是利用宿主机的网络,也会利用宿主机的端口,所以当Pod调度过去之后端口被其它的Pod占用了
那么为什么启动的Pod也访问不了呢?因为deploy部署的时间全部的Pod都是同时创建的,都去争抢宿主机的端口,这就导致谁也抢不到需要绑定的端口
  1. [root@master01 ~/deploy]# kubectl logs -f deployment-tomcat-577bcdbddc-qsxhj
  2. 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])
  3.         java.net.BindException: Address already in use
  4.                 at java.base/sun.nio.ch.Net.bind0(Native Method)
  5.                 at java.base/sun.nio.ch.Net.bind(Net.java:565)
  6.                 at java.base/sun.nio.ch.Net.bind(Net.java:554)
  7.                 at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
  8.                 at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
  9.                 at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
  10.                 at org.apache.catalina.core.StandardServer.await(StandardServer.java:537)
  11.                 at org.apache.catalina.startup.Catalina.await(Catalina.java:829)
  12.                 at org.apache.catalina.startup.Catalina.start(Catalina.java:777)
  13.                 at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
  14.                 at java.base/java.lang.reflect.Method.invoke(Method.java:580)
  15.                 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
  16.                 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
复制代码
利用Pod进行部署
  1. [root@master01 ~/pod]# cat pod-tomcat.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: pod-tomcat
  6. spec:
  7.   hostNetwork: true
  8.   containers:
  9.   - name: container-tomcat
  10.     image: tomcat:latest
  11.     imagePullPolicy: Always
  12. [root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
  13. pod/pod-tomcat created
  14. # 查看pod调度到哪个节点
  15. [root@master01 ~/pod]# kubectl get po -o wide
  16. NAME                                READY   STATUS             RESTARTS        AGE     IP                NODE     NOMINATED NODE   READINESS GATES
  17. pod-tomcat                          1/1     Running            0               7s      10.0.0.32         node02   <none>           <none>
复制代码
访问一下

查看Pod调度到哪个节点上,用节点IP进行访问,例如我利用10.0.0.32节点的IP进行访问
  1. # 验证端口是否存在,tomcat端口为8080
  2. [root@node02 ~]# ss -lntup | grep 8080
  3. tcp   LISTEN 0      100                     *:8080             *:*    users:(("java",pid=2141262,fd=44))
  4. # 在master节点进行curl访问
  5. [root@master01 ~/pod]# curl 10.0.0.32:8080
  6. <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title>...
复制代码
HostPort

在 Pod 定义中直接将容器端口映射到宿主机端口,绕过 Service 层,外部可通过 节点 IP + HostPort 直接访问 Pod。
这种方式在k8s v1.23.17+版本之后不会有端口监听,是采用iptables来进行转发规则。
示例:
  1. # 定义资源文件
  2. [root@master01 ~/pod]# cat pod-tomcat.yaml
  3. apiVersion: v1
  4. kind: Pod
  5. metadata:
  6.   name: pod-tomcat
  7. spec:
  8.   containers:
  9.   - name: container-tomcat
  10.     image: tomcat:latest
  11.     imagePullPolicy: Always
  12.     ports:
  13.     - name: http
  14.       # 容器的端口
  15.       containerPort: 8080
  16.       # 映射到宿主机的端口
  17.       hostPort: 8080
  18.       # 指定端口协议
  19.       protocol: TCP
  20. # 创建Pod
  21. [root@master01 ~/pod]# kubectl apply -f pod-tomcat.yaml
  22. pod/pod-tomcat created
复制代码
访问测试
  1. # 查看Pod调度到哪个节点
  2. [root@master01 ~/pod]# kubectl get po -o wide
  3. NAME                                READY   STATUS             RESTARTS          AGE     IP                NODE     NOMINATED NODE   READINESS GATES
  4. pod-tomcat                          1/1     Running            0                 28s     100.95.185.255    node02   <none>           <none>
  5. # 通过分配的IP进行访问
  6. [root@master01 ~/pod]# curl 100.95.185.255:8080
  7. <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title>...
  8. # 通过宿主机IP进行访问
  9. [root@master01 ~/pod]# curl 10.0.0.32:8080
  10. <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title>...
复制代码
port-forward方式

kubectl port-forward 是 Kubernetes 命令行工具 (kubectl) 提供的一个功能,用于在本地计算机和集群内运行的Pod之间创建临时的网络连接,实现端口转发。通常用于开发或者测试
基本语法
  1. 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运行的最长时间,超过这个时间命令会退出
示例
  1. # 创建deploy
  2. [root@master01 ~/deploy]# cat deploy-tomcat.yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6.   name: deployment-tomcat
  7.   namespace: default
  8. spec:
  9.   # 定义更新策略
  10.   strategy:
  11.     type: RollingUpdate
  12.     rollingUpdate:
  13.       maxSurge: 1
  14.       maxUnavailable: 1
  15.   replicas: 3
  16.   selector:
  17.     matchLabels:
  18.       app: tomcat
  19.   template:
  20.     metadata:
  21.       name: pod-tomcat
  22.       labels:
  23.         app: tomcat
  24.     spec:
  25.       containers:
  26.       - name: container-tomcat
  27.         image: tomcat:9.0
  28.       restartPolicy: Always
  29. [root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
  30. deployment.apps/deployment-tomcat created
复制代码
进行port-forward
  1. [root@master01 ~/deploy]# kubectl port-forward deployment-tomcat-7ddf96c4d8-mgqzf 8080:8080 --address 0.0.0.0
  2. Forwarding from 0.0.0.0:8080 -> 8080
复制代码
访问测试
  1. # curl访问
  2. [root@node01 ~]# curl 10.0.0.30:8080
  3. <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found
复制代码
浏览器访问,这里404只是表示没有资源,但是访问成功了

service的方式

service有两种方式可以将Pod对外提供访问,分别是NodePort和Loadbanlacer
NodePort可以看这篇文章:K8s新手系列之Service资源
Loadbanlacer可以看这篇文章:K8s进阶之MetalLB实现LoadBalancer
ingress的方式(生产环境推荐!!!)

Ingress相称于一个7层的负载平衡器,是kubernetes对反向代理的一个抽象,它的工作原理雷同于Nginx,可以理解成在Ingress里创建诸多映射规则,Ingress Controller通过监听这些设置规则并转化成Nginx的反向代理设置 , 然后对外部提供服务
可以参考这篇文章:K8s进阶之初识Ingress

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

卖不甜枣

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表