从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort

注:文中各种内网、公网 IP 仅为示例,不保证所有 IP 都可以访问,且你的环境中 IP 可能不同。

背景

在上一篇文章 自己搭建一个k8s环境 中,我们一顿操作猛如虎,搭建出了由 1 个 master 和 1 个 worker 节点组成的 k8s 集群,大概是这样的效果:

f3414047b6e9545f7a8f552fff9835cb.png

为了验证我们搭建的环境是否好使,本篇文章就借搭建 httpd 来复习复习 k8s 的部署,顺便理清 k8s 配置中的 containerPort、port、nodePort、targetPort。

如果你没有听说过 httpd,那么只需要知道它是一款功能类似于 nginx、IIS 的 Web 服务器,它的全名是 Apache HTTP Server。当部署好后访问它默认的首页,会收获 It Works 这样一行令人愉快的提示语。

nginx https://nginx.org/en/
IIS https://www.iis.net/
Apache HTTP Server https://httpd.apache.org/

先把最终效果放上,图中展示了下面会用到的各种 k8s 资源以及访问效果,阅读后面的内容时可以对照着图看看:

2fb8a5666892cdf80602cb263fcb41f9.png

部署 httpd

为了部署 httpd,我们需要用到以下知识:

  • Namespace:通过 Namespace 可以对集群内的资源进行分组,例如我希望所有和部署 httpd 有关的资源都在同一个分组中,那么就可以通过设置 namespace 实现(当然,Namespace 还影响着诸如 DNS 等内容,可以在官方文档中查看)

  • Deployment:我们知道,Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元,但通常我们不需要直接创建 Pod,而是通过 Deployment 之类的 工作负载 资源来管理它。所以我们通过 Deployment 来部署 httpd

  • Service:当部署妥当后,需要有一种方式来访问部署好的程序,Service 就是将 Pod 里的程序公开为网络服务的抽象方法

Namespace https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
Deployment https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
Pod https://kubernetes.io/zh/docs/concepts/workloads/pods/
工作负载 https://kubernetes.io/zh/docs/concepts/workloads/
Service https://kubernetes.io/zh/docs/concepts/services-networking/service/

了解了相关知识后,马上开干,我们通过 kubectl 来管理集群,所以需要登录到 master 节点上来使用 kubectl

kubectl https://kubernetes.io/zh/docs/reference/kubectl/overview/

下面会通过 yaml 文件的方式创建相关资源,

YAML is a human-friendly data serialization language for all programming languages.
YAML 是一种人类友好的数据序列化语言,适用于所有编程语言。

简而言之就是通过一种易于书写和阅读的格式,来描述数据(和大家熟悉的 JSON 以及 XML 做的事情一样)。

创建 Namespace

首先创建一个 httpd-namespace.yaml 文件:

apiVersion: v1
kind: Namespace
metadata:name: httpd
  • 通过 kind 指定要创建的资源为 Namespace

  • 通过 metadata.name 来指定 Namespace 的名称

然后执行

kubectl create -f ./httpd-namespace.yaml

表示通过文件创建资源。

然后查看我们创建的 namespace:

kubectl get namespace httpd

得到结果:

NAME    STATUS   AGE
httpd   Active   11s

一些资源有自己的缩写,例如 namespace 可以缩写为 ns

kubectl get ns httpd

这样能少打几个字母,提高效率。
通过 kubectl api-resources 可以查看相关列表。

创建 Deployment

接下来创建 httpd-deployment.yaml 文件:

apiVersion: apps/v1
kind: Deployment
metadata:namespace: httpdname: httpd
spec:selector:matchLabels:app: httpdtemplate:metadata:labels:app: httpdspec:containers:- name: httpdimage: httpd:alpineports:- containerPort: 80
  • 通过 kind 指定要创建的资源为 Deployment

  • metadata

    • 通过 namespace 设置该 Deployment 属于 httpd Namespace 下

    • 通过 name 将该 Deployment 的名称设为 httpd(有的朋友喜欢加上前缀或后缀表示是 Deployment,例如 httpd-deployment。都是可以的,只是我个人更喜欢资源类型加名称已经可以唯一标识一个资源了,就不再添加前后缀了)

  • spec

    • selector 表示 Deployment 如何找到要管理的 Pod。这里使用的 matchLabels 表示,匹配带有 app 这个 label,且值为 httpd 的 Pod

    • template 中的

    • metadata.labels 会为 Pod 增加 app: httpd label,这个 label 必须和前面 selector 定义的匹配

    • spec.containers 表示创建一个名为 httpd 的 container,使用 httpd:alpine 镜像,并开放容器的 80 端口

