🙄

NetBox on Kubernetes

39 min read

はじめに

最近、社内メンバのブログで NetBox なる IPAM のプロダクトの記事を拝見しました。IP アドレス管理はどこでも困っていたので、試しついでに記事にした限りです。今回は Kuberentes 上に NetBox を構築します。

インストールは VM または Docker Compose でのインストールが提供されています。しかし、Kubernetes / helm での利用例が少なかったので、ツールを使って Compose のマニフェストファイルを変換しながらデプロイしよう思います。

※公開されている Kubernetes デプロイ方法はこちら。他 Wiki も。

https://github.com/CENGN/netbox-kubernetes
https://github.com/bootc/netbox-chart
https://github.com/netbox-community/netbox/wiki/Community-Contributions

環境情報

Kubernetes:v1.20.6
※PV に Cephを利用しています
NetBox:2.11.9(netbox-docker リポジトリ:1.2.0)
Kompose:1.23.0

Kompose を使ったマニフェストファイル変換

冒頭にも述べたように、NetBox は Docker Compose のマニフェストファイルが提供されています。Kubernetesにデプロイする際に、このマニフェストファイルを読み、または構成を理解しマニフェストファイルを 1 から作成するのも良いのですが、今回はマニフェストファイルの変換ツールとして Kompose を利用します。
Kompose は Docker Compose のマニフェストファイルを Kuberentes のマニフェストファイルに変換するソフトウェアとなります。以前から Compose のマニフェストはあるんだけど、helm Chart がない!なんてプロダクトもあって、うってつけのソフトウェアだと思いました。
※今回は土台を Compose で作ってもらって、細かい点で修正を入れていきます。

https://github.com/kubernetes/kompose

導入はバイナリを置くだけです。ついでに、NetBox の資材もダウンロードします。

# パスが通っているディレクトリ(/usr/local/sbin)にダウンロード
$ curl -L https://github.com/kubernetes/kompose/releases/download/v1.23.0/kompose-linux-amd64 -o /usr/local/sbin/kompose
$ chmod 755 /usr/local/sbin/kompose
$ kompose version
1.23.0 (bc7d9f4f)

# NetBox の資材ダウンロード
$ git clone https://github.com/netbox-community/netbox-docker.git -b 1.2.0 --depth 1

作業ディレクトリに資材をコピーして、早速 Kompose でマニフェストファイルを変換していきます。

# 作業用ディレクトリ作成
$ mkdir netbox

# 必要な資材をコピー
$ cp -r netbox-docker/{startup_scripts,initializers,configuration,reports,scripts,env,docker-compose.yml} netbox

$ cd netbox; ls -l
total 28
drwxr-xr-x 3 root root 4096 Jul 24 20:41 configuration
-rw-r--r-- 1 root root 1538 Jul 24 20:41 docker-compose.yml
drwxr-xr-x 2 root root 4096 Jul 24 20:41 env
drwxr-xr-x 2 root root 4096 Jul 24 20:41 initializers
drwxr-xr-x 2 root root 4096 Jul 24 20:41 reports
drwxr-xr-x 2 root root 4096 Jul 24 20:41 scripts
drwxr-xr-x 3 root root 4096 Jul 24 20:41 startup_scripts

# 変換したファイルが分からなくならないように、出力先ディレクトリ(kompose)を作成
$ mkdir kompose

# kompose 実行
# -f:Compose マニフェストファイル、-o:出力先ディレクトリ
$ kompose convert -f docker-compose.yml -o kompose
WARN Service "netbox" won't be created because 'ports' is not specified
WARN Volume mount on the host "/root/netbox/startup_scripts" isn't supported - ignoring path on the host
・・・
INFO Kubernetes file "kompose/netbox-deployment.yaml" created
・・・
INFO Kubernetes file "kompose/env-redis-cache-env-configmap.yaml" created

# 出力ファイルの一覧
$ ls -l kompose/
total 104
-rw-r--r-- 1 root root 1245 Jul 24 20:47 env-netbox-env-configmap.yaml
-rw-r--r-- 1 root root  242 Jul 24 20:47 env-postgres-env-configmap.yaml
-rw-r--r-- 1 root root  206 Jul 24 20:47 env-redis-cache-env-configmap.yaml
-rw-r--r-- 1 root root  181 Jul 24 20:47 env-redis-env-configmap.yaml
-rw-r--r-- 1 root root  248 Jul 24 20:47 netbox-claim0-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  248 Jul 24 20:47 netbox-claim1-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  248 Jul 24 20:47 netbox-claim2-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  248 Jul 24 20:47 netbox-claim3-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  248 Jul 24 20:47 netbox-claim4-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root 8710 Jul 24 20:47 netbox-deployment.yaml
-rw-r--r-- 1 root root  259 Jul 24 20:47 netbox-media-files-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  263 Jul 24 20:47 netbox-postgres-data-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  257 Jul 24 20:47 netbox-redis-data-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  262 Jul 24 20:47 netbox-worker-claim0-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  262 Jul 24 20:47 netbox-worker-claim1-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  262 Jul 24 20:47 netbox-worker-claim2-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  262 Jul 24 20:47 netbox-worker-claim3-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root  262 Jul 24 20:47 netbox-worker-claim4-persistentvolumeclaim.yaml
-rw-r--r-- 1 root root 8993 Jul 24 20:47 netbox-worker-deployment.yaml
-rw-r--r-- 1 root root 1532 Jul 24 20:47 postgres-deployment.yaml
-rw-r--r-- 1 root root 1051 Jul 24 20:47 redis-cache-deployment.yaml
-rw-r--r-- 1 root root 1264 Jul 24 20:47 redis-deployment.yaml

