Go工程師體系課 018

12次閱讀

API 網關與持續部署入門(Kong & Jenkins)

對應資料目錄《第 2 章 Jenkins 入門》《第 3 章 通過 Jenkins 部署服務》,整理 Kong 與 Jenkins 在企業級持續交付中的實戰路徑。即便零基礎,也能順着步驟搭建出自己的網關 + 持續部署流水線。

課前導覽:什麼是 API 網關

API 網關位於客戶端與後端微服務之間,相當於系統的“統一入口”。它負責接收外部請求、根據配置路由到不同的後端服務,並在入口層完成一系列通用能力(認證、鑑權、限流、監控、協議轉換等),從而簡化客戶端調用流程、降低服務之間的耦合。

graph LR
    ClientA[Web 客戶端] --> APIGateway[API Gateway]
    ClientB[移動端] --> APIGateway
    ClientC[第三方合作方] --> APIGateway
    APIGateway -->| 路由 / 聚合 | ServiceA[用戶服務]
    APIGateway -->| 協議轉換 | ServiceB[訂單服務]
    APIGateway -->| 安全控制 | ServiceC[支付服務]

核心職責

  • 統一入口與路由 :所有請求先到網關,再按照路徑、域名、Header 等規則轉發。
  • 安全防護 :集中處理認證、鑑權、限流、IP 白名單、WAF 等安全策略。
  • 協議與格式轉換 :支持 REST、gRPC、GraphQL 等,將多種協議對外統一。
  • 可觀測與運維 :收集日誌、指標、Tracing,提供熔斷、重試、緩存等彈性措施。
  • 聚合與編排 :組合多個後端接口,返回定製化響應,降低客戶端調用複雜度。

爲什麼需要 API 網關

  • 微服務數量增長 :客戶端不必關心每個服務的地址和認證方式,由網關統一暴露。
  • 治理策略集中化 :限流、熔斷、監控等策略在網關層統一實施,避免各服務重複實現。
  • 便於演進與灰度 :通過路由規則實現灰度發佈、A/B 測試和版本切換。
  • 提升安全合規性 :統一入口便於審計與風險控制。
sequenceDiagram
    participant Client as 客戶端
    participant Gateway as API 網關
    participant Auth as 身份驗證服務
    participant Order as 訂單服務
    participant Billing as 計費服務

    Client->>Gateway: 請求 /v1/order
    Gateway->>Auth: 校驗 Token
    Auth-->>Gateway: 返回用戶信息
    Gateway->>Order: 調用訂單詳情
    Gateway->>Billing: 查詢支付狀態
    Gateway-->>Client: 聚合後的訂單響應

常見產品:Nginx + Lua、Kong、Tyk、APISIX、AWS API Gateway、Spring Cloud Gateway 等。

第 2 章:Kong 實戰入門

結合 2-1 ~ 2-6 視頻,掌握從安裝到安全加固的常見操作。

2-1 Kong 的 8001、8000 和 1337 端口號

Kong 默認開放多個端口,每個端口承載不同職責。先弄清楚它們的作用,更容易排查問題。

端口 協議 角色 常見操作
8000 HTTP 對外代理入口 業務請求走這裏
8443 HTTPS 代理入口(TLS) 暴露 HTTPS 服務
8001 HTTP Admin API 新建 Service/Route、查看狀態
8444 HTTPS Admin API(TLS) 在生產環境更安全
1337 HTTP Dev Portal/Manager 可視化配置(Docker 快速體驗)
graph TD
    subgraph 業務面
        Client[客戶端流量] --> Proxy[8000/8443 Proxy]
        Proxy --> UpstreamPool[上游服務]
    end
    subgraph 運維面
        AdminAPI[8001/8444 Admin API] --> KongCore[Kong 核心]
        Portal[1337 Manager] --> KongCore
    end
    KongCore --> Metrics[日誌 / 指標輸出]

快速自檢命令:

# 確認端口監聽狀態
docker exec kong netstat -tnlp | grep 800
# 用 Admin API 獲取節點信息
curl http://localhost:8001/

2-2 基本的路由轉發配置

入門最先做的事情是讓一個 URL 能正確轉發到後端服務。

  1. 註冊 Service:定義上游地址與協議。
  2. 創建 Route:決定哪些請求命中上述 Service。
  3. 驗證轉發 :通過 curl 或瀏覽器訪問代理入口。
# 1. 註冊服務
curl -X POST http://localhost:8001/services \
  --data "name=user-service" \
  --data "url=http://mockbin.org"

# 2. 綁定路由
curl -X POST http://localhost:8001/services/user-service/routes \
  --data "paths[]=/users" \
  --data "strip_path=true"

# 3. 訪問 Kong 代理
curl -i http://localhost:8000/users

常見坑:hostspathsmethods 是“與”關係,匹配條件越多,命中概率越低;務必確保客戶端 Host Header 與路由配置一致。

2-3 Kong 的 Service、Route、Upstream

Service、Route、Upstream 構成 Kong 的核心抽象,理解它們之間的關係能幫助你靈活組合流量策略。

  • Service:描述後端應用(協議、域名、端口、超時)。
  • Route:定義如何把請求匹配到某個 Service。
  • Upstream:爲 Service 提供“實例池”,支持負載均衡、健康檢查。
  • Target:Upstream 中的具體實例(IP:Port)。
graph TD
    Client --> Route[Route: hosts/paths]
    Route --> Service[Service: http://orders.internal]
    Service --> Upstream[Upstream: order-upstream]
    Upstream --> TargetA[10.0.1.10:9000]
    Upstream --> TargetB[10.0.1.11:9000]
    Route -- Plugin 鏈 --> Plugins[認證 / 限流 / 日誌]

最佳實踐:

  • 爲每個上游服務創建獨立 Upstream,方便後續滾動升級。
  • 插件既可以掛在 Route,也可以掛在 Service 或全局,全局策略優先級最低。
  • 使用標籤(Tags)對資源分組,便於運維搜索。

2-4 Kong 集成 Consul 實現服務發現和健康檢查

當後端實例經常變化時,把健康檢查託付給 Consul 能減輕人工維護壓力。

  1. 準備 Consul:啓動 Consul Agent,並註冊你的應用實例(可使用 service.json 文件)。
  2. 配置 Service Discovery:在 Kong 的 Service 中新增 hostservice.consul 形式,同時在 KONG_DATABASEkong.conf 中開啓 service_discovery
  3. 聲明 Upstream 使用 Consul
curl -X POST http://localhost:8001/upstreams \
  --data "name=order.consul" \
  --data "service=orders" \
  --data "healthchecks.active.type=http"
  1. Consul 維護實例 :當實例上下線時,Consul 自動同步,Kong 讀取最新健康狀態。
graph LR
    Consul -->| 服務健康 | KongUpstream
    Jenkins -->| 部署後註冊 | Consul
    KongProxy --> KongUpstream --> BackendPods[訂單服務實例]

提示:確保 Kong 與 Consul 網絡可達,並在 Consul 中開啓 TTL 或 HTTP 健康檢查。

2-5 Kong 配置 JWT 實現登錄校驗

JWT 插件讓 Kong 成爲統一認證入口。典型流程如下。

  1. 啓用插件並創建消費者
# 添加一個消費者
curl -X POST http://localhost:8001/consumers \
  --data "username=mobile-app"

# 爲消費者生成密鑰對
curl -X POST http://localhost:8001/consumers/mobile-app/jwt
  1. 在 Route 或 Service 上啓用 JWT 插件
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data "name=jwt" \
  --data "config.claims_to_verify=exp"
  1. 客戶端構造並帶上 Token
curl http://localhost:8000/users \
  -H "Host: api.example.com" \
  -H "Authorization: Bearer < 簽名後的 JWT>"
sequenceDiagram
    participant Client as 客戶端
    participant Kong as Kong 網關
    participant JWT as JWT 插件
    participant Upstream as 上游服務

    Client->>Kong: 帶 Authorization 的請求
    Kong->>JWT: 校驗簽名、過期時間
    JWT-->>Kong: 校驗通過 / 失敗
    opt 校驗通過
        Kong->>Upstream: 轉發請求
        Upstream-->>Kong: 返回業務響應
        Kong-->>Client: 200 OK
    end
    opt 校驗失敗
        Kong-->>Client: 401 未授權
    end

小貼士:結合 key-authrate-limiting 插件可以進一步區分不同終端的訪問權限與頻率。

2-6 Kong 配置反爬蟲 IP 黑名單

對抗惡意請求的常見手段是“白名單 + 黑名單 + 速率限制”。

# 開啓 IP 限制插件
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data "name=ip-restriction" \
  --data "config.deny[]=192.168.1.100" \
  --data "config.deny[]=203.0.113.0/24"

結合思路:

  • 黑名單 :發現惡意 IP 立即加入 deny 列表。
  • 白名單 :對於管理後臺、BFF 接口可設置 allow 列表,默認拒絕其他來源。
  • 限速 :搭配 rate-limitingbot-detection 插件削峯。
  • 審計 :將 Kong 日誌投遞到 ELK/Loki,識別異常 UA、Referer。
graph TD
    ClientReq[請求] --> IPCheck[IP 限制插件]
    IPCheck -->| 黑名單 | Block[返回 403]
    IPCheck -->| 通過 | RateLimit[限流插件]
    RateLimit --> Backend[上游服務]

通過 Jenkins 部署服務

對應 3-1 ~ 3-11 視頻,帶你從 Jenkins 安裝、插件選擇到 Pipeline 編排與發佈自動化。

3-1 敏捷開發中的持續集成痛點

  • 代碼合併頻繁,人工打包、手動發版效率低。
  • 不同環境依賴差異大,容易出現“在我電腦能跑”。
  • 缺少統一的質量門檻,測試遺漏導致線上回滾。
  • 部署結果缺乏追溯,無法快速定位失敗節點。

敏捷開發:我們也不知道到底要開發啥,走一步看一步吧
用戶故事:老闆說明天要上這個功能,怎麼實現我不管
快速迭代:上次做的功能點擊率太低,把廣告改成全屏
用戶痛點:昨天用戶投訴了,把廣告調整下
擁抱變化:老闆天天都有新想法,大家要適應(不要怪我)
持續交付:每個版本都有問題,總是持續交給測試,交付間隔 10 分鐘
結對開發:bug 太多了,直接去測試妹子的工位邊測邊改
代碼評審:這個代碼是你審的,將來出了問題你是要負責任的
彈性工作:不限定下班時間,修完 bug 才能走
四個會議:(Scrum Meeting)每天早上 9:00 開始,想上班遲到沒門

上面這段“段子體”調侃了業界常見的敏捷誤區:把敏捷等同於無計劃、把用戶故事當作臨時需求、以“快速迭代”包裝粗糙上線,甚至以持續交付之名忽視質量門檻。真正的敏捷強調的是:

  • 有節奏的計劃 :迭代前仍需梳理需求、估算工作量,並對外同步可交付目標。
  • 用戶故事聚焦價值 :描述的是用戶角色、場景與收益,幫助團隊理解“爲什麼做”,不是拍腦袋的功能指令。
  • 持續交付的前提是質量 :自動化測試、代碼評審、監控告警是基礎保障,頻繁交付是爲了快速驗證價值,而非帶着缺陷不停“扔給測試”。
  • 擁抱變化也要有邊界 :通過產品 backlog 和迭代節奏管理變更,必要時調整優先級而非臨時插單。
  • Scrum 四會 (計劃會、每日站會、評審會、回顧會)是爲了同步信息、發現風險、持續改進,而不是形式主義的打卡。

理解這些原則,才能把敏捷和持續集成結合起來,讓 Jenkins 流水線服務於“持續交付價值”而不是“持續交付問題”。

3-2 安裝 Jenkins 和關閉防火牆

  1. Docker 安裝最快捷
docker run -d --name jenkins \
  -p 8080:8080 -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts
  1. 初始化嚮導 :根據提示輸入解鎖密碼、安裝推薦插件、創建管理員。
  2. 服務器防火牆 :若使用 CentOS,可先關閉或放行 8080 端口。
sudo systemctl stop firewalld
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

3-3 Jenkins 構建服務部署流程

sequenceDiagram
    participant Dev as 開發者
    participant Git as 代碼倉庫
    participant Jenkins
    participant Registry as 鏡像倉庫
    participant K8s as Kubernetes
    participant Kong

    Dev->>Git: 提交代碼
    Git-->>Jenkins: Webhook/ 輪詢觸發
    Jenkins->>Jenkins: 編譯 + 測試
    Jenkins->>Registry: 推送鏡像 / 製品
    Jenkins->>K8s: 滾動更新
    Jenkins->>Kong: 調用 Admin API 刷新路由
    Jenkins-->>Dev: 通知結果(釘釘 / 郵件)

流程關鍵點:

  • 用憑證(Credentials)保存 Git、Registry、Kubernetes 的訪問密鑰。
  • 在失敗階段及時 emailext 或機器人提醒,方便第一時間處理。
  • 通過 post 塊寫明成功與失敗的不同通知動作。

3-4 安裝 Jenkins 常用插件

  • Git/Git Parameter:支持多倉庫、多分支構建。
  • Pipeline + Blue Ocean:聲明式流水線與可視化展示。
  • Credentials Binding:將敏感憑證注入環境變量。
  • Kubernetes / Docker:容器化構建能力。
  • Email Extension、釘釘 / 企業微信插件 :構建通知。
  • Config File Provider:集中管理 Maven settings、Kubeconfig 等文件。

3-5 通過 Freestyle Style 構建項目

  1. 新建 Freestyle project,配置描述幫助團隊理解用途。
  2. Source Code Management 中填入 Git 地址和憑證。
  3. Build Triggers 勾選 GitHub hook triggerPoll SCM
  4. Build 步驟添加 Shell,例如:
go test ./...
go build -o bin/order-service ./cmd/order
  1. Post-build Actions 可歸檔二進制、發佈通知。

適用於簡單項目或快速 PoC,後續可遷移到 Pipeline。

3-6 將構建服務器上的代碼上傳到運行環境

常見做法:

  • SCP/RSYNC:把編譯產物推送到目標主機。
scp bin/order-service deploy@10.0.0.12:/srv/apps/order/
ssh deploy@10.0.0.12 "systemctl restart order.service"
  • Artifactory/Nexus:上傳構建物,部署機再拉取。
  • Docker Registry:構建鏡像後用 kubectldocker stack 部署。

記得在 Jenkins 中配置 SSH 憑證,並限制執行節點的權限。

3-7 通過 Pipeline 實現持續集成

聲明式 Pipeline 能把流程寫成代碼,便於複用與審查。

pipeline {
  agent any
  environment {
    REGISTRY = "registry.example.com"
    APP = "order-service"
  }
  stages {stage('Checkout') {steps { git url: 'https://github.com/demo/order-service.git', branch: 'main'}
    }
    stage('Test') {steps { sh 'go test ./...'}
    }
    stage('Build Image') {steps { sh 'docker build -t $REGISTRY/$APP:$BUILD_NUMBER .'}
    }
    stage('Push Image') {steps { sh 'docker push $REGISTRY/$APP:$BUILD_NUMBER'}
    }
    stage('Deploy') {
      steps {
        sh '''
        kubectl set image deploy/order-service order=$REGISTRY/$APP:$BUILD_NUMBER
        kubectl rollout status deploy/order-service
        '''
      }
    }
    stage('Notify Kong') {steps { sh 'curl -X POST http://kong-admin:8001/services/order-service/reload'}
    }
  }
  post {success { emailext subject: "Order Service #${BUILD_NUMBER} 成功 ", to: "team@example.com" }
    failure {emailext subject: "Order Service #${BUILD_NUMBER} 失敗 ", to: "devops@example.com" }
  }
}

3-8 通過 Jenkinsfile 管理構建 Pipeline

  • Jenkinsfile 存放在代碼倉庫根目錄,版本化構建流程。
  • 代碼評審不僅看業務代碼,也要審查流水線改動。
  • 可以創建多分支 Pipeline,讓 Jenkins 自動發現新分支的 Jenkinsfile。

目錄示例:

.
├── Jenkinsfile
├── cmd/
├── deploy/
└── infra/helm/

3-9 通過遠程和其他工程觸發構建

  • 遠程觸發 :在 Job 設置 Trigger builds remotely,生成 Token,使用 curl 調用。
curl "http://jenkins.example.com/job/order-service/build?token=deploy"
  • 上游工程觸發 :在 Build Triggers 勾選 Build after other projects are built,實現流水線串聯。
  • 通過腳本觸發 :利用 Jenkins CLI 或 REST API 與 ChatOps 機器人聯動。

3-10 定時構建和輪詢 SCM 構建

  • Poll SCM:輸入 Cron 表達式,例如 H/5 * * * * 表示每 5 分鐘檢查一次 Git 是否有新提交。
  • Build periodically:無需代碼變更也定時執行,例如夜間運行安全掃描。
  • Cron 小技巧:使用 H 讓 Jenkins 爲不同作業自動分散執行時間,避免任務扎堆。

3-11 參數化 Pipeline 構建項目

參數化讓流水線更加靈活,常見用於選擇分支、版本或部署環境。

pipeline {
  agent any
  parameters {choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: '部署環境')
    string(name: 'IMAGE_TAG', defaultValue: 'latest', description: '鏡像版本')
    booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '是否跳過測試')
  }
  stages {stage('Checkout') {steps { git branch: params.ENV == 'prod' ? 'main' : params.ENV, url: 'https://github.com/demo/order-service.git'}
    }
    stage('Test') {when { expression { return !params.SKIP_TEST} }
      steps {sh 'go test ./...'}
    }
    stage('Deploy') {steps { sh "kubectl set image deploy/order-service order=${params.IMAGE_TAG}" }
    }
  }
}

常見用法:一份 Pipeline 覆蓋多個環境,或爲手動回滾提供快捷入口。


複習與練習清單

  • 畫出公司內的 API 網關拓撲,標註 Service、Route、Plugin 的關係和流量來源。
  • 用 Docker 啓動 Kong,復現 2-1 ~ 2-6 的端口檢查、路由、JWT、黑名單配置。
  • 在測試環境部署 Jenkins,完成一條 Freestyle 與一條 Pipeline 流水線,並打通到 Kong 的熱更新。
  • 將 Jenkinsfile 納入代碼評審流程,嘗試爲主要分支增加參數化發佈。
  • 使用 deckdecK 導出 Kong 配置,結合 Git 管理,實現“配置即代碼”。
正文完
 0