Kubernetes基础(二十七)-nodePort/targetPort/port/containerPort/hostPort

1  nodePort/targetPort/port/containerPort

1.1 实现层级

1.2 配置方式

########service###########
apiVersion: v1  
kind: Service  
metadata:  labels:  name: app1  name: app1  namespace: default  
spec:  type: NodePort  ports:  - <strong>port: 8080  targetPort: 8080  nodePort: 30062</strong>  selector:  name: app1########deployment###########apiVersion: apps/v1
kind: Deployment
......
spec:
......template:.......spec:.......containers:ports:- containerPort: 8080name: httpprotocol: TCP- containerPort: 8443name: httpsprotocol: TCP- containerPort: 12200name: rpcprotocol: TCP

1.3 nodePort

外部机器可访问的端口,一般为node机器上开放的端口。 场景案例如下:

  • 比如一个Web应用需要被其他用户访问,那么需要配置​​​type=NodePort​​​,而且配置​​nodePort=30001​​​,那么其他机器就可以通过浏览器访问scheme://node:30001访问到该服务,例如​​http://node:30001​​。 
  • 例如MySQL数据库可能不需要被外界访问,只需被内部服务访问,那么不必设置​​​NodePort​​。

nodePort是kubernetes提供给集群外部客户访问service入口的一种方式(另一种方式是LoadBalancer),所以,<nodeIP>:nodePort 是提供给集群外部客户访问service的入口。

1.4 port

kubernetes中的服务之间访问的端口,service暴露在cluster ip上的端口,<cluster ip>:port 是提供给集群内部客户访问service的入口。尽管mysql容器暴露了3306端口(参考​ ​https://github.com/docker-library/mysql/​​的DockerFile),但是集群内其他容器需要通过33306端口访问该服务,外部机器不能访问mysql服务,因为没有配置NodePort类型。

1.5 targetPort

容器的端口(最根本的端口入口),与制作容器时暴露的端口一致(DockerFile中EXPOSE),例如docker.io官方的nginx暴露的是80端口。 
docker.io官方的nginx容器的DockerFile参考​​ ​https://github.com/nginxinc/docker-nginx​​。

targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。

1.6 containerPort

containerPort是在pod控制器中定义的、pod中的容器需要暴露的端口。

targetPort和containerPort必须一致。

1.7 port/nodePort总结

port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。

2 hostPort

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

apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-v1-deployment
spec:replicas: 2 selector:matchLabels:app: tomcat-v1template:metadata:labels:app: tomcat-v1spec:containers:- name: tomcatimage: tomcatports:- containerPort: 8080hostPort: 9000

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

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

2.1 hostPort 与 hostNetwork 的异同 

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

相同点:

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

不同点:

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

hostPort 截图:

hostNetwork 截图:

2.2 hostPort 原理

2.2.1 hostPort案例

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

[root@master1 ~]# kubectl get nodes -o wideNAME      STATUS   ROLES                  AGE   VERSION    INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                                  KERNEL-VERSION                    CONTAINER-RUNTIMEmaster1   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.9master2   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.9master3   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.9worker1   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.9worker2   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 modemode: ipvs

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

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

2.2.2 原理解析

2.2.2.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 的顺序进行处理。但是,实际流量的经过路径可能会受到应用配置和网络堆栈的影响,所以在进行流量管理和路由时,请务必仔细考虑业务需求和设置。

1)分析 PREROUTING 链规则

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

2)分析 IPVS 规则

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

3)分析 FORWARD 链规则规则

无 CNI-HOSTPORT 相关规则。

4)分析 POSTROUTING 链规则

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

5) 抓包验证

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

[root@worker1 ~]# docker ps|grep http-request-printer267f462be8b6   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_0e60564d42fc6   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_0432a811e77e1   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 308222nsenter: cannot open /proc/308222/ns/net: No such file or directory[root@worker1 ~]# docker ps|grep http-request-printer267f462be8b6   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_0e60564d42fc6   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_0432a811e77e1   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}}" 267f462be8b6145003[root@worker1 ~]#  nsenter -n -t 145003[root@worker1 ~]# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450inet 10.233.1.133  netmask 255.255.255.0  broadcast 10.233.1.255ether 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 0TX packets 14493  bytes 23701690 (22.6 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0loop  txqueuelen 1000  (Local Loopback)RX packets 8483  bytes 37018407 (35.3 MiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 8483  bytes 37018407 (35.3 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

抓包来确定进入容器中的包没有进行源地址转换(抓包时客户端 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.pcapdropped privs to tcpdumptcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes^C6 packets captured6 packets received by filter0 packets dropped by kernel

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

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

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

OUTPUT -> IPVS  -> POSTROUTING

1)分析 OUTPUT 链规则

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

2)分析 IPVS 规则

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

3)分析 POSTROUTING 链规则

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

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

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 服务。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于C#开发OPC DA客户端——搭建KEPServerEX服务

简介 OPC DA (OLE for Process Control Data Access) 是一种工业自动化领域中的通信协议标准&#xff0c;它定义了应用程序如何访问由OPC服务器提供的过程控制数据。OPC DA标准允许软件应用程序&#xff08;客户端&#xff09;从OPC服务器读取实时数据或向服务器写入数据&…

python:pyecharts 画基金净值 月K线图

pip install pyecharts1.9.1 pyecharts-1.9.1-py3-none-any.whl 我想在本地&#xff08;PC) 画出 基金净值 月K线图&#xff0c;不想每次看图都需联网。 cd my_dir mkdir echarts cd echarts curl -O https://assets.pyecharts.org/assets/echarts.min.js 修改一下开源代码 …

题目 1041: [编程入门]宏定义之找最大数

问题描述&#xff1a; 分别用函数和带参的宏&#xff0c;从三个数中找出最大的数。 样例输入&#xff1a; 1 2 3 样例输出&#xff1a; 3.000 3.000 代码分析&#xff1a; 函数与宏的使用&#xff1a; 函数 max() 用于找出三个实数中的最大值&#xff0c;通过比较大小并…

记录前端面试的一些笔试题(持续更新......)

文章目录 js相关数组去重数组对象去重 实现数组unshift数组扁平化tree型数据扁平化list数据转tree型数据 对象深拷贝防抖/节流函数柯里化函数管道 随便记录一些&#xff0c;面试或者工作中都会用到&#xff0c;实现的方法很多&#xff0c;这里只是一小部分&#xff0c;有更好的…

蓝桥集训之棋盘

蓝桥集训之棋盘 核心思想&#xff1a;差分二进制 因为最终输出的棋盘为01组成k&1 –> 奇1偶0 所以每次差分时元素 最中&1输出即可 #include<iostream>#include<cstring>using namespace std;const int N 2010;int b[N][N];int n,m;int main(){cin&g…

Kubernetes(k8s第四部分之servers)

1&#xff0c;为什么不使用round-robin DNS&#xff1f; 因为DNS有缓存&#xff0c;不会清理&#xff0c;无法负载均衡 ipvs代理模式&#xff0c;这种模式&#xff0c;kube-proxy会监视Kubernetes Service 对象和Endpoints&#xff0c;调用netlink接口以相应地创建ipvs规则并…

理解Linux环境变量及export命令

主要看三个问题 在Linux和Unix系统中&#xff0c;环境变量对于管理系统和应用程序的行为至关重要。本文将介绍Linux环境变量的概念&#xff0c;以及使用export命令设置环境变量的原理和作用。 什么是环境变量&#xff1f; 在Linux和Unix系统中&#xff0c;环境变量是一种可以…

将字典中的键和值对换

Python中要将字典中的键和值对换比如&#xff1a; {daisy: 0, dandelion: 1, roses: 2, sunflower: 3, tulips: 4} 变成 {0: daisy, 1: dandelion, 2: roses, 3: sunflower, 4: tulipsoriginal_dict {daisy: 0, dandelion: 1, roses: 2, sunflower: 3, tulips: 4} new_dict {…

pwn学习笔记(5)--格式化字符串漏洞(未完全完成)

pwn学习笔记&#xff08;5&#xff09;–格式化字符串漏洞 ​ 前言&#xff1a;由于条件有限&#xff0c;因此对于该漏洞的学习不算很多&#xff0c; 格式化字符串漏洞基础&#xff1a; 格式化字符串介绍&#xff1a; ​ 格式化字符串函数可以接收可变数量的参数&#xff0…

清除注册表的U盘(USB盘)使用记录,或者电脑的U盘记录

