用 Helm Charts + Flux 学习 GitOps
本月早些时候,我使用 kubernetes 和 Flux 构建并部署了我的第一个 GitOps 持续交付管道。在整个过程中,我发现自己在阅读大量过时且令人困惑的文档,因此在到达另一边后,我想写下我所采取的步骤的演练,希望其他开发人员可以更轻松地度过.
堆栈:
AWS EKS用于 kubernetes 集群
HelmOperator byFlux用于 GitOps
Terraform+Cloudformation用于基础设施
我部署到集群的应用程序是一个 GraphQL API,它存在于 AWS ECR 上的 docker 映像中,但这可以适应任何 docker 容器或其他容器化构建。
由于有很多很好的资源可以创建特定于您使用的任何服务(AWS、Google GKE 等)的 kubernetes 集群,因此我将假设您有一个想要的现有集群来开始本演练将映像部署到。
第1步:GitHub
您将需要一个专用的 GitHub 存储库来执行此过程。在这里您将提交所有以下配置(您的 helm 图表、helm 版本等),并且它应该与您用于构建您正在部署的应用程序的任何存储库分开。
第 2 步:设置 Fluxcd
按照的说明安装 Helm和Fluxctl
然后,使用 helm 安装 Fluxcd 图表:
helm repo add fluxcd https://charts.fluxcd.io
在您的集群上创建一个命名空间,以供与通量相关的 pod 生存:
我使用了“fluxcd”,但您可以选择任何对您有意义的命名空间
kubectl create ns fluxcd
创建您的通量 pod(GitHub 存储库 + 分支将来自第 1 步):
helm upgrade -i flux fluxcd/flux --wait \
--namespace fluxcd \
--set git.url=git@github.com:<GITHUB REPO> \
--set git.branch=<BRANCH>
如果您的存储库是私有的,您还需要添加 knownhosts 标志:
--set-file ssh.known_hosts=$known_hosts_path
指向您的 knownhosts 所在的路径,通常在 ~/.ssh 目录中。
第三步:Helm Operator
helm operator 是一个控制器,它与 Flux 协同工作,并允许您创建将部署映像的 HelmReleases,并在 Flux 检测到更改时将映像更新到最新版本。
将 Helm Operator 应用到您的集群:
kubectl apply -f https://raw.githubusercontent.com/fluxcd/helm-operator/master/deploy/flux-helm-release-crd.yaml
创建 helmRelease pod:
helm upgrade -i helm-operator fluxcd/helm-operator --wait \
--namespace fluxcd \
--set helm.versions=v3
检索 SSH 密钥:
fluxctl identity --k8s-fwd-ns fluxcd
并将其添加到部署密钥下的 github 存储库中。
您将希望授予此密钥写入权限,以便 Flux 在检测到图像的新版本时更新您的 helmReleases。
第 4 步:HelmReleases
现在助焊剂已全部设置好,是时候开始制作好东西了。正如我之前提到的,HelmReleases 是 Flux 用于部署映像的 yaml 文件。
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
name: <app name -- name of the application you're deploying>
namespace: default
annotations:
flux.weave.works/automated: "true"
flux.weave.works/tag.chart-image: glob:dev-*
spec:
releaseName: <app name>
helmVersion: v3
chart:
git: <github repo from step 1>
path: <the directory where your charts live -- ex. charts/app-name >
ref: <github branch set in step 2>
values:
image: <image endpoint of your application>
replicaCount: 1
hpa:
enabled: true
maxReplicas: 3
cpu: 1
extraEnvs:
## This is where you can add any public env variables
username: oliver_2020
dbServer: 11.0.1.213
envFrom:
secretRef:
## The Secret Name for private env variables (more on that later)
name: mysecrets
您拥有的每个 HelmRelease 都需要一个相应的 Helm Chart。 Helm 有一些很棒的文档关于构建自定义 Helm 图表 + 模板,但我会添加基础知识。
第 5 步:Helm 图表
如果 Kubernetes 是领航员,Helm 就是方向盘。大多数 Helm Charts 包含以下组件:
Chart.yaml 文件几乎就像掌舵图的“标题页”。它由图表名称和版本信息组成。
apiVersion: v1
kind: application
description: A Super Awesome GraphQL API
name: graphql
version: 1.0.0
values.yaml 文件用于定义图表所需的所有变量。
image: <image endpoint of your application>
replicaCount: 1
hpa:
enabled: true
maxReplicas: 3
cpu: 1
extraEnvs:
username: oliver_2020
这些变量然后被各种模板文件使用。
一个常见的模板文件是部署模板:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ template "app.name" . }}
chart: {{ template "app.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "app.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "app.name" . }}
release: {{ .Release.Name }}
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
- name: publicEnvKey
value: {{ .Values.extraEnv.key | quote }}
- name: secretEnvKey
valueFrom:
secretKeyRef:
key: dbPassword
name: mysecrets
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: data
emptyDir: {}
您将可以使用模板语法访问整个图表中定义的变量
.价值观
。发布
。图表
但是,如果您需要更改值的结构,例如删除或添加连字符,则可以添加 helper.tpl 文件。模板助手对于生成时间戳等值也很有用,将它放在你的 values.yaml 文件中是没有意义的,因为它并不是图表的真正组成部分。
第 6 步:模板助手
变量在帮助文件中使用define操作定义
{{- define "mychart.labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}
{{- end }}
然后,您可以使用template操作在任何模板文件中调用此值
{{ template "mychart.labels" }}
模板引擎会将其读取为当前日期。
有关声明自定义值的完整参考,请参阅 helm命名模板指南
第7步:密封的秘密
如果您有任何要使用的私有环境变量,最好将它们存储在一个秘密中。 Kubernetes 有一种存储机密的本机方式,但值只是 base64 编码,这不是最安全的策略,所以我一直在使用一个名为seal-secrets的工具,它允许您创建 SealedSecrets 资源,然后您可以将其存储在其中GitHub,因为它们只能由创建它们的控制器解密。
SealedSecret 资源如下所示:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: mysecrets
namespace: default
spec:
encryptedData:
dbPassword: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
并且可以通过秘密名称在您的 helmRelease 中引用
envFrom:
secretRef:
name: mysecrets
首先,安装 Stable 存储库:
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
更新 Helm 存储库:
helm repo update
然后从稳定的存储库安装密封的秘密:
helm install --namespace kube-system stable/sealed-secrets --generate-name
安装后,您可以将 seal-secrets 控制器应用于您的集群:
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.9.6/controller.yaml
然后使用生成的密封秘密 pod 名称获取生成的公钥(可以提交到 GitHub):
kubeseal --fetch-cert \
--controller-namespace=kube-system \
--controller-name=sealed-secrets-230493143 \
> pub-cert.pem
您可以使用kubectl get pods -n kube-system获取 pod 名称
步骤 8:创建 SealedSecret 资源
要创建 Secret,您将首先使用 kubectl 生成它,然后使用 kubeseal 对其进行加密
kubectl -n <env namespace> create secret generic <secretname> \
--from-literal=<key>=<value> \
--from-literal=<key>=<value> \
--dry-run \
-o json > <secretname>.json
试运行标志将创建具有 base64 加密值的 json 文件,但不会在您的集群上创建实际的 kubernetes 机密。
要使用 kubeseal 对其进行加密,您将传递上一步中公钥的位置、您刚刚创建的 json 文件的名称以及您要用于秘密的文件名
kubeseal --format=yaml --cert=pub-cert.pem < secretname.json > secretname.yaml
此过程将生成一个自定义 SealedSecret 资源,其中包含只能由创建它的控制器解封的加密凭据。
拥有 SealedSecret 资源后,您可以删除或 .gitignore 生成的 json 文件。当您提交 pub-cert 文件和新的 SealedSecrets 资源到 GitHub 时,flux 会将密钥应用到您的集群,然后控制器会将其解封为本地 kubernetes 密钥以供集群读取。
第 9 步:推送到 Git
一旦你的 helm 发布和相应的 helm 图表都设置好了,你可以继续从第 1 步将你的提交推送到 GitHub 存储库。
一旦您的提交被合并或推送到您在步骤 2 中指定的分支,flux 将获取更改并部署您的第一个掌舵版本。
Flux 通常需要一两分钟才能同步,但您可以手动强制同步
fluxctl sync --k8s-fwd-ns fluxcd
将fluxcd替换为您在步骤 2 中为通量 pod 选择的任何命名空间。
步骤 10. 故障排除
如果您推送了提交,等待通量同步,但仍然没有看到带有 helm 版本中 app-name 的 pod,那么您可以通过几种方法进行故障排除。
获取具有kubectl get pods --all-namespaces的所有 pod 的列表并复制通量 pod 的名称。然后运行kubectl logs <fluxpodname> -n fluxcd
您应该能够看到 Flux 尝试克隆 repo 的日志,并轮询更新,并可以检查任何错误。
另一种策略是kubectl get hr,它将获取所有 helm 发布实例,并且通常会显示发布在部署过程中的位置以及出现的任何错误。
最后,我总是发现描述资源并确保它们按预期配置很有帮助。您可以使用kubectl describe <resourcetype> <resourcename>描述任何 Kubernetes 资源
结论
这只是为您的 Kubernetes 管道配置持续交付管道的众多方法之一。 Flux 是一个很棒的工具,因为它可以很好地与 Helm 集成,并且是一种自动化部署过程的相对直接的方式。 Helm 最近更新到版本 3,并且对 Helm v3 的通量支持仍处于 beta 模式,因此有些令人困惑/过时的文档,但 Weaveworks 的团队在他们的 slack 频道https://cloud-native.slack .com/,希望本演练也能帮助解决一些复杂问题。
有问题、反馈、宠物照片吗?不要犹豫,在下面发表评论并快乐编码!
更多推荐

所有评论(0)