ミニPC上で動く自宅サーバーにFluxを導入して自動的にデプロイできるようにしてみた
2025-05-01
azblob://2025/04/30/eyecatch/2025-04-30-minipc-fluxv2-yattemita-000.jpg

※ この記事は個人でも投稿予定です。

はじめに

この記事ではFlux version 2(以降、Fluxと略記)のインストールと簡単なアプリケーションのデプロイを行います。

まずFlux CLIをインストールし、GitHubリポジトリを作成して準備を整えた後、Metal LBとNginxをデプロイする所までを行います。

この記事を通じて、Fluxの概要と実際の使用方法を理解できるようになります。

なお、この記事は以前執筆した自宅サーバーシリーズの1つになります。

よろしければそちらもご参照ください。

自宅サーバーシリーズ

動作環境

今回の記事の動作環境は以下の通りです。

  • OS: macOS Sonoma 14.5
  • K3s: v1.30.2+k3s1
  • kubectl: Client Version: v1.31.2, Kustomize Version: v5.4.2
  • Flux CLI: flux version 2.4.0

前提条件

前提条件は以下の通りです。

  • K3sのセットアップが済んでいること
  • kubectlパッケージがインストールされていること

上記の内容はこの記事内では取り扱わないため注意してください。

Fluxとは

FluxはGitHubなどのリポジトリをもとにKubernetesクラスターの状態を自動的に管理してくれるGitOpsツールです。

以下、公式ドキュメントの文章を引用させていただきます。

Flux is a set of continuous and progressive delivery solutions for Kubernetes that are open and extensible.

https://fluxcd.io/

これまでは、Kubernetesへのリソース適用をkubectl applyなどのコマンドで手動で行っていました。

しかしFluxを用いることで、リポジトリにコミットするだけでクラスターに変更が反映されるようになります。

Argo CDとの比較

しかしFluxを用いることで、リポジトリにコミットするだけでクラスターに変更が反映されるようになります。

上記の内容はArgo CDでも可能です。

事実、少し前までは自宅サーバーにArgo CDを導入していました。

ではなぜFluxに移行したかと言うと、「メモリ使用量がかなり少ない」ためです。

Argo CDがGUIで動作するのに対して、FluxはCUIで動作します。

 ※ 設定などを探せばArgo CDでもCUIで動作するかもしれませんが、少なくとも初期状態ではGUIで動作します。

参考程度にArgo CDやFluxだけをデプロイしてkubectl topコマンドを実行した際の結果が以下になります。

# デフォルト
kubectl top nodes

NAME                   CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k3s-staging-server-1   62m          1%     631Mi           16% 

# Argo CD
kubectl top nodes

NAME                   CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k3s-staging-server-1   61m          1%     1311Mi          33%

# Flux
kubectl top nodes

NAME                   CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k3s-staging-server-1   70m          1%     996Mi           25%   

今回はミニPCというリソースがかなり限られている状況のため、Fluxを採用することに決めました。

なお、Argo CDはGUIが用意されているという性質上、状況を一目で把握することができ、入門に最適でした。

Flux CLIのインストール

早速、Fluxを試していきます。

まずはFlux CLIのインストールから行います。

公式ドキュメントのFlux installationにインストールコマンドが掲載されています。

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

なお、私はパッケージマネージャーにnixを採用しているので以下のような形でインストールしています。

{ pkgs, ...}:

{
	home.packages = with pkgs; [
        # 一部パッケージ省略
		kubectl fluxcd
	];
}

インストールが完了したら以下のコマンドを実行して実際にインストールされているか確認してみましょう。

flux -v
flux version 2.4.0

これでFlux CLIのインストールが完了しました。

事前準備 - GitHubリポジトリの作成とPersonal Access Tokenの発行

続いて、GitHubリポジトリを作成し、実行に必要なPersonal Access Token(以降、PATと略記)を発行します。

このステップでGitHubリポジトリを明示的に作成しますが、後のステップで実行するflux bootstrapコマンドで作成することもできます。

また、flux bootstrapコマンドで指定するオプションは個人アカウントか、組織が管理するリポジトリか、などによって異なります。

今回は「個人アカウント」で管理するリポジトリを作成します。

GitHubリポジトリを作成する

※ 一般的なリポジトリを作成する手順と何ら変わらないため詳細は割愛させていただきます。

GitHubにアクセスしたらNew repositoryから管理対象のリポジトリを作成します。

名前はお好みで。

リポジトリ作成画面

Personal Access Tokenを発行する

続いてPATの発行を行います。

GitHubのSettingsを選択してSettings画面に遷移したら、左サイドバーの一番下にある「Developer settings」を選択します。

Developer settings

Developer settings画面に遷移したら、先ほどと同様に左サイドバーにPersonal access tokensという項目があるため、その中の「Fine-grained tokens」を選択します。

右上に「Generete new token」というボタンが表示されるため、こちらを押下してください。

Fine-grained personal access tokens画面

Token nameやExpirationをお好みで設定したら、PermissionsのRepository permissionsにて以下の設定をしてください。

  • Administration: Read and write
  • Contents: Read and write
  • Metadata: Read-only
Repository permissionsの設定

選択後、ページ下部にある「Generete token」からPATを発行し、表示された値を適切に保管してください。

これにてGitHubリポジトリの作成と実行に必要なPATの発行は完了です。

事前準備 - デプロイする対象のマニフェストファイルの作成

ここでは今回の記事でデプロイするMetal LBとNginxのマニフェストファイルを用意します。

上記のマニフェストファイルと、Fluxのマニフェストファイルの配置場所はWays of structuring your repositoriesを参考にします。

# https://fluxcd.io/flux/guides/repository-structure/#repository-structure
├── apps
│   ├── base
│   ├── production 
│   └── staging
├── infrastructure
│   ├── base
│   ├── production 
│   └── staging
└── clusters
    ├── production
    └── staging

Metal LBのマニフェストファイルを作成する

まずはkustomization.yamlを./infrastructure/metallb-system/kustomization.yamlに作成します。

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: metallb-system
resources:
  - github.com/metallb/metallb/config/native?ref=v0.14.3
  - metallb-config.yaml

resourcesで指定しているmetallb-config.yamlは以下の通りです。

上記のkustomization.yamlと同じ階層に配置してください。

---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:

---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: metallb-l2-advertisement
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

続いてinfrastructure.yamlを作成します。 

今回は./clusters/staging/infrastructure.yamlに作成します。  

---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: metallb-system
  namespace: flux-system
spec:
  interval: 1h
  retryInterval: 1m
  timeout: 5m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure/metallb-system
  prune: true
  patches:
    - patch: |-
        apiVersion: metallb.io/v1beta1
        kind: IPAddressPool
        metadata:
          name: first-pool
          namespace: metallb-system
        spec:
          addresses:
          - 192.168.0.160-192.168.0.169
      target:
        name: first-pool
        kind: IPAddressPool

ついでにapps.yamlを作成します。

上記のinfrastructure.yamlと同じ./clusters/staging/apps.yamlに作成します。

---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m0s
  dependsOn:
    - name: metallb-system
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/staging
  prune: true
  wait: true
  timeout: 5m0s

これでMetal LBの準備は完了です。

Nginxのマニフェストファイルを作成する

続いてNginxのマニフェストファイルを作成します。 

まずはkustomization.yamlです。

./apps/base/nginx/kustomization.yamlに作成します。

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: nginx
resources:
  - namespace.yaml
  - deployment.yaml
  - service.yaml

上記のresourcesで指定しているyamlファイルを以下に示します。

省略のため1つにまとめていますが、上記のkustomization.yamlと同じ階層にそれぞれ作成してください。

# namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: nginx

# deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

# service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080
  type: NodePort

続いて環境別のマニフェストファイルを作成します。

kustomization.yamlを./apps/staging/nginx/kustomization.yamlに作成します。

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: nginx
resources:
  - ../../base/nginx
patches:
  - path: nginx-service-values.yaml
    target:
      kind: Service
  - path: nginx-values.yaml
    target:
      kind: Deployment

patches.pathに指定したファイルは以下の通りです。

なお、nginx-values.yamlは後々編集し、自動的に設定が変わることを確認するために使用します。

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
  loadBalancerIP: 192.168.0.161
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx
  labels:
    app: nginx
spec:
  replicas: 1

これでNginxのマニフェストファイルの用意は完了です。

flux bootstrapコマンドの実行

続いてFlux関連のリソースをクラスターにデプロイします。

flux bootstrapコマンドで関連リソースのデプロイからGitHubリポジトリへのコミットまでまとめて行ってくれます。

このコマンドにはいくつかのサブコマンドが用意されているのですが、今回はGitHubを使用するため、flux bootstrap githubコマンドを使用します。

まずはGitHubのPATとユーザー名をEXPORTします。

export GITHUB_TOKEN=<token>
export GITHUB_USER=<username>

続いて、flux bootstrap githubコマンドを実行します。

リポジトリ名やブランチ名、パスは環境に応じて使い分けてください。

今回は先ほどのセクションで作成したblog-sample-fluxリポジトリのmainブランチを監視対象にしてコミットし、./clusters/stagingディレクトリのflux-systemディレクトリにFlux関連リソースのマニフェストファイルを作成します。

flux bootstrap github \
  --token-auth \
  --owner=$GITHUB_USER \
  --repository=blog-sample-flux \
  --branch=main \
  --path=./clusters/staging \
  --personal

このコマンドの実行後、GitHubにアクセスするとFlux関連のリソースがコミットされます。

Flux関連のリソースがコミットされている

 flux get kustomizations --watchコマンドを実行すればFluxがデプロイしている様子を確認できます。

flux get kustomizations --watch
metallb-system  main@sha1:4667d15f      False   True    Applied revision: main@sha1:356bf408
metallb-system  main@sha1:356bf408      False   True    Applied revision: main@sha1:356bf408
flux-system     main@sha1:4667d15f      False   True    Applied revision: main@sha1:356bf408
flux-system     main@sha1:356bf408      False   True    Applied revision: main@sha1:356bf408
apps            False   Unknown Reconciliation in progress
apps            False   Unknown Reconciliation in progress
apps            False   Unknown Reconciliation in progress

apps            False   True    Applied revision: main@sha1:356bf408
apps    main@sha1:356bf408      False   True    Applied revision: main@sha1:356bf408

上記のようにAppliedと表示された後、リソースを確認してみると前のセクションで作成したマニフェストファイルの内容が自動的にデプロイされています。

kubectl get pods -n nginx

NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-576c6b7b6-4zjgp   1/1     Running   0          7m10s

kubectl get svc -n nginx

NAME            TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
nginx-service   LoadBalancer   10.43.90.45   192.168.0.161   80:30080/TCP   4m2s
Nginxのデプロイ完了

マニフェストファイルを編集して自動的に変更が反映されることを確認する

FluxによってMetal LBとNginxのリソースがデプロイされていることが確認できました。

Nginxのマニフェストファイルを変更して実際にリソースが変更されることを確認します。

 ./apps/staging/nginx/nginx-values.yamlのspec.replicasを10に変更します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx
  labels:
    app: nginx
spec:
  - replicas: 1
  + replicas: 10

編集後、上記の内容をコミットしてプッシュします。

コミット後、しばらくしてから確認すると上記の変更が自動的に反映されています。

kubectl get pods -n nginx

NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-576c6b7b6-2l4gz   1/1     Running   0          88s
nginx-deployment-576c6b7b6-4zjgp   1/1     Running   0          11m
nginx-deployment-576c6b7b6-f6rct   1/1     Running   0          88s
nginx-deployment-576c6b7b6-j6lf9   1/1     Running   0          88s
nginx-deployment-576c6b7b6-k9rvj   1/1     Running   0          88s
nginx-deployment-576c6b7b6-p2dqr   1/1     Running   0          88s
nginx-deployment-576c6b7b6-rz6kq   1/1     Running   0          88s
nginx-deployment-576c6b7b6-vc2vs   1/1     Running   0          88s
nginx-deployment-576c6b7b6-vjlnx   1/1     Running   0          88s
nginx-deployment-576c6b7b6-xz44h   1/1     Running   0          88s

補足 - すでにFluxのマニフェストファイルが存在する場合

自宅サーバーではよくあったのですが、クラスターを削除した影響で、すでにGitHubリポジトリ上にFlux関連のマニフェストファイルはあるがクラスターにリソースが存在しない。というような場面がありました。

このような場合はリソースに対してkubectl apply -kコマンドを実行して、GitHubリポジトリとやり取りをするためのシークレットを作成することで解決します。

ls clusters/staging/flux-system
gotk-components.yaml gotk-sync.yaml kustomization.yaml

kubectl apply -k clusters/staging/flux-system

kubectl create secret generic flux-system \
  --namespace=flux-system \
  --from-literal=username="$GITHUB_USER" \
  --from-literal=password="$GITHUB_TOKEN"

トラブルシューティング - 一向に同期が開始しない

基本的にTroubleshooting cheatsheetを参照すれば解消できる可能性が高いです。 

自分の場合は手動でapplyした結果、上記のシークレットが存在しないことによりエラーが発生していました。

flux get sourceコマンドを実行したことによって判明しました。

flux get source git
NAME            REVISION        SUSPENDED       READY   MESSAGE                                                                                                                     
flux-system                     False           False   failed to configure authentication options: failed to get secret 'flux-system/flux-system': secrets "flux-system" not found

おわりに

今回の記事ではFluxをインストールして、Metal LBとNginxのデプロイを行いました。