一起养成写作习惯!这是我参与「掘金日新计划 · 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-smmxkPod中依然也没有注册环境变量。这也就证实了我们前面提到的注意事项。
现在创建新的 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中了。