OpenShift ClusterOperator-DNS

OpenShift是一個企業(yè)就緒型Kubernetes容器平臺,提供WebUI及網(wǎng)絡(luò)、監(jiān)控、日志收集、身份驗證和授權(quán)、CI/CD、存儲等解決方案,可以實現(xiàn)全棧自動化運維,基于Kubernetes而強于Kubernetes。OpenShift需訂閱使用,社區(qū)版OKD是免費的。本文講解OpenShift集群中的DNS ClusterOperator。
1,DNS的使用場景
OpenShift集群中,使用DNS有下面三個地方:

  • Pod訪問集群外的域名,比如“www.itdecent.cn
  • Pod通過服務(wù)的域名訪問集群中的服務(wù),即服務(wù)發(fā)現(xiàn)功能,需要通過DNS得到Cluster IP從而訪問到對應(yīng)的服務(wù)
  • 集群外部通過域名訪問部署在OpenShift中的服務(wù),需要DNS來解析服務(wù)的集群外域名

下面部分解釋OpenShift 4是如何實現(xiàn)上述三個功能的(OpenShift 3使用了SkyDNS,有很大不同)
2,DNS工作原理
首先要知道Pod從哪里得到DNS服務(wù)的IP。在Linux系統(tǒng)中,DNS服務(wù)器的IP保存在文件“/etc/resolv.conf”中,Pod也不例外。任意選擇運行在集群中的Pod,查看其“/etc/resolv.conf”文件,內(nèi)容如下:

~ $ cat /etc/resolv.conf 
search apache-exporter.svc.cluster.local svc.cluster.local cluster.local okd-infra.example.com
nameserver 172.30.0.10
options ndots:5

172.30.0.10是名為“dns-default”的Service的Cluster IP,

kind: Service
apiVersion: v1
metadata:
  name: dns-default
  namespace: openshift-dns
  selfLink: /api/v1/namespaces/openshift-dns/services/dns-default
  uid: b850c113-a15d-493f-8be8-5302217106aa
  resourceVersion: '10820'
  creationTimestamp: '2020-05-20T13:24:26Z'
  labels:
    dns.operator.openshift.io/owning-dns: default
  ownerReferences:
    - apiVersion: operator.openshift.io/v1
      kind: DNS
      name: default
      uid: b2aadbb6-c743-43d6-b0b5-83e039b319ab
      controller: true
spec:
  ports:
    - name: dns
      protocol: UDP
      port: 53
      targetPort: dns
    - name: dns-tcp
      protocol: TCP
      port: 53
      targetPort: dns-tcp
    - name: metrics
      protocol: TCP
      port: 9153
      targetPort: metrics
  selector:
    dns.operator.openshift.io/daemonset-dns: default
  clusterIP: 172.30.0.10
  type: ClusterIP
  sessionAffinity: None
status:
  loadBalancer: {}

該服務(wù)的后端是以DaemonSet方式部署在每臺宿主機上“dns-default-<id>” Pod,其中核心容器名字為“dns”,運行CoreDNS,完成所有的地址解析和轉(zhuǎn)發(fā)工作(后面詳細(xì)介紹)。
登錄一臺“dns-default-<id>” Pod,查看CoreDNS的配置文件(配置文件的含義可以參考官方文檔,這里不做介紹),

sh-4.2# cat /etc/coredns/Corefile 
.:5353 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        upstream
        fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf {
        policy sequential
    }
    cache 30
    reload
}

請求內(nèi)部域名由帶“kubernetes”插件的CoreDNS處理,請求外部域名由“forward”插件處理。
<1> Pod訪問外部域名
當(dāng)集群內(nèi)的Pod請求外部的域名如“www.toutiao.com”時,從上面的分析可知,請求需要發(fā)送到配置在文件“/etc/reslov.conf”中的DNS服務(wù)器,該文件的內(nèi)容如下,

sh-4.2# cat /etc/resolv.conf 
search okd-infra.example.com
nameserver 10.255.1.1

nameserver的IP和宿主機保持一致(實際文件就是拷貝宿主機的),這就簡單了,當(dāng)集群內(nèi)的Pod需要訪問外部的域名時,由外部的DNS服務(wù)器做解析,和普通的Linux服務(wù)器DNS請求原理一致。
<2> 集群服務(wù)發(fā)現(xiàn)
CoreDNS的“kubernetes”插件實現(xiàn)了基于DNS的服務(wù)發(fā)現(xiàn)(還有一種服務(wù)發(fā)現(xiàn)基于Pod中的環(huán)境變量),該插件解析的DNS name格式是這樣的:<service_name>.<namespace>. svc .cluster.local,解析出的地址是“service_name”的Cluster IP。
比如位于“my-exporter”NameSpace中的服務(wù)“rocketmq-exporter”,登錄集群內(nèi)任意主機,通過集群內(nèi)的DNS服務(wù)做解析,

[core@master-1 ~]$ dig rocketmq-exporter.my-exporter.svc.cluster.local @172.30.0.10

