之前的文章讲解了service,其实service很大的作用就是暴露一个ClusterIP,来访问对应deployment的pod,如果我们有2个应用,一个web端,一个db端,通过deployment关联起来,并且都通过 Service 暴露出了端口提供服务。web 需要连接到 db 这个应用,只知道 db 应用的名称和 db 对应的 Service 的名称,但是并不知道它的 ClusterIP地址,前面学的都是通过ClusterIP来访问pod,是不是只有知道ClusterIP才可以访问呢?
apiserver 中直接查询,一个特殊的应用,通过 apiserver 去查询到 Service 后面的 Endpoints 直接使用是没问题的,但是如果每个应用都在启动的时候去查询依赖的服务,这不但增加了应用的复杂度,这也导致了应用需要依赖 Kubernetes 了,耦合度有点太高,不适合通用,维护起来很复杂。
Kubernetes 采用了环境变量的方法,每个 Pod 启动的时候,会生成对应的环境变量,设置所有服务的 IP 和 port 信息,这样 Pod 中的应用可以通过读取环境变量来获取依赖服务的地址信息,这种方法使用起来相对简单,但是有一个很大的问题就是依赖的服务必须在 Pod 启动之前就存在,不然是不会被注入到环境变量中的。
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
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的,真不具有通用性,不是最优解啊。
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,自带好了,这里都不做介绍了。
实现的功能和 KubeDNS 是一致的,不过 CoreDNS 的所有功能都集成在了同一个容器中,在最新版的1.11.0版本中官方已经推荐使用 CoreDNS了,大家也可以安装 CoreDNS 来代替 KubeDNS,其他使用方法都是一致的: https://coredns.io/
CoreDNS从2017年初就成为了CNCF的的孵化项目,CoreDNS的特点就是十分灵活和可扩展的插件机制,各种插件实现不同的功能,如重定向、定制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。
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下如何进行通信的问题。
>>原创文章,欢迎转载。转载请注明:转载自,谢谢!>>原文链接地址:上一篇:下一篇: