Kubernetes 里,怎么让 Pod 有 DNS 记录?

在专栏“深入剖析Kubernetes”的第20章,我们学到很容易让一个 StatefulSet 中的 Pod 拥有 DNS 记录。如果一个 StatefulSet 的名字是 memcached, 而它指定了关联的 serviceName 叫 memcached-cluster,那 kube-dns 就会为它的每个 pod 解析如下的 DNS A 记录:

  • memcached-0.memcached-cluster.svc.cluster.local
  • memcached-1.memcached-cluster.svc.cluster.local
  • ...

这里假设 cluster domain 是默认的 cluster.local。关于 StatefulSet 的 pod DNS,官方文档中也有简单说明

那除了由 StatefulSet 管理的 pod,其它的 pod 能不能有 DNS 记录呢?就在该专栏第27章,我们看到 etcd operator 在生成 etcd 的启动命令时,使用了 pod 的 DNS 记录而不是 IP,这说明答案是肯定的—— pod 是可以有自己的 DNS 记录的。

我们来部署一个官方文档中提到的 nginx deployment,其定义如下:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

部署后创建了两个 pod:

$ kubectl apply -f nginx-deployment.yaml
$ kubectl get pod -o wide
NAME                                READY     STATUS    RESTARTS   AGE       IP          NODE      NOMINATED NODE
nginx-deployment-67594d6bf6-brfcw   1/1       Running   0          18m       10.32.0.6   k8s-0     <none>
nginx-deployment-67594d6bf6-nnxg5   1/1       Running   0          18m       10.44.0.6   k8s-1     <none>

然后定义如下的 headless service:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  clusterIP: None
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 9330
  selector:
    app: nginx
  type: ClusterIP

创建该 service,并尝试解析 service DNS:

$ kubectl apply -f nginx-service.yaml
service/nginx created
$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   47m
nginx        ClusterIP   None         <none>        80/TCP    21s
$ dig @10.96.0.10 nginx.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> @10.96.0.10 nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13949
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 095945e3dc8b19b8 (echoed)
;; QUESTION SECTION:
;nginx.default.svc.cluster.local. IN    A

;; ANSWER SECTION:
nginx.default.svc.cluster.local. 5 IN   A   10.32.0.6
nginx.default.svc.cluster.local. 5 IN   A   10.44.0.6

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Apr 19 14:50:13 CST 2019
;; MSG SIZE  rcvd: 166

跟预期的一样,kube-dns 为 service 的名字返回了多条 A 记录,每一条对应一个 pod。上面 dig 命令中使用的 10.96.0.10 就是 kube-dns 的 cluster IP,可以在 kube-system namespace 中查看:

$ kubectl -n kube-system get svc
NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
kube-dns               ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP   52m

现在试试在 service 名字前面加上 pod 名字交给 kube-dns 做解析:

$ dig @10.96.0.10 nginx-deployment-67594d6bf6-brfcw.nginx.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> @10.96.0.10 nginx-deployment-67594d6bf6-brfcw.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 10513
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 2ddad0cd6f72dfd7 (echoed)
;; QUESTION SECTION:
;nginx-deployment-67594d6bf6-brfcw.nginx.default.svc.cluster.local. IN A

;; AUTHORITY SECTION:
cluster.local.      30  IN  SOA ns.dns.cluster.local. hostmaster.cluster.local. 1555656528 7200 1800 86400 30

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Apr 19 14:51:01 CST 2019
;; MSG SIZE  rcvd: 199

无法解析。官方文档中有一段 Pod’s hostname and subdomain fields 说:

The Pod spec also has an optional subdomain field which can be used to specify its subdomain. For example, a Pod with hostname set to “foo”, and subdomain set to “bar”, in namespace “my-namespace”, will have the fully qualified domain name (FQDN) “foo.bar.my-namespace.svc.cluster.local”.

If there exists a headless service in the same namespace as the pod and with the same name as the subdomain, the cluster’s KubeDNS Server also returns an A record for the Pod’s fully qualified hostname.

编辑一下 nginx-deployment.yaml 加上 subdomain:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      subdomain: nginx
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

更新部署再尝试解析 pod DNS (注意现在两个 pod 都是重新创建的,名字已变):

