【Kubernetes基础--Service深入理解】--查阅笔记4
目录
- Service 的用法
- docker 对外提供服务
- service 对外提供服务
- 从集群外部访问 Pod 或 Service
- 将容器应用的端口号映射到物理机
- 将 Service 的端口号映射到物理机
- Ingress:HTTP 7层路由机制
- 创建Ingress Controller和默认的backend服务
k8s 通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。
Service 的用法
docker 对外提供服务
一般来说,对外提供服务的应用程序,对于容器应用最简便的方式就是通过 TCP/IP 机制及监听 IP 和端口号来实现。例如,定义一个提供Web 服务的 RC,由两个 Tomcat 容器副本组成,每个容器都通过 containerPort 设置提供服务的端口号为 8080:
# webapp-rc.yamlapiVersion: v1
kind: ReplicationController
metadata:name: webapp
spec:replicas: 2template:metadata:name: webapplabels:app: webappspec:containers:- name: webappimage: tomcatports:- containerPort: 8080
创建 RC,获取 IP:
kubectl create -f webapp-rc.yamlkubectl get pods -l app=webapp -o yaml | grep podIP
# podIP: 172.17.1.3
# podIP: 172.17.1.4
可以通过这两个 Pod 的 IP 地址和端口号访问 Tomcat 服务:
curl 172.17.1.3:8080curl 172.17.1.4:8080
但是,这种方式是不可靠的。例如当 Pod 所在的 Node 发生故障,Pod 将被 k8s 重新调度到另一个 Node,Pod 的 IP 地址将发生变化。我们着重考虑的是,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。k8s 中的 Service 就是用于解决这些问题的核心组件。
service 对外提供服务
以上面的 webapp 为例,为了访问 Tomcat Pod 实例,我们来创建一个 Service 提供服务:
kubectl expose rc webapp
# service "webapp" exposed
# 查看新创建的 Service,可以看到系统为它分配了一个虚拟的IP地址(ClusterIP),Service 所需的端口号则从 Pod 中的 containerPort 复制而来:
kubectl get svc
# NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# webapp 169.169.235.79 <none> 8080/TCP 3scurl 169.169.235.79:8080
这里,对 Service 地址 169.169.235.79:8080 的访问被自动负载分发到了后端两个 Pod 之一:172.17.1.3:8080或172.17.1.4:8080。
除了使用 kubectl expose 命令创建 Service,也可以通过配置文件定义 Service,再通过 kubectl create 命令进行创建:
apiVersion: v1
kind: Service
metadata:name: webapp
spec:ports:- port: 8081targetPort: 8080selector:app: webapp
Service 定义中的关键字段是 ports 和 selector。上面 ports 定义部分指定了 Service 所需的虚拟端口号为 8081,由于与 Pod 容器端口号8080 不一样,所以需要再通过 targetPort 来指定后端 Pod 的端口号。selector 定义部分设置的是后端 Pod所拥有的 label:app=webapp。
创建该Service并查看其 ClusterIP 地址:
kubectl create -f webapp-svc.yaml
# service "webapp" created
kubectl get svc
# NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# webapp 169.169.28.190 <none> 8081/TCP 3scurl 169.169.28.190:8081
目前 k8s 提供了两种负载分发策略:RoundRobin 和 SessionAffinity:
- RoundRobin:轮询模式(默认),即轮询将请求转发到后端的各个 Pod 上
- SessionAffinity:基于客户端 IP 地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个 Pod 上,之后从相同的客户端发起的请求都将被转发到后端相同的 Pod 上
在默认情况下,k8s 采用 RoundRobin 模式对客户端请求进行负载分发,也可以通过设置 service.spec.sessionAffinity=ClientIP 来启用SessionAffinity 策略。这样,同一个客户端 IP 发来的请求就会被转发到后端固定的某个 Pod 上了。通过 Service 的定义,k8s 实现了一种分布式应用统一入口的定义和负载均衡机制。
从集群外部访问 Pod 或 Service
Pod 和 Service 都是 k8s 的虚拟概念,集群外的客户端系统无法通过 Pod 的 IP 地址或者 Service 的虚拟 IP 地址和虚拟端口号访问他们。我们需要将 Pod 或 Service 的端口号映射到宿主机,以使客户端应用能够通过物理机访问容器应用。
将容器应用的端口号映射到物理机
- 通过设置容器级别的 hostPort,将容器应用的端口号映射到物理机上:
# pod-hostport.yaml
apiVersion: v1
kind: Pod
metadata:name: webapplabels:app: webapp
spec:containers:- name: webappimage: tomcatports:- containerPort: 8080hostPort: 8081
kubectl create -f pod-hostport.yaml # pod "webapp" createdcurl 192.168.18.3:8081 # 宿主机ip
- 通过设置 Pod 级别的 hostNetwork=true,该 Pod 中所有容器的端口号都将被直接映射到物理机上。在设置 hostNetwork=true 时需要注意,在容器的 ports 定义部分如果不指定 hostPort,则默认 hostPort 等于 containerPort,如果指定了 hostPort,则 hostPort 必须等于containerPort 的值:
# pod-hostnetwork.yaml
apiVersion: v1
kind: Pod
metadata:name: webapplabels:app: webapp
spec:hostNetwork: true # 设置宿主机网络containers:- name: webappimage: tomcatimagePullPolicy: Neverports:- containerPort: 8080
kubectl create -f pod-hostnetwork.yaml # pod "webapp" createdcurl 192.168.18.4:8080
将 Service 的端口号映射到物理机
- 通过设置 nodePort 映射到物理机,同时设置 Service 的类型为 NodePort:
apiVersion: v1
kind: Service
metadata:name: webapp
spec:type: NodePort # service 类型设置为 NodePortports:- port: 8080targetPort: 8080nodePort: 8081 # 指定 nodePort 端口号selector:app: webapp
kubectl create -f webapp-svc-nodeport.yaml
# service "webapp" created
# 注意,这里系统提示:由于要使用物理机的端口号,所以需要在防火墙上做好相应的配置,以使外部客户端能够访问到该端口
curl 192.168.18.4:8081
- 通过设置 LoadBalancer 映射到云服务商提供的 LoadBalancer 地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。
示例中,status.loadBalancer.ingress.ip 设置的 146.148.47.155 为云服务商提供的负载均衡器的 IP 地址。对该 Service 的访问请求将会通过 LoadBalancer 转发到后端 Pod 上,负载分发的实现方式则依赖于云服务商提供的 LoadBalancer 的实现机制:
kind: Service
apiVersion: v1
metadata:name: my-service
spec:selector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376nodePort: 30061clusterIP: 10.0.171.239loadBalancerIP: 78.11.24.19type: LoadBalancer
status:loadBalancer:ingress:- ip: 146.148.47.155
Ingress:HTTP 7层路由机制
如前所述,Service 的表现形式为 IP:Port,即工作在 TCP/IP 层。而对于基于 HTTP 的服务来说,不同的 URL 地址经常对应到不同的后端服务或者虚拟服务器(Virtual Host),这些应用层的转发机制仅通过 k8s 的 Service 机制是无法实现的。
Ingress 资源对象,可以将不同 URL 的访问请求转发到后端不同的 Service,以实现 HTTP 层的业务路由机制。k8s 使用了一个 Ingress 策略定义和一个具体的 Ingress Controller,两者结合并实现了一个完整的 Ingress 负载均衡器。代理不同后端 Service 而设置的负载均衡服务,就是 k8s 里的 Ingress 服务。
可以这样理解:Ingress 就是 Service 的 “Service”,是“反向代理”的一种抽象。
使用 Ingress 进行负载分发时,Ingress Controller 基于 Ingress 规则将客户端请求直接转发到 Service 对应的后端 Endpoint(Pod)上,这样会跳过 kube-proxy 的转发功能,kube-proxy 不再起作用。如果 Ingress Controller 提供的是对外服务,则实际上实现的是边缘路由器的功能。
为使用 Ingress,需要创建 Ingress Controller(带一个默认 backend 服务)和 Ingress 策略设置来共同完成。
创建Ingress Controller和默认的backend服务
在定义 Ingress 策略前,先部署 Ingress Controller,来实现为所有后端 Service 提供统一入口。Ingress Controller 需要实现基于不同 HTTP URL 向后转发的负载分发规则,并可以灵活设置7层负载分发策略。如果公有云服务商能够提供该类型的 HTTP 路由 LoadBalancer,则也可设置其为 Ingress Controller。
下面示例中,使用谷歌提供的 nginx-ingress-controller 镜像来创建 Ingress Controller。该 Ingress Controller 以 daemonset 的形式进行创建,在每个 Node 上都将启动一个Nginx服务。
Nginx 容器设置了 hostPort,将容器应用监听的 80 和 443 端口号映射到物理机上,使得客户端应用可以通过 URL 地址“http://物理机IP:80”或“https://物理机IP:443”来访问该 Ingress Controller。这使得 Nginx 类似于通过 NodePort 映射到物理机的 Service,成为代替 kube-proxy的 HTTP 层的 Load Balancer:
# nginx-ingress-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: nginx-ingress-lblabels:name: nginx-ingress-lbnamespace: kube-system
spec:template:metadata:labels:name: nginx-ingress-lbspec:terminationGracePeriodSeconds: 60containers:- image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2name: nginx-ingress-lbreadinessProbe:httpGet:path: /healthzport: 10254scheme: HTTPlivenessProbe:httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10timeoutSeconds: 1ports:- containerPort: 80hostPort: 80 # 映射到主机80端口- containerPort: 443hostPort: 443env:- name: POD_NAMEvalueFrom: # Downward API,将Pod信息注入为环境变量fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespaceargs:- /nginx-ingress-controller- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
为了让 Ingress Controller 正常启动,我们配置一个默认的 backend,用于在客户端访问的 URL 地址不存在时,返回404。这个 backend 服务用任何应用实现都可以,只要满足对根路径“/”的访问返回404应答,并且提供 /healthz 路径以使 kubelet 完成对它的健康检查。另外,由于 Nginx 通过 default-backend-service 的服务名称(Service Name)去访问它,所以需要 DNS 服务正确运行:
# default-backend.yamlapiVersion: extensions/v1beta1
kind: Deployment
metadata:name: default-http-backendlabels:k8s-app: default-http-backendnamespace: kube-system
spec:replicas: 1template:metadata:labels:k8s-app: default-http-backendspec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backendimage: gcr.io/google_containers/defaultbackend:1.0livenessProbe:httpGet:path: /healthzport: 8080scheme: HTTPinitialDelaySeconds: 30timeoutSeconds: 5ports:- containerPort: 8080resources:limits:cpu: 10mmemory: 20Mirequests:cpu: 10mmemory: 20Mi
---
apiVersion: v1
kind: Service
metadata:name: default-http-backendnamespace: kube-systemlabels:k8s-app: default-http-backend
spec:ports:- port: 80targetPort: 8080selector:k8s-app: default-http-backend
创建 backend 服务,并且创建 nginx-ingress-controller:
kubectl create -f default-backend.yaml
# deployment "default-http-backend" created
# service "default-http-backend" createdkubectl create -f nginx-ingress-daemonset.yaml # daemonset "nginx-ingress-lb" created# 查看 default-http-backend 和 nginx-ingress-controller 容器是否正确运行
kubectl get pod --namespace=kube-system
# NAME READY STATUS RESTARTS AGE
# default-http-backend-1132503640-84lnv 1/1 Running 0 3m
# kube-dns-v11-z3cb0 4/4 Running 0 10m
# nginx-ingress-lb-5jbwv 1/1 Running 0 3m
# nginx-ingress-lb-60j7h 1/1 Running 0 3m
# nginx-ingress-lb-dttr9 1/1 Running 0 3m# 用 curl 访问任意 Node 的 80 端口号,验证 nginx-ingress-controller 和 default-http-backend 服务正常工作:
curl k8s-node-2 # default backend -404
相关文章:
【Kubernetes基础--Service深入理解】--查阅笔记4
目录 Service 的用法docker 对外提供服务service 对外提供服务 从集群外部访问 Pod 或 Service将容器应用的端口号映射到物理机将 Service 的端口号映射到物理机 Ingress:HTTP 7层路由机制创建Ingress Controller和默认的backend服务 k8s 通过创建 Serviceÿ…...
蓝桥杯 5. Excel地址
原题目链接 题目描述 Excel 单元格的地址表示很有趣,它使用字母来表示列号。例如: A 表示第 1 列B 表示第 2 列...Z 表示第 26 列AA 表示第 27 列AB 表示第 28 列BA 表示第 53 列... Excel 的最大列号是有限的,但本题将这种表示法一般化&…...
yolov8复现
Yolov8的复现流程主要包含环境配置、下载源码和验证环境三大步骤: 环境配置 查看电脑状况:通过任务管理器查看电脑是否有独立显卡(NVIDIA卡)。若有,后续可安装GPU版本的pytorch以加速训练;若没有࿰…...
C#学习第15天:泛型
什么是泛型? 定义:泛型允许您在类、接口和方法中定义占位符,这些占位符在使用时可以指定为具体的类型。作用:通过减少重复代码和提供更强的类型检查,提高了代码的可重用性和性能。 泛型的核心概念 1.泛型类 泛型类能…...
WPF ObjectDataProvider
在 WPF(Windows Presentation Foundation)中,ObjectDataProvider 是一个非常有用的类,用于将非 UI 数据对象(如业务逻辑类或服务类)与 XAML 绑定集成。它允许在 XAML 中直接调用方法、访问属性或实例化对象,而无需编写额外的代码。以下是关于 ObjectDataProvider 的详细…...
Windows系统安装RustDesk Server的详细步骤和客户端设置
Windows系统安装RustDesk Server的详细步骤 在Windows系统上安装RustDesk Server涉及几个关键步骤,包括安装必要的依赖、下载RustDesk Server程序、配置并启动服务。以下是详细的步骤: 1. 安装Node.js和PM2 RustDesk Server的某些版本可能需要Node.js环境来运行,而PM2是一…...
RestSharp和Newtonsoft.Json结合发送和解析http
1.下载RestSharp和Newtonsoft.Json 2编写ApiRequest和ApiResponse和调用工具类HttpRestClient 请求模型 /// <summary>/// 请求模型/// </summary>public class ApiRequest{/// <summary>/// 请求地址/api路由地址/// </summary>public string Route {…...
《基于 RNN 的股票预测模型代码优化:从重塑到直接可视化》
在深度学习领域,使用循环神经网络(RNN)进行股票价格预测是一个常见且具有挑战性的任务。本文将围绕一段基于 RNN 的股票预测代码的改动前后差别展开,深入剖析代码的优化思路和效果。 原始代码思路与问题 原始代码实现了一个完整…...
【Pytorch之一】--torch.stack()方法详解
torch.stack方法详解 pytorch官网注释 Parameters tensors:张量序列,也就是要进行stack操作的对象们,可以有很多个张量。 dim:按照dim的方式对这些张量进行stack操作,也就是你要按照哪种堆叠方式对张量进行堆叠。dim的…...
半导体设备通信标准—secsgem v0.3.0版本使用说明文档(3)之SECS(SEMI E4,SEMI E5)
文章目录 1、变量1.1、数组类型1.2、获取数据1.3、设置数据1.4、编码/解码1.5、Array1.6、List1.7、动态变量 2、Items2.1、 Item types2.2、 Creating items2.1.1、 From value2.1.2、From SML text2.1.3、 From protocol text 2.3、 Getting data2.3.1、 Python value2.3.2、…...
数据中台(大数据平台)之数据资源目录
数据资源目录是数据管理的账本,是数据应用的基础,更是是数据治理成果的体现,因此数据中台产品应提供数据资源目录编制、发布、资源挂载、下架的管理能力。 1.数据资源目录分类 资源目录能够支持基于业务特点创建和维护基础目录分类和特色目…...
【随身WiFi】随身WiFi Debian系统优化教程
0.操作前必看 本教程基于Debian系统进行优化,有些操作对随身WiFi来说可能会带来负优化,根据需要选择。 所有操作需要在root用户环境下运行,否则都要加sudo 随身wifi Debian系统,可以去某安的随声WiFi模块自行搜索刷机 点赞&am…...
【WORD】批量将doc转为docx
具体步骤进行: 打开Word文档,按下AltF11快捷键,打开VBA编辑器。在VBA编辑器中,左侧的“项目资源管理器”窗口会显示当前打开的Word文档相关项目。找到您要添加代码的文档项目(通常以文档名称命名)…...
JAVA Web_定义Servlet2_学生登录验证Servlet
题目 页面StudentLogin.html中有一HTML的表单代码如下: <form action"studentLogin" method"post">学生姓名:<input type"text" name"stuName" value""><br>登录密码:…...
深入理解设计模式之模板方法模式 1d87ab8b42e98069b6c2c5a3d2710f9a
深入理解设计模式之模板方法模式 深入理解设计模式之模板方法模式 在软件开发的漫长征程中,我们常常会遇到各种复杂的业务逻辑,其中部分逻辑具有相似的流程框架,但在具体细节上又有所不同。这种情况下,模板方法模式就如同一位得…...
Unity入门笔记(缘更)
内容来源SiKi学院的Luna’s Fantasy 文章目录 一、基础知识1.准备2.基础知识1.层级(Layer)2.轴心点3.预制体(Prefab)4.刚体组件(Rigidbody)5.碰撞器组件(BoxCollider) 二、代码1.移动 一、基础知识 1.准备 Unity安装: https://unity.cn 2.基础知识 1.层级(Layer…...
【Python】用Python写一个俄罗斯方块玩玩
【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏,凑近一看…...
Java 本地缓存的实现:常见的四种方式
在 Java 中,常用的本地缓存实现主要有以下几种,以下是它们的代码示例及适用场景: 一、使用 ConcurrentHashMap 实现简单缓存 适合轻量级、无需复杂淘汰策略的场景。 import java.util.concurrent.ConcurrentHashMap;public class Simp…...
记录一次生产中mysql主备延迟问题处理
登录库: mysql -uXXXX -pXXXX -P3306 -hXXXXXX -A 备库上执行:show slave status\G 查看 seconds_Behind_Master,延迟 2705s,而且还一直在增加。 SHOW CREATE TABLE proc_i_income_temp; -- 查看表的结构 show index from proc…...
路由器原理与配置技术详解
一、路由基础原理 1.1 路由器的核心功能 网络层设备:工作在OSI参考模型第三层,实现不同网络间的互联互通智能路径选择:基于路由表为数据包选择最优传输路径协议转换:处理不同网络接口间的协议差异(如以太网与PPP&…...
第五节:React Hooks进阶篇-如何用useMemo/useCallback优化性能
反模式:滥用导致的内存开销React 19编译器自动Memoization原理 React Hooks 性能优化进阶:从手动到自动 Memoization (基于 React 18 及以下版本,结合 React 19 新特性分析) 一、useMemo/useCallback 的正确使用场景…...
STL迭代器:C++泛型编程的核心工具 [特殊字符]
在C中,STL(标准模板库)的迭代器是泛型编程的核心,它不仅解决了指针的局限性,还为算法与容器之间提供了抽象的访问接口。接下来,我们将探讨迭代器的核心作用、与指针的关键区别以及其设计哲学。 一、迭代器的…...
ffmpeg无损转格式的命令行
将ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式转换后.mkv -c:v copy 仅做拷贝视频,不重新编码 -c:a copy 仅做拷贝音频 ,不重新编码...
Monorepo 是什么?前端项目的多模块管理终极方案
前言 你是否曾经维护过多个前端项目?是否在多个项目之间来回复制粘贴组件,工具函数?是否经常被"组件更新没同步","构建时间太长","依赖版本冲突"等问题困扰? 这些问题都指向一个关键点: 项目结构和管理方式 今天,我来聊聊一种非常火但又容…...
对象池模式在uniapp鸿蒙APP中的深度应用
文章目录 对象池模式在uniapp鸿蒙APP中的深度应用指南一、对象池模式核心概念1.1 什么是对象池模式?1.2 为什么在鸿蒙APP中需要对象池?1.3 性能对比数据 二、uniapp中的对象池完整实现2.1 基础对象池实现2.1.1 核心代码结构2.1.2 在Vue组件中的应用 2.2 …...
条款05:了解C++默默编写并调用哪些函数
目录 1.默认生成的函数 2.无法生成的情况 2.1当成员函数有引用 或者 被const修饰 2.2.operator在基类被私有 1.默认生成的函数 class empty {};//相当于class empty { public:empty(){ ... } // 构造函数empty(const empty& rhs) { ... }// 拷贝构造~empty(){ ... } //…...
PythonFlask打造高效流式接口的实战
一、环境搭建与项目初始化 要使用 Flask 提供流式接口,首先得确保开发环境正确配置。在 Ubuntu 系统上,可借助 apt 包管理器便捷安装 Python 和 pip: sudo apt update sudo apt install python3 python3-pip对于 Windows 用户,推荐从官网下载安装包进行安装。安装完成后,…...
强化学习算法系列(五):最主流的算法框架——Actor-Critic算法框架
强化学习算法 (一)动态规划方法——策略迭代算法(PI)和值迭代算法(VI) (二)Model-Free类方法——蒙特卡洛算法(MC)和时序差分算法(TD) (三)基于动作值的算法——Sarsa算法与Q-Learning算法 (四…...
设计模式(结构型)-桥接模式
目录 摘要 定义 类图 角色 具体实现 优缺点 优点 缺点 使用场景 使用案例 JDBC 和桥接模式 总结 摘要 在软件开发领域,随着系统规模和复杂性的不断攀升,如何设计出具有良好扩展性、灵活性以及可维护性的软件架构成为关键挑战。桥接模式作为一…...
【MySQL】MySQL数据库 —— 简单认识
目录 1. 数据库的介绍 1.1 什么是数据库 1.2 数据库和数据结构之间关系 2. 数据库分类 2.1 关系型数据库(RDBMS) 2.2 非关系型数据库 2.3 区别 一些行内名词简单解释: 3. 关于mysql 主要学什么 4. MySQL中重要的概念 4.1 概念 4…...
