Operator作成について 連載第4回目 NginxをインストールのOperatorの作成について

はじめに

 前回でOperatorの開発環境を構築したため、Kubernetes Operatorを作成するためのサンプルとして、nginxが起動するOperatorを作成し動作テストを行います。

KubernetesへのNginxデプロイ

 Kubernetes上で、Nginxをデプロイする場合は、以下の図1のように、DeploymentやServiceリソースが書かれたYAMLファイルをKubernetesに登録することで、Kubernetesのコンポーネントが解釈して、nginxのPodを立ち上げたり、そのPodへアクセスするためのサービスを割り振ります。

図1 KubernetesでNginxをデプロイメント

 上記図1を実現するためのリソース設定するYAMLファイルを作成する場合は以下の通りになります。

  • Deploymentリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: 'nginx-sample'
spec:
  selector:
    matchLabels:
      app: nginx-app
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
        - name: nginx-sample
          image: quay.io/k_nakajima/nginx-sample:latest #OpenShiftで動くnginxコンテナ
          ports:
            - containerPort: 8080
  • Serviceリソース
apiVersion: v1
kind: Service
metadata:
  name: 'nginx-service'
spec:
  selector:
    app: 'nginx-app'
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

作成Operatorについて

上記動作をOperatorで簡易化させたときのKubernetesの動作図を図2に示します。

図2 Operatorを使用したNginxのデプロイ

 上記図2は、図1に記載したDeploymentやServiceリソースをテンプレート化して、一つのリソースを設定することで、nginxを立ち上げる仕組みを表しています。

プロジェクト作成

 本章以降では、実際にNginxのインストールを自動するOperator作成について説明いたします。本記事では、Operator-SDKを使用して、AnsibleベースのOperatorを作成します。

 Operator-SDKを使用してプロジェクトやAPIを初期する際に必要な変数の情報を以下表1に示します。

表1 Operatorのコントローラ開発プロジェクトについて

名前備考
使用言語Ansible
プロジェクト名nginx-operatorプロジェクトの管理フォルダ名
ドメイン名sios.nginx.testing
カスタムリソースStartコントローラ動作開始のトリガも兼任
Startのグループ名install
StartのAPI Versionv1

プロジェクトの初期化

 Operator-SDKのコマンドを使用して、Operator作成のプロジェクトを作成する。以下のコマンドを実行して、プロジェクトを初期化します。

mkdir nginx-operator
cd nginx-operator
operator-sdk init --plugins=ansible --domain=sios.nginx.testing

Makefile修正

 OpertorSDKのプロジェクトを初期化することで作成したMakefileはデフォルトのままだとpodmanに対応していなかったり、URLのリンクが異なっていたりするので以下の通りに修正します。

 OperatorSDKのプロジェクト初期化で作成されたMakefileで、Ansible-operatorプログラムのダウンロードリンクが正しくないので以下の通りに修正します。

curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\
mv ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\

上記コードを以下のように修正します。

# curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ;\
# mv ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator_linux_amd64; \
mv ansible-operator_linux_amd64 ./bin/ansible-operator ;\

 前回の環境構築でコンテナのビルドや制御はDockerではなく、Podmanを導入したため、以下のようにdockerコマンドをpodmanコマンドに変更します。

docker-build:
docker build . -t ${IMG}

上記コードを以下の通りに変更します。

docker-build:
podman build . -t ${IMG}
docker-push:
docker push ${IMG}

上記コードを以下の通りに変更します。

docker-push:
podman push ${IMG}
.PHONY: bundle-build
bundle-build:
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .

上記コードを以下の通りに変更します。

.PHONY: bundle-build
bundle-build:
podman build -f bundle.Dockerfile -t $(BUNDLE_IMG) .

コンテナをビルドする際の命名指定が少し、使いずらいので以下の通りに修正します。

# Current Operator version
VERSION ?= 0.0.1
# Default bundle image tag
BUNDLE_IMG ?= controller-bundle:$(VERSION)
# Options for 'bundle-build'
ifneq ($(origin CHANNELS), undefined)
BUNDLE_CHANNELS := --channels=$(CHANNELS)
endif
ifneq ($(origin DEFAULT_CHANNEL), undefined)
BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
# Image URL to use all building/pushing image targets
IMG ?= controller:latest

上記コードを以下の通りに変更します。

IMG_NAME ?= controller
# Current Operator version
VERSION ?= 0.0.1
# Default bundle image tag
BUNDLE_IMG ?= $(IMG_NAME)-olm:$(VERSION)
# Options for 'bundle-build'
ifneq ($(origin CHANNELS), undefined)
BUNDLE_CHANNELS := --channels=$(CHANNELS)
endif
ifneq ($(origin DEFAULT_CHANNEL), undefined)
BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
 
# Image URL to use all building/pushing image targets
IMG ?= $(IMG_NAME):$(VERSION)

APIの作成

 本章はコントローラのAPIやカスタムリソースをOperator-SDKによりベースフレームワークを作成してから、カスタマイズする方法を記載します。

ベースフレームワーク作成

 以下のコマンドを使用して、カスタムリソースやコントローラのフレームワークを生成します。

operator-sdk create api --group install --version v1 --kind Start --generate-role

カスタムリソース定義作成

 本Operator内が作成するカスタムリソースの定義ファイルは「config/crd/bases」のフォルダ内に生成される。カスタムリソースの登録条件などに制限しないため本記事は編集をせずにそのままにします。

カスタムコントローラ作成

 図2の状態、カスタムリソースを参照して、Deploymetn、Serviceリソース自動生成するコントローラを作成します。それを実現するためのテンプレートとして以下の場所とファイル名で作成します。

  • roles/start/templates/deployment-nginx.yaml
  • roles/start/templates/service-nginx.yaml

  コントローラ動作のプログラムとして以下のファイルを編集します。

  • roles/start/defaults/main.yml
  • roles/start/tasks/main.yml

各ファイルの内容は以下の通りになります。

  • roles/start/templates/deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: '{{ name }}-sample'
  namespace: '{{ ansible_operator_meta.namespace }}'
spec:
  selector:
    matchLabels:
      app: {{ name }}-app
  replicas: 1
  template:
    metadata:
      labels:
        app: {{ name }}-app
    spec:
      containers:
        - name: {{ name }}-sample
          image: quay.io/k_nakajima/nginx-sample:latest
          ports:
            - containerPort: 8080
  • roles/start/templates/service-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: '{{ name }}-service'
  namespace: '{{ ansible_operator_meta.namespace }}'
spec:
  selector:
    app: '{{ name }}-app'
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  • roles/start/defaults/main.yml
---
# defaults file for Start
name: nginx
  • roles/start/tasks/main.yml
---
# tasks file for Start
- name: Deploy Deployment
  k8s:
    state: "{{ state | default(omit) }}"
    definition: "{{ lookup('template', 'deployment-nginx.yaml') }}"
- name: Deploy Service
  k8s:
    state: "{{ state | default(omit) }}"
    definition: "{{ lookup('template', 'service-nginx.yaml') }}"

動作確認

 本記事では、作成したコントローラをコンテナ化せずに動作確認する方法について説明します。

テスト環境

図3 Operator開発テスト環境

 本記事では、上記図3の環境を前回の環境構築で用意しました。コントローラの動作てすとは、開発PC側で動作させてその動作結果をOpenShift上に適用されます。

 なお、コントローラをコンテナ化して、OpenShit上で動作確認する方法は本記事では触れません。

OpenShiftログイン

 Kubernetesではなく、OpenShiftを使用してOperatorの動作テストを行う場合は、管理者ユーザでログインしておきます。

カスタムリソース定義導入

以下のコマンドを実行してカスタムリソース定義をOpenShiftにデプロイします。

make install

カスタムコントローラ起動

以下のコマンドを実行して、カスタムコントローラを立ち上げます。

make run

カスタムコントローラ立ち上げ後、以下のコマンドを実行し、カスタムリソースを適応します。

oc apply -f config/samples/install_v1_start.yaml

カスタムリソース導入後、カスタムコントローラが動作して、DeploymetとServiceリソースが作成します。この動作結果は、以下のコマンドで確認できます。

$ oc get deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-sample   1/1     1            1           11s
 
$ oc get service
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
nginx-service   ClusterIP   10.217.4.45   <none>        8080/TCP   32s

 以上、カスタムリソースを適用することで、DeploymentとServiceリソースを作成するカスタムコントローラを作成することを確認しました。

 もし、起動させたカスタムコントローラを停止する場合はCtrl+Cを入力してください。また、Kubernetesに適用したカスタムリソース定義を削除する場合は、以下のコマンドを実行します。

make uninstall

まとめ

 以上で、NginxをインストールするOperatorを作成することができました。本記事では、コントローラをコンテナ化する方法やOLMを使用したOperator管理について触れませんでしたが、次回はOLMについて触れて、次々回でコントローラをコンテナ化する方法について説明します。