说说Kubernetes是怎么实现服务发现的

Published on with 0 views and 0 comments

我们来说说 kubernetes 的服务发现。那么首先这个大前提是同主机通信以及跨主机通信都是 ok 的,即同一 kubernetes 集群中各个 pod 都是互通的。这点是由更底层的方案实现,包括 docker0/CNI 网桥、flannel vxlan/host-gw 模式等,在此篇就不展开讲了。

在各 pod 都互通的前提下,我们可以通过访问 podIp 来调用 pod 上的资源,那么离服务发现还有多少距离呢?首先 Pod 的 IP 不是固定的,另一方面我们访问一组 Pod 实例的时候往往会有负载均衡的需求,那么 service 对象就是用来解决此类问题的。

集群内通信

endPoints

service 首先解决的是集群内通信的需求,首先我们编写一个普通的 deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostnames
spec:
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
        - name: hostnames
          image: mirrorgooglecontainers/serve_hostname
          ports:
            - containerPort: 9376
              protocol: TCP

这个应用干的事儿就是访问它是返回自己的 hostname,并且每个 pod 都带上了 app 为 hostnames 的标签。

那么我们为这些 pod 编写一个普通的 service:

apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
    - name: default
      protocol: TCP
      port: 80
      targetPort: 9376

可以看到 service 通过 selector 选择 了带相应的标签 pod,而这些被选中的 pod,成为 endpoints,我们可以试一下:

[root@k8s-master network]# kubectl -n demo get ep  hostnames
NAME        ENDPOINTS                                           AGE
hostnames   10.244.0.4:9376,10.244.1.38:9376,10.244.2.20:9376   5m34s

当某一个 pod 出现问题,不处于 running 状态或者 readinessProbe 未通过时,endpoints 列表会将其摘除。

clusterIp

以上我们有了 service 和 endpoints,而默认创建 service 的类型是 clusterIp 类型,我们查看一下之前创建的 service:

[root@k8s-master network]# kubectl -n demo get svc hostnames
NAME        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
hostnames   ClusterIP   10.104.31.44   <none>        80/TCP    6m54s

我们看到 cluster-ip 是 10.104.31.44,那么我们此时可以在 kubernetes 集群内通过这个地址访问到 endpoints 列表里的任意 pod:

[root@k8s-master network]# curl 10.104.31.44
hostnames-6d4c8b87-7wt75
[root@k8s-master network]# curl 10.104.31.44
hostnames-6d4c8b87-nkfbl
[root@k8s-master network]# curl 10.104.31.44

访问了三次 clusterIp 地址,返回了三个不同的 hostname,我们意识到 clusterIp 模式的 service 自动对请求做了 round robin 形式的负载均衡。

对于此时 clusterIp 模式 serivice 来说,它有一个 A 记录是 service-name.namespace-name.svc.cluster.local,指向 clusterIp 地址:


标题:说说Kubernetes是怎么实现服务发现的
作者:cuijianzhe
地址:https://cuijianzhe.github.io/articles/2020/08/15/1597473942670.html