netbox-dockerのホスト移植

動機

  • 現在ホストA上でnetboxをdocker-composeで動かしている。
  • これをデータも含めてホストBに移行したい

自分のサーバ上でとりあえず試運用していた。よさそうだったので、監視サーバに移行させたい。

環境

便宜上以下のように表記する。

  • 移行元のサーバ: src server
  • 移行先のサーバ: dst server
  • 作業用のPC: local

src server

  • Ubuntu 16.04
  • docker: 18.09.6

dst server

  • Ubuntu: 16.04
  • docker: 19.03.2

現状確認

src serverでのnetboxの状況を確認する。

netbox-communityのgithubで公開されているdocker-composeをそのまま動かしている。

github.com

docker-compose ps
            Name                           Command               State                Ports             
--------------------------------------------------------------------------------------------------------
netbox-docker_netbox-worker_1   python3 /opt/netbox/netbox ...   Up                                     
netbox-docker_netbox_1          /opt/netbox/docker-entrypo ...   Up                                     
netbox-docker_nginx_1           nginx -c /etc/netbox-nginx ...   Up      80/tcp, 0.0.0.0:32769->8080/tcp
netbox-docker_postgres_1        docker-entrypoint.sh postgres    Up      5432/tcp                       
netbox-docker_redis_1           docker-entrypoint.sh sh -c ...   Up      6379/tcp    

redisはなんのために使っているんだろうか。 docker-compose.yml の中身を見てみると、netboxnetbox-workerdepends_on されている。 セッション管理とかかな?

普通に作られていればコンテナ自体を移植する必要はないはず。 docker pullすれば同じコンテナが入るはずだから、データだけを移植すればいい。 移行すべきデータはpostgres のデータのみになる。

やるべきこと

README.mdに正解があった。

  • To create a database backup run docker-compose exec postgres sh -c 'pg_dump -cU $POSTGRES_USER $POSTGRES_DB' | gzip > db_dump.sql.gz
  • To restore that database backup run gunzip -c db_dump.sql.gz | docker exec -i $(docker-compose ps -q postgres) sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'.

netboxの移行

dst serverの設定

dockerのインストール

dockerとdocker-composeが入っていなければインストールする必要がある。

docs.docker.com

docs.docker.com

netbox-dockerのセットアップ

README.mdに従う。

github.com

$ git clone https://github.com/netbox-community/netbox-docker.git

# docker-compose pull
# docker-compose up -d

データの移行

@src server: データを出力。

# docker-compose exec postgres sh -c 'pg_dump -cU $POSTGRES_USER $POSTGRES_DB' | gzip > db_dump.sql.gz

@local: src serverで出力したデータをコピーして、dst serverに送信。

$ scp host-a:~/netbox-docker/db_dump.sql.gz /tmp
$ scp /tmp/db_dump.sql.gz host-b:~/

@dst server: データを解凍してSQLを実行。

# gunzip -c db_dump.sql.gz | docker exec -i $(docker-compose ps -q postgres) sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'

これで完了。

ただ自分の環境ではこれだけではうまくいかなかったので、以下にエラー&ワークアラウンドを書いた。

エラー&ワークアラウンド

エラー

https://example.com:32768 に行ってみるとデータが追加されていない。おかしい。適当にvlanを手動で追加してみると以下のような画面が。

f:id:ninigishi:20190907122919p:plain

[o] src serverでnetboxのバージョン更新後に移行

@src host

docker-compose down
git clone -b master https://github.com/netbox-community/netbox-docker.git
docker-compose up -d

この後にデータ移行の処理をもう一度やるとdst serverで正常に稼働した。

src serverにnetbox-dockerを入れたのは数カ月前だったので、おそらくその間にnetboxがアップデートされてしまったことが原因。 netboxのバージョンが上がったからデータベースのカラムが変更されてしまった?

あまりこのエラーは起こらなそう。

[x] migrate.pyを実行

うまくいかなかった方法。

エラーメッセージの通りにmigrationを実行。

# docker-compose exec netbox /bin/bash

bash-5.0# python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, circuits, contenttypes, dcim, extras, ipam, secrets, sessions, taggit, tenancy, users, virtualization
Running migrations:
  Applying extras.0019_tag_taggeditem...Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "extras_tag" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 234, in handle
    fake_initial=fake_initial,
  File "/usr/local/lib/python3.7/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.7/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.7/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/usr/local/lib/python3.7/site-packages/django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/usr/local/lib/python3.7/site-packages/django/db/migrations/operations/models.py", line 92, in database_forwards
    schema_editor.create_model(model)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 307, in create_model
    self.execute(sql, params or None)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 137, in execute
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.7/site-packages/cacheops/transaction.py", line 99, in execute
    result = self._no_monkey.execute(self, sql, params)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "extras_tag" already exists

なんかうまくいかない。

[x] --fakeオプション付でmigrate.pyを実行

うまくいかなかった方法。

調べた結果--fakeオプションを付けて実行すると動くらしい。

# bash-5.0# python3 manage.py migrate --fake
Operations to perform:
  Apply all migrations: admin, auth, circuits, contenttypes, dcim, extras, ipam, secrets, sessions, taggit, tenancy, users, virtualization
Running migrations:
  Applying extras.0019_tag_taggeditem... FAKED
  Applying circuits.0015_custom_tag_models... FAKED
  Applying virtualization.0009_custom_tag_models... FAKED
  Applying tenancy.0006_custom_tag_models... FAKED
  Applying secrets.0006_custom_tag_models... FAKED
  Applying ipam.0025_custom_tag_models... FAKED
  Applying dcim.0070_custom_tag_models... FAKED
  Applying extras.0020_tag_data... FAKED
  Applying extras.0021_add_color_comments_changelog_to_tag... FAKED
  Applying dcim.0071_device_components_add_description... FAKED
  Applying dcim.0072_powerfeeds... FAKED
  Applying dcim.0073_interface_form_factor_to_type... FAKED
  Applying extras.0022_custom_links... FAKED
  Applying extras.0023_fix_tag_sequences... FAKED
  Applying extras.0024_scripts... FAKED
  Applying extras.0025_objectchange_time_index... FAKED
  Applying ipam.0026_prefix_ordering_vrf_nulls_first... FAKED
  Applying ipam.0027_ipaddress_add_dns_name... FAKED

上手く行った風だけど動かない…さっきと同じエラー画面が表示される。

github.com

よくわからない。