清除注册表的U盘(USB盘)使用记录&#xff0c;或者电脑的U盘记录 1、可以考虑使用psexec.exe&#xff0c;在Windows图标按右键选择Windows PowerShell(管理员)(A)&#xff0c;然后输入PsExec.exe -i -d -s regedit.exe就可以删除(如果打开注册表&#xff0c;删除id需要右键修改…

鸿蒙学习-数据持久化

应用数据持久化概述 应用数据持久化&#xff0c;是指应用将内存中的数据通过文件或数据库的形式保存到设备上。内存中的数据形态通常是任意的数据结构或数据对象&#xff0c;存储介质上的数据形态可能是文本、数据库、二进制文件等。 HarmonyOS标准系统支持典型的存储数据形态…

win11下安装mysql

一、下载MySQL 官方下载传送门 我安装的版本是5.7.83 二、安装MySQL 1.双击安装包 2.选择Custom(自定义安装)&#xff0c;然后Next> 3.根据你的系统做选择&#xff0c;我的是64位&#xff0c;所选MySQL Servers 5.7.38 -x64&#xff0c;然后按箭头将选中的版本移到右边…

qt学习:QPaintEvent绘图事件+QPainter画家

目录 QPaintEvent绘图事件 常见事件 QPainter 初始化 QPainter 设置画笔和画刷 绘制图形 结束绘制 画线 画矩形 画圆形 画弧线 画扇形 指定画笔大小 QPen 抗锯齿 无边框 画指针 多边形 渐变色 QLinearGradient 使用步骤 示例一 线性渐变 示例二 径向渐…

Java基于springboot的社区团购系统设计论文

摘 要 本课题是根据用户的需要以及网络的优势建立的一个社区团购系统&#xff0c;来满足用户团购的需求。 本社区团购系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于Spring Boot框架开发。在网站的整个开发过程中&#xff0c;首先对系统进行了需求分析&…

小迪安全32WEB 攻防-通用漏洞文件上传二次渲染.htaccess变异免杀

#知识点&#xff1a; 1、文件上传-二次渲染 2、文件上传-简单免杀变异 3、文件上传-.htaccess 妙用 4、文件上传-PHP 语言特性 #详细点&#xff1a; 1、检测层面&#xff1a;前端&#xff0c;后端等 2、检测内容&#xff1a;文件头&#xff0c;完整性&#xff0c…

青蛙过河。

&#xff01;&#xff01;&#xff01;思路和代码源自蓝桥云课大佬题解 问题描述 小青蛙住在一条河边&#xff0c;它想到河对岸的学校去学习。小青蛙打算经过河里的石头跳到对岸。 河里的石头排成了一条直线小青蛙每次跳跃必须落在一块石头或者岸上。 不过,每块石头有一个高度,…

【数据结构】拆分详解 - 排序

文章目录 前言一、排序的概念及其运用  1.1 排序的概念  1.2 排序的运用  1.3 常见的排序算法  1.4 排序算法性能测试对比函数 二、常见排序算法的实现  2.1 插入排序   2.1.1  基本思想   2.1.2  直接插入排序   2.1.3  希尔排序     1. 预排序&am…

特殊设计模式

▶实现一个类&#xff0c;不能被拷贝 ▶实现一个类&#xff0c;只能在堆上创建 ❗实现一个类&#xff0c;只能创建在栈上 ❗设计一个不能继承的类 ❗单例模式——一个类只能生成一个对象   ❔饿汉模式——在每次程序启动都会自动生成一个对象   ❓懒汉模式——在第一次需要…

学编程怎么样才能更快入手,编程怎么简单易学

学编程怎么样才能更快入手&#xff0c;编程怎么简单易学 一、前言 对于初学编程建议先从简单入手&#xff0c;然后再学习其他复杂的编程语言。 今天给大家分享的中文编程开发语言工具 进度条构件的用法。 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 …

JAVA集合4-HashMap

介绍 HashMap 它实现了 Map 接口&#xff0c;提供了键值对的存储和检索功能。HashMap 的底层数据结构是基于哈希表实现的,JDK7 是数组链表&#xff0c;JDK8 是数组链表红黑 树。其中有两个重要的参数&#xff1a; 容量负载因子 容量的默认大小是 16&#xff0c;负载因子是 0…