「走进k8s」Kubernetes1.15.1的服务发现kubedns(34)

image.png

之前的文章讲解了service,其实service很大的作用就是暴露一个ClusterIP,来访问对应deployment的pod,如果我们有2个应用,一个web端,一个db端,通过deployment关联起来,并且都通过 Service 暴露出了端口提供服务。web 需要连接到 db 这个应用,只知道 db 应用的名称和 db 对应的 Service 的名称,但是并不知道它的 ClusterIP地址,前面学的都是通过ClusterIP来访问pod,是不是只有知道ClusterIP才可以访问呢?

image.png

(一)apiserver的方式进行服务发现

apiserver 中直接查询,一个特殊的应用,通过 apiserver 去查询到 Service 后面的 Endpoints 直接使用是没问题的,但是如果每个应用都在启动的时候去查询依赖的服务,这不但增加了应用的复杂度,这也导致了应用需要依赖 Kubernetes 了,耦合度有点太高,不适合通用,维护起来很复杂。

(二)环境变量

Kubernetes 采用了环境变量的方法,每个 Pod 启动的时候,会生成对应的环境变量,设置所有服务的 IP 和 port 信息,这样 Pod 中的应用可以通过读取环境变量来获取依赖服务的地址信息,这种方法使用起来相对简单,但是有一个很大的问题就是依赖的服务必须在 Pod 启动之前就存在,不然是不会被注入到环境变量中的。

  • ① 创建test-nginx.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    k8s-app: nginx-demo
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.8
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    name: nginx-service
spec:
  ports:
  - port: 5000
    targetPort: 80
  selector:
    app: nginx

  • ② 创建服务
kubectl apply -f test-nginx.yaml 

kubectl get deployment

kubectl get pods 

 kubectl get svc

service 里面关联了3个pod

 kubectl describe svc nginx-service 

  • ③ 查看上边的服务信息,创建一个服务查看,所有的环境变量,顺便查看下nginx-server
apiVersion: v1
kind: Pod
metadata:
  name: test-api
spec:
  containers:
  - name: test-api
    image: busybox
    command: ["/bin/sh", "-c", "env"]

执行pod的yml,查看日志

kubectl apply -f test-pod.yaml

说明新建立的pod,可以获得nginx-server的环境变量信息

既然新建的pod可以获得刚创建的nginx-server的服务,前提是nginx-server必须启动,如果想这样的话,必须在pod中添加初始化容器服务,之前讲过,这里在演示一下,修改test-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-api
spec:
  initContainers:
    - name: init-nginx-server
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ['sh', '-c', 'until nslookup nginx-service;do echo waiting for nginx-service sleep 2; done;']
  containers:
  - name: test-api
    image: busybox
    command: ["/bin/sh", "-c", "env"]

创建修改后的test-pod.yaml,获取信息发现出现init的情况,因为进行了初始化容器的检测。

kubectl delete pod  test-api
kubectl apply -f test-pod.yaml
kubectl get pods

kubectl logs test-api 

可以直接通过 NGINX_SERVICE_SERVICE_HOST 和 NGINX_SERVICE_SERVICE_PORT ,这样也是一种方式。如果存在依赖关系可以通过初始化容器的方式,但是这种方式有点复杂,每次编写yaml的,真不具有通用性,不是最优解啊。

(三)kubedns

  • ① DNS发展史

  • ② 官网

https://github.com/kubernetes/dns

  • ③ 介绍

Kubernetes DNS 在集群中会启动dns pod(coredns)和service(kube-dns)。集群中的container使用kube-dns service进行dns解析。在集群中,每个service都会分配一个域名,默认一个pod会查找他自己namespace和集群中的default域。如:在bar namespace中分配一个service foo,运行在bar namespace中的pod可以通过foo查找这个服务,运行在quux namespace中的pod需要foo.bar查找这个服务。

之前的文章关于搭建k8s的时候,其实dns已经搭建了使用了的是coreDNS,自带好了,这里都不做介绍了。

  • ④ CoreDNS

实现的功能和 KubeDNS 是一致的,不过 CoreDNS 的所有功能都集成在了同一个容器中,在最新版的1.11.0版本中官方已经推荐使用 CoreDNS了,大家也可以安装 CoreDNS 来代替 KubeDNS,其他使用方法都是一致的:https://coredns.io/

CoreDNS从2017年初就成为了CNCF的的孵化项目,CoreDNS的特点就是十分灵活和可扩展的插件机制,各种插件实现不同的功能,如重定向、定制DNS记录、记录日志等等。

  • ⑤ 查看dns信息
kubectl get pods -n kube-system

  • ⑥ 域名格式

1.普通的 Service

会生成 servicename.namespace.svc.cluster.local 的域名,会解析到 Service 对应的 ClusterIP 上,在 Pod 之间的调用可以简写成 servicename.namespace,如果处于同一个命名空间下面,甚至可以只写成 servicename 即可访问

2.Headless Service

无头服务,就是把 clusterIP 设置为 None 的,会被解析为指定 Pod 的 IP 列表,同样还可以通过 podname.servicename.namespace.svc.cluster.local 访问到具体的某一个 Pod。

  • ⑥ 测试查看dns地址
 kubectl run -it --image=busybox:1.28.4 --rm --restart=Never sh

# cat /etc/resolv.conf 

通过域名的形式访问,加上 5000 端口,就正常访问到服务

wget -q -O- nginx-service.default.svc.cluster.local:5000


wget -q -O- nginx-service.default:5000

wget -q -O- nginx-service.default.svc:5000

PS:通过dns可以访问同一个namespace,dns跟网络经常使用的域名方式很类似的,就是域名dns找到对应的服务,性质是一样的。下节咱们说说如果不在同一个namespace下如何进行通信的问题。

>>原创文章,欢迎转载。转载请注明:转载自IT人故事会,谢谢!
>>原文链接地址:「走进k8s」Kubernetes1.15.1的服务发现kubedns(34)
上一篇: 下一篇:

发表评论

电子邮件地址不会被公开。 必填项已用*标注