<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?DNS在Kubernetes中的高階玩法(一)

          共 6256字,需瀏覽 13分鐘

           ·

          2020-11-16 23:39

          云原生小白

          看到上面藍(lán)色字了么?關(guān)注下吧!

          自從 Kubernetes1.11 之后,CoreDNS 作為集群內(nèi)默認(rèn)的域名解析服務(wù),你是否對它還僅僅還停留在對 Kubernetes 的 Service 解析呢?事實上光 DNS 在 K8S 內(nèi)就有很多有意思的操作,今天我們不妨來看看 CoreDNS 的各種高階玩法。

          1. 自定義 hosts 解析

          默認(rèn)情況下,Kubernetes 集群內(nèi)的容器要解析外部域名時,CoreDNS 會將請求轉(zhuǎn)發(fā)給/etc/resolv.conf文件里指定的上游 DNS 服務(wù)器。這個是由這個配置決定的。

          forward?.?/etc/resolv.conf

          有的時候,我們?nèi)绻枰?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(245, 70, 0);">集群內(nèi)全局劫持某個域名時,我們通??梢岳?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(245, 70, 0);">hosts插件來幫忙。hosts插件會每隔 5s 將需解析的信息重新加載到 coredns 當(dāng)中,當(dāng)你有任何變化時直接更新它的配置區(qū)塊即可。常見的 host 有兩種方法配置,分別如下:

          • 定義 host
          .:53?{
          ????hosts?{
          ????????1.1.1.1?test.cloudxiaobai.com
          ????????2.2.2.2?test2.cloudxiaobai.com
          ????????fallthrough
          ????}
          }
          • 加載 hosts 文件
          #直接從/etc/hosts加載host信息
          .?{
          ????hosts?{
          ????????fallthrough
          ????}
          }

          #又或者,從當(dāng)前目錄的test.hosts文件中加載host信息

          .?{
          ????hosts?test.hosts?{
          ????????fallthrough
          ????}
          }

          當(dāng)被需要解析的域名不在 hosts 當(dāng)中時,需要用fallthrough繼續(xù)將請求轉(zhuǎn)發(fā)給其它插件繼續(xù)處理

          擴展

          如果我們只是想在 Workloads 內(nèi)局部生效部分 host 信息時,那么可以借助于HostAliases向Pod的/etc/hosts文件內(nèi)添加主機信息。我們拿 deployment 來舉例,

          apiVersion:?extensions/v1beta1
          kind:?Deployment
          spec:
          ??template
          ????spec:
          ??????containers:
          ??????-?image:?busybox:latest
          ????????name:?nginx
          ??????hostAliases:
          ??????-?ip:?1.1.1.1
          ????????hostnames:
          ????????-?test1.cloudxiaobai.com
          ??????-?ip:?2.2.2.2
          ????????hostnames:
          ????????-?test1.cloudxiaobai.com
          ...

          2. 支持 SRV 記錄

          SRV 記錄是域名系統(tǒng)中用于指定服務(wù)器提供服務(wù)的位置(如主機名和端口)數(shù)據(jù)。它在 DNS 記錄中的是個新鮮面孔,在 RFC2082 中才對 SRV 記錄進行了定義,因此有很多老舊服務(wù)器并不支持SRV記錄。SRV 在 RFC2082 定義的標(biāo)準(zhǔn)記錄格式如下:

          #英文
          _Service._Proto.Name?TTL?Class?SRV?Priority?Weight?Port?Target

          #中文
          _服務(wù)._協(xié)議.名稱.?TTL?類別?SRV?優(yōu)先級?權(quán)重?端口?主機.
          • Service :服務(wù)的符號名稱
          • Proto :服務(wù)的傳輸協(xié)議,通常為 TCP 或 UDP,Proto 不區(qū)分大小寫
          • Name :此 RR 所指的域名,在這個域名下 SRV RR 是唯一的
          • TTL :標(biāo)準(zhǔn) DNS 存活時間
          • CLASS :標(biāo)準(zhǔn) DNS 類別值(此值總為 IN)
          • Priority :目標(biāo)主機的優(yōu)先級,值越小越優(yōu)先,范圍 0-65535
          • Weight :相同優(yōu)先度記錄的相對權(quán)重,值越大越優(yōu)先
          • Port :服務(wù)所在的 TCP 或 UDP 端口
          • Target : 提供服務(wù)的規(guī)范主機名,以半角句號結(jié)尾

          在 Kubernetes 里面,CoreDNS 會為有名稱的端口創(chuàng)建SRV記錄,這些端口可以是 svc 或 headless.svc 的一部分。對每個命名端口,SRV 記錄了一個類似下列格式的記錄:

          _port-name._port-protocol.my-svc.my-namespace.svc.cluster.local

          在 Golang 中我們用 net.LookupSRV 來發(fā)起 SRV 記錄查詢

          func?(r?*Resolver)?LookupSRV(ctx?context.Context,?service,?proto,?name?string)?(cname?string,?addrs?[]*SRV,?err?error)

          net 庫里對 SRV 結(jié)構(gòu)體里定義了 4 個字段,分別是Target,Port,Priority,Wright。當(dāng)我們使用LookupSRV發(fā)起 SRV 查詢時,得到的返回的記錄會按優(yōu)先級排序,并在優(yōu)先級內(nèi)按權(quán)重進行隨機分配。如果 service 和 proto 均為空字符串,則 LookupSRV 直接查找 name。

          拿 thanos 的 SRV 查詢舉個例子

          1. 第一步 resolver.go 中 SRV 查詢邏輯

          thanos 中的 resolver.go 里面包含了處理 SRV 查詢的邏輯,如下:

          ?case?SRV,?SRVNoA:
          ??_,?recs,?err?:=?s.resolver.LookupSRV(ctx,?"",?"",?host)
          ??if?err?!=?nil?{
          ???return?nil,?errors.Wrapf(err,?"lookup?SRV?records?%q",?host)
          ??}

          ??for?_,?rec?:=?range?recs?{
          ???resPort?:=?port
          ???if?resPort?==?""?{
          ???//獲取SRV返回的端口
          ????resPort?=?strconv.Itoa(int(rec.Port))
          ???}

          ???if?qtype?==?SRVNoA?{
          ?????????//如果不需要使用A或者AAAA記錄查詢時,則組合主機名:端口
          ????res?=?append(res,?appendScheme(scheme,?net.JoinHostPort(rec.Target,?resPort)))
          ????continue
          ???}
          ???//?Do?A?lookup?for?the?domain?in?SRV?answer.
          ???resIPs,?err?:=?s.resolver.LookupIPAddr(ctx,?rec.Target)
          ???if?err?!=?nil?{
          ????return?nil,?errors.Wrapf(err,?"look?IP?addresses?%q",?rec.Target)
          ???}
          ???//根據(jù)主機名遍歷出所有的ip地址,并組合成ip:port的方式
          ???for?_,?resIP?:=?range?resIPs?{
          ????res?=?append(res,?appendScheme(scheme,?net.JoinHostPort(resIP.String(),?resPort)))
          ???}

          第二步 創(chuàng)建 Kubernetes Service

          CoreDNS 中對于有名稱的 port,會為其創(chuàng)建一條對應(yīng)的 SRV 記錄。

          apiVersion:?v1
          kind:?Service
          metadata:
          ??labels:
          ????app:?thanos-receiver
          ??name:?thanos-receiver
          ??namespace:?monitor
          spec:
          ??ClusterIP:?None
          ??ports:
          ??-?name:?grpc
          ????port:?10901
          ????protocol:?TCP
          ????targetPort:?10901

          如上結(jié)構(gòu)的 Service 我們就可以使用如下方式查詢域名:

          _grpc._tcp.thanos-receiver.monitor.svc.cluster.local

          我們用 dig 命令做一次 SRV 記錄查詢就可以得到響應(yīng),可以看到下列的ANSWER SECTION中得到了 net 庫里面定義的 SRV 結(jié)構(gòu)體的數(shù)據(jù)了,并且 CoreDNS 返回了三條記錄:

          #?dig?srv?_grpc._tcp.thanos-receiver.monitor.svc.cluster.local

          ...
          ;;?ANSWER?SECTION:
          _grpc._tcp.thanos-receiver.monitor.svc.cluster.local.?6?IN?SRV?0?33?10901?10-59-155-238.thanos-receiver.monitor.svc.cluster.local.
          _grpc._tcp.thanos-receiver.monitor.svc.cluster.local.?6?IN?SRV?0?33?10901?10-59-42-68.thanos-receiver.monitor.svc.cluster.local.
          _grpc._tcp.thanos-receiver.monitor.svc.cluster.local.?6?IN?SRV?0?33?10901?10-59-48-162.thanos-receiver.monitor.svc.cluster.local.

          ;;?ADDITIONAL?SECTION:
          10-59-48-162.thanos-receiver.monitor.svc.cluster.local.?6?IN?A?10.59.48.162
          10-59-42-68.thanos-receiver.monitor.svc.cluster.local.?6?IN?A?10.59.42.68
          10-59-155-238.thanos-receiver.monitor.svc.cluster.local.?6?IN?A?10.59.155.238
          ...

          可以看到這條 SRV 記錄里面,分別返回了三個服務(wù)的IP地址、端口、以及服務(wù)的優(yōu)先級權(quán)重

          第三步 使用 SRV 記錄做服務(wù)發(fā)現(xiàn)

          對于代碼中啟用了 SRV 記錄的業(yè)務(wù),只需要在業(yè)務(wù)配置里面加上需要訪問的 SRV 地址即可,例如 thanos-query 需要調(diào) thanos-receiver 的 grpc 端口做監(jiān)控數(shù)據(jù)查詢,如果我們集群內(nèi)有多個 receiver 服務(wù)的話,我們就像如下配置,即可做到 DNS 的服務(wù)發(fā)現(xiàn):

          ...
          ????spec:
          ??????containers:
          ??????-?args:
          ????????-?query
          ????????#?定義thanos-receiver服務(wù)SRV記錄
          ????????-?--store=dnssrv+_grpc._tcp.thanos-receiver.monitor.svc.cluster.local
          ...

          當(dāng)服務(wù)正常運行后我們就可以查到 receiver 服務(wù)以及注冊到 query 里面了

          3. NodeLocal DNSCache

          有很多同學(xué)經(jīng)常會抱怨,在 Kubernetes 中有時候會遇到 DNS 解析間歇性 5s 超時的問題。其實這個問題社區(qū)很早意識到 DNS 的經(jīng)過 Iptables 到 Conntrack 遇到競爭的問題,并給出來利用 Daemonset 在集群的每個 Node 上運行一個精簡版的 CoreDNS 并監(jiān)聽一個虛擬 ip 地址來繞過 Conntrack,同時還能充當(dāng)緩存環(huán)境 CoreDNS 壓力。此舉能大幅降低 DNS 查詢 timeout 的頻次,提升服務(wù)穩(wěn)定性。

          關(guān)于部署

          node-local-dns通過添加 iptables 規(guī)則能夠接收節(jié)點上所有發(fā)往 169.254.20.10 的 dns 查詢請求,把針對集群內(nèi)部域名查詢請求路由到 coredns。把集群外部域名請求直接通過 host 網(wǎng)絡(luò)發(fā)往本地/etc/resolv.conf記錄的外部 DNS 服務(wù)器中。

          #?下載部署腳本
          $?curl?https://node-local-dns.oss-cn-hangzhou.aliyuncs.com/install-nodelocaldns.sh

          #?部署,確保kubectl能夠連接集群
          $?bash?install-nodelocaldns.sh

          如何使用

          NodeLocal DNSCache的部署并不會直接產(chǎn)生效果,通常我們有兩種方式可以讓集群的 pod 使用上本機 DNS 緩存。

          1. 定制業(yè)務(wù)容器 dnsConfig

          Kubernetes 的 workload 中允許我們自定義 dns 相關(guān)的配置,其中我們需要注意以下幾點:

          • dnsPolicy: None,不使用 ClusterDNS。
          • 配置 searches,保證集群內(nèi)部域名能夠被正常解析。
          • 適當(dāng)降低 ndots 值,當(dāng)前 ACK 集群 ndots 值默認(rèn)為 5,降低 ndots 值有利于加速集群外部域名訪問。
          • 適當(dāng)調(diào)整 options 參數(shù),避免并發(fā)請求single-request和分開 A 和 AAAA 請求采用的源端口single-request-reopen

          可以參考如下

          dnsPolicy:?None
          dnsConfig:
          ????nameservers:?["169.254.20.10"]
          ????searches:
          ????-?default.svc.cluster.local
          ????-?svc.cluster.local
          ????-?cluster.local
          ????options:
          ????-?name:?ndots
          ??????value:?"2"
          ????-?name:?single-request-reopen
          ??????value:?""
          ????-?name:?timeout
          ??????value:?"1"

          2. 修改 Kubelet 配置

          kubelet 啟動參數(shù)中可以通過參數(shù)--cluster-dns來指定容器的 nameserver,我們只需將它修改成169.254.20.10重啟即可。不過容器要真正將 NodeLocal DNSCache 用起來話,還得將Pod重啟才會生效。

          4. 禁用 IPv6 域名解析

          有時候我們 Kubernetes 集群內(nèi)沒有啟用 IPv6 的話,可以在 CoreDNS 內(nèi)禁止 IPv6 的域名解析,這個時候我們可以用 Template 這個插件來解決:

          .:53?{
          ????template?ANY?AAAA?{
          ????????rcode?NXDOMAIN
          ????}
          ...
          }

          這條記錄會將所有的 AAAA 查詢直接返回NXDOMAIN,并且不會被轉(zhuǎn)發(fā)給其它插件處理

          --- 未完待續(xù) ---



          點贊鼓勵一下

          瀏覽 101
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人A√在线 | 后入美女视频 | www.翔田千里 | 黄色一级片免费观看 | 激情射av|