Service关键概念

为了方便访问Pod资源,k8s定义了一个统一访问入口:service资源对象。service是一个固定接入层,客户端可以通过访问service的IP和端口访问到service关联的后端pod。

为什么定义service对象?

1、pod ip经常变化,service是pod的代理,我们客户端访问,只需要访问service,就会把请求代理到Pod
2、pod ip在k8s集群之外无法访问,所以需要创建service,这个service可以在k8s集群外访问的。

Service对象解读

1.DNS插件(coreDNS):service的名称解析是依赖于dns附件的
2.网络插件(calico):kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件
3.kube-proxy组件:
始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态。

这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的

工作原理

1.k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象。
2.当Pod 地址发生变化时,endpoint也会随之发生变化。
3.service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

资源清单解释

# kubectl explain service.spec
allocateLoadBalancerNodePorts   <boolean>
clusterIP   <string>      #动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了
clusterIPs  <[]string>
externalIPs <[]string>
externalName    <string>
externalTrafficPolicy   <string>
healthCheckNodePort <integer>
ipFamilies  <[]string>
ipFamilyPolicy  <string>
loadBalancerIP  <string>
loadBalancerSourceRanges    <[]string>
ports   <[]Object>              #定义service端口,用来和后端pod建立联系
publishNotReadyAddresses    <boolean>
selector    <map[string]string> #通过标签选择器选择关联的pod有哪些
sessionAffinity <string>
sessionAffinityConfig   <Object>
#service在实现负载均衡的时候还支持sessionAffinity,sessionAffinity
什么意思?会话联系,默认是none,随机调度的(基于iptables规则调度的);如果我们定义sessionAffinity的client ip,那就表示把来自同一客户端的IP请求调度到同一个pod上
topologyKeys    <[]string>
type    <string>                #定义service的类型# kubectl explain service.spec.type
【四类service】
ExternalName, ClusterIP, NodePort, and LoadBalancer# kubectl explain service.spec.ports
appProtocol <string>
name    <string>             #定义端口的名字
nodePort    <integer>        #宿主机上映射的端口,比如一个Web应用需要被k8s集群之外的其他用户访问,那么需要配置type=NodePort,若配置nodePort=30001,那么其他机器就可以通过浏览器访问scheme://k8s集群中的任何一个节点ip:30001即可访问到该服务,例如http://192.168.1.63:30001。如果在k8s中部署MySQL数据库,MySQL可能不需要被外界访问,只需被内部服务访问,那么就不需要设置NodePort
port    <integer> -required-  #service的端口,这个是k8s集群内部服务可访问的端口
protocol    <string>          #协议(TCP默认、UDP、SCTP)
targetPort  <string>          #需要绑定的pod的端口

service的四种类型

## ExternalName
适用于k8s集群内部容器访问外部资源,它没有selector,也没有定义任何的端口和Endpoint。
以下Service 定义的是将prod名称空间中的my-service服务映射到my.database.example.com
kind: Service
apiVersion: v1
metadata:name: my-servicenamespace: prod
spec:type: ExternalNameexternalName: my.database.example.com
当查询主机 my-service.prod.svc.cluster.local 时,群集DNS将返回值为my.database.example.com的CNAME记录。
## ClusterIP
通过k8s集群内部IP暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的ServiceType。
## NodePort
通过每个Node节点上的IP和静态端口暴露k8s集群内部的服务。通过请求<NodeIP>:<NodePort>可以把请求代理到内部的pod。Client----->NodeIP:NodePort----->Service Ip:ServicePort----->PodIP:ContainerPort。
## LoadBalancer
使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterIP 服务。

字段详述

类型是ClusterIP

