使用 flux2+kustomize+helm+github 進行多集群 GitOps 雲原生漸進式交付


對於此示例,我們假設有兩個集群的場景:暫存(staging)和生產(production)。
最終目標是利用 FluxKustomize 來管理兩個集群,同時最大限度地減少重復聲明。

我們將配置 Flux 以使用 HelmRepositoryHelmRelease
自定義資源安裝、測試和升級演示應用程序。
Flux 將監控 Helm 存儲庫,並根據 semver 范圍自動將 Helm 版本升級到最新的 chart 版本。

准備工作

flux2-kustomize-helm-example

您將需要 Kubernetes 集群版本 1.16 或更新版本以及 kubectl 版本 1.18 或更新。
對於快速的本地測試,您可以使用
Kubernetes kind。不過,任何其他 Kubernetes 設置也可以正常工作。

為了遵循本指南,您需要一個 GitHub 帳戶和一個可以創建存儲庫的
personal access token(檢查 repo 下的所有權限)。

使用 HomebrewMacOSLinux 上安裝 Flux CLI

brew install fluxcd/tap/flux

或者通過使用 Bash 腳本下載預編譯的二進制文件來安裝 CLI:

curl -s https://fluxcd.io/install.sh | sudo bash

項目結構

Git 存儲庫包含以下頂級目錄:

  • apps 目錄包含每個集群具有自定義配置的 Helm 版本
  • infrastructure 目錄包含常見的基礎設施工具,例如 NGINX ingress controller 和 Helm 存儲庫定義
  • clusters 目錄包含每個集群的 Flux 配置
├── apps
│   ├── base
│   ├── production 
│   └── staging
├── infrastructure
│   ├── nginx
│   ├── redis
│   └── sources
└── clusters
    ├── production
    └── staging

apps 配置結構為:

  • apps/base/ 目錄包含命名空間和 Helm 發布定義(release definitions)
  • apps/production/ 目錄包含生產 Helm 發布值(release values)
  • apps/staging/ 目錄包含 staging values
./apps/
├── base
│   └── podinfo
│       ├── kustomization.yaml
│       ├── namespace.yaml
│       └── release.yaml
├── production
│   ├── kustomization.yaml
│   └── podinfo-patch.yaml
└── staging
    ├── kustomization.yaml
    └── podinfo-patch.yaml

apps/base/podinfo/ 目錄中,我們有一個 HelmRelease,兩個集群都有共同的值:

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: podinfo
  namespace: podinfo
spec:
  releaseName: podinfo
  chart:
    spec:
      chart: podinfo
      sourceRef:
        kind: HelmRepository
        name: podinfo
        namespace: flux-system
  interval: 5m
  values:
    cache: redis-master.redis:6379
    ingress:
      enabled: true
      annotations:
        kubernetes.io/ingress.class: nginx
      path: "/*"

apps/staging/ 目錄中,我們有一個帶有 staging 特定值的 Kustomize 補丁(patch):

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: podinfo
spec:
  chart:
    spec:
      version: ">=1.0.0-alpha"
  test:
    enable: true
  values:
    ingress:
      hosts:
        - podinfo.staging

請注意,使用 version: ">=1.0.0-alpha" 我們配置 Flux 以自動將 HelmRelease 升級到最新的 chart 版本,包括 alphabeta 和預發布(pre-releases)。

apps/production/ 目錄中,我們有一個帶有生產特定值的 Kustomize 補丁:

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: podinfo
  namespace: podinfo
spec:
  chart:
    spec:
      version: ">=1.0.0"
  values:
    ingress:
      hosts:
        - podinfo.production

請注意,使用 version: ">=1.0.0" 我們配置 Flux 以自動將 HelmRelease 升級到
最新的穩定 chart 版本(alphabetapre-releases 將被忽略)。

基礎設施:

./infrastructure/
├── nginx
│   ├── kustomization.yaml
│   ├── namespace.yaml
│   └── release.yaml
├── redis
│   ├── kustomization.yaml
│   ├── namespace.yaml
│   └── release.yaml
└── sources
    ├── bitnami.yaml
    ├── kustomization.yaml
    └── podinfo.yaml