然后创建 Deployment:

kubectl create -f ./httpd-deployment.yaml

查看创建好的 Deployment:

kubectl get deploy -n httpd
  • deploy 是 deployments 的缩写

  • 因为我们的 Deployment 在 httpd Namespace 下,所以还需要 -n 设置 Namespace

可以看到创建好的 Deployment:

NAME    READY   UP-TO-DATE   AVAILABLE   AGE
httpd   1/1     1            1           17s

由于 Deployment 会为我们管理 Pod,这时 Pod 已经创建好了,查看 Pod:

kubectl get pods -n httpd

可以看到创建好的 Pod:

NAME                     READY   STATUS    RESTARTS   AGE
httpd-76f7455774-mdk4t   1/1     Running   0          33s

由 Deployment 生成的 Pod 的名称为 httpd 和随机字符串组成,所以你看到的 Pod 名称可能和我不同。

观察 Pod 的网络

让我们来看看这个 Pod 的 IP 地址,通过 -o 可以设置输出的格式:

kubectl get pod -n httpd -o wide

得到的返回如下:

NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE            NOMINATED NODE   READINESS GATES
httpd-76f7455774-mdk4t   1/1     Running   0          1m15s   10.10.229.95   bun-worker-01   <none>           <none>

可以看到 httpd Pod 运行于 bun-worker-01 节点,并且有一个 IP 地址。由于我们开放的端口为 80 ,试试访问一下:

wget -qO - 10.10.229.95

wow,可以访问,并得到了响应:

<html><body><h1>It works!</h1></body></html>

说明 httpd 工作良好。

再来看看这个 IP 地址 10.10.229.95,和之前通过 kubeadm init 设置的 pod-network-cidr=10.10.0.0/16 正好一致,使用的是我们为 Pod 划分的网段。

现在,我们的 Worker 节点里大概是这个模样:

e96bafee6c3f5ae3a26e3dc3c23c412b.png

这是不是意味着只要在 master 或 worker 节点上装一个 nginx 来反向代理这个 IP 地址,就能把 Pod 里的内容发布出去了呢?是,也不是 🤭

我们的这个 Pod 是通过 Deployment 管理的,可以试试删掉这个 Pod,然后 Deployment 应该自动会重新创建一个新的 Pod:

kubectl delete pod httpd-76f7455774-mdk4t -n httpd
kubectl get pods -n httpd -o wide

果然,又创建出一个新的 Pod:

NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
httpd-76f7455774-mrx79   1/1     Running   0          6s    10.10.229.96   bun-worker-01   <none>           <none>

不过 IP 地址变了😂
当然,也有奇技淫巧可以固定住 Pod 的 IP,但我们并不需要,因为有专业人士负责把 Pod 内的资源公开出去,那就是 Service。

创建 Service

创建 httpd-service.yaml 文件:

apiVersion: v1
kind: Service
metadata:namespace:  httpdname: httpd
spec:selector:app: httpdtype: NodePortports:- protocol: TCPport: 8081targetPort: 80nodePort: 30000
  • 通过 kind 指定要创建的资源为 Service

  • spec

    • selector 用于查找 Service 要服务的 Pod

    • type 这里指定了 NodePort,表示通过 Node 节点的端口暴露服务

    • ports 下面设置了使用的协议为 TCP 以及一系列的端口,后面会介绍(这里特地为各种端口设置了不同的值,方便下面进行试验)

在生产环境中,一般直接使用的是云厂商提供的负载均衡服务(即 type 设为 LoadBalancer)。但我们的宗旨是低成本(qiong)自建 k8s,所以选用 NodePort 方式非常合适。

创建 Service:

kubectl create -f ./httpd-service.yaml