出力されたファイルは以下のとおりです。

NetBox(Application)
- netbox-deployment.yaml
- env-netbox-env-configmap.yaml
- netbox-claim0-persistentvolumeclaim.yaml
- netbox-claim1-persistentvolumeclaim.yaml
- netbox-claim2-persistentvolumeclaim.yaml
- netbox-claim3-persistentvolumeclaim.yaml
- netbox-claim4-persistentvolumeclaim.yaml
- netbox-media-files-persistentvolumeclaim.yaml

- netbox-worker-deployment.yaml
- netbox-worker-claim0-persistentvolumeclaim.yaml
- netbox-worker-claim1-persistentvolumeclaim.yaml
- netbox-worker-claim2-persistentvolumeclaim.yaml
- netbox-worker-claim3-persistentvolumeclaim.yaml
- netbox-worker-claim4-persistentvolumeclaim.yaml

PostgreSQL(Database)
- postgres-deployment.yaml
- env-postgres-env-configmap.yaml
- netbox-postgres-data-persistentvolumeclaim.yaml

Redis(Task queing)
- redis-deployment.yaml
- redis-cache-deployment.yaml
- env-redis-env-configmap.yaml
- env-redis-cache-env-configmap.yaml
- netbox-redis-data-persistentvolumeclaim.yaml

細かい部分を修正していきます。
先に最終的なファイル構成を展開します。

netbox/
├ # NetBox の資材からコピー(configuration ~ startup_scripts)
├ configuration/
├ env/
├ initializers/
├ reports/
├ scripts/
├ startup_scripts/
├ docker-compose.yml         # 元の Compose マニフェストファイル
├ kompose/                   # 変換後のマニフェストファイル格納ディレクトリ
│ ├ # [ NetBox ]
│ ├ netbox-deployment.yaml
│ ├ netbox-worker-deployment.yaml
│ ├ env-netbox-env-configmap.yaml
│ ├ env-netbox-env-secret.yaml
│ ├ netbox-claim-pvc.yaml
│ ├ netbox-media-files-persistentvolumeclaim.yaml
│ ├ # [ PostgreSQL ]
│ ├ postgres-deployment.yaml
│ ├ env-postgres-env-configmap.yaml
│ ├ netbox-postgres-data-persistentvolumeclaim.yaml
│ ├ # [ Redis ]
│ ├ redis-deployment.yaml
│ ├ redis-cache-deployment.yaml
│ ├ env-redis-env-configmap.yaml
│ ├ env-redis-cache-env-configmap.yaml
│ └ netbox-redis-data-persistentvolumeclaim.yaml
├ pod.yaml                   # Pod(資材配置用一時 Pod)
└ svc.yaml                   # Service

YAML(Redis / RedisCache)

1つ目は Redis からとりかかります。
まずは ConfigMap に割当てられている以下のファイルを修正します。内容が機密情報(パスワード)なので、ConfigMap から Secret に変更し Base64 エンコードした値で書き換えます。
※記載しているパスワード情報はデフォルトのパスワードを Base64 エンコードしています。
 必要に応じて変更したパスワードを base64 に変換して記載してください。

kompose/env-redis-env-configmap.yaml
apiVersion: v1
kind: Secret
metadata:
  name: env-redis-env
data:
  REDIS_PASSWORD: SDczM0tkam5ka3M4MQ==
kompose/env-redis-cache-env-configmap.yaml
apiVersion: v1
kind: Secret
metadata:
  name: env-redis-cache-env
data:
  REDIS_PASSWORD: dDRQaDcyMnFKNVFIZVExcWZ1MzY=

次に PVC です。以下を修正しています。

  • ストレージサイズを 1Gi までスケールアップ
  • StorageClass を明示的に指定
kompose/netbox-redis-data-persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-redis-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-ceph-block

最後に Deployment です。以下を修正しています。

  • env で指定していた ConfigMap を Secret 参照するように修正
  • 各 Pod からアクセス出来るようにポートを定義
  • 以下の不要な定義を削除(以降の YAML でも同じように削除しています)
    • annotations
    • creationTimestamp
    • status
kompose/redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    io.kompose.service: redis
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: redis
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        io.kompose.service: redis
    spec:
      containers:
        - args:
            - sh
            - -c
            - redis-server --appendonly yes --requirepass $REDIS_PASSWORD
          env:
            - name: REDIS_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: REDIS_PASSWORD
                  name: env-redis-env
          image: redis:6-alpine
          name: redis
          ports:
          - containerPort: 6379
          volumeMounts:
            - mountPath: /data
              name: netbox-redis-data
      restartPolicy: Always
      volumes:
        - name: netbox-redis-data
          persistentVolumeClaim:
            claimName: netbox-redis-data
kompose/redis-cache-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    io.kompose.service: redis-cache
  name: redis-cache
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: redis-cache
  template:
    metadata:
      labels:
        io.kompose.service: redis-cache
    spec:
      containers:
        - args:
            - sh
            - -c
            - redis-server --requirepass $REDIS_PASSWORD
          env:
            - name: REDIS_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: REDIS_PASSWORD
                  name: env-redis-cache-env
          image: redis:6-alpine
          name: redis-cache
          ports:
          - containerPort: 6379
      restartPolicy: Always

NetBox 用の namespace を作成して、早速デプロイします。

# namespace 作成
$ kubectl create ns netbox
namespace/netbox created

# 作業対象 namespace を指定
$ kubectl config set-context <Context名> --namespace netbox

# デプロイ
$ kubectl apply -f kompose/env-redis-env-configmap.yaml -f kompose/env-redis-cache-env-configmap.yaml
secret/env-redis-env created
secret/env-redis-cache-env created

$ kubectl apply -f kompose/netbox-redis-data-persistentvolumeclaim.yaml
persistentvolumeclaim/netbox-redis-data created

$ kubectl apply -f kompose/redis-cache-deployment.yaml -f kompose/redis-deployment.yaml
deployment.apps/redis-cache created
deployment.apps/redis created

# 確認
$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
redis-695cc7c5fc-8hjfv         1/1     Running   0          7s
redis-cache-7f44df8798-bm5tr   1/1     Running   0          7s

YAML(PostgreSQL)

2つ目は PostgreSQL です。
こちらもまずは ConfigMap のマニフェストを Secret に変更し、中の値を base64 に更新します。

kompose/env-postgres-env-configmap.yaml
apiVersion: v1
kind: Secret
metadata:
  name: env-postgres-env
data:
  POSTGRES_DB: bmV0Ym94
  POSTGRES_PASSWORD: SjVickhyQVhGTFFTaWYwSw==
  POSTGRES_USER: bmV0Ym94

PVC も Redis 同様に、ストレージサイズを増やし、StorageClass を明示的に指定しました。

kompose/netbox-postgres-data-persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-postgres-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-ceph-block

Deployment も Redis 同様に env を変更し、ポートを定義します。
YAML が長くなってきたので、差分だけ記載します。

kompose/postgres-deployment.yaml
@@ -28,21 +20,23 @@
         - env:
             - name: POSTGRES_DB
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: POSTGRES_DB
                   name: env-postgres-env
             - name: POSTGRES_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: POSTGRES_PASSWORD
                   name: env-postgres-env
             - name: POSTGRES_USER
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: POSTGRES_USER
                   name: env-postgres-env
           image: postgres:12-alpine
           name: postgres
+          ports:
+          - containerPort: 5432
           resources: {}
           volumeMounts:
             - mountPath: /var/lib/postgresql/data

ではこちらもデプロイします。

$ kubectl apply -f kompose/env-postgres-env-configmap.yaml
secret/env-postgres-env created

$ kubectl apply -f kompose/netbox-postgres-data-persistentvolumeclaim.yaml
persistentvolumeclaim/netbox-postgres-data created

$ kubectl apply -f kompose/postgres-deployment.yaml
deployment.apps/postgres created

$ kubeclt get po
NAME                           READY   STATUS             RESTARTS   AGE
postgres-6b9b8d6954-dm45b      0/1     CrashLoopBackOff   7          14m
redis-695cc7c5fc-8hjfv         1/1     Running            0          27m
redis-cache-7f44df8798-bm5tr   1/1     Running            0          27m

あら、エラーとなりますね・・・ログを確認すると。

$ kubectl logs -f postgres-6b9b8d6954-dm45b
The files belonging to this database system will be owned by user "postgres".
initdb: error: directory "/var/lib/postgresql/data" exists but is not empty
It contains a lost+found directory, perhaps due to it being a mount point.
Using a mount point directly as the data directory is not recommended.
Create a subdirectory under the mount point.
This user must also own the server process.
・・・

どうやらデータディレクトリがマウントポイント直下だと推奨されないようです。環境変数でデータディレクトリをマウントポイント配下のサブディレクトリを指定するように変更します。

kompose/postgres-deployment.yaml
         - env:
・・・
+            - name: PGDATA
+              value: /var/lib/postgresql/data/pgdata

再デプロイで正常に起動しました。

$ kubectl get po
NAME                           READY   STATUS    RESTARTS   AGE
postgres-5d949ff9cb-d4tj8      1/1     Running   0          5m12s
redis-695cc7c5fc-8hjfv         1/1     Running   0          42m
redis-cache-7f44df8798-bm5tr   1/1     Running   0          42m

YAML(NetBox)

最後に NetBox 本体の YAML を編集していきます。
まずは ConfigMap ですが、機密情報と設定情報が入り乱れているので、ConfigMap と Secret に分割しようと思います。ファイルをコピーして分割します。

$ cp -p kompose/env-netbox-env-{configmap,secret}.yaml
$ ls -l kompose/env-netbox-env-*
-rw-r--r-- 1 root root 1245 Jul 24 20:47 kompose/env-netbox-env-configmap.yaml
-rw-r--r-- 1 root root 1245 Jul 24 20:47 kompose/env-netbox-env-secret.yaml

ConfigMap の定義ファイルから機密情報である *_PASSWORD*_KEY*_TOKEN を削除します。
また、各コンテナに接続する際のポート情報を追記します。
※詳細はまとめ*で紹介したいと思います。

kompose/env-netbox-env-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-netbox-env
data:
  CORS_ORIGIN_ALLOW_ALL: "True"
  DB_HOST: postgres
  DB_NAME: netbox
  DB_USER: netbox
  EMAIL_FROM: netbox@bar.com
  EMAIL_PORT: "25"
  EMAIL_SERVER: localhost
  EMAIL_SSL_CERTFILE: ""
  EMAIL_SSL_KEYFILE: ""
  EMAIL_TIMEOUT: "5"
  SUPERUSER_API_TOKEN: 0123456789abcdef0123456789abcdef01234561
  EMAIL_USE_SSL: "false"
  EMAIL_USE_TLS: "false"
  EMAIL_USERNAME: netbox
  MAX_PAGE_SIZE: "1000"
  MEDIA_ROOT: /opt/netbox/netbox/media
  METRICS_ENABLED: "false"
  NAPALM_TIMEOUT: "10"
  NAPALM_USERNAME: ""
  POSTGRES_PORT: "5432"
  REDIS_CACHE_DATABASE: "1"
  REDIS_CACHE_HOST: redis-cache
  REDIS_CACHE_PORT: "6379"
  REDIS_CACHE_SSL: "false"
  REDIS_DATABASE: "0"
  REDIS_HOST: redis
  REDIS_PORT: "6379"
  REDIS_SSL: "false"
  RELEASE_CHECK_URL: https://api.github.com/repos/netbox-community/netbox/releases
  SKIP_STARTUP_SCRIPTS: "false"
  SKIP_SUPERUSER: "false"
  SUPERUSER_EMAIL: admin@example.com
  SUPERUSER_NAME: admin
  WEBHOOKS_ENABLED: "true"

また、Secret 用のファイルは Kind などの定義を変更し、データを base64 エンコードして更新します。
※前節で Redis / PostgreSQL の Secret 情報が既に存在していたので、該当箇所は除外し、NetBox の ConfigMap に出てきたものだけ今回の Secret に定義しました。

kompose/env-netbox-env-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: env-netbox-env
data:
  EMAIL_PASSWORD: IA==
  NAPALM_PASSWORD: IA==
  SECRET_KEY: cjhPd0R6bmohIWRjaSNQOWdobVJmZHUxWXN4bTBBaVBlRENRaEtFK05fckNsZldOag==
  SUPERUSER_API_TOKEN: MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nw==
  SUPERUSER_PASSWORD: YWRtaW4=

次に PVC です。いくつかあるのですが、まずは netbox-media-files-persistentvolumeclaim.yaml から。
netboxnetbox-worker の Pod からそれぞれからアクセスされるので、以下の記事で設定した CephFS を StorageClass として指定し、AccessMode が RWX(ReadWriteMany)を指定できるようにします。
また、他と同様にサイズを少し大きくしています。

https://zenn.dev/t_ume/articles/adedeb6e7bd7ce
kompose/netbox-media-files-persistentvolumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: netbox-media-files
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-cephfs

残りの以下の PVC は元々の Compose の設定で、ホストのディレクトリを ReadOnly でマウントする設定になっています。
※同様な YAML ファイルに netbox-worker-claim~がありますが、こちらは下記ファイルと重複するため利用しません。

  • netbox-claim0-persistentvolumeclaim.yaml - コピー対象:startup_scripts/
  • netbox-claim1-persistentvolumeclaim.yaml - コピー対象:initializers/
  • netbox-claim2-persistentvolumeclaim.yaml - コピー対象:config/
  • netbox-claim3-persistentvolumeclaim.yaml - コピー対象:reports/
  • netbox-claim4-persistentvolumeclaim.yaml - コピー対象:scripts/

CopnfigMap でも対応できそうでしたが、今回は PV を作成して、ファイルコピーを行います。まずはマニフェストファイルを編集します。
0~4のファイルを、1つにまとめます。
※まとめるのと合わせて、StorageClass を指定し、AccessModeも変更しています。

kompose/netbox-claim-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: netbox-claim0
  name: netbox-claim0
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi
  storageClassName: rook-cephfs
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: netbox-claim1
  name: netbox-claim1
spec:
  accessModes:
    - ReadWritMany
  resources:
    requests:
      storage: 100Mi
  storageClassName: rook-cephfs
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: netbox-claim2
  name: netbox-claim2
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi
  storageClassName: rook-cephfs
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: netbox-claim3
  name: netbox-claim3
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi
  storageClassName: rook-cephfs
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: netbox-claim4
  name: netbox-claim4
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi
  storageClassName: rook-cephfs

PVC/PV を作成しローカルにあるファイルを配置するため、各PVC をマウントした作業用の Pod を作成します。マニフェストファイルは以下のとおりです。

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
spec:
  containers:
    - name: startup-scripts
      image: busybox:1.28.4-glibc
      command: ["sleep", "3600" ]
      volumeMounts:
        - mountPath: /mnt
          name: netbox-claim0
    - name: initializers
      image: busybox:1.28.4-glibc
      command: ["sleep", "3600" ]
      volumeMounts:
        - mountPath: /mnt
          name: netbox-claim1
    - name: config
      image: busybox:1.28.4-glibc
      command: ["sleep", "3600" ]
      volumeMounts:
        - mountPath: /mnt
          name: netbox-claim2
    - name: reports
      image: busybox:1.28.4-glibc
      command: ["sleep", "3600" ]
      volumeMounts:
        - mountPath: /mnt
          name: netbox-claim3
    - name: scripts
      image: busybox:1.28.4-glibc
      command: ["sleep", "3600" ]
      volumeMounts:
        - mountPath: /mnt
          name: netbox-claim4
  volumes:
    - name: netbox-claim0
      persistentVolumeClaim:
        claimName: netbox-claim0
    - name: netbox-claim1
      persistentVolumeClaim:
        claimName: netbox-claim1
    - name: netbox-claim2
      persistentVolumeClaim:
        claimName: netbox-claim2
    - name: netbox-claim3
      persistentVolumeClaim:
        claimName: netbox-claim3
    - name: netbox-claim4
      persistentVolumeClaim:
        claimName: netbox-claim4

デプロイしてローカルにある資材をコピーしていきます。
※強引に kubectl でコピーしていますが、スクリプト組んだほうが速そう・・・

$ kubectl apply -f kompose/netbox-claim-pvc.yaml
persistentvolumeclaim/netbox-claim0 created
persistentvolumeclaim/netbox-claim1 created
persistentvolumeclaim/netbox-claim2 created
persistentvolumeclaim/netbox-claim3 created
persistentvolumeclaim/netbox-claim4 created

$ kubectl apply -f pod.yaml
pod/busybox created
$ kubectl get pod busybox
NAME      READY   STATUS    RESTARTS   AGE
busybox   5/5     Running   0          27s

$ ls
configuration  docker-compose.yml  env  initializers  kompose  reports  scripts  startup_scripts

# 00. startup_scripts
$ kubectl cp startup_scripts busybox:/mnt -c startup-scripts
$ kubectl exec busybox -c startup-scripts -- sh -c "mv /mnt/startup_scripts/* /mnt"
$ kubectl exec busybox -c startup-scripts -- sh -c "rmdir /mnt/startup_scripts"
$ kubectl exec busybox -c startup-scripts -- sh -c "ls /mnt"
000_users.py
010_groups.py
015_object_permissions.py
・・・

# 01. initializers
$ kubectl cp initializers busybox:/mnt -c initializers
$ kubectl exec busybox -c initializers -- sh -c "mv /mnt/initializers/* /mnt/"
$ kubectl exec busybox -c initializers -- sh -c "rmdir /mnt/initializers"
$ kubectl exec busybox -c initializers -- sh -c "ls /mnt"
aggregates.yml
circuit_types.yml
circuits.yml
・・・

# 02. configuration
$ kubectl cp configuration busybox:/mnt -c config
$ kubectl exec busybox -c config -- sh -c "mv /mnt/configuration/* /mnt/"
$ kubectl exec busybox -c config -- sh -c "rmdir /mnt/configuration"
$ kubectl exec busybox -c config -- sh -c "ls /mnt"
configuration.py
extra.py
ldap
logging.py
lost+found
plugins.py

# 03. reports
$ kubectl cp reports busybox:/mnt -c reports
$ kubectl exec busybox -c reports -- sh -c "mv /mnt/reports/* /mnt/"
$ kubectl exec busybox -c reports -- sh -c "rmdir /mnt/reports"
$ kubectl exec busybox -c reports -- sh -c "ls /mnt"
devices.py.example
lost+found

# 04. scripts
$ kubectl cp scripts busybox:/mnt -c scripts
$ kubectl exec busybox -c scripts -- sh -c "mv /mnt/scripts/* /mnt/"
$ kubectl exec busybox -c scripts -- sh -c "rmdir /mnt/scripts"
$ kubectl exec busybox -c scripts -- sh -c "ls /mnt/"
__init__.py
lost+found

# 作業用の Pod を削除
$ kc delete -f pod.yaml
pod "busybox" deleted

最後に NetBox / NetBox Worker の YAML を修正していきます。
以下が修正箇所です。

  • docker image のバージョンを指定
  • Secret に定義変更した変数の修正(configMapKeyRefsecretKeyRef
  • PostgreSQL / Redis の Secret 読み込み先を修正
  • 各 Pod への接続用ポート変数を追加
  • NetBox のポートの定義を追加
  • worker は PVC の volumes を NetBox に合わせる
kompose/netbox-worker-deployment.yaml
@@ -48,9 +40,9 @@
                   name: env-netbox-env
             - name: DB_PASSWORD
               valueFrom:
-                configMapKeyRef:
-                  key: DB_PASSWORD
-                  name: env-netbox-env
+                secretKeyRef:
+                  key: POSTGRES_PASSWORD
+                  name: env-postgres-env
             - name: DB_USER
               valueFrom:
                 configMapKeyRef:
@@ -63,7 +55,7 @@
                   name: env-netbox-env
             - name: EMAIL_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: EMAIL_PASSWORD
                   name: env-netbox-env
             - name: EMAIL_PORT
@@ -123,7 +115,7 @@
                   name: env-netbox-env
             - name: NAPALM_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: NAPALM_PASSWORD
                   name: env-netbox-env
             - name: NAPALM_TIMEOUT
@@ -136,6 +128,11 @@
                 configMapKeyRef:
                   key: NAPALM_USERNAME
                   name: env-netbox-env
+            - name: POSTGRES_PORT
+              valueFrom:
+                configMapKeyRef:
+                  key: POSTGRES_PORT
+                  name: env-netbox-env
             - name: REDIS_CACHE_DATABASE
               valueFrom:
                 configMapKeyRef:
@@ -148,8 +145,13 @@
                   name: env-netbox-env
             - name: REDIS_CACHE_PASSWORD
               valueFrom:
+                secretKeyRef:
+                  key: REDIS_PASSWORD
+                  name: env-redis-cache-env
+            - name: REDIS_CACHE_PORT
+              valueFrom:
                 configMapKeyRef:
-                  key: REDIS_CACHE_PASSWORD
+                  key: REDIS_CACHE_PORT
                   name: env-netbox-env
             - name: REDIS_CACHE_SSL
               valueFrom:
@@ -168,8 +170,13 @@
                   name: env-netbox-env
             - name: REDIS_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: REDIS_PASSWORD
+                  name: env-redis-env
+            - name: REDIS_PORT
+              valueFrom:
+                configMapKeyRef:
+                  key: REDIS_PORT
                   name: env-netbox-env
             - name: REDIS_SSL
               valueFrom:
@@ -183,7 +190,7 @@
                   name: env-netbox-env
             - name: SECRET_KEY
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SECRET_KEY
                   name: env-netbox-env
             - name: SKIP_STARTUP_SCRIPTS
@@ -198,7 +205,7 @@
                   name: env-netbox-env
             - name: SUPERUSER_API_TOKEN
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SUPERUSER_API_TOKEN
                   name: env-netbox-env
             - name: SUPERUSER_EMAIL
@@ -213,7 +220,7 @@
                   name: env-netbox-env
             - name: SUPERUSER_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SUPERUSER_PASSWORD
                   name: env-netbox-env
             - name: WEBHOOKS_ENABLED
@@ -221,7 +228,7 @@
                 configMapKeyRef:
                   key: WEBHOOKS_ENABLED
                   name: env-netbox-env
-          image: netboxcommunity/netbox:latest
+          image: netboxcommunity/netbox:v2.11.9
           name: netbox-worker
           resources: {}
           securityContext:
@@ -248,23 +255,23 @@
       volumes:
         - name: netbox-worker-claim0
           persistentVolumeClaim:
-            claimName: netbox-worker-claim0
+            claimName: netbox-claim0
             readOnly: true
         - name: netbox-worker-claim1
           persistentVolumeClaim:
-            claimName: netbox-worker-claim1
+            claimName: netbox-claim1
             readOnly: true
         - name: netbox-worker-claim2
           persistentVolumeClaim:
-            claimName: netbox-worker-claim2
+            claimName: netbox-claim2
             readOnly: true
         - name: netbox-worker-claim3
           persistentVolumeClaim:
-            claimName: netbox-worker-claim3
+            claimName: netbox-claim3
             readOnly: true
         - name: netbox-worker-claim4
           persistentVolumeClaim:
-            claimName: netbox-worker-claim4
+            claimName: netbox-claim4
             readOnly: true
         - name: netbox-media-files
           persistentVolumeClaim:
kompose/netbox-deployment.yaml
@@ -43,9 +35,9 @@
                   name: env-netbox-env
             - name: DB_PASSWORD
               valueFrom:
-                configMapKeyRef:
-                  key: DB_PASSWORD
-                  name: env-netbox-env
+                secretKeyRef:
+                  key: POSTGRES_PASSWORD
+                  name: env-postgres-env
             - name: DB_USER
               valueFrom:
                 configMapKeyRef:
@@ -58,7 +50,7 @@
                   name: env-netbox-env
             - name: EMAIL_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: EMAIL_PASSWORD
                   name: env-netbox-env
             - name: EMAIL_PORT
@@ -118,7 +110,7 @@
                   name: env-netbox-env
             - name: NAPALM_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: NAPALM_PASSWORD
                   name: env-netbox-env
             - name: NAPALM_TIMEOUT
@@ -126,6 +118,11 @@
                 configMapKeyRef:
                   key: NAPALM_TIMEOUT
                   name: env-netbox-env
+            - name: POSTGRES_PORT
+              valueFrom:
+                configMapKeyRef:
+                  key: POSTGRES_PORT
+                  name: env-netbox-env
             - name: NAPALM_USERNAME
               valueFrom:
                 configMapKeyRef:
@@ -143,8 +140,13 @@
                   name: env-netbox-env
             - name: REDIS_CACHE_PASSWORD
               valueFrom:
+                secretKeyRef:
+                  key: REDIS_PASSWORD
+                  name: env-redis-cache-env
+            - name: REDIS_CACHE_PORT
+              valueFrom:
                 configMapKeyRef:
-                  key: REDIS_CACHE_PASSWORD
+                  key: REDIS_CACHE_PORT
                   name: env-netbox-env
             - name: REDIS_CACHE_SSL
               valueFrom:
@@ -163,8 +165,13 @@
                   name: env-netbox-env
             - name: REDIS_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: REDIS_PASSWORD
+                  name: env-redis-env
+            - name: REDIS_PORT
+              valueFrom:
+                configMapKeyRef:
+                  key: REDIS_PORT
                   name: env-netbox-env
             - name: REDIS_SSL
               valueFrom:
@@ -178,7 +185,7 @@
                   name: env-netbox-env
             - name: SECRET_KEY
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SECRET_KEY
                   name: env-netbox-env
             - name: SKIP_STARTUP_SCRIPTS
@@ -193,7 +200,7 @@
                   name: env-netbox-env
             - name: SUPERUSER_API_TOKEN
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SUPERUSER_API_TOKEN
                   name: env-netbox-env
             - name: SUPERUSER_EMAIL
@@ -208,7 +215,7 @@
                   name: env-netbox-env
             - name: SUPERUSER_PASSWORD
               valueFrom:
-                configMapKeyRef:
+                secretKeyRef:
                   key: SUPERUSER_PASSWORD
                   name: env-netbox-env
             - name: WEBHOOKS_ENABLED
@@ -216,8 +223,10 @@
                 configMapKeyRef:
                   key: WEBHOOKS_ENABLED
                   name: env-netbox-env
-          image: netboxcommunity/netbox:latest
+          image: netboxcommunity/netbox:v2.11.9
           name: netbox
+          ports:
+          - containerPort: 8080
           resources: {}
           securityContext:
             runAsUser: 101

Kompose から 出力した YAML の修正は、一旦ここまでです。お疲れ様でした!

YAML(Service)

各 Pod 間でサービスに接続できるように Service のマニフェストを追加します。また、NetBox アクセス用に NodePort の Service を合わせて追加します。

svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  selector:
    io.kompose.service: redis
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cache
spec:
  selector:
    io.kompose.service: redis-cache
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
spec:
  selector:
    io.kompose.service: postgres
  ports:
  - protocol: TCP
    port: 5432
    targetPort: 5432
---
apiVersion: v1
kind: Service
metadata:
  name: netbox
spec:
  ports:
  - name: http
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    io.kompose.service: netbox
  type: NodePort

NetBox デプロイ

準備ができたので NetBox をデプロイしていきます。

# ConfigMap / Secret デプロイ
$ kubectl apply -f kompose/env-netbox-env-configmap.yaml -f kompose/env-netbox-env-secret.yaml
configmap/env-netbox-env created
secret/env-netbox-env created

# PVC デプロイ
$ kubectl apply -f kompose/netbox-media-files-persistentvolumeclaim.yaml
persistentvolumeclaim/netbox-media-files created

# Service デプロイ
$ kubectl apply -f svc.yaml
service/redis created
service/redis-cache created
service/postgres created
service/netbox created

# Netbox - Worker デプロイ
$ kubectl apply -f kompose/netbox-worker-deployment.yaml
deployment.apps/netbox-worker created

$ kubectl get pod -l io.kompose.service=netbox-worker
NAME                             READY   STATUS    RESTARTS   AGE
netbox-worker-78cd8886bf-wpkzn   1/1     Running   0          103s

# Netbox デプロイ
$ kubectl apply -f kompose/netbox-deployment.yaml
deployment.apps/netbox created

$ kubectl get pod -l io.kompose.service=netbox
NAME                      READY   STATUS    RESTARTS   AGE
netbox-595c5cd458-h59q5   1/1     Running   0          2m1s

# 念のため起動できたかどうかをログで確認
# started が表示されていれば OK なはず
$ kubectl logs -l io.kompose.service=netbox
⚙️ Applying configuration from /etc/unit/nginx-unit.json
2021/08/03 18:48:18 [info] 22#22 "netbox" application started
🧬 loaded config '/etc/netbox/config/configuration.py'
🧬 loaded config '/etc/netbox/config/extra.py'
🧬 loaded config '/etc/netbox/config/logging.py'
🧬 loaded config '/etc/netbox/config/plugins.py'
✅ Unit configuration loaded successfully
2021/08/03 18:48:20 [notice] 1#1 process 14 exited with code 0

# NebBox アクセス先確認
# NodePort なので Node の IP 表示
$ kubectl get nodes -o jsonpath="{.items[0].status.addresses[0].address}"
192.168.10.61

# NodePort で開放されたポートを確認
$ kubectl get services netbox -n netbox -o jsonpath="{.spec.ports[0].nodePort}"
31585

アクセス確認

デプロイ出来たのでアクセス確認してみます。
上記で確認した情報( http://192.168.10.61:31585 ) でアクセスします。

右上ログインボタンをクリックし、Secret で定義した SUPERUSER_NAMESUPERUSER_PASSWORD でログインできます。
※デフォルトの設定では admin/admin です

まとめ

気がつけば随分と長い記事になってしまいました・・・。Kompose を使った マニフェストの変換から、Netbox の起動を無事に行うことが出来ました。幾つか詰まる箇所はありましたが、マニフェストファイルもある程度の修正で起動することが出来たかと思います。

次回はデプロイした NetBox を実際に触り倒してみたいと思います。

つまづいたポイント

その1(Secret で改行)

今回パスワードを Secret に入れ直したのですが、NetBox 起動後にパスワードが悪いとエラーログがでました。。。中に入って確認したところ環境変数で不要な改行が・・・調べてみると、base64 エンコードする際に入ってしまったらしいです。

# 改行が含まれてしまう
$ echo 'admin' | base64
YWRtaW4K

# -n:末尾の改行を除外
$ echo -n 'admin' | base64
YWRtaW4=

その2(NetBox コンテナ内の環境変数(Port))

デフォルトの NetBox の定義ファイルでは、Redis や PostgreSQL の Port の定義はなかったのでデフォルトで通ると思っていたところ、起動に失敗しました・・・こちらもコンテナ内で環境変数を確認したところ、~_PORT に正しいポート番号がセットされていませんでした。
tcp://<IPADDRESS>:<PORT>/ でセットされていた。

このため、今回は明示的に環境変数にセットすることで起動できるようにしました。

その3(RWX/RWO)

この辺り私の勉強不足で Pod だと思っていたのですが、関連するのは Node だったんですね・・・。スクラップか、別の記事で検証できればと思います。

https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/#アクセスモード

参考

社内の多くの方のブログで勉強させていただきました、ありがとうございます!

https://zaki-hmkc.hatenablog.com/search?q=netbox
https://usage-automate.hatenablog.com/entry/2021/04/26/215956
https://tekunabe.hatenablog.jp/search?q=netbox
https://qiita.com/mztk/items/cdf25c50ab0d783d09cb
https://mitomito.hatenablog.jp/
https://qiita.com/ze0/items/9b1f48f936368d80c0e8

NetBox 公式の中で Kuberentes 導入に関連し参考にしたページは以下のとおりです。

https://github.com/netbox-community/netbox-docker/wiki/Deployment
https://github.com/netbox-community/netbox-docker/wiki/configuration#configure-for-production

Discussion

ログインするとコメントできます