K8S - 在集群内反向代理外部资源 - headless service 的使用

在上一篇文章中
K8S - 理解ClusterIP - 集群内部service之间的反向代理和loadbalancer

介绍了 ClusterIP 的主要作用 :
在k8s 集群内部 代理 内部的多实例 service

但是ClusterIP 还有1个变种 -> 无头服务 (headless service)
它用于代理集群外部的 ip资源

当然代理外部资源的方法有很多种, 除了headless service 还有externalName等service。
本文主要讲 headless service





什么是无头服务

referring:
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#headless-services

无头服务(Headless Services)
有时你并不需要负载均衡,也不需要单独的 Service IP。遇到这种情况,可以通过显式设置 集群 IP(spec.clusterIP)的值为 "None" 来创建无头服务(Headless Service)。你可以使用无头 Service 与其他服务发现机制交互,而不必绑定到 Kubernetes 的实现。无头 Service 不会获得集群 IP,kube-proxy 不会处理这类 Service, 而且平台也不会为它们提供负载均衡或路由支持。无头 Service 允许客户端直接连接到它所偏好的任一 Pod。 无头 Service 不使用虚拟 IP 地址和代理 配置路由和数据包转发;相反,无头 Service 通过内部 DNS 记录报告各个 Pod 的端点 IP 地址,这些 DNS 记录是由集群的 DNS 服务所提供的。 这些 DNS 记录是由集群内部 DNS 服务所提供的 要定义无头 Service,你需要将 .spec.type 设置为 ClusterIP(这也是 type 的默认值),并进一步将 .spec.clusterIP 设置为 None。字符串值 None 是一种特殊情况,与未设置 .spec.clusterIP 字段不同。DNS 如何自动配置取决于 Service 是否定义了选择器:

其实官方文档写得不明不白 还是要实操才能理解





ClusterIP, headless 和 externalName的区别

这3个都属于 k8s 的services 大类

而且, headless 是ClusterIP 的一种, 是特别的ClusterIP (属性 spec.clusterip = none)

而externalName 是专门做外部资源代理的

为何本文例子不用 externalName service 呢

原因是externalName 有个limitation, 它只能代理外部资源的域名, 而不是能是ip地址。

下面是官网的说明

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#externalname

========================================

ExternalName 类型

类型为 ExternalName 的 Service 将 Service 映射到 DNS 名称,而不是典型的选择算符, 例如 my-service 或者 cassandra。你可以使用 spec.externalName 参数指定这些服务。

例如,以下 Service 定义将 prod 名字空间中的 my-service 服务映射到 my.database.example.com:

apiVersion: v1
kind: Service
metadata:name: my-servicenamespace: prod
spec:type: ExternalNameexternalName: my.database.example.com

说明:
type: ExternalName 的服务接受 IPv4 地址字符串,但将该字符串视为由数字组成的 DNS 名称, 而不是 IP 地址(然而,互联网不允许在 DNS 中使用此类名称)。 类似于 IPv4 地址的外部名称无法被 DNS 服务器解析。

如果你想要将服务直接映射到某特定 IP 地址,请考虑使用无头服务。

=======================================================================

考虑到本文的例子 是用 ip address , 所以不深究 externalName





应用场景

在这里插入图片描述

如上图, 为了让bq api service 的实例们可以访问 集群外的 cloud-user , 我们要找个solution

方法一:
把cloud-user 的ip hardcode 在 bq-api-service 配置文件中

缺点:
较难实现 load balance
当 cloud user 被部署到其他server时, 需要修改配置

方法二:
就是本文的例子, 利用headless service 去代理集群外的资源





创建和应用headless service

编写yaml

headless-cloud-user

apiVersion: v1
kind: Service
metadata:name: headless-cloud-usernamespace: defaultlabels:app: cloud-user
spec:clusterIP: None # headless service---
apiVersion: v1
kind: Endpoints
metadata:name: headless-cloud-user # the name must be same with the name of service# because the service will use this endpoint to get the target ip and portnamespace: defaultlabels:target-app: cloud-user
subsets:- addresses:- ip: 192.168.0.47- ip: 192.168.0.51 # can add more ip , support base load balance

我已经踩好坑了

  1. 首先, 我们要把 service 和 endpoints 两部分分开写, 所以Service 部分不能写spec.selector. 想想也对, 这个service 不是代理pods资源, 是不应该有selector的

  2. clusterIP 设成0, 实际试过不写这个配置, 会分配1个ip, 但是这个service 本身还是work的

  3. Service 里不需要写port 的 信息了, 灵活分发, 例如调用的是 8080 端口, 映射就是外部资源的相同端口

  4. 在endpoint 部分, 名字要跟service 的名字一样! 否则不work

  5. labels 不需要一样, 如例子

  6. 被代理的ip 可以写多个

部署yaml
[gateman@manjaro-x13 bq-api-service-proxy-external]$ kubectl apply -f headless-cloud-user.yaml
service/headless-cloud-user created
endpoints/headless-cloud-user created

查看svc:

[gateman@manjaro-x13 bq-api-service-proxy-external]$ kubectl get svc -o wide
NAME                  TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
headless-cloud-user   ClusterIP   None         <none>        <none>    56m   <none>
kubernetes            ClusterIP   10.96.0.1    <none>        443/TCP   78d   <none>

可以见到 这个service 仍然属于 ClusterIP , 但是CLUSTER- IP 那一列为吉, 就是没有分配虚拟ip, ports 信息也是吉

查看endpoinds:

[gateman@manjaro-x13 bq-api-service-proxy-external]$ kubectl get ep -o wide
NAME                  ENDPOINTS                   AGE
headless-cloud-user   192.168.0.47,192.168.0.51   57m
kubernetes            192.168.0.3:6443            78d

它代理了两个 外部ip, 但是没有端口信息, 实际上就是全部端口都可以代理

测试

当然最快速的测试方法还是在dns-test 容器里测试

可以见到, 多次调用这个service情况下, 返回的信息是随机来自于 不同的ip地址的实例的

而且当我关闭其中1个ip实例时,
多次调用下, 它都自动选择健康的实例, 牛!

/ # curl headless-cloud-user:8081/actuator/info
{"app":"Cloud User API","version":"1.0.1","hostname":"b1a26a0f6685","dbUrl":"jdbc:mysql://192.168.0.42:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true","des/ # curl headless-cloud-user:8081/actuator/info
{"app":"Cloud User API","version":"1.0.1","hostname":"e166316cddb1","dbUrl":"jdbc:mysql://192.168.0.42:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true","des/ # curl headless-cloud-user:8081/actuator/info
{"app":"Cloud User API","version":"1.0.1","hostname":"e166316cddb1","dbUrl":"jdbc:mysql://192.168.0.42:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true","des/ # curl headless-cloud-user:8081/actuator/info
{"app":"Cloud User API","version":"1.0.1","hostname":"e166316cddb1","dbUrl":"jdbc:mysql://192.168.0.42:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true","des/ # curl headless-cloud-user:8081/actuator/info
{"app":"Cloud User API","version":"1.0.1","hostname":"b1a26a0f6685","dbUrl":"jdbc:mysql://192.168.0.42:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true","des/ # curl headless-cloud-user:8081/actuator/info

一些见解

同过这个例子, 有一些看法

  1. 既然 headless 可以代理外部资源, 而headless 也属于ClusterIP, 所以认为ClusterIP 只能代理内部资源的说法是错误的

  2. headless 可以写多个ip地址, 也就有了基本load balance 功能, 所以认为headless service 无负载均衡的说法也是错的

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

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

相关文章

AI应用带你玩系列之SadTalker

前段时间我刷微信视频&#xff0c;我无意间点开了一个&#xff0c;画面缓缓展开&#xff0c;是一幅精致的水墨画&#xff0c;画中人物皆是古代装束&#xff0c;衣袂飘飘&#xff0c;仿佛能闻到墨香。然而&#xff0c;这宁静的画面突然被打破了&#xff0c;画中的人物开始动了起…

初识 SpringMVC,运行配置第一个Spring MVC 程序

1. 初识 SpringMVC&#xff0c;运行配置第一个Spring MVC 程序 文章目录 1. 初识 SpringMVC&#xff0c;运行配置第一个Spring MVC 程序1.1 什么是 MVC 2. Spring MVC 概述2.1 Spring MVC 的作用&#xff1a; 3. 运行配置第一个 Spring MVC 程序3.1 第一步&#xff1a;创建Mave…

鸿蒙开发系统基础能力:【@ohos.faultLogger (故障日志获取)】

故障日志获取 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import faultLogger from ohos.faultLoggerFaultType 故障类型枚举。 系统能力&#xff1a; 以下各项对应的系统能力…

利用MSSQL模拟提权

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 利用MSSQL模拟提权 在MS SQL数据库&#xff0c;可以使用EXECUTE AS语句&#xff0c;以其他用户的上下文执行SQL查询。需要注意的是只有明确授予模拟&#xff08;Impers…

vuex的深入学习[基于vuex3]----篇(二)

store对象的创建 store的传递图 创建语句索引 创建vuex的语句为new Vuex.Store({…})Vuex的入口文件是index.js,store是index.js导出的store类store类是store.js文件中定义的。 Store的构造函数constructor 判断vuex是否被注入&#xff0c;就是将vue挂载在window对象上&am…

Java | Leetcode Java题解之第169题多数元素

题目&#xff1a; 题解&#xff1a; class Solution {public int majorityElement(int[] nums) {int count 0;Integer candidate null;for (int num : nums) {if (count 0) {candidate num;}count (num candidate) ? 1 : -1;}return candidate;} }

TLS握手中的RTT

文章目录 TLS 1.2 握手过程中的 RTT 次数TLS 1.3 1-RTT 初次TLS1.3 0-RTT 握手过程总结 TLS 1.2 握手过程中的 RTT 次数 TLS 1.2 握手通常需要2 RTT 才能完成。具体步骤如下&#xff1a; 第一次 RTT&#xff1a; 客户端发送 ClientHello&#xff1a;客户端生成一个随机数&…

26.3 Django路由层

1. 路由作用 在Django中, URL配置(通常称为URLconf)是定义网站结构的基础, 它充当着Django所支撑网站的目录. URLconf是一个映射表, 用于将URL模式(patterns)映射到Python的视图函数或类视图上. 这种映射机制是Django处理HTTP请求的基础, 它决定了当客户端发送请求时, Django如…

消息认证码解析

1. 什么是消息认证码 消息认证码(Message Authentication Code)是一种确认完整性并进行认证的技术&#xff0c;取三个单词的首字母&#xff0c;简称为MAC。 消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥&#xff0c;它可以输出固定长度的数据&#x…

AIGC-Animate Anyone阿里的图像到视频 角色合成的框架-论文解读

Animate Anyone: Consistent and Controllable Image-to-Video Synthesis for Character Animation 论文:https://arxiv.org/pdf/2311.17117 网页:https://humanaigc.github.io/animate-anyone/ MOTIVATION 角色动画的目标是将静态图像转换成逼真的视频&#xff0c;这在在线零…

ip地址怎么写才是的对的?合法ip地址正确的格式

IP地址怎么写才是的对的&#xff1f;在互联网的世界里&#xff0c;IP地址就像是我们生活中的门牌号码&#xff0c;它是每个设备在网络中的唯一标识。正确的书写IP地址对于确保网络通信的顺畅至关重要。本文将带您了解合法IP地址的正确格式与书写规范&#xff0c;并深入探讨其在…

css如何动态累计数字?

导读&#xff1a;css如何动态累计数字&#xff1f;用于章节目录的序列数生成&#xff0c;用css的计数器实现起来比 js方式更简单&#xff01; 伪元素 ::after ::before伪元素设置content 可以在元素的首部和尾部添加内容&#xff0c;我们要在元素的首部添加序列号&#xff0c…

Spring AI 介绍以及与 Spring Boot 项目整合

Spring AI 项目旨在简化使用 Spring Boot 开发包含人工智能功能的应用程序&#xff0c;提供抽象和支持多种模型提供商及矢量数据库提供商。 Spring AI 的功能特点 支持主流模型提供商&#xff1a;如 OpenAI、Microsoft、Amazon、Google 和 Huggingface 等。支持多种模型类型&a…

如何从magento1迁移到magento2

m2相较m1 变化可以说非常大&#xff0c;相当于从头到位都改写一遍&#xff0c;更现代化&#xff0c;更优雅。除了数据库表变化不是很大。 主要迁移的内容有&#xff1a; 1&#xff0c;主题 2&#xff0c;插件(自己开发的或者第三方插件) 3&#xff0c;数据库 主题 不能迁移到m…

STM32上实现spwm调制原理分析

在STM32微控制器上实现SPWM&#xff08;正弦脉宽调制&#xff0c;Sinusoidal Pulse Width Modulation&#xff09;调制的核心是利用高频载波&#xff08;三角波&#xff09;与低频基波&#xff08;正弦波&#xff09;作比较得出。 那么在STM32里三角波和正弦波分别是什么&…

java实现分类下拉树,点击时对应搜索---后端逻辑

一直想做分类下拉&#xff0c;然后选择后搜索的页面&#xff0c;正好做项目有了明确的需求&#xff0c;查找后发现el-tree的构件可满足需求&#xff0c;数据要求为&#xff1a;{ id:1, label:name, childer:[……] }形式的&#xff0c;于是乎&#xff0c;开搞&#xff01; 一…

Golang | Leetcode Golang题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; const L 10 var bin map[byte]int{A: 0, C: 1, G: 2, T: 3}func findRepeatedDnaSequences(s string) (ans []string) {n : len(s)if n < L {return}x : 0for _, ch : range s[:L-1] {x x<<2 | bin[byte(ch)]}cnt : map[int]in…

文件创建与查看

touch touch命令用于创建一个新的文件。 语法&#xff1a;touch Linux路径 其中路径可以是相对路径、绝对路径或者特殊路径符都可以。 改图展示了通过 touch test.txt 命令创建了一个 test.txt文件&#xff0c;其中深色的代表文件夹&#xff0c;白色的代表文件。 使用 ls -lh…

[MYSQL] 数据库基础

1.什么是数据库 从数据库的名字可以看出,它是用来操作(增删查改....)数据的,事实上也的确如此,通过数据库,我们可以更方便.更高效的来操作.管理数据 以文件形式存储数据的缺点 文件的安全问题文件不利于数据的查询和删除文件不利于存储海量数据操作文件并不方便 为了解决上述问…

汽车IVI中控开发入门及进阶(二十九):i.MX6

前言: i.MX 6双/6Quad处理器集成多媒体应用处理器,是不断增长的多媒体产品系列的一部分,提供高性能处理,并针对最低功耗进行了优化。 i.MX 6Dual/6Quad处理器采用先进的quad-ArmCortex-A9内核,运行速度高达800 MHz,包括2D和3D图形处理器、1080p视频处理和集成电源管理。…