## 使用Deployment创建Pod,副本数是2,通过Pod的IP访问资源
vim deploy-test-myapp.yaml
# curl <pod-ip>:<80>## 创建service,通过ClusterIP访问资源
vim svc-test-myapp.yaml
kubectl apply -f svc-test-myapp.yaml
# curl <cluster-ip>:<80># 查看详细信息,看到EndPoints有两个IP(对应副本数)
kubectl describe svc my-nginx
kubectl get ep my-nginx
apiVersion: v1
kind: Service
metadata:name: my-nginxlabels:run: my-nginx
spec:type: ClusterIPports:- port: 80          #service的端口,暴露给k8s集群内部服务访问protocol: TCPtargetPort: 80    #pod容器中定义的端口selector:run: my-nginx     #选择拥有run=my-nginx标签的pod 【VIP】
## 资源转发流程
1.service可以对外提供统一固定的ip地址,并将请求重定向至集群中的pod。2.其中“将请求重定向至集群中的pod”就是通过endpoint与selector协同工作实现。3.selector是用于选择pod,由selector选择出来的pod的ip地址和端口号,将会被记录在endpoint中。endpoint便记录了所有pod的ip地址和端口号。4.当一个请求访问到service的ip地址时,就会从endpoint中选择出一个ip地址和端口号,然后将请求重定向至pod中。(具体把请求代理到哪个pod,需要的就是kube-proxy的轮询实现的)5.service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。

类型是NodePort

## 创建Pod资源## 创建service资源,允许宿主机访问
vim svc-test-NodePort.yaml##【验证】
通过宿主机浏览器访问myapp的接口资源:<ip>:<30380>/path
apiVersion: v1
kind: Service
metadata:name: my-nginx-nodeportlabels:run: my-nginx-nodeport
spec:type: NodePortports:- port: 80protocol: TCPtargetPort: 80nodePort: 30380selector:run: my-nginx-nodeport
服务请求走向:
Client-node ip:30380->service ip:80-pod ip:container port Client ->192.168.1.63:30380->10.100.156.7:80->pod ip:80

类型是ExternalName

## 跨名称空间访问
#default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务## 创建名称空间test
kubectl create ns test## 创建第一个Pod资源
vim deploy-test-busybox.yaml
## 创建第一个service资源
# 该文件中指定了到 nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。
vim svc-test-ExternalName.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: client
spec: replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboxcommand: ["/bin/sh","-c","sleep 36000"]
---
apiVersion: v1
kind: Service
metadata:name: client-svc
spec:type: ExternalNameexternalName: nginx-svc.test.svc.cluster.localports:- name: httpport: 80targetPort: 80
## 创建第二个Pod资源
vim deploy-test-nginx.yaml
## 创建第二个service资源
vim svc-test-normal.yaml## 【验证】下面两个请求结果一致,说明client-svc已经将请求转到了nginx-svc
kubectl exec -it  client-76b6556d97-xk7mg -- /bin/sh
wget -q -O - client-svc.default.svc.cluster.local
wget -q -O - nginx-svc.test.svc.cluster.local
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxnamespace: test
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:name: nginx-svcnamespace: test
spec:selector:app: nginxports:- name: httpprotocol: TCPport: 80targetPort: 80

实践案例:引用外部MySQL

## 安装MySQL
yum install mariadb-server.x86_64 -y
systemctl start mariadbvim svc-mysql.yaml
vim ep-mysql.yaml
apiVersion: v1
kind: Service
metadata:name: mysql
spec:type: ClusterIPports:- port: 3306---
apiVersion: v1
kind: Endpoints
metadata:name: mysql
subsets:
- addresses:- ip: 10.11.2.58ports:- port: 3306
# kubectl describe svc mysql
Name:              mysql
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"mysql","namespace":"default"},"spec":{"ports":[{"port":3306}],"ty...
Selector:          <none>
Type:              ClusterIP
IP:                10.97.86.201
Port:              <unset>  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.11.2.58:3306
Session Affinity:  None

三种IP

【1】Node Network(节点网络):物理节点或者虚拟节点的网络,如ens33接口上的网路地址
【2】Pod network(pod 网络),创建的Pod具有的IP地址Node Network和Pod network这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的
【3】Cluster Network(集群地址,也称为service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。

kube-proxy了解

Service只是将应用对外提供服的方式做了抽象,真正的应用跑在Pod中,我们的请求转发到NodePort上,然后kube-proxy解析存储在iptables或者IPVS中的规则,来实现负载均衡。kube-proxy实现了内部从pod到service和外部的从node port向service的访问。

1、kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。
2、kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也可以称为是Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。

kube-proxy三种工作模式

【Userspace方式】
Client Pod要访问Server Pod时,它先将请求发给内核空间中的service iptables规则,由它再将请求转给监听在指定套接字上的kube-proxy的端口,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求转发给内核空间中的service ip,由service iptables将请求转给各个节点中的Server Pod。
【iptables方式】
客户端IP请求时,直接请求本地内核service ip,根据iptables的规则直接将请求转发到到各pod上,因为使用iptable NAT来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存上万的Service/Endpoint,那么Node上的iptables rules将会非常庞大,性能还会再打折
【ipvs方式】
客户端请求时到达内核空间时,根据ipvs的规则直接分发到各pod上。kube-proxy会监视Service对象和Endpoints,调用netlink接口以相应地创建ipvs规则并定期与Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。与iptables类似,ipvs基于netfilter的hook功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量,并且在同步代理规则时具有更好的性能。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wtCfxFt7-1658732730761)(./pic/kube-proxy-01.png)]

