成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

說說 Kubernetes 是怎么實現服務發現的

云計算
我們來說說 Kubernetes 的服務發現。那么首先這個大前提是同主機通信以及跨主機通信都是 ok 的,即同一 Kubernetes 集群中各個 Pod 都是互通的。這點是由更底層的方案實現,包括 docker0/CNI 網橋、Flannel vxlan/host-gw 模式等,在此篇就不展開講了。

我們來說說 Kubernetes 的服務發現。那么首先這個大前提是同主機通信以及跨主機通信都是 ok 的,即同一 Kubernetes 集群中各個 Pod 都是互通的。這點是由更底層的方案實現,包括 docker0/CNI 網橋、Flannel vxlan/host-gw 模式等,在此篇就不展開講了。

[[422281]]

在各 Pod 都互通的前提下,我們可以通過訪問 podIP 來調用 Pod 上的資源,那么離服務發現還有多少距離呢?首先 Pod 的 IP 不是固定的,另一方面我們訪問一組 Pod 實例的時候往往會有負載均衡的需求,那么 Service 對象就是用來解決此類問題的。

集群內通信

Endpoints

Service 首先解決的是集群內通信的需求,首先我們編寫一個普通的 deployment: 

  1. apiVersion: apps/v1 
  2. kind: Deployment 
  3. metadata: 
  4. name: hostnames 
  5. spec: 
  6. selector: 
  7. matchLabels: 
  8.   app: hostnames 
  9. replicas: 3 
  10. template: 
  11. metadata: 
  12.   labels: 
  13.     app: hostnames 
  14. spec: 
  15.   containers: 
  16.     - name: hostnames 
  17.       image: mirrorgooglecontainers/serve_hostname 
  18.       ports: 
  19.         - containerPort: 9376 
  20.           protocol: TCP 

這個應用干的事兒就是訪問它是返回自己的 hostname,并且每個 Pod 都帶上了 APP 為 hostnames 的標簽。

那么我們為這些 pod 編寫一個普通的 Service: 

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4. name: hostnames 
  5. spec: 
  6. selector: 
  7. app: hostnames 
  8. ports: 
  9. namedefault 
  10.   protocol: TCP 
  11.   port: 80 
  12.   targetPort: 9376 

可以看到 Service 通過 selector 選擇 了帶相應的標簽 Pod,而這些被選中的 Pod,成為 Endpoints,我們可以試一下: 

  1. ~/cloud/k8s kubectl get ep hostnames 
  2. NAME        ENDPOINTS 
  3. hostnames   172.28.21.66:9376,172.28.29.52:9376,172.28.70.13:9376 

當某一個 Pod 出現問題,不處于 running 狀態或者 readinessProbe 未通過時,Endpoints 列表會將其摘除。

ClusterIP

以上我們有了 Service 和 Endpoints,而默認創建 Service 的類型是 ClusterIP 類型,我們查看一下之前創建的 Service: 

  1. ~ kubectl get svc hostnames 
  2. NAME        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE 
  3. hostnames   ClusterIP   10.212.8.127   <none>        80/TCP    8m2s 

我們看到 ClusterIP 是 10.212.8.127,那么我們此時可以在 Kubernetes 集群內通過這個地址訪問到 Endpoints 列表里的任意 Pod: 

  1. sh-4.2# curl 10.212.8.127 
  2. hostnames-8548b869d7-9qk6b 
  3. sh-4.2# curl 10.212.8.127 
  4. hostnames-8548b869d7-wzksp 
  5. sh-4.2# curl 10.212.8.127 
  6. hostnames-8548b869d7-bvlw8 

訪問了三次 ClusterIP 地址,返回了三個不同的 hostname,我們意識到 ClusterIP 模式的 Service 自動對請求做了 round robin 形式的負載均衡。

對于此時 ClusterIP 模式 Serivice 來說,它有一個 A 記錄是 service-name.namespace-name.svc.cluster.local,指向 ClusterIP 地址: 

  1. sh-4.2# nslookup hostnames.coops-dev.svc.cluster.local 
  2. Server:     10.212.0.2 
  3. Address:    10.212.0.2#53 
  4.  
  5. Name:   hostnames.coops-dev.svc.cluster.local 
  6. Address: 10.212.8.127 

理所當然我們通過此 A 記錄去訪問得到的效果一樣: 

  1. sh-4.2# curl hostnames.coops-dev.svc.cluster.local 
  2. hostnames-8548b869d7-wzksp 

