Service
Service 是 某种抽象封装 的 Pod ,因此Service也有其IP
Service 也是 Pod ,因此他们只能在k8s集群内部被访问到,如果想要从外部访问
- 用 Ingress
- 用 NodePort
服务发现:在微服务架构中,服务可能会动态地注册和注销,服务的端口可能会变化。服务发现机制允许服务实例在启动时注册自己的endpoint信息,包括IP和端口,客户端通过服务发现机制来获取最新的服务endpoint信息。
原理#
看下面解析配合上面的图片
各个部分
Service
每个Service都有其IP
- 创建 Service 时,会创建一个服务名即
nginx-svc
, 同时他会绑定一个端口号 :80:32057
:80
是pod暴露出来的端口号,:32057
是Service监听的端口号当使用
NodePort
类型的 Service 时,外部流量通过 Node IP(也就是192.168.113.120) 和指定的端口(NodePort:32057)访问服务。这允许从集群外部访问集群内的服务。Service 通过选择器(selector)与一组 Pod 相关联,它将流量路由到这些 Pod,即
selector: app=nginx-deploy
Service 实际上是连接这整个集群的所有Node的,因此但我访问
192.168.113.120:32057
,192.168.113.121:32057
,192.168.113.122:32057
效果是一样的
- 创建 Service 时,会创建一个服务名即
Endpoint
- 这个控制器是在Service被创建的时候自动会被创建,主要管理的是对 PodIP 和 ServiceIP 的映射,
address:10.244.36.107
就表示对于selector: app=nginx-deploy
这个服务对应的 PodIP 是这个address- Endpoint中还会显示出Pod的
targetPort:80
,表示Pod暴露出来的端口是80端口 - Endpoint的服务名称通常与Service一致为
nginx-svc
kube-proxy
代理,为什么Endpoint会知道Pod的IP,就是靠这个ProxyIP来访问的
访问任何节点的
80
端口将通过 kube-proxy 转发到后端的 Pod — 任何要访问到Pod都需要 kube-proxy的代理各个IP
- NodeIP : 也就是各个节点的IP,可以简单理解为主机IP
- PodIP : 这个是PodIP,这个Pod在创建销毁过程中会不断变化
- ServiceIP: 这个是Service的IP,通过访问ServiceIP来转化到Pod的IP
- ClusterIP: 这是一个虚拟的IP地址,用于在集群内部访问 Service。
NodePort
上面讲的东西都是k8s内部的网络访问,但是这个NodePort是提供外部访问的,他相当于是在Node上面开了一个Port,然后我们可以通过这个NodePort来访问这个Pod
访问流程
如果 Node1 -> Node2
也就是 Node1 -> service -> endpoint -> kube-proxy -> Node2
配置文件#
1 | apiVersion: v1 |
如果要查看:
1 | kubectl get svc #service |
代理外部服务(可以不看,yzy说一般不干这事)#
实现service外部服务的一个访问
即请求pod的时候能够通过service访问到外部的服务
Pod ------> Service ------> 外部服务
第一种需求:
我们应用环境有开发环境和测试环境,每个环境有不同的IP,我想要的就是不改变Pod应用程序内部的代码结构,只改变Service中的内容从而改变选择不同的环境
第二种需求:
项目迁移到k8s时,mysql的迁移不好进行,不能直接实现迁移
就导致我们有一部分的mysql的业务还得在k8s集权之外实现,所以需要代理外部服务
现在就有两种访问形式
- 直接通过Pod来访问外部服务 (不可取)
- Pod->service->外部服务 这个形式来访问 (可取)
why: 第一种形式需要在Pod内部写上mysql的Pod不方便,第二种只需要改变Service内部的mysql配置,因此第二种更方便,同时如果我有几十个mysql,你就会发现我动一发而改全身,非常麻烦。
究其原因还是关于解耦的问题 ,核心都是通过Service这个中间人的方式灵活设置转换这些配置
实现方式:
当我编写 Service 的时候,不编写 selector , 也就不会自动创建 Endpoint ,然后我们自己创建 Endpoint
首先我们进入
/home/echin/services
创建相应的services-svc-external.yaml
1
2
3
4
5
6
7
8
9
10apiVersion: v1
kind: Service
metadata:
name: nginx-svc-external
spec:
type: ClusterIP # 将 type 设置在 spec 层级下
ports:
- port: 80 # Service 监听的端口,在内网访问时使用
targetPort: 80 # Pod 暴露的端口
name: web # 端口的名字hhhyc@hhhyc:~/services$ sudo kubectl create -f services-svc-external.yaml \service/nginx-svc-external created
可以发现我们创建了 Service 但是并没有创建 endpoint1
2
3
4
5
6
7
8
9
10
11
12
* ````sh
hhhyc@hhhyc:~/services$ sudo kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 3d16h
nginx ClusterIP None <none> 80/TCP 19h
nginx-svc-external ClusterIP 10.43.204.225 <none> 80/TCP 32s
hhhyc@hhhyc:~/services$ sudo kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.21.133.183:6443 3d16h
nginx <none> 19h配置一下
endpoint.yaml
vim nginx-ep-external.yaml
直接创建,配置1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: Endpoints
metadata:
name: nginx-svc-external # 与 Service 名称对应
subsets:
- addresses:
- ip: 120.78.159.117 # 这里写上我们要代理的外部服务的Ip地址,一般来说这里>时k8s内部的地址
ports:
- name: web
port: 80
protocol: TCP注意
- 这里的
addresses
是目标ip,就是要访问的外部服务ip - 下面这个
ports:name
需要和对应的 Service中的Port:name
相对应 metadata:name
也要和 Service 中的相对应
- 这里的
创建 endpoint
1
2hhhyc@hhhyc:~/services$ sudo kubectl create -f nginx-ep-external.yaml
endpoints/nginx-svc-external created查看是否创建成功
1
2
3
4
5hhhyc@hhhyc:~/services$ sudo kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.21.133.183:6443 3d16h
nginx <none> 20h
nginx-svc-external 120.78.159.117:80 13s查看 Service 服务发现目标ip已经修改完毕
1
2
3
4
5
6
7
8
9
10
11
12
13
14hhhyc@hhhyc:~/services$ sudo kubectl describe ep nginx-svc-external
Name: nginx-svc-external
Namespace: default
Labels: <none>
Annotations: <none>
Subsets:
Addresses: 120.78.159.117
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
web 80 TCP
Events: <none>最后访问
但是视频中教学的是有个脚本,我跳了一些,就访问不了哈哈哈
Type#
ClusterIP
只能在集群内部使用,不配置类型的话默认是 ClulsterIP
ExternalName
这个就是刚才的哪个访问外部服务的例子,我们给他一个域名,他就能自动跳转到那个域名
NodePort(不建议)
在所有的Node上开个端口,所有节点上都可以访问端口,
如果要用一般这个也不写死,随机一个Port,不会重复,但还是不建议访问
LoadBlancer(不建议)
使用云服务商来访问Pod
感觉有必要总结一下我的Service#
- Service 是 Pod ,因此有IP,pod
- Service 是用来服务发现的,所以相当于他是个中间人,Pod要找其他的Pod就通过Service来实现
- Pod,service 都是在 k8s集群 内部的实现,这里的访问只有东西流量的访问,没有外部参与
这样子理解会好很多–建议多看看配置文件和敲命令行理解