这篇文章主要来介绍 Service 元件
内容会谈到 Service 的功能与不同种 Services 类型与适合使用时机
在 k8s 丛集里, 每个 Pod 都有自己的内部 IP
内部 IP 是在 Pod 启动时动态给予的
因此, 当 Pod 重起之後内部 IP 的就会跟原本的不同
所以使用内部 IP 来存取 Pod 不是个好方法
Service 元件提供了一个固定 IP 给 Pod
所以一旦让 Pod 绑定 Service
就可以透过这个固定 IP 来存取 Pod
除了提供固定 IP 外, 当多个 Pod 挂载在同一个 Service 上时
Service 会对传入的 request 做负载平衡
由於 Pod 绑定 Service 所以对於其他相关的服务只依赖於 Service 这个抽象层
所以对 Pod 间做到了松耦合
而对於 Pod 来说对内与对外的接口都是透过 Service 来做处理
在 k8s 丛集中, Service 类别分为好几种, 以下就分别来介绍几种比较常见的
k8s 丛集, 预设的 Service 就是 ClusterIP Service
设定档范例如下:
apiVersion: v1
kind: Service
metadata:
name: microservice-one-service
spec:
selector:
app: microservice-one
ports:
- protocol: TCP
port: 3200
targetPort: 3000
上面设定档, 如果 kind 部份直接设定成 Service
则预设就是给 ClusterIP Service
而实际上关於 ClusterIP Service 给的固定 IP 值是看 Pode 所处的结点 IP 范围
如下图所示:
如果想要查询 Pod 所对应的 IP 可以使用以下指令
kubectl get pod -o wide
假设给定 Ingress, Service 与 Deployment 设定
ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: analytics.myapp.com
http:
paths:
- path: "/"
path: Prefix
backend:
service:
name: microservice-one-service
port:
number: 3200
service-clusterIP.yaml 如下
apiVersion: v1
kind: Service:
metadata:
name: microservice-one-service
spec:
selector:
app: microservice-one
ports:
- portocol: TCP
port: 3200
targetPort: 3000
deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: v
spec:
replicas: 2
...
template:
metadata:
labels:
app: microservice-one
则 ingress 透过 Service 的 name 找到到相对应的路由
而 Service 透过 selector 比对 Deployment 中的 Pod 对应的 labels 找到对应的 Pod
举例来说: 上面的 Service selector 为 app: microservice
而 Deployment 中 template 内的 metadata labels 也是相同的值
而 Service 要路由到 Pod 的 Port 则定义在 Service 的 TargetPort
封包路由如下图:
当 k8s 丛集建立 Service, 同时也会建立 Endpoint 物件
EndPoint 物件会跟 Service 具有相同名称, 除了 IP 资讯外多了一个 Port 资讯
下面是 k8s 官网 EndPoint 物件的设定档范例
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 192.0.2.42
ports:
- port: 9376
EndPoint 物件用来纪录哪个 Pod 属於哪一个 Service
Service 定义的对外的 Port 可以由使用者定义
targetPort 则必须要开放到 Pod 内 Container 实际服务的 Port
这类的 Service 代表同时会开放对应到两个 Port
举例来说: 假设 mongodb 除了本身外还有一个 mongodb-exporter 需要开发给 Prometheus app 存取, 设定档如下
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- name: mongodb
protocol: 27017
targetPort: 27017
- name: mongodb-exporter
protocol: 9216
targetPort: 9216
注意的是, 如果同时服务两个以上的 Port 就必须要设定名称
Headless 只会连接一个 Pod
设定档范例如下:
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017
当不需要做平衡负载时, 就可以使用 Headless Service
使用时机当想要只跟某个一特定的 Pod 做通讯
这种 Service 会使用在有状态的应用, 比如 资料库(mysql, mongodb), elastic search
因为有状态的应用每个 Pod 并非相同, 像是资料库只有 master Pod 才能做写入
这类 Service 的 IP 会直接回应 Pod IP address
当要建立 Service 时, type 有三种值可以设定 ClusterIP, NodePort, LoadBalancer
是 type 的预设值, 不需要特别设定
属於内部 Service, 外面读取不到
范例如下:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
就是对於每个结点 IP 开一个固定的 Port 来做端点
这类 Service 可以从外部经过以下形式的路径来存取:
NodeIP: 开启的 Port
设定档范例如下:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
假设一个 NodePort Service 定义如下:
apiVersion: v1
kind: Service
metadata:
name: ms-service-nodeport
spec:
type: NodePort
selector:
app: microservice-one
ports:
- protocol: TCP
port: 3200
targetPort: 3000
nodePort: 30008
则代表这个 microservice-one 服务的 Port 在定义的 nodePort 30008
而这个 NodePort 有一个范围限定 30000-32767
然而, NodePort Service 因为直接开放结点的 Port 给外部来连接
因此不是一个安全的作法
LoadBalancer 类别让 Service 可以透过 cloud provider 的负载平衡器来对外开放服务
其结构概念如下:
由结构图可以发现当 type 为 LoadBalancer Service 建立时, 相对应的 NodePort Service 与 ClusterIP Service 也会自动建立
设定档范例如下
apiVersion: v1
kind: Service
metadata:
name: my-service-loadbalancer
spec:
type: LoadBalancer
selector:
app: microservice-one
ports:
- protocol: TCP
port: 3200
targetPort: 3000
nodePort: 30010
注意的是, 这边的 nodePort 只开放给 loadBalancer 存取
loadBalancer 透过 nodePort 传递封包到结点然後透过对应的 ClusterIP Service 传递到对应的 Pod
一般而言, 实务上不太会使用 NodePort Service 在正式环境上, NodePort Service 只会在测试阶段拿来验证服务
在 k8s 丛集, 用来把应用对外开放的元件一般来说是使用 loadBalancer 类型的 Service 外面对接 cloud provider 提供的 loadbalancer 或是直接使用 Ingress 对接 ClusterIP Service 来使用
>>: Day13 - [丰收款] 将Django程序,放上Heroku!
资通安全责任等级 依照资通安全责任等级分级办法,由主管机关核定相对应之等级,按照等级决定导入系统之...
我们知道监督式学习(Supervised Learning)就是有一堆Label好的训练资料,而半监...
中台作为一种生态系统层级的架构,倚赖业界主流的技术系统,包含开源技术平台与框架: 业务中台:微服务─...
iT邦帮忙一直以来都是我查询技术问题的好夥伴;而铁人赛为IT界名闻遐迩的年度盛事。 在友人极力鼓吹报...
1. Dom元素无生成完毕,使用this.$nextTick 情境:Dom元素无生成 导致 refs...