在 AWS EKS 上佈署應用程式後,若要從外部網路存取服務,需要設定 Ingress 控制器。本文將逐步說明如何使用 Contour Ingress 控制器解決 EKS 服務的外部連線問題。首先,透過 kubectl exec 指令在 Pod 內部執行 curl 指令,確認服務本身運作正常。接著,佈署 Contour Ingress 控制器,並使用 kubectl get pods 確認 Pod 狀態。佈署完成後,透過 kubectl get ingress 取得 Ingress 資源的外部連線位址,即可從外部網路使用 curl 指令測試連線。最後,文章說明如何使用 HTTPProxy 設定多個服務的路由規則,並提供詳細的 YAML 設定檔範例,方便讀者參考與實作。

在EKS中實作Ingress服務的挑戰與解決方案

在前面的章節中,我們已經成功在AWS EKS(Elastic Kubernetes Service)上佈署了應用程式並掛載了EFS(Elastic File System)。然而,在嘗試從本地工作站存取服務時,卻遇到了無法連線的問題。這是因為工作節點位於AWS VPC網路內,而本地工作站則在本地網路中,兩者之間沒有直接的網路連線。

為什麼在microk8s中可以運作而在EKS中不行?

在microk8s的設定中,Ingress資源和工作站位於同一網路中,因此可以正常運作。然而,在AWS EKS的情況下,由於網路環境的不同,導致無法直接存取服務。

從Pod內部驗證服務

為了確認服務是否正常運作,我們可以從Pod內部執行命令來驗證。首先,我們需要取得Pod的名稱,如以下清單16-32所示。

清單16-32. 取得Pod名稱

kubectl get pods

輸出結果如下:

NAME                                    READY   STATUS    RESTARTS   AGE
mydeployment-64845ffdff-c2677           1/1     Running   0          48m
primeornot-79f775bb8c-8hjq2             1/1     Running   0          92m

接下來,我們選擇mydeployment-64845ffdff-c2677這個Pod,並從中執行CURL命令,如清單16-33所示。

清單16-33. 從Pod內部存取nginx伺服器

kubectl exec -i -t mydeployment-64845ffdff-c2677 -- curl localhost

輸出結果如下:

<html>
  <title>Hello from EFS!</title>
  <body>
    This content is served to you by the EFS that is mounted on this pod that is running this nginx! <br>
    we just inserted brs in this file <br>
    How cool, eh!<br>
  </body>
</html>

內容解密:

此命令使用kubectl exec在指定的Pod內部執行curl localhost命令,驗證nginx伺服器是否正常運作。輸出結果顯示了nginx伺服器傳回的HTML內容,證明服務正在Pod內正常運作。

將服務暴露給外部網路

為了讓外部網路可以存取我們的服務,我們需要佈署一個Ingress控制器。在清單16-30中,我們可以看到Ingress資源的ADDRESS欄位是空的,這是因為我們尚未佈署Ingress控制器。

為什麼需要Ingress控制器?

Ingress控制器是Kubernetes中的一個重要元件,負責實作Ingress資源定義的路由規則。在microk8s中,啟用Ingress外掛時會自動佈署Ingress控制器,而在EKS中,這是一個需要手動執行的兩步驟過程。

佈署Contour Ingress控制器

我們選擇使用Contour作為Ingress控制器,因為它易於上手且功能強大。按照Contour官方檔案的指示,我們可以透過執行以下命令來佈署Contour Ingress控制器,如清單16-34所示。

清單16-34. 佈署Contour Ingress控制器的前置條件

kubectl apply -f https://projectcontour.io/quickstart/contour.yaml

輸出結果如下:

namespace/projectcontour created
serviceaccount/contour created
serviceaccount/envoy created
configmap/contour created
customresourcedefinition.apiextensions.k8s.io/contourconfigurations.projectcontour.io created
customresourcedefinition.apiextensions.k8s.io/contourdeployments.projectcontour.io created
customresourcedefinition.apiextensions.k8s.io/extensionservices.projectcontour.io created
customresourcedefinition.apiextensions.k8s.io/httpproxies.projectcontour.io created
customresourcedefinition.apiextensions.k8s.io/tlscertificatedelegations.projectcontour.io created
serviceaccount/contour-certgen created
rolebinding.rbac.authorization.k8s.io/contour created
role.rbac.authorization.k8s.io/contour-certgen created
job.batch/contour-certgen-v1.23.2 created
clusterrolebinding.rbac.authorization.k8s.io/contour created
rolebinding.rbac.authorization.k8s.io/contour-rolebinding created
clusterrole.rbac.authorization.k8s.io/contour created
role.rbac.authorization.k8s.io/contour created
service/contour created
service/envoy created
deployment.apps/contour created
daemonset.apps/envoy created

內容解密:

此命令使用kubectl apply來佈署Contour Ingress控制器所需的各種資源,包括名稱空間、服務帳戶、組態對映、自定義資源定義等。這些資源的建立使得Contour Ingress控制器能夠正常運作。

驗證Contour Ingress控制器的佈署

佈署完成後,我們可以透過以下命令驗證Contour Ingress控制器的Pod是否正常運作,如清單16-35所示。

清單16-35. 驗證Contour Ingress控制器Pod的狀態

kubectl get pods -n projectcontour

輸出結果如下:

NAME                                    READY   STATUS    RESTARTS   AGE
contour-684bc99dd9-9ls8s              1/1     Running   0          12m
contour-684bc99dd9-ln4dm              1/1     Running   0          12m
contour-certgen-v1.23.2-fr25g0         1/1     Completed 0          12m
envoy-f9tq9                            2/2     Running   0          12m

內容解密:

此命令使用kubectl get pods來取得projectcontour名稱空間中的Pod狀態。可以看到Contour和Envoy的Pod都處於Running狀態,表示Ingress控制器已經成功佈署。

取得Ingress資源的外部地址

佈署Contour Ingress控制器後,我們可以透過以下命令取得Ingress資源的詳細資訊,如清單16-36所示。

清單16-36. 取得Ingress資源的詳細資訊

kubectl get ingress

輸出結果如下:

NAME          CLASS     HOSTS   ADDRESS                                               PORTS   AGE
myingress01   <none>    *       aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com   80      35m

內容解密:

此命令使用kubectl get ingress來取得Ingress資源的詳細資訊。可以看到Ingress資源已經獲得了一個外部地址aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com,這使得我們可以從外部存取服務。

測試外部存取

我們可以使用CURL命令來測試透過Ingress控制器提供的外部地址存取nginx服務,如清單16-37所示。

清單16-37. 透過Ingress控制器提供的外部地址存取nginx服務

curl aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com

輸出結果如下:

<html>
  <title>Hello from EFS!</title>
  <body>
    This content is served to you by the EFS that is mounted on this pod that is running this nginx! <br>
    we just inserted brs in this file <br>
    How cool, eh!<br>
  </body>
</html>

內容解密:

此命令使用curl來存取Ingress控制器提供的外部地址,驗證nginx服務是否可以從外部存取。輸出結果與從Pod內部存取的結果一致,證明服務已經成功暴露給外部網路。

描述Ingress資源

為了進一步瞭解Ingress資源的組態和狀態,我們可以使用kubectl describe命令,如清單16-38所示。

清單16-38. 描述Ingress資源

kubectl describe ingress myingress01

內容解密:

此命令使用kubectl describe來取得Ingress資源的詳細描述,包括其組態、事件和狀態等資訊。透過這些資訊,我們可以更好地理解Ingress資源的工作原理和當前狀態。

Kubernetes 網路組態與 Ingress 控制器詳解

在現代雲原生架構中,Kubernetes 已成為容器協調的標準。隨著微服務架構的普及,如何有效地管理服務之間的網路流量成為一大挑戰。本章將探討 Kubernetes 中的網路組態,特別是如何使用 Ingress 控制器來公開叢集內部的服務給外部使用者。

Ingress 資源的描述與管理

在 Kubernetes 中,Ingress 資源定義瞭如何將外部請求路由到叢集內部的服務。以下是一個典型的 Ingress 資源描述範例:

kubectl describe ingress

輸出結果可能如下所示:

Name: myingress01
Namespace: default
Address: aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com
Default backend: label-nginx:80 (172.31.7.31:80)
Rules:
Host Path Backends
---- ---- --------
* * label-nginx:80 (172.31.7.31:80)
Annotations: <none>
Events: <none>

內容解密:

  • Name:Ingress 資源的名稱。
  • Namespace:Ingress 所屬的名稱空間。
  • Address:與此 Ingress 相關聯的負載平衡器地址。
  • Default backend:預設後端服務,用於處理不符合任何規則的請求。
  • Rules:定義瞭如何將請求路由到後端服務。

使用 HTTPProxy 公開多個服務

當需要公開多個服務時,可以使用 HTTPProxy(由 Contour 提供)。HTTPProxy 允許我們定義虛擬主機並將請求路由到不同的後端服務。

建立 HTTPProxy 組態檔

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: myingress01
spec:
  virtualhost:
    fqdn: aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com
  routes:
  - conditions:
    - prefix: /
    services:
    - name: primeornot
      port: 80
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: myingress02
spec:
  virtualhost:
    fqdn: myeksnginx.example.org
  routes:
  - conditions:
    - prefix: /
    services:
    - name: label-nginx
      port: 80

內容解密:

  • apiVersionkind:定義了資源的 API 版本和型別。
  • metadata.name:HTTPProxy 資源的名稱。
  • spec.virtualhost.fqdn:虛擬主機的網域名稱。
  • spec.routes:定義了請求路由規則,將符合特定條件的請求路由到指定的後端服務。

套用 HTTPProxy 組態並驗證

kubectl apply -f eks-myingress03.yaml
kubectl get httpproxy

輸出結果可能如下所示:

NAME         FQDN                                             TLS SECRET   STATUS   STATUS DESCRIPTION
myingress01  aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com             valid    Valid HTTPProxy
myingress02  myeksnginx.example.org                                      valid    Valid HTTPProxy

內容解密:

  • kubectl apply:套用新的 HTTPProxy 組態。
  • kubectl get httpproxy:列出所有 HTTPProxy 資源及其狀態。

測試服務可存取性

為了測試服務是否正確公開,可以使用 curl 指令存取組態的網域名稱:

curl myeksnginx.example.org
curl aa1555cf26850457789cb252f01a8e1b-851197561.us-east-2.elb.amazonaws.com

內容解密:

  • curl:用於測試 HTTP 服務的工具。
  • 透過存取不同的網域名稱,可以驗證請求是否正確路由到對應的後端服務。

關鍵概念

  • Ingress:Kubernetes 資源,用於管理外部存取叢集內服務的規則。
  • HTTPProxy:由 Contour 提供的資源,用於定義虛擬主機和請求路由規則。
  • 負載平衡器:將外部流量分配到叢集內多個節點的服務。

參考資料

程式碼範例

  graph LR;
    A[外部請求] -->|路由規則|> B[Ingress Controller];
    B --> C[HTTPProxy];
    C --> D[後端服務1];
    C --> E[後端服務2];

圖表翻譯: 此圖表展示了外部請求如何透過 Ingress Controller 和 HTTPProxy 被路由到不同的後端服務。

隨著 Kubernetes 生態系統的不斷發展,Ingress 和相關工具的功能將進一步增強,為管理複雜的微服務架構提供更強大的支援。未來章節將繼續探討 Kubernetes 相關技術和最佳實踐。