はじめに
これは KWC Advent Calendar 2022 の記事です。
こんにちは。KWCでSREを担当する、パクヒョンギョンです。
今回、K8Sの勉強のため、個人で開発しているKubernetes Operatorを書いてみよう思います。
この記事は「https://tech.kakao.com/2022/02/09/k8s-redis/」こちらの記事の内容通り実際に開発してみたことなどをまとめたものです。
韓国語の記事ですが、PM(Physical Machine)に乗っているRedisをVM(Virtual Machine)に変更してK8S環境に運用する手順と問題点が記載してあります。
この記事を作成しようとした切っ掛け
K8Sは実務で使ったことがなく独学していますので、関連知識を高めるために今回の記事を作成しました。
記事の内容と間違っているところや記事を読みながらよく分からない部分は勝手に解析して開発したものもありますので
あくまでこの記事は参考用でみて頂けると幸いです。
構成方法
結論からいうとKubernetes Operator Patternを使いました。そして、
HAのためPod Affinityを適用し、モニタリングのためにRedis ExporterとPrometheus、そしてGrafanaを使いました。
韓国の記事にはRedisの性能のためHost Networkを使っていますが、
Containers:
Port: 80/TCP
Host Port: 80/TCP
こちらの記事ではRedisクラスタにアクセスするにはIngress Controllerを使って通信するように開発してみようと思います。
- Kubernetes Operator Pattern
- Ingress Controller
- Pod Affinity
- Redis Exporter + Prometheus + Grafana
CRDの動きと詳細
Redis Controller (Reconcile)
Kubernetesは定義されたアプリケーションの意図した状態(Desired State)と現在の状態(Current State)が一致しているかを監視して一致してない場合、これをControllerから調整(Reconcile)する作業が実施され、意図した状態になります。
例として以下は「Replication Controller」の動きとしては
になります。
今回は(KRedis)というCustom Resourceを作りますので「Redis Controller」を開発しようとします。
ちなみにDeploymentとかJobとか既存K8SリソースにもControllerがあります。
https://developers.redhat.com/articles/2021/06/22/kubernetes-operators-101-part-2-how-operators-work#deploying_workloads_in_kubernetes
CRDが追加された場合
まだ、開発中ですが、CRを作るとRedis ControllerからReconcile関数が実行され、Deploymentが立ち上がるのとPodのSpecなどをお見せします。
まず、make deploy
でcontrollerをClusterにディプロイできます。詳しい内容はOperatorをインストールして「Makefile」の中身をご覧ください。
% kubectl get all -n operator-system
NAME READY STATUS RESTARTS AGE
pod/operator-controller-manager-567b446c69-jrrdx 2/2 Running 0 18s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/operator-controller-manager-metrics-service ClusterIP 10.***.***.*** <none> 8443/TCP 19s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/operator-controller-manager 1/1 1 1 19s
NAME DESIRED CURRENT READY AGE
replicaset.apps/operator-controller-manager-567b446c69 1 1 1 19s
get
で確認してみると私が作ったcontrollerが「deployment.apps/operator-controller-manager」名のdeploymentで立ち上がっているのを確認できました。
基本的にリソースが生成されるネームスペースはプロジェクト名になります。
そして、Controllerも「Replicas 1、Surge 100%」Deploymentリソースになります。
controllerが上がっている状態でCRを生成してみます。
% kubectl apply -f config/samples/stable_v1_kredis.yaml -n operator-system
kredis.stable.example.com/kredis-sample created
% kubectl get kredis -n operator-system
NAME AGE
kredis-sample 60s
問題なく生成されてget
で確認しても「kredis-sample」名で立ち上がっているのを確認できました。
私が追加したSpec通り設定されているかも確認してみます。
% kubectl describe kredis kredis-sample -n operator-system | grep -A9 "Spec"
Spec:
Base Port: 10000
Image: {AWS ECR}/redis-cluster:latest
Masters: 2
Memory: 1gb
Replicas: 1
Resource:
Requests:
Cpu: 2
Memory: 2000Mi
Specには問題なさそうですのでReconcileによってdeploymentまで生成されたのか確認してみます。
% kubectl get all -n operator-system | grep -B1 "kredis"
NAME READY STATUS RESTARTS AGE
pod/kredis-sample-7bc8b59fbc-vptdb 1/1 Running 0 7m32s
--
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kredis-sample ClusterIP 10.***.***.*** <none> 6379/TCP 7m33s
--
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kredis-sample 1/1 1 1 7m33s
--
NAME DESIRED CURRENT READY AGE
replicaset.apps/kredis-sample-7bc8b59fbc 1 1 1 7m33s
deploymentも問題なく立ち上がっていて「pod/kredis-sample-7bc8b59fbc-vptdb」Podに入ってRedisコンソールに入れるのも確認できました。
一応、今回はここまで開発ができましたが、残りは今後時間があれば続けて開発しようと思います。
ちなみにOperatorがK8Sリソースを操作するには、Service Accountに権限(ClusterRole)を追加する必要があります。
https://book.kubebuilder.io/reference/markers/rbac.html
CRDが更新された場合:(HPA)
ClusterにCRDが既にある場合、更新(Reconcile)作業を行います。こちらの処理もCustom Controllerで直接、開発する必要があります。←こちらはCRD追加処理の開発が終わってないので更新処理はまだ、未実装です。
そして、普通にkind: HorizontalPodAutoscaler
のリソースを使ってHPAを実装しようとしましたが、通常のHPAはDeploymentのReplicasを調整してくれますので
今回、調整したかったのは
を実装したかったのですが、CRDのSpecを調整する方法がわからないため現在継続調査中です。
https://book.kubebuilder.io/reference/generating-crd.html#scale
こちらをみるとCRDにもHPAのためにOperatorにコードを追加して設定するのがあるようですので今後、参考して開発するつもりです。
Redis Cluster HA処理:(failover)
Redis Cluster自体でMasterノードが落ちるとreplica設定で結んでいるslave nodeが自動でMasterノード(failover)になります。
Redisポッドの構成
topology key
HAのためにMaster nodeとReplica nodeのPodを別のワーカーノードに配置するため、labelを追加して対応しようとしますが、
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
nodeId: "masterNodeId"
topologykey: "kubernetes.io/hostname"
こちらもまだ、開発中です。一応、上の仕様通り設定すればいけるかなと思っていて前の開発が終わってから検証してみようと思います。
CRD Spec
以下はCRDのSpecになります。
spec:
masters: 2 # Redis Cluster のMaster Node 数
replicas: 1 # Redis Cluster のReplica Node 数
memory: 1gb # これはRedisのMax Memory
basePort: 10000 # redis port: 10000, redis exporter port: 15000, Cluster bus port: 20000,
image:
resource:
requests:
cpu: '2'
memory: 2000Mi
OperatorでCRDのSpecを変えるには「{crd}_types.go」を修正する必要があります。
https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/#define-the-api
// KRedisSpec defines the desired state of KRedis
type KRedisSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of KRedis. Edit kredis_types.go to remove/update
Image string `json:"image"`
Masters int32 `json:"masters"`
Replicas int32 `json:"replicas"`
Memory string `json:"memory"`
BasePort int32 `json:"basePort"`
Resource map[string]map[string]string `json:"resource"`
}
モニタリング
metrics-server インストール
モニタリングとHPAを設定するためには metrics-server をインストールします。
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
これでkubectl top ~
のコマンドが実行できるようになりました。CPUとMemory使用量のmetric情報はetcdに保存され、スケジューラがスケールアウトする時やPrometheusが情報収集する際に使用されます。
Prometheus、Grafana
Prometheus
こちらを参考にConfigMapを作ってPrometheusを構築し、Grafanaまで設定しました。
後、Redis Exporterを入れてPrometheusのTargetを設定をする必要がありますが、調査と構築するには時間がかかりそうですので今回は監視インフラだけ設定しました。
まだ、未実装のところ
- 監視(Redis Exporter)の設定
- CRDの更新やスケールイン・アウト(HPA)の時、追加されたPodをRedis Clusterに追加、削除
- Master nodeとReplica nodeのRedis Podを別のワーカーノードに配置されるようにAffinity設定(HA)
- Podが落ちて削除された場合、Replica nodeを追加 ← (削除されたら他のPodがMasterに昇格されるので)
- (Liveness, Readiness)でPodの状態を確認
- Ingress Controllerと紐づいて疎通テスト
- Roll Back処理
- 検証
おわりに
RedisをK8S上に運用することでメリットとしてはHA構成であってスケールイン・アウトもしやすくなった点ではないかと思います。
今回、KubernetesのCRDとCustom Controllerを直接、開発してみてちょっとK8Sに慣れてきましたので
もし、K8Sを勉強しようとする方にはOperatorを直接、開発してみることをおすすめします。
ここまで読んで頂いてありがとうございます。記事の作成と並行で開発してて未実装のところが多く、ほとんど、日記のような内容でしたが、皆様にお役に立てれば幸いです。
KWC Advent Calendar 2022 はまだまだ続きます!明日の投稿もお楽しみに!