特性

  • Service 通过 label 关联对应的 Pod
  • Servcie 生命周期不跟 Pod 绑定,不会因为 Pod 重创改变 IP
  • 提供了负载均衡功能,自动转发流量到不同 Pod
  • 可对集群外部提供访问端口
  • 集群内部可通过服务名字访问

5.Service - 图1

创建 Service

创建 一个 Service,通过标签nginx-server跟对应的 Pod 关联上
nginx-service.yaml

  1. apiVersion: v1 # api版本声明
  2. kind: Service # 指定创建资源的类型
  3. metadata: # 资源的元数据/属性
  4. name: nginx-service # service名称
  5. namespace: demo # service的命名空间
  6. labels: # 定义标签
  7. name: nginx-service # service的标签名称
  8. spec: # 资源规格定义
  9. type: ClusterIP # 类型是NodePort。Service有四种type: ClusterIP(默认)、NodePort、LoadBalancer、ExternalName. 其中NodePort和LoadBalancer两类型的Services可以对外提供服务。
  10. selector: # 定义标签选择器
  11. app: nginx-server # 这里选择需要管理的pod的标签名
  12. ports: # 端口定义
  13. - port: 8081 # 集群内部通讯端口(自定义)
  14. targetPort: 80 # 容器对外暴露的端口,即containerPort

应用配置

$ kubectl apply -f nginx-service.yaml


查看服务

$ kubectl get svc -n demo
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
nginx-service   ClusterIP   10.244.52.159   <none>        8081/TCP   4m49s


查看服务详情 kubectl describe svc nginx-service -n demo,可以发现 Endpoints 是各个 Pod 的 IP,也就是他会把流量转发到这些节点。

$ kubectl describe svc nginx-service -n demo
Name:              nginx-service
Namespace:         demo
Labels:            name=nginx-service
Annotations:       <none>
Selector:          app=nginx-server
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.244.52.159
IPs:               10.244.52.159
Port:              <unset>  8081/TCP
TargetPort:        80/TCP
Endpoints:         172.16.126.62:80
Session Affinity:  None
Events:            <none>

服务的默认类型是ClusterIP,只能在集群内部访问,我们可以进入到调试 Pod 里面访问:

$ kubectl run busybox --image=radial/busyboxplus:curl -n demo -i --tty --rm
If you don't see a command prompt, try pressing enter.
[ root@busybox:/ ]$ curl -w '%{http_code}' http://nginx-service.demo.svc.cluster.local:8081
999

如果要在集群外部访问,可以通过端口转发实现(只适合临时测试用):
kubectl port-forward service/nginx-service --address 0.0.0.0 8888:8081 -n demo

如果你用 minikube,也可以这样minikube service nginx-service

对外暴露服务

上面我们是通过端口转发的方式可以在外面访问到集群里的服务,如果想要直接把集群服务暴露出来,我们可以使用NodePortLoadbalancer 类型的 Service

apiVersion: v1                        # api版本声明
kind: Service                         # 指定创建资源的类型
metadata:                             # 资源的元数据/属性
  name: nginx-service                 # service名称
  namespace: demo                     # service的命名空间
  labels:                             # 定义标签
    name: nginx-service               # service的标签名称
spec:                                 # 资源规格定义
  type: NodePort                      # 类型是NodePort。Service有四种type: ClusterIP(默认)、NodePort、LoadBalancer、ExternalName. 其中NodePort和LoadBalancer两类型的Services可以对外提供服务。
  selector:                           # 定义标签选择器
    app: nginx-server                 # 这里选择需要管理的pod的标签名
  ports:                              # 端口定义
    - protocol: TCP                   # 端口通讯协议
      port: 8081                      # 集群内部通讯端口(自定义)
      targetPort: 80                  # 容器对外暴露的端口,即containerPort
      nodePort: 32334                 # 所有的节点都会开放此端口,此端口供外部调用

应用配置 kubectl apply -f nginx-service.yaml
在节点上,我们可以 curl http://${node_ip}:32334 访问到应用

如果你是用 minikube,因为是模拟集群,你的电脑并不是节点,节点是 minikube 模拟出来的,所以你并不能直接在电脑上访问到服务

Loadbalancer 也可以对外提供服务,这需要一个负载均衡器的支持,因为它需要生成一个新的 IP 对外服务,否则状态就一直是 pendding,后面我们会讲更高端的 Ingress 来代替它。

总结

ClusterIP

默认的,仅在集群内可用

NodePort

暴露端口到节点,提供了集群外部访问的入口
端口范围固定 30000 ~ 32767

LoadBalancer

需要负载均衡器(通常都需要云服务商提供,裸机可以安装 metallb 测试)
会额外生成一个 IP 对外服务
K8S 支持的负载均衡器:负载均衡器

Headless

适合数据库
clusterIp 设置为 None 就变成 Headless 了,不会再分配 IP,后面会再讲到具体用法
官网文档