最近在弄AlertManager,发现其集群模式需要知道各个AlertManager节点的IP地址,而我们现在需要在2个K8s集群同时部署AlertManager上来创建一套AlertManager,以确保在某一个K8s集群挂了后报警还能发出来,同时确保当2个K8s集群都正常的时候,一个告警只发一次出来。

但怎么在A集群上找到B集群上的POD的IP,这是个问题。通过研究,我们发现CoreDns可以很好的解决这个问题。

假设我们现在有2套集群,2套集群使用的DNS后缀都是cluster.local,容器网段及service网段都不一样。

我们现在在A集群上,先看旧的CoreDNS的配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        log . {combined} {
          class error
        }
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        reload
        loadbalance
        #rewrite name saas-fe-zhan.internal.com public-fe-zhan-node-dev.public-fe-node-dev.svc.cluster.local
    }
        

可以看到,只配置了默认根域,我们可以再增加一个B集群的域的配置。修改CoreDNS的配置如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        log . {combined} {
          class error
        }
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        reload
        loadbalance
        #rewrite name saas-fe-zhan.internal.com public-fe-zhan-node-dev.public-fe-node-dev.svc.cluster.local
    }
    cluster.dev.:53 {
        log . {combined} {
          class error
        }
        errors
        health
        ready
        kubernetes cluster.dev {
          kubeconfig /etc/coredns/RemoteK8sConfig context1
        }
        cache 30
        reload
        loadbalance
    }    

  RemoteK8sConfig: |
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JS==
        server: https://k8s-apiserver.internal.com:8443
      name: cluster1
    contexts:
    - context:
        cluster: cluster1
        user: user1
      name: context1
    current-context: context1
    kind: Config
    preferences: {}
    users:
    - name: user1
      user:
        client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JS=
        client-key-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JS=    

需要注意的是kubeconfig /etc/coredns/RemoteK8sConfig context1中的context1表示kubeconfig文件中的上下文名,这个参数官方文档显示为可选,实际上按照我的测试,不写会出现如下报错:

plugin/kubernetes: ./coreconf:24 - Error during parsing: Wrong argument count or unexpected line ending after '/etc/coredns/RemoteK8sConfig'

将以上配置生效,修改CoreDns的Depolyment,增加RemoteK8sConfig配置加载:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: CoreDNS
  name: coredns
  namespace: kube-system
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kube-dns
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: k8s-app
                  operator: In
                  values:
                  - kube-dns
              topologyKey: kubernetes.io/hostname
            weight: 100
      containers:
      - args:
        - -conf
        - /etc/coredns/Corefile
        image: coredns/coredns:1.8.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 5
        name: coredns
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /etc/coredns
          name: config-volume
          readOnly: true
      dnsPolicy: Default
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: coredns
      serviceAccountName: coredns
      terminationGracePeriodSeconds: 30
      tolerations:
      - key: CriticalAddonsOnly
        operator: Exists
      volumes:
      - configMap:
          defaultMode: 420
          items:
          - key: Corefile
            path: Corefile
          - key: RemoteK8sConfig
            path: RemoteK8sConfig
          name: coredns
        name: config-volume

CoreDns的配置重启后,我们现在测试和验证效果:

通过查询DNS kubernetes.default.svc.cluster.localkubernetes.default.svc.cluster.dev可以看到解析出来的IP是不一样的。说明配置是有生效的。

[root@sh-saas-k8stest-master-dev-01 yaml]# dig @10.248.1.193 kubernetes.default.svc.cluster.local

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @10.248.1.193 kubernetes.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: 49170
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

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

;; ANSWER SECTION:
kubernetes.default.svc.cluster.local. 5	IN A	10.248.252.1

;; Query time: 0 msec
;; SERVER: 10.248.1.193#53(10.248.1.193)
;; WHEN: Mon Dec 13 18:48:25 CST 2021
;; MSG SIZE  rcvd: 117

[root@sh-saas-k8stest-master-dev-01 yaml]# dig @10.248.1.193 kubernetes.default.svc.cluster.dev

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @10.248.1.193 kubernetes.default.svc.cluster.dev
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59137
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

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

;; ANSWER SECTION:
kubernetes.default.svc.cluster.dev. 5 IN A	10.253.252.1

;; Query time: 0 msec
;; SERVER: 10.248.1.193#53(10.248.1.193)
;; WHEN: Mon Dec 13 18:48:29 CST 2021
;; MSG SIZE  rcvd: 113

再查一下B集群上的一个有状态服务的POD DNS,也没问题。

[root@sh-saas-k8stest-master-dev-01 yaml]# dig @10.248.1.193 vmstorage-victoria-metrics-k8s-stack-0.vmstorage-victoria-metrics-k8s-stack.victoria.svc.cluster.dev

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @10.248.1.193 vmstorage-victoria-metrics-k8s-stack-0.vmstorage-victoria-metrics-k8s-stack.victoria.svc.cluster.dev
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15816
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;vmstorage-victoria-metrics-k8s-stack-0.vmstorage-victoria-metrics-k8s-stack.victoria.svc.cluster.dev. IN A

;; ANSWER SECTION:
vmstorage-victoria-metrics-k8s-stack-0.vmstorage-victoria-metrics-k8s-stack.victoria.svc.cluster.dev. 5	IN A 10.253.7.107

;; Query time: 0 msec
;; SERVER: 10.248.1.193#53(10.248.1.193)
;; WHEN: Mon Dec 13 18:47:57 CST 2021
;; MSG SIZE  rcvd: 245

[root@sh-saas-k8s1-master-dev-01 ~]# kubectl get pod vmstorage-victoria-metrics-k8s-stack-0 -n victoria -o wide
NAME                                     READY   STATUS    RESTARTS   AGE     IP             NODE          NOMINATED NODE   READINESS GATES
vmstorage-victoria-metrics-k8s-stack-0   2/2     Running   1          5d23h   10.253.7.107   10.12.97.33   <none>           <none>

最后,留一个问题,2个K8s集群配置的域名后缀都是cluster.local,为什么通过后缀cluster.dev却能查出来结果?