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同樣有參考價值,有任何問題歡迎交流指正,也希望這篇文章能幫到正在努力前進的你。