查看创建好的 Service:

kubectl get svc -n httpd

返回的内容:

NAME    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
httpd   NodePort   10.1.96.193   <none>        8081:30000/TCP   6s

Cluster IP 和 port

首先来看 CLUSTER-IP,这也是通过 kubeadm init 设置的 service-cidr=10.1.0.0/16 决定的,通过 Cluster IP 可以在集群内部进行通信。

我们进入 httpd 的 Pod 里试验一下:

kubectl exec -it httpd-76f7455774-mrx79 -n httpd /bin/sh

exec 可以对 Pod 内的容器执行命令,例如这里执行的是 /bin/sh 命令,让我们可以直接与容器内部进行交互。注意将 exec 后方的 Pod 名称换成你自己的。

注意:现在,终端的内容来自 httpd Pod 内部。

在 Service 中,我们指定的 port 为 8081,那么通过 ClusterIP:port 就可以访问到通过 Service 公开的内容:

wget -qO - 10.1.96.193:8081

确实可以,相当于我(httpd Pod)绕了一圈访问了我自己:

<html><body><h1>It works!</h1></body></html>

k8s 中还有另一种访问 Service 的方式,那就是通过 <Service 名称>.<Namespace 名称>.svc.cluster.local 域名,来试一试:

wget -qO - httpd.httpd.svc.cluster.local:8081

鹅妹子嘤,也可以访问!
它背后的原理则是创建 Service 时,k8s 会创建对应的 DNS 记录 ,用 nslookup 命令看看 httpd.httpd.svc.cluster.local 解析后的 IP 是哪里:

nslookup httpd.httpd.svc.cluster.local

结果:

Server:        10.1.0.10
Address:    10.1.0.10:53Name:    httpd.httpd.svc.cluster.local
Address: 10.1.96.193

域名解析后又指向了 Cluster IP。

DNS 记录 https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service/

输入 exit 退出和 Pod 的交互,回到 master。

Node IP 和 nodePort

nodePort 顾名思义就是从节点上开放的端口,它确实在物理上占用了这个节点(主机)的一个端口,可以通过 NodeIP:nodePort 访问。在这里 httpd Pod 运行在 bun-worker-01 节点上,节点的 IP 是 172.17.0.2,那么这样也可以访问到 httpd:

wget -qO - 172.17.0.2:30000

默认情况下,nodePort 可用的范围为 30000-32767,当不设置 nodePort 时会在这个范围内随机分配一个。

Pod IP 和 targetPort

在 Service 的配置中,如果不设置 targetPort,那么它默认会被设为和 port 一样的值。不过我们为 Pod 开放的端口为 80,所以在 Service 中配置的 targetPort 需要和 Deployment 中的 containerPort 对应上。

这样通过 NodeIP:nodePort 以及 ClusterIP:port 来的流量才能通过 PodIP:targetPort 进入到容器中。

通过公网 IP 访问 httpd

最后,我们可以通过公网访问 Pod 里的 httpd!因为 NodePort 类型的 Service 是真的在节点上开放了一个端口,即 nodePort,那么我们只需要用节点的公网 IP + nodePort 就能访问到 httpd 了!

记得先在云主机的防火墙中开放 30000 端口:

0a6fa07cd02d84c0106e077d7d7d812f.png

接下打开浏览器,见证奇迹。我的 bun-worker-01 节点公网 IP 为 101.35.132.54

7b9e14cdae33c78981dface305ad23a8.png

但是不管静态设置或动态分配节点的 Port 总归是有些麻烦,而且目前这样如果想通过域名解析来访问 httpd,意味着域名后还需要接上 30000 端口才行,且不易实现负载均衡访问,不是主流的方案。

下一篇我们将使用 ingress-nginx,直接公开节点的 80 和 443 端口,像是安装了 nginx 一样,通过简单的配置,就能使用域名直接访问 Pod 里的资源。

ingress-nginx https://kubernetes.github.io/ingress-nginx/

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

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

相关文章

360文件粉碎机_中山三乡资料文件销毁粉碎销毁资料文件公司一览表

