首页 > 其他分享 >Kubernetes hostPort 使用

Kubernetes hostPort 使用

时间:2023-08-18 16:22:51浏览次数:51  
标签:容器 hour Kubernetes hostPort 端口 使用 Pod 节点

1、概述

在 Kubernetes 中,hostPort 是一种用于将主机上的特定端口映射到运行在 Pod 内部容器的端口的配置选项。通过使用 hostPort,你可以在主机上暴露容器的服务,从而允许外部网络通过主机的 IP 地址和指定的端口访问容器内的应用程序。如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-v1-deployment
spec:
  replicas: 2  
  selector:
    matchLabels:
      app: tomcat-v1
  template:
    metadata:
      labels:
        app: tomcat-v1
    spec:
      containers:
        - name: tomcat
          image: tomcat
          ports:
            - containerPort: 8080
              hostPort: 9000

 

 

 

 

注意 1:hostPort 与 NodePort 的区别是,NodePort 服务默认是把请求转发到随机的一个运行的 Pod 上,而 hostPort 是直接转发到本 Node 上的指定 Pod。

一个 Node 只能启动一个 hostPort,所以最初是用于把守护进程集(DaemonSets)部署到每个 Node (确保一个 Node 只有一个 hostPort )。如下图所示,3个 Node 上部署4个带 hostPort 的 Pod,会有一个不成功。

即便是3个 Node 上部署3个带 hostPort 的 Pod 滚动升级时也会有问题,所以使用 hostPort 的服务在升级的时候一定要保障先停掉旧版本的 Pod 实例再启动新版本的 Pod 实例,服务升级这块内容配置详情可以参见 《Kubernetes应用编排与管理 —— Deployment升级策略》这篇博文。 

2、hostPort 与 hostNetwork 的异同

讲到 hostPort 就不得不提 hostNetwork。hostNetwork 也是一种用于将主机上的特定端口映射到运行在 Pod 内部容器的端口的配置选项,对于客户端来说这两种访问方式都是一样的,但是它们的原理却大不相同,下面说一下 hostPort 与 hostNetwork 的异同。

相同点:

  1. hostPort 与 hostNetwork 本质上都是终端用户能访问到pod中的业务;
  2. 访问的时候,只能用 pod所有宿主机IP + 容器端口或 hostport 端口进行访问。

不同点:

  1. 网络地址空间不同。hostport使用CNI分配的地址,hostNetwork使用宿主机网络地址空间;
  2. 宿主机端口生成。hostport宿主机不生成端口,hostNetwork宿主机生成端口;
  3. hostport通过 iptables 防火墙的 nat 表进行转发,hostNetwork 直接通过主机端口到容器中;
  4. 定义的路径不同。deploy.spec.template.spec.containers.ports.hostPort 与 deploy.spec.template.spec.hostNetwork;
  5. 优先级不同,hostNetwork 高于 hostPort。

hostPort 截图:

hostNetwork 截图:

 3、hostPort 原理

(1)示例环境

当前示例Kubernetes集群节点信息如下(共五个节点,k8s版本为1.21.14):

[root@master1 ~]# kubectl get nodes -o wide
NAME      STATUS   ROLES                  AGE   VERSION    INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                                  KERNEL-VERSION                    CONTAINER-RUNTIME
master1   Ready    control-plane,master   19d   v1.21.14   10.20.32.201   <none>        Kylin Linux Advanced Server V10 (Lance)   4.19.90-52.22.v2207.ky10.x86_64   docker://20.10.9
master2   Ready    control-plane,master   19d   v1.21.14   10.20.32.202   <none>        Kylin Linux Advanced Server V10 (Lance)   4.19.90-52.22.v2207.ky10.x86_64   docker://20.10.9
master3   Ready    control-plane,master   19d   v1.21.14   10.20.32.203   <none>        Kylin Linux Advanced Server V10 (Lance)   4.19.90-52.22.v2207.ky10.x86_64   docker://20.10.9
worker1   Ready    worker                 19d   v1.21.14   10.20.32.204   <none>        Kylin Linux Advanced Server V10 (Lance)   4.19.90-52.22.v2207.ky10.x86_64   docker://20.10.9
worker2   Ready    worker                 19d   v1.21.14   10.20.32.205   <none>        Kylin Linux Advanced Server V10 (Lance)   4.19.90-52.22.v2207.ky10.x86_64   docker://20.10.9