那對 Pod 來說它的 A 記錄是啥呢,我們可以看一下: 

  1. sh-4.2# nslookup 172.28.21.66  
  2. 66.21.28.172.in-addr.arpa name = 172-28-21-66.hostnames.coops-dev.svc.cluster.local

Headless service

Service 的 CluserIP 默認是 Kubernetes 自動分配的,當然也可以自己設置,當我們將 CluserIP 設置成 None 的時候,它就變成了 Headless service。

Headless service 一般配合 StatefulSet 使用。StatefulSet 是一種有狀態應用的容器編排方式,其核心思想是給予 Pod 指定的編號名稱,從而讓 Pod 有一個不變的唯一網絡標識碼。那這么說來,使用 CluserIP 負載均衡訪問 Pod 的方式顯然是行不通了,因為我們渴望通過某個標識直接訪問到 Pod 本身,而不是一個虛擬 vip。

這個時候我們其實可以借助 DNS,每個 Pod 都會有一條 A 記錄 pod-name.service-name.namespace-name.svc.cluster.local 指向 podIP,我們可以通過這條 A 記錄直接訪問到 Pod。

我們編寫相應的 StatefulSet 和 Service 來看一下: 

  1. --- 
  2. apiVersion: apps/v1 
  3. kind: StatefulSet 
  4. metadata: 
  5. name: hostnames 
  6. spec: 
  7. serviceName: "hostnames" 
  8. selector: 
  9. matchLabels: 
  10.   app: hostnames 
  11. replicas: 3 
  12. template: 
  13. metadata: 
  14.   labels: 
  15.     app: hostnames 
  16. spec: 
  17.   containers: 
  18.     - name: hostnames 
  19.       image: mirrorgooglecontainers/serve_hostname 
  20.       ports: 
  21.         - containerPort: 9376 
  22.           protocol: TCP 
  23.  
  24. --- 
  25. apiVersion: v1 
  26. kind: Service 
  27. metadata: 
  28. name: hostnames 
  29. spec: 
  30. selector: 
  31. app: hostnames 
  32. clusterIP: None 
  33. ports: 
  34. namedefault 
  35.   protocol: TCP 
  36.   port: 80 
  37.   targetPort: 9376 

如上,StatefulSet 和 deployment 并沒有什么不同,多了一個字段 spec.serviceName,這個字段的作用就是告訴 StatefulSet controller,在邏輯處理時使用 hostnames 這個 Service 來保證 Pod 的唯一可解析性。

當你執行 apply 之后,一會你就可以看到生成了對應的 Pod: 

  1. ~ kubectl get pods -w -l app=hostnames 
  2. NAME          READY   STATUS    RESTARTS   AGE 
  3. hostnames-0   1/1     Running   0          9m54s 
  4. hostnames-1   1/1     Running   0          9m28s 
  5. hostnames-2   1/1     Running   0          9m24s 

如意料之中,這里對 Pod 名稱進行了遞增編號,并不重復,同時這些 Pod 的創建過程也是按照編號依次串行進行的。我們知道,使用 deployment 部署的 Pod 名稱會加上 replicaSet 名稱和隨機數,重啟后是不斷變化的。而這邊使用 StatefulSet 部署的 Pod,雖然 podIP 仍然會變化,但名稱是一直不會變的,基于此我們得以通過固定的 DNS A 記錄來訪問到每個 Pod。

那么此時,我們來看一下 Pod 的 A 記錄: 

  1. sh-4.2# nslookup hostnames-0.hostnames 
  2. Server:     10.212.0.2 
  3. Address:    10.212.0.2#53 
  4.  
  5. Name:   hostnames-0.hostnames.coops-dev.svc.cluster.local 
  6. Address: 172.28.3.57 
  7.  
  8. sh-4.2# nslookup hostnames-1.hostnames 
  9. Server:     10.212.0.2 
  10. Address:    10.212.0.2#53 
  11.  
  12. Name:   hostnames-1.hostnames.coops-dev.svc.cluster.local 
  13. Address: 172.28.29.31 
  14.  
  15. sh-4.2# nslookup hostnames-2.hostnames 
  16. Server:     10.212.0.2 
  17. Address:    10.212.0.2#53 
  18.  
  19. Name:   hostnames-2.hostnames.coops-dev.svc.cluster.local 
  20. Address: 172.28.23.31 