infrastructure/sources/ 目錄中,我們有 Helm 存儲庫定義:

apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
  name: podinfo
spec:
  interval: 5m
  url: https://stefanprodan.github.io/podinfo
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
  name: bitnami
spec:
  interval: 30m
  url: https://charts.bitnami.com/bitnami

請注意,使用 interval: 5m 我們將 Flux 配置為每五分鍾拉一次 Helm 存儲庫索引。
如果索引包含與 HelmRelease semver 范圍匹配的新 chart 版本,Flux 將升級該版本。

Bootstrap staging 和 production

集群目錄包含 Flux 配置:

./clusters/
├── production
│   ├── apps.yaml
│   └── infrastructure.yaml
└── staging
    ├── apps.yaml
    └── infrastructure.yaml

clusters/staging/ 目錄中,我們有 Kustomization 定義:

apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m0s
  dependsOn:
    - name: infrastructure
  sourceRef:
    kind: GitRepository
    name: flux-sytem
  path: ./apps/staging
  prune: true
  validation: client
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: infrastructure
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure

請注意,使用 path: ./apps/staging 我們配置 Flux 以同步暫存 Kustomize 覆蓋,並使用 dependsOn 我們告訴 Flux 在部署應用程序之前創建基礎設施項。

在您的個人 GitHub 帳戶上 Fork 此存儲庫並導出您的 GitHub access token、用戶名和存儲庫名稱:

export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-username>
export GITHUB_REPO=<repository-name>

驗證您的臨時集群是否滿足先決條件:

flux check --pre

kubectl context 設置為您的 staging 集群和 bootstrap Flux:

flux bootstrap github \
    --context=staging \
    --owner=${GITHUB_USER} \
    --repository=${GITHUB_REPO} \
    --branch=main \
    --personal \
    --path=clusters/staging

bootstrap 命令在 clusters/staging/flux-system 目錄中提交 Flux 組件的清單,並在 GitHub 上創建一個具有只讀訪問權限的部署密鑰,因此它可以在集群內拉取更改(pull changes)。

注意在 staging 上安裝的 Helm releases:

$ watch flux get helmreleases --all-namespaces 
NAMESPACE	NAME   	REVISION	SUSPENDED	READY	MESSAGE                          
nginx    	nginx  	5.6.14  	False    	True 	release reconciliation succeeded	
podinfo  	podinfo	5.0.3   	False    	True 	release reconciliation succeeded	
redis    	redis  	11.3.4  	False    	True 	release reconciliation succeeded

驗證 demo app 是否可以通過 ingress 訪問:

$ kubectl -n nginx port-forward svc/nginx-ingress-controller 8080:80 &

$ curl -H "Host: podinfo.staging" http://localhost:8080
{
  "hostname": "podinfo-59489db7b5-lmwpn",
  "version": "5.0.3"
}

通過設置生產集群的上下文和路徑來引導生產上的 Flux

flux bootstrap github \
    --context=production \
    --owner=${GITHUB_USER} \
    --repository=${GITHUB_REPO} \
    --branch=main \
    --personal \
    --path=clusters/production

監控 production reconciliation:

$ watch flux get kustomizations
NAME          	REVISION                                        READY
apps          	main/797cd90cc8e81feb30cfe471a5186b86daf2758d	True
flux-system   	main/797cd90cc8e81feb30cfe471a5186b86daf2758d	True
infrastructure	main/797cd90cc8e81feb30cfe471a5186b86daf2758d	True

加密 Kubernetes secrets

為了將 secrets 安全地存儲在 Git 存儲庫中,
您可以使用 MozillaSOPS CLI 通過 OpenPGPKMS 加密 Kubernetes secrets

安裝 gnupgsops:

brew install gnupg sops

Flux 生成一個不指定密碼短語(passphrase)的 GPG key,並獲取GPG key ID

$ gpg --full-generate-key
Email address: fluxcdbot@users.noreply.github.com

