Kubernetes | 服务发现

2020 08 10, Mon

我们平时部署服务的时候需要特别在意服务的IP、端口、协议什么的。

正常情况下服务IP是不会变的,我们只要配置对应的IP就行,或者我们配置一个域名,每次服务改变地址我们都改一下A记录就行。

但是这在k8s里面似乎不大方便,因为我们并不知道各自谁在哪里,节点的IP会随时改变。上一秒你还可以在某个IP找到你的容器,下一秒它就跑了。

服务发现

服务发现就是用某种方法,协助程序发现自己依赖的其他服务的地址和路由。

其实我们上面说的用域名就是服务发现了,只不过还是比较原始,要手工改一下IP。docker里面

而k8s中自带服务发现机制。

k8s

k8s服务编排的最小单位是Pod,一个Pod里面可以运行一个或者多个Container,共用一套CPU、内存、网络资源。可以通过一些Controller,比如说Deployment,来动态部署、实时确保服务运行。

定义Pod后,可以定义一类叫Service的资源。Service就是一个Pod的集合,以及访问这些Pod的策略。

比如说我定义了一个Nginx服务

# from https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

我要从另一个服务里面访问这个服务,就需要再定义一个Service,在k8s中记录这个服务的存在:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 1234
      targetPort: 80

这样k8s就会知道,你有一个nginx的app在监听80/tcp,你希望别的服务通过nginx-service这个名字和1234这个端口找到它。

然后当你在同namespace的其他pod中解析nginx时,就可以通过nginx-service:1234来访问这个实例了。在别的namespace中我们也可以用nginx-service.$namespace$比如说nginx-service.default来访问这个nginx,在别的集群上就是需要service.namespace.cluster。

这就是k8s中服务发现最简单的方法。

验证

还记得上一篇博客中,我们用openfaas跑了一个函数叫dig,这个函数解析域名并且返回一个字符串形式表示的IP的JSON列表。忘了的话可以看看这里

我们在终端中先看一眼我们有哪些函数:

$ kubectl get --namespace openfaas-fn svc
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
dig        ClusterIP   10.43.58.194   <none>        8080/TCP   2d13h
nodeinfo   ClusterIP   10.43.79.165   <none>        8080/TCP   2d9h

我们看到我们有俩service,一个叫dig,一个叫nodeinfo,就是上一次我们跑的两个fn。

我们在dig中执行一下nodeinfo,就会得到["10.43.79.165"]