给 Pod 添加 DNS 记录

我们都知道 StatefulSet 中的 Pod 是拥有单独的 DNS 记录的,比如一个 StatefulSet 名称为 etcd,而它关联的 Headless SVC 名称为 etcd-headless,那么 CoreDNS 就会为它的每个 Pod 解析如下的 A 记录:

  • etcd-0.etcd-headless.default.svc.cluster.local
  • etcd-1.etcd-headless.default.svc.cluster.local
  • ……

那么除了 StatefulSet 管理的 Pod 之外,其他的 Pod 是否也可以生成 DNS 记录呢?

如下所示,我们这里只有一个 Headless 的 SVC,并没有 StatefulSet 管理的 Pod,而是 ReplicaSet 管理的 Pod,我们可以看到貌似也生成了类似于 StatefulSet 中的解析记录。

这是怎么做到的呢?按照我们常规的理解会认为这是一个 StatefulSet 管理的 Pod,但其实这里是不同的 ReplicaSet 而已。这里的实现其实是因为 Pod 自己本身也是可以有自己的 DNS 记录的,所以我们是可以去实现一个类似于 StatefulSet 的 Pod 那样的解析记录的。

首先我们来部署一个 Deployment 管理的普通应用,其定义如下:

# nginx.yaml
apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

部署后创建了两个 Pod:

$ kubectl apply -f nginx.yaml
deployment.apps/nginx created
$ kubectl get pod -l app=nginx -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-5d59d67564-2cwdz   1/1     Running   0          19s   10.244.1.68    node1   <none>           <none>
nginx-5d59d67564-bp5br   1/1     Running   0          19s   10.244.2.209   node2   <none>           <none>

然后定义如下的 Headless Service:

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  clusterIP: None
  ports:
  - name: http
    port: 80
    protocol: TCP
  selector:
    app: nginx
  type: ClusterIP

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

$ kubectl apply -f ervice.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                      38d
nginx                      ClusterIP   None             <none>        80/TCP                       7s
$ dig @10.96.0.10 nginx.default.svc.cluster.local

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> @10.96.0.10 nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2573
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx.default.svc.cluster.local. IN	A

;; ANSWER SECTION:
nginx.default.svc.cluster.local. 30 IN	A	10.244.2.209
nginx.default.svc.cluster.local. 30 IN	A	10.244.1.68

;; Query time: 19 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Nov 25 11:44:41 CST 2020
;; MSG SIZE  rcvd: 154

然后我们对 nginx 的 FQDN 域名进行 dig 操作,可以看到返回了多条 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-5d59d67564-bp5br.nginx.default.svc.cluster.local

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> @10.96.0.10 nginx-5d59d67564-bp5br.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 10485
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx-5d59d67564-bp5br.nginx.default.svc.cluster.local.	IN A

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

;; Query time: 4 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Nov 25 11:47:31 CST 2020
;; MSG SIZE  rcvd: 176

可以看到并没有得到解析结果。官方文档中有一段 Pod’s hostname and subdomain fields 说明:

Pod 规约中包含一个可选的 hostname 字段,可以用来指定 Pod 的主机名。 当这个字段被设置时,它将优先于 Pod 的名字成为该 Pod 的主机名。 举个例子,给定一个 hostname 设置为 “my-host” 的 Pod, 该 Pod 的主机名将被设置为 “my-host”。Pod 规约还有一个可选的 subdomain 字段,可以用来指定 Pod 的子域名。 举个例子,某 Pod 的 hostname 设置为 “foo”,subdomain 设置为 “bar”, 在名字空间 “my-namespace” 中对应的完全限定域名(FQDN)为 “foo.bar.my-namespace.svc.cluster-domain.example”

现在我们编辑一下 nginx.yaml 加上 subdomain 测试下看看:

apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      subdomain: nginx
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

更新部署再尝试解析 Pod DNS:

$ kubectl apply -f nginx.yaml
$ kubectl get pod -l app=nginx -o wide
NAME                     READY   STATUS        RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
nginx-78f58d8bcb-6kctm   1/1     Running       0          8s      10.244.2.210   node2   <none>           <none>
nginx-78f58d8bcb-6tbnv   1/1     Running       0          15s     10.244.1.69    node1   <none>           <none>
$ dig @10.96.0.10 nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> @10.96.0.10 nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 34172
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx-78f58d8bcb-6kctm.nginx.default.svc.cluster.local.	IN A

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

;; Query time: 2 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Nov 25 11:52:18 CST 2020
;; MSG SIZE  rcvd: 176

可以看到依然不能解析,那就试试官方文档中的例子 ,不用 Deployment 直接创建 Pod 吧。第一步先将 hostname 和 subdomain 注释掉:

# individual-pods-example.yaml
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

现在我们看到有 ANSWER 记录回来了,hostname 和 subdomain 二者都必须显式指定,缺一不可。一开始我们的截图中的实现方式其实也是这种方式。

