Deploy Applications on Kubernetes Cluster with GitLab CI/CD Tunnel
原始來源與檔名:2026-06-02T093143+0800-Deploy Applications on Kubernetes Cluster with GitLab CICD Tunnel.md
NAPKIN | 餐巾纸
餐巾纸公式
安全的 K8s 部署 = GitLab KAS (Kubernetes Agent Server) + 內網 K8s Agent + CI/CD Tunnel
透過在 K8s 叢集內部署 Agent 主動連線至 GitLab (Pull-based),無須對外曝露 Kubernetes API 即可在 CI/CD 流水線中安全地推送部署指令。
一句话
GitLab CI/CD Tunnel 讓開發者能透過部署在內網 K8s 叢集中的 Agent,在不開放 K8s API 對外連線的前提下,安全地執行
kubectl或helm部署應用程式。
餐巾纸草图
[ GitLab CI/CD Pipeline ] [ 企業防火牆 / 內網 K8s 叢集 ]
| |
| (CI/CD Tunnel) v
| <--------------------- [ GitLab Agent (Pod) ]
| (主動建立連線) |
v v
[ GitLab KAS (Agent Server) ] [ K8s API Server ]
ROUND 1: SKELETON | 骨架掃描
“这本书在说什么”
- 核心问题: 傳統 CI/CD 部署到 Kubernetes 時,通常需要將 K8s API 暴露在公開網路上讓 CI Server 呼叫,這會帶來嚴重的安全風險。如何在不暴露 API 的情況下完成部署?
- 核心答案: 透過設定 GitLab Kubernetes Agent Server (KAS) 並在 K8s 叢集中安裝 Agent,由 Agent 主動向 GitLab 發起連線建立 CI/CD Tunnel,流水線即可透過此通道安全部署。
- 论证结构: 實作教學型。介紹前置準備 -> 配置 Agent (Repo A) -> 綁定 K8s 叢集 -> 配置 Application (Repo B) 並授權 -> 示範使用
kubectl與helmfile進行部署。
章节骨架
- Connect K8s Cluster to GitLab: 啟用 KAS,建立 Agent 配置專屬 Repo (Repo A) 並在 K8s 中安裝 Agent Pod。
- Create application repository: 在應用程式 Repo (Repo B) 撰寫
.gitlab-ci.yml,透過 CI/CD Tunnel 切換 Kube Context 並執行kubectl apply。 - Authorize application repo: 在 Agent Repo (Repo A) 中設定
ci_access,授權 Repo B 能夠使用該 Agent 連線。 - Deploy using helmfile: 展示另一種部署方式,使用
gl-helmfile在 Pipeline 中自動套用 Helm Chart。
ROUND 2: DISSECTION | 血肉解剖
“凭什么这么说”
论证链
暴露 K8s API 存在高風險 --> 需要一種將外部 Push 轉為內部 Pull 的機制 --> GitLab KAS 與 Cluster-side Agent 之間建立長連線 (Tunnel) --> CI 流水線透過這個安全的 Tunnel 直接與目標叢集對話 --> 達成兼顧自動化與網路安全 (Zero Inbound) 的部署架構。
关键证据
- GitLab KAS 整合: 自 GitLab 14.5 起免費提供此功能,Agent 會在
gitlab-kubernetes-agentnamespace 中運行,主動連線 GitLab,免除 Inbound 網路配置。 - KUBE_CONTEXT 變數: 在
.gitlab-ci.yml中,只要設定KUBE_CONTEXT: org/agent-repo:agent-name,就能無縫切換kubectl config use-context,證明 Tunnel 的透通性。 - 權限隔離設計: 透過區分 Agent 配置專案 (Repo A) 與 應用程式專案 (Repo B),並透過
config.yaml顯式聲明ci_access,確保只有被授權的專案能部署到該叢集。
隐形假设与边界
- 隐形假设:
- K8s 叢集的對外網路 (Outbound) 是暢通的,且能解析並連線到 GitLab (如
registry.gitlab.com與 KAS 端點)。 - 安裝 Agent 時所用的 Service Account 具有足夠的 RBAC 權限來部署目標應用程式。
- K8s 叢集的對外網路 (Outbound) 是暢通的,且能解析並連線到 GitLab (如
- 边界条件:
- 若為地端 (Self-managed) GitLab,必須管理員手動修改
gitlab.rb啟用gitlab_kas['enable'] = true並重新設定,無法單純從 Web UI 完成。 - 如果叢集處於完全封閉的 Air-gapped 環境 (無 Outbound),此 Pull-based Tunnel 方案將無法建立。
- 若為地端 (Self-managed) GitLab,必須管理員手動修改
ROUND 3: SOUL | 靈魂提取
“还能怎么用”
- 作者盲点: 作者著重於 “Push” 模式的延伸 (在 CI Pipeline 中執行
kubectl apply)。但實際上 GitLab Agent 更強大的功能是 GitOps (Pull 模式),亦即讓 Agent 自動監聽 Repo 的 YAML 變化並套用到叢集,而非在 CI/CD 中觸發。 - 知识连接:
- Reverse Proxy / Tunneling: 技術本質與 ngrok 或 Cloudflare Tunnel (Argo Tunnel) 相同,透過建立反向隧道突破 NAT/防火牆限制。
- GitOps (ArgoCD / Flux): 與專門的 GitOps 工具相比,GitLab Agent 提供了與程式碼庫更緊密結合的原生體驗,適合已經重度依賴 GitLab 生態系的團隊。
- 行动触发: 審查現有 CI/CD 流水線,如果發現有直接使用 Kubeconfig 並將 K8s API 暴露於公網的作法,應立即規劃遷移至 CI/CD Tunnel 或導入 ArgoCD。
跨域映射
- 在 網路架構,这叫 反向隧道 (Reverse Tunnel):內網主動連外,避免開啟防火牆 Inbound Port。
- 在 雲端安全,這叫 Zero Trust Network Access (ZTNA):不依賴網路邊界,而是基於身分與受控通道進行連線。
Deploy Applications on Kubernetes Cluster with GitLab CI/CD Tunnel (Architectural Deep Dive)
前言/背景
在實踐 CI/CD 的過程中,將應用程式自動部署至 Kubernetes 叢集是最後一哩路。然而,傳統做法要求將 K8s API Server 暴露在網際網路上以接收來自 CI 系統的部署指令,這帶來了極大的資安風險。本文介紹了 GitLab CI/CD Tunnel 功能,透過在叢集內部安裝主動連外 (Pull-based) 的 Agent,實現在 不暴露 K8s API 的前提下完成安全部署。
章節詳細總結
1. 啟用 KAS 與連接 K8s 叢集 (Connect K8s Cluster to GitLab)
要建立 Tunnel,首先需要依賴 GitLab Kubernetes Agent Server (KAS)。
對於 Self-managed GitLab,必須先在底層配置 /etc/gitlab/gitlab.rb 中啟用 KAS:
gitlab_kas['enable'] = true
建立配置專案 (Repo A)
GitLab 的設計將「環境設定」與「應用程式碼」分離。你需要建立一個專屬的 Repository (文中稱為 kubernetes-cluster) 來存放 Agent 配置。
路徑必須嚴格遵循:.gitlab/agents/<agentname>/config.yaml。
註冊與安裝 Agent
在 GitLab UI (Infrastructure → Kubernetes Cluster) 註冊該 Agent 後,會獲得一串註冊 Token 與 Helm/Docker 安裝指令。在目標 K8s 的 Bastion Host 執行後,Agent 會被部署至 gitlab-kubernetes-agent namespace 中,並主動與 GitLab KAS 建立長連線 (Tunnel)。
2. 授權與配置 CI/CD 流水線 (Create & Authorize Application Repository)
建立完 Tunnel 後,應用程式專案 (Repo B) 並不能隨便使用它,必須經過顯式授權,這是良好的安全邊界設計。
配置存取權限 (CI Access)
在 Repo A 的 Agent config.yaml 中,必須指明哪些專案可以存取此叢集:
ci_access:
projects:
- id: linuxshots/k8s-applications # 授權 Repo B
撰寫 .gitlab-ci.yml 進行部署
在 Repo B 中,透過指定 KUBE_CONTEXT 環境變數,GitLab Runner 會自動透過 Tunnel 將 kubectl 指令導向目標叢集:
variables:
# 格式: 專案路徑:Agent名稱
KUBE_CONTEXT: linuxshots/kubernetes-cluster:mygitlabagent
.kube-context:
before_script:
- if [ -n "$KUBE_CONTEXT" ]; then kubectl config use-context "$KUBE_CONTEXT"; fi
deploy:
extends: [.kube-context]
image:
name: bitnami/kubectl:latest
entrypoint: [""]
script:
- kubectl apply -f $CI_PROJECT_DIR/sampleapps/.
架構考量:這種做法保留了開發者熟悉的 “Push” 部署體驗 (在 CI 看到部署 Log),同時享有類似 “Pull” 模式的安全網路架構。
3. 進階:使用 Helmfile 部署 (Deploy using helmfile)
除了原生 kubectl,GitLab 官方也提供包裝好的 Image 來支援 Helm 部署。
利用 registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications 映像檔,可以直接執行 gl-helmfile 工具:
deploy:
extends: [.kube-context]
stage: deploy
image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v1.3.2"
script:
# 自動確保 namespace 存在
- gl-ensure-namespace vault
# 套用 helmfile.yaml
- gl-helmfile --file $CI_PROJECT_DIR/helmfile.yaml apply --suppress-secrets
這種方式有利於管理複雜的 Chart 依賴與多環境的 values.yaml。
總結與結論
- 安全左移與零信任 (Zero Trust):GitLab CI/CD Tunnel 完美解決了 Inbound 防火牆開洞的痛點,將 Push 型的資安風險轉化為安全的 Pull 型代理架構,是企業內網 K8s 叢集與外部 CI/CD SaaS (如 Gitlab.com) 整合的最佳實踐。
- 關注點分離 (Separation of Concerns):透過將 Agent Config (Repo A) 與 Application Code (Repo B) 拆分,平台工程 (Platform Engineering) 團隊可以集中控管基礎設施權限,而開發團隊仍保有部署的自主性。
- GitOps 的過渡階段:雖然本文展示的是 “CI-driven” 部署,但建立好 GitLab Agent 後,架構師可進一步將其轉為真正的 “GitOps (Pull-driven)” 模式,讓 Agent 自動監聽 Repo 並同步狀態,達到更嚴謹的宣告式基礎設施管理。