中山三乡资料文件销毁粉碎销毁资料文件公司一览表安排搬运工作人员及运输车辆上门收取销毁物品&#xff0c;将需销毁的物品装上运输车辆&#xff0c;并进行拍照、车箱粘贴封条等工作。第五步&#xff1a;客户可安排工作人员&#xff0c;跟我公司销毁运输车辆一同前往我公司销毁…

Sonnedix收购意大利11.2MW光伏电站产品组合

2016年9月5日, 太阳能独立发电商Sonnedix宣布已经在意大利获得Trading Emissions 的11.2MW太阳能光伏电站产品组合&#xff0c;此交易预计将在2016年第四季度关闭。 该产品组合包括三个地面安装光伏电站: 阿布鲁佐的Basciano和Cupello、以及西西里岛的Librandello。 Sonnedix在…

oracle中行数少于1000,oracle中in的个数超过1000的解决办法

oracle中in的个数要是超过1000就会报错&#xff0c;那么我们可以把它拆成一节一节的&#xff1a;in(1,2) or in (3,4)StringUtils.defaultIfEmpty的命名空间是&#xff1a;import org.apache.commons.lang.StringUtils;private String getOracleSQLIn(List> ids, int count,…

Xamarin效果第十七篇之AR GIS

在前面几篇文章中简单玩耍了一下在线、离线加载高德地图和添加Mark;今天在原来的基础上再去玩玩AR GIS;来看看最终效果:1、先通过NuGet引用:Install-Package Esri.ArcGISRuntime.ARToolkit.Forms -Version 100.13.02、在AndroidManifest.xml中配置:<application android:lab…

maven 多项目搭建

参考http://www.cnblogs.com/xdp-gacl/p/3498271.html 。 1.什么是maven maven是基于项目对象模型(POM)&#xff0c;是跨平台的管理工具&#xff0c;主要服务于java平台的项目构建&#xff0c;依赖管理和项目信息管理。 2.maven的好处 Maven中使用约定&#xff0c;约定java源代…

rog live service是什么_双11手机怎么买?ROG游戏手机3“独一份”体验,值得剁手...

对于追求极致的手游党来说&#xff0c;手机设备性能的强悍极为重要&#xff0c;毕竟时刻影响着流畅性与游戏体验。纵观当下手机厂商推出的游戏手机来看&#xff0c;ROG游戏手机3可以说是目前性能最强的游戏手机&#xff0c;在下半年发布的多款旗舰均没能领先过ROG。这也证明了我…

SQL Server 2005将某些数据库行为设置为与指定的 SQL Server 版本兼容

语法 sp_dbcmptlevel [ [ dbname ] name ] [ , [ new_cmptlevel ] version ]参数 [ dbname ] name要为其更改兼容级别的数据库的名称。数据库名称必须符合标识符的规则。name 的数据类型为 sysname&#xff0c;默认值为 NULL。 [ new_cmptlevel ] version数据库要与之兼容的…

oracle 优化分组 sql语句,Oracle SQL语句之常见优化方法 五

0、低效SQL语句查询:SELECT b.sql_text, --SQL內容a.sid,a.serial#,a.status,a.machine, --哪台机器運行的SQLa.username, --用戶a.module, --運行方式a.action, --Responsibilityc.opname,c.target,c.message,c.sofar totalwork * 100, --工作執行了百分之多少c.elapsed_secon…

我将 20 年前开发的操作系统迁移到 .NET 6,竟然成功了!

作者 | Scott Hanselman译者 | 弯月早在2001年&#xff0c;我用C#为学校的一门300系列的操作系统课程编写了一个微型虚拟操作系统&#xff0c;后来在2002年将其移植到了VB.NET。这些都是在.NET Core出现之前的代码&#xff0c;基于Windows早期的.NET 1.1或2.0。五年前&#xff…

bzoj2132: 圈地计划

要分成两坨对吧。。 所以显然最小割 但是不兹辞啊。。 最小割是最小的啊 求最大费用怎么玩啊 那咱们就把所有费用都加起来&#xff0c;减掉一个最小的呗 但是两个属于不同集合的点贡献的价值是负的啊 网络流怎么跑负的啊 那咱就交换一下呗 原图是二分图啊&#xff0c;把另一部分…

