9

kubernetes中使用dns来访问服务

 3 years ago
source link: https://www.yangyanxing.com/article/namespace-k8s.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

之前的文章kubernetes中pod间的通信 中,我们使用环境变量来解析服务的IP,但是可以使用环境变量有一个限制,所有的pods须在一个namespace中,也就是说在同一个namespace中的pod才会共享环境变量,如果不在同一个namespace该如何访问呢?我们还是一个python的flask应用为例,这次我们将redis放到default的namespace中,flask的应用放到yyxtest的namespace中。

创建redis的pod与service

redis.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: redis
name: redis-master
spec:
selector:
matchLabels:
app: redis
replicas: 1
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis
name: redis-master2
ports:
- containerPort: 6379

redis-service.yaml

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: redis-master-sr
labels:
name: redis-master
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis

查看pod与service信息

1
2
3
4
5
6
7
# kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-wjq6t 1/1 Running 0 8m55s

C:\Users\54523\Desktop\k8stest>kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis-master-sr ClusterIP 10.97.140.58 <none> 6379/TCP 3m3s

创建python应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#-*- coding:utf-8 -*-
# author:Yang
# datetime:2020/2/10 16:07
# software: PyCharm

from flask import Flask
from flask_redis import FlaskRedis
import time
import os

if os.environ.get("envname") == "k8s": # 说明是在k8s中
redis_server = os.environ.get("REDIS_MASTER_SR_SERVICE_HOST")
redis_port = os.environ.get("REDIS_MASTER_SR_SERVICE_PORT")
REDIS_URL = "redis://{}:{}/{}".format(redis_server, redis_port, 1)
else:
REDIS_URL = "redis://{}:{}/{}".format('127.0.0.1', 6380, 1)


app = Flask(__name__)
app.config['REDIS_URL'] = REDIS_URL
redis_client = FlaskRedis(app)

@app.route("/")
def index_handle():
redis_client.set("reidstest",time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())))
name = redis_client.get("reidstest").decode()
return "hello %s"% name

app.run(host='0.0.0.0', port=6000, debug=True)

上面是之前的代码,采用环境变量的方式,获取到redis_server和redis_port,之前创建flask的应用的pod和service都没有指定namespace,如果没有指定的话,默认是创建在了default的namespace,由于redis也没有指定,所以它们之间是可以通过共享环境变量来解决服务地址的,那现在我们将python应用创建在yyxtest的namespace中,看看情况如何。

将先之前python应用打包 docker build -t flaskk8s:dns .

创建deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: flasktest
name: flasktest
namespace: yyxtest
spec:
selector:
matchLabels:
app: flasktest
replicas: 2
template:
metadata:
labels:
app: flasktest
spec:
containers:
- image: flaskk8s:dns
name: flaskweb
imagePullPolicy: Never
ports:
- containerPort: 6000

再创建service.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
name: flask-service
labels:
name: flaskservice
namespace: yyxtest
spec:
type: NodePort
ports:
- port: 6000
nodePort: 30003
selector:
app: flasktest

这次在deployment和service中的metadata中都添加了namespace: yyxtest ,它们将会被创建到 yyxtest的namespace中

使用kubectl get pods --namespace=yyxtest 来查看pods,此时pods直接显示error了,通过查看pods里的日志发现,redis_port = os.environ.get("REDIS_MASTER_SR_SERVICE_PORT") 这行代码没有获取到REDIS_MASTER_SR_SERVICE_PORT的值,返回的是个None,所以在之后的redis初始化时就报错失败了,这也说明,在yyxtesxt的名称空间中的pod里是没有REDIS_MASTER_SR_SERVICE_PORT 这个环境变量的。

我们同样在default的namespace中也创建flask的pod和service,此时就可以正常的访问。

我们使用kubectl exec命令分别进入到两个namespace空间中的flask应用的pod中

在default的名称空间中

1
2
3
4
5
# env
...
FLASK_SERVICE_SERVICE_HOST=10.109.55.91
REDIS_MASTER_SR_SERVICE_PORT=6379
...

它包含有这两个环境变量,但是在yyxtest的pod中却没有这两个环境变量,这也就说明,原来的代码在非default空间(准确的说是和redis不在同一个空间中)是不能正常运行的。

使用dns来解析服务地址

除了可以使用环境变量来解析服务地址,用的更多的应该是使用dns来解析了,在创建redis的service时,Kubernetes 会创建一个相应的 DNS 条目,该条目的形式是 <service-name>.<namespace-name>.svc.cluster.local,这意味着如果容器只使用 <service-name>,它将被解析到本地命名空间的服务。比如在yaml文件中设置了

1
2
metadata:
name: redis-master-sr

则会创建一个 redis-master-sr.default.svc.cluster.local的记录, 我们在default名称空间中的pod试一下

1
2
# ping redis-master-sr
PING redis-master-sr.default.svc.cluster.local (10.97.140.58) 56(84) bytes of data.

在yyxtest名称空间中的pod再试一下

1
2
# ping redis-master-sr
ping: redis-master-sr: Name or service not known

说明服务名只能中它所在的空间中(本例中的default)有dns记录,不在它的空间(本例中的yyxtest)中则不存在,但是我们注意中,在default空间中 redis-master-sr解析到了redis-master-sr.default.svc.cluster.local ,那么在非default空间中是否可以正常解析redis-master-sr.default.svc.cluster.local 这个名称呢?

在yyxtest的pod中执行

1
2
ping redis-master-sr.default.svc.cluster.local
PING redis-master-sr.default.svc.cluster.local (10.97.140.58) 56(84) bytes of data.

也是可以正常解析的,所以这时我们来修改一下python的代码

1
2
3
4
if os.environ.get("envname") == "k8s": # 说明是在k8s中
REDIS_URL = "redis://{}:{}/{}".format("redis-master-sr.default.svc.cluster.local", 6379, 1)
else:
REDIS_URL = "redis://{}:{}/{}".format('127.0.0.1', 6380, 1)

这时,我们就可以和redis不同的名称空间创建应用了。

命名空间


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK