浅入Kubernetes(11):了解 Service 和 Endpoint
浅入Kubernetes(8):外网访问集群 中已经介绍过部署一个 Deployment 和 Service,本篇是它的补充,将会广泛地聊一下 Service。
文章地址 https://www.cnblogs.com/whuanle/p/14685430.html
Srevice
Service 是将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。如果我们使用 Deployment 部署 pod,则可以以 Deployment 为对象创建 Service。
在 K8S 中,每个 Pod 都有其自己唯一的 ip 地址,而 Service 可以为多个 Pod(一组)提供相同的 DNS 名,并且可以在他们直接进行负载均衡。
假如有一组 nginx pod,如果 nginx 动态伸缩改变或因为某些原因 ip/端口发生改变,那么其 ip 和 端口都不是固定的,而且我们很难确定它新扩容的 pod 的地址是什么,又万一 pod 被删除,ip 不再可用。
又假如一组 pod 称为前端,如 web 服务,另一组 pod 称为后端,例如 mysql。那么 前端 如何查找并跟踪要连接的 ip 地址,以便前端可以使用工作负载的后端部分?
这真是 Service 要解决的问题。Kubernetes Service 定义了一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。当使用 Service 为一组 pod (Deployment 的方式创建的)创建服务时,无论我们创建了多少个 pod 副本,这些 pod 怎么变化,前端不需要关心它们调用了哪个后端副本,而且不需要知道后端 pod 的状态也不需要跟踪 pod。Service 把前后端的这种关联抽象化,把它们解耦了。
Service 的创建及现象
现在按照下面的命令快速创建 pod,pod 将会在各个节点中部署运行。
kubectl create deployment nginx --image=nginx:latest --replicas=3
kubectl expose deployment nginx --type=LoadBalancer --port=80
然后执行命令查看 Service:
kubectl get services
也就是说外部访问端口是 30424。
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        3d6h
nginx        LoadBalancer   10.101.132.236   <pending>     80:30424/TCP   39s
这时,我们可以通过公网和端口访问这个 Service。
我们可以查看此 Service 的 yaml 文件:
kubectl get service nginx -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2021-04-23T07:40:35Z"
  labels:
    app: nginx
  name: nginx
  namespace: default
  resourceVersion: "369738"
  uid: 8dc49805-2fc8-4407-adc0-8e31dc24fa79
spec:
  clusterIP: 10.101.132.236
  clusterIPs:
  - 10.101.132.236
  externalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 30424
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer: {}
有了标准的 yaml 文件模板,我们可以很方便地修改并定制一个 Service。
我们查看通过 Deployment 创建的 pod:
kubectl get pods -o wide
NAME                        IP              NODE       NOMINATED NODE   READINESS GATES
nginx-55649fd747-9fzlr    192.168.56.56    instance-2   <none>           <none>
nginx-55649fd747-ckhrw    192.168.56.57    instance-2   <none>           <none>
nginx-55649fd747-ldzkf    192.168.23.138   instance-1   <none>           <none>
注:pod 在哪个节点中运行,我们是不一样的。
当我们通过外部网络访问时,Service 会自动提供其中一个 pod 给我们,但是这个过程较为复杂,我们这里先将表面现象。
               ------------
               |          |
--- 公网ip -->  |   pod1   |
               |   pod2  |
               |   pod3  |
               ------------
然后我们通过命令查看 iptables 配置:
iptables-save
然后查找 random 关键字:

你可以看到有三个 default/nginx, 第一个 pod 被访问的机会都是 0.33333...,然后 2/3 的概率中,2/3 的 0.5 的概率选择第二个 pod,剩下的 1/3 概率选择第三个 pod。
如果要访问 pod,可以以任意部署了 nginx pod 的节点的 ip 进行访问。由于 master 不能部署 pod,所以不能通过 master 的 ip 进行访问。
当然,它并不是直接都是 0.33333.. 这样的,iptables 的规则有点复杂,这里难以讲清楚,我们只需要知道 外网能够访问 Service,而 Service 通过 iptable 为我们转发流量。即使 Deployment 部署的 pod 不在同一个节点上, k8s 的 dns 服务等会正确处理的,我们不需要手动配置这些网络。

【图来源:k8s 官网】
Service 定义
在上一小节中,介绍了 Service 的创建方法(kubectl expose ...),也介绍了其依赖的 iptables,这里将继续学习 Service 的定义方法。
因为之前我们是通过 Deployment 进行操作,直接为一个 deployment 中的 pod (副本)统一映射。当然我们也可以为不同的 pod 进行网络映射。
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 6666
      targetPort: 80