$ kubectl apply -f nginx-deployment.yaml
$ kubectl get pod -o wide
NAME                                READY     STATUS    RESTARTS   AGE       IP          NODE      NOMINATED NODE
nginx-deployment-59d854d9c8-nbvdm   1/1       Running   0          11s       10.32.0.8   k8s-0     <none>
nginx-deployment-59d854d9c8-thvkd   1/1       Running   0          13s       10.44.0.7   k8s-1     <none>
$ dig @10.96.0.10 nginx-deployment-59d854d9c8-thvkd.nginx.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> @10.96.0.10 nginx-deployment-59d854d9c8-thvkd.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4952
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 0e2b8426f0e8fe33 (echoed)
;; QUESTION SECTION:
;nginx-deployment-59d854d9c8-thvkd.nginx.default.svc.cluster.local. IN A

;; AUTHORITY SECTION:
cluster.local.      30  IN  SOA ns.dns.cluster.local. hostmaster.cluster.local. 1555658111 7200 1800 86400 30

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Apr 19 15:18:14 CST 2019
;; MSG SIZE  rcvd: 199

还是不行!

那就试试官方文档中的例子 (还是之前链接中 Pod’s hostname and subdomain fields 那一段),不用 Deployment 直接创建 pod 吧。第一步先试试把 hostname 和 subdomain 注释掉:

apiVersion: v1
kind: Service
metadata:
  name: default-subdomain
spec:
  selector:
    name: busybox
  clusterIP: None
  ports:
  - name: foo # Actually, no port is needed.
    port: 1234
    targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostname: busybox-1
  subdomain: default-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox2
  labels:
    name: busybox
spec:
  hostname: busybox-2
  subdomain: default-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

部署然后尝试解析 pod DNS (注意这里 hostname 和 pod 的名字有区别,中间多了减号):

$ kubectl apply -f individual-pods-example.yaml
$ $ dig @10.96.0.10 busybox-1.default-subdomain.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> @10.96.0.10 busybox-1.default-subdomain.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12636
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 5499ded915cf1ff2 (echoed)
;; QUESTION SECTION:
;busybox-1.default-subdomain.default.svc.cluster.local. IN A

;; ANSWER SECTION:
busybox-1.default-subdomain.default.svc.cluster.local. 5 IN A 10.44.0.6

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Apr 19 15:27:38 CST 2019
;; MSG SIZE  rcvd: 163

终于可以了。我实际测试中发现 hostname 和 subdomain 二者都必须显式指定,缺一不可。我修改了一下之前的 nginx deployment 加上 hostname,果然可以解析了:

$ dig @10.96.0.10 nginx.nginx.default.svc.cluster.local

; <<>> DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> @10.96.0.10 nginx.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16903
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 1a664224b34c5f87 (echoed)
;; QUESTION SECTION:
;nginx.nginx.default.svc.cluster.local. IN A

;; ANSWER SECTION:
nginx.nginx.default.svc.cluster.local. 5 IN A   10.32.0.9
nginx.nginx.default.svc.cluster.local. 5 IN A   10.44.0.8

;; Query time: 2 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Fri Apr 19 15:41:25 CST 2019
;; MSG SIZE  rcvd: 184

果然可以解析了。但是因为 deployment 中无法给每个 pod 指定不同的 hostname,所以两个 pod 有同样的 hostname,解析出来两个 IP,跟我们的本意就不符合了。

从这个角度也可以看出,etcd operator 是直接管理 pod,而不是通过 deployment。这可以理解,在这种场景中,没必要也不应该通过 deployment 去管理 pod。可以从源代码中看见 etcd operator 给 pod 设置 hostname 和 subdomain。在 changelog 里,Release 0.2.5 也记录了相应的变动

其实社区也有人呼吁给让 deployment 创建的 pod 也支持 DNS 解析,但是呼声不够高,没有被采纳—— Make pod hostname/subdomain feature compatible with Deployments.

原文地址:https://www.cnblogs.com/yangtzeyankee/p/10736289.html

时间: 2024-10-04 13:37:50

Kubernetes 里,怎么让 Pod 有 DNS 记录?的相关文章

kubernetes里let&#39;s encrypt通配符证书的自动续期更新

