istio 多集群實(shí)踐 -- 獨(dú)立控制面板

istio 是服務(wù)網(wǎng)格的一種實(shí)現(xiàn)诉瓦,目前經(jīng)過(guò)了 1.5 版本的架構(gòu)調(diào)整與重構(gòu)之后,優(yōu)化了很多內(nèi)容固额。istio 可以部署在單一集群中煞聪,也可以部署在多個(gè)集群中昔脯,istio 在多集群中的不同部署方式,可以用于規(guī)劃服務(wù)網(wǎng)格的規(guī)模大小以及控制面納管的集群隧饼,更細(xì)粒度則設(shè)計(jì)服務(wù)的跨集群部署碱鳞、服務(wù)跨集群安全訪問(wèn)等問(wèn)題窿给。

istio 目前提供了兩種多集群部署方案,這兩種方案都可以使多個(gè)集群構(gòu)建為一個(gè)大的服務(wù)網(wǎng)格:

  • 多集群獨(dú)立控制面板:
    每一個(gè)集群部署一套 istio 控制面板禁荒,不同網(wǎng)格間的服務(wù)通過(guò) istio 提供的gateway 相互訪問(wèn)角撞。

  • 多集群共享控制面板
    多集群間使用同一套 istio 控制面板谒所,多集群構(gòu)成一個(gè)大規(guī)模的服務(wù)網(wǎng)格。

本文則著重探究 多集群獨(dú)立控制面板 的相關(guān)內(nèi)容

多集群獨(dú)立控制面板

使用多個(gè)獨(dú)立控制面板將多 K8s 集群構(gòu)建成為一個(gè)服務(wù)網(wǎng)格姐军,需要多個(gè)前置條件:

  • root CA 作為統(tǒng)一的簽發(fā)機(jī)構(gòu)尖淘,每個(gè)控制面板的證書均需要此機(jī)構(gòu)簽發(fā)
  • 跨集群服務(wù)間通信依賴于 istio 的 ingress-gateway 和 egress-gateway
  • 每個(gè)群集中的istio-ingressgateway服務(wù)的IP地址必須可從其他每個(gè)群集訪問(wèn)

    注意村生,此處官方建議使用 L4 負(fù)載均衡(NLB),這個(gè)需要cloud provider 支持辽话。若部署在沒(méi)有 NLB 的環(huán)境中時(shí)屡穗, 可能需要修改負(fù)載平衡的健康檢查。

在不同集群中部署 istio 控制面板

首先需要 root CA 為每個(gè)集群簽發(fā)一套證書,包括 ca-cert.pem ca-key.pem (簽發(fā)好的證書和key)础废、root-cert.pem(根證書)cert-chain.pem(證書鏈)

在部署 istio 控制面之前罕模,執(zhí)行以下命令:

kubectl create ns istio-system
kubectl create secret generic cacerts -n istio-system \
  --from-file=<your path>/ca-cert.pem \
  --from-file=<your path>/ca-key.pem \
  --from-file=<your path>/root-cert.pem \
  --from-file=<your path>/cert-chain.pem \

部署istio

istioctl manifest apply \
    -f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-gateways.yaml

values-istio-multicluster-gateways.yaml是 istio 官方針對(duì)多集群進(jìn)行的配置淑掌,其內(nèi)容如下:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator             # istio Operator 用于部署 istio 組件
spec:
  addonComponents:
    istiocoredns:               # 開(kāi)啟 istiocoredns
      enabled: true

  components:
    egressGateways:             # 開(kāi)啟 egressGateway,因?yàn)閕ngressGateway默認(rèn)開(kāi)啟芋绸,此處沒(méi)有配置
      - name: istio-egressgateway
        enabled: true

  values:
    global:
      # Provides dns resolution for global services
      podDNSSearchNamespaces:
        - global
        - "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global"

      multiCluster:
        enabled: true

      controlPlaneSecurityEnabled: true

    # Multicluster with gateways requires a root CA
    # Cluster local CAs are bootstrapped with the root CA.
    # 關(guān)閉自簽名證書摔敛,使用我們上面創(chuàng)建的證書
    security:
      selfSigned: false

    gateways:
      istio-egressgateway:
        env:
          # Needed to route traffic via egress gateway if desired.
          ISTIO_META_REQUESTED_NETWORK_VIEW: "external"