BEVFormerV2 论文阅读

论文链接 BEVFormer v2: Adapting Modern Image Backbones to Bird’s-Eye-View Recognition via Perspective Supervision 0. Abstract 提出了一种新颖的 BEV 检测器&#xff0c;具有透视监督&#xff0c;收敛速度更快&#xff0c;更适合现代图像基础架构优先考虑通过引入透…

光磁记录实现数据冷存储

通过一定强度的短脉冲可以在掺杂了钴离子的钇铁石榴石的磁性层上记录数据。据开发商介绍&#xff0c;这种新颖的光学存储机制有可能成为一种通用的、节能型数据存储技术&#xff0c;并替代现有的存储技术&#xff0c;这源于该技术能够完成超低热度的快速磁盘读写过程&#xff0…

aop在项目中的实际运用_【消防验收】防火玻璃在实际运用中的四大关键问题

扫码入群&#xff0c;与消防企业同行交流&#xff01;防火玻璃虽然开始在建筑中大量使用&#xff0c;但如何正确使用防火玻璃&#xff0c;使用哪种类型的防火玻璃&#xff0c;哪些部位可以使用防火玻璃等问题在实际运用中仍有很多盲区。同时&#xff0c;很多建设单位、设计单位…

CondenserDotNet - 使用 Kestrel 和 Consul 的 API 反向代理库!

简介CondenserDotNet - 使用 Kestrel 和 Consul 的 API 反向代理库&#xff01;特点•Consul 客户端库&#xff0c;包括服务注册、发现和配置•反向代理•交互式 UI&#xff0c;用于查看有关代理的统计信息配置示例配置遵循 LIFO 策略&#xff0c;以最后注册的配置为准var conf…

pdf转tiff

概述 基于Java&#xff0c;将pdf转成单一的tiff文件。 MAVEN依赖 <groupId>com.sun.media</groupId><artifactId>jai_codec</artifactId><version>1.1-mr</version> </dependency> <dependency><groupId>javax.media<…

配置PHP启动Apache服务报错

为什么80%的码农都做不了架构师&#xff1f;>>> 在新的服务器&#xff08;centos 6.3&#xff09;编译安装完php-5.4.8&#xff0c;再配置好php.ini和httpd.conf后&#xff0c;启动apache-2.4.3的时候&#xff0c;命令执行/usr/local/apache2/bin/apachectl start时…

嵌入式WiFi芯片价格战已经打响 MCU企业该醒悟了

在物联网万物互联的驱动下&#xff0c;无可厚非&#xff0c;嵌入式WiFi芯片市场成为了“引爆点”&#xff0c;预计2016年的总出货量将达到1亿颗。面对如此巨大的“诱惑”&#xff0c;国内外WiFi芯片企业自然干劲十足&#xff0c;本想好好大干一场。万万没想到&#xff0c;WiFi芯…

linux系统下图像处理开发板,Linux系统入门教程:五大图像处理软件

发文章时&#xff0c;总免不了要用图片说话。经过长时间的磨合&#xff0c;在Linux桌面系统下有几款图片处理软件我已经用得比较顺手了。这几款软件在Linux世界使用广泛&#xff0c;各个Linux发行版的软件仓库中都有自带的安装包&#xff0c;而且这几款软件运行稳定、界面美观。…

BZOJ1001 狼抓兔子 终于过了!

时间来不及了&#xff0c;先贴代码吧&#xff01;有时间再写。 好苦逼啊&#xff0c;WA了若干次&#xff0c;还有一次RE&#xff0c;一次TLE。 虽然主要运用的算法和资料都由师兄提供了。还是太弱了&#xff0c;太天真了。 首先&#xff0c;数据范围就WA了&#xff0c;RE了&…

如何使用GeneralUpdte构建客户端自动升级功能

一、概要本篇文章将向各位小伙伴介绍GeneralUpdate组件的使用&#xff0c;帮助第一次接触开发者快速上手应用在自己或企业项目中。如果本篇文章对您有帮助&#xff0c;希望帮忙点一下star。感谢各位开发者的支持。帮助文档讲解视频&#xff1a;https://www.bilibili.com/video/…