Kubernetes 映射外部服务到集群内部的场景

2023-11-09

fb73a0f0ae91449615263e261dcca9c0.png

0x04 Kubernetes 映射外部服务到集群内部的场景

场景 1.集群外的数据库映射到集群内部(IP地址)

描述: 如果您在 Kubernetes 内部和外部分别运行一些服务应用,此时应用如果分别依赖集群内部和外部应用时,通过采用将集群外部服务映射到K8s集群内部。

希望未来某个时候您可以将所有服务都移入集群内,但在此之前将是“内外混用”的状态。幸运的是您可以使用静态 Kubernetes 服务来缓解上述痛点。

在本例中,假如有一个集群外的 MySQL 服务器, 由于此服务器在与 Kubernetes 集群相同的网络(或 VPC)中创建,因此可以使用高性能的内部 IP 地址映射到集群内部以供Pod访问。

  • 第一步,我们创建一个将从此服务接收流量的 Endpoints 对象并将该对象与Service进行绑定。

# 非常注意: service和endpoint名字要相同属于同一个名称空间.
tee mapping-svc-ep.yaml << 'EOF'
kind: Endpoints
apiVersion: v1
metadata:
  name: mysqldb
  namespace: test
subsets:
  - addresses:
    - ip: 192.168.12.50
    ports:
    - port: 3306
      protocol: TCP
---

kind: Service
apiVersion: v1
metadata:
  name: mysqldb
  namespace: test
spec:
  type: ClusterIP  
  ports:
  - port: 13306
    protocol: TCP
    targetPort: 3306
EOF
  • 第二步,创建Service和Endpoints,然后您可以看到 Endpoints 手动定义了数据库的 IP 地址,并且使用的名称与服务名称相同。

$ kubectl apply -f mapping-svc-ep.yaml
  # endpoints/mysqldb created
  # service/mysqldb created
$ kubectl describe svc/mysql -n test
  # Name:              mysqldb
  # Namespace:         test
  # Labels:            <none>
  # Annotations:       <none>
  # Selector:          <none>
  # Type:              ClusterIP
  # IP:                10.102.172.40
  # Port:              <unset>  13306/TCP  # 集群内部访问的映射端口
  # TargetPort:        3306/TCP            # 目标服务端口
  # Endpoints:         192.168.12.50:3306  # 目标服务IP及端口
  # Session Affinity:  None
  # Events:            <none>

$ kubectl get svc -n test mysqldb
  NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
  mysql   ClusterIP   10.102.172.40   <none>        13306/TCP   23s
  • 第三步,集群内部Pod访问映射的MySQL服务。

# Telnet cluster_ip mapping_port
$ telnet 10.102.172.40 13306
  # Trying 10.102.172.40...
  # Connected to 10.102.172.40.
  # Escape character is '^]'.

  # 5.5.5-10.4.18-MariaDB-1:10.4.18+maria~bionic-log&

# 创建测试Pod
~$ kubectl run busybox-demo -n test --image=busybox:latest --command -- sleep 3600
~$ kubectl get pod -n test
  # NAME                         READY   STATUS             RESTARTS   AGE
  # busybox-demo                 1/1     Running            0          11s

# 进入Pod的终端
$ kubectl exec -it -n test busybox-demo -- sh
ping mysql.test.svc -c 1
  # PING mysql.test.svc (10.102.172.40): 56 data bytes
  # 64 bytes from 10.102.172.40: seq=0 ttl=64 time=0.062 ms
telnet mysql.test.svc 13306  # 连接方式1
  # Connected to mysql.test.svc
  # t
  # 5.5.5-10.4.18-MariaDB-1:10.4.18+maria~bionic-log(AxY7G<8C▒'8&SPv&TU0/8mysql_native_passwordxterm-256color
  # !#08S01Got packets out of orderConnection closed by foreign host
telnet mysql 13306          # 连接方式2
  Connected to mysql
  ....
  5.5.5-10.4.18-MariaDB-1:10.4.18+maria~bionic-log
  ...

Kubernetes 将 Endpoints 中定义的所有 IP 地址视为与常规 Kubernetes Pod 一样。现在您可以用一个简单的连接字符串访问数据库:mysql://mysql.test.svc 或者 mysql://mysql

根本不需要在代码中使用 IP 地址!如果以后 IP 地址发生变化,您可以为端点更新 IP 地址,而应用无需进行任何更改。

