電通総研 テックブログ

電通総研が運営する技術ブログ

Renovateを用いたKubernetesエコシステムの自動バージョンアップ

こんにちは。Xイノベーション本部クラウドイノベーションセンターの柴田です。

本記事では Renovate を使ったKubernetesエコシステムの自動バージョンアップを紹介します。

なお本記事の内容は Kubernetes Meetup Tokyo #48 で紹介された 個人運用k8sクラスタの構成要素の技術選定 - でこてっくろぐ ねお にインスパイアされています。

背景

Kubernetesでは、Kubernetesと連携して動作する様々なOSSやサービスを活用することで、アプリケーションの開発・運用に関する生産性向上や効率化を図ることができます。 本記事ではそれらをKubernetesエコシステムと呼びます。 多くのKubernetesエコシステムは開発元が提供しているコンテナイメージやマニフェストファイルを自分たちのKubernetesクラスタへデプロイして利用します。 開発が盛んなKubernetesエコシステムでは、頻繁に新機能やセキュリティ改善が実装され、新しいバージョンとしてリリースされます。 Kubernetesエコシステムの恩恵を最大限に享受するにはなるべく新しいバージョンを使用することが望ましいです。

またKubernetesでは、マニフェストファイルを GitOps と呼ばれる手法で管理・デプロイすることが多いです。 GitOpsはWeaveworks社が提唱した継続的デプロイの方法であり、以下の特徴があります。

  • システム全体が宣言的に記述されていること。
  • マニフェストがgitで管理され、それが信頼できる唯一の情報源(Single Source of Truth)であること。
  • 承認されたマニフェストの変更が自動的にデプロイされること。またその際Kubernetesクラスタへの認証情報を外部(例えばCIサーバなど)に持たせる必要がないこと。
  • マニフェストKubernetesクラスタの間に差分がある場合、それを検知したり、自動的に修正したりできること。

GitOpsを実現するツールには例えば Argo CDFluxPipeCD があります。

以上から、Kubernetesエコシステムの新しいバージョンがリリースされる度に、gitリポジトリで管理されたそれらのマニフェストを最新の内容に更新できることが望ましいです。 また、運用負荷がかからないよう、マニフェストの更新はなるべく自動的に行えることが望ましいです。

Renovateとは

Renovate はプロジェクトの依存関係の更新を自動化するツールです。 似たようなツールに Dependabot などがあります。 Renovateはアプリケーションのライブラリの自動バージョンアップに使われることが多いですが、アプリケーション開発以外の用途でも利用できます。

ここからはRenovateで何ができるかを簡単に説明します。 なお本記事では Renovate v32.97.0 を前提とします。

Platform

Renovateは以下に格納された依存関係ファイルを更新できます。

Manager

Renovateは以下の依存関係を更新できます。

Datasource

Renovateは以下の依存先の更新を検知できます。

adoptium-java, artifactory, aws-machine-image, bitbucket-tags, cdnjs, clojure, conan, conda, crate, dart, docker, flutter-version, galaxy, galaxy-collection, git-refs, git-tags, github-releases, github-tags, gitlab-packages, gitlab-releases, gitlab-tags, go, golang-version, gradle-version, helm, hex, jenkins-plugins, maven, node, npm, nuget, orb, packagist, pod, pypi, repology, ruby-version, rubygems, sbt-package, sbt-plugin, terraform-module, terraform-provider

Versioning

依存関係を更新するためにはバージョン表記を比較できる必要があります。 Renovateでは以下のフォーマットのバージョン表記を扱えます。

aws-machine-image, cargo, composer, conan, debian, docker, git, gradle, hashicorp, helm, hex, ivy, loose, maven, node, npm, nuget, pep440, poetry, regex, rez, ruby, semver, semver-coerced, swift, ubuntu

RenovateでKubernetesエコシステムを自動更新する

では実際にRenovateを使ってKubernetesエコシステムの更新作業を自動化したいと思います。

更新対象のKubernetesクラスタ

今回は私が検証用途で使用しているKubernetesクラスタを対象にします。 このKubernetesクラスタには以下の特徴があります。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.10.3/config/master/aws-k8s-cni.yaml
images:
  - name: 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni
    newName: 602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni
    newTag: v1.10.3
  - name: 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init
    newName: 602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni-init
    newTag: v1.10.3

Renovateを実行する

Renovateには大まかに2種類の実行方法があります。

  • GitHub App を使用する
  • 自分たちでRenovateを実行する(Self-Hosting)

今回はGitHub Actions renovatebot/github-action を使用して自分たちでRenovateを実行します。 その他のSelf-Hostingの実行方法は Self-Hosting Renovate を参照してください。

以下はGitHub Actionsのワークフローです。

# .github/workflows/renovate.yaml
name: Renovate
on:
  schedule:
    - cron: '0 0 * * *' # Run workflow at 09:00 AM JST every day
jobs:
  renovate:
    name: Renovate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run renovate
        uses: renovatebot/github-action@v32.97.0
        with:
          token: ${{ secrets.GH_TOKEN }}
          configurationFile: renovate.json

GH_TOKENhttps://github.com/renovatebot/github-action#token に従って作成したGitHubのPersonal Access Tokenです。 GitHub Actionsでは GITHUB_TOKEN が利用できますが、 https://github.com/renovatebot/github-action#token

Note that the GITHUB_TOKEN secret can't be used for authenticating Renovate.

とあるためこのようにしています。

Renovateの設定

次にRenovateの設定ファイル renovate.json を作成します。 今回使用した設定は以下のとおりです。

{
    "repositories": [
        "ISID/renovate-sample"
    ],
    "extends": [
        "config:base",
        ":prHourlyLimitNone",
        ":prConcurrentLimitNone"
    ],
    "enabledManagers": [
        "argocd",
        "flux",
        "helmfile",
        "kustomize",
        "regex"
    ],
    "labels": [
        "renovate"
    ],
    "assignees": [
        "@ShibataTakao"
    ],
    "argocd": {
        "fileMatch": [
            "^manifests/argo-cd-apps/.*\\.ya?ml$"
        ]
    },
    "flux": {
        "fileMatch": [
            "^manifests/flux/.*\\.ya?ml$",
            "^manifests/flux-ks/.*\\.ya?ml$"
        ]
    },
    "regexManagers": [
        {
            "fileMatch": [
                "(^|/)kustomization\\.ya?ml$"
            ],
            "matchStrings": [
                "https://raw\\.githubusercontent\\.com/(?<depName>[^/]+/[^/]+)/(?<currentValue>[^/]+)/.*",
                "https://github\\.com/(?<depName>[^/]+/[^/]+)/releases/download/(?<currentValue>[^/]+)/.*"
            ],
            "datasourceTemplate": "github-releases",
            "versioningTemplate": "semver"
        }
    ],
    "packageRules": [
        {
            "matchPackageNames": [
                "kubernetes/autoscaler"
            ],
            "matchDatasources": [
                "github-tags",
                "github-releases"
            ],
            "versioning": "regex:^cluster-autoscaler-(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)?$",
            "allowedVersions": "< 1.23.0"
        },
        {
            "matchPackageNames": [
                "k8s.gcr.io/autoscaling/cluster-autoscaler"
            ],
            "matchDatasources": [
                "docker"
            ],
            "allowedVersions": "< 1.23.0"
        }
    ]
}

各設定を順に見ていきましょう。

"repositories": [
    "ISID/renovate-sample"
]

repositories にはRenovateの対象とするリポジトリを指定します。 リポジトリ名を直接指定するかわりに autodiscoverautodiscoverFilter を設定してRenovateの対象とするリポジトリを自動的に検出することもできます。

"extends": [
    "config:base",
    ":prHourlyLimitNone",
    ":prConcurrentLimitNone"
]

extends には Preset を指定します。 Presetは定義済みの設定の集合です。 デフォルトで定義されたPresetを使うだけでなく、独自のPresetを定義することもできます。 今回は以下のPresetを使用します。

"enabledManagers": [
    "argocd",
    "flux",
    "helmfile",
    "kustomize",
    "regex"
]

enabledManagers を設定して明示的に指定したManagerのみを有効化します。

多くのManagerはデフォルトで有効になっています。 各Managerの有効/無効は <manager>.enabled の値を true または false に設定することで変更できます。 または enabledManagers に有効にするManagerを明示的に指定することで、指定したManagerのみを有効にできます。 詳細は Enabling and disabling managers を参照してください。

今回は以下のManagerのみを有効化します。

今回の更新対象のうち

  • Helm: 公式や3rd partyが提供するHelm Chartを利用します。 具体的にはArgo CDの Application リソースやFluxの HelmRelease リソースとしてKubernetesクラスタへデプロイします。 またローカル環境でマニフェストを生成できるよう helmfile も使用しています。

argocdfluxhelmfile を使ってHelm ChartをバージョンアップするためのPRを自動成します。 また

  • Kustomize: kustomize を使って公式が提供するマニフェストhttps経由で参照します。 イメージタグを書き換えることもあります。

kustomizeregex を使って参照先のマニフェストのURLやイメージタグをバージョンアップするためのPRを自動作成します。 regex については後ほどもう少し詳しく説明します。

"labels": [
    "renovate"
],
"assignees": [
    "@ShibataTakao"
]

labelsassignees にはRenovateが依存関係を更新するために作成するPRのLabelsとAssigneesを設定します。

"argocd": {
    "fileMatch": [
        "^manifests/argo-cd-apps/.*\\.ya?ml$"
    ]
},
"flux": {
    "fileMatch": [
        "^manifests/flux/.*\\.ya?ml$",
        "^manifests/flux-ks/.*\\.ya?ml$"
    ]
}

fileMatch には各Managerの依存関係ファイルの追加パスを正規表現で記述します。 多くのManagerにはデフォルトの fileMatch が設定されていますが、デフォルトの fileMatch が設定されていない場合や独自のファイルパスを追加で設定したい場合には、 fileMatch にそれらを追加設定できます。

"regexManagers": [
    {
        "fileMatch": [
            "(^|/)kustomization\\.ya?ml$"
        ],
        "matchStrings": [
            "https://raw\\.githubusercontent\\.com/(?<depName>[^/]+/[^/]+)/(?<currentValue>[^/]+)/.*",
            "https://github\\.com/(?<depName>[^/]+/[^/]+)/releases/download/(?<currentValue>[^/]+)/.*"
        ],
        "datasourceTemplate": "github-releases",
        "versioningTemplate": "semver"
    }
]

regexManagers には regex Managerの設定を記述します。 regex を用いることで正規表現を使用して依存関係を検出・自動更新するユーザー独自の仕組みを構築できます。 今回は

yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.10.3/config/master/aws-k8s-cni.yaml images: - name: 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni newName: 602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni newTag: v1.10.3 - name: 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init newName: 602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni-init newTag: v1.10.3

で述べた参照先のマニフェストのURLを自動更新するためにこの仕組みを利用します。

fileMatch には更新対象のファイル kustomization.yaml のファイルパスを正規表現で設定します。

matchStrings には kustomization.yaml 内の更新対象の文字列を設定します。 今回は

  • https://raw.githubusercontent.com/<user>/<repo>/<tag>/<filepath>GitHubリポジトリのコンテンツ)
  • https://github.com/<user>/<repo>/releases/download/<release>/<filepath>GitHubリポジトリのリリースのアセット)

が更新対象です。

regex では更新対象の依存関係に関する以下の設定をする必要があります。 これらは、該当する設定項目に値を設定するか、 matchStrings正規表現に名前付きキャプチャグループを用いることで設定できます。

Capture Group Config Field 必須 説明
currentValue なし 必須 現在のバージョン。Renovateによって更新される。
depName depNameTemplate 必須 依存関係の名前。
packageName packageNameTemplate オプション パッケージ名。省略した場合 depName と同じになる。
datasource datasourceTemplate 必須 依存関係の参照先( Datasource )。
depType depTypeTemplate オプション 依存関係の種類。
versioning versioningTemplate オプション 依存関係のバージョン表記( Versioning )。デフォルトは semver
extractVersion extractVersionTemplate オプション キャプチャしたバージョンと Datasource のバージョンの表記が異なる場合に使用する。詳細は extractVersion を参照。
currentDigest なし オプション 現在のDigest。Renovateによって更新される。
registryUrl registryUrlTemplate オプション 依存関係の参照先のURL。詳細は registryUrls を参照。
"packageRules": [
    {
        "matchPackageNames": [
            "kubernetes/autoscaler"
        ],
        "matchDatasources": [
            "github-tags",
            "github-releases"
        ],
        "versioning": "regex:^cluster-autoscaler-(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)?$",
        "allowedVersions": "< 1.23.0"
    },
    {
        "matchPackageNames": [
            "k8s.gcr.io/autoscaling/cluster-autoscaler"
        ],
        "matchDatasources": [
            "docker"
        ],
        "allowedVersions": "< 1.23.0"
    }
]

packageRules には特定の依存関係の更新における追加ルールを設定します。 今回は Cluster Autoscaler に関する以下の追加ルールを設定します。

実行結果

設定に従いGitHub Actionsが毎朝9時にRenovateを実行します。

Helm Chartに更新がある場合は以下のようなPRが自動的に作成されます。

Kustomizeが参照するマニフェストのURLやイメージタグに更新がある場合は以下のようなPRが自動的に作成されます。

PRの説明文には公式GitHubリポジトリのReleaseからRelease Notesが転記されており、具体的な変更内容を知ることができます。

また Dependency Dashboard を有効にしておくと、Renovateが作成したPRを一覧して管理できるIssueが作成されます。 Dependency Dashboardを有効化する設定はPreset config:base に含まれています。

あとはこれらのPRをマージし、Argo CDやFluxを使ってKubernetesクラスタへデプロイするだけで、Kubernetesエコシステムの更新は完了です。

なお今回は全てのPRの承認・マージを手動で行う形にしましたが、特定の更新のみ承認・マージを必要にしてそれ以外はPRを自動的にマージするよう設定することも可能です。 特定の更新として、例えば特定のパッケージやメジャーバージョンの更新などが設定できます。

おわりに

本記事ではRenovateを使ったKubernetesエコシステムの自動バージョンアップを紹介しました。

開発が盛んなKubernetesエコシステムでは、頻繁に新機能やセキュリティ改善が実装され、新しいバージョンとしてリリースされます。 Renovateを活用し、Kubernetesエコシステムを頻繁かつ自動的にバージョンアップすることで、それらの恩恵を最大限に享受できます。

本記事が少しでもKubernetesクラスタを運用している方のお役に立てば幸いです。


私たちは同じチームで働いてくれる仲間を探しています。クラウドアーキテクトの業務に興味がある方のご応募をお待ちしています。

執筆:@shibata.takao、レビュー:@yamashita.tsuyoshiShodoで執筆されました