[1]kube-proxy都通过watch的方式监控着apiserver写入etcd中关于Pod的最新状态信息。
[2]它一旦检查到一个Pod资源被删除了或新建了,它将立即将这些变化,反应再iptables或ipvs规则中。
[3]以便iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况。
[4]自k8s1.11以后,service默认使用ipvs规则,若ipvs没有被激活,则降级使用iptables规则。

iptables规则分析

在k8s创建的service,虽然有ip地址,但是service的ip是虚拟的,不存在物理机上的,是在iptables或者ipvs规则里的。通过上面可以看到之前创建的service,会通过kube-proxyiptables中生成一个规则,来实现流量路由,有一系列目标为 KUBE-SVC-xxx 链的规则,每条规则都会匹配某个目标 ip 与端口。也就是说访问某个 ip:port 的请求会由 KUBE-SVC-xxx 链来处理。这个目标 IP 其实就是service ip。

# 查看ClusterIP
kubectl get svc
# 根据IP查找
iptables -t nat -L | grep 10.111.145.211KUBE-MARK-MASQ  tcp  -- !10.244.0.0/16        10.111.145.211       /* default/springboot:server cluster IP */ tcp dpt:tproxy
KUBE-SVC-N6LLN4RK7MJQ5NNI  tcp  --  anywhere             10.111.145.211       /* default/springboot:server cluster IP */ tcp dpt:tproxy# 根据上述信息继续查询
iptables -t nat -S | grep KUBE-SVC-N6LLN4RK7MJQ5NNI-N KUBE-SVC-N6LLN4RK7MJQ5NNI
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/springboot:server" -m tcp --dport 31180 -j KUBE-SVC-N6LLN4RK7MJQ5NNI
-A KUBE-SERVICES -d 10.111.145.211/32 -p tcp -m comment --comment "default/springboot:server cluster IP" -m tcp --dport 8081 -j KUBE-SVC-N6LLN4RK7MJQ5NNI
-A KUBE-SVC-N6LLN4RK7MJQ5NNI -m comment --comment "default/springboot:server" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-YG5CH4BKPZQUH2S6
-A KUBE-SVC-N6LLN4RK7MJQ5NNI -m comment --comment "default/springboot:server" -j KUBE-SEP-WVMWCPQS2EJEYDWI# 查找出对应Pod的端口和IP
iptables -t nat -S | grep KUBE-SEP-WVMWCPQS2EJEYDWI
iptables -t nat -S | grep KUBE-SEP-YG5CH4BKPZQUH2S6-N KUBE-SEP-YG5CH4BKPZQUH2S6
-A KUBE-SEP-YG5CH4BKPZQUH2S6 -s 10.244.30.91/32 -m comment --comment "default/springboot:server" -j KUBE-MARK-MASQ
-A KUBE-SEP-YG5CH4BKPZQUH2S6 -p tcp -m comment --comment "default/springboot:server" -m tcp -j DNAT --to-destination 10.244.30.91:8081
-A KUBE-SVC-N6LLN4RK7MJQ5NNI -m comment --comment "default/springboot:server" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-YG5CH4BKPZQUH2S6

coreDNS了解

属于k8s的一个DNS插件服务,是一种常见的服务发现手段。

验证coredns

# 安装dig
vim pod-dig.yaml
# 解析dns,如有以下返回说明dns安装成功
kubectl exec -it dig -- nslookup kubernetesServer:      10.96.0.10
Address:    10.96.0.10#53
Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1
apiVersion: v1
kind: Pod
metadata:name: dignamespace: default
spec:containers:- name: digimage:  xianchao/dig:latestcommand:- sleep- "3600"imagePullPolicy: IfNotPresentrestartPolicy: Always

