【Kubernetes】Service 服务发现 之 环境变量

497 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

一、前言

集群内部通过固定不变的 Service IP 地址就可以访问到后端 Pods。 表面上看服务一直在稳定运行中,但是后端的 Pods 却根据集群整体的情况不断动态变化以达到新的平衡,这个过程中旧的 Pods 可能不断在被清理回收,新的 Pods 正在创建中。

这些 Pods 如何知道 ServiceIP 和端口 Port 呢?

服务发现主要解决的问题是:让 Pods 及时知道 ServiceIP 和端口 Port

Service 服务发现目前有两种类型,为 环境变量DNS

推荐使用: DNS

二、环境变量

Node 上新创建一个 Pod 时,kubelet 会为每个 Pod(容器)添加一组环境变量,其中就包括当前系统中已经存在的 ServiceIP 地址和端口号。

环境变量格式,例如:

{SVCNAME}_SERVICE_HOST=host
{SVCNAME}_SERVICE_PORT=port

环境变量名都必须为大写,如果其中有连字符的会被转换为下划线。

例如:集群中已经存在一个名为 redis-masterService,它在集群内的 IP 地址为:10.0.0.11TCP 端口号为 6379,那么新创建的 Pod 中就会被初始化一组环境变量如下所示:

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

**问题:**服务必须先于 Pods 创建。

如果先创建 Pods 后创建 Service,那么后创建的 Service 环境变量不会存在于先创建的 Pods 中。

(1)举个栗子

  1. 创建 nginx-deployment.yaml 文件
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
  1. 执行创建
$ kubectl create -f nginx-deployment.yaml
deployment.apps/myweb created
  1. 查看新创建的 pods 的名称
$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
myweb-5754944d6c-smmxk  1/1     Running   0          5m56s
myweb-5754944d6c-8cngx   1/1     Running   0          5m56s
  1. 查看环境变量
$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   82d

$ kubectl exec myweb-5754944d6c-smmxk env
# 可以看到 Pod 已经被初始化注册了 Kubernetes 服务的相关环境变量
  1. 直接使用命令创建名为 myweb 的服务
$ kubectl expose deploy myweb
service/myweb exposed
  1. 查看 myweb service 的集群 IP 和 端口号
$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   82d
myweb        ClusterIP   10.104.100.171   <none>        80/TCP    4s
  1. 再次执行 kubectl exec myweb-5754944d6c

会发现新创建的服务在 myweb-5754944d6c-smmxk Pod 中依然也没有注册环境变量。这也就证实了我们前面提到的注意事项。

现在创建新的 pod,是否初始化环境变量,就将 myweb service 注册进去呢?

  1. 创建 tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: tomcat
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
        - name: tomcat
          image: tomcat
          ports:
            - containerPort: 8080
  1. 执行创建
$ kubectl create -f tomcat-deployment.yaml
deployment.apps/myapp created
  1. 查看新建的 pods
$ kubectl get pods -l app=tomcat
NAME                     READY   STATUS    RESTARTS   AGE
myapp-69ff6fc7c6-lm9mk   1/1     Running   0          10m
myapp-69ff6fc7c6-rjr4f   1/1     Running   0          10m
  1. 查看其中的一个 pod 环境变量
$ kubectl exec myapp-69ff6fc7c6-lm9mk env|grep MYWEB
MYWEB_PORT_80_TCP=tcp://10.104.100.171:80
MYWEB_PORT_80_TCP_PORT=80
MYWEB_PORT_80_TCP_ADDR=10.104.100.171
MYWEB_SERVICE_HOST=10.104.100.171
MYWEB_SERVICE_PORT=80
MYWEB_PORT=tcp://10.104.100.171:80
MYWEB_PORT_80_TCP_PROTO=tcp

可以看到 myweb service 环境变量已经注册进 tomcat pod中了。