环境与需求: Ubuntu云服务器上,已经做好了ssl证书的免费申请,但是证书的期限是3个月,3个月到期后必须重新申请或者更新.由于k8s集群里的服务一直在使用证书,每三个月人工更新太麻烦,所以想要配置一些做个定时自动更新. 准备: 其中, certbot-auto 执行命令,可以对证书进行申请更新删除等一系列操作 dns_script 调用连接服务器控制台设置DNS校验记录的脚本 pytz python的一个模块 一.下载hook功能的脚本文件 git clone https://github

开发者如何快速搭建本地 Kubernetes 集群?Minikube趟坑记录

1.背景 为啥要在本地搭建 Kubernetes 集群?因为开发者可以在本地快速验证自己实现的功能,接口.众所周知,由于 Kubernetes 部署较为复杂,使得广大开发者和运维人员学习和试用 Kubernetes 的门槛很高,光是部署一套 Kubernetes 集群,就需要部署大量的组件,花费精力较大.为了降低用户体验 Kubernetes 的门槛,Minikube 项目应运而生,它是 Github 上的一个开源项目,提供了一键安装的 Kubernetes 本地集群,支持 MacOS,Linu

防止垃圾email的spf的DNS记录

目前垃圾邮件多如牛毛,与之对应的防止方法层出不穷,黑名单,白名单,关键字过滤,特征分析,专门网站提供特征,还有这个SPF. 这个SPF是啥呢,全称为 Sender Policy Framework 是DNS记录配合的一个协议. 目前的DNS服务器大多不支持SPF记录,我还没看见那个DNS服务支持的,那么为了解决这个问题,都是使用该域的txt记录. SPF记录定义了几种方式 + 通过 - 拒绝 ~ 软拒绝 ? 不置可否,也就是不做判断 来看一个例子 synkbit.com     text = "

给网站添加IPv6 DNS记录

一. 1) 使6box提供的DNS64服务,解析出自己网站对应的IPv6域名 Windows: Win+R打开运行,输入cmd,打开命令提示符,输入以下命令 Nslookup www.6box.cn dns64.6box.cn 命令中www.6box.cn改成你的网站名称,如果APP里调用了多个子域名,都需要进行转换,如a.6box.cn ,b.6box.cn 2) 将解析出来的IPv6地址记录添加到DNS域名托管商管理系统里,此操作通常在万网等域名网站里操作,不是在网站服务器上操作,建议直接联

如何使用Kubernetes里的NetworkPolicy

创建一个类型为NetworkPolicy的Kubernetes对象的yaml文件. 第九行的podSelector指定这个NetworkPolicy施加在哪些pod上,通过label来做pod的过滤. 从第16行开始的ingress定义,定义了只有具备标签component=ads,module=app的pod才能够连接component=ads, module=db的pod. 首先创建一个临时的pod,使用正确的label(component=ads,module=app)去访问db pod:

kubernetes集群发布 Pod 端口

kubernetes集群发布Pod 端口 创建测试环境 vi nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: run: my-nginx replicas: 2 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx p

DNS记录类型介绍(A记录、MX记录、NS记录等)

DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 建站名词解释:DNS A记录 NS记录 MX记录 CNAME记录 TXT记录 TTL值 PTR值 泛域名 泛解析 域名绑定 域名转向 1.DNS:Domain Name System 域名管理系统 域名是由圆点分开一串单词或缩写组成的,每一个域名都对应一个惟一的IP地址,这一命名的方法或这样管理域名的系统叫做域名管理系统.  DNS:Domain Name Server 域名服务器 域名虽然便于人们记忆,但网络中

如何验证是否为域控制器创建了 SRV DNS 记录

http://blog.chinaunix.net/uid-641896-id-338662.html 如何验证是否为域控制器创建了 SRV DNS 记录,布布扣,bubuko.com

dns记录整理

由于在使用DNS管理后台之前DNS记录是手动去写入的,记录格式有点乱. 现在按格式整理DNS记录(A记录以及CNAME记录): domain            TTL    type    data www.baidu.com    1800    A    127.0.0.1 #!/bin/bash filelist=`ls | grep "^named"` basedir=`pwd` resdir="$basedir"/dnsdata/ rm -rf &qu