一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
一、前言
集群内部通过固定不变的
Service IP
地址就可以访问到后端Pods
。 表面上看服务一直在稳定运行中,但是后端的Pods
却根据集群整体的情况不断动态变化以达到新的平衡,这个过程中旧的Pods
可能不断在被清理回收,新的Pods
正在创建中。
这些 Pods
如何知道 Service
的 IP
和端口 Port
呢?
服务发现主要解决的问题是:让 Pods
及时知道 Service
的 IP
和端口 Port
。
Service
服务发现目前有两种类型,为 环境变量 和 DNS
推荐使用:
DNS
二、环境变量
在 Node
上新创建一个 Pod
时,kubelet
会为每个 Pod
(容器)添加一组环境变量,其中就包括当前系统中已经存在的 Service
的 IP
地址和端口号。
环境变量格式,例如:
{SVCNAME}_SERVICE_HOST=host
{SVCNAME}_SERVICE_PORT=port
环境变量名都必须为大写,如果其中有连字符的会被转换为下划线。
例如:集群中已经存在一个名为 redis-master
的 Service
,它在集群内的 IP
地址为:10.0.0.11
,TCP
端口号为 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)举个栗子
- 创建
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
- 执行创建
$ kubectl create -f nginx-deployment.yaml
deployment.apps/myweb created
- 查看新创建的
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
- 查看环境变量
$ 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 服务的相关环境变量
- 直接使用命令创建名为
myweb
的服务
$ kubectl expose deploy myweb
service/myweb exposed
- 查看
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
- 再次执行
kubectl exec myweb-5754944d6c
会发现新创建的服务在
myweb-5754944d6c-smmxk
Pod
中依然也没有注册环境变量。这也就证实了我们前面提到的注意事项。
现在创建新的 pod
,是否初始化环境变量,就将 myweb service
注册进去呢?
- 创建
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
- 执行创建
$ kubectl create -f tomcat-deployment.yaml
deployment.apps/myapp created
- 查看新建的
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
- 查看其中的一个
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
中了。