对于此示例,我们假设有两个集群的场景:暂存(staging)和生产(production)。最终目标是利用 Flux 和 Kustomize 来管理两个集群,同时最大限度地减少重复声明。
我们将配置 Flux 以使用 HelmRepository 和 HelmRelease 自定义资源安装、测试和升级演示应用程序。 Flux 将监控 Helm 存储库,并根据 semver 范围自动将 Helm 版本升级到最新的 chart 版本。
准备工作
flux2-kustomize-helm-example
https://github.com/fluxcd/flux2-kustomize-helm-example
您将需要 Kubernetes 集群版本 1.16 或更新版本以及 kubectl 版本 1.18 或更新。对于快速的本地测试,您可以使用 Kubernetes kind。不过,任何其他 Kubernetes 设置也可以正常工作。
为了遵循本指南,您需要一个 GitHub 帐户和一个可以创建存储库的 personal access token(检查 repo 下的所有权限)。
使用 Homebrew 在 MacOS 和 Linux 上安装 Flux CLI:
brewinstallfluxcd/tap/flux
或者通过使用 Bash 脚本下载预编译的二进制文件来安装 CLI:
curl-shttps://fluxcd.io/install.sh|sudobash 项目结构
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/v2beta1kind:HelmReleasemetadata:name:podinfonamespace:podinfospec:releaseName:podinfochart:spec:chart:podinfosourceRef:kind:HelmRepositoryname:podinfonamespace:flux-systeminterval:5mvalues:cache:redis-master.redis:6379ingress:enabled:trueannotations:kubernetes.io/ingress.class:nginxpath:\”/*\”
在 apps/staging/ 目录中,我们有一个带有 staging 特定值的 Kustomize 补丁(patch):
apiVersion:helm.toolkit.fluxcd.io/v2beta1kind:HelmReleasemetadata:name:podinfospec:chart:spec:version:\”>=1.0.0-alpha\”test:enable:truevalues:ingress:hosts:-podinfo.staging
请注意,使用 version: \”>=1.0.0-alpha\” 我们配置 Flux 以自动将 HelmRelease 升级到最新的 chart 版本,包括 alpha、beta 和预发布(pre-releases)。
在 apps/production/ 目录中,我们有一个带有生产特定值的 Kustomize 补丁:
apiVersion:helm.toolkit.fluxcd.io/v2beta1kind:HelmReleasemetadata:name:podinfonamespace:podinfospec:chart:spec:version:\”>=1.0.0\”values:ingress:hosts:-podinfo.production
请注意,使用 version: \”>=1.0.0\” 我们配置 Flux 以自动将 HelmRelease 升级到 最新的稳定 chart 版本(alpha、beta 和 pre-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/v1beta1kind:HelmRepositorymetadata:name:podinfospec:interval:5murl:https://stefanprodan.github.io/podinfo—apiVersion:source.toolkit.fluxcd.io/v1beta1kind:HelmRepositorymetadata:name:bitnamispec:interval:30murl: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/v1beta1kind:Kustomizationmetadata:name:appsnamespace:flux-systemspec:interval:10m0sdependsOn:-name:infrastructuresourceRef:kind:GitRepositoryname:flux-sytempath:./apps/stagingprune:truevalidation:client—apiVersion:kustomize.toolkit.fluxcd.io/v1beta1kind:Kustomizationmetadata:name:infrastructurenamespace:flux-systemspec:interval:10m0ssourceRef:kind:GitRepositoryname:flux-systempath:./infrastructure
请注意,使用 path: ./apps/staging 我们配置 Flux 以同步暂存 Kustomize 覆盖,并使用 dependsOn 我们告诉 Flux 在部署应用程序之前创建基础设施项。
在您的个人 GitHub 帐户上 Fork 此存储库并导出您的 GitHub access token、用户名和存储库名称:
exportGITHUB_TOKEN=exportGITHUB_USER=exportGITHUB_REPO=
验证您的临时集群是否满足先决条件:
fluxcheck–pre
将 kubectl context 设置为您的 staging 集群和 bootstrap Flux:
fluxbootstrapgithub–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:
$watchfluxgethelmreleases–all-namespacesNAMESPACENAMEREVISIONSUSPENDEDREADYMESSAGEnginxnginx5.6.14FalseTruereleasereconciliationsucceededpodinfopodinfo5.0.3FalseTruereleasereconciliationsucceededredisredis11.3.4FalseTruereleasereconciliationsucceeded
验证 demo app 是否可以通过 ingress 访问:
$kubectl-nnginxport-forwardsvc/nginx-ingress-controller8080:80&$curl-H\”Host:podinfo.staging\”http://localhost:8080{\”hostname\”:\”podinfo-59489db7b5-lmwpn\”,\”version\”:\”5.0.3\”}
通过设置生产集群的上下文和路径来引导生产上的 Flux:
fluxbootstrapgithub–context=production–owner=${GITHUB_USER}–repository=${GITHUB_REPO}–branch=main–personal–path=clusters/production
监控 production reconciliation:
$watchfluxgetkustomizationsNAMEREVISIONREADYappsmain/797cd90cc8e81feb30cfe471a5186b86daf2758dTrueflux-systemmain/797cd90cc8e81feb30cfe471a5186b86daf2758dTrueinfrastructuremain/797cd90cc8e81feb30cfe471a5186b86daf2758dTrue 加密 Kubernetes secrets
为了将 secrets 安全地存储在 Git 存储库中, 您可以使用 Mozilla 的 SOPS CLI 通过 OpenPGP 或 KMS 加密 Kubernetes secrets。
安装 gnupg 和 sops:
brewinstallgnupgsops
为 Flux 生成一个不指定密码短语(passphrase)的 GPG key,并获取GPG key ID:
$gpg–full-generate-keyEmailaddress:fluxcdbot@users.noreply.github.com$gpg–list-secret-keysfluxcdbot@users.noreply.github.comsecrsa30722020-09-06[SC]1F3D1CED2F865F5E59CA564553241F147E7C5FA4
使用 private key 在集群上创建 Kubernetes secret:
gpg–export-secret-keys–armor1F3D1CED2F865F5E59CA564553241F147E7C5FA4|kubectlcreatesecretgenericsops-gpg–namespace=flux-system–from-file=sops.asc=/dev/stdin
生成 Kubernetes secret manifest 并使用 sops 加密 secret 的数据字段:
kubectl-nrediscreatesecretgenericredis-auth–from-literal=password=change-me–dry-run=client-oyaml>infrastructure/redis/redis-auth.yamlsops–encrypt–pgp=1F3D1CED2F865F5E59CA564553241F147E7C5FA4–encrypted-regex\’^(data|stringData)$\’–in-placeinfrastructure/redis/redis-auth.yaml
添加 secret 到 infrastructure/redis/kustomization.yaml:
apiVersion:kustomize.config.k8s.io/v1beta1kind:Kustomizationnamespace:redisresources:-namespace.yaml-release.yaml-redis-auth.yaml
通过编辑 infrastructure.yaml 文件在集群上启用解密:
apiVersion:kustomize.toolkit.fluxcd.io/v1beta1kind:Kustomizationmetadata:name:infrastructurenamespace:flux-systemspec:#contentomittedforbrevitydecryption:provider:sopssecretRef:name:sops-gpg
导出公钥(public key),以便任何有权访问存储库的人都可以加密 secrets 但不能解密它们:
gpg–export-afluxcdbot@users.noreply.github.com>public.key
将更改推送到主分支:
gitadd-A&&gitcommit-m\”addencryptedsecret\”&&gitpush
验证是否已在两个集群的 redis 命名空间中创建了 secret:
kubectl–contextstaging-nredisgetsecretskubectl–contextproduction-nredisgetsecrets
您可以使用 Kubernetes secrets 为您的 Helm releases 提供值:
apiVersion:helm.toolkit.fluxcd.io/v2beta1kind:HelmReleasemetadata:name:redisspec:#contentomittedforbrevityvalues:usePassword:truevaluesFrom:-kind:Secretname:redis-authvaluesKey:passwordtargetPath:password
在 docs 中了解有关 Helm releases values 覆盖的更多信息。
添加集群
如果要将集群添加到你的 fleet 中,请先在本地克隆存储库:
gitclonehttps://github.com/${GITHUB_USER}/${GITHUB_REPO}.gitcd${GITHUB_REPO}
使用您的集群名称在 clusters 中创建一个目录:
mkdir-pclusters/dev
从 staging 复制同步清单:
cpclusters/staging/infrastructure.yamlclusters/devcpclusters/staging/apps.yamlclusters/dev
您可以在 apps 内创建一个 dev overlay,确保将 clusters/dev/apps.yaml 内的 spec.path 更改为 path: ./apps/dev。
将更改推送到主分支:
gitadd-A&&gitcommit-m\”adddevcluster\”&&gitpush
将 kubectl 上下文和路径设置为您的 dev cluster 并引导 Flux:
fluxbootstrapgithub–context=dev–owner=${GITHUB_USER}–repository=${GITHUB_REPO}–branch=main–personal–path=clusters/dev 相同的环境
如果你想启动一个相同的环境,你可以引导一个集群,例如 production-clone 并重用 production 定义。
引导 production-clone 集群:
fluxbootstrapgithub–context=production-clone–owner=${GITHUB_USER}–repository=${GITHUB_REPO}–branch=main–personal–path=clusters/production-clone
在本地拉取更改:
gitpulloriginmain
在 clusters/production-clone 目录中创建一个 kustomization.yaml:
apiVersion:kustomize.config.k8s.io/v1beta1kind:Kustomizationresources:-flux-system-../production/infrastructure.yaml-../production/apps.yaml
请注意,除了 flux-system kustomize overlay,我们还包括来自 production 目录的 infrastructure 和 apps 清单。
将更改推送到主分支:
gitadd-A&&gitcommit-m\”addproductionclone\”&&gitpush
告诉 Flux 在 production-clone 集群上部署生产工作负载(production workloads):
fluxreconcilekustomizationflux-system–context=production-clone–with-source