什么是service?

service是逻辑上的一组pod,一种可以访问pod的策略,而且其他pod可以通过service访问到这个service代理的pod,可以把它理解为传统架构中的反向代理。

相对于pod而言,service有一个固定的名称,不会发生改变,并且提供了负载均衡的功能。

通过service的定义,可以对客户端应用屏蔽后端pod实例数量及pod ip地址的变化,通过负载均衡策略实现请求到后端pod实例的转发,为客户端应用提供一个稳定的服务访问入口地址。

service实现的是微服务架构中的几个核心功能:全自动的服务注册、服务发现、服务负载均衡等。

创建一个service实例

apiversion: v1
kind: service
metadata:
  labels:
    app: nginx-svc
  name: nginx-svc
spec:
  ports:
  - name: http #service端口名称
    port: 80 #service自己的端口
    protocol: tcp #支持tcp udp sctp等
    targetport: 80 #后端应用接口
  - name: https
    port: 443
    protocol: tcp
    targetport: 443
  selector:
    app: nginx  #这个就是匹配规则,代理标签中有nginx的后端服务器
  sessionaffinity: none
  type: clusterip

执行上面的yaml文件,创建一个service

[root@k8s-master01 ~]# kubectl create -f nginx-svc.yaml 
service/nginx-svc created
[root@k8s-master01 ~]# kubectl get svc
name         type        cluster-ip      external-ip   port(s)          age
kubernetes   clusterip   10.96.0.1       <none>        443/tcp          9d
nginx-svc    clusterip   10.110.150.87   <none>        80/tcp,443/tcp   15s

我们通过访问svc地址就能访问到后端的nginx

[root@k8s-master01 ~]# curl 10.110.150.87
<!doctype html>
<html>
<head>
<title>welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: tahoma, verdana, arial, sans-serif; }
</style>
</head>
<body>
<h1>welcome to nginx!</h1>
<p>if you see this page, the nginx web server is successfully installed and
working. further configuration is required.</p>

<p>for online documentation and support please refer to
<a href="http://nginx.org/" rel="external nofollow" >nginx.org</a>.<br/>
commercial support is available at
<a href="http://nginx.com/" rel="external nofollow" >nginx.com</a>.</p>

<p><em>thank you for using nginx.</em></p>
</body>
</html>
  • 在同一个namespace中,其他pod访问svc只需要curl http://nginx-svc就可以
  • 跨namespace的话,需要在svc名称后加.namespace名称就可以了,使用需谨慎,没必要不推荐
  • 不建议通过ip地址访问,因为ip不是固定的,删除或重建后ip会随机生成

注意,以上内容只能在集群内部访问

集群外部访问svc

  • 希望在生产中使用某个固定的名称而非ip地址进行访问外部的中间件服务
  • 希望service指向另一个namespace中或其他集群中的服务
  • 某项目正在迁移至k8s集群,但是一部分服务仍然在集群外部,此时可以使用service代理外部的服务

创建代理外部应用的service实例

下面我们定义一个外部应用的service

apiversion: v1
kind: service
metadata:
  labels:
    app: nginx-svc-w
  name: nginx-svc-w
spec:
  ports:
  - name: http 
    port: 80 
    protocol: tcp 
    targetport: 80 
#  - name: https
#    port: 443
#    protocol: tcp
#    targetport: 443
#  selector:
#    app: nginx 
  sessionaffinity: none
  type: clusterip

区别就是少了这两个参数:

  selector:
    app: nginx 

创建成功后查看,可以发现虽然创建成功了但是没有endpoints

[root@k8s-master01 ~]# kubectl get svc
name          type        cluster-ip      external-ip   port(s)          age
kubernetes    clusterip   10.96.0.1       <none>        443/tcp          9d
nginx-svc     clusterip   10.110.150.87   <none>        80/tcp,443/tcp   31m
nginx-svc-w   clusterip   10.110.144.61   <none>        80/tcp           58s
[root@k8s-master01 ~]# kubectl get ep
name         endpoints                                                          age
kubernetes   192.168.10.2:6443,192.168.10.3:6443,192.168.10.4:6443              9d
nginx-svc    172.17.125.10:443,172.18.195.22:443,172.17.125.10:80 + 1 more...   31m

接下来我们需要手动创建一个自定义的endpoints借用存在的ep生成一个新的ep文件

[root@k8s-master01 ~]# kubectl get ep nginx-svc -o yaml > nginx-ep-w.yaml
apiversion: v1
kind: endpoints
metadata:
  labels:
    app: nginx-svc-w
  name: nginx-svc-w
  namespace: default
subsets:
- addresses:
  - ip: 110.242.68.3 # 代理的外部服务的地址
  ports:
  - name: http
    port: 80
    protocol: tcp

可以看到已经有外部的代理了

[root@k8s-master01 ~]# kubectl create -f nginx-ep-w.yaml 
endpoints/nginx-svc-w created
[root@k8s-master01 ~]# kubectl get ep
name          endpoints                                                          age
kubernetes    192.168.10.2:6443,192.168.10.3:6443,192.168.10.4:6443              9d
nginx-svc     172.17.125.10:443,172.18.195.22:443,172.17.125.10:80 + 1 more...   47m
nginx-svc-w   110.242.68.3:80                                                    11s

接下来试试能不能访问成功

# 直接访问的话是通的,返回值200
[root@k8s-master01 ~]# curl baidu.com -i
http/1.1 200 ok
date: mon, 14 feb 2022 01:43:18 gmt
server: apache
last-modified: tue, 12 jan 2010 13:48:00 gmt
etag: "51-47cf7e6ee8400"
accept-ranges: bytes
content-length: 81
cache-control: max-age=86400
expires: tue, 15 feb 2022 01:43:18 gmt
connection: keep-alive
content-type: text/html
# 通过访问service的ip可以看到也是通的,返回值200
[root@k8s-master01 ~]# curl 10.110.144.61 -i
http/1.1 200 ok
date: mon, 14 feb 2022 01:44:20 gmt
server: apache
last-modified: tue, 12 jan 2010 13:48:00 gmt
etag: "51-47cf7e6ee8400"
accept-ranges: bytes
content-length: 81
cache-control: max-age=86400
expires: tue, 15 feb 2022 01:44:20 gmt
connection: keep-alive
content-type: text/html

如果业务变更ep地址变了怎么办?只需要在ep中将代理的地址更换即可。

比如我们更换一个taobao的地址测试:

# 取出taobao的ip
[root@k8s-master01 ~]# ping taobao.com
ping taobao.com (140.205.94.189) 56(84) bytes of data.
64 bytes from 140.205.94.189 (140.205.94.189): icmp_seq=1 ttl=128 time=27.4 ms
64 bytes from 140.205.94.189 (140.205.94.189): icmp_seq=2 ttl=128 time=27.4 ms
# 修改ep的yaml文件:nginx-ep-w.yaml
apiversion: v1
kind: endpoints
metadata:
  labels:
    app: nginx-svc-w
  name: nginx-svc-w
  namespace: default
subsets:
- addresses:
  - ip: 140.205.94.189 # taobao
  ports:
  - name: http
    port: 80
    protocol: tcp
# 重新加载
[root@k8s-master01 ~]# kubectl replace -f nginx-ep-w.yaml 

访问测试一下看是否连通:这个返回501是没问题的。

[root@k8s-master01 ~]# curl 10.110.144.61 -i
http/1.1 501 not implemented
server: tengine
date: mon, 14 feb 2022 01:39:16 gmt
content-type: text/html
content-length: 583
connection: close

service反代外部域名

这个不说了,知道怎么配就行了。
service的yaml文件:

apiversion: v1
kind: service
metadata:
  labels:
    app: nginx-svc-wname
  name: nginx-svc-wname
spec:
  type: externalname
  externalname: www.baidu.com

然后创建就行了:

kubectl apply -f nginx-svc-wname.yaml

service 的类型:

clusterip:在集群内部使用,默认

externalname:通过返回定义的cname别名

nodeport:在所有安装了kube-proxy的节点上打开一个端口,此端口可以代理至后端pod,然后集群外部可以使用节点的ip地址和nodeport端口号访问到集群pod服务。端口取值范围默认30000-32767

loadbalancer:使用云服务商提供的负载均衡器公开服务

以上就是服务发现与负载均衡机制service实例创建的详细内容,更多关于服务发现与负载均衡service的资料请关注其它相关文章!