现在我们修改一下之前的 nginx deployment 加上 hostname,重新解析:

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

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> @10.96.0.10 nginx.nginx.default.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21127
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx.nginx.default.svc.cluster.local. IN A

;; ANSWER SECTION:
nginx.nginx.default.svc.cluster.local. 30 IN A	10.244.2.211
nginx.nginx.default.svc.cluster.local. 30 IN A	10.244.1.70

;; Query time: 1 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Nov 25 11:55:37 CST 2020
;; MSG SIZE  rcvd: 172

可以看到解析成功了,但是因为 Deployment 中无法给每个 Pod 指定不同的 hostname,所以两个 Pod 有同样的 hostname,解析出来两个 IP,跟我们的本意就不符合了。

不过知道了这种方式过后我们就可以自己去写一个 Operator 去直接管理 Pod 了,给每个 Pod 设置不同的 hostname 和一个 Headless SVC 名称的 subdomain,这样就相当于实现了 StatefulSet 中的 Pod 解析。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 在Kubernetes集群中,每个Pod都有一个内置的DNS服务器,该服务器可以通过服务名称和DNS域名的形式来解析服务和Pod的IP地址。 要在Pod中配置DNS,你需要在Pod的`spec`字段中的`dnsConfig`字段中进行设置。例如,以下是一个Pod定义文件的示例,其中包含了DNS配置信息: ```yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: nginx:1.14 dnsConfig: nameservers: - 8.8.8.8 - 8.8.4.4 searches: - my.dns.search.suffix options: - name: edns0 hostname: my-hostname subdomain: my-subdomain ``` 在这个示例中,我们设置了两个DNS服务器(8.8.8.8和8.8.4.4),一个DNS搜索后缀(my.dns.search.suffix)和一个EDNS0选项(可选)。我们还设置了Pod的主机名(my-hostname)和子域名(my-subdomain)。 请注意,你需要使用kubectl或其他Kubernetes客户端工具来创建或修改Pod定义文件,然后使用`kubectl apply`命令来部署Pod到集群中。 希望这能帮到你! ### 回答2: PodDNS 配置主要依赖于 Kubernetes 的 DNS 服务。Kubernetes 默认提供了一个集群内部的 DNS 服务,该服务会为 Pod 分配一个唯一的 DNS 域名。要配置 PodDNS,可以按照以下步骤进行操作: 1. 首先,在 Pod 定义文件中,确保将 `dnsPolicy` 参数设置为 `ClusterFirst`,这样 Pod 就会使用集群内部的 DNS 服务。 2. 然后,如果要在 Pod 中访问集群外部的域名,需要为 Pod 分配一个或多个 DNS 服务器的 IP 地址。可以使用 Pod 的环境变量 `dnsConfig` 来指定这些 DNS 服务器的 IP 地址。例如: ``` apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image dnsConfig: nameservers: - 8.8.8.8 - 8.8.4.4 ``` 在上述例子中,我们为 Pod 分配了谷歌的 DNS 服务器的 IP 地址。 3. 最后,可以使用 `kube-dns` 命令行工具来验证 PodDNS 配置是否生效。例如,可以在 Pod 内部执行如下命令: ``` kubectl exec -it my-pod -- nslookup example.com ``` 这会查找 `example.com` 的 IP 地址,并返回结果。 总之,通过适当配置 Pod 的 `dnsPolicy` 参数和 `dnsConfig` 参数,可以确保 Pod 正确地使用 Kubernetes 的 DNS 服务,并可以访问集群内外的域名。 ### 回答3: Pod如何配置DNS取决于Pod所依赖的Kubernetes集群的配置。Kubernetes集群通过DNS服务来帮助Pod进行服务发现和网络通信。 要配置PodDNS,可以按照以下步骤进行: 首先,在Pod定义文件中指定DNS配置。在spec部分添加`dnsConfig`字段,设置需要的DNS选项。可以设置`nameservers`字段指定DNS服务器的IP地址,或设置`searches`字段指定搜索域的顺序。 其次,确保Kubernetes集群中存在一个运行着的DNS服务,例如CoreDNS或kube-dns。这些服务会处理Pod发出的DNS请求,并将其路由到正确的服务或IP地址。 然后,通过创建一个ConfigMap来配置DNS服务。使用kubectl创建一个ConfigMap对象,包含要配置的DNS选项,例如nameservers和searches。然后,在Pod的spec部分的`dnsConfig`字段中引用这个ConfigMap。 最后,部署Pod。当Pod启动时,它将使用定义的DNS配置进行网络通信和服务发现。 需要注意的是,DNS配置的生效可能需要一些时间,因此在进行配置时需要等待一段时间,以确保Pod可以正确地解析域名和发现所需的服务。 总之,配置PodDNS需要定义PodDNS配置选项,并确保Kubernetes集群中存在运行的DNS服务。通过引用ConfigMap来指定DNS配置,并启动Pod以生效配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CN-FuWei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值