K8S学习笔记之Service和kube-proxy相关推荐

  1. K8S 学习笔记三 核心技术 Helm nfs prometheus grafana 高可用集群部署 容器部署流程

    K8S 学习笔记三 核心技术 2.13 Helm 2.13.1 Helm 引入 2.13.2 使用 Helm 可以解决哪些问题 2.13.3 Helm 概述 2.13.4 Helm 的 3 个重要概念 ...

  2. k8s学习笔记一集群部署

    k8s安装笔记 基础环境配置 修改主机名: 修改hosts配置文件 安装依赖包 关闭防火墙并未Iptables设置空规则 关闭swap分区和linux虚拟内存 调整内核参数 调整系统时区 关闭系统不需 ...

  3. docker,k8s学习笔记汇总

    整理了下博客里关于docker和k8s的文章,方便查看 docker学习笔记(一)docker入门 docker学习笔记(二)创建自己的镜像 docker学习笔记(三)docker中的网络 docke ...

  4. k8s组件说明:kubelet 和 kube proxy

    k8s的node节点需要安装三个组件:docker/kubelet/kube proxy pod是存储容器的容器,但容器不止docker一种. CRI:container runtime interf ...

  5. 最详细的 K8S 学习笔记总结(2021最新版)

    虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理.资源调度.文件管理等等.那么在这样一个百花齐放的容器时代涌现出了很多解决方案,比如 Mesos.Swarm.Kubern ...

  6. k8s学习笔记(一)

    第一章 kubernetes介绍 本章节主要介绍应用程序在服务器上部署方式演变以及kubernetes的概念.组件和工作原理. 应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署 ...

  7. k8s学习笔记- 部署prometheus

    1.Prometheus概述 Prometheus是一个开源监控系统,它前身是SoundCloud的警告工具包.从2012年开始,许多公司和组织开始使用Prometheus. 该项目的开发人员和用户社 ...

  8. [k8s 学习笔记]

    摘自知乎: k8s入门及实践 一. k8s简介 K8S 是Kubernetes的全称,官方称其是: Kubernetes is an open source system for managing c ...

  9. k8s学习笔记(10)--- kubernetes核心组件之controller manager详解

    kubernetes核心组件之controller manager详解 一.Controller Manager简介 1.1 Replication Controller 1.2 Node Contr ...

最新文章

  1. 给自己的程序添加BugReport
  2. Cannot connect to the Docker daemon. Is the docker daemon running on this host?
  3. Collect proper diagnostic data is very important
  4. 转 框架页有Frame、Iframe、Frameset 3个标记,初学者容易将三者混淆,下面分别讲解三者的区别。...
  5. SAP全球技术研发者大会上海站电子票欣赏
  6. 点击事件为什么会失效_1917年的法蒂玛事件,为什么会被称为最为惊悚的UFO目击事件?...
  7. 技术动态 | 67 亿美金搞个图,创建知识图谱的成本有多高你知道吗?
  8. 解决PowerPoint英语课件配音难同步的问题
  9. 为了离去的纪念——google
  10. 控制器(下) -运维笔记
  11. 虚拟电脑键盘app_App发布倒计时
  12. android后台倒计时,android倒计时封装(活动进入后台,倒计时依然能正常计时)...
  13. Hive grouping sets 多维度交叉清洗数据
  14. 期刊级别应该是怎样划分的呢?
  15. 时间序列分析 | 相似性度量基本方法
  16. 2017年全球IDC、光器件、100G及400G数通模块市场预测
  17. cuda 原子锁多线程操作通用原子操作
  18. 山东省农商行计算机真题,2018山东农商行招聘考试题库:计算机试题三
  19. 浪潮m6智能服务器,浪潮全新M6服务器满足智慧时代算力需求
  20. TCP/IP协议栈Lwip的设计与实现:之三

热门文章

  1. 超越BERT、GPT------屏蔽序列到序列预训练MASS(原理篇)
  2. 为什么程序员不那么爱说话
  3. Python函数-int()
  4. Luogu P3054 [USACO12OPEN]跑圈Running Laps
  5. poj 3230 Travel
  6. 邮件伪造测试-Swaks
  7. c语言 扫描码,一种全键盘扫描码的获取方法
  8. es模糊查询与精准查询混用、距离排序、返回距离
  9. oracle 完全检查点条件,ORACLE Checkpoint(检查点)
  10. 项目冲刺 Sixth