介绍
本指南将引导您在 Kubernetes 集群上设置渐进式交付 GitOps 管道。
原文地址:GitOps Progressive Deliver with Flagger, Helm v3 and Linkerd
GitOps Helm 研讨会(https://helm-workshop.hacker-linner.com/)
GitOps 是什么?
GitOps 是一种进行持续交付的方法,它通过将 Git 用作声明性基础结构和工作负载的真实来源来工作。对于 Kubernetes,这意味着使用 git push
代替 kubectl create/apply
或者 kubectl create/apply
。
GitOps vs CiOps 在传统的 CI/CD 管道中,CD 是由持续集成工具支持的实现扩展,用于将构建工件升级到生产环境。在 GitOps 管道模型中,对生产的任何更改必须先在源代码管理中提交(最好通过拉取请求),然后再应用于集群。如果整个生产状态受版本控制并在单个Git 存储库中进行描述,则在灾难发生时,可以快速恢复整个基础架构,而无需重新运行 CI 管道。
Kubernetes 反模式:让我们做 GitOps,而不是 CIOps!【https://www.weave.works/blog/kubernetes-anti-patterns-let-s-do-gitops-not-ciops】
为了将 GitOps 模型应用到 Kubernetes 上,你需要做三件事:
- 一个 Git 存储库,其中包含以 YAM 格式定义的工作负载、Helm charts 和定义集群所需状态的任何其他 Kubernetes 自定义资源
- 一个容器注册中心(registry),CI 系统在其中推送不可变的镜像(没有 latest 标签,使用 语义版本控制 或 git commit sha)
- 一个进行双向同步的 Kubernetes 控制器:
- 监视配置存储库中的更改并将其应用于您的集群
- 监视容器 registry(注册中心) 的新映像,并根据部署策略更新工作负载定义。
在本研讨会中,您将使用 GitHub 托管配置存储库,使用 Docker Hub 作为容器注册中心,使用 Flux 作为 GitOps 控制器,并使用 Helm Operator 进行应用程序生命周期管理。
什么是渐进式交付?
渐进式交付是高级部署模式(如金丝雀,功能标记和 A/B 测试)的总称。通过给予应用程序开发人员和 SRE 团队对爆炸半径的细粒度控制,渐进交付技术被用来降低在生产中引入新软件版本的风险。
使用金丝雀的好处是能够在生产环境中使用发现问题的安全回滚策略对新版本进行容量测试。通过缓慢增加负载,您可以监视和捕获有关新版本如何影响生产环境的指标。
Martin Fowler 博客(https://martinfowler.com/bliki/CanaryRelease.html)
在本研讨会中,您将使用 Flagger, Linkerd 和 Prometheus 来自动化金丝雀分布 Helm charts。
前提条件
为了安装研讨会的前提条件,您需要一个 Kubernetes 集群(1.13 或更新版本),并支持 负载平衡器 和 RBAC。确保您已经在本地安装了以下工具:
- kubectl 1.16
- git 2.20
Helm v3
在 macOS 上安装 Helm v3 CLI:
brew install helm
在 Linux 或 Windows 上,您可以从官方发布页面下载二进制文件。
Git
Fork workshop 仓库并克隆它到本地(使用你的 GitHub 用户名替换 GHUSER
):
export GHUSER=stefanprodan git clone https://github.com/${GHUSER}/gitops-helm-workshop
设置您的 GitHub 用户名和电子邮件:
cd gitops-helm-workshop git config user.name "${GHUSER}" git config user.email "your@main.address"
集群状态目录结构:
├── cluster ├── canaries ├── charts │ └── podinfo ├── namespaces └── releases
Flux
将 Flux 存储库添加到 Helm 存储库:
helm repo add fluxcd https://charts.fluxcd.io
创建 fluxcd namespace:
kubectl create ns fluxcd
通过提供您的 GitHub 存储库 URL 安装 Flux:
helm upgrade -i flux fluxcd/flux --wait \ --namespace fluxcd \ --set registry.pollInterval=1m \ --set git.pollInterval=1m \ --set git.url=git@github.com:${GHUSER}/gitops-helm-workshop
安装 fluxctl:
# macOS and linux curl -sL https://fluxcd.io/install | sh export PATH=$PATH:$HOME/.fluxcd/bin # windows https://github.com/fluxcd/flux/releases
找到 Git SSH 公钥:
export FLUX_FORWARD_NAMESPACE=fluxcd fluxctl identity
复制公钥并在 GitHub 存储库上创建具有写访问权的部署密钥。转到 Settings > Deploy keys
,单击 Add deploy key
,选中 Allow write access
,粘贴 Flux 公钥并单击 Add key
。
Helm Operator
在 fluxcd
命名空间中安装 Flux Helm Operator:
helm upgrade -i helm-operator fluxcd/helm-operator --wait \ --namespace fluxcd \ --set git.ssh.secretName=flux-git-deploy \ --set git.pollInterval=1m \ --set chartsSyncInterval=1m \ --set helm.versions=v3
Linkerd
下载 Linkerd v2 CLI:
# macOS and linux curl -sL https://run.linkerd.io/install | sh export PATH=$PATH:$HOME/.linkerd2/bin # windows https://github.com/linkerd/linkerd2/releases
在 linkerd
名称空间中安装 Linkerd 控制平面:
linkerd install | kubectl apply -f -
使用以下命令验证安装:
linkerd check
Flagger
添加 Flagger Helm 仓库:
helm repo add flagger https://flagger.app
安装 Flagger 的金丝雀 CRD:
kubectl apply -f https://raw.githubusercontent.com/weaveworks/flagger/master/artifacts/flagger/crd.yaml
在 linkerd
命名空间中安装 Flagger:
helm upgrade -i flagger flagger/flagger --wait \ --namespace linkerd \ --set crd.create=false \ --set metricsServer=http://linkerd-prometheus:9090 \ --set meshProvider=linkerd
Helm 发布
一个 chart 发布是通过 Kubernetes 自定义资源 HelmRelease 进行描述的。
一个 Helm release 可以引用的 chart,如下:
- 通过 HTTPS 的公共或私有 Helm 存储库
- 通过 SSH 的公共或私有 Git 存储库
安装 NGINX
为了将应用程序暴露在集群之外,您将使用 NGINX ingress 控制器。控制器将在 Linkerd 网格内运行。
创建一个启用 linkerd 注入的名称空间:
apiVersion: v1 kind: Namespace metadata: annotations: fluxcd.io/ignore: "false" linkerd.io/inject: enabled name: ingress-nginx
创建一个 Helm release 来安装 NGINX ingress 控制器:
apiVersion: helm.fluxcd.io/v1 kind: HelmRelease metadata: name: nginx-ingress namespace: ingress-nginx annotations: fluxcd.io/ignore: "false" spec: releaseName: nginx-ingress chart: repository: https://kubernetes-charts.storage.googleapis.com/ name: nginx-ingress version: 1.33.4 values: controller: service: type: LoadBalancer
应用更改:
git add -A && \ git commit -m "install ingress" && \ git push origin master && \ fluxctl sync
验证 Helm operator 是否已安装 release:
kubectl -n ingress-nginx get hr
查找 ingress 控制器的公共 IP:
kubectl -n ingress-nginx get svc
安装 podinfo
Podinfo 是一个很小的 Go Web 应用程序。您将使用存储 cluster/charts/podinfo
的 git 仓库中的 Helm chart 安装 podinfo。
创建启用 linkerd 注入的 prod
命名空间:
apiVersion: v1 kind: Namespace metadata: annotations: fluxcd.io/ignore: "false" linkerd.io/inject: enabled name: prod
创建一个 Helm release 以安装 podinfo chart(替换 GHUSER
为你的 GitHub 用户名和使用你的 ingress IP 替换 LB-PUBLIC-IP
):
apiVersion: helm.fluxcd.io/v1 kind: HelmRelease metadata: name: podinfo namespace: prod annotations: fluxcd.io/ignore: "false" spec: releaseName: podinfo chart: git: git@github.com:GHUSER/gitops-helm-workshop ref: master path: cluster/charts/podinfo values: image: repository: stefanprodan/podinfo tag: 3.1.0 service: enabled: true type: ClusterIP ingress: enabled: true annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header l5d-dst-override $service_name.$namespace.svc.cluster.local:9898; proxy_hide_header l5d-remote-ip; proxy_hide_header l5d-server-id; path: / hosts: - LB-PUBLIC-IP.nip.io
请注意,如果您使用的是 EKS,则主机应设置为 elb.amazonaws.com
地址:
kubectl -n ingress-nginx get svc | grep Ingress
应用更改:
git add -A && \ git commit -m "install podinfo" && \ git push origin master && \ fluxctl sync
验证 Helm operator 是否已安装 podinfo:
kubectl -n prod get hr
打开浏览器并导航到 http://LB-PUBLIC-IP.nip.io/
,您应该看到 podinfo v3.1.0 UI
。
自动升级
Flux 可以用于自动化集群中的容器映像更新。您可以通过注释 Helm release 对象来启用自动化 image 标记更新。您还可以通过使用 glob、regex 或语义版本表达式来控制更新应该考虑哪些标记。
编辑 podinfo Helm release 并启用 Flux 自动 Image 更新:
apiVersion: helm.fluxcd.io/v1 kind: HelmRelease metadata: annotations: fluxcd.io/automated: "true" fluxcd.io/tag.chart-image: semver:~3.1
应用更改:
git add -A && \ git commit -m "automate podinfo" && \ git push origin master && \ fluxctl sync
验证 Helm operator 是否已升级 podinfo:
kubectl -n prod get hr
在本地拉取 Flux 所做的更改:
git pull origin master
打开浏览器并导航到 http://LB-PUBLIC-IP.nip.io/
,您应该看到 podinfo v3.1.5 UI。
密封的 secrets
为了将 secrets 安全地存储在公共 Git 存储库中,您可以使用 Sealed Secrets 控制器 并将您的 Kubernetes Secrets 加密为 SealedSecrets。只能通过在集群中运行的控制器来解密密封的 secrets。
创建 Sealed Secrets Helm release:
apiVersion: helm.fluxcd.io/v1 kind: HelmRelease metadata: name: sealed-secrets namespace: fluxcd annotations: fluxcd.io/ignore: "false" spec: releaseName: sealed-secrets chart: repository: https://kubernetes-charts.storage.googleapis.com/ name: sealed-secrets version: 1.8.0
应用更改:
git add -A && \ git commit -m "install sealed-secrets" && \ git push origin master && \ fluxctl sync
安装 kubeseal CLI:
wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v1.8.0/kubeseal-darwin-amd64 sudo install -m 755 kubeseal-darwin-amd64 /usr/local/bin/kubeseal
在启动时,sealed-secrets 控制器生成一个 RSA key 并记录公钥。使用 kubeseal,您可以将您的公钥保存为 pub-cert.pem,公钥可安全存储在 Git 中,可用于加密 secrets,无需直接访问 Kubernetes 集群:
kubeseal --fetch-cert \ --controller-namespace=fluxcd \ --controller-name=sealed-secrets \ > pub-cert.pem
您可以使用 kubectl 在本地生成 Kubernetes secret,并使用 kubeseal 对其进行加密:
kubectl -n prod create secret generic basic-auth \ --from-literal=user=admin \ --from-literal=password=admin \ --dry-run \ -o json > basic-auth.json kubeseal --format=yaml --cert=pub-cert.pem < basic-auth.json > basic-auth.yaml
这将生成一个类型为 SealedSecret 的自定义资源,其中包含加密的凭据。
Flux 将在您的集群上应用 sealed secret,然后 sealed-secrets 的控制器将其解密为 Kubernetes secret。
为了准备进行灾难恢复,您应该使用以下命令备份 Sealed Secrets 控制器的私钥:
kubectl get secret -n fluxcd sealed-secrets-key -o yaml \ --export > sealed-secrets-key.yaml
要在灾难后从备份中恢复,请替换新创建的密钥并重新启动控制器:
kubectl replace secret -n fluxcd sealed-secrets-key -f sealed-secrets-key.yaml kubectl delete pod -n fluxcd -l app=sealed-secrets