当前集群kube-proxy模式为ipvs:

[root@master1 ~]# kubectl get configmaps -n=kube-system kube-proxy -o yaml|grep mode
    mode: ipvs

(2)示例

启动一个 Pod 示例,其是使用 Go 语言来创建一个简单的 HTTP 服务器,使用 hostPort 将主机上的 80 端口映射到运行在 Pod 内部的容器端口上,其调度到 woker1 (10.20.32.204)节点上。

客户端通过主机 ip:hostPort 访问服务能够正常响应。

(3)原理解析

3.1)节点外客户端访问当前节点容器

现在连接到 worker1 机器,由于当前集群 kube-proxy 模式选用的是 ipvs,所以当外部客户端的访问当前节点的容器时,流量包通常会先后经过以下链:

  1. PREROUTING 链(iptables): 外部流量进入主机后,首先经过 PREROUTING 链(位于 nat 表),这是网络地址转换(NAT)处理的第一个步骤。你可以在 PREROUTING 链中创建规则,以便将流量导入其他自定义的 iptables 链或 ipvs 转发路径。
  2. IPVS 转发路径: 如果你使用了 ipvs 来进行负载均衡,外部流量可能会直接进入 ipvs 的负载均衡路径。这是流量被转发到正确的后端 Pod 的地方,绕过了 iptables 的后续处理。
  3. FORWARD 链(iptables): 如果流量需要在主机内部进行转发,它会进入 FORWARD 链(位于 filter 表),在这里可以进行进一步的处理,例如网络策略、防火墙规则等。
  4. POSTROUTING 链(iptables): 流量最终经过 POSTROUTING 链(位于 nat 表),这是 NAT 处理的最后一步。你可以在这里进行出站流量的地址转换等处理。

总结起来,流量通常会按照 PREROUTING -> IPVS -> FORWARD -> POSTROUTING 的顺序进行处理。但是,实际流量的经过路径可能会受到你的配置和网络堆栈的影响,所以在进行流量管理和路由时,请务必仔细考虑你的需求和设置。

3.1.1)分析 PREROUTING 链规则

外部流量进来后首先经过PREROUTING 链,通过规则匹配只要是访问当前节点的80端口,都会进行dnat转换,转换成 PodIP:Pod端口。

3.1.2)分析 IPVS 规则

执行 ipvsadm -L -n 命令查看当前节点 IPVS 规则,在规则中没有查找到 10.20.32.204:80 匹配项。

3.1.3)分析 FORWARD 链规则规则

无 CNI-HOSTPORT 相关规则。

3.1.4)分析 POSTROUTING 链规则

CNI-HOSTPORT_MASQ规则在最前面,并且无需源地址转换。

 3.1.5) 抓包验证

进入示例容器网络命令空间:

[root@worker1 ~]# docker ps|grep http-request-printer
267f462be8b6   25585bdfb0f7                                                  "/usr/local/bin/pilo…"   About an hour ago   Up About an hour             k8s_istio-proxy_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
e60564d42fc6   6246a84777e8                                                  "./http_request_prin…"   About an hour ago   Up About an hour             k8s_container-rr19ea_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
432a811e77e1   10.20.32.201:80/library/pause:3.4.1                        "/pause"                 About an hour ago   Up About an hour             k8s_POD_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
[root@worker1 ~]#  nsenter -n -t 308222
nsenter: cannot open /proc/308222/ns/net: No such file or directory
[root@worker1 ~]# docker ps|grep http-request-printer
267f462be8b6   25585bdfb0f7                                                  "/usr/local/bin/pilo…"   About an hour ago   Up About an hour             k8s_istio-proxy_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
e60564d42fc6   6246a84777e8                                                  "./http_request_prin…"   About an hour ago   Up About an hour             k8s_container-rr19ea_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
432a811e77e1   10.20.32.201:80/library/pause:3.4.1                        "/pause"                 About an hour ago   Up About an hour             k8s_POD_http-request-printer-v1-856959f7d9-kxx6g_tracing_fa8a0a82-e233-4757-ba28-f16eb2d311f4_0
[root@worker1 ~]# docker inspect --format "{{.State.Pid}}" 267f462be8b6
145003
[root@worker1 ~]#  nsenter -n -t 145003
[root@worker1 ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.233.1.133  netmask 255.255.255.0  broadcast 10.233.1.255
        ether 2e:2c:82:08:eb:8e  txqueuelen 0  (Ethernet)
        RX packets 15372  bytes 9093248 (8.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14493  bytes 23701690 (22.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 8483  bytes 37018407 (35.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8483  bytes 37018407 (35.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@worker1 ~]# 

抓包来确定进入容器中的包没有进行源地址转换(抓包时客户端 10.20.32.201 通过 curl http://10.20.32.204:80 命令访问此服务)。

[root@worker1 ~]# tcpdump -i eth0 host 10.233.1.133 and dst port 80 -w svc_host_port.pcap
dropped privs to tcpdump
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C6 packets captured
6 packets received by filter
0 packets dropped by kernel

将抓的包下载到本地通过并使用 wireshark 软件进行分析,可以看到当节点外客户端通过 hostPort 访问容器时,进入容器中的包没有进行源地址转换。

3.2)节点上客户端访问当前节点容器

现在连接到 worker1 机器,由于当前集群 kube-proxy 模式选用的是 ipvs,所以当当前节点客户端的访问当前节点的容器时,流量包通常会先后经过以下链:

OUTPUT -> IPVS  -> POSTROUTING 

3.2.1)分析 OUTPUT 链规则

当前节点流量先经过OUTPUT 链,通过规则匹配只要是访问当前节点的80端口,都会进行dnat转换,转换成 PodIP:Pod端口,除了源地址是PodIp或127.0.0.1时会对数据包打标签,其他规则和3.1.1中类似,这里不再赘余。

3.2.2)分析 IPVS 规则

执行 ipvsadm -L -n 命令查看当前节点 IPVS 规则,在规则中没有查找到 10.20.32.204:80 匹配项。

3.2.3)分析 POSTROUTING 链规则

CNI-HOSTPORT_MASQ规则在最前面,如果源地址是PodIp或者127.0.0.1需要源地址转换。

 注意 1:没太想明白Pod是互通的,为什么源PodIP还需要进行源地址转换。

3.2.4) 路由匹配将流量发送到 Pod 里面。

 4、总结

在 Kubernetes 中,hostPort 是一种用于将主机上的特定端口映射到运行在 Pod 内部容器的端口的配置选项。通过使用 hostPort,你可以在主机上暴露容器的服务,从而允许外部网络通过主机的 IP 地址和指定的端口访问容器内的应用程序。

一个 Node 只能启动一个 hostPort,所以最初是用于把守护进程集(DaemonSets)部署到每个 Node (确保一个 Node 只有一个 hostPort ),或者部署固定在特定节点的应用程序(比如 Nginx Ingress Controller 通常以高可用形式部署在固定三个节点上面)。

按照官方文档说的,除非绝对必要,否则不要为 Pod 指定 hostPort。 将 Pod 绑定到 hostPort 时,它会限制 Pod 可以调度的位置数,因为每个 <hostIP, hostPort, protocol> 组合必须是唯一的。 如果您没有明确指定 hostIP 和 protocol,Kubernetes 将使用 0.0.0.0 作为默认 hostIP 和 TCP 作为默认 protocol,请在使用 hostPort 之前考虑使用 NodePort 服务。 

