2021年6月6日日曜日

k8s の Operator を理解するために Operator SDK golang をとりあえず流してみた

k8s の Operator を理解するために Operator SDK golang をとりあえず流してみた

概要

k8s の Operator や CustomResource の実装をするにあたって全くイメージがなかったのでまずは Operatro SDK のチュートリアルを試してみました

環境

  • k8s v1.20.1
  • golang 1.16.3
    • operator-sdk 1.8.0
  • docker 19.03.6

準備

今回は以下の環境で実施しています

  • k8s 環境の準備
  • docker プライベートレジストリの準備

operator-sdk のインストール

まずは operator-sdk をインストールします これをインストールすることでひな形やビルドを簡単に行うことができます

  • export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac)
  • export OS=$(uname | awk ‘{print tolower($0)}’)
  • export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.8.0
  • curl -LO KaTeX parse error: Expected group after '_' at position 35: …L}/operator-sdk_̲{OS}_${ARCH}
  • gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E
  • curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt
  • curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc
  • gpg -u “Operator SDK (release) cncf-operator-sdk@cncf.io” --verify checksums.txt.asc
  • grep operator-sdk_KaTeX parse error: Expected group after '_' at position 5: {OS}_̲{ARCH} checksums.txt | sha256sum -c -

これで operator-sdk コマンドが使えるようになります

  • operator-sdk version

プロジェクトの作成

プロジェクトの雛形を作成します

example.com の部分は自身で準備したプライベートレジストリのドメインを設定してください

example.com でも問題なく進められるのでこのままでも OK です

以下のようなディレクトリとファイル構成で作成されます

  • tree
.
├── config
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   └── manager_config_patch.yaml
│   ├── manager
│   │   ├── controller_manager_config.yaml
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── manifests
│   │   └── kustomization.yaml
│   ├── prometheus
│   │   ├── kustomization.yaml
│   │   └── monitor.yaml
│   ├── rbac
│   │   ├── auth_proxy_client_clusterrole.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── role_binding.yaml
│   │   └── service_account.yaml
│   └── scorecard
│       ├── bases
│       │   └── config.yaml
│       ├── kustomization.yaml
│       └── patches
│           ├── basic.config.yaml
│           └── olm.config.yaml
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
├── main.go
├── Makefile
└── PROJECT

API リソースの作成

次に operator の動作に必要な API の go ファイルを作成します 生成される go ファイルでプログラムすることで独自のオペレータを作成することができます

今回はチュートリアルなので github にあるサンプルを使います なお公式のチュートリアルだけだとすべてが記載されていないので注意してください

CustomResource の定義

こちらは spec のパラメータなどを指定します

コントローラの定義

実際にメインの処理を記載するコントローラを生成します

なお公式のチュートリアルは執筆時点では v1.3.0 タグの mmemcached_controller.go を使っているのですがそれで実行すると 60 行目で invalid memory address or nil pointer dereference になります

リソースファイルの生成

memcached_types.go と memcached_controller.go を編集できたらリソースファイルを生成します

  • make generate
  • make manifests

成功すると CustomResource と RBAC のマニフェストファイルが生成されます

  • less config/crd/bases/cache.example.com_memcacheds.yaml
  • less config/rbac/role.yaml

依存関係でエラーになる場合は以下を追加でインストールしてください

ビルド&プッシュ

実際に k8s 上に CustomResource をデプロイするためにイメージをビルドしてレジストリにプッシュします

冒頭プロジェクト作成時に指定した domain の部分をレジストリのドメインにしていてもプッシュ先の URL が違う場合は Makefile を修正します IMG の部分がビルドされるイメージ名になるのでここにプッシュ可能なイメージ名を指定します

  • vim Makefile
IMG ?= container-registry.your.private.repo/hawksnowlog/proj:latest

ちなみにデフォルトでは dockerhub にプッシュするようになっています あとはビルド、プッシュしましょう

  • make docker-build docker-push

もしプッシュできない場合は上記の IMG の設定を再確認してください もしくはプライベートレジストリにログインできているか確認してください もしできていない場合は docker login してからビルドしてください

デプロイ

CustomResource のイメージがレジストリにプッシュできたら実際に k8s 上に展開してみます

  • make deploy

しばらくすると以下のように CustomResource 用の Pod がデプロイされます

  • kubectl get pod -n memcached-operator-system
NAME                                                    READY   STATUS    RESTARTS   AGE
memcached-operator-controller-manager-6fb5b6d8b-bg4x5   2/2     Running   0          8m40s

認証ありのプライベートレジストリを使っている場合は

k8s からもプライベートレジストリにアクセスできる必要があります レジストリ認証情報を secret として登録しその secret 情報を CustomResource 用の Pod から使うようにします

  • kubectl create secret generic regcred --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson -n memcached-operator-system
  • kubectl edit deployment -n memcached-operator-system
    spec:
      imagePullSecrets:
      - name: regcred

もしかすると operator 作成時に imagePullSecrets を指定する方法があるのですが見つからなかったので今回は make deploy 後に手動で secrts の情報を指定しています

動作確認

これで自作の CustomResource を使ったオペレータを使って Pod などのデプロイができるようになります マニフェストは以下のファイルにあります spec の部分に size: 3 を指定しましょう

  • vim config/samples/cache_v1alpha1_memcached.yaml
apiVersion: cache.example.com/v1alpha1
kind: Memcached
metadata:
  name: memcached-sample
spec:
  size: 3

ポイントは kind: Memcached になっている点です これが CustomResource として自作で作成したリソースになります

デプロイして memcached の Pod が上がってくることを確認します

  • kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml
# kubectl get pod
NAME                                               READY   STATUS    RESTARTS   AGE
memcached-sample-6c765df685-gsc5w                  1/1     Running   0          21s
memcached-sample-6c765df685-r9dnh                  1/1     Running   0          21s
memcached-sample-6c765df685-v8tph                  1/1     Running   0          21s
# kubectl exec pod/memcached-sample-6c765df685-gsc5w -it -- telnet localhost 11211
set name 0 0 11
hawksnowlog
STORED
quit
Connection closed by foreign host
command terminated with exit code 1

# kubectl exec pod/memcached-sample-6c765df685-gsc5w -it -- telnet localhost 11211
get name
VALUE name 0 11
hawksnowlog
END
quit
Connection closed by foreign host
command terminated with exit code 1

今回は Service などの定義がないので直接 Pod で実行していますが問題なく memcached が動作するのが確認できると思います

クリーンアップ

  • make undeploy

最後に

ポイントは

  • CustomResource を作成し API として k8s 上にデプロイする
  • その API を使って CustomResource を作成する
  • リソース作成時に好きな命令を golang で実装できる

です とりあえず今回のチュートリアルだけでもこの流れはつかめるかなと思います

実際は controller や types をプログラムして独自のオペレータを実装することになります ビルドやデプロイの流れは同じかなと思います

トラブルシューティング

memcached の Pod が CustomResource を使ってデプロイできない場合は memcached-operator-controller-manager のログを確認してみましょう

go スクリプトのビルドはできたけど nil 参照などしている場所がある場合はそこでエラーとなり CustomResource が動作していないことが確認できると思います

参考サイト

0 件のコメント:

コメントを投稿