配置 dns 配置

CoreDNS

在配置 istio dns 之前马昙,我們需要了解一下 coredns 刹悴。目前 K8s 中默認(rèn)使用 CoreDNS 作為service name 解析服務(wù)。

CoreDNS 是一個(gè) CNCF 下的孵化級(jí)項(xiàng)目子房,其主要目的是構(gòu)建一個(gè)快速靈活的 DNS 服務(wù)器池颈,讓用戶可以通過(guò)不同方式訪問(wèn)和使用 DNS 內(nèi)的數(shù)據(jù)钓丰。基于 Caddy 服務(wù)器框架琢歇,CoreDNS 實(shí)現(xiàn)了一個(gè)插件鏈的架構(gòu)李茫,將大量邏輯抽象成插件 Plugin 的形式暴露給使用者,每個(gè)插件都執(zhí)行 DNS 功能秸侣,例如 Kubernetes 的 DNS 服務(wù)發(fā)現(xiàn)宠互、Prometheus 監(jiān)控等予跌。

CoreDNS 使用 Corefile 進(jìn)行配置,在Corefile中定義了以下內(nèi)容:

  • 服務(wù)器以什么協(xié)議監(jiān)聽(tīng)在哪個(gè)端口(可以同時(shí)定義多個(gè) server 監(jiān)聽(tīng)不同端口)
  • 服務(wù)器負(fù)責(zé)哪個(gè) zone 的 authoritative DNS 解析
  • 服務(wù)器將加載哪些插件

Corefile 的典型結(jié)構(gòu)為:

ZONE:[PORT]:
  [PLUGIN]...

下面是一個(gè)Corefile在K8s中的示例:

apiVersion: v1
data:
  Corefile: |
    .:53 {                          # 監(jiān)聽(tīng)域?yàn)楸镜仄到危O(jiān)聽(tīng)端口53
        errors                      # 錯(cuò)誤記錄到標(biāo)準(zhǔn)輸出
        health                      # 健康狀況 可以通過(guò)http://localhost:8080/health查看
        # 根據(jù)服務(wù)的IP響應(yīng)DNS查詢請(qǐng)求航邢,Cluster Domain默認(rèn)為cluster.local
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          #upstream /etc/resolv.conf
          fallthrough in-addr.arpa ip6.arpa
        }
        # 可以通過(guò)http://localhost:9153/metrics獲取prometheus格式的監(jiān)控?cái)?shù)據(jù)
        prometheus :9153
        # 若解析不到考阱,可以向上轉(zhuǎn)發(fā)到 /etc/resolve.conf 中定義的 dns服務(wù)中
        #forward . /etc/resolv.conf
        # 緩存時(shí)間
        cache 30
        loop
        reload
        loadbalance
    }
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
  name: coredns
  namespace: kube-system

當(dāng) CoreDNS 啟動(dòng)后乞榨,它將根據(jù)配置文件啟動(dòng)不同 server 吃既,每臺(tái) server 都擁有自己的插件鏈。當(dāng)有 DNS 請(qǐng)求時(shí)河质,它將依次經(jīng)歷如下 3 步邏輯:

  • 如果有當(dāng)前請(qǐng)求的 server 有多個(gè) zone震叙,將采用貪心原則選擇最匹配的 zone媒楼。
  • 一旦找到匹配的 server,按照 plugin.cfg 定義的順序執(zhí)行插件鏈上的插件扔嵌。
  • 每個(gè)插件將判斷當(dāng)前請(qǐng)求是否應(yīng)該處理,將有以下幾種可能:
    • 請(qǐng)求被當(dāng)前插件處理
      插件將生成對(duì)應(yīng)的響應(yīng)并回給客戶端胁勺,此時(shí)請(qǐng)求結(jié)束署穗,下一個(gè)插件將不會(huì)被調(diào)用嵌洼,如 whoami 插件。
    • 請(qǐng)求不被當(dāng)前插件處理
      直接調(diào)用下一個(gè)插件。如果最后一個(gè)插件執(zhí)行錯(cuò)誤回溺,服務(wù)器返回 SERVFAIL 響應(yīng)混萝。
    • 請(qǐng)求被當(dāng)前插件以 Fallthrough 形式處理
      如果請(qǐng)求在該插件處理過(guò)程中有可能將跳轉(zhuǎn)至下一個(gè)插件逸嘀,該過(guò)程稱為 fallthrough,并以關(guān)鍵字 fallthrough 來(lái)決定是否允許此項(xiàng)操作翼岁,例如 host 插件琅坡,當(dāng)查詢域名未位于 /etc/hosts残家,則調(diào)用下一個(gè)插件。
      • 請(qǐng)求在處理過(guò)程被攜帶 Hint茴晋。
      • 請(qǐng)求被插件處理诺擅,并在其響應(yīng)中添加了某些信息(hint)后繼續(xù)交由下一個(gè)插件處理毫玖。這些額外的信息將組成對(duì)客戶端的最終響應(yīng),如 metric 插件烹玉。