参考:https://knowledge.zhaoweiguo.com/build/html/cloudnative/k8s/yamls/option_hostport

参考:hostPort 与 hostNetwork 异同

标签:容器,hour,Kubernetes,hostPort,端口,使用,Pod,节点
From: https://www.cnblogs.com/zhangmingcheng/p/17640118.html

相关文章

  • pinia使用
    主要还是看官网和vuex是一样的,但是比vuex强大,状态管理器,可以在组件里面直接调用数据,里面只可以有数据和方法1.下载piniayarnaddpinia#或者使用npmnpminstallpinia2.创建pinia实例创建store文件夹---》index.js文件里面写import{createPinia}from'pinia'con......
  • C++快速入门 第四十四讲:函数模板swap使用
    泛型编程技术支持程序员创建函数和类的蓝图(即模板,template),而不是具体的函数和类。标准模板库STL(StandardTemplateLibrary),STL库是泛型编程技术的经典之作,它包含了许多非常有用的数据类型和算法。当拥有一个模板时,编译器将根据模板自动创建一个函数,该函数会使用正确的数据类型......
  • 软件测试|使用 VMware 安装 Ubuntu 虚拟机的详细教程
    简介在日常工作中,我们有时候会遇到需要在Linux系统中部署环境,但是申请服务器资源的时效性又不高,很多时候就需要我们自己在电脑中有一套Linux的环境,但是如何在Windows电脑中部署Linux系统呢?很多时候,在电脑中创建一个虚拟机是我们的首选,在本教程中,我们将介绍如何使用VMware虚拟化软......
  • Java 工具类库:Hutool使用说明
    Hutool是什么Hutool是一个Java工具包类库,它可以对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Utils工具类。Hutool即是Hu(谐音“糊涂”)+tool,前者致敬作者“前任公司”,后者为工具之意,谐音“糊涂”,寓意追求“万事都作糊涂观,无所谓失,无所谓得”的......
  • 使用 OpenCV Python 检测和可视化两个图像之间的差异
    使用OpenCVPython检测和可视化两个图像之间的差异转自:使用OpenCVPython检测和可视化两个图像之间的差异-Glasshost如果您需要比较两个图像并确定它们之间的差异,OpenCVPython提供了一种简单有效的方法来完成此任务。本指南将向您展示如何使用OpenCVPython检测和可视......
  • 使用GO为启明防火墙添加黑名单
    packagemainimport( "bytes" "encoding/json" "fmt" "net/http" "crypto/tls" "net/url" "strings" "regexp" "bufio" "os")var( //client*......
  • for循环中使用setTimeout得到的结果
    for(varindex=0;index<5;index++){setTimeout(()=>{console.log(index)},1000)}//输出5个5for(letindex=0;index<5;index++){setTimeout(()=>{......
  • C# 特性的创建与使用
    1、先创建一些特性以及一个示例类//应用的目标类型:类,属性,或者其他,是否对同一个目标进行多次应用[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple=false)]classDoseInterstingThingAttribute:Attribute{publici......
  • docker-compose是什么怎么使用
    docker-compose是一个用于定义和运行多个Docker容器的工具,它允许你使用一个单独的配置文件来定义多个容器、网络设置、卷挂载等,并可以一次性地启动、停止、重建整个应用程序。以下是使用docker-compose的基本步骤:创建docker-compose.yml文件:在你的项目目录下创建一个......
  • python使用netmiko连接交换机绑定mac
    环境背景python3.8,华为交换机每次手动登录交换机再进行绑定操作,太过机械化啊,本着懒人原则,写一个脚本真不是事情脚本fromnetmikoimportConnectHandlerimporttimedefbing_mac(mac):sw_ip='10.10.10.10'#交换机ipusername='admin'#交换机账号......