一、Service 详解与基本用法
1. Service 的定义
Service 是 Kubernetes 的核心概念之一,创建一个 Service 可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。
完整 yaml 格式的 Service 定义文件如下:
apiVersion: v1 #版本号
kind: Service
metadata: #元数据
name: string #Service名称
namespace: string #命名空间,默认为default
labels: #自定义标签属性列表
- name: string
annotations: #自定义注解属性列表
- name: string
spec: #详细描述
selector: [] #Label Selector配置
type: string #Service的类型
clusterIP: string #虚拟服务的IP地址
sessionAffinity: string #是否支持Session
ports: #Service需要暴露的端口列表
- name: string #端口名称
protocol: string #端口协议,支持TCP/UDP,默认TCP
port: int #服务监听的端口号
targetPort: int #需要转发到后端Pod的端口号
nodePort: int
status:
loadBalancer: #外部负载均衡器
ingress:
ip: string #外部负载均衡器IP地址
hostname: string #主机名
2. Service 的基本用法
一般情况下,对外部提供服务的应用程序需要通过某种机制来实现。而对于容器应用来说,最简单的方式就是通过 TCP/UDP 机制及监听 IP 端口号来实现。
如下案例:创建一个基本功能的 Service;
apiVersion: v1
kind: ReplicationController
metadata:
name: mywebapp
spec:
replicas: 2
template:
metadata:
name: mywebapp
labels:
app: mywebapp
spec:
containers:
- name: mywebapp
image: tomcat
ports:
- containerPort: 8080
然后通过 kubectl get pods -l app=mywebapp -o yaml | grep podIP
命令获取 Pod 的 IP 地址和端口号,最后使用 curl podIP:8080
来访问 Tomcat 服务。
但是要知道直接通过 Pod IP 和端口号访问应用服务是不可靠的,因为如果 Pod 所在的 Node 发生了故障,那么 Pod 将会被 Kubenetes 重新调度到另一台 Node,这也就导致 Pod 地址发生了改变。
为了避免这个问题,我们可以先配置一个 yaml 文件来定义 Service,然后通过 kubectl create 来创建,这样就可以通过 Service 的地址访问后端的 Pod 了。
如下案例:先 vim
定义一个 Service 的 yaml 文件;
apiVersion: v1
kind: Service
metadata:
name: mywebapp-svc
spec:
ports:
- port: 8081
targetPort: 8080
selector:
app: mywebapp
然后通过命令 kubectl get svc
获取到我们所创建的 Service 的 IP 地址;
最后使用命令 curl IP:8081
即可访问 Pod。
这里我使用 8081 端口号是因为我们在定义 service 的文件当中是用 8081 来映射 8080 的。
3. 多端口 Service
有时一个容器应用也可能需要提供多个端口的服务,那么在 Service 的定义中就可以相应的将其设置为多个端口对应多个应用服务。格式如下:
apiVersion: v1
kind: Service
metadata:
name: mywebappService
spec:
ports:
- port: 8080
targetPort: 8080
name: web
- port: 8005
targetPort: 8005
name: management
selector:
app: mywebapp
4. 外部服务 Service
在某些特殊服务环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群中的服务作为服务的后端,这时可以通过创建一个 无Label Selector
的 Service 来实现。格式如下:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
-----------------------
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- IP: 目标pod IP
ports:
port: 8080
可以看到,无 Label Selector 的 Service 与普通 Service 的区别在于它没有了 selector 标签来指定 Label,而是需要创建一个 Endpoints
指定一个同名
的元数据来映射到自己要访问的 Pod 上。
二、Service 存在的意义
1. 防止 Pod 失联(服务发现)
通常一个网站包含前端和后端两个部分,通过在前端页面的操作访问后台服务。比如在前端有三个 Pod,后端也有三个 Pod,那么这个访问过程也就时通过前端的 Pod 进入到后端的 Pod 中,这最常用的方式就是通过 Pod 的 IP 地址进行访问。
但是 Pod 的 IP 地址并不固定,比如做了升级回滚、更新等操作,IP 地址都会改变。当访问了某一个 Pod,过了几分钟之后再次访问该 Pod 时,由于一些操作这个 IP 却不存在了,这也就是所说的 Pod 失联。
而 Service 恰恰解决了这个问题,具体实现方式就是每一个 Pod 在操作之前先在 Service 中(注册中心)使用自己的 IP 和名字做一个“注册”,当要进行访问时,先到 Service 中找到注册用的 IP,然后再访问。如果某个 Pod 的 IP 进行了改变,也会第一时间通知到 Service IP 的变化,使得其他服务再次访问时使用新的 IP。
2. 定义一组 Pod 访问策略(负载均衡)
如果说前端的某个 Pod 访问后端,而后端有若干个 Pod,那么到底访问哪个 Pod 就成了问题。这时候就需要 Service 发挥作用了,它使得访问请求可以平均的分配到不同的 Pod 中,也就是实现 负载均衡
。分配规则可以是根据 响应时间
、并发量
进行分配或者是根据 空闲时间
等进行分配,这也就实现了 Pod 访问策略的定义。
三、Pod 和 Service 的关系
首先,Pod 和 Service 也是通过 Label 和 selector 标签建立联系的,如下。文章来源:https://www.toymoban.com/news/detail-428539.html
#service中
selector:
app: redis
#pod中
labels:
app: redis
其次,Pod 的服务发现和负载均衡是通过 Service 来实现的。文章来源地址https://www.toymoban.com/news/detail-428539.html
四、Service 的三种常用类型
- ClusterIP:通常用于集群内部。
- NodePort:对外访问应用时使用。
- LoadBalancer:对外访问应用时使用,也可用于公有云环境中。
到了这里,关于【云原生 • Kubernetes】kubernetes 核心技术 - Service的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!