在雲端環境中佈署 NGINX 虛擬機器已成為常見的 Web 服務架構。本文將以 Azure 和 GCP 為例,逐步說明如何在雲端平台上建立和組態 NGINX 虛擬機器,並涵蓋網路設定、NGINX 安裝以及後續的機器映像建立。此外,文章也將探討在沒有雲端原生負載平衡器的情況下,如何使用 Route 53 等 DNS 服務進行流量路由和容錯移轉,以確保服務的高用性。更進一步,本文將探討如何利用 NGINX 實作高效能負載平衡,包含地理路由、自動容錯移轉以及負載平衡三明治架構等進階設定,並以 AWS、Azure 和 GCP 等平台為例,說明如何在不同雲端環境中佈署和組態 NGINX,以滿足動態擴充套件和高用性的需求。最後,文章將詳細介紹如何使用 NGINX 作為 API 閘道器,包含設定內部路由、定義 API 金鑰、啟用身份驗證和速率限制等,提供一個完整的 API 管理解決方案。

在雲端環境中佈署 NGINX 虛擬機器

本章節將以 Azure 為例,介紹如何在雲端環境中佈署 NGINX 虛擬機器(VM)。雖然本例使用 Azure,但核心概念同樣適用於其他雲端供應商,如 AWS、GCP 和 DigitalOcean。

建立新的虛擬機器

  1. 在 Azure 虛擬機器控制檯中建立新的 VM。
  2. 選擇 Azure 訂閱和資源群組。如果沒有資源群組,可以建立一個新的。
  3. 提供 VM 名稱、區域、可用性選項、安全型別和基礎映像。選擇您最熟悉的 Linux 發行版。
  4. 設定 VM 大小和系統管理員帳戶。確保開啟 SSH 連線埠 22,以便稍後進行遠端存取。
  5. 進入磁碟組態部分,根據工作負載需求選擇適當的磁碟組態。考慮到磁碟大小和速度,如果您將使用 NGINX 來提供靜態資產或快取資源。

網路組態

  1. 在網路部分,選擇或建立新的虛擬網路和子網路。
  2. 為 VM 分配公用 IP 位址,以便從公用網際網路存取。同時確保開啟 SSH 連線埠 22。
  3. 為了方便稍後的清理,可以選擇在刪除 VM 時一併刪除公用 IP 和 NIC。

完成建立虛擬機器

  1. 除非有特殊需求,否則其他部分的設定可以保留預設值。
  2. 檢閱組態並點選「建立」按鈕。Azure 將建立並組態所有必要的資源。
  3. 建立完成後,點選「前往資源」按鈕以檢視新建立的 VM 資訊。

存取虛擬機器並安裝 NGINX

  1. 在 VM 的「屬性」標籤的「網路」部分找到公用 IP 位址。使用此 IP 位址和系統管理員憑證進行 SSH 連線。
  2. 透過套件管理器安裝 NGINX 或 NGINX Plus。根據需要組態 NGINX 並重新載入。

安裝 NGINX 範例程式碼

# 在 Ubuntu 上安裝 NGINX
sudo apt update
sudo apt install nginx

內容解密:

  • sudo apt update:更新套件列表,以確保安裝的是最新版本的 NGINX。
  • sudo apt install nginx:安裝 NGINX。

建立 NGINX 機器映像

本文將以 GCP 為例,介紹如何建立 NGINX 機器映像。雖然本例使用 GCP,但核心概念同樣適用於其他雲端供應商。

建立機器映像的步驟

  1. 在 VM 上安裝並組態 NGINX 後,將啟動磁碟的自動刪除狀態設為 false。
  2. 編輯 VM,在磁碟組態部分取消選取「刪除例項時刪除啟動磁碟」的核取方塊。
  3. 刪除例項,但不要選取刪除啟動磁碟的選項。這樣,您將保留一個已安裝 NGINX 的未附加啟動磁碟。
  4. 從 Google Compute Engine 控制檯的「映像」部分,建立一個新的 Compute Image。使用未附加的 NGINX 啟動磁碟作為來源磁碟。

使用機器映像的好處

使用機器映像可以確保每個例項的組態完全相同,避免因套件版本不同而導致的問題。您可以驗證每個套件是否按照預期執行,從而提高服務的可靠性。

無雲端原生負載平衡器的情況下路由到 NGINX 節點

本文將介紹如何在沒有雲端原生負載平衡器的情況下,將流量路由到多個 NGINX 節點,或建立主備容錯移轉設定。

使用 Amazon Route 53 DNS 服務

  1. 使用 Amazon Route 53 DNS 服務將流量路由到多個活動的 NGINX 節點。
  2. 組態健康檢查和容錯移轉,以實作主備高用性設定。

DNS 負載平衡的優點

DNS 長期以來一直用於在伺服器之間平衡負載。Route 53 提供了多種進階功能,如多個 IP 位址對應到單個 A 記錄、權重分配等。您可以利用這些功能實作負載平衡和高用性。

使用 Route 53 的健康檢查功能

// Route 53 健康檢查範例組態
{
  "Type": "HTTP",
  "ResourcePath": "/healthcheck",
  "IPAddress": "192.0.2.1",
  "Port": 80,
  "RequestInterval": "30",
  "FailureThreshold": "3"
}

內容解密:

  • Type:指定健康檢查型別為 HTTP。
  • ResourcePath:指定健康檢查的 URI 路徑。
  • IPAddressPort:指定要檢查的 IP 位址和連線埠。
  • RequestIntervalFailureThreshold:定義檢查頻率和判定失敗的閾值。

在雲端環境中佈署NGINX實作高效能負載平衡

在現代雲端架構中,NGINX已成為實作高效能負載平衡和流量管理的關鍵元件。本章將探討如何在不同雲端平台(如AWS、Azure和GCP)上佈署NGINX,以滿足動態擴充套件和高用性的需求。

地理路由與自動容錯移轉

利用Amazon Route 53的DNS服務,可以根據使用者的地理位置將流量導向最近的健康節點。當執行多個活動-活動組態的基礎設施時,可以透過健康檢查自動容錯移轉到其他地理位置。

實作自動DNS記錄管理

為了實作NGINX節點的自動擴充套件和DNS記錄管理,可以使用Amazon Auto Scaling生命週期掛鉤觸發指令碼,這些指令碼透過Amazon CLI或SDK與Route 53 API互動,動態新增或刪除NGINX機器的IP和健康檢查組態。

負載平衡三明治架構

在需要對NGINX層進行自動擴充套件並在應用伺服器之間均勻分配負載的場景中,可以採用負載平衡三明治架構。此架構涉及在NGINX層前後分別佈署網路負載平衡器(NLB),使NGINX能夠無縫地與Auto Scaling群組整合。

架構設計與實作

  1. 建立網路負載平衡器(NLB):組態NLB並建立目標群組,將其與NLB的監聽器關聯。
  2. 組態Auto Scaling群組:建立Auto Scaling群組並組態啟動範本,確保NGINX在EC2例項上安裝。將Auto Scaling群組與目標群組連結,實作自動註冊和登出。
  3. 應用伺服器組態:將應用伺服器置於另一個NLB和目標群組後,並組態NGINX代理到應用NLB。

架構優勢

  • 自動註冊與健康檢查:NLB與Auto Scaling群組的整合實作了新節點的自動註冊和被終止節點的移除,以及健康檢查,確保流量只被導向健康的節點。
  • 內部流量管理:透過內部NLB,服務可以在不離開網路的情況下透過NGINX呼叫其他服務,使NGINX成為應用程式流量路由的核心。

在Azure中使用虛擬機器擴充套件集擴充套件NGINX

在Azure環境中,可以透過虛擬機器擴充套件集(VMSS)和Azure負載平衡器實作NGINX的高用性和動態資源利用。

實施步驟

  1. 建立Azure負載平衡器:組態負載平衡器,可以是公用或內部。
  2. 佈署NGINX虛擬機器映像:將NGINX虛擬機器映像佈署到VMSS中。
  3. 組態後端池和負載平衡規則:將負載平衡器的後端池組態到VMSS,並設定負載平衡規則。

優勢

  • 動態擴充套件:VMSS允許根據需求動態擴充套件NGINX例項。
  • 健康檢查:Azure負載平衡器提供健康檢查功能,確保流量只被導向健康的NGINX節點。

為Google App Engine建立代理

在需要為Google App Engine建立代理以進行上下文切換或在自定義域下提供HTTPS服務的場景中,可以在Google Compute Engine上使用NGINX。

實作方法

  1. 建立虛擬機器或例項範本:在Google Compute Engine上建立虛擬機器或使用安裝了NGINX的虛擬機器映像建立例項範本。
  2. 組態NGINX代理:組態NGINX代理到Google App Engine端點,確保使用HTTPS加密通訊。

透過上述方法,可以在不同雲端環境中靈活佈署NGINX,實作高效能的負載平衡和流量管理,滿足現代雲端架構的需求。

在 Google App Engine 前使用 NGINX

在將請求代理到 Google App Engine 時,需要在 NGINX 中將端點設定為變數,然後在 proxy_pass 指令中使用該變數,以確保 NGINX 在每次請求時進行 DNS 解析。要使 NGINX 進行 DNS 解析,還需要使用 resolver 指令並指向您喜歡的 DNS 解析器。Google 提供 8.8.8.8 這個 IP 地址供公眾使用。如果您使用的是 NGINX Plus,您將能夠在 upstream 區塊中的 server 指令上使用 resolve 旗標,保持連線活性和 upstream 模組的其他好處。

您可以選擇將 NGINX 設定檔儲存在 Google Cloud Storage 中,然後使用案例項的啟動指令碼在啟動時提取設定。這樣,您就可以在不需重新建立映像檔的情況下更改設定。然而,這將增加 NGINX 伺服器的啟動時間。

討論

當您使用自己的網域並希望透過 HTTPS 使應用程式可用時,您會希望在 Google App Engine 前面執行 NGINX。目前,Google App Engine 不允許您上傳自己的 SSL 證書。因此,如果您希望在非 Google 提供的 appspot.com 網域下提供應用程式並進行加密,您需要建立一個使用 NGINX 的代理來監聽您的自定義網域。NGINX 將加密自己與客戶端之間以及與 Google App Engine 之間的通訊。

另一個在 Google App Engine 前面執行 NGINX 的原因是為了在同一個網域下託管多個 App Engine 應用程式,並使用 NGINX 進行根據 URI 的上下文切換。微服務是一種流行的架構,使用像 NGINX 這樣的代理進行流量路由是很常見的。Google App Engine 使佈署應用程式變得容易,與 NGINX 結合使用,您就擁有了一個完整的功能性應用程式交付平台。

第 11 章:容器/微服務

11.0 簡介

容器在應用層提供了一層抽象,將套件和依賴項的安裝從佈署轉移到構建過程。這很重要,因為工程師現在正在交付可以在任何環境中以統一方式執行和佈署的程式碼單元。推廣容器作為可執行單元減少了環境之間的依賴和組態問題。因此,組織一直在推動將應用程式佈署到容器平台上。在容器平台上執行應用程式時,通常會盡可能地容器化整個堆積疊,包括代理或負載平衡器。NGINX 可以輕鬆地容器化和交付。它還包括許多功能,使交付容器化應用程式更加流暢。本章重點介紹構建 NGINX 容器映像、在容器化環境中更方便使用的功能,以及在 Kubernetes 和 OpenShift 上佈署您的映像。

使用容器時的架構考慮

在容器化服務時,為了利用 Docker 日誌驅動程式,日誌必須輸出到 /dev/stdout,錯誤日誌則導向 /dev/stderr。這樣,日誌就會串流到 Docker 日誌驅動程式,該驅動程式能夠原生地將它們路由到集中式日誌伺服器。

在使用 NGINX Plus 的容器化環境中,也需要考慮負載平衡方法。least_time 負載平衡方法是在考慮到容器化網路疊加的情況下設計的。透過偏好較低的回應時間,NGINX Plus 將傳入請求傳遞給平均回應時間最快的上游伺服器。當所有伺服器都足夠負載平衡且效能相當時,NGINX Plus 可以根據網路延遲進行最佳化,優先處理網路鄰近度最近的伺服器。

11.1 使用 NGINX 作為 API 閘道器

問題

您需要一個 API 閘道器來驗證、驗證、操作和路由傳入的請求,以滿足您的使用案例。

解決方案

使用 NGINX 作為 API 閘道器。API 閘道器為一個或多個 API 提供入口點。NGINX 非常適合這個角色。本文將重點介紹一些核心概念,並參考本文中的其他章節以取得更多詳細資訊。同樣重要的是要注意,NGINX 已釋出了一本關於此主題的完整電子書:《Deploying NGINX as an API Gateway》,作者是 Liam Crilly。

首先,為您的 API 閘道器在自己的檔案中定義一個 server 區塊。像 /etc/nginx/api_gateway.conf 這樣的名稱就很合適:

server {
    listen 443 ssl;
    server_name api.company.com;
    # SSL 設定參見第 7 章
    default_type application/json;
}

新增基本錯誤處理回應

proxy_intercept_errors on;
error_page 400 = @400;
location @400 { return 400 '{"status":400,"message":"Bad request"}\n'; }
error_page 401 = @401;
location @401 { return 401 '{"status":401,"message":"Unauthorized"}\n'; }
error_page 403 = @403;
location @403 { return 403 '{"status":403,"message":"Forbidden"}\n'; }
error_page 404 = @404;
location @404 { return 404 '{"status":404,"message":"Resource not found"}\n'; }

載入 API 閘道器組態

上述 NGINX 組態段可以直接新增到 /etc/nginx/api_gateway.conf 中的 server 區塊中,或者放在單獨的檔案中,並透過 include 指令匯入。include 指令在配方 1.6 中有介紹。使用 include 指令將此伺服器組態匯入到 http 上下文中的主 nginx.conf 檔案中:

include /etc/nginx/api_gateway.conf;

定義上游伺服器端點

您現在需要定義上游伺服器端點。第 2 章介紹了負載平衡,其中討論了 upstream 區塊。提醒一下,upstreamhttp 上下文中有效,而不在 server 上下文中。以下內容必須包含或設定在 server 區塊之外:

upstream service_1 {
    server 10.0.0.12:80;
    server 10.0.0.13:80;
}

upstream service_2 {
    server 10.0.0.14:80;
    server 10.0.0.15:80;
}

設定說明:

  1. Server區塊定義:首先定義了一個監聽443埠並啟用SSL的伺服器區塊,用於接收HTTPS請求。
  2. 錯誤處理:設定了錯誤頁面處理,當發生特定HTTP錯誤時傳回對應的JSON格式錯誤訊息。
  3. 包含組態:使用include指令將API閘道器組態匯入主組態檔案中,實作組態的模組化管理。
  4. 上游服務定義:定義了上游服務群組,用於負載平衡後端服務請求。

這樣,NGINX 就被組態為一個API閘道器,能夠有效地管理和路由傳入的API請求,同時提供錯誤處理和負載平衡功能。

使用NGINX作為API閘道器

API閘道器為API提供了一個進入點。為了實作這個功能,NGINX可以被組態為驗證、授權、轉換和路由請求到不同的服務之間。本文將展示如何使用NGINX來實作這些功能。

設定內部路由位置

首先,為每個服務建立一個內部路由位置(internally routable location)於伺服器區塊內:

location = /_service_1 {
    internal;
    # 對服務的共同組態
    proxy_pass http://service_1/$request_uri;
}

location = /_service_2 {
    internal;
    # 對服務的共同組態
    proxy_pass http://service_2/$request_uri;
}

內容解密:

  • location = /_service_1location = /_service_2:定義了兩個內部路由位置,分別對應服務1和服務2。
  • internal;:表示這些位置只能被內部請求存取,不能直接被外部客戶端存取。
  • proxy_pass http://service_1/$request_uri;proxy_pass http://service_2/$request_uri;:將請求代理到指定的服務,並且保留原始的請求URI。

建立API閘道器的目錄結構

接下來,建立一個新的目錄來存放API閘道器的組態檔案:

mkdir /etc/nginx/api_conf.d/

定義服務的具體路由規則

/etc/nginx/api_conf.d/目錄下,建立檔案來定義每個服務的路由規則。例如:

location /api/service_1/object {
    limit_except GET PUT { deny all; }
    rewrite ^ /_service_1 last;
}

location /api/service_1/object/[^/]*$ {
    limit_except GET POST { deny all; }
    rewrite ^ /_service_1 last;
}

內容解密:

  • limit_except GET PUT { deny all; }limit_except GET POST { deny all; }:限制了允許的HTTP方法,除了GET和PUT或GET和POST之外,其他方法都被拒絕。
  • rewrite ^ /_service_1 last;:將請求重寫到先前定義的內部路由位置,並且使用last標誌來指示NGINX重新處理請求。

包含組態檔案

在伺服器區塊中,包含API閘道器的組態檔案:

server {
    listen 443 ssl;
    server_name api.company.com;
    # SSL設定參見第7章
    default_type application/json;
    include api_conf.d/*.conf;
}

內容解密:

  • include api_conf.d/*.conf;:包含了/etc/nginx/api_conf.d/目錄下的所有.conf檔案,使得NGINX可以載入API閘道器的組態。

啟用身份驗證和速率限制

使用map指令來定義API金鑰與客戶端名稱之間的對映關係:

map $http_apikey $api_client_name {
    default "";
    "j7UqLLB+yRv2VTCXXDZ1M/N4" "client_one";
    "6B2kbyrrTiIN8S8JhSAxb63R" "client_two";
    "KcVgIDSY4Nm46m3tXVY3vbgA" "client_three";
}

定義速率限制區域:

limit_req_zone $http_apikey zone=limitbyapikey:10m rate=100r/s;
limit_req_status 429;

在特定的位置區塊中啟用速率限制和身份驗證:

location /api/service_2/object {
    limit_req zone=limitbyapikey;
    if ($http_apikey = "") {
        return 401;
    }
    if ($api_client_name = "") {
        return 403;
    }
    limit_except GET PUT { deny all; }
    rewrite ^ /_service_2 last;
}

內容解密:

  • limit_req zone=limitbyapikey;:啟用了速率限制,使用之前定義的limitbyapikey區域。
  • if ($http_apikey = "") { return 401; }if ($api_client_name = "") { return 403; }:檢查API金鑰是否存在以及是否有效,如果無效則傳回相應的HTTP狀態碼。