; <<>> DiG 9.11.20-RedHat-9.11.20-1.fc32 <<>> rocketmq-exporter.my-exporter.svc.cluster.local @172.30.0.10
;; 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: 61833
;; 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
; COOKIE: f31e6b5240840234 (echoed)
;; QUESTION SECTION:
;rocketmq-exporter.my-exporter.svc.cluster.local. IN A

;; ANSWER SECTION:
rocketmq-exporter.my-exporter.svc.cluster.local. 5 IN A 172.30.15.144

;; Query time: 1 msec
;; SERVER: 172.30.0.10#53(172.30.0.10)
;; WHEN: Wed Oct 28 10:29:37 UTC 2020
;; MSG SIZE  rcvd: 157

解析出的172.30.15.144就是服務(wù)“rocketmq-exporter”的Cluster IP,

[core@master-1 ~]$ oc get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
rocketmq-exporter   ClusterIP   172.30.15.144   <none>        5557/TCP   2d1h

原理很簡單,安裝“kubernetes”插件的CoreDNS作為客戶端請求kubernetes API Server,得到service、namespace、cluster domain,cluster IP等信息,然后將這些信息通過DNS A記錄(或AAAA記錄)的形式暴露出來給Pod訪問。
<3> 外部訪問集群內(nèi)的服務(wù)
安裝OpenShift 4需要一個安裝配置文件“install-config.yaml”,其中“baseDomain”和“metadata.name”組成了從集群外訪問內(nèi)部服務(wù)的域名,如下,

aneirin@host-1:~$ cat install-config.yaml 
apiVersion: v1
baseDomain: example.com
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 0
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: okd-infra
......

配置集群外使用的DNS服務(wù),

.....
api             IN  A       10.1.95.9        ;  haproxy IP
api-int       IN  A       10.1.95.9        ;  haproxy IP
*.apps        IN  A      10.1.95.9       ;  haproxy IP

筆者通過“bare metal”的方式安裝OpenShift集群,這種搭建方式?jīng)]有現(xiàn)成的“l(fā)oad balancer”可用,需要自己實現(xiàn)load balance功能,實際使用HAProxy。通過上面DNS的配置將訪問集群的外部請求路由到HAProxy,服務(wù)后端是OpenShift的Router pod運行的宿主機,HAProxy配置片段,

......
#---------------------------------------------------------------------
frontend ingress-http
    bind    10.1.95.9:80
    default_backend ingress-http
    mode tcp
#---------------------------------------------------------------------
backend ingress-http
    balance source
    mode        tcp
    server  worker-1    10.1.99.14:80  check port 80
    server  worker-2    10.1.99.15:80  check port 80
#---------------------------------------------------------------------
frontend ingress-https
    bind    10.1.95.9:443
    default_backend ingress-https
    mode tcp
#---------------------------------------------------------------------
backend ingress-https
    balance source
    mode        tcp
    server  worker-1    10.1.99.14:443  check port 443
    server  worker-2    10.1.99.15:443  check port 443
#---------------------------------------------------------------------
......

Router Pod使用了宿主機網(wǎng)絡(luò),和宿主機使用同一個網(wǎng)絡(luò)棧,所以像訪問宿主機一樣訪問Router Pod。
這一部分和Operator DNS的關(guān)系不大,它屬于集群Ingress的范疇,就不深入了。
3,DNS相關(guān)組件介紹
DNS Operator使用DaemonSet部署CoreDNS,這樣保證集群中的每一個宿主機都有一個本地CoreDNS pod副本。DaemonSet部署的Pod含有三個容器:“dns”運行CoreDNS,完成核心的地址解析和轉(zhuǎn)發(fā)服務(wù),“dns-node-resolver”添加集群image registry的DNS name到宿主機的“/etc/hosts”文件,因為宿主機不請求集群的DNS服務(wù),它沒法知道image registry的IP地址,需要“dns-node-resolver”將image registry的地址信息加入宿主機的“/etc/hosts”文件,如下,最后一行就是“dns-node-resolver”添加的,

[core@master-1 ~]$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.30.238.6 image-registry.openshift-image-registry.svc \
 image-registry.openshift-image-registry.svc.cluster.local # openshift-generated-node-resolver

還有一個名為 “kube-rbac-proxy”的容器和授權(quán)相關(guān),不講解。當(dāng)Pod請求DNS name時,它不是直接請求本地的“dns-default-<id>” Pod,而是請求“openshift-dns”namespace中的“dns-default”服務(wù),由該服務(wù)隨機選擇一個“dns-default-<id>” Pod完成查詢,當(dāng)然請求的“dns-default-<id>” Pod可能運行在別的宿主機上。
總結(jié)
本文對OpenShift 4集群DNS服務(wù)的原理和相關(guān)組件做簡單介紹,Kubernetes同樣有參考價值,有任何問題歡迎交流指正,也希望這篇文章能幫到正在努力前進的你。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容