接入 istiocoredns

在一開(kāi)始的部署過(guò)程中二打,我們開(kāi)啟了 istiocoredns,因此在 istio-system namespace中會(huì)出現(xiàn)

NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
istiocoredns   ClusterIP   172.19.XX.XX   <none>         53/UDP,53/TCP   44m

此外症杏,在集群的 CoreDNS 的 Corefile 中厉颤,也已經(jīng)出現(xiàn)了global域的配置:

Corefile: |-
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           upstream
           fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        proxy . /etc/resolv.conf
        cache 30
        reload
    }
    global:53 {
         errors
         cache 30
         proxy . {cluster IP of this istiocoredns service}
    }

下文中 serviceEntry 會(huì)將集群外的服務(wù)配置為 global 域逼友,因此在dns 解析過(guò)程中秤涩,coredns會(huì)將帶有g(shù)lobal的解析請(qǐng)求上傳給 istiocoredns筐眷,由其完成解析工作。

不同集群間的服務(wù)通信

使用 serviceEntry

跨集群的服務(wù)通信依賴于 istio 的 ServiceEntry照棋。假設(shè) A集群中有服務(wù)serviceA振定,需要訪問(wèn)B集群中的serviceB后频,此時(shí)我們需要在 A集群中創(chuàng)建 ServiceEntry 資源,其定義如下:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: serviceB
spec:
  hosts:
  # 此處需要將host 定義為 <serviceName>.<namespace>.global膏执,這樣才能通過(guò) coredns 的global 域從 istiocoredns 中獲取到 serviceB 中的ip
  - serviceB.namespace.global
  # 此處定義 serviceB 是服務(wù)網(wǎng)格中的內(nèi)部服務(wù)更米,因?yàn)锳集群和B集群是公用同一套根證書
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 8000
    protocol: http
  resolution: DNS
  addresses:
  # 此IP 是一個(gè)虛擬IP毫痕,且是A集群無(wú)法訪問(wèn)到的,當(dāng)有訪問(wèn)該IP的數(shù)據(jù)包時(shí)类腮,該流量會(huì)被 sidecar 劫持蛉加,并正確路由针饥。
  - 240.0.0.2
  endpoints:
  # 此 ip 是 B集群中的 istioGateway 的ip
  - address: ${CLUSTER2_GW_ADDR}
    ports:
      http1: 15443 # 此端口為 B集群 istioGateway 的加密端口,服務(wù)間通信均使用 TLS 加密筷凤。

注意上述 yaml 文件中的 address苞七, 如果serviceB有明確的 vip莽鸭,則應(yīng)該直接定義吃靠,否則istio官方建議使用 E類地址 240.0.0.0/4巢块,因?yàn)檫@類地址的流量會(huì)被 sidecar 劫持族奢。當(dāng)sidecar 劫持流量之后,會(huì)直接將流量導(dǎo)向 B集群的 ingressGateway中棚品。

如果 serviceB 有多個(gè)版本铜跑,我們可以在 serviceEntry 中添加 label 指定訪問(wèn)的版本:

endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    labels:
      cluster: cluster2
    ports:
      http1: 15443 # Do not change this port value

之后骡澈,在A集群中,我們可以同樣配置 VirtualServiceDestinationRule

使用egress Gateway

