使用 FluxCD 实现 Kubernetes GitOps

WilliamGates
发布于 2023-11-24 11:33
浏览
0收藏

Flux 是一套针对 Kubernetes 的持续交付和渐进式交付的解决方案,可以让我们以 GitOps 的方式轻松地交付应用。和另一个同类的 CNCF 孵化项目 Argo CD 不同,Flux CD 是许多工具集的集合,天然松耦合并且有良好的扩展性,用户可按需取用。最新版本的 Flux 引入了许多新功能,使其更加灵活多样。Flux 已经是 CNCF 毕业项目。

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

组件

Flux 是使用 GitOps Toolkit 组件构建的,它是一组:

  • 专用工具和 Flux 控制器
  • 可组合的 API
  • 在 fluxcd GitHub 组织下,为构建基于 Kubernetes 的持续交付提供可重用的 Go 依赖包。

用于在 Kubernetes 之上构建持续交付。

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

这些 API 包括 Kubernetes 自定义资源,可以由集群用户或其他自动化工具进行创建和更新。我们可以使用这个工具包扩展 Flux,并构建自己的持续交付系统。

Flux 的核心工具包包括以下 5 个:

  • Source Controller
  • Kustomize Controller
  • Helm Controller
  • Notification Controller
  • Image automation controllers

每个工具包都是一个控制器,都有自己的自定义资源定义 (CRD),用于定义其行为。

安装

Flux 项目由命令行工具(FLux CLI)和一系列 Kubernetes 控制器组成。要安装 Flux,首先需要下载 Flux CLI,然后使用 CLI,可以在集群上部署 Flux 控制器并配置 GitOps 交付流水线。

Flux CLI 是一个二进制可执行文件,可以从 GitHub 发布页面下载直接下载即可。

对于 Mac 用户可以直接使用 homebrew 进行一键安装:

$ brew install fluxcd/tap/flux

如果是 Linux 用户也可以使用下面的命令进行安装:

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

安装完成后,可以使用 ​​flux​​ 命令来验证是否安装成功:

$ flux --version
flux version 2.1.1

接下来我们就可以使用 Flux CLI 来安装 Flux 控制器了。

Flux CLI 提供了一个 ​​bootstrap​​​ 命令在 Kubernetes 集群上部署 Flux 控制器,并配置控制器以从 Git 存储库同步集群状态。除了安装控制器之外,​​bootstrap​​ 命令还将 Flux 清单推送到 Git 存储库,并将 Flux 配置为从 Git 进行自我更新。

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

如果集群上存在 Flux 控制器,则 ​​bootstrap​​ 命令将在需要时执行升级。Bootstrap 是幂等的,可以安全地运行该命令任意多次。

Flux 与主流的 Git 提供商进行集成,以简化部署密钥和其他身份验证机制的初始设置。比如我们这里选择和 GitLab 进行集成。那么我们可以使用 ​​bootstrap gitlab​​​ 命令在 Kubernetes 集群上部署 Flux 控制器,并配置控制器从 GitLab 项目同步集群状态。除了安装控制器之外,​​bootstrap​​​ 命令还将 Flux 清单推送到 GitLab 项目,并将 Flux 配置为从 Git 进行自我更新。运行 ​​bootstrap​​ 命令后,对集群的任何操作都可以通过 Git 推送完成,无需连接到 Kubernetes 集群。

要启动 Flux,运行命令的人员必须拥有目标 Kubernetes 集群的集群管理员权限,还要求运行该命令的人是 GitLab 项目的所有者,或者具有 GitLab 组的管理员权限。

为了访问 GitLab API,​​boostrap​​ 命令需要具有对 GitLab API 的完整读/写访问权限的 GitLab 个人访问令牌 (PAT)。GitLab PAT 可以导出为环境变量:

export GITLAB_TOKEN=<gh-token>

如果未设置 ​​GITLAB_TOKEN​​​ 环境变量,​​boostrap​​​ 命令将提示你输入 token,当然可以使用管道提供,例如:​​echo "<gl-token>" | flux bootstrap gitlab​​。

比如我们这里可以前往 GitLab 个人访问令牌页面 页面创建一个 PAT:

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

然后我们可以使用下面的命令来安装 Flux:

export GITLAB_TOKEN=glpat-RzooW-ViSatx6zgzmb6d
flux bootstrap gitlab \
  --deploy-token-auth \
  --hostname=gitlab.k8s.local \
  --owner=cnych \
  --repository=flux \
  --branch=main \
  --path=clusters/my-cluster \
  --personal

如果指定的项目不存在,Flux 将为你创建一个私有项目,如果希望创建公共项目,需要设置 ​​--private=false​​​ 参数。使用 ​​--deploy-token-auth​​​ 时,CLI 会生成一个 GitLab 项目部署令牌,并将其作为 Kubernetes Secret 存储在集群中 ​​flux-system​​ 命名空间内。

对多环境集群的支持并没有采用多仓库/多分支的策略,而是用的使用不同路径来管理不同的集群,这也是 Flux 推荐的策略,可以减少代码维护和合并的难度。

上面的命令执行后会出现如下所示的错误信息:

► connecting to https://gitlab.k8s.local
✗ failed to get Git repository "https://gitlab.k8s.local/cnych/flux": provider error: Get "https://gitlab.k8s.local/api/v4/projects/cnych%2Fflux": tls: failed to verify certificate: x509: certificate is valid for ingress.local, not gitlab.k8s.local

这是因为我们这里安装的 GitLab 使用的是 http 的方式,而且该命令下面并没有跳过对 https 证书校验的参数,所以这里我们需要换另外一种方式来安装,使用通用的 ​​git​​ 方式来安装,命令如下所示:

flux bootstrap git \
  --url=http://gitlab.k8s.local/cnych/flux \
  --username=cnych \
  --password=<gh-token> \
  --token-auth=true \
  --path=clusters/my-cluster
  --allow-insecure-http=true  # 运行不安全的 http 方式

上面的命令会在 ​​flux-system​​​ 命名空间中部署一系列 Kubernetes 控制器及其 CRD、RBAC 和网络策略,默认的组件包括:​​source-controller​​​、​​kustomize-controller​​​、​​helm-controller​​​、​​notification-controller​​​,可以通过 ​​--components​​​ 参数来指定要安装的组件,但是需要注意最小安装需要 ​​source-controller​​​ 和 ​​kustomize-controller​​ 两个组件。

上面的命令执行后会正常情况下会出现如下所示的输出信息:

► cloning branch "main" from Git repository "http://gitlab.k8s.local/cnych/flux"
✔ cloned repository
► generating component manifests
✔ generated component manifests
✔ component manifests are up to date
✔ reconciled components
► determining if source secret "flux-system/flux-system" exists
► generating source secret
► applying source secret "flux-system/flux-system"
✔ reconciled source secret
► generating sync manifests
✔ generated sync manifests
✔ sync manifests are up to date
► applying sync manifests
✔ reconciled sync configuration
◎ waiting for Kustomization "flux-system/flux-system" to be reconciled
✔ Kustomization reconciled successfully
► confirming components are healthy
✔ helm-controller: deployment ready
✔ kustomize-controller: deployment ready
✔ notification-controller: deployment ready
✔ source-controller: deployment ready
✔ all components are healthy

在 ​​flux-system​​ 命名空间中可以查看到部署的 Flux 控制器:

$ kubectl get pods -n flux-system
NAME                                      READY   STATUS    RESTARTS   AGE
helm-controller-7c8b698656-gftdr          1/1     Running   0          65m
kustomize-controller-858996fc8d-k2dlx     1/1     Running   0          65m
notification-controller-ddf44665d-49vtp   1/1     Running   0          65m
source-controller-594c848975-sq2pp        1/1     Running   0          29m

此时在对于的 GitLab 代码仓库 http://gitlab.k8s.local/cnych/flux 中可以看到 Flux 为我们创建了一个 ​​clusters/my-cluster/flux-system​​ 的目录,里面包含了一些 Flux 的配置文件。

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

到这里我们就完成了 Flux 的安装。

示例

这里我们还是以前面 Jenkins Pipeline 章节中的示例来进行说明,如何通过 Flux 来实现 GitOps 的持续交付。

示例中要用到的 Git 资源清单仓库为 http://gitlab.k8s.local/cnych/k8s-demo-config,该项目中包含一个 helm 目录,目录下面就是一个 helm chart 包:

使用 FluxCD 实现 Kubernetes GitOps-鸿蒙开发者社区

当然在继续之前,为避免产生影响,我们可以将前面通过 Argo CD 部署的应用删除掉。

接下来我们就可以通过 Flux 来部署应用了,首先需要为 FluxCD 创建一个仓库连接信息,这就需要用到一个名为 ​​GitRepository​​ 的 CRD 对象,该对象可以定义一个 Source 代码源来为 Git 存储库的一个版本生成一个制品,如下所示:

# k8s-demo-git-repo.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: k8s-demo
spec:
  url: http://gitlab.k8s.local/cnych/k8s-demo-config
  timeout: 60s
  interval: 30s
  ref:
    branch: main
  secretRef:
    name: k8s-demo
---
apiVersion: v1
stringData:
  password: <gl-token>
  username: cnych
kind: Secret
metadata:
  name: k8s-demo
type: Opaque

这里我们创建了一个名为 ​​k8s-demo​​​ 的 GitRepository 对象,其中 ​​spec​​​ 字段定义了如何从 Git 存储库提取数据,​​url​​​ 字段指定了 Git 存储库的 URL,​​ref​​​ 字段指定了要提取的代码分支,​​interval​​​ 字段指定了从 Git 存储库提取数据的频率,​​secretRef​​ 字段指定了包含 GitRepository 身份验证凭据的 Secret。

对于 HTTPS 仓库,Secret 必须包含基本认证的 ​​username​​​ 和 ​​password​​​ 字段,或者令牌认证的 ​​bearerToken​​​ 字段。对于 SSH 仓库,Secret 必须包含 ​​identity​​​ 和 ​​known_hosts​​ 字段。

直接应用该资源对象即可:

$ kubectl apply -f k8s-demo-git-repo.yaml
gitrepository.source.toolkit.fluxcd.io/k8s-demo created
secret/k8s-demo created
$ kubectl get gitrepositories
NAME       URL                                             AGE   READY   STATUS
k8s-demo   http://gitlab.k8s.local/cnych/k8s-demo-config   53s   True    stored artifact for revision 'main@sha1:cbb0226130da3ff5e1d4ccad9407e210ab65e551'

创建后我们可以通过 ​​kubectl describe gitrepository k8s-demo​​ 命令来查看 GitRepository 的各种状态:

$ kubectl describe gitrepositories k8s-demo
Name:         k8s-demo
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  source.toolkit.fluxcd.io/v1
Kind:         GitRepository
Metadata:
  Creation Timestamp:  2023-09-23T09:29:35Z
  Finalizers:
    finalizers.fluxcd.io
  Generation:        1
  Resource Version:  485193
  UID:               fef6070d-56bf-452b-8aeb-c821a76ab8f2
Spec:
  Interval:  30s
  Ref:
    Branch:  main
  Secret Ref:
    Name:   k8s-demo
  Timeout:  60s
  URL:      http://gitlab.k8s.local/cnych/k8s-demo-config
Status:
  Artifact:
    Digest:            sha256:b1944afa22fe6b0ce816100b7ac307fc142506287af9d8ac2cc693f7af73364b
    Last Update Time:  2023-09-23T09:29:36Z
    Path:              gitrepository/default/k8s-demo/cbb0226130da3ff5e1d4ccad9407e210ab65e551.tar.gz
    Revision:          main@sha1:cbb0226130da3ff5e1d4ccad9407e210ab65e551
    Size:              7240
    URL:               http://source-controller.flux-system.svc.cluster.local./gitrepository/default/k8s-demo/cbb0226130da3ff5e1d4ccad9407e210ab65e551.tar.gz
  Conditions:
    Last Transition Time:  2023-09-23T09:29:36Z
    Message:               stored artifact for revision 'main@sha1:cbb0226130da3ff5e1d4ccad9407e210ab65e551'
    Observed Generation:   1
    Reason:                Succeeded
    Status:                True
    Type:                  Ready
    Last Transition Time:  2023-09-23T09:29:36Z
    Message:               stored artifact for revision 'main@sha1:cbb0226130da3ff5e1d4ccad9407e210ab65e551'
    Observed Generation:   1
    Reason:                Succeeded
    Status:                True
    Type:                  ArtifactInStorage
  Observed Generation:     1
Events:
  Type    Reason                 Age                From               Message
  ----    ------                 ----               ----               -------
  Normal  NewArtifact            103s               source-controller  stored artifact for commit 'build: automatic update of devops-demo2'
  Normal  GitOperationSucceeded  14s (x3 over 72s)  source-controller  no changes since last reconcilation: observed revision 'main@sha1:cbb0226130da3ff5e1d4ccad9407e210ab65e551'

通过 ​​.status.artifact.revision​​​ 字段可以查看到当前的 Git 版本,新的制品在 ​​.status.artifact​​ 字段中可以查看到。

接下来我们只需要为该应用创建一个部署策略即可,由于我们这里要发布的是 Helm Chart,所以我们需要创建一个 ​​HelmRelease​​​ 对象,该对象可以定义一个包含 Chart 的源(可以是 ​​HelmRepository​​​、​​GitRepository​​​ 或 ​​Bucket​​​)告知 source-controller,以便 HelmRelease 能够引用它,很明显我们这里的源就是上面定义的 ​​GitRepository​​ 对象。

我们这里创建的 ​​HelmRelease​​ 对象如下所示:

# k8s-demo-helm-release.yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: k8s-demo
  namespace: default
spec:
  interval: 30s
  chart:
    spec:
      chart: helm # Chart 是 Helm chart 在 SourceRef 中可用的名称或路径
      sourceRef:
        kind: GitRepository
        name: k8s-demo
        namespace: default
      valuesFiles:
        - helm/values.yaml
        - helm/my-values.yaml
      interval: 30s
  values:
    replicaCount: 2

上面我们定义了一个 ​​HelmRelease​​​ 对象,其中 ​​chart​​​ 字段指定了 Helm Chart 的源,因为我们这里的 Helm Chart 是存储在 Git 代码仓库中的,所以我们通过 ​​sourceRef​​​ 字段来指定 ​​GitRepository​​​ 对象,​​interval​​​ 字段指定了从 Git 存储库提取数据的频率,​​values​​ 字段指定了 Chart 的 values 值。

其中的 ​​valuesFiles​​​ 字段是一个备选的值文件列表,用作 Chart 的 Values 值(默认情况下不包括 ​​values.yaml​​),是相对于 SourceRef 的路径,Values 文件按照此列表的顺序合并,最后一个文件将覆盖第一个文件。

同样直接应用该资源对象即可:

$ kubectl apply -f k8s-demo-helm-release.yaml
helmrelease.helm.toolkit.fluxcd.io/k8s-demo created
$ kubectl get helmrelease
NAME       AGE     READY   STATUS
k8s-demo   5m56s   True    Release reconciliation succeeded

我们可以看到已经成功部署了应用,如果出现了任何问题,可以通过 ​​kubectl describe helmrelease k8s-demo​​ 命令来查看 HelmRelease 的各种状态:

$ kubectl describe helmrelease k8s-demo
Name:         k8s-demo
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  helm.toolkit.fluxcd.io/v2beta1
Kind:         HelmRelease
Metadata:
  Creation Timestamp:  2023-09-23T09:53:49Z
  Finalizers:
    finalizers.fluxcd.io
  Generation:        2
  Resource Version:  491438
  UID:               7dc72409-57ee-4e4a-8950-ea5d09e43bc1
Spec:
  Chart:
    Spec:
      Chart:               helm
      Interval:            30s
      Reconcile Strategy:  ChartVersion
      Source Ref:
        Kind:       GitRepository
        Name:       k8s-demo
        Namespace:  default
      Values Files:
        helm/values.yaml
        helm/my-values.yaml
      Version:  *
  Interval:     30s
  Values:
    Replica Count:  2
Status:
  Conditions:
    Last Transition Time:          2023-09-23T09:59:44Z
    Message:                       Release reconciliation succeeded
    Reason:                        ReconciliationSucceeded
    Status:                        True
    Type:                          Ready
    Last Transition Time:          2023-09-23T09:59:44Z
    Message:                       Helm install succeeded
    Reason:                        InstallSucceeded
    Status:                        True
    Type:                          Released
  Helm Chart:                      default/default-k8s-demo
  Last Applied Revision:           0.1.0+2
  Last Attempted Revision:         0.1.0+2
  Last Attempted Values Checksum:  1dd4966b30314fd329b48c5892b6a85412fd0236
  Last Release Revision:           1
  Observed Generation:             2
Events:
  Type    Reason  Age                   From             Message
  ----    ------  ----                  ----             -------
  Normal  info    41s (x13 over 6m31s)  helm-controller  HelmChart 'default/default-k8s-demo' is not ready
  Normal  info    41s                   helm-controller  Helm install has started
  Normal  info    36s                   helm-controller  Helm install succeeded

事实上我们虽然是在 HelmRelease 中去为 chart 源关联的 GitRepository 对象,但是实际上 HelmRelease 会自动创建一个 ​​HelmChart​​​ 对象,该对象可以定义一个包含 Chart 的源,以便 ​​HelmRelease​​ 能够引用它,如下所示:

$ kubectl get helmchart default-k8s-demo
NAME               CHART   VERSION   SOURCE KIND     SOURCE NAME   AGE     READY   STATUS
default-k8s-demo   helm    *         GitRepository   k8s-demo      7m35s   True    packaged 'devops-demo' chart with version '0.1.0+2' and merged values files [helm/values.yaml helm/my-values.yaml]
$ kubectl get helmchart default-k8s-demo -o yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmChart
metadata:
  name: default-k8s-demo
  namespace: default
spec:
  chart: helm
  interval: 30s
  reconcileStrategy: ChartVersion
  sourceRef:
    kind: GitRepository
    name: k8s-demo
  valuesFiles:
  - helm/values.yaml
  - helm/my-values.yaml
  version: '*'
# ......

最后我们也可以通过 helm 命令来验证我们的应用是否已经部署成功:

$ helm ls
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                 APP VERSION
k8s-demo        default         1               2023-09-23 09:59:39.906949292 +0000 UTC deployed        devops-demo-0.1.0+2   1.0

这样接下来我们只需要在 CI 流水线中去将镜像构建完成后,将镜像推送到镜像仓库,然后更新 Git 代码仓库中的 Values 文件的镜像版本即可,Flux 会自动检测到 Chart 版本的变化,然后自动更新应用。

但是这样的话,我们每次都需要在 CI 流水线去手动更新 Git 代码仓库中的 Values 文件的镜像版本,这样就会比较麻烦,和 Argo CD 类似,Flux 也提供了一个 ​​Image Automation​​ 控制器的功能,请关注后续文章~


文章转载自公众号:k8s技术圈

分类
标签
已于2023-11-24 11:33:30修改
收藏
回复
举报
回复
    相关推荐