#kubernetes #k8s


连接一些多实例的服务(比如Kafka、ES)时,通常是在client端做负载均衡。
假如这种集群又恰好跑在k8s中,如果是普通业务类型的服务,通常是创建一个Service来做为一个代理去访问不同实例,从而达到负载均衡的目的。
但是诸如如:Kafka、ES类型的服务,还用Service来做负载均衡,显然就不那么合理了(诚然,Kafka、ES这种东西多半是不会跑在k8s上的,这里只是作为一个引子,不在本文讨论的范畴)。

实验环境

  • 多实例服务whoamikube-test-1的命名空间下
  • 多实例服务whoamiStatefulSet方式部署,设置为3个实例,会自动创建whoami-0whoami-1以及whoami-2三个Pod
  • StatefulSet创建Headless类型的Service
  • 模拟客户端使用Nginx镜像,部署在kube-test-2的命名空间下(使用curl命令模拟)

本实验创建资源使用的k8s dashboard,创建的资源默认放在选中的明明空间下,因此yml文件中未指定namespace

Server cluster

服务端模拟相关资源在kube-test-1下创建

StatefulSet

使用traefik/whoami镜像来模拟服务端

这里使用StatefulSet的方式创建服务端。spec.replicas设为3,此时会自动创建whoami-0whoami-1以及whoami-2三个Pod

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  serviceName: whoami
  template:
    metadata:
      name: whoami
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami
          ports:
            - containerPort: 80

注意这里的spec.serviceName必须与下面的Service名字相同,否则调用时候podsubdomain只能使用IP

$ k get pod -n kube-test-1 -o wide | grep whoami
whoami-0                 1/1     Running   0          29m   10.244.1.220   node2   <none>           <none>
whoami-1                 1/1     Running   0          29m   10.244.0.52    node1   <none>           <none>
whoami-2                 1/1     Running   0          29m   10.244.1.221   node2   <none>           <none>

Headless

使用Headless的方式向外暴露Pod,不允许使用Service的负载均衡

apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  clusterIP: None
  ports:
    - port: 80
  selector:
    app: whoami
$ k get service -n kube-test-1 -o wide | grep whoami
whoami   ClusterIP   None         <none>        80/TCP    10s   app=whoami

Client

客户端模拟相关资源在kube-test-2下创建

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

nginx用来模拟客户端,调用镜像自带的curl命令

进入nginx容器

$ k exec -it nginx-6799fc88d8-cgvtp -n kube-test-2 /bin/bash

使用curl命令分别调用几个服务端

$ curl whoami-0.whoami.kube-test-1.svc.cluster.local
Hostname: whoami-0
IP: 127.0.0.1
IP: 10.244.1.220
RemoteAddr: 10.244.0.53:39400
GET / HTTP/1.1
Host: whoami-0.whoami.kube-test-1.svc.cluster.local
User-Agent: curl/7.64.0
Accept: */*

$ curl whoami-1.whoami.kube-test-1.svc.cluster.local
Hostname: whoami-1
IP: 127.0.0.1
IP: 10.244.0.52
RemoteAddr: 10.244.0.53:40354
GET / HTTP/1.1
Host: whoami-1.whoami.kube-test-1.svc.cluster.local
User-Agent: curl/7.64.0
Accept: */*

$ curl whoami-2.whoami.kube-test-1.svc.cluster.local
Hostname: whoami-2
IP: 127.0.0.1
IP: 10.244.1.221
RemoteAddr: 10.244.0.53:38370
GET / HTTP/1.1
Host: whoami-2.whoami.kube-test-1.svc.cluster.local
User-Agent: curl/7.64.0
Accept: */*

可以看到分别访问到三个不同的服务端pod了。

总结

访问的url格式为:

pod-ip-address.deployment-name.my-namespace.svc.cluster-domain.example

参考链接