【Kubernetes资源篇】Service四层代理入门实战详解

2023-11-15

一、Service四层代理概念、原理

官网中文参考文档:

1、Service四层代理概念

在K8S中Pod是有生命周期的,如果重启Pod如果Pod重启它的IP很有可能会发生变化,如果我们程序中指定Pod地址是写死的,Pod每升级一次,刚升级的Pod,集群中其他关联此Pod的服务就找不到升级的Pod。

为了解决上面问题,在K8S集群中定义了Service资源对象(简写svc),Service的IP地址是不会随便改动的,相当于定义了一个服务的入口,客户端或者集群中其他组件通过连接Service,Service代理到后端相应的服务实例,Service是一组Pod的集合,这组Pod能够被Service访问到,通常是通过标签关联实现的。

小结:

1、Pod IP地址经常发生变化,Service代理Pod,我们客户端访问,只需要访问Service,Service代理到后端Pod。

2、通过Pod IP在K8S集群之外是无法访问到的,所以需要创建Service,这个Service可以在K8s集群外部访问。

2、Service工作原理

  • k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象。

  • 当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

小结:

具体来说,当一个Pod被创建并加入到Service中时,Kubernetes会为该Pod创建一个Endpoint对象,Endpoint对象包含了Pod的IP地址和端口号。当请求到达Service的Cluster IP地址时,ipvs(iptables)规则会将请求转发到对应的Endpoint上,从而实现了四层代理的功能。

3、Service原理解读

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mCUCSq3H-1686303029941)(D:\MD归档文档\IMG\image-20230605095326789.png)]

  • Service是一个固定接入层,客户端通过访问ServiceIP+端口,从而访问到后端关联的Pod资源,Service的工作需要依赖于K8S集群中的DNS服务,不同版本的K8S集群,使用的DNS服务也是不同的,1.11之前版本使用kubeDNS,较新版本使用coreDNS。

  • Service的域名解析需要依赖于DNS服务,而DNS服务需要依赖于网络插件(flannel、calico)等,因此在部署K8S集群后也需要部署网络插件。

  • K8s节点上kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

4、Service四种类型

  • ClusterIP:默认类型,只能在集群内部访问,通过ClusterIP暴露服务,可以在集群内部的其他Pod中访问该服务。
  • NodePort:在ClusterIP的基础上,通过NodePort将服务暴露到集群外部,可以通过NodeIP:NodePort的方式访问服务。
  • ExternalName:将服务映射到集群外部的DNS记录,可以通过服务名称直接访问外部服务,应用在夸名称空间访问。

二、Service四层代理三种类型案例

1、创建ClusterIP类型Service

默认类型,只能在集群内部访问,通过ClusterIP暴露服务,可以在集群内部的其他Pod中访问该服务。

cat clusterip-deploy.yaml 

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-cluster
  namespace: default
  labels:
    type: web-cluster
    env: uat
spec:
  selector:
    matchLabels:
      type: web-cluster
      env: uat
  replicas: 3 
  template:
    metadata:
      namespace: default
      labels:
        type: web-cluster
        env: uat
    spec:
      containers:
      - name: web-cluster
        image: nginx
        imagePullPolicy: IfNotPresent 
        startupProbe:
          tcpSocket:
            port: 80
        readinessProbe:
          httpGet:
            port: 80
            path: "index.html"
        livenessProbe:
          httpGet:
            port: 80
            path: "index.html"

service资源清单如下:

cat clusterip-svc.yaml 

---
apiVersion: v1
kind: Service
metadata:
  name: web-clusterip
  namespace: default
  labels:
    env: uat
spec:
  type: ClusterIP     # ClusterIP类型
  ports:
  - port: 80          # SVC端口
    protocol: TCP     # TCP协议
    targetPort: 80    # Pod暴露端口
  selector:           # 关联具有以下标签的Pod
    env: uat
    type: web-cluster

执行YAML文件 && 查看资源

kubectl apply -f clusterip-deploy.yaml -f clusterip-svc.yaml 
kubectl get pods,svc

查看Service Endpoints 是否关联上Pod

kubectl describe svc web-clusterip

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0R2UynR-1686303029942)(D:\MD归档文档\IMG\image-20230609124223861.png)]

获取Service IP地址,通过Service代理访问后端Pod

kubectl get svc web-clusterip|awk NR==2|awk '{print $3}'
10.103.211.187
curl 10.103.211.187

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H4jELXhy-1686303029943)(D:\MD归档文档\IMG\image-20230609124400233.png)]

2、创建NodePort类型Service

在ClusterIP的基础上,通过NodePort将服务暴露到集群外部,可以通过NodeIP:NodePort的方式访问服务。

创建NodePort类型svc关联标签具有 app=demo-nginx

Deployment资源清单如下:

cat nodeport-deploy.yaml 

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-nodeport
  namespace: default
  labels:
    app: web-nodeport
    env: uat
spec:
  selector:
    matchLabels:
      app: web-nodeport
      env: uat
  replicas: 3
  template:
    metadata:
      namespace: default
      labels:
        app: web-nodeport
        env: uat
    spec:
      containers:
      - name: uat-nginx
        image: nginx
        imagePullPolicy: IfNotPresent 
        startupProbe:
          tcpSocket:
            port: 80
        readinessProbe:
          httpGet:
            port: 80
            path: "index.html"
        livenessProbe:
          httpGet:
            port: 80
            path: "index.html"

Service资源清单如下:

cat nodeport-svc.yaml 

---
apiVersion: v1
kind: Service
metadata:
  name: nodeport-svc
  namespace: default
  labels:
    env: uat
spec:
  type: NodePort
  ports:
  - port: 80               # svc的端口,这个是k8s集群内部服务可访问的端口
    protocol: TCP          # 协议
    targetPort: 80         # Pod上端口
    nodePort: 30303        # Node节点暴露端口
  selector:                # 关联具有app=web-nginx && env=uat 的Pod
    app: web-nodeport
    env: uat

执行YAML清单 && 查看状态

kubectl apply -f nodeport-deploy.yaml 
kubectl apply -f nodeport-svc.yaml 
kubectl get pods,svc

查看Service的Endpoints是否关联上Pod

kubectl describe svc nodeport-svc|grep Endpoints

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BFxq3buD-1686303029943)(D:\MD归档文档\IMG\image-20230609130818398.png)]

通过浏览器访问NodeIP:30303

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8aLEg8Ex-1686303029943)(D:\MD归档文档\IMG\image-20230609130955135.png)]

3、创建ExternalName类型Service

将服务映射到集群外部的DNS记录,可以通过服务名称直接访问外部服务。

应用场景:跨名称空间关联,ExternalName可以理解成软链接SVC资源

需求:default名称空间下的client服务要可以访问nginx-ns名称空间下的nginx-svc服务,实验图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cODOsLwZ-1686303029943)(D:\MD归档文档\IMG\image-20230609164044118.png)]

创建 服务端相关资源,并放在 nginx-ns 命名空间下

cat nginx-server.yaml 

---
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-ns
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-server
  namespace: nginx-ns
  labels:
    app: nginx-server
    env: uat
spec:
  selector:
    matchLabels:
      app: nginx-server
      env: uat
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-server
        env: uat
    spec:
      containers:
      - name: nginx-server
        image: nginx
        imagePullPolicy: IfNotPresent 
        startupProbe:
          tcpSocket:
            port: 80
        readinessProbe:
          httpGet:
            port: 80
            path: "index.html"
        livenessProbe:
          httpGet:
            port: 80
            path: "index.html"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: nginx-ns
spec:
  ports:
  - name: http
    port: 80              
    protocol: TCP        
  selector:           
    app: nginx-server 
    env: uat
kubectl apply -f nginx-server.yaml 

创建 客户端 Pod资源:

cat nginx-client.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-client
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-client
  template:
    metadata:
      labels:
        app: nginx-client
    spec:
      containers:
      - name: nginx-client
        image: busybox:1.28
        imagePullPolicy: IfNotPresent
        command: ["/bin/sh", "-c", "sleep 3600000"]
kubectl apply -f nginx-client.yaml

创建 ExternalName 类型 Service,链接到 nginx-ns 名称空间下的nginx-svc Service

cat nginx-client-svc.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: client-nginx
spec:
  type: ExternalName
  externalName: nginx-svc.nginx-ns.svc.cluster.local # 访问此SVC链接到nginx-svc.nginx-ns.svc.cluster.local SVC
  ports:
  - name: http
    port: 80
    targetPort: 80
kubectl apply -f nginx-client-svc.yaml

查看Service详细信息:

kubectl describe svc client-nginx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iQ2iZRNw-1686303029944)(D:\MD归档文档\IMG\image-20230609163103581.png)]

测试:进入client端访问nginx-service网站

kubectl exec -it nginx-client-784fd7bfc7-2d892 -- /bin/sh
wget -q -O - client-nginx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bM2E4cJY-1686303029944)(D:\MD归档文档\IMG\image-20230609163403871.png)]

三、拓展

1、Service域名解析

Service只要创建成功,我们就可以直接通过他的域名来访问(在Pod内可以使用域名访问,在Node节点是不可以使用域名访问的),每个服务创建后都会在集群DNS中动态添加一个资源记录,添加完成后就可以解析了,资源记录的格式是:

SVC_NAME.NS_NAME.DOMAIN.LTD.
服务名.命名空间.域名后缀
集群默认的域名后缀是svc.cluster.local.

用上面的 创建ClusterIP类型svc 来做实验,在Pod中使用域名访问。

kubectl exec -it web-cluster-5db6bc847b-226k9 -- /bin/bash
curl web-clusterip.default.svc.cluster.local

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IZMqj0Q5-1686303029944)(D:\MD归档文档\IMG\image-20230609130152791.png)]

2、自定义Endpoints资源

场景:创建Service资源,代理本机的3306端口

首先在宿主机安装、启动MySQL服务

yum install mariadb-server.x86_64 -y
systemctl start mariadb
systemctl enable mariadb

创建Service代理3306端口 YAML如下:

cat 3306-svc.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: svc-3306
spec:
  type: ClusterIP
  ports:
  - port: 3306
kubectl apply -f 3306-svc.yaml	

我们svc中没有定义关联的Pod标签,所以svc中并Endpoint为none

kubectl describe svc svc-3306

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yNYsLcQg-1686303029944)(D:\MD归档文档\IMG\image-20230609165500615.png)]

创建 Endpoint资源 并关联上面的SVC

cat 3306-ep.yaml 
---
apiVersion: v1
kind: Endpoints
metadata:
  name: svc-3306 # ep的名称必须和svc一致,通过名称相关联
subsets:
- addresses:
  - ip: 172.21.0.13
  ports:
  - port: 3306

OK,此时我们查看SVC的 Endpoint 会关联上面创建的Endpoint,后续K8S集群连接MySQL服务直接可以写SVC的IP+端口进行访问了。

kubectl describe svc svc-3306

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1xOXWVf6-1686303029945)(D:\MD归档文档\IMG\image-20230609171418074.png)]

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

【Kubernetes资源篇】Service四层代理入门实战详解 的相关文章