这里我们使用了 selector 选择器,一般 pod 的 Label 都会有 app,表示此 pod 的名称(一般是镜像名称)。port、targetPort 分别是 pod 端口、提供给外界访问的端口。
当我们不通过 Deployment 或者 job 等对象处理 pod 时,可以通过 selector 来选择合适的 pod。
Service 能够将一个接收 容器或者 pod 的端口 targetPort 映射到任意的 port 端口,port 是外部可以访问的端口。 如果使用 kubectl expose 去映射端口,会默认随机提供一个 30xxx 端口。而使用 yaml ,默认情况下,targetPort 将被设置为与 port 字段相同的值。
Endpoint slices
”端点切片(Endpoint Slices) 提供了一种简单的方法来跟踪 Kubernetes 集群中的网络端点 (network endpoints)。它们为 Endpoints 提供了一种可伸缩和可拓展的替代方案。“
在 Kubernetes 中,EndpointSlice 包含对一组网络端点的引用。 指定选择器后控制面会自动为设置了 选择算符 的 Kubernetes 服务创建 Endpoint。
也就是说创建 Service(带选择运算符) 会自动创建 Endpiont。
我们查看默认命名空间的 endpoint:
kubectl get endpoints
NAME         ENDPOINTS                                            AGE
kubernetes   10.170.0.2:6443                                      3d7h
nginx        192.168.56.24:80,192.168.56.25:80,192.168.56.26:80   59m
这些都是 pod 的 ip 和端口,也就是说,通过 Endpoint 我们跟踪 Kubernetes 集群中的网络端点 (network endpoints)变得更加任意。不过这样解释是很难明白的,笔者翻了很多次资料,一点点试错才搞懂。接下来我们一步步来上手操作,然后一点点理解这些操作的含义。
创建 Endpoint、Service
接下来我们手动创建 Service 和 Endpoint 和 ,需要先创建 Service ,再创建 Endpoint (这两者创建顺序可以随意)。
Service
我们先删除之前创建的 service。
kubectl delete service nginx
编写 service.yaml 文件内容如下如下:
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
    - protocol: TCP
      port: 6666
      targetPort: 80
应用这个 Service:
kubectl apply -f service.yaml
查看 service :
kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   3d12h
nginx        ClusterIP   10.98.113.242   <none>        6666/TCP    6s
由于此 Service 没有映射任何 pod 等,因此没有任何用处,但是此时已经可以给开发人员一个交待了,或者说确定下 nginx 的 Service 端口和地址。至于真正的 nginx 服务,后面再确定。创建 Service 和 Endpoint 的顺序是任意的,只是这里我们提出抽象,先约定 端口,再提供服务,所以先创建 Service。
创建应用
我们随便找台 worker 或者 master 节点,创建一个 nginx 容器:
docker run -itd -p 80:80 nginx:latest
为什么不用 pod,直接创建容器?因为我们处于开发阶段,如果把 nginx 改成 mysql,我们要 Debug 呢?测试自己的数据库呢?要模拟数据呢?我们在生产时再通过 Deployment 创建应用,但是此时我们可以使用自己的数据库或者本地应用。
官方文档说:
- 希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。
 - 希望服务指向另一个 名字空间(Namespace) 中或其它集群中的服务。
 - 你正在将工作负载迁移到 Kubernetes。 在评估该方法时,你仅在 Kubernetes 中运行一部分后端。
 
总之,我们创建了 Service,可以提供了抽象,至于怎么提供这个服务,我们可以使用 pod ,也可以直接使用命令执行机器上的二进制程序,也可以通过 docker 提供。而且 mysql 可能是在外部服务提供的,或者 mysql 直接部署在宿主机上,而不使用容器和 pod,我们可以通过 Endpoint 来跟踪 mysql 服务的端口。
然后查询这个容器的 ip,:
docker inspect {容器id} | grep IPAddress
笔者得到的是:"IPAddress": "172.17.0.2",可以试试 curl 172.17.0.2 ,看看是否能够访问 nginx,如果没问题我们来进行下一步。
创建 Endpoint
创建一个 endpoint.yaml 文件,内容如下(注意替换ip为你容器访问ip):
apiVersion: v1
kind: Endpoints
metadata:
  name: nginx
subsets:
  - addresses:
      - ip: 172.17.0.2
    ports:
      - port: 80
然后应用 yaml:
kubectl apply -f endpoint.yaml
查看 endpoint:
kubectl get endpoints
# 不能填写成 endpoint
然后访问 Service 的 ip:
curl 10.99.142.24:6666
也可以通过公网访问此 IP。
如果 Endpoint 需要跟踪多个 ip (多个 pod 或者容器或者应用),可以使用:
  - addresses:
      - ip: 172.17.0.2
      - ip: 172.17.0.3
      - ip: 172.17.0.4
      ... ...
												
											浅入Kubernetes(11):了解 Service 和 Endpoint的更多相关文章
- 浅入Kubernetes(8):外网访问集群
		
目录 查询 Service Service 外部服务类型 配置 ServiceType 伸缩数量 阶段总结 在前面几篇文章中,我们学习了 kubeadm .kubectl 的一些命令,也学会了 Dep ...
 - 浅入Kubernetes(6):CKAD认证中的部署教程
		