我們也可以使用 egressGateway囤锉,不讓流量從 sidecar 直接流量 B集群的 ingressGateway官地,而是統(tǒng)一走 egressGateway 所在的節(jié)點(diǎn)。這樣做可以統(tǒng)一管理集群邊界拧粪。

使用egressGateway可霎,相應(yīng)的 serviceEntry 需要做如下變動(dòng):

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: serviceB
spec:
  hosts:
  # must be of form name.namespace.global
  - serviceB.namespace.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 8000
    protocol: http
  # 解析規(guī)則設(shè)置為靜態(tài)
  resolution: STATIC
  addresses:
  - 240.0.0.2
  # endpoints 需要指定兩個(gè)ip癣朗,集群B的 ingressGateway ip旺罢;集群A的 egressGateway ip
  endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    network: external
    ports:
      http1: 15443
  - address: ${CLUSTER1_EGW_ADDR}
    ports:
      http1: 15443

總結(jié)

下圖為 pod A 跨集群訪問(wèn)名為 serviceB 的 pod 時(shí)整個(gè)流程圖:


image
  1. podA 的 sidecar 會(huì)劫持出pod 的流量扁达,向集群中的 coredns 解析 serviceB.default.global域名
  2. coredns 根據(jù)global 域向上請(qǐng)求 istioCoreDNS 解析域名正卧,istiocoredns 依據(jù) serviceEntry 將域名解析為 serviceEntry yaml 文件中的address ip
  3. sidecar 發(fā)現(xiàn)返回的ip并不存在,則直接轉(zhuǎn)發(fā)到 serviceEntry 中 clusterB 的 ingressGateway
  4. clusterB ingressGateway 將流量轉(zhuǎn)發(fā)至 podB中

使用Istio網(wǎng)關(guān)跪解,公共根CA和serviceEntry炉旷,可以跨多個(gè)Kubernetes集群配置單個(gè)Istio服務(wù)網(wǎng)格。
以這種方式配置后叉讥,流量可以透明地路由到遠(yuǎn)程集群窘行,而無(wú)需任何應(yīng)用程序的參與。
serviceEntry的創(chuàng)建需要手動(dòng)或程序進(jìn)行創(chuàng)建图仓,istio并不會(huì)為我們創(chuàng)建罐盔。

這種方式部署簡(jiǎn)單,使用較為麻煩惶看,但它對(duì)于多集群是否處于同一網(wǎng)絡(luò)沒(méi)有要求,podIP六孵、service碳竟、namespace也沒(méi)有任何限制。

下一篇將繼續(xù)介紹 istio 多集群的另一種方式:多集群共享控制面板

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狸臣,一起剝皮案震驚了整個(gè)濱河市莹桅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖诈泼,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懂拾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铐达,警方通過(guò)查閱死者的電腦和手機(jī)岖赋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瓮孙,“玉大人唐断,你說(shuō)我怎么就攤上這事『伎伲” “怎么了脸甘?”我有些...
    開(kāi)封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)偏灿。 經(jīng)常有香客問(wèn)我丹诀,道長(zhǎng),這世上最難降的妖魔是什么翁垂? 我笑而不...
    開(kāi)封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任铆遭,我火速辦了婚禮,結(jié)果婚禮上沿猜,老公的妹妹穿的比我還像新娘枚荣。我一直安慰自己,他們只是感情好啼肩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布棍弄。 她就那樣靜靜地躺著,像睡著了一般疟游。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痕支,一...
    開(kāi)封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天颁虐,我揣著相機(jī)與錄音,去河邊找鬼卧须。 笑死另绩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的花嘶。 我是一名探鬼主播笋籽,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼椭员!你這毒婦竟也來(lái)了车海?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤隘击,失蹤者是張志新(化名)和其女友劉穎侍芝,沒(méi)想到半個(gè)月后研铆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡州叠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年棵红,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咧栗。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逆甜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出致板,到底是詐尸還是另有隱情交煞,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布可岂,位于F島的核電站错敢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缕粹。R本人自食惡果不足惜稚茅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望平斩。 院中可真熱鬧亚享,春花似錦、人聲如沸绘面。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)揭璃。三九已至晚凿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瘦馍,已是汗流浹背歼秽。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留情组,地道東北人燥筷。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像院崇,于是被迫代替她去往敵國(guó)和親肆氓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容