kubernetes-服务发现service(九)

2020-09-30 11:20:21 浏览数 (1)

service

    •防止Pod失联     •定义一组Pod的访问策略     •支持ClusterIP,NodePort以及LoadBalancer三种类型     •Service的底层实现主要有iptables和ipvs二种网络模式

pod与service的关系:

    •通过label-selector相关联     •通过Service实现Pod的负载均衡(TCP/UDP 4层)

每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式

kube-proxy 这个组件始终监视着apiserver中有关service的变动信息,获取任何一个与service资源相关的变动状态,通过watch监视,一旦有service资源相关的变动和创建,kube-proxy都要转换为当前节点上的能够实现资源调度规则(例如:iptables、ipvs)

service代理模式

iptables代理模式:

客户端IP请求时,直接请求本地内核service ip,根据iptables的规则直接将请求转发到到各pod上,因为使用iptable NAT来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存在上万的Service/Endpoint,那么Node上的iptables rules将会非常庞大,性能还会再打折扣。

ipvs代理模式:

客户端IP请求时到达内核空间时,根据ipvs的规则直接分发到各pod上。kube-proxy会监视Kubernetes Service对象和Endpoints,调用netlink接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。

service类型
  • ClusterIP通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType
  • NodePort通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个 NodePort 服务。
  • LoadBalancer使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。

 ClusterIP

代码语言:javascript复制
[root@k8s-master1 nginx]# vim nginx-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx

[root@k8s-master1 nginx]# kubectl apply -f nginx-service.yaml
service/nginx-service created
[root@k8s-master1 nginx]# kubectl get svc
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.0.0.1     <none>        443/TCP   6d15h
nginx-service   ClusterIP   10.0.0.6     <none>        80/TCP    14s

service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。
[root@k8s-master1 nginx]# kubectl get pod -l app=nginx
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5fc86c987f-jdpkv   1/1     Running   0          21m
nginx-deployment-5fc86c987f-scns6   1/1     Running   0          21m
nginx-deployment-5fc86c987f-wwvlx   1/1     Running   0          21m
[root@k8s-master1 nginx]# kubectl get ep
NAME            ENDPOINTS                                      AGE
kubernetes      192.168.0.123:6443,192.168.0.124:6443          6d15h
nginx-service   172.17.32.3:80,172.17.73.3:80,172.17.73.4:80   76s

service只要创建完,就会在dns中添加一个资源记录进行解析,添加完成即可进行解析。

NodePort

代码语言:javascript复制
[root@k8s-master1 ~]# kubectl get pod --show-labels
NAME                   READY   STATUS    RESTARTS   AGE   LABELS
myapp-9b4987d5-hk5n9   1/1     Running   0          82s   pod-template-hash=9b4987d5,run=myapp
myapp-9b4987d5-ngvbk   1/1     Running   0          82s   pod-template-hash=9b4987d5,run=myapp
myapp-9b4987d5-r7q49   1/1     Running   0          82s   pod-template-hash=9b4987d5,run=myapp

[root@k8s-master1 ~]# vim myapp-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  type: NodePort
  ports: 
  - port: 80
    targetPort: 80
    nodePort: 37695

[root@k8s-master1 ~]# kubectl create -f myapp-service.yaml 
service/myapp created
[root@k8s-master1 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP        6d16h
myapp        NodePort    10.0.0.214   <none>        80:37695/TCP   8m14s

通过NodePort方式已经实现了从集群外部端口进行访问
[root@k8s-master1 ~]# while true;do curl http://192.168.0.125:37695/hostname.html;sleep 1;done
myapp-9b4987d5-ngvbk
myapp-9b4987d5-hk5n9
myapp-9b4987d5-r7q49
myapp-9b4987d5-ngvbk
myapp-9b4987d5-hk5n9
myapp-9b4987d5-r7q49
myapp-9b4987d5-ngvbk

会话保持

代码语言:javascript复制
[root@k8s-master1 ~]# vim myapp-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  sessionAffinity: ClientIP
  type: NodePort
  ports: 
  - port: 80
    targetPort: 80
    nodePort: 37695

[root@k8s-master1 ~]# kubectl create -f myapp-service.yaml 
service/myapp created

[root@k8s-master1 ~]# while true;do curl http://192.168.0.125:37695/hostname.html;sleep 1;done
myapp-9b4987d5-hk5n9
myapp-9b4987d5-hk5n9
myapp-9b4987d5-hk5n9

Headless Service 

有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。

这个选项允许开发人员自由寻找他们自己的方式,从而降低与 Kubernetes 系统的耦合性。 应用仍然可以使用一种自注册的模式和适配器,对其它需要发现机制的系统能够很容易地基于这个 API 来构建。

对这类 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了 selector。

headless service做dns解析是直接解析到pod的,而servcie是解析到ClusterIP的

代码语言:javascript复制
[root@k8s-master1 ~]# vim myapp.svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: "None"
  ports: 
  - port: 80
    targetPort: 80

[root@k8s-master1 ~]# kubectl apply -f myapp-svc.yaml 
service/myapp created
[root@k8s-master1 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   6d17h
myapp        ClusterIP   None         <none>        80/TCP    6m27s

0 人点赞