k8s集群中service的域名解析、pod的域名解析

前言

在k8s集群中,service和pod都可以通过域名的形式进行相互通信,换句话说,在k8s集群内,通过service和pod的域名,可以直接访问内部应用,不必在通过service ip地址进行通信,一般的,我们创建service的时候不建议指定service的clusterIP,而是让k8s自动为service分配一个clusterIP,这样,service的IP是自动分配,但是service名字总是固定的吧,这样在集群内部就可以直接通过service的域名来连接即可,如前端pod应用直接通过service域名来连接后端pod。

service的域名

完整的service域名解析是:<servicename>.<namespace>.svc.<clusterdomain> 其中,servicename为service名称,namespace为service所处的命名空间,clusterdomain是k8s集群设计的域名后缀,默认为cluster.local。
一般的,在生产环境中,我们可以直接简写为<servicename>.<namespace>即可,后面的部分保持默认即可。如果pod与svc是在同一个命名空间,那么直接写svc即可,如 <servicename>

#查看k8s集群设置的域名后缀
cat /opt/kubernetes/config/kubelet-config.yml  | grep -i clusterDomain			#二进制安装的k8s集群,可以这样查看
cat  /etc/kubernetes/kubelet.conf 					#kubeadm安装的k8s集群,各个节点的kubelet.conf文件中的字段clusterDomain
kubectl  -n kube-system get cm coredns -oyaml		#coredns cm里面也可以看到
kubectl  exec -it deployment-busybox-567674bd67-lmrgw --  cat /etc/resolv.conf	#直接看pod里面的resolv.conf文件亦可

演示示例:
下面,我们通过创建一个deployment和service,然后创建一个测试pod,在测试pod中通过访问service域名的形式访问应用,验证service域名是否正常。如下所示:

# 创建一个deployment,有3个副本
[root@master service]# vim deployment-nginx.yaml         
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    env: dev
    tiar: front
  name: deployment-nginx
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        name: nginx-container
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
      restartPolicy: Always
#创建一个service,用于反向代理上面创建的deployment的pod
[root@master service]# vim svc-deployment-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: svc-deployment-nginx
  namespace: default
spec:
  ports:
  - name: nginx-port
    nodePort: 30080
    port: 80
    protocol: TCP
    targetPort: http
  selector:
    app: nginx
  type: NodePort
#创建一个pod用于测试
[root@master service]# cat ../pod/pod-busybox.yaml 
apiVersion: v1
kind: Pod
metadata: 
  name: pod-command
  labels: 
    env: dev
  namespace: default
spec:
  nodeName: node2
  containers:
  - image: busybox
    name: busybox-container
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt;sleep 3;done;"]
    resources:
      limits:
        cpu: 2
        memory: 2G
      requests:
        cpu: 1
        memory: 500M
[root@master service]# 
# 在测试pod中直接访问service的域名
[root@master service]# kubectl exec -it pod-command -- /bin/sh			#进入到测试pod中
/ # wget http://svc-deployment-nginx.default.svc.cluster.local:80		#这个pod没有curl命令,所以通过wget命令下载
Connecting to svc-deployment-nginx.default.svc.cluster.local:80 (10.111.193.190:80)		#下载成功
saving to 'index.html'
index.html           100% |*******************************************************************************************************************************************************************************************|   612  0:00:00 ETA
'index.html' saved
/ # cat index.html 														#下载成功,这是nginx的index文件,说明通过service域名访问是正常的
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
/ # 


wget http://svc-deployment-nginx.default.svc.cluster.local:80		#完整的写法
wget http://svc-deployment-nginx.default:80							#带命名空间写法
wget http://svc-deployment-nginx:80									#如果pod与svc在同一个命名空间,可以将命名空间省略不写

以上,说明,在pod内部通过访问service域名的形式访问其他服务,service的域名解析是正常的。

注意:不要在宿主机上curl service的域名,这样是访问不通的,因为service的域名是由k8s集群dns 这个pod解析的,不是外部宿主机的dns服务器解析的。所以,你直接在宿主机命令行curl service域名,肯定是行不通的。service的域名解析是供k8s集群内部pod应用之间进行访问的。换句话说,service域名仅供pod内使用。

pod的域名解析

pod的DNS域名格式为:<pod-ip>.<namespace>.pod.<clusterdomain> ,其中,pod-ip需要使用-将ip直接的点替换掉,namespace为pod所在的命名空间,clusterdomain是k8s集群设置的域名后缀,一般默认为 cluster.local ,如果没有改变k8s集群默认的域名后缀,则可以省略该后缀不写。除此之外,其他的均不可省略,这一点与svc域名有所不同。
演示如下:

#进入default命名空间的busybox pod里面,测试下载文件
kubectl -n default exec -it deployment-busybox-567674bd67-lmrgw -- sh
wget 10-244-166-167.helm.pod.cluster.local:80		#可以正常下载,这里下载的是helm命名空间里的IP为10.244.166.167的pod
wget 10-244-166-167.helm.pod:80						#可以正常下载,这里把k8s集群设置的域名后缀默认省略了					
wget 10-244-166-143.default.pod:80					#可以正常下载,这里下载的是default命名空间里的IP为10.244.166.143的pod
wget 10-244-166-143.default:80						#报错了,错误写法,说明不能省略pod关键字
wget 10-244-166-143:80								#报错了,错误写法,说明不能省略命名空间和pod关键字

对应deployment、deamonset等创建的pod,还可以<pod-ip>.<deployment-name>.<namespace>.svc.<clusterdomain> 访问。(这个一直测试失败,不指定是不是书中写错了,所以这点存疑)

对于StatefulSet创建的pod,statefulset.spec.serviceName字段解释如下:

[root@matser ~]# kubectl explain  statefulset.spec.serviceName
KIND:     StatefulSet
VERSION:  apps/v1
FIELD:    serviceName <string>
DESCRIPTION:
     serviceName is the name of the service that governs this StatefulSet. This
     service must exist before the StatefulSet, and is responsible for the
     network identity of the set. Pods get DNS/hostnames that follow the
     pattern: pod-specific-string.serviceName.default.svc.cluster.local where
     "pod-specific-string" is managed by the StatefulSet controller.
[root@matser ~]#

也就是说sts创建的pod,其pod的域名为:pod-specific-string.serviceName.default.svc.cluster.local,而pod-specific-string就是pod的名称。
例如:redis-sts-0.redis-svc.default.svc.cluster.local:6379,redis-sts-1.redis-svc.default.svc.cluster.local:6379,redis-sts-2.redis-svc.default.svc.cluster.local:6379,redis-sts-3.redis-svc.default.svc.cluster.local:6379,redis-sts-4.redis-svc.default.svc.cluster.local:6379,redis-sts-5.redis-svc.default.svc.cluster.local:6379,pod里面的应用程序就可以拿这串字符串去连接Redis集群了。

总结

以上,service的域名解析很重要,我们只需要在k8s集群内部的pod里面连接访问service的域名即可,因为service的名称总是固定的,既然是固定的,那么可以直接通过访问service的域名方式来访问对应的service即可。
至于普通pod的域名解析,可以不用太过在乎,了解即可,因为pod的生命周期是不固定的,随时都可能消亡,也就是说pod IP随时可能变化,所以根本不会使用pod域名访问pod应用。
对应StatefulSet 创建的有状态的pod,其pod域名解析是固定格式的,这个要记着,pod-specific-string.serviceName.default.svc.cluster.local,pod-specific-string就是pod的名称。

  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值