随机推荐

  • 【BERT类预训练模型整理】

    BERT类预训练模型整理 1 BERT的相关内容 1 1 BERT的预训练技术 1 1 1 掩码机制 1 1 2 NSP Next Sentence Prediction 1 2 BERT模型的局限性 2 RoBERTa的相关内容 2 1
  • 小程序(二十三)微信小程序左上角返回按钮触发事件

    微信并没有为我们提供左上角返回上一页触发的事件 但是有的时候这个操作我们还是需要监听一下 下图红框标注的返回上一页按钮 最后实现的效果 点击返回上一页的时候 我需要重新加载上一页的数据 返回上一页按钮只会触发上一页的onShow生命周期函数
  • 怎么将本地文件上传到远程git仓库

    怎么将本地文件上传到远程git仓库 1 先进入项目文件夹 通过命令 git init 把这个目录变成git可以管理的仓库 git init 2 把文件添加到版本库中 使用命令 git add 添加到暂存区里面去 不要忘记后面的小数点 意为添
  • 第二篇:UE4如何动态修改物体材质

    1 找到需要替换材质的物体 可以看到下方所有的材质 它是一个数组 前面是材质的下标 2 打开关卡蓝图 编写如下蓝图 第一步获取所有材质 创建动态材质接口 第二部设置材质 element Index代表要替换的材质下标 Material代表要
  • 米米商城项目

    米米商城 1 开发环境 2 项目功能 3 项目搭建步骤 4 配置文件 4 1 pom xml 4 2 jdbc properties 4 3 Mybaties配置文件 SqlMapConfig xml 4 4 Spring配置文件 4 4
  • 15.Mybatis 更新操作-update

    1 update 标签 update 标签是用于定义更新 语句的 1 1 常用属性 update 有几个常用的属性 但是通常只需要设置id 即可 id sql 片段在命名空间内的唯一标识 和mapper 中方法名保持一致 parameter
  • python使用keyboard库写的GUI键盘宏

    前言 之前和朋友玩游戏 需要一直按住两个按键 很麻烦 就像用python写个小脚本来方便自己 说干就干 用于学习 正文 用到的库 keyborad threading tkinter time 分析 由于需要监听键盘与运行可视化界面 所以要
  • 5.1 setfenv,但5.3可以使用lua_getglobal(l1, "_G");

    5 1使用法 lua State L luaL newstate luaL openlibs L dostring L function f1 my var 100 print var set end create func on stat
  • Springboot+Netty+Websocket实现消息推送实例

    Springboot Netty Websocket实现消息推送 文章目录 Springboot Netty Websocket实现消息推送 前言 一 引入netty依赖 二 使用步骤 1 引入基础配置类 2 netty服务启动监听器 3
  • windows 消息机制

    windows 操作系统是由事件驱动的 也叫消息机制 一般来说分为四步 用户动作也就是事件 gt windows 将事件翻译成消息 gt 将消息放入消息队列 gt 消息循环从消息队列中取出消息并发送给窗口处理程序 我们来看一下窗口最简单窗口
  • Elasticsearch 设置用户名密码认证(亲测)

    文章目录 第一步 在 elasticsearch yml 中添加如下配置 第二步 重启elasticsearch服务 第三步 设置elasticsearch密码 第四步 验证 修改密码 如果密码忘了怎么办 如何重置密码 1 修改elasti
  • 题目2-1 where is the flag

    对照启明星辰网络空间安全学院编著的 CTF安全竞赛入门 靶场和解题思路 考查点 网页源代码 右键查看源代码
  • 谁有用vue.js写的前端模板页面??? 急需!!!

    谁有用vue js写的前端模板页面 急需
  • Ubuntu切换root用户

    Ubuntu下root用户的默认密码 Ubuntu下root的默认密码是随机的 每次开机都会有一个新的密码 可以在中断输入命令 sudo passwd 然后输入当前用户的密码 按下回车 终端会提示输入新的密码并确认 此时的密码就是root新
  • Node.js 学习系列(五)—— 文件系统

    Node js 提供一组类似 UNIX POSIX 标准的文件操作API Node 导入文件系统模块 fs 语法如下所示 var fs require fs 异步和同步 Node js 文件系统 fs 模块 模块中的方法均有异步和同步版本
  • 如何使用SWC,如何发布,打包SWC

    SWC的使用方法 1 如果是FLEX的话就比较简单 直接在library中加入即可 2 是Flash的情况下 目前只有CS4可以直接导入 方法是 file gt gt publish settings gt gt flash gt gt s
  • 从零开始的Python编程

    目录 1 输出函数print 2 转义字符 3 Python中的标识符和保留字 4 变量的定义和使用 5 Python中常见的数据类型 6 数据类型转换 7 Python中的注释 8 input函数的使用 9 运算符 10 对象的布尔值 1
  • SQL优化 ----锁机制

    锁机制 解决因资源共享 而造成的并发问题 示例 当仓库中最后一件衣服时 A这时候下单 随后B也同一时间下单 这时候就会出现问题 到底这最后一件衣服卖给了谁 所以就要通过锁来解决这种问题 衣服 A来的时候加锁 gt 然后A就可以下单 付款 打
  • C++的复制构造函数三种用法

    前言 如果真的想明白 为什么你写的函数的返回值是对象时 有的时候调用了复制构造函数 而有的时候 没有调用复制构造函数 需要明白一件事 函数的返回值是对象时 什么情况下 函数的返回是return by value 即生成了临时对象 这两个问题
  • 【Kubernetes资源篇】Service四层代理入门实战详解

    文章目录 一 Service四层代理概念 原理 1 Service四层代理概念 2 Service工作原理 3 Service原理解读 4 Service四种类型 二 Service四层代理三种类型案例 1 创建ClusterIP类型Ser