5、Kubernetes Service

171 阅读4分钟

Service是Kubernetes最核心的概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求进行负载分发到后端的各个容器应用上。

1、Service的四种类型

1、ClusterIP: 默认类型,自动分配一个仅cluster内部可以访问的虚拟ip。

2、NodePort: 在clusterip基础上为service在每台机器上绑定一个端口,这样就可以通过Nodeip:port方式来访问该服务。

3、LoadBalancer:在NodePort基础上,接触cloud provider创建一个外部负载均衡器,并将请求转发到nodeip:port。

4、ExternalName: 把集群外部的服务引入到集群内部,在集群内中直接使用,没有任何类型的代理被创建。

Endpoint 介绍:

Endpoint是可被访问的服务端点,即一个状态为running的Pod,它是Service访问的落点,只有Service关联的Pod才可能成为Endpoint。

Endpoint、Service 和 Pod 的关系:

Endpoints表示一个Service对应的所有Pod副本的访问地址。

Node上的Kube-proxy进程获取每个Service的Endpoints,实现Service的负载均衡功能。

ReplicaSet参数控制Pod的数量,ReplicaSet被Deployment配置文件管理。

Deployment控制Pod应用的升级、回滚,当然也能控制pod的数量。

Service为同一类label的Pod提供一个统一固定入口,负责将前端请求均衡的转发给Pod中。

2、Service 部署

1、创建Deployment + ClusterIP Service

 apiVersion: apps/v1
 # 声明一个Deployment资源对象
 kind: Deployment
 metadata: 
   # 定义 pod 名称
   name: demo1-nginx-deployment
 spec:
   # 通过 replicas 声明 pod 个数是4
   replicas: 4
   # 通过标签选择被控制的 pod   
   selector:
     matchLabels:
       name: demo-nginx
   # 在 template 中定义 pod  
   template: 
     metadata:
     # 给pod打上标签
       labels:
         name: demo-nginx
         type: pod
         release: stable
     spec:
       containers:
       # 声明容器名称,注意不是pod名称,pod名称应该定义在metadata中
       - name: demo-nginx-container
         image: nginx
         ports:
         - name: http
           containerPort: 80
 # 在一个yaml文件中通过---分割多个资源对象
 ---
 apiVersion: v1
 # 声明一个Service资源对象
 kind: Service
 metadata: 
   name: demo1-nginx-service
   labels:
     name: demo-nginx
     type: clusterip
     release: stable
 spec:
   # 设置 nodePort 映射到物理机,同时这是Service的类型为nodePort
   # 如果不设置 type 则为默认的 ClusterIP 类型
   # type: NodePort
   # demo1-nginx-service 选择标签包含 demo-nginx 的pod
   selector: 
     name: demo-nginx
   ports:
   - protocol: TCP
     name: http
     # service 的监听端口
     port: 80
     # 转发到 pod 的端口
     targetPort: 80
     # 暴露在服务器上的端口
     # nodePort: 30080
 [root@k8s-1 k8s-yaml]# kubectl apply  -f test-service.yaml
 deployment.apps/demo1-nginx-deployment created
 service/demo1-nginx-service created

查看容器状态:

image-20220112155439659

使用 kubectl describe svc demo1-nginx-service 查看 demo1-nginx-service 的详细信息,我们可以知道 demo1-nginx-service的 IP是10.98.135.41,访问 10.98.135.41:80 会将请求转发到 10.244.1.47:80,10.244.2.46:80,10.244.2.47:80 + 1 more... 四个 real server 上。

image-20220112155904085

测试服务是否可用:

image-20220112155627879

2、创建Deployment + NodePort Service

将上方 ClusterIP Service 的yaml配置文件添加两行配置。可以将ClusterIP升级为NodePort Service。

   Service.spec.type
   # 设置 nodePort 映射到物理机,同时这是Service的类型为nodePort
   type: NodePort
   
   Service.spec.ports.nodePort
   # 暴露在服务器上的端口
   nodePort: 30080

使用NodePort类型,将服务暴露出来,可以通过 http://ip:30080 来进行访问

tips:

1、对于Service 的升级操作,从ClusterIP升级为NodePort是可以的,但是不建议从NodePort降级为ClusterIP,容易发生问题,建议重新创建。

2、因为Service其实是iptables或ipvs的转发规则,不支持ICMP协议,所以是没有办法ping通的。

3、LoadBalancer

LoadBalancer 和 NodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导入流量。

4、ExternalName

这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:www.baidu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

 apiVersion: v1
 kind: Service
 metadata:
   # svc 的名称,也是内部访问的域名
   name: test-external
   # 标签
   labels:
     name: test-external
     type: externalname
     release: stable
   # 所属命名空间
   namespace: default
 spec:
   # Service 的类型
   type: ExternalName
   # 外部地址,可以使用ip或者域名
   externalName: www.baidu.com

检测 ExternalName 是否ok:

 [root@k8s-1 k8s-yaml]# kubectl run test-pod -it --rm --image=busybox:1.28.3 -n default
 / # nslookup test-external
 Server:    10.96.0.10
 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
 
 Name:      test-external
 Address 1: 163.177.151.110
 Address 2: 163.177.151.109
 
 # 163.177.151.110、163.177.151.109 就是百度的ip

当查询主机 test-external 时,集群的 DNS 服务将返回一个 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。