目录 预设网络 kubeadm 安装 k8s 配置 calico 自动补全工具 状态描述 目前为止,笔者已经写了 5 篇关于 k8s 的文章,这一篇笔者将介绍 CKAD 认证官方课程中,如何部署 k8 ...
 - 浅入Kubernetes(7):应用部署实例,Deployment、Service、ReplicaSet
		
目录 Deployment 创建 Deployment kubectl apply/create 网络端口映射和更新 Deployment ReplicaSet 在本文之前,你需要阅读: 尝试 kub ...
 - 浅入kubernetes(1):Kubernetes 入门基础
		
目录 Kubernetes 入门基础 Introduction basic of kubernetes What Is Kubernetes? Components of Kubernetes Kub ...
 - 浅入kubernetes(2):Kubernetes 的组成
		
目录 说明 Kubernetes集群的组成 What are containerized applications? What are Kubernetes containers? What are ...
 - 浅入Kubernetes(10):控制节点的部署,选择器、亲和性、污点
		
目录 标签和nodeSelector 标签选择 亲和性和反亲和性 污点和容忍度 系统默认污点 容忍度 DaemonSet 在前面的学习中,我们学到了 Deployment 部署,以及副本数(Repli ...
 - 浅入kubernetes(5):尝试kubeadm
		
本篇介绍利用 kubernetes 的命令行工具,快速创建集群实例,完成 hello world 实践. 上一篇试用 minikube 去搭建集群,这一篇将介绍通过 kubeadm 去操作. 命令行工 ...
 - 浅入Kubernetes(12):Deployment 的升级、回滚
		
目录 更新 上线 会滚 缩放 Deployment 直接设置 Pod 水平自动缩放 比例缩放 暂停 Deployment 上线 本篇内容讨论 Pod 的更新和回滚,内容不多. 更新 打开 https: ...
 - 浅谈 kubernetes service 那些事(上篇)
		
一.问题 首先,我们思考这样一个问题: 访问k8s集群中的pod, 客户端需要知道pod地址,需要感知pod的状态.那如何获取各个pod的地址?若某一node上的pod故障,客户端如何感知? 二.k8 ...
 
随机推荐
- 1004 Counting Leaves ——PAT甲级真题
			
1004 Counting Leaves A family hierarchy is usually presented by a pedigree tree. Your job is to coun ...
 - 我ssh框架遇到报错及处理方式
			
Exception encountered during context initialization - cancelling refresh attempt 修改hbm.xml后遇到的问题,错误可 ...
 - 500GJava/Hadoop/Spark/机器学习...视频教程免费分享 百度云持续更新
			
参加工作这么长时间了,工作中遇到了不少技能都是看视频教程学习的,相比较看书而言看视频确实比较容易理解.分享一下自己看过的和收集的视频教程. 资源包括: 大数据方面的Hadoop(云帆,小象学院,八斗学 ...
 - 解决springboot项目打成jar包部署到linux服务器后上传图片无法访问的问题
			
前言:目前大三,自己也在学习和摸索的阶段.在和学校的同学一起做前后端分离项目的时候,我们发现将后端打包成jar,然后部署到服务器中通过java -jar xxx.jar运行项目以后,项目中存在文件上传 ...
 - HDOJ-6621(线段树+二分法)
			
K-th Closest Distance HDOJ-6621 本题可以使用线段树解决,结点存本结点对应的所有元素,并按照从小打到排序 最后使用二分法求解答案.因为题目中有绝对值,所以需要使用两次查找 ...
 - io流(File类)
			
File类 创建一个file类(没有无参构造)的对象,并与文件进行关联 用File类来操作文件,代码如下: package com.bjsxt.test01; import java.io.File; ...
 - Linux入门视频笔记一(基本命令)
			
一.简单命令 1.date:当前时间 2.cal:当前日期(日历格式) ①cal 2019:2019年全年日历 ②cal 1 2019:2019年1月份 二.Linux文件结构 1.根目录:root( ...
 - VS2015上OpenCV-2.4.13安装与Hi35xx .jpg/.bmp格式转.bgr格式开发
			
因为Hi3559AV100后期深度学习开发需要用到.bgr格式的图片,而目前在手的一般为.jpg或.bmp格式的图片,下面随笔将给出基于OpenCV-2.4.13的格式转换,实现Hi35xx .jpg ...
 - 密码学系列之:csrf跨站点请求伪造
			
目录 简介 CSRF的特点 CSRF的历史 CSRF攻击的限制 CSRF攻击的防范 STP技术 Cookie-to-header token Double Submit Cookie SameSite ...
 - 网络对抗技术Exp2-后门原理与实践
			
后门概念 后门就是不经过正常认证流程而访问系统的通道. 哪里有后门呢? 编译器留后门 操作系统留后门 最常见的当然还是应用程序中留后门 还有就是潜伏于操作系统中或伪装为特定应用的专用后门程序. 下面是 ...