场景 2.具有 URI 的远程服务映射到集群内部

描述: 如果您使用的是来自第三方的托管网站,它们可能会为您提供可用于连接的统一资源标识符 (URI)。
如果它们为您提供 IP 地址,则可以使用场景 1 中的方法。

在本例中,我在 集群外部创建了一个网站,而我想在集群内部进行重定向访问。

第一步,编写部署的资源清单。

cat > mapping-svc-ExternalName.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: myweb
  namespace: test
spec:
  type: ExternalName
  externalName: www.weiyigeek.top
EOF

第二步,部署ExternalName类型的services, 我们创建一个 “ExternalName” Kubernetes 服务,此服务为您提供将流量重定向到外部服务的静态 Kubernetes 服务。此服务在内核级别执行简单的 CNAME 重定向,因此对性能的影响非常小。

~$ kubectl apply -f mapping-svc-ExternalName.yaml
~$ kubectl describe svc/myweb -n test
  # Name:              myweb
  # Namespace:         test
  # Labels:            <none>
  # Annotations:       <none>
  # Selector:          <none>
  # Type:              ExternalName
  # IP:
  # External Name:     www.weiyigeek.top  # 外部域名
  # Session Affinity:  None
  # Events:            <none>

~$ kubectl get svc -n test myweb
  NAME    TYPE           CLUSTER-IP   EXTERNAL-IP       PORT(S)   AGE
  myweb   ExternalName   <none>       www.weiyigeek.top   <none>    48s

第三步,进入Pod中进行访问测试

~$ kubectl exec -it -n test busybox-demo -- sh
ping myweb
  # PING myweb (192.168.12.18): 56 data bytes
  # 64 bytes from 192.168.12.18: seq=0 ttl=63 time=0.344 ms

wget myweb/api.json # 由于Busybox 中不带curl 此处简单采用wget进行演示
  # Connecting to myweb (192.168.12.18:80)
  # saving to 'api.json'
  # api.json             100%  15  0:00:00 ETA
  # 'api.json' saved

cat api.json
  # {"status":"ok"}

wget --spider myweb.test.svc/api.json # 
  # Connecting to myweb.test.svc (192.168.12.18:80)
  # remote file exists

Tips: 非常注意,由于 “ExternalName” 使用 CNAME 重定向,因此无法执行端口重映射我们无法使用port指定集群内部访问端口字段。

场景 3.具有 URI 和端口重映射功能的远程托管数据库

描述: CNAME 重定向对于每个环境均使用相同端口的服务非常有效,但如果每个环境的不同端点使用不同的端口,CNAME 重定向就略显不足,此时我们可以

幸运的是我们可以使用一些基本工具来解决这个问题,手动创建无头服务及endpoint,引入外部数据库,然后通过k8s集群中的域名解析服务访问,访问的主机名格式为[svc_name].[namespace_name].svc.cluster.local

在本例中,我在其它K8S集群外部创建了一个appspring的应用,而我想在当前集群通过集群services进行访问调用。

第一步,资源清单的创建,此处使用无头服务,对应的svc及endpoint配置文件应该如下。

tee svc-ep-clusterIP.yaml << 'EOF'
kind: Endpoints
apiVersion: v1
metadata:
  name: appspring
  namespace: test
  labels:
    app: appspring
subsets:
  - addresses:
    - ip: 10.41.40.21
    - ip: 10.41.40.22
    - ip: 10.41.40.23
    ports:
    - name: http
      port: 32179
      protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
  name: appspring
  namespace: test
  labels:
    app: appspring
spec:
  clusterIP: None
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 32179
  type: ClusterIP
EOF

第二步,创建service及endpoint

$ kubectl apply -f svc-ep-clusterIP.yaml
  # endpoints/appspring created
  # service/appspring created

$ kubectl describe svc/appspring -n test
  # Name:              appspring
  # Namespace:         test
  # Labels:            app=appspring
  # Annotations:       <none>
  # Selector:          <none>
  # Type:              ClusterIP
  # IP:                None
  # Port:              http  80/TCP  # 映射到集群内部端口
  # TargetPort:        32179/TCP
  # Endpoints:         10.41.40.21:32179,10.41.40.22:32179,10.41.40.23:32179    # 目标负载IP以及应用端口
  # Session Affinity:  None
  # Events:            <none>

$ kubectl get svc -n test
  # NAME   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
  # appspring   ClusterIP   None         <none>        80/TCP    4m45s

第三步,在k8s集群中启动一个alpine:latest容器进行验证:

kubectl run alpine-demo -n test --image=alpine:latest --command -- sleep 3600
kubectl exec -it -n test  alpine-demo -- sh
/ # ping appspring -c 1  # 可以看出是轮询请求的
PING appspring (10.41.40.22): 56 data bytes
64 bytes from 10.41.40.22: seq=0 ttl=60 time=1.196 ms

/ # ping appspring -c 1
PING appspring (10.41.40.21): 56 data bytes
64 bytes from 10.41.40.21: seq=0 ttl=60 time=1.273 ms

/ # ping appspring -c 1
PING appspring (10.41.40.23): 56 data bytes
64 bytes from 10.41.40.23: seq=0 ttl=60 time=1.304 ms

/ # wget appspring:32179
Connecting to appspring:32179 (10.41.40.22:32179)
Connecting to appspring:32179 (10.41.40.21:32179)
saving to 'index.html'
index.html           100% |*************************************************************************|  5275  0:00:00 ETA
'index.html' saved
/ # cat index.html

/ # ls -alh index.html
-rw-r--r--    1 root     root        5.2K Dec  6 14:58 index.htm

注:URI 可以使用 DNS 在多个 IP 地址之间进行负载平衡,因此,如果 IP 地址发生变化,这个方法可能会有风险!如果您通过上述命令获取多个 IP 地址,则可以将所有这些地址都包含在 Endpoints YAML 中,并且 Kubernetes 会在所有 IP 地址之间进行流量的负载平衡。

映射总结:
将外部服务映射到内部服务可让您未来灵活地将这些服务纳入集群,同时最大限度地减少重构工作。即使您今天不打算将服务加入集群,以后可能也会这样做!而且,这样一来,您可以更轻松地管理和了解组织所使用的外部服务。

如果外部服务具有有效域名,并且您不需要重新映射端口,那么使用 “ExternalName” 服务类型将外部服务映射到内部服务十分简便、快捷。如果您没有域名或需要执行端口重映射,只需将 IP 地址添加到端点并使用即可。

至此从K8s集群中引入外部服务实践完成。

欢迎各位志同道合的朋友一起学习交流,如文章有误请在下方留下您宝贵的经验知识,个人邮箱地址【master#weiyigeek.top】,欢迎各位读者关注。

更多文章来源: https://weiyigeek.top 【WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少】

专栏书写不易,如果你觉得这个专栏还不错的,请给这篇专栏点个赞、投个币、收个藏、关个注,转个发,这将对我的肯定,谢谢!。

fmt.Printf("不要白嫖哟,亲!") 

附录参考:

7-Kubernetes入门基础之服务发现Service介绍

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kubernetes 映射外部服务到集群内部的场景 的相关文章

随机推荐

  • group by的使用场景

    group by的使用场景 自我理解 一般配合sum使用 用来分组统计总 量 面试的时候最好说我们当时用的group 加sum查询每个sku的销量 group by 分组 查询 就是把记录集中的记录按一定规则进行 分组统计 假设一个学生名单
  • Android 关于inflate

    通俗的说 inflate就相当于将一个xml中定义的布局找出来 因为在一个Activity里如果直接用findViewById 的话 对应的是setConentView 的那个layout里的组件 因此如果你的Activity里如果用到别的
  • AWK入门到精通系列——awk快速入门

    简介 AWK是一个优良的文本处理工具 Linux及Unix环境中现有的功能最强大的数据处理引擎之一 这种编程及数据操作语言 其名称得自于它的创始人阿尔佛雷德 艾侯 彼得 温伯格和布莱恩 柯林汉姓氏的首个字母 的最大功能取决于一个人所拥有的知
  • nrm下载报错(C:\Users\16500\AppData\Roaming\npm\node_modules\nrm\cli.js:9const open = require(‘open‘)问题解决

    问题报错 建议大家下载nrm的时候尽量在node js 16版本之上 不然会造成很多报错问题无法解决 node 16版本下载地址 node js 16 问题原因是应该使用 open 的 CommonJs规范的包 现在 open v9 0 0
  • 华为云计算01——虚拟化技术

    云计算概述 云计算不是一个新的技术 它是通过虚拟化技术 将物理硬件资源虚拟化成为多个能独立运行且相同的 能为多个虚拟机提供服务 最开始云计算由亚马逊提出 并完成了云计算的初步架构 但是 亚马逊云是私有的 未公布其代码与实现原理 而后来开源社
  • Flutter drawer 侧滑实现二(通过点击现实显示侧滑栏)

    1 首先在需要使用的页面加入下方代码 GlobalKey
  • FreeRTOS(1):任务

    目录 一 FreeRTOS 介绍 什么是 FreeRTOS 为什么选择 FreeRTOS FreeRTOS 资料与源码下载 FreeRTOS 实现多任务的原理 二 移植 FreeRTOS 到STM32 手动移植 使用CubeMX快速移植 快
  • printf() 函数不加 \n 无法及时输出

    for printf worker进程休息1秒 sleep 1 printf 函数末尾不加 n 就无法及时地将信息显示到屏幕上 这是因为行缓存 Windows上一般没有 类Unix上才有 行缓存 需要输出的数据不直接显示到终端 而是首先缓存
  • 关于详解Java的对象创建

    前言 在 还不清楚怎样面向对象 和 面向对象再探究 两篇文章中 都介绍了关于面向对象程序设计的概念和特点 其中也涉及到了许多代码 比如 Dog dog new Dog 这篇文章就主要来谈谈创建对象时的具体操作 2 引入例子 下面是一个Dog
  • 洛谷 P5710 数的性质

    题目描述 一些数字可能拥有以下的性质 性质 1 是偶数 性质 2 大于 4 且不大于 12 小A 喜欢这两个性质同时成立的数字 Uim 喜欢这至少符合其中一种性质的数字 八尾勇喜欢刚好有符合其中一个性质的数字 正妹喜欢不符合这两个性质的数字
  • VR开发——Unity中导入常用的VR开发插件及简单使用

    VR开发 Unity中导入VIVE的VR开发插件及简单使用 V客学院 今天我们来讲解如何进行简单的htc vive设备的软体开发 今天的教程主要讲解从插件的导入到基本的设置以及场景搭建 小白向 首先 我们需要进入Unity中的AssetsS
  • MySQL explain 、explain extended用法

    explain显示了mysql如何使用索引来处理select语句以及连接表 可以帮助选择更好的索引和写出更优化的查询语句 使用方法 在select语句前加上explain就可以了 如 explain select from statuses
  • Unity基础之Vuforia

    Vuforia官网 https developer vuforia com Vuforia Agumented Reality SDK Vuforia增强现实扩展工具包 所属公司 高通 支持平台 Android IOS UWP 支持设备 前
  • 基于langChain 的privateGPT 文档问答 研究

    参考 gihtub代码 https github com imartinez privateGPT 官网 privateGPT可以在断网的情况下 借助GPT和文档进行交互 有利于保护数据隐私 privateGPT可以有四个用处 1 增强知识
  • [nodejs]解决mysql和连接池(pool)自动断开问题

    最近在做一个个人项目 数据库尝试使用了mongodb sqlite和mysql 分享一下关于mysql的连接池用法 项目部署于appfog 项目中我使用连接池链接数据库 本地测试一切正常 上线以后 经过几次请求两个数据接口总是报503 一直
  • stm32_acs712电流采集计算思路

    Acs712数据手册地址 https item szlcsc com 45473 html 需要测量的参数 0 实际电流值 ACS712 A 1 acs712供电电压 Vin 2 ACS 输出电压 712 OUT V 3 ACS 输出电压
  • ps命令查看具体进程的所有线程

    ps p PID t
  • 【Java数据结构】——详解优先级队列-(堆)

    文章目录 一 堆的概念 二 向下调整 1 建初堆 2 建堆 三 优先级队列 1 什么是优先队列 2 入队列 3 出队列 4 返回队首元素 5 堆的其他TopK问题 总结 一 堆的概念 堆的定义 n个元素的序列 k1 k2 kn 称之为堆 当
  • Hyperledger Fabric架构详解

    Fabric是一个模块化和可扩展的开源系统 用于部署和操作许可的区块链 也是Linux基金会 www hyperledger org 主持的Hyperledger项目之一 Hyperledger Fabric是一个较为典型的联盟链结构 1
  • Kubernetes 映射外部服务到集群内部的场景

    0x04 Kubernetes 映射外部服务到集群内部的场景 场景 1 集群外的数据库映射到集群内部 IP地址 描述 如果您在 Kubernetes 内部和外部分别运行一些服务应用 此时应用如果分别依赖集群内部和外部应用时 通过采用将集群外