Fluxでk8sをGitOpsしてみる

f:id:fclout:20200531225600p:plain

はじめに


今回はコンテナ仮想化プラットフォーム「docker」のオーケストレーションツールである「Kubernetesk8s)」の話。


k8sを運用する場合に、マニフェストだったりdockerイメージだったりをリポジトリで管理すると思うのですが、
その際に出てくる考え方がGitOpsです。

www.weave.works

FluxはGitOpsを実現するためのツール

f:id:fclout:20200531225954p:plain

今回はいくつかあるツールの中でも、
GitOps提唱者であるweaveworks社が出している「Flux」を使ってみたいと思います。
(他にもArgoCDやJenkinsXなどがあります)

k8sクラスタ環境が前提となりますが「Flux」の導入はとっても簡単です。
k8sクラスタ環境の構築については以下のREADMEにまとめてあります。

github.com


では早速導入していきましょう。

前提

今回の導入環境です。

項目 備考
OS CentOS Linux release 8.1.1911 (Core) Hyper-Vゲスト
CPU 2vCPU
メモリ 8GB
docker 17.06
kubernetes v1.18.1 マスターノード
Gitリポジトリサービス Github https://github.com/ultimania

 


fluxctlの導入

fluxのセットアップにはfluxctlというツールが必要になります。
Linuxの場合はsnapdを使ってインストールします。

dnf install epel-release
dnf install snapd
systemctl enable --now snapd.socket
ln -s /var/lib/snapd/snap /snap

ここでsnapdを有効化するために再起動。

reboot


再起動後にfluxctlをインストール。

snap install fluxctl --classic


ちなみに再起動しないままやっちゃうと以下のエラーがおきます。

	error: too early for operation, device not yet seeded or device model not acknowledged

  


同期先リポジトリの準備

今回は同期先のリポジトリとしてサンプルで用意されている以下のリポジトリをforkして使用します。

サンプルリポジトリ fork後のリポジトリ
https://github.com/fluxcd/flux-get-started https://github.com/ultimania/flux-get-started

  


fluxのセットアップ


flux用のnamespaceを作成。

kubectl create ns flux

	namespace/flux created


fluxをセットアップ。
GHUSER環境変数にはGithubのアカウント名を入れてください。

export GHUSER="ultimania"
fluxctl install \
--git-user=${GHUSER} \
--git-email=${GHUSER}@users.noreply.github.com \
--git-url=git@github.com:${GHUSER}/flux-get-started \
--git-path=namespaces,workloads \
--namespace=flux | kubectl apply -f -

	serviceaccount/flux created
	clusterrole.rbac.authorization.k8s.io/flux created
	clusterrolebinding.rbac.authorization.k8s.io/flux created
	deployment.apps/flux created
	secret/flux-git-deploy created
	deployment.apps/memcached created
	service/memcached created


fluxctl install はfluxコンポーネントを作成するためのマニフェスト群を標準出力するコマンドです。
それを"|"(パイプ)で kubectl apply に渡しているわけですね。
なので同じ方法でkubectl deleteに渡せばすぐにuninstallできちゃいます。


fluxがインストールされていることを確認します。

kubectl get all -n flux

	NAME                             READY   STATUS    RESTARTS   AGE
	pod/flux-59bc5545b-9ln86         1/1     Running   0          17m
	pod/memcached-5bd7849b84-9zwds   1/1     Running   0          17m
	
	NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
	service/memcached   ClusterIP   10.101.159.19   <none>        11211/TCP   17m
	
	NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
	deployment.apps/flux        1/1     1            1           17m
	deployment.apps/memcached   1/1     1            1           17m
	
	NAME                                   DESIRED   CURRENT   READY   AGE
	replicaset.apps/flux-59bc5545b         1         1         1       17m
	replicaset.apps/memcached-5bd7849b84   1         1         1       17m

Runningになっており問題ないようです



fluxとGithubリポジトリとの同期

Githubとの同期をとるために、対象のリポジトリにFluxで作成した公開鍵を登録します。

公開鍵の作成

まずFluxで公開鍵を作成します。

fluxctl identity --k8s-fwd-ns flux

	ssh-rsa *******= root@flux-********

出力された公開鍵(ssh-rsaから始まる文字列)をコピー。


Githubの対象リポジトリにデプロイキーとして登録。

Githubのサイトからデプロイキーを登録します。

f:id:fclout:20200601001555p:plain

対象リポジトリの画面の「Setting」をクリック


f:id:fclout:20200601002119p:plain

左のサイドバーから「Deploy keys」をクリックし、
右上に出てくる「Add deploy key」をクリック。


f:id:fclout:20200601002601p:plain

登録フォームの画面で以下を入力する

  • Title:わかりやすいタイトル(「flux-key」とか)
  • Key:上でコピーした公開鍵の文字列を貼り付け
  • Allow write accessチェックボックスをON

すべての入力が完了したら「Add key」をクリック


f:id:fclout:20200601002839p:plain

デプロイキーが登録されます。


Githubの対象リポジトリk8sクラスタを同期

現状ではまだリポジトリの中身(サンプルコンテナ)はk8sにデプロイされてません。
デフォルトではfluxは5分に1回対象リポジトリにプルしにいくみたいですが、
すぐに同期をとりたい場合は以下のコマンドを実行します。

fluxctl sync --k8s-fwd-ns flux

	Synchronizing with ssh://git@github.com/ultimania/flux-get-started
	Revision of master to apply is e38a100
	Waiting for e38a100 to be applied ...
	Done.


ちなみに鍵がうまく登録されていなかったり、リポジトリやアカウント名が間違っており
うまく同期がとれない場合は上記コマンドが失敗します。

fluxctl sync --k8s-fwd-ns flux

	Error: git repository ssh://git@github.com/ultimania/flux-get-started 

	Full error message: git clone --mirror: fatal: Could not read from rem
	 Cloning into bare repository '/tmp/flux-gitclone047582877'...
	git@github.com: Permission denied (publickey).
	fatal: Could not read from remote repository.

	Please make sure you have the correct access rights
	and the repository exists.

	Run 'fluxctl sync --help' for usage.


きちんと同期がとれているかどうか確認するためにもfluxctl syncは実行しておきましょう。


サンプルコンテナがデプロイされたことを確認

うまく同期がとれたので、対象リポジトリに登録されているマニフェストにもとづいて
ローカルのk8sクラスタにコンテナがデプロイされているはずです。
確認してみましょう。

kubectl get all -n demo

	NAME                           READY   STATUS    RESTARTS   AGE
	pod/podinfo-58df84dbff-gk5lc   1/1     Running   0          47s
	pod/podinfo-58df84dbff-vb22g   1/1     Running   0          29s

	NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   
	service/podinfo   ClusterIP   10.96.116.154   <none>        9898/TCP  

	NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
	deployment.apps/podinfo   2/2     2            2           113s

	NAME                                 DESIRED   CURRENT   READY   AGE
	replicaset.apps/podinfo-58df84dbff   2         2         2       48s
	replicaset.apps/podinfo-789f8bd555   0         0         0       113s
	replicaset.apps/podinfo-9f6bdc7d8    0         0         0       66s


demoという名前空間にPodやらserviceやらが登録されています!
どうやら成功したみたいです。

サンプルサービスへの疎通確認

ちなみに今回デプロイされたserviceはClusterIPなので、
ポートフォワードさせて試しにアクセスしてみたいと思います。
(ブラウザからもアクセスできますが今回はcurlで)

kubectl port-forward svc/podinfo 8080:9898 -n 

	Forwarding from 127.0.0.1:8080 -> 9898
	Forwarding from [::1]:8080 -> 9898
curl localhost:8080

	{
	  "hostname": "podinfo-58df84dbff-gk5lc",
	  "version": "3.1.5",
	  "revision": "948de81ed319b4cae86ef9758866165acd4426a2",
	  "color": "#34577c",
	  "logo": "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif",
	  "message": "greetings from podinfo v3.1.5",
	  "goos": "linux",
	  "goarch": "amd64",
	  "runtime": "go1.13.6",
	  "num_goroutine": "8",
	  "num_cpu": "2"
	}

簡単な情報を表示するためのロゴページみたいです。
JSONでちゃんと返してくれるあたりがいいですね。


さいごに

この後はリポジトリ側で変更を加える(commit&pushする)と
それと同期してk8s側も自動的にkubectl applyされます。
まさにGitOpsな環境が出来上がりました。

あとはこれをどう運用していくのかという点も含めてもっと掘り下げたいと思います。


k8sクラスタさえできていれば、fluxの導入は簡単です。
便利な世の中になりましたよね~。

他にもk8sがらみのツールはたくさんあるので、
よりDevOpsな環境を整えるために色々と調査・検証していきたいと思います。