Flux導入とMetalLB実装 - おうちでGitOpsシリーズ投稿3/6
こちらはおうちでGitOpsシリーズの3つ目のポストです。
前回はKubernetesクラスタが出来上がりましたので、今回はようやくGitOpsができるようレポジトリやツールのセットアップをしていきます。また出来上がったGitOps環境でmetallbという、サービスをKubernetesクラスタ外からアクセスできるようにするシステムの導入もやっていきます。
本シリーズのお約束
-
Kubernetes
Cluster on 3 nodes (2 raspberry pi4 - arm64, and 1 amd64 fanless mini PC)-
flannel
for networking -
flux
as a GitOps tool - metallb for
LoadBalancer
service type implementation
-
- 1 or more machine running
Docker
- serving
GitLab
(Used for GitOps central repository) - serving
Nginx
(Reverse proxy to provide access to GitLab and other web services to be created on Kubernetes Cluster) - serving
Unbound
(DNS resolver for machines on LAN)
- serving
- public DNS domain + SSL/TLS certification (for example, Let's Encrypt) recommended
- they are all
mydomain.net
in the series - replace
mydomain.net
with your own DNS domain to follow through
- they are all
More on Docker - Series Top: Dockerで作るおうちLAN遊び場 シリーズ1/7
Interested in getting your own DNS domain?
現状の再確認
まずは本ポスト開始時点で、前回までに用意したGitLabサーバと、構築したてのKubernetesクラスタがあります。
Kubernetesクラスタにはkube-systemというnamespace上に、Kubernetesクラスタとして機能するために必要な数々のpodが動作しています。ちなみにcontrol-planeでkubectl get pods -n kube-system
と実行するとpodのリストが見られます。またオプションを加えてkubectl get pods -n kube-system -o wide
とすると各podがどのnode上で動作しているかなども見られます。
今回追加されるもの
今回追加されるものリストは次の通りです。
- "flux-config"というレポジトリをGitLabに追加
- control-planeにfluxツールをインストール
- fluxツールでKubernetesクラスタと"flux-config"というレポジトリを関連付ける
- この時、"flux-config"レポジトリにflux関連のマニフェストファイルが書き加えられる
- 同時にクラスタ上にflux-systemというnamespaceと、fluxがGitOpsツールとして動作するのに必要なpodが作られる
- 以後、flux-system内のpodらがレポジトリの変更を監視し、レポジトリ上の変更内容に応じてfluxのpodがKubernetesクラスタへ変更命令を出すという形になる
- "flux-config"レポジトリにmetallb追加用のファイルを追加する
- fluxがKubernetesクラスタ上にmetallbを追加するよう手配してくれる
セットアップ開始
それではセットアップを進めていきます。まずはGitLabでの準備からです。
GitLab上の準備開始
実は今回やっていくことは、大体GitLab公式のドキュメントで紹介されている通りになります。
https://docs.gitlab.com/ee/user/clusters/agent/gitops/flux_tutorial.html
gitopsグループ作成
まずはgitopsというグループを作りましょう。そしてそのグループのページへ移動しましょう。https://gitlab.mydomain.net/gitops
といったURLになると思います。
グループアクセストークン発行
"Settings > Access Tokens"と移動し、グループアクセストークンを発行します。以下のような設定で発行し、トークン・文字列を控えておきましょう。
- Token name: "gitops_token"など、自由に決めましょう
- Expiration date: 私は10年後としました
- Select a role: 私はMaintainerにしました (developerでもよかったでしょうか)
- Select scopes: apiのみ有効にします
flux-configレポジトリを作成
gitopsグループでflux-configという名称のレポジトリを作成しましょう。
control-planeにfluxツールをインストール
一旦GitLabから離れ、Kubernetesクラスタのcontrol-planeとして動いているノード、本シリーズではrpi4bp、で作業します。
先に紹介したGitLab上のドキュメントにもリンクがありますが、flux公式のドキュメントがこちらです。
# install flux
curl -s https://fluxcd.io/install.sh | sudo bash
# check
❯ which flux
/usr/local/bin/flux
❯ flux --version
flux version 2.0.0-rc.2
bootstrap
続いてfluxでbootstrapします。これはつまりKubernetesクラスタ構築時にkubeadm init
したのと同様に、fluxをKubernetesクラスタおよびGitLabレポジトリに導入する初期セットアッププロセスです。
まず先程取得したグループアクセストークンをGITLAB_TOKENとしてexportします。続くflux bootstrap gitlab
コマンドでbootstrapを実行させます。
コマンドは以下の通りとなります。なおこのポストを書いている時点で、GitLab上のドキュメントではトークンに関するオプションが--deploy-token-auth
となっていますが、flux側のバージョンアップの結果でしょうか、--token-auth
が有効なオプションとなっています。
# export access token as GITLAB_TOKEN
export GITLAB_TOKEN={gitlab group access token string}
# run flux bootstrap
flux bootstrap gitlab \
--hostname=gitlab.mydomain.net \
--owner=gitops \
--repository=flux-config \
--branch=main \
--path=clusters/my-cluster \
--token-auth
GitOpsを試そう!!
これでGitOps環境は完成です!以後、flux-configレポジトリ内、mainブランチのclusters/my-cluster
配下に配置したマニフェストはfluxによってKubernetesクラスタへ反映されていきます。これがGitOpsの肝で、reconcilationというプロセスによって成されるのですが、「ソースとして記載されている状態とKubernetesクラスタのリソースの状態とを合致させる」といったイメージのプロセスとなります。
では早速gitでpushするだけでKubernetesクラスタにモノをデプロイできるのか試してみましょう。
先のGitLab公式ドキュメントにもbootstrapの続きがあり、それについても後でカバーしたいのですが、まずはmetallbをクラスタに導入させてください。
metallb
Kubernetesはサービスへアクセスできるようにするのが難しい
Dockerで初めて遊ぶ時、コンテナを実行して比較的すぐそのコンテナのサービスにDockerのホスト端末および他の端末からでもアクセスできるようにできます。例えばdocker run hello-world
でローカルでコンテナを実行・確認でき、docker run -p 80:80 nginx
でリモートからもdockerコンテナを走らせている端末のポート80へのアクセスでサービスへのアクセスが確認できます。
ところがKubernetesの場合、kubeadm init/join
でクラスタを構築できたと思いきや、ネットワークプラグインを導入するまでpodを実行してみることはできず、更にはマニフェストを流し込んでpodを実行できてkubectl get pods
などで実行していることを確認できたと思いきや、今度はそのpodのサービスにアクセスする方法がなくて困るといったことに直面します。クラスタのcontrol-planeなどからはcurl {IP address of pod running nginx}
などでアクセスできるのですが、クラスタ外からはDockerのコンテナの例のように簡単にはアクセスがセットアップできません。クラウドサービスの場合はもちろん他からクラスタ上のサービスへアクセスするための仕組み・サービスが備わっていますが、オンプレに自前で構築したKubernetesクラスタにはそういったものがありません。
前置きが長くなってしまいましたが、要するにmetallbを導入すればKubernetesクラスタ上に走らせるサービスへのクラスタ外からのアクセスを容易に構築できます。
metallbに使わせるLANのIPアドレスレンジ
このシリーズでは192.168.1.0/24が実ネットワークとなっており、192.168.1.55-56あたりのノードでGitLabや他のサービスをDockerコンテナとして走らせています。Kubernetesクラスタ上のサービスも同じサブネット上のアドレスでアクセスできるようにするのですが、それをやってくれるmetallbには192.168.1.200-250を設定することにします。
マニフェスト
ではfluxに拾ってもらい、Kubernetesクラスタへ当ててもらうマニフェストファイルを用意していきます。
最初にディレクトリの用意です。/clusters/my-cluster
以下に、/clusters/my-cluster/metallb-system
としてディレクトリを用意しましょう。
このmetallb-system
ディレクトリに3つファイルを用意します。
1つ目はkustomization.yaml
です。大本のシステムに関するマニフェストはマニュアルに倣いgithub上にあるものを直接参照します。更に追加で、このディレクトリに配置するconfig.yaml
とl2adv.yaml
も使うということを指示しているファイルとなります。
なおバージョンについてはその時の最新のものを参照すればよいと思います。ここではv0.13.9
となっています。
https://metallb.universe.tf/installation/#installation-with-kustomize
namespace: metallb-system
resources:
- github.com/metallb/metallb/config/native?ref=v0.13.9
- config.yaml
- l2adv.yaml
2つ目のファイルはconfig.yaml
です。先程触れた、metallbに使わせるIPアドレスレンジを指定しています。
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: lan-addr-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
最後にl2adv.yaml
です。OSI参照レイヤ2の仕組みでなんとかしてサービスをネットワーク上に広報しますよ、つまりARPやMACアドレスでなんとかしますよという場合、L2Advertisement
を選択します。このファイルではどのIPAddressPool
を使うのかという指定をしていません。その場合、あるものすべて使いなさいということになり、今回は唯一config.yaml
内で作っているプールだけ使われるということになります。
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2adv-addr-pool
namespace: metallb-system
このシリーズではカバーしませんが、LAN環境にBGPルータがいる場合は、metallbのBGPAdvertisement
で構築するのもよいと思います。大きなKubernetesクラスタ、大きなサービス用サブネットで豪勢に遊べると思います。BFDやlocal pref、community、vrfなども利用できます。
さて、以上の3ファイルをレポジトリのmainブランチにpushすると、ほどなくKubernetesクラスタに反映されます。kubectl get ns
でmetallb-system
ができていることが確認でき、kubectl get pods -n metallb-system -o wide
でcontrollerのpodが一つ、speakerのpodが各ノードで走っていることが確認できます。
metallb導入が完了しました!
❯ tree
.
|-.git
|-clusters
| |-my-cluster
| | |-flux-system
| | | |-gotk-components.yaml
| | | |-kustomization.yaml
| | | |-gotk-sync.yaml
| | |-metallb-system
| | | |-config.yaml
| | | |-l2adv.yaml
| | | |-kustomization.yaml
|-README.md
nginx deployment
それでは続いてNginxを走らせてみましょう。大体先のGitLab公式のドキュメントの続きをなぞっていく形になりますが、metallbを活用してLAN上の他の端末からアクセスできる状態にまで持っていきます。
別レポジトリの用意
まずはgitopsグループ下に"web-app-manifests"という新しいレポジトリを作りましょう。
deploymentマニフェストの用意
そしてそのレポジトリにnginx-deployment.yaml
というマニフェストファイルを用意しましょう。内容は以下の通りです。GitLab公式のドキュメントからの変更点は、replicasを3から1にしているところです。3のままでも全く問題ありません。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
デプロイトークンの発行
次にこのレポジトリのデプロイトークンを発行します。"Settings > Repository settings > Deploy tokens"に行き、NameとScopesを入力して"Create deploy token"をクリックすれば発行できます。例えば次のようにしましょう。
- name: web-app-manifests-deploy-token
- scopes: read_repository
- expiration dateとusernameはoptionalなので空欄のまま
Usernameとpasswordが生成されますので一時的にどこかに記録しておきましょう。
デプロイトークンをクラスタ上にsecretとして作成
Kubernetesクラスタのcontrol-planeにfluxをインストールしたかと思いますが、このflux cliをbootstrapぶりに使います。ドキュメント通りの命名となりますが、"flux-deployment-authentication"という名称のsecretをKubernetesクラスタ上に作成します。
flux create secret git flux-deploy-authentication \
--url=https://gitlab.mydomain.net/gitops/web-app-manifests \
--namespace=default \
--username={deploy token username} \
--password={deploy token password}
kubectl -n default get secrets flux-deploy-authentication -o yaml
を実行し、secretができていることを確認しましょう。
flux-configに参照の追加
Kubernetesクラスタと連携させてあるflux-configレポジトリで、参照するソースの追加をしましょう。
例によってYAML形式のマニフェストファイルをレポジトリのclusters/my-cluster
に配置するのですが、内容はflux cliを使って生成することができます。もしローカルにレポジトリがある状態であれば、以下で直接ファイルを用意できます。
flux create source git web-app-manifests \
--url=https://gitlab.mydomain.net/gitops/web-app-manifests.git \
--branch=main \
--secret-ref=flux-deploy-authentication \
--export > clusters/mycluster/web-app-manifests-source.yaml
ちなみに生成される内容は以下です。
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: web-app-manifests
namespace: flux-system
spec:
interval: 1m0s
ref:
branch: main
secretRef:
name: flux-deploy-authentication
url: https://gitlab.mydomain.net/gitops/web-app-manifests.git
kustomizationの追加
参照すべき別のgitレポジトリの追加はこれでできました。最後にkustomizationの追加です。これもflux cliで生成できます。先に用意した"web-app-manifests"というgit sourceを対象に、そのレポジトリの"./"にあるマニフェストを対象とするkustomizationファイルになります。
つまり先程"web-app-manifests"レポジトリ上に用意したnginx-deployment.yaml
の内容がKubernetesクラスタに反映されるわけです。
flux create kustomization nginx-source-kustomization \
--namespace=default \
--source=GitRepository/web-app-manifests \
--path="./" \
--prune=true \
--interval=1m \
--target-namespace=default \
--export > clusters/mycluster/web-app-manifests-kustomization.yaml
生成される内容は以下です。
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: nginx-source-kustomization
namespace: default
spec:
interval: 1m0s
path: ./
prune: true
sourceRef:
kind: GitRepository
name: web-app-manifests
targetNamespace: default
nginx-deployment完成
少し待つと、podがクラスタ上で実行されていることが確認できます。
# check the available deployment
❯ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 1/1 1 1 61s
# check the pod
❯ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-cbdccf466-8rvpf 1/1 Running 0 4s 10.244.2.13 rpi4 <none> <none>
# check the service
❯ curl 10.244.2.13 -I
HTTP/1.1 200 OK
Server: nginx/1.14.2
......
metallbの利用
最後にmetallbも利用してこのNginxにLAN、192.168.1.0/24上のアドレスでアクセスできるようにしましょう。
"web-app-manifests"レポジトリで、追加のファイルとして用意しても良いですし、nginx-deployment.yaml
ファイルに追記する形でもよいです。Serviceを追加しましょう。以下の内容となります。
---
apiVersion: v1
kind: Service
metadata:
name: web-app
labels:
app: nginx
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- name: http-svc
protocol: TCP
port: 80
After MetalLB is installed and configured, to expose a service externally, simply create it with
spec.type
set toLoadBalancer
, and MetalLB will do the rest.
metallbが動作しているKubernetesクラスタでは、LoadBalancerタイプのServiceを用意するとそれだけでIPアドレスプールよりIPアドレスを選んで勝手にLAN上で見えるようになります。なんて便利なのでしょう。
それではserviceを確認してみましょう。以下の出力はcontrol-plane上で実行したcurlですが、LAN上の他のPCやスマホのブラウザなどからもアクセスできるようになっています!
# check service
❯ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
web-app LoadBalancer 10.99.119.177 192.168.1.201 80:31224/TCP 6s
# access 192.168.1.201:80 to verify access
❯ curl -I 192.168.1.201
HTTP/1.1 200 OK
Server: nginx/1.14.2
......
出来上がったもの
前回まででGitLabとまっさらなKubernetesクラスタを作りました。今回はそれらの上にいろいろ導入しました。
- GitLabに"gitops"グループ作成
- API利用権限を付与したグループアクセストークン発行
- GitLabの"gitops"グループ下に新規プロジェクト・レポジトリ"flux-config"を作成
- Kubernetesクラスタのcontrol-planeにfluxツールをインストール
- flux bootstrapで"flux-config"レポジトリおよびKubernetesクラスタにfluxを導入
- GitOps環境完成!!
- "flux-config"の
/clusters/my-cluster
以下に配置したマニフェストなどはGitOpsで処理されるようになった
- metallbのkustomizationや他のマニフェストを
/clusters/my-cluster/metallb-system
に配置し、metallbをKubernetesクラスタに導入 - GitLabに新規レポジトリ"web-app-manifests"を作成し、Nginxのdeploymentマニフェストファイルを配置
- またこのレポジトリより、read-onlyのデプロイトークンを発行
- flux cliを使い、トークンを"flux-deploy-authentication"という名称のKubernetesのsecretとして作成
- "flux-config"の
/clusters/my-cluster
以下に"web-app-manifests"を外部git sourceとして登録するマニフェストを配置- またこのマニフェストにはデプロイトークン・secretを使うよう記載されている
- 更に"flux-config"の
/clusters/my-cluster
以下に"web-app-manifests"レポジトリの内容を参照してkustomizationを走らせるというマニフェストファイルも配置 - Nginx用にLoadBalancerタイプのServiceを作るよう、"web-app-manifests"上のマニフェストファイルに追記
- Kubernetesクラスタ上にServiceが作られる
- 同時に、metallbによって実ネットワークのIPアドレスでサービスにアクセスできる入り口が作られる
Discussion