和之前的推論一致,我們可以通過 pod-name.service-name.namespace-name.svc.cluster.local 這條 A 記錄訪問到 podIP,在同一個 namespace 中,我們可以簡化為 pod-name.service-name。

而這個時候,Service 的 A 記錄是什么呢: 

  1. sh-4.2# nslookup hostnames 
  2. Server:     10.212.0.2 
  3. Address:    10.212.0.2#53 
  4.  
  5. Name:   hostnames.coops-dev.svc.cluster.local 
  6. Address: 172.28.29.31 
  7. Name:   hostnames.coops-dev.svc.cluster.local 
  8. Address: 172.28.3.57 
  9. Name:   hostnames.coops-dev.svc.cluster.local 
  10. Address: 172.28.23.31 

原來是 Endpoints 列表里的一組 podIP,也就是說此時你依然可以通過service-name.namespace-name.svc.cluster.local這條 A 記錄來負載均衡地訪問到后端 Pod。

iptables

或多或少我們知道 Kubernetes 里面的 Service 是基于 kube-proxy 和 iptables 工作的。Service 創建之后可以被 kube-proxy 感知到,那么它會為此在宿主機上創建對應的 iptables 規則。

以 CluserIP 模式的 Service 為例,首先它會創建一條 KUBE-SERVICES 規則作為入口:

  1. -A KUBE-SERVICES -d 10.212.8.127/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3 

這條記錄的意思是:所有目的地址是 10.212.8.127 這條 CluserIP 的,都將跳轉到 KUBE-SVC iptables 鏈處理。

那么我們來看 KUBE-SVC 鏈都是什么: 

  1. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ 
  2. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3 
  3. -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR 

這組規則其實是用于負載均衡的,我們看到了--probability 依次是 1/3、1/2、1,由于 iptables 規則是自上而下匹配的,所以設置這些值能保證每條鏈匹配到的幾率一樣。處理完負載均衡的邏輯后,又分別將請求轉發到了另外三條規則,我們來看一下: 

  1. -A KUBE-SEP-57KPRZ3JQVENLNBR -s 172.28.21.66/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000  
  2. -A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.21.66:9376 
  3.  
  4. -A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 172.28.29.52/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000  
  5. -A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.29.52:9376 
  6.  
  7. -A KUBE-SEP-X3P2623AGDH6CDF3 -s 172.28.70.13/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000  
  8. -A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 172.28.70.13:9376 

可以看到 KUBE-SEP 鏈就是三條 DNAT 規則,并在 DNAT 之前設置了一個 0x00004000 的標志。DNAT 規則就是在 PREROUTING,即路由作用之前,將請求的目的地址和端口改為 --to-destination 指定的 podIP 和端口。這樣一來,我們起先訪問 10.212.8.127 這個 CluserIP 的請求,就會被負載均衡到各個 Pod 上。

那么 Pod 重啟了,podIP 變了怎么辦?自然是 kube-proxy 負責監聽 Pod 變化以及更新維護 iptables 規則了。

而對于 Headless service 來說,我們直接通過固定的 A 記錄訪問到了 Pod,自然不需要這些 iptables 規則了。

iptables 理解起來比較簡單,但實際上性能并不好。可以想象,當我們的 Pod 非常多時,成千上萬的 iptables 規則將被創建出來,并不斷刷新,會占用宿主機大量的 CPU 資源。一個行之有效的方案是基于 IPVS 模式的 Service,IPVS 不需要為每個 Pod 都設置 iptables 規則,而是將這些規則都放到了內核態,極大降低了維護這些規則的成本。

集群間通信

外界訪問 Service

以上我們講了請求怎么在 Kubernetes 集群內互通,主要基于 kube-dns 生成的 DNS 記錄以及 kube-proxy 維護的 iptables 規則。而這些信息都是作用在集群內的,那么自然我們從集群外訪問不到一個具體的 Service 或者 Pod 了。

Service 除了默認的 CluserIP 模式外,還提供了很多其他的模式,比如 nodePort 模式,就是用于解決該問題的。 

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4. name: hostnames 
  5. spec: 
  6. selector: 
  7. app: hostnames 
  8. type: NodePort 
  9. ports: 
  10. - nodePort: 8477 
  11.   protocol: TCP 
  12.   port: 80 
  13.   targetPort: 9376 

我們編寫了一個 NodePort 模式的 Service,并且設置 NodePort 為 8477,那么意味著我們可以通過任意一臺宿主機的 8477 端口訪問到 hostnames 這個 Service。 

  1. sh-4.2# curl 10.1.6.25:8477 
  2. hostnames-8548b869d7-j5lj9 
  3. sh-4.2# curl 10.1.6.25:8477 
  4. hostnames-8548b869d7-66vnv 
  5. sh-4.2# curl 10.1.6.25:8477 
  6. hostnames-8548b869d7-szz4f 

我們隨便找了一臺 Node 地址去訪問,得到了相同的返回配方。

那么這個時候它的 iptables 規則是怎么作用的呢:

  1. -A KUBE-NODEPORTS -p tcp -m comment --comment "default/hostnames: nodePort" -m tcp --dport 8477 -j KUBE-SVC-67RL4FN6JRUPOJYM 

kube-proxy 在每臺宿主機上都生成了如上的 iptables 規則,通過 --dport 指定了端口,訪問該端口的請求都會跳轉到 KUBE-SVC 鏈上,KUBE-SVC 鏈和之前 CluserIP Service 的配方一樣,接下來就和訪問 CluserIP Service 沒什么區別了。

不過還需要注意的是,在請求離開當前宿主機發往其他 Node 時會對其做一次 SNAT 操作:

  1. -A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE 

可以看到這條 postrouting 規則給即將離開主機的請求進行了一次 SNAT,判斷條件為帶有 0x4000 標志,這就是之前 DNAT 帶的標志,從而判斷請求是從 Service 轉發出來的,而不是普通請求。

需要做 SNAT 的原因很簡單,首先這是一個外部的未經 Kubernetes 處理的請求,如果它訪問 node1,node1 的負載均衡將其轉發給 node2 上的某個 Pod,這沒什么問題,而這個 Pod 處理完后直接返回給外部 client,那么外部 client 就很疑惑,明明自己訪問的是 node1,給自己返回的確是 node2,這時往往會報錯。

SNAT 的作用與 DNAT 相反,就是在請求從 node1 離開發往 node2 時,將源地址改為 node1 的地址,那么當 node2 上的 Pod 返回時,會返回給 node1,然后再讓 node1 返回給 client。 

  1. client 
  2.             | ^ 
  3.             | | 
  4.             v | 
  5. node 2 <--- node 1 
  6. | ^   SNAT 
  7. | |   ---> 
  8. v | 
  9. endpoints 

Service 還有另外 2 種通過外界訪問的方式。適用于公有云的 LoadBalancer 模式的 service,公有云 Kubernetes 會調用 CloudProvider 在公有云上為你創建一個負載均衡服務,并且把被代理的 Pod 的 IP 地址配置給負載均衡服務做后端。另外一種是 ExternalName 模式,可以通過在 spec.externalName 來指定你想要的外部訪問域名,例如 hostnames.example.com,那么你訪問該域名和訪問 service-name.namespace-name.svc.cluser.local 效果是一樣的,這時候你應該知道,其實 kube-dns 為你添加了一條 CNAME 記錄。

Ingress

Service 有一種類型叫作 LoadBalancer,不過如果每個 Service 對外都配置一個負載均衡服務,成本很高而且浪費。一般來說我們希望有一個全局的負載均衡器,通過訪問不同 url,轉發到不同 Service 上,而這就是 Ingress 的功能,Ingress 可以看做是 Service 的 Service。

Ingress 其實是對反向代理的一種抽象,相信大家已經感覺到,這玩意兒和 Nginx 十分相似,實際上 Ingress 是抽象層,而其實現層其中之一就支持 Nginx。

我們可以部署一個 nginx ingress controller:

  1. $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml 

mandatory.yaml是官方維護的 ingress controller,我們看一下: 

  1. kind: ConfigMap 
  2. apiVersion: v1 
  3. metadata: 
  4. name: nginx-configuration 
  5. namespace: ingress-nginx 
  6. labels: 
  7. app.kubernetes.io/name: ingress-nginx 
  8. app.kubernetes.io/part-of: ingress-nginx 
  9. --- 
  10. apiVersion: extensions/v1beta1 
  11. kind: Deployment 
  12. metadata: 
  13. name: nginx-ingress-controller 
  14. namespace: ingress-nginx 
  15. labels: 
  16. app.kubernetes.io/name: ingress-nginx 
  17. app.kubernetes.io/part-of: ingress-nginx 
  18. spec: 
  19. replicas: 1 
  20. selector: 
  21. matchLabels: 
  22.   app.kubernetes.io/name: ingress-nginx 
  23.   app.kubernetes.io/part-of: ingress-nginx 
  24. template: 
  25. metadata: 
  26.   labels: 
  27.     app.kubernetes.io/name: ingress-nginx 
  28.     app.kubernetes.io/part-of: ingress-nginx 
  29.   annotations: 
  30.     ... 
  31. spec: 
  32.   serviceAccountName: nginx-ingress-serviceaccount 
  33.   containers: 
  34.     - name: nginx-ingress-controller 
  35.       image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0 
  36.       args: 
  37.         - /nginx-ingress-controller 
  38.         - --configmap=$(POD_NAMESPACE)/nginx-configuration 
  39.         - --publish-service=$(POD_NAMESPACE)/ingress-nginx 
  40.         - --annotations-prefix=nginx.ingress.kubernetes.io 
  41.       securityContext: 
  42.         capabilities: 
  43.           drop
  44.             - ALL 
  45.           add
  46.             - NET_BIND_SERVICE 
  47.         # www-data -> 33 
  48.         runAsUser: 33 
  49.       env: 
  50.         - name: POD_NAME 
  51.           valueFrom: 
  52.             fieldRef: 
  53.               fieldPath: metadata.name 
  54.         - name: POD_NAMESPACE 
  55.         - name: http 
  56.           valueFrom: 
  57.             fieldRef: 
  58.               fieldPath: metadata.namespace 
  59.       ports: 
  60.         - name: http 
  61.           containerPort: 80 
  62.         - name: https 
  63.           containerPort: 443 

總的來說,我們定義了一個基于 nginx-ingress-controller 鏡像的 Pod,而這個 Pod 自身,是一個監聽 Ingress 對象及其代理后端 Service 變化的控制器。

當一個 Ingress 對象被創建時,nginx-ingress-controller 就會根據 Ingress 對象里的內容,生成一份 Nginx 配置文件(nginx.conf),并依此啟動一個 Nginx 服務。

當 Ingress 對象被更新時,nginx-ingress-controller 就會更新這個配置文件。nginx-ingress-controller 還通過 Nginx Lua 方案實現了 nginx upstream 的動態配置。

為了讓外界可以訪問到這個 Nginx,我們還得給它創建一個 Service 來把 Nginx 暴露出去:

  1. $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml 

這里面的內容描述了一個 NodePort 類型的 Service: 

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4. name: ingress-nginx 
  5. namespace: ingress-nginx 
  6. labels: 
  7. app.kubernetes.io/name: ingress-nginx 
  8. app.kubernetes.io/part-of: ingress-nginx 
  9. spec: 
  10. type: NodePort 
  11. ports: 
  12. name: http 
  13.   port: 80 
  14.   targetPort: 80 
  15.   protocol: TCP 
  16. name: https 
  17.   port: 443 
  18.   targetPort: 443 
  19.   protocol: TCP 
  20. selector: 
  21. app.kubernetes.io/name: ingress-nginx 
  22. app.kubernetes.io/part-of: ingress-nginx 

可以看到這個 Service 僅僅是把 Nginx Pod 的 80/443 端口暴露出去,完了你就可以通過宿主機 IP 和 NodePort 端口訪問到 Nginx 了。

接下來我們來看 Ingress 對象一般是如何編寫的,我們可以參考一個例子。 

  1. apiVersion: extensions/v1beta1 
  2. kind: Ingress 
  3. metadata: 
  4. name: cafe-ingress 
  5. spec: 
  6. tls: 
  7. - hosts: 
  8. - cafe.example.com 
  9. secretName: cafe-secret 
  10. rules: 
  11. - host: cafe.example.com 
  12. http: 
  13.   paths: 
  14.   - path: /tea 
  15.     backend: 
  16.       serviceName: tea-svc 
  17.       servicePort: 80 
  18.   - path: /coffee 
  19.     backend: 
  20.       serviceName: coffee-svc 
  21.       servicePort: 80 

這個 Ingress 表明我們整體的域名是 cafe.example.com,希望通過 cafe.example.com/tea 訪問 tea-svc 這個 Service,通過 cafe.example.com/coffee 訪問 coffee-svc 這個 Service。這里我們通過關鍵字段 spec.rules 來編寫轉發規則。

我們可以查看到 Ingress 對象的詳細信息: 

  1. $ kubectl get ingress 
  2. NAME           HOSTS              ADDRESS   PORTS     AGE 
  3. cafe-ingress   cafe.example.com             80, 443   2h 
  4.  
  5. $ kubectl describe ingress cafe-ingress 
  6. Name:             cafe-ingress 
  7. Namespace:        default 
  8. Address: 
  9. Default backend:  default-http-backend:80 (<none>) 
  10. TLS: 
  11. cafe-secret terminates cafe.example.com 
  12. Rules: 
  13. Host              Path  Backends 
  14. ----              ----  -------- 
  15. cafe.example.com 
  16.                 /tea      tea-svc:80 (<none>) 
  17.                 /coffee   coffee-svc:80 (<none>) 
  18. Annotations: 
  19. Events: 
  20. Type    Reason  Age   From                      Message 
  21. ----    ------  ----  ----                      ------- 
  22. Normal  CREATE  4m    nginx-ingress-controller  Ingress default/cafe-ingress 

我們之前講了我們通過 NodePort 的方式將 nginx-ingress 暴露出去了,而這時候我們 Ingress 配置又希望通過 cafe.example.com 來訪問到后端 Pod,那么首先 cafe.example.com 這個域名得指到任意一臺宿主機 Ip:nodePort上,請求到達 nginx-ingress 之后再轉發到各個后端 Service 上。當然,暴露 nginx-ingress 的方式有很多種,除了 NodePort 外還包括 LoadBalancer、hostNetwork 方式等等。

我們最后來試一下請求: 

  1. $ curl cafe.example.com/coffee 
  2. Server name: coffee-7dbb5795f6-vglbv 
  3. $ curl cafe.example.com/tea 
  4. Server name: tea-7d57856c44-lwbnp 

可以看到 Nginx Ingress controller 已經為我們成功將請求轉發到了對應的后端 Service。而當請求沒有匹配到任何一條 ingress rule 的時候,理所當然我們會得到一個 404。

至此,Kubernetes 的容器網絡是怎么實現服務發現的已經講完了,而服務發現正是微服務架構中最核心的問題,解決了這個問題,那么使用 Kubernetes 來實現微服務架構也就實現了一大半。

 

責任編輯:未麗燕 來源: fredal的博客
相關推薦

2019-12-24 09:39:06

Kubernetes工具微服務

2021-11-17 09:00:00

Kubernetes集群容器

2023-11-29 16:21:30

Kubernetes服務注冊

2022-04-26 05:36:42

服務治理模式

2019-06-09 09:13:14

Istio負載均衡架構

2021-03-16 11:01:02

KubernetesCLI技術

2024-03-06 15:38:06

Spring微服務架構擴展組件

2019-07-12 14:41:31

微服務Kubernetes容器

2022-03-28 11:27:17

Kubernetes運維服務發現

2023-03-06 00:24:05

Kubernetes項目開源

2019-10-30 21:19:42

技術數據結構設計

2024-05-31 09:31:00

2018-07-30 11:53:04

Kubernetes無服務器容器

2022-02-09 07:03:01

SpringNacos服務注冊

2022-08-14 07:04:44

微服務架構設計模式

2021-09-30 08:54:58

prometheus監控遠端服務

2025-04-08 00:00:00

@AsyncSpring異步

2009-02-17 18:52:06

網絡虛擬化路由系統數據中心

2024-09-18 13:49:42

2023-11-27 00:55:43

Eureka服務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线观看日本高清二区 | 久久精品免费看 | 亚洲天堂av网| 日韩免费视频一区二区 | av大片在线 | 91精品在线观看入口 | 黄色大片网| 在线免费观看成年人视频 | 天天综合操 | 日韩有码一区二区三区 | 天天操夜夜拍 | 美女久久视频 | 欧美国产精品一区二区三区 | av日韩一区 | 国产一级在线 | 亚洲国产一区二区三区在线观看 | 日本黄色一级视频 | 免费av观看 | 日韩免费成人av | 精品视频在线一区 | 久草免费在线视频 | 一级毛毛片 | 一区二区国产精品 | 亚洲成a人片 | hitomi一区二区三区精品 | 亚洲第一av | 91偷拍精品一区二区三区 | 精品国产乱码久久久久久果冻传媒 | 九九热在线视频 | 日韩综合网 | 久久99精品国产 | 伊人超碰| 国产一区| 欧美日韩三级 | 亚洲精品成人网 | 亚洲天堂久久 | 中文字幕在线免费 | 国产www在线 | 久久久久久国产精品免费免费 | 国产一区在线看 | 亚洲精品国产第一综合99久久 |