kubernetes中使用dns來訪問服務


之前的文章kubernetes中pod間的通信 中,我們使用環境變量來解析服務的IP,但是可以使用環境變量有一個限制,所有的pods須在一個namespace中,也就是說在同一個namespace中的pod才會共享環境變量,如果不在同一個namespace該如何訪問呢?我們還是一個python的flask應用為例,這次我們將redis放到default的namespace中,flask的應用放到yyxtest的namespace中。

創建redis的pod與service

redis.yaml

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

apiVersion: v1
kind: Service
metadata:
  name: redis-master-sr
  labels:
    name: redis-master
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis

查看pod與service信息

# 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應用

#-*- 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

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

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的名稱空間中

# 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文件中設置了

metadata:
  name: redis-master-sr

則會創建一個 redis-master-sr.default.svc.cluster.local的記錄, 我們在default名稱空間中的pod試一下

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

在yyxtest名稱空間中的pod再試一下

# 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中執行

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的代碼

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不同的名稱空間創建應用了。

參考文章

命名空間


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM