概要
- 本記事では、operator-sdkを利用して、deploymentのimageが変更されるたびに、slackに通知する仕組みを作成します。
- サンプルコード: https://github.com/solt9029/deployment-image-watcher
- 挙動: https://www.youtube.com/watch?v=eknVJj8E-HE&feature=youtu.be
対象読者
- 基本的なkubernetesの知識がある人
- operatorとは何か、なんとなく把握しているが、開発を行なったことがない人
- go言語の基本的な文法が読める人
はじめに
kubernetesの拡張機能の1つに、operatorが存在します。
operatorを利用すれば、運用の自動化を行うことができます。
operatorに関する詳しい説明は、下記リンクをご覧ください。
https://qiita.com/MahoTakara/items/af4ad8ab69c24102bd72
複数人で同一のclusterやnamespace上で開発を行なっている場合に、
誰がいつdeploymentのimageを変更したか分からず困る状況を想定し、
本記事では、deploymentのimageが変更されるたびに、slackに通知する仕組みを作成していきます。
なお、本記事で作成するものは、本来のoperator-sdkの使い方とは言えないため、
あくまでoperator-sdkに触れる目的であることをご留意ください。
環境構築
以下の環境が必要です。
- go
- operator-sdk
- docker
- kubectl
dockerやkubectlのインストールについては説明を省きます。
下記手順により、goおよびoperator-sdkをインストールします。
brew install go
go version # 筆者はv1.13.3を使用
export Go111MODULE=on # Go Modulesを使用するため
brew install operator-sdk
operator-sdk version # 筆者はv0.15.2を使用
また、kubernetesクラスタやdockerhub、slackapi(botによるメッセージ送信)が利用できる状態としてください。
開発
テンプレート生成
下記手順によりテンプレートを生成します。
operator-sdk new deployment-image-watcher --repo=github.com/<username>/deployment-image-watcher
cd deployment-image-watcher
operator-sdk add controller --api-version=deployment.k8s.io/v1alpha1 --kind=Deployment
通常、operator-sdkを使用する場合、CRD(Custom Resource Definition)を利用するのが一般的ですが、
今回はdeploymentのimageの変更を検知したいだけなので、CRDは生成しません。
controller
さっそく、根幹となるcontrollerを編集していきます。
controllerはpkg/controller/deployment/deployment_controller.go
に存在します。
重要な部分は以下の通りです。
またファイル全体は https://github.com/solt9029/deployment-image-watcher/blob/master/pkg/controller/deployment/deployment_controller.go から確認できます。
func add(mgr manager.Manager, r reconcile.Reconciler) error {
c, err := controller.New("deployment-controller", mgr, controller.Options{Reconciler: r})
if err != nil {
return err
}
slackClient := slack.New(os.Getenv("SLACK_TOKEN"))
source := &source.Kind{Type: &appsv1.Deployment{}}
handler := &handler.EnqueueRequestForObject{}
predicate := predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
for _, oldContainer := range e.MetaOld.(*appsv1.Deployment).Spec.Template.Spec.Containers {
for _, newContainer := range e.MetaNew.(*appsv1.Deployment).Spec.Template.Spec.Containers {
if oldContainer.Name == newContainer.Name && oldContainer.Image != newContainer.Image {
messageText := createMessage(newContainer.Name, newContainer.Image, oldContainer.Image)
slackClient.PostMessage(os.Getenv("SLACK_CHANNEL"), slack.MsgOptionText(messageText, true))
}
}
}
return true
},
}
err = c.Watch(source, handler, predicate)
if err != nil {
return err
}
return nil
}
watch関数のsourceの引数によって、監視対象としてdeploymentを設定します。
predicateは本来、deploymentの変更や追加、削除などのイベントに対して、
reconcileを行うべきかフィルタリングする役割を担っています。
このpredicate内では変更前の状態と変更後の状態を両方取得することができるため、
今回はこの部分でimageが変更されたかどうかを判定し、slack通知を行うロジックを書いています。
e.MetaOld.(*appsv1.Deployment).Spec.Template.Spec.Containers
によって変更前のdeployment.spec.template.containersを取得できます。
同様に、変更後のdeployment.spec.template.containersも取得できます。
それらを用いて、imageを比較し、変更があればslack通知を行なっています。
ビルド
これだけで開発は終了です。
下記手順でビルドし、イメージをdocker registryにpushします。
operator-sdk build <username>/deployment-image-watcher:latest
docker push <username>/deployment-image-watcher:latest
マニフェスト
deploy/secret.yaml
を追加し、以下のようなsecretのマニフェストを記述します。
SLACK_TOKEN
にはslackapiのtokenをbase64化した値を入れてください。
echo -n "<your slack token>" | base64
apiVersion: v1
kind: Secret
metadata:
name: deployment-image-watcher
type: Opaque
data:
SLACK_TOKEN: <YOUR_SLACK_TOKEN_BASE64_ENCODED>
次に、deploy/operator.yaml
を編集します。
以下の2つの環境変数を追加してください。
- name: SLACK_TOKEN
valueFrom:
secretKeyRef:
name: deployment-image-watcher
key: SLACK_TOKEN
- name: SLACK_CHANNEL
value: "general"
動作確認
下記手順により、deployment-image-watcherをデプロイします。
kubectl apply -f deploy/
なんらかのdeploymentをapplyし、imageを変更してみてください。
slackに通知が届くはずです。
おわりに
本記事では、operator-sdkを利用して、deploymentのimageが変更されるたびに、slackに通知する仕組みを作成しました。
operator-sdkを手軽に使うために、CRDを用いずに簡易的なサンプルを実装しました。
本来のoperator-sdkの利用目的とは若干ずれていましたが、本記事によって基本的な使い方がわかれば幸いです。
ありがとうございました。