$ gpg --list-secret-keys fluxcdbot@users.noreply.github.com
sec   rsa3072 2020-09-06 [SC]
      1F3D1CED2F865F5E59CA564553241F147E7C5FA4

使用 private key 在集群上創建 Kubernetes secret:

gpg --export-secret-keys \
--armor 1F3D1CED2F865F5E59CA564553241F147E7C5FA4 |
kubectl create secret generic sops-gpg \
--namespace=flux-system \
--from-file=sops.asc=/dev/stdin

生成 Kubernetes secret manifest 並使用 sops 加密 secret 的數據字段:

kubectl -n redis create secret generic redis-auth \
--from-literal=password=change-me \
--dry-run=client \
-o yaml > infrastructure/redis/redis-auth.yaml

sops --encrypt \
--pgp=1F3D1CED2F865F5E59CA564553241F147E7C5FA4 \
--encrypted-regex '^(data|stringData)$' \
--in-place infrastructure/redis/redis-auth.yaml

添加 secret 到 infrastructure/redis/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: redis
resources:
  - namespace.yaml
  - release.yaml
  - redis-auth.yaml

通過編輯 infrastructure.yaml 文件在集群上啟用解密:

apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: infrastructure
  namespace: flux-system
spec:
  # content omitted for brevity
  decryption:
    provider: sops
    secretRef:
      name: sops-gpg

導出公鑰(public key),以便任何有權訪問存儲庫的人都可以加密 secrets 但不能解密它們:

gpg --export -a fluxcdbot@users.noreply.github.com > public.key

將更改推送到主分支:

git add -A && git commit -m "add encrypted secret" && git push

驗證是否已在兩個集群的 redis 命名空間中創建了 secret

kubectl --context staging -n redis get secrets
kubectl --context production -n redis get secrets

您可以使用 Kubernetes secrets 為您的 Helm releases 提供值:

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: redis
spec:
  # content omitted for brevity
  values:
    usePassword: true
  valuesFrom:
  - kind: Secret
    name: redis-auth
    valuesKey: password
    targetPath: password

docs 中了解有關 Helm releases values 覆蓋的更多信息。

添加集群

如果要將集群添加到你的 fleet 中,請先在本地克隆存儲庫:

git clone https://github.com/${GITHUB_USER}/${GITHUB_REPO}.git
cd ${GITHUB_REPO}

使用您的集群名稱在 clusters 中創建一個目錄:

mkdir -p clusters/dev

staging 復制同步清單:

cp clusters/staging/infrastructure.yaml clusters/dev
cp clusters/staging/apps.yaml clusters/dev

您可以在 apps 內創建一個 dev overlay,確保將 clusters/dev/apps.yaml 內的 spec.path 更改為 path: ./apps/dev

將更改推送到主分支:

git add -A && git commit -m "add dev cluster" && git push

將 kubectl 上下文和路徑設置為您的 dev cluster 並引導 Flux:

flux bootstrap github \
    --context=dev \
    --owner=${GITHUB_USER} \
    --repository=${GITHUB_REPO} \
    --branch=main \
    --personal \
    --path=clusters/dev

相同的環境

如果你想啟動一個相同的環境,你可以引導一個集群,例如 production-clone 並重用 production 定義。

引導 production-clone 集群:

flux bootstrap github \
    --context=production-clone \
    --owner=${GITHUB_USER} \
    --repository=${GITHUB_REPO} \
    --branch=main \
    --personal \
    --path=clusters/production-clone

在本地拉取更改:

git pull origin main

clusters/production-clone 目錄中創建一個 kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - flux-system
  - ../production/infrastructure.yaml
  - ../production/apps.yaml

請注意,除了 flux-system kustomize overlay,我們還包括來自 production 目錄的 infrastructureapps 清單。

將更改推送到主分支:

git add -A && git commit -m "add production clone" && git push

告訴 Flux 在 production-clone 集群上部署生產工作負載(production workloads):

flux reconcile kustomization flux-system \
    --context=production-clone \
    --with-source 
我是為少
微信:uuhells123
公眾號:黑客下午茶


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM