服务发现

1.服务发现存在的意义

我们可以通过 Service 生成的 ClusterIP(VIP) 来访问 Pod 提供的服务,但是在使用的时候还有一个问题:我们怎么知道某个应用的 VIP 呢?比如我们有两个应用,一个是 api 应用,一个是 db 应用,两个应用都是通过 Deployment 进行管理的,并且都通过 Service 暴露出了端口提供服务。api 需要连接到 db 这个应用,我们只知道 db 应用的名称和 db 对应的 Service 的名称,但是并不知道它的 VIP 地址,我们前面的 Service 课程中是不是学习到我们通过 ClusterIP 就可以访问到后面的 Pod 服务,如果我们知道了 VIP 的地址是不是就行了?

2.环境变量

为了解决上面的问题,在之前的版本中,Kubernetes 采用了环境变量的方法,每个 Pod 启动的时候,会通过环境变量设置所有服务的 IP 和 port 信息,这样 Pod 中的应用可以通过读取环境变量来获取依赖服务的地址信息,这种方法使用起来相对简单,但是有一个很大的问题就是依赖的服务必须在 Pod 启动之前就存在,不然是不会被注入到环境变量中的。比如我们首先创建一个 Nginx 服务:(test-nginx.yaml)
[root@master01 service]# cat test-nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deploy
spec:
 replicas: 2
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.7.9
       ports:
       - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
 name: nginx-service
 labels:
   name: nginx-service
spec:
 ports:
 - port: 5000
   targetPort: 80
 selector:
   app: nginx
[root@master01 service]# kubectl get pod 
NAME                            READY   STATUS             RESTARTS   AGE
nginx-deploy-5d59d67564-x84pj   1/1     Running            0          15m
nginx-deploy-5d59d67564-zdv5b   1/1     Running            0          15m
[root@master01 service]# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP    3d1h
nginx-service   ClusterIP   10.110.142.114   <none>        5000/TCP   16m
[root@master01 service]# kubectl describe svc  nginx-service
Name:              nginx-service
Namespace:         default
Labels:            name=nginx-service
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP:                10.110.142.114
Port:              <unset>  5000/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.4:80,10.244.2.8:80
Session Affinity:  None
Events:            <none>

我们可以看到两个 Pod 和一个名为 nginx-service 的服务创建成功了,该 Service 监听的端口是 5000,同时它会把流量转发给它代理的所有 Pod(我们这里就是拥有 app: nginx 标签的两个 Pod)。

3.现在我们再来创建一个普通的 Pod,观察下该 Pod 中的环境变量是否包含上面的 nginx-service 的服务信息:(test-pod.yaml)

[root@master01 service]# cat test-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-service-pod
    image: busybox
    command: ["/bin/sh", "-c", "env"]
[root@master01 service]# kubectl logs  test-pod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=test-pod
SHLVL=1
HOME=/root
NGINX_SERVICE_PORT_5000_TCP_ADDR=10.110.142.114
NGINX_SERVICE_PORT_5000_TCP_PORT=5000
NGINX_SERVICE_PORT_5000_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_SERVICE_SERVICE_HOST=10.110.142.114
KUBERNETES_PORT_443_TCP_PORT=443
NGINX_SERVICE_PORT_5000_TCP=tcp://10.110.142.114:5000
KUBERNETES_PORT_443_TCP_PROTO=tcp
NGINX_SERVICE_PORT=tcp://10.110.142.114:5000
NGINX_SERVICE_SERVICE_PORT=5000
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=
我们可以看到打印了很多环境变量信息,其中就包括我们刚刚创建的 nginx-service 这个服务,有 HOST、PORT、PROTO、ADDR 等,也包括其他已经存在的 Service 的环境变量,现在如果我们需要在这个 Pod 里面访问 nginx-service 的服务,我们是不是可以直接通过 NGINX_SERVICE_SERVICE_HOST 和 NGINX_SERVICE_SERVICE_PORT 就可以了,但是如果这个 Pod 启动起来的时候 nginx-service 服务还没启动起来,在环境变量中我们是无法获取到这些信息的,当然我们可以通过 initContainer 之类的方法来确保 nginx-service 启动后再启动 Pod,但是这种方法毕竟增加了 Pod 启动的复杂性,所以这不是最优的方法,局限性太多了。
上一篇:假设有N盏灯(N为不大于5000的正整数)从1到N按顺序依次编号,初始时全为开启状态;有M个人......题目如图


下一篇:DSX-5000支持铜缆认证、光纤损耗及OTDR测试