Ponz Dev Log

ゆるくてマイペースな開発日記

OpenShift LocalでPVのDynamic Provisioningを試す

この記事はOpenShift Advent Calender 2022の10日目の記事です。 前日は @ArakiToshihiro さんの『見かけたjarファイルをOpenShift にデプロイする』でした。

お仕事でOpenShiftを使うことが多くなり、手元で気軽にOpenShiftを試す環境としてOpenShift Local (旧称Red Hat CodeReady Containers)を使っています。 半年ぶりくらいにOpenShift Localをアップデートした際に見つけたPV周りの小ネタを書きます。

PVは事前に作成されなくなった

私が最後に試したバージョン1.39では、OpenShift LocalでOpenShiftクラスタを作成するとPVが30個事前に作成されていました。 しかしOpenShift Local バージョン2.11を使ってクラスタを構築した直後では、PVは1つしかありません。 内部レジストリ用にアサインされたものだけです。

デフォルトStorageClassはPVを動的プロビジョニングできる

OpenShiftクラスタアサイン済みPVを深掘りすると、StorageClassは crc-csi-hostpath-provisioner です。

OpenShift LocalのデフォルトStorageClass

また、StorageClassの詳細を見るとプロビジョナーは kubevirt/hostpath-provisioner という見慣れないものになっています。

デフォルトStorageClassのプロビジョナー

このプロビジョナーを使ったStorageClassおよびPVの作成方法は、以前からDynamic Provisioningの実現方法としてWikiに掲載されていたものです。 まだWikiやリリースノートに記載されていませんが、ようやくデフォルトのStorageClassでPVをDynamic Provisioningできるものになったようです。

github.com

github.com

PVをDynamic Provisioningしてワークロードに紐づけてみる

検証対象

実際にデフォルトのStorageClassでPVをDynamic Provisioningできるか、ステートフルなワークロードをデプロイして検証してみます。 Red Hat Enterprise Linux 9.1にインストールしたOpenShift Local バージョン2.11を使用して検証してみます。

$ crc version
CRC version: 2.11.0+823e40d
OpenShift version: 4.11.13
Podman version: 4.2.0

ステートフルなワークロードをデプロイ

ステートフルなワークロードの例として、Red Hat AMQ Streams Operator (2.2.0-3) でデプロイしたKafkaクラスタを使います。 事前にOperatorHubからRed Hat AMQ Streams Operatorをインストールしておきます。 デプロイ先のプロジェクト名は適当に ponz-sample-project を作成して指定しました。

Red Hat AMQ Streams Operatorをインストール

Operatorのカスタムリソース Kafka でKafkaクラスタを作成します。 このカスタムリソースの中で、Zookeeperを1台、Kafka Brokerを3台、それぞれ5GiBの容量を確保するように設定しておきます。 マニフェストspec.{kafka|zookeeper}.storage にPVの要求内容を記述します。

次のカスタムリソースを適用してKafkaクラスタを作成します。

$ cat <<EOF > kafka-dynamic-pv-sample-cluster.yaml 
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: dynamic-pv-sample-cluster
  namespace: ponz-sample-project
spec:
  entityOperator:
    topicOperator: {}
    userOperator: {}
  kafka:
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: true
    storage:
      type: persistent-claim
      size: 5Gi
    version: 3.2.3
    replicas: 3
    config:
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
      default.replication.factor: 3
      min.insync.replicas: 2
      inter.broker.protocol.version: '3.2'
  zookeeper:
    storage:
      type: persistent-claim
      size: 5Gi
    replicas: 1
EOF

$ oc apply -f kafka-dynamic-pv-sample-cluster.yaml
kafka.kafka.strimzi.io/dynamic-pv-sample-cluster created

カスタムリソースを適用してしばらく待つと、StatefulSet経由でPodをデプロイされます。 それぞれのPodにはPVが紐づけられます。

$ oc get kafka/dynamic-pv-sample-cluster
NAME                        DESIRED KAFKA REPLICAS   DESIRED ZK REPLICAS   READY   WARNINGS
dynamic-pv-sample-cluster   3                        1                     True

$ oc get sts
NAME                                  READY   AGE
dynamic-pv-sample-cluster-kafka       3/3     105s
dynamic-pv-sample-cluster-zookeeper   1/1     2m38s

$ oc get pvc
NAME                                         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                   AGE
data-dynamic-pv-sample-cluster-kafka-0       Bound    pvc-780ddd84-df96-44c9-8985-36a44ac5d808   79Gi       RWO            crc-csi-hostpath-provisioner   2m2s
data-dynamic-pv-sample-cluster-kafka-1       Bound    pvc-64c19c56-3ca0-4124-bfbd-72be6584a156   79Gi       RWO            crc-csi-hostpath-provisioner   2m2s
data-dynamic-pv-sample-cluster-kafka-2       Bound    pvc-0a985451-0701-4e4e-a49d-ebc24c6e527f   79Gi       RWO            crc-csi-hostpath-provisioner   2m2s
data-dynamic-pv-sample-cluster-zookeeper-0   Bound    pvc-1f168f25-5368-4399-963f-4bfcfdb2718a   79Gi       RWO            crc-csi-hostpath-provisioner   2m56s

デフォルトのStorageClassでPVCがDynamic Provisioningされていますね。 PVCの容量は5GiBで要求しましたが、適用したマニフェストでは全て同じくホストマシンのディスク容量が指定されてしまうようです。

動作確認

Kafkaクラスタに接続およびGUIから参照するため、Kafdropをデプロイします。 oc new-app コマンドを使います。

アドベントカレンダー前日の記事がJARからコンテナイメージのビルドだったので、ここでは試しにOpenJDKビルダーイメージとKafdropのソースコードからコンテナイメージをビルドしてデプロイしています。(KafdropはDocker Hubにイメージもありますがせっかくなので)

また、KafdropはKafka Bootstrapサーバ接続先を環境変数にセットする必要があります。 Kafkaカスタムリソースで自動作成されるサービス名を指定します。 ここでは oc new-app--env フラグに Kafkaカスタムリソースのname-kafka-bootstrap.プロジェクト名.svc.cluster.local:9092 を渡します。

$ oc new-app --name kafdrop ubi8-openjdk-11:1.12~https://github.com/obsidiandynamics/kafdrop.git  \
    --env KAFKA_BROKERCONNECT="dynamic-pv-sample-cluster-kafka-bootstrap.ponz-sample-project.svc.cluster.local:9092"  \
    --env SERVER_SERVLET_CONTEXTPATH="/"  \
    --env JVM_OPTS="-Xms32M -Xmx64M"

$ oc expose deploy/kafdrop-ui --port=9000
service/kafdrop-ui exposed

$ oc expose svc kafdrop
route.route.openshift.io/kafdrop exposed

$ oc get route/kafdrop
NAME      HOST/PORT                                      PATH   SERVICES   PORT   TERMINATION   WILDCARD
kafdrop   kafdrop-ponz-sample-project.apps-crc.testing          kafdrop    9000                 None

Routeで払い出されたホスト名でブラウザからアクセスすると、PVと紐づいたKafkaに接続できています。

KafdropからDynamic ProvisioningしたPVを使ったKafkaクラスタに接続


PV事前作成の手間要らずで、以前よりも気軽にステートフルなワークロードを使えるようになりましたね。

以上!