仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

JUJU + MAAS を使用したOpenstack構築 + 監視設定

JUJU + MAASによるOpenstackの構築と、 Gnocchi Grafanaを使用したリソース監視の作成に挑戦しました。

今回の筆者は コムシス情報システム株式会社 山本 聡(やまもと さとる)です。 以前のエントリーでKubernetesの構築について書かせていただきました。 http://tech.virtualtech.jp/entry/2018/03/29/104216

実行環境

構成はk8s構築で使用した物理サーバを流用します。 また、Openstack外部接続用のネットワークを追加しました。

f:id:virtualtech:20180424130921p:plain

MAASのインストール

MAAS、Ubuntuのインストールを実施します。

以下の設定でUbuntu Serverをインストール

  • インストールモード:Install Ubuntu Server(通常のインストール)

  • Language:日本語

  • Timezone:日本

  • Keyboard:Japanese

  • ソフトウェアの選択:OpenSSH Server

ネットワーク設定からMAAS+JUJUのインストール

JUJUのインストールまで以前のエントリーと同様です。 http://tech.virtualtech.jp/entry/2018/03/29/104216

MAASで認識された各サーバにタグを付与

Openstackのデプロイ用にMAAS上の各ノードにタグを付与します。

  • node01

 コントローラーノードとして設定

  • node02

 コンピュート及びcephノードとして設定

  • node03

 コンピュート及びcephノードとして設定

Openstackデプロイ

Openstackデプロイ用yamlファイルの作成

Openstack自動構築用のyamlファイルを用意します。 "tags="で記述される箇所がMAASのタグと一致するよう注意してください。

$ vim openstack-telemetry.yaml
machines:
  '0':
    series: xenial
    constraints: "arch=amd64 tags=node01"
  '1':
    series: xenial
    constraints: "arch=amd64 tags=node02"
  '2':
    series: xenial
    constraints: "arch=amd64 tags=node03"
relations:
- - nova-compute:amqp
  - rabbitmq-server:amqp
- - neutron-gateway:amqp
  - rabbitmq-server:amqp
- - keystone:shared-db
  - mysql:shared-db
- - nova-cloud-controller:identity-service
  - keystone:identity-service
- - glance:identity-service
  - keystone:identity-service
- - neutron-api:identity-service
  - keystone:identity-service
- - neutron-openvswitch:neutron-plugin-api
  - neutron-api:neutron-plugin-api
- - neutron-api:shared-db
  - mysql:shared-db
- - neutron-api:amqp
  - rabbitmq-server:amqp
- - neutron-gateway:neutron-plugin-api
  - neutron-api:neutron-plugin-api
- - glance:shared-db
  - mysql:shared-db
- - glance:amqp
  - rabbitmq-server:amqp
- - nova-cloud-controller:image-service
  - glance:image-service
- - nova-compute:image-service
  - glance:image-service
- - nova-cloud-controller:cloud-compute
  - nova-compute:cloud-compute
- - nova-cloud-controller:amqp
  - rabbitmq-server:amqp
- - nova-cloud-controller:quantum-network-service
  - neutron-gateway:quantum-network-service
- - nova-compute:neutron-plugin
  - neutron-openvswitch:neutron-plugin
- - neutron-openvswitch:amqp
  - rabbitmq-server:amqp
- - openstack-dashboard:identity-service
  - keystone:identity-service
- - nova-cloud-controller:shared-db
  - mysql:shared-db
- - nova-cloud-controller:neutron-api
  - neutron-api:neutron-api
- - cinder:image-service
  - glance:image-service
- - cinder:amqp
  - rabbitmq-server:amqp
- - cinder:identity-service
  - keystone:identity-service
- - cinder:cinder-volume-service
  - nova-cloud-controller:cinder-volume-service
- - cinder-ceph:storage-backend
  - cinder:storage-backend
- - ceph-mon:client
  - nova-compute:ceph
- - nova-compute:ceph-access
  - cinder-ceph:ceph-access
- - cinder:shared-db
  - mysql:shared-db
- - ceph-mon:client
  - cinder-ceph:ceph
- - ceph-mon:client
  - glance:ceph
- - ceph-osd:mon
  - ceph-mon:osd
- - ntp:juju-info
  - nova-compute:juju-info
- - ntp:juju-info
  - neutron-gateway:juju-info
- - ceph-radosgw:mon
  - ceph-mon:radosgw
- - ceph-radosgw:identity-service
  - keystone:identity-service
- - ceilometer:amqp
  - rabbitmq-server:amqp
- - ceilometer-agent:ceilometer-service
  - ceilometer:ceilometer-service
- - ceilometer:identity-notifications
  - keystone:identity-notifications
- - ceilometer-agent:nova-ceilometer
  - nova-compute:nova-ceilometer
- - aodh:shared-db
  - mysql:shared-db
- - aodh:identity-service
  - keystone:identity-service
- - aodh:amqp
  - rabbitmq-server:amqp
- - gnocchi:storage-ceph
  - ceph-mon:client
- - gnocchi:shared-db
  - mysql:shared-db
- - gnocchi:amqp
  - rabbitmq-server:amqp
- - gnocchi:coordinator-memcached
  - memcached:cache
- - gnocchi:metric-service
  - ceilometer:metric-service
- - gnocchi:identity-service
  - keystone:identity-service
- - ceilometer:identity-credentials
  - keystone:identity-credentials

series: xenial
services:
  aodh:
    annotations:
      gui-x: '1500'
      gui-y: '0'
    charm: cs:aodh-12
    num_units: 1
    options:
      openstack-origin: cloud:xenial-queens
    to:
    - lxd:0
  ceilometer:
    annotations:
      gui-x: '1250'
      gui-y: '0'
    charm: cs:ceilometer-252
    num_units: 1
    options:
      openstack-origin: cloud:xenial-queens
    to:
    - lxd:2
  ceilometer-agent:
    annotations:
      gui-x: '1250'
      gui-y: '500'
    charm: cs:ceilometer-agent-243
    num_units: 0
  ceph-mon:
    annotations:
      gui-x: '750'
      gui-y: '500'
    charm: cs:ceph-mon-23
    num_units: 2
    options:
      expected-osd-count: 2
      monitor-count: 2
      source: cloud:xenial-queens
    to:
    - lxd:1
    - lxd:2
  ceph-osd:
    annotations:
      gui-x: '1000'
      gui-y: '500'
    charm: cs:ceph-osd-257
    num_units: 2
    options:
      osd-devices: /dev/sdb
      osd-reformat: 'yes'
      source: cloud:xenial-queens
    to:
    - '1'
    - '2'
  ceph-radosgw:
    annotations:
      gui-x: '1000'
      gui-y: '250'
    charm: cs:ceph-radosgw-256
    num_units: 1
    options:
      source: cloud:xenial-queens
    to:
    - lxd:1
  cinder:
    annotations:
      gui-x: '750'
      gui-y: '0'
    charm: cs:cinder-268
    num_units: 1
    options:
      block-device: None
      glance-api-version: 2
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - lxd:2
  cinder-ceph:
    annotations:
      gui-x: '750'
      gui-y: '250'
    charm: cs:cinder-ceph-231
    num_units: 0
  glance:
    annotations:
      gui-x: '250'
      gui-y: '0'
    charm: cs:glance-263
    num_units: 1
    options:
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - lxd:2
  gnocchi:
    annotations:
      gui-x: '1500'
      gui-y: '250'
    charm: cs:gnocchi-7
    num_units: 1
    options:
      openstack-origin: cloud:xenial-queens
    to:
    - lxd:0
  keystone:
    annotations:
      gui-x: '500'
      gui-y: '0'
    charm: cs:keystone-275
    num_units: 1
    options:
      admin-password: openstack
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - lxd:1
  memcached:
    annotations:
      gui-x: '1500'
      gui-y: '500'
    charm: cs:memcached-18
    num_units: 1
    to:
    - lxd:2
  mysql:
    annotations:
      gui-x: '0'
      gui-y: '250'
    charm: cs:percona-cluster-259
    num_units: 1
    options:
      innodb-buffer-pool-size: 256M
      max-connections: 1000
    to:
    - lxd:2
  neutron-api:
    annotations:
      gui-x: '500'
      gui-y: '500'
    charm: cs:neutron-api-258
    num_units: 1
    options:
      flat-network-providers: physnet1
      neutron-security-groups: true
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - lxd:2
  neutron-gateway:
    annotations:
      gui-x: '0'
      gui-y: '0'
    charm: cs:neutron-gateway-247
    num_units: 1
    options:
      bridge-mappings: physnet1:br-ex
      data-port: br-ex:eno2
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - '0'
  neutron-openvswitch:
    annotations:
      gui-x: '250'
      gui-y: '500'
    charm: cs:neutron-openvswitch-249
    num_units: 0
  nova-cloud-controller:
    annotations:
      gui-x: '0'
      gui-y: '500'
    charm: cs:nova-cloud-controller-306
    num_units: 1
    options:
      network-manager: Neutron
      openstack-origin: cloud:xenial-queens
      worker-multiplier: 0.25
    to:
    - lxd:0
  nova-compute:
    annotations:
      gui-x: '250'
      gui-y: '250'
    charm: cs:nova-compute-282
    num_units: 2
    options:
      config-flags: default_ephemeral_format=ext4
      enable-live-migration: true
      enable-resize: true
      migration-auth-type: ssh
      openstack-origin: cloud:xenial-queens
    to:
    - '1'
    - '2'
  ntp:
    annotations:
      gui-x: '1000'
      gui-y: '0'
    charm: cs:ntp-24
    num_units: 0
  openstack-dashboard:
    annotations:
      gui-x: '500'
      gui-y: '-250'
    charm: cs:openstack-dashboard-257
    num_units: 1
    options:
      openstack-origin: cloud:xenial-queens
    to:
    - lxd:0
  rabbitmq-server:
    annotations:
      gui-x: '500'
      gui-y: '250'
    charm: cs:rabbitmq-server-72
    num_units: 1
    to:
    - lxd:0
  grafana:
    charm: "cs:xenial/grafana-9"
    num_units: 1
    options:
      install_method: apt
      admin_password: password5656
    annotations:
      gui-x: '132.75'
      gui-y: '1066'
    to:
      - lxd:1

設定値のポイント解説

  • osd-devices: /dev/sdb

ceph-osdが設定されるサーバはディスクが2つ設定されている必要があります。

  • bridge-mappings: physnet1:br-ex
  • data-port: br-ex:eno2

サーバが認識するネットワークポートと一致させる必要があります。

  • config-flags: default_ephemeral_format=ext4

今回はext4で構成しますが、異なるファイルシステムも使用することが出来ます。

juju deploy を実行

$ juju deploy openstack-telemetry.yaml

openstackclientをインストール

Openstackを操作するためのクライアントをインストールします。

$ sudo apt install python-openstackclient

novarc_autoファイルの作成

Openstackクライアントの動作に必要なrcファイルを作成します

$ vim novarc_auto
_OS_PARAMS=$(env | awk 'BEGIN {FS="="} /^OS_/ {print $1;}' | paste -sd ' ')
for param in $_OS_PARAMS; do
    unset $param
done
unset _OS_PARAMS

keystone_unit=$(juju status keystone|grep -i workload -A1|tail -n1|awk '{print $1}'|tr -d '*')
echo Keystone unit: ${keystone_unit}
if ! curl -qs `juju run --unit ${keystone_unit} "unit-get private-address"`:5000/v3 | grep 404 ;
then
echo Using keystone v3 api
export OS_AUTH_URL=${OS_AUTH_PROTOCOL:-http}://`juju run --unit ${keystone_unit} "unit-get private-address"`:5000/v3
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_DOMAIN_NAME=admin_domain
export OS_USER_DOMAIN_NAME=admin_domain
export OS_PROJECT_DOMAIN_NAME=admin_domain
export OS_PROJECT_NAME=admin
export OS_REGION_NAME=RegionOne
export OS_IDENTITY_API_VERSION=3
# Swift needs this:
export OS_AUTH_VERSION=3
else
echo Using keystone v2 api
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_TENANT_NAME=admin
export OS_REGION_NAME=RegionOne
export OS_AUTH_URL=${OS_AUTH_PROTOCOL:-http}://`juju run --unit ${keystone_unit} "unit-get private-address"`:5000/v2.0

rcファイルの読み込み

$ source novarc_auto

監視確認

Openstack状態の確認

デプロイがすべて完了したことをjuju statusコマンドで確認後、 実際にOpenstackが操作できるかをコマンドで打ってみましょう。

$ openstack service list

+----------------------------------+-----------+--------------+
| ID                               | Name      | Type         |
+----------------------------------+-----------+--------------+
| 0a6aac12ae71496494a3b0748e17021b | aodh      | alarming     |
| 2447939369d74795a0ee65bda1bfe3a1 | swift     | object-store |
| 4a1d931905fd43c3bf3403eb25a96bd4 | placement | placement    |
| 4a40e8739f9046d7978422e5331c8383 | gnocchi   | metric       |
| 5586181aad80426392ee40c41ab9b19a | keystone  | identity     |
| 56608d839340422a8b02af265de70ce9 | neutron   | network      |
| 5e1abf112ca44857a347ba0bd471720e | nova      | compute      |
| 671b147f8d06417fa1b9ff14475d0f40 | glance    | image        |
| 9820e33afcf3467da93a7138632ea917 | cinderv3  | volumev3     |
| bfb458d163314bdeaefd1e867de2ead9 | cinderv2  | volumev2     |
+----------------------------------+-----------+--------------+

上記のような応答があれば成功です。

Ceilometerを有効化

今回の構成のようにCeilometerとGnocchiを連携する場合、 以下のコマンドで有効化する必要があります。

$ juju run-action ceilometer/0 ceilometer-upgrade

Dashboardにアクセス

Dashboardにアクセスします。 juju statusコマンドでopenstack-dashboardのIPアドレスを確認し、 http://xx.xx.xx.xx/horizon のURLでブラウザからアクセスしてください。 yamlファイルに認証の変更を加えていなければ、以下の情報でログインできます。

  • ドメイン:admin_domain
  • ユーザ名:admin
  • パスワード:openstack

インスタンスの作成

監視データの蓄積をするため、監視対象となるインスタンスの作成を行います。 jujuで構築したOpenstackは初期状態においてインスタンス作成に必要な下記項目が設定されていないので、 Dashboardから設定を行ってください。

  • イメージの登録
  • ルーターの作成
  • 内部ネットワークの作成
  • 内部ネットワークサブネットの作成
  • フレーバーの作成

CirrOS等の軽量イメージを使用してインスタンスを稼働しましょう。

メトリックデータの取得

実際に監視データが取得できているかを確認します。 まずはリソースの一覧から表示してみましょう。

$ openstack metric resource list

+--------------------------------------+----------------------------+----------------------------------+----------------------------------+-----------------------------------------------------------------------+----------------------------------+----------+----------------------------------+--------------+-------------------------------------------------------------------+
| id                                   | type                       | project_id                       | user_id                          | original_resource_id                                                  | started_at                       | ended_at | revision_start                   | revision_end | creator                                                           |
+--------------------------------------+----------------------------+----------------------------------+----------------------------------+-----------------------------------------------------------------------+----------------------------------+----------+----------------------------------+--------------+-------------------------------------------------------------------+
| 579ef430-4278-51ca-ad28-4edd6897fee6 | instance_network_interface | d948eedc6f1047bfaf9539e6526dd919 | 8981ef1a6dcb4683b97b82925fd87a9f | instance-00000001-bd7f158f-369c-41dc-81b1-84487a583c6e-tap91c4a8f8-9d | 2018-04-24T01:12:48.853092+00:00 | None     | 2018-04-24T01:12:48.853151+00:00 | None         | 1cf01d45402749e286c098b89caf5eaf:5f5d5bfecb944273a00697e59eafc436 |
| b39ba0c5-860f-598a-b0f4-82ab5afb5c50 | instance_disk              | d948eedc6f1047bfaf9539e6526dd919 | 8981ef1a6dcb4683b97b82925fd87a9f | bd7f158f-369c-41dc-81b1-84487a583c6e-vdb                              | 2018-04-24T01:12:48.941122+00:00 | None     | 2018-04-24T01:12:48.941142+00:00 | None         | 1cf01d45402749e286c098b89caf5eaf:5f5d5bfecb944273a00697e59eafc436 |
| 3f830f79-7cf9-5060-affd-5e4d43196ffc | instance_disk              | d948eedc6f1047bfaf9539e6526dd919 | 8981ef1a6dcb4683b97b82925fd87a9f | bd7f158f-369c-41dc-81b1-84487a583c6e-vda                              | 2018-04-24T01:12:49.119669+00:00 | None     | 2018-04-24T01:12:49.119688+00:00 | None         | 1cf01d45402749e286c098b89caf5eaf:5f5d5bfecb944273a00697e59eafc436 |
| bd7f158f-369c-41dc-81b1-84487a583c6e | instance                   | d948eedc6f1047bfaf9539e6526dd919 | 8981ef1a6dcb4683b97b82925fd87a9f | bd7f158f-369c-41dc-81b1-84487a583c6e                                  | 2018-04-24T01:17:48.346622+00:00 | None     | 2018-04-24T01:17:48.346641+00:00 | None         | 1cf01d45402749e286c098b89caf5eaf:5f5d5bfecb944273a00697e59eafc436 |
+--------------------------------------+----------------------------+----------------------------------+----------------------------------+-----------------------------------------------------------------------+----------------------------------+----------+----------------------------------+--------------+-------------------------------------------------------------------+

次にリソースの詳細です、instanceの詳細を表示してみます。

$ openstack metric resource show bd7f158f-369c-41dc-81b1-84487a583c6e

+-----------------------+---------------------------------------------------------------------+
| Field                 | Value                                                               |
+-----------------------+---------------------------------------------------------------------+
| created_by_project_id | 5f5d5bfecb944273a00697e59eafc436                                    |
| created_by_user_id    | 1cf01d45402749e286c098b89caf5eaf                                    |
| creator               | 1cf01d45402749e286c098b89caf5eaf:5f5d5bfecb944273a00697e59eafc436   |
| ended_at              | None                                                                |
| id                    | bd7f158f-369c-41dc-81b1-84487a583c6e                                |
| metrics               | compute.instance.booting.time: 41aa5d18-772c-49ef-b1f6-26ce117d9290 |
|                       | cpu.delta: f76b4f69-8a30-4565-95af-bbf5f080cb85                     |
|                       | cpu: f9e7437c-6346-49d1-bd93-e82320afad90                           |
|                       | cpu_l3_cache: fbbb5723-f24a-4376-8253-c9b69768022c                  |
|                       | cpu_util: 5c22865d-6727-4c6c-ba3d-37a6d8ee6f4c                      |
|                       | disk.allocation: cb44a188-0d14-443e-aa4b-f85cc502d021               |
|                       | disk.capacity: 8fae7b4d-43f7-4357-8250-e7644e93cd3c                 |
|                       | disk.ephemeral.size: 07eb3f61-6faa-481d-aa4a-6d2e66591b05           |
|                       | disk.iops: 62c81e4c-fb7d-4d96-8657-9e9884dc3aef                     |
|                       | disk.latency: 17f8f246-36c4-4096-8901-c32d5a0ecf42                  |
|                       | disk.read.bytes.rate: 7a7776a4-abe9-4c81-8981-d2c560f52f12          |
|                       | disk.read.bytes: bbe8c0a0-a7bc-4c67-9c62-b500f20fa7d2               |
|                       | disk.read.requests.rate: 4508526a-af1c-4289-b340-0255f012c042       |
|                       | disk.read.requests: 36e36446-fc08-4e20-8d1e-ffaa5c8543c5            |
|                       | disk.root.size: 504a2693-5083-4c2b-9653-1394ad3ed415                |
|                       | disk.usage: 8afdfafe-e499-4c8a-b6e8-c9b60fb61504                    |
|                       | disk.write.bytes.rate: 422f0e51-1fca-4762-b418-c6de634601f7         |
|                       | disk.write.bytes: d21bd9f7-c441-4f95-ad0f-1e29fc799231              |
|                       | disk.write.requests.rate: 114edd3e-ce8e-4fd7-b96e-5fe2808de96e      |
|                       | disk.write.requests: 6e15ee6b-965d-46e7-82a7-bd869464c956           |
|                       | memory.bandwidth.local: a05a8117-2364-47a1-8eb8-4335227b89f2        |
|                       | memory.bandwidth.total: 6ea4ed00-bcca-49bc-96a7-a089577f08aa        |
|                       | memory.resident: 72564fd4-e3df-46f2-b2a5-0da106e749ce               |
|                       | memory.swap.in: 8c150408-0952-4a56-8c49-7bf196d3382d                |
|                       | memory.swap.out: ba87a10a-7e53-46e4-ba0d-40285990d5e6               |
|                       | memory.usage: 8c1008d1-a1ca-4986-8526-d95fd1a91886                  |
|                       | memory: 111aae74-7814-4228-b959-b0133b70a600                        |
|                       | perf.cache.misses: 76ac152a-cd9f-4593-be95-c586cc65471e             |
|                       | perf.cache.references: 44dae2f5-67b2-4509-8457-b6b512fee081         |
|                       | perf.cpu.cycles: 6fdcae77-b548-4cd9-b78f-fdbf5dc9057c               |
|                       | perf.instructions: 09357908-90bb-43bb-a74b-8cb86dda8833             |
|                       | vcpus: d1ad1631-b464-4179-95fe-573b2d83ee69                         |
| original_resource_id  | bd7f158f-369c-41dc-81b1-84487a583c6e                                |
| project_id            | d948eedc6f1047bfaf9539e6526dd919                                    |
| revision_end          | None                                                                |
| revision_start        | 2018-04-24T01:17:48.346641+00:00                                    |
| started_at            | 2018-04-24T01:17:48.346622+00:00                                    |
| type                  | instance                                                            |
| user_id               | 8981ef1a6dcb4683b97b82925fd87a9f                                    |
+-----------------------+---------------------------------------------------------------------+

監視の値を取得してみます、memory.usageの表示です。

$ openstack metric measures show 8c1008d1-a1ca-4986-8526-d95fd1a91886
+---------------------------+-------------+-------+
| timestamp                 | granularity | value |
+---------------------------+-------------+-------+
| 2018-04-24T10:15:00+09:00 |       300.0 |  45.0 |
+---------------------------+-------------+-------+

Grafanaによるグラフ化

GrafanaへGnocchi-Pluginのインストール

コマンドラインで監視データが取得できたので、今度はグラフ化に挑みます。 まずはGrafanaへGnocchiをデータソースとして利用するためのプラグインを入れます。

$ juju ssh grafana/0
$ sudo grafana-cli plugins install gnocchixyz-gnocchi-datasource
installing gnocchixyz-gnocchi-datasource @ 1.7.0
from url: https://grafana.com/api/plugins/gnocchixyz-gnocchi-datasource/versions/1.7.0/download
into: /var/lib/grafana/plugins

Failed downloading. Will retry once.
✔ Installed gnocchixyz-gnocchi-datasource successfully 

Restart grafana after installing plugins . <service grafana-server restart>

Grafanaサービスをリスタートし、Grafanaサーバから抜けます。

$ sudo service grafana-server restart
$ exit

Grafanaログイン情報の表示

Grafanaへログインするためのパスワードを表示します。

unit-grafana-0:
  id: 57b95cec-fb95-43e1-86c5-86ad0f274c33
  results:
    password: password5656
  status: completed
  timing:
    completed: 2018-04-24 01:29:02 +0000 UTC
    enqueued: 2018-04-24 01:29:01 +0000 UTC
    started: 2018-04-24 01:29:02 +0000 UTC
  unit: grafana/0

Grafanaへ接続

Grafanaデプロイ先アドレスにWebアクセスします。 ユーザ名はadmin、パスワードは上記で表示されたものを使用します。

http://xx.xx.xx.xx:3000

Data Sourceの設定

続いてData Sourceを設定します。 Gnocchi-Pluginがインストールされていれば、TypeにGnocchiを選択できます。

f:id:virtualtech:20180424131020p:plain

しかしここで問題発生、Gnocchiへの認証モードがkeystoneを使用すると通りません。

f:id:virtualtech:20180424131023p:plain

どうやらCORSを設定しなければならないようですが、jujuの設定項目で解決ができない範囲のようです。

https://blog.sileht.net/configuring-cors-for-gnocchi-and-keystone.html

何とか出来ないものかとpluginの設定項目を探すと、認証にtokenを指定できるのを見つけました。 強引ですが、tokenを引っ張ってきて設定してみます。

$ curl -i -X POST -H "Content-Type: application/json" -d '
{
  "auth": {
    "identity": {
      "methods": [
        "password"
      ],
      "password": {
        "user": {
          "name": "admin",
          "password": "openstack",
          "domain": {
            "name": "admin_domain"
          }
        }
      }
    },
    "scope": {
      "project": {
        "name": "admin",
        "domain": {
          "name": "admin_domain"
        }
      }
    }
  }
}' http://172.17.30.89:5000/v3/auth/tokens

HTTP/1.1 201 Created
Date: Tue, 24 Apr 2018 01:42:59 GMT
Server: Apache/2.4.18 (Ubuntu)
X-Subject-Token: 830d04244cfc4598b8c5cbb4f2fdc31c
Vary: X-Auth-Token
X-Distribution: Ubuntu
x-openstack-request-id: req-ceae75ca-0b04-4fe0-bb3e-cacb630a3a1c
Content-Length: 6557
Content-Type: application/json

{"token": {"is_domain": false, "methods": ["password"], "roles": [{"id": "097ec800c2f64a438a787f058066fbc3", "name": "Admin"}, {"id": "b6b8500fe90048e7b4700bea94ffdb31", "name": "Member"}], (省略)

tokenを渡した所、正常にData Sourceを設定できたようです。

f:id:virtualtech:20180424131025p:plain

グラフ化

設定したDeta Sourceを指定してグラフを表示させてみます。 metric IDを直接指定する方式で値が取れているのがわかります。

f:id:virtualtech:20180424131027p:plain

認証の問題

何とかグラフ化に成功しましたが、tokenの期限が切れてしまうとData Sourceが機能しなくなってしまうため、別の手法を模索する必要があると感じました。 引き続き調査したいと思います。

KubernetesでPodを作る方法

KubernetesでPodを作る方法は公式のドキュメント「Kubernetes 101」にまとめられていますし、Web検索すると同じような内容のブログ記事やフォーラムのFAQが見つかります。

多くの人がこんな内容のYAMLファイルを書いて、Nginx 1.7.9をデプロイしたはずです。 ちなみにDocker HubのNginxのタグ一覧を見る限り、1.13.11が最新です。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80

では、「Nginxではなく、FedoraとかUbuntuとかCentOSとか、そういった環境をPodを作って動かしたい時はどうするか」と思ったのでその方法を調査することから始めました。

ます確認したのはKubernetes公式のドキュメントです。隅々見たつもりですが、残念ながら有力な情報は見つけられませんでした。そこでさらに色々調べたところ、次のようなサイトの情報を見つけることができました。

foxutech.com

必要な部分だけ抜き出すと、「spec - containers」にDockerのイメージと次のような記述を入れると良いようです。勘が良いかたは気がつくと思いますが、この内容でPodを作った場合Podは1000秒経過すると、自動的に終了してしまいます。なんかあの作品っぽいですね。

...
spec:
  containers:
  - name: shell
    image: centos:7
    command:
      - "bin/bash"
      - "-c"
      - "sleep 1000"

これでは場合によっては困るので、他の方法を考えてみました。

apiVersion: v1
kind: Pod
metadata:
  name: fedora
spec:
  restartPolicy: OnFailure
  containers:
    - name: fedora
      image: fedora:latest
      command:
        - "/sbin/init"

コマンドとしてInitを実行してみました。このようなYAMLを書いてkubectl create -f deploy.ymlすると、Fedoraが起動するPodを作ることができます。一応、手元の環境ではうまく動いていました。

metadataにnameとしてPodの名前を記述しておくと、その名前でPodが作成されます。imagesはデフォルトではDocker Hubに登録されたイメージが使われます。

JUJU + MAAS を使用したKubernetes構築 + 監視設定

最近当ブログでよく書かれているKubernetes。 そのKubernetesについて、物理サーバを使用した構築を行ってみようと考えました。

今回はJUJU + MAASによるKubernetes(k8s)の構築と、 PrometheusとGrafanaを使用したリソース監視の環境を作成した結果を公開いたします。

JUJU、MAAS、Kubernetesの基本的な説明については以前のエントリーを参照ください。 http://tech.virtualtech.jp/entry/2018/02/05/124557

申し遅れました、今回の筆者を努めます コムシス情報システム株式会社 山本 聡(やまもと さとる)と申します。 現在、日本仮想化技術株式会社様の元でKubernetesを学習させていただいております。

実行環境

構成を単純化するため、JUJUデプロイまでは全て物理サーバでの構築を行いました。 JUJU+MAAS以外のサーバはJUJU+MAASが自動的にアドレスを割り当てます。 今回のKubernetes構築ではMatser1台、Worker2台で構成します。

f:id:virtualtech:20180329094428p:plain

MAASのインストール

MAASサーバのみ手動でUbuntuのインストールを実施します。

Ubuntu Serverをインストール

Ubuntu Serverについては、ベーシックなインストール設定とします。 インストール後にSSHで操作するため、OpenSSH Serverを選択しています。

  • インストールモード:Install Ubuntu Server(通常のインストール)

  • Language:日本語

  • Timezone:日本

  • Keyboard:Japanese

  • ソフトウェアの選択:OpenSSH Server

ネットワーク設定

まずはネットワーク設定を行いましょう。

vim /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# eno1
auto iface eno1 inet static
address 172.17.30.10
network 172.17.30.0
netmask 255.255.255.0
broadcast 172.17.30.255
gateway 172.17.30.1
dns-nameservers 8.8.8.8

インターフェース有効化のため再起動

$ sudo reboot

アップデート

$ sudo apt -y update
$ sudo apt -y upgrade

MAASインストール

$ sudo apt install maas

執筆時点でのバージョンは2.3.0がインストールされました。

MAASユーザ設定

MAASの管理者を作成します。 今回はmaasadminというユーザを作成しました。 import SSH keysは後で入力するため、ここではEnterでスキップしておきます。

$ sudo maas createadmin

Username:maasadmin
Password:maasadmin
Again:maasadmin
Email:
Import SSH keys [] (lp:user-id or gh:user-id):

MAASダッシュボードを開く

ここまで完了すると、MAASの管理画面を開くことができます。 Port:5240 へWEBブラウザからアクセスしてみましょう。 MAASユーザ設定で使用した情報を使ってログインします。

http://172.17.30.10:5240/MAAS

f:id:virtualtech:20180329094622p:plain

MAASネットワーク設定

次に、MAAS-DHCPが使用するアドレス帯(Reserve Dynamic range)と 優先的に使用しないアドレス帯(Reserve range)を設定します。

  • subnet → VLAN

  • Reserve dynamic range :172.17.30.240 - 254

  • Reserve range :172.17.30.1 - 50

f:id:virtualtech:20180329094653p:plain

MAAS鍵設定

画面右上のユーザ名からUser Preferencesを表示し、MAAS Keysを確認して控えておきます。 またMAASが使用するssh公開鍵をSSH keysに登録しましょう。 SSH keyはssh-keygen -t rsaを使用して予め作成しておきます。

f:id:virtualtech:20180329094734p:plain

各サーバをPXEブート

MAASのネットワーク設定が終わったら、各サーバをPXEで起動してみてください。 MAASからネットワークアドレスやミニマムなOSが自動的に配信され、enlistが行われます。 Nodesに表示された各サーバをコミッショニングし、StatusがReadyになればサーバの準備は完了です。

  • Enlist 自動

  • Commission MAASが認識したサーバを選択、Take Actionからコミッションする

JUJUのインストール

JUJUのインストールと、JUJU Bootstrapサーバを構築します。 コンポーネントのインストールとBootstrap用のyamlファイルを用意しましょう。

MAASサーバにJUJUをインストール

今回はMAASサーバにJUJUのインストールを行いました。

$ sudo snap instal juju --clasic

JUJU Bootstrapの作成

Bootstrap用のyamファイルを作成します。

$ vim mymaas.yaml

clouds:
   maas-server:
      type: maas
      auth-types: [oauth1]
      endpoint: http://172.17.30.10/MAAS/

用意したyamlファイルをjuju-addcloudして登録します。

$ juju add-cloud maas-server mymaas.yaml

maas-serverという名前でCloudが作成されているかを確認します。

$ juju clouds

Cloud        Regions  Default          Type        Description
aws               14  us-east-1        ec2         Amazon Web Services
aws-china          1  cn-north-1       ec2         Amazon China
aws-gov            1  us-gov-west-1    ec2         Amazon (USA Government)
azure             26  centralus        azure       Microsoft Azure
azure-china        2  chinaeast        azure       Microsoft Azure China
cloudsigma         5  hnl              cloudsigma  CloudSigma Cloud
google             9  us-east1         gce         Google Cloud Platform
joyent             6  eu-ams-1         joyent      Joyent Cloud
oracle             5  uscom-central-1  oracle      Oracle Compute Cloud Service
rackspace          6  dfw              rackspace   Rackspace Cloud
localhost          1  localhost        lxd         LXD Container Hypervisor
maas-server        0                   maas        Metal As A Service

MAASとの連携を行うためのMAAS keyをJUJUに登録します。

$ juju add-credential Zner4ZAkAMvsg6xcST:bGQsgV4ALNKj2wmh5u:tz7gGj7Rwc77vUSgq9CGdw5WGW5cPdAJ

MAAS keyが登録されたかを確認します。

$ juju credentials --format yaml --show-secrets

JUJU Bootstrapを作成します。

$ juju bootstrap --constraints tags=bootstrap maas-server maas

もしBootstrap作成に失敗した場合は、kill-controllerを使用して再実行してください。

$ juju kill-controller maas

juju guiの表示

Bootstrapの作成が完了すると、juju guiコマンドで表示されたURLにアクセスするとjujuのGUI画面を表示できます。

$ juju gui

GUI 2.12.1 for model "admin/default" is enabled at:
  https://172.17.30.56:17070/gui/u/admin/default
Your login credential is:
  username: admin
  password: 765b9d00e1cff4338b193767fd4c9db5

Kubernetesのデプロイ

Kubernetesを構築する準備が整いました。 ここまで構築すれば、JUJUとMAASが自動的にKubernetesを構築してくれます。

MAASで認識された各サーバにタグを付与

Kubernetesのデプロイ用にMAAS上の各ノードにタグを付与します。

  • master

  • worker01

  • worker02

f:id:virtualtech:20180329095022p:plain

Kubernetesデプロイ用yamlファイルの作成

Kubernetes自動構築用のyamlファイルを用意します。 "tags="で記述される箇所がMAASのタグと一致するよう注意してください。

$ vim bundle.yaml
description: A 2-machine Kubernetes cluster, appropriate for PoC. Includes a 1 Kubernetes worker nodes.
machines:
  '0':
    series: xenial
    constraints: "arch=amd64 tags=master"
  '1':
    series: xenial
    constraints: "arch=amd64 tags=worker01"
  '2':
    series: xenial
    constraints: "arch=amd64 tags=worker02"

services:
  easyrsa:
    annotations:
      gui-x: '450'
      gui-y: '550'
    charm: cs:~containers/easyrsa-27
    num_units: 1
    to:
    - lxd:0
  etcd:
    annotations:
      gui-x: '800'
      gui-y: '550'
    charm: cs:~containers/etcd-63
    num_units: 1
    to:
    - '0'
  flannel:
    annotations:
      gui-x: '450'
      gui-y: '750'
    charm: cs:~containers/flannel-40
  kubeapi-load-balancer:
    annotations:
      gui-x: '450'
      gui-y: '250'
    charm: cs:~containers/kubeapi-load-balancer-53
    expose: true
    num_units: 1
    options:
      proxy_read_timeout: 120
    to:
    - '0'
  kubernetes-master:
    annotations:
      gui-x: '800'
      gui-y: '850'
    charm: cs:~containers/kubernetes-master-89
    num_units: 1
    options:
      channel: 1.9/stable
    to:
    - '0'
  kubernetes-worker:
    annotations:
      gui-x: '100'
      gui-y: '850'
    charm: cs:~containers/kubernetes-worker-106
    expose: true
    num_units: 2
    options:
      channel: 1.9/stable
    to:
    - '1'
    - '2'
relations:
- - kubernetes-master:kube-api-endpoint
  - kubeapi-load-balancer:apiserver
- - kubernetes-master:loadbalancer
  - kubeapi-load-balancer:loadbalancer
- - kubernetes-master:kube-control
  - kubernetes-worker:kube-control
- - kubernetes-master:certificates
  - easyrsa:client
- - etcd:certificates
  - easyrsa:client
- - kubernetes-master:etcd
  - etcd:db
- - kubernetes-worker:certificates
  - easyrsa:client
- - kubernetes-worker:kube-api-endpoint
  - kubeapi-load-balancer:website
- - kubeapi-load-balancer:certificates
  - easyrsa:client
- - flannel:etcd
  - etcd:db
- - flannel:cni
  - kubernetes-master:cni
- - flannel:cni
  - kubernetes-worker:cni

JUJUにk8sのモデルを作成

$ juju add-model k8s
$ juju switch k8s
$ juju models

Controller: maas

Model       Cloud/Region  Status     Machines  Cores  Access  Last connection
controller  maas-server   available         1     16  admin   just now
default     maas-server   available         0      -  admin   2018-03-26
k8s*        maas-server   available         7     80  admin   4 hours ago

アフタリスクがついている場所が、現在選択されているモデルです。

juju deploy を実行

$ juju deploy bundle.yaml

デプロイ中のログ表示

$ juju debug-log

yamlファイルの記述ミスなどのデプロイ失敗時

デプロイに失敗したなどでやり直す場合、デプロイ先のモデルを再作成して実行しましょう。

$ juju destroy-model k8s
$ juju add-model k8s
$ juju switch k8s

kubectlをインストール

Kubernetesを操作するためのクライアントをインストールします。

$ sudo snap install kubectl --classic

kubernetesコンフィグファイルのコピー

$ mkdir ~/.kube && touch ~/.kube/config
$ juju scp kubernetes-master/0:config ~/.kube/config

kubernetes状態の確認

実際にKubernetesが操作できるかをコマンドで確認してみましょう。

$ kubectl cluster-info

Kubernetes master is running at https://172.17.30.58:443
Heapster is running at https://172.17.30.58:443/api/v1/namespaces/kube-system/services/heapster/proxy
KubeDNS is running at https://172.17.30.58:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
kubernetes-dashboard is running at https://172.17.30.58:443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
Grafana is running at https://172.17.30.58:443/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
InfluxDB is running at https://172.17.30.58:443/api/v1/namespaces/kube-system/services/monitoring-influxdb:http/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

「kubernetes-dashboard is running at...」に表示されるURLがKubernetesのダッシュボードです。 アクセス時は認証を要求されるため、configの閲覧し、アカウントを控えておきます。

$ kubectl config view

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: REDACTED
    server: https://172.17.30.58:443
  name: juju-cluster
contexts:
- context:
    cluster: juju-cluster
    user: admin
  name: juju-context
current-context: juju-context
kind: Config
preferences: {}
users:
- name: admin
  user:
    password: chVha5l96WG9720cKwgHpDJuduJpdtGQ
    username: admin

Prometheus + AlertManager + Grafanaのデプロイ

PrometheusとGrafanaをデプロイします。 既にデプロイした環境に追加するため、yamlファイルをコピーして編集します。 元のyamlファイルに追記する形で各コンポーネントを記述します。 既にデプロイ済みの環境に対し、追加でデプロイを行う場合は元のyamlにコンポーネントを追記する形を取りましょう。 分けてしまうと、JUJUはまだ使われていないマシンを探し出してデプロイしようとしてしまいます。

$ cp -p bundle.yaml cp -p bundle.yaml addmonitor.yaml
$ vim addmonitor.yaml
description: A 2-machine Kubernetes cluster, appropriate for PoC. Includes a 1 Kubernetes worker nodes.
machines:
  '0':
    series: xenial
    constraints: "arch=amd64 tags=master"
  '1':
    series: xenial
    constraints: "arch=amd64 tags=worker01"
  '2':
    series: xenial
    constraints: "arch=amd64 tags=worker02"

services:
  easyrsa:
    annotations:
      gui-x: '450'
      gui-y: '550'
    charm: cs:~containers/easyrsa-27
    num_units: 1
    to:
    - lxd:0
  etcd:
    annotations:
      gui-x: '800'
      gui-y: '550'
    charm: cs:~containers/etcd-63
    num_units: 1
    to:
    - '0'
  flannel:
    annotations:
      gui-x: '450'
      gui-y: '750'
    charm: cs:~containers/flannel-40
  kubeapi-load-balancer:
    annotations:
      gui-x: '450'
      gui-y: '250'
    charm: cs:~containers/kubeapi-load-balancer-53
    expose: true
    num_units: 1
    options:
      proxy_read_timeout: 120
    to:
    - '0'
  kubernetes-master:
    annotations:
      gui-x: '800'
      gui-y: '850'
    charm: cs:~containers/kubernetes-master-89
    num_units: 1
    options:
      channel: 1.9/stable
    to:
    - '0'
  kubernetes-worker:
    annotations:
      gui-x: '100'
      gui-y: '850'
    charm: cs:~containers/kubernetes-worker-106
    expose: true
    num_units: 2
    options:
      channel: 1.9/stable
    to:
    - '1'
    - '2'
  prometheus:
    charm: "cs:xenial/prometheus-5"
    num_units: 1
    storage metrics-filesystem: rootfs
    options:
      install_method: snap
      web-listen-port: 9090
      static-targets: 172.17.30.62:9100
    annotations:
      gui-x: '422.25006103515625'
      gui-y: '1066.5'
    to:
      - lxd:0
  grafana:
    charm: "cs:xenial/grafana-9"
    num_units: 1
    options:
      install_method: apt
      admin_password: password5656
    annotations:
      gui-x: '132.75'
      gui-y: '1066'
    to:
      - lxd:0
  prometheus-alertmanager:
    charm: "cs:xenial/prometheus-alertmanager-2"
    num_units: 1
    options:
      snap_channel: stable
      port: 9093
    annotations:
      gui-x: '720.2500610351562'
      gui-y: '1076.5'
    to:
      - lxd:0

relations:
- - kubernetes-master:kube-api-endpoint
  - kubeapi-load-balancer:apiserver
- - kubernetes-master:loadbalancer
  - kubeapi-load-balancer:loadbalancer
- - kubernetes-master:kube-control
  - kubernetes-worker:kube-control
- - kubernetes-master:certificates
  - easyrsa:client
- - etcd:certificates
  - easyrsa:client
- - kubernetes-master:etcd
  - etcd:db
- - kubernetes-worker:certificates
  - easyrsa:client
- - kubernetes-worker:kube-api-endpoint
  - kubeapi-load-balancer:website
- - kubeapi-load-balancer:certificates
  - easyrsa:client
- - flannel:etcd
  - etcd:db
- - flannel:cni
  - kubernetes-master:cni
- - flannel:cni
  - kubernetes-worker:cni
- - grafana:grafana-source
  - prometheus:grafana-source
- - prometheus-alertmanager:alertmanager-service
  - prometheus:alertmanager-service

デプロイを実行

$ juju deploy addmonitor.yaml

以下のコマンドでデプロイの状態を表示できます。 各コンンポーネントがどのIPアドレスを使用しているかも分かるため、デプロイ後には一度チェックをしておきましょう。

$ juju status

Model  Controller  Cloud/Region  Version  SLA
k8s    maas        maas-server   2.3.4    unsupported

App                      Version  Status  Scale  Charm                    Store       Rev  OS      Notes
easyrsa                  3.0.1    active      1  easyrsa                  jujucharms   27  ubuntu  
etcd                     2.3.8    active      1  etcd                     jujucharms   63  ubuntu  
flannel                  0.9.1    active      3  flannel                  jujucharms   40  ubuntu  
grafana                           active      1  grafana                  jujucharms    9  ubuntu  
kubeapi-load-balancer    1.10.3   active      1  kubeapi-load-balancer    jujucharms   53  ubuntu  exposed
kubernetes-master        1.9.4    active      1  kubernetes-master        jujucharms   89  ubuntu  
kubernetes-worker        1.9.4    active      2  kubernetes-worker        jujucharms  106  ubuntu  exposed
prometheus                        active      1  prometheus               jujucharms    5  ubuntu  
prometheus-alertmanager           active      1  prometheus-alertmanager  jujucharms    2  ubuntu  

Unit                        Workload  Agent  Machine  Public address  Ports               Message
easyrsa/0*                  active    idle   0/lxd/0  172.17.30.74                        Certificate Authority connected.
etcd/0*                     active    idle   0        172.17.30.71    2379/tcp            Healthy with 1 known peer
grafana/0*                  active    idle   0/lxd/1  172.17.30.76    3000/tcp            Started grafana-server
kubeapi-load-balancer/0*    active    idle   0        172.17.30.71    443/tcp             Loadbalancer ready.
kubernetes-master/0*        active    idle   0        172.17.30.71    6443/tcp            Kubernetes master running.
  flannel/1                 active    idle            172.17.30.71                        Flannel subnet 10.1.28.1/24
kubernetes-worker/0         active    idle   1        172.17.30.72    80/tcp,443/tcp      Kubernetes worker running.
  flannel/2                 active    idle            172.17.30.72                        Flannel subnet 10.1.89.1/24
kubernetes-worker/1*        active    idle   2        172.17.30.73    80/tcp,443/tcp      Kubernetes worker running.
  flannel/0*                active    idle            172.17.30.73                        Flannel subnet 10.1.64.1/24
prometheus-alertmanager/0*  active    idle   0/lxd/3  172.17.30.75    9093/tcp            Ready
prometheus/0*               active    idle   0/lxd/2  172.17.30.77    9090/tcp,12321/tcp  Ready

Machine  State    DNS           Inst id              Series  AZ       Message
0        started  172.17.30.71  rdkykf               xenial  default  Deployed
0/lxd/0  started  172.17.30.74  juju-3f8b8d-0-lxd-0  xenial  default  Container started
0/lxd/1  started  172.17.30.76  juju-3f8b8d-0-lxd-1  xenial  default  Container started
0/lxd/2  started  172.17.30.77  juju-3f8b8d-0-lxd-2  xenial  default  Container started
0/lxd/3  started  172.17.30.75  juju-3f8b8d-0-lxd-3  xenial  default  Container started
1        started  172.17.30.72  cqpcs3               xenial  default  Deployed
2        started  172.17.30.73  mdc8es               xenial  default  Deployed

Relation provider                             Requirer                             Interface         Type         Message
easyrsa:client                                etcd:certificates                    tls-certificates  regular      
easyrsa:client                                kubeapi-load-balancer:certificates   tls-certificates  regular      
easyrsa:client                                kubernetes-master:certificates       tls-certificates  regular      
easyrsa:client                                kubernetes-worker:certificates       tls-certificates  regular      
etcd:cluster                                  etcd:cluster                         etcd              peer         
etcd:db                                       flannel:etcd                         etcd              regular      
etcd:db                                       kubernetes-master:etcd               etcd              regular      
kubeapi-load-balancer:loadbalancer            kubernetes-master:loadbalancer       public-address    regular      
kubeapi-load-balancer:website                 kubernetes-worker:kube-api-endpoint  http              regular      
kubernetes-master:cni                         flannel:cni                          kubernetes-cni    subordinate  
kubernetes-master:kube-api-endpoint           kubeapi-load-balancer:apiserver      http              regular      
kubernetes-master:kube-control                kubernetes-worker:kube-control       kube-control      regular      
kubernetes-worker:cni                         flannel:cni                          kubernetes-cni    subordinate  
prometheus-alertmanager:alertmanager-service  prometheus:alertmanager-service      http              regular      
prometheus:grafana-source                     grafana:grafana-source               grafana-source    regular      

NodeExporterのデプロイ

Prometheusが各ノードの情報を取得するためのNodeExporterを導入します。 今回はKubernetesのデーモンセットとして機能させます。 監視コンポーネントのように、ノードに対し一律で配置するようなものについては、Kubernetesデーモンセットを使用すると新規追加したノードにも自動的にコンポーネントが展開されます。

$ vim node-exporter.yml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  template:
    metadata:
      labels:
        app: node-exporter
      annotations:
        prometheus.io/scrape: 'true'
        prometheus.io/port: '9100'
    spec:
      containers:
      - name: node-exporter
        image: prom/node-exporter:v0.13.0
        ports:
        - containerPort: 9100
      hostNetwork: true
      hostPID: true
$ kubectl create -f node-exporter.yml

Kubernetes-Metricsのデプロイ

Kubernetesクラスタを監視するメトリクスを追加します。

$ vim kubernetes-metrics.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-state-metrics
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: kube-state-metrics
      annotations:
        prometheus.io/scrape: 'true'
        prometheus.io/port: '8080'
    spec:
      containers:
      - name: kube-state-metrics
        image: gcr.io/google_containers/kube-state-metrics:v0.3.0
        ports:
        - containerPort: 8080
$ kubectl create -f kubernetes-metrics.yml

Prometheusジョブ設定

jujuからPrometheusの”scrape-jobs (string)”へ追記

- job_name: 'kubernetes-pods'

  kubernetes_sd_configs:
  - role: pod

  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)
  - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
    action: replace
    regex: (.+):(?:\d+);(\d+)
    replacement: ${1}:${2}
    target_label: __address__
  - action: labelmap
    regex: __meta_kubernetes_pod_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_pod_name]
    action: replace
    target_label: kubernetes_pod_name

f:id:virtualtech:20180329095124p:plain

Prometheusターゲット設定

jujuからPrometheusの”static-targets (string)”へ追記

172.17.30.72:4194,
172.17.30.73:4194,
172.17.30.72:9100,
172.17.30.73:9100

f:id:virtualtech:20180329095150p:plain

Prometheusデプロイ

Save Changes → Commit changes

Target確認

Prometheusデプロイ先アドレスにWebアクセスし、targetの状態を確認します。 StatusがUPとなっていれば成功です。 デプロイ先アドレスがわからなくなった場合はjuju statusを使いましょう。

http://172.17.30.77:9090/targets

Grafanaログイン情報の表示

Grafanaへログインするためのパスワードを表示します。

$ juju run-action --wait grafana/0 get-admin-password

unit-grafana-0:
  id: a39e3b5d-e975-4348-8479-9d511f52cf86
  results:
    password: password5656
  status: completed
  timing:
    completed: 2018-03-26 07:33:58 +0000 UTC
    enqueued: 2018-03-26 07:33:57 +0000 UTC
    started: 2018-03-26 07:33:58 +0000 UTC
  unit: grafana/0

Grafanaへ接続

Prometheusデプロイ先アドレスにWebアクセスします。 ユーザ名はadmin、パスワードは上記で表示されたものを使用します。

http://172.17.30.76:3000

ダッシュボード作成

Grafanaでダッシュボードを作成します。 importからIDを指定すると、Grafanaで公開されているテンプレートを使用できます。

f:id:virtualtech:20180329095226p:plain

ID:3119のテンプレートを使用したグラフが以下となります。

f:id:virtualtech:20180329095246p:plain

今回は性能監視についてKubernetesでの実現方法の一例を取り上げました。 基盤がどのようなものであれ、アプリケーション開発者、インフラ管理者双方が関心を寄せる事項かと思われます。

Jujuで構築するKubernetesでGPUを使うには

JujuでKubernetesをデプロイする方法については以前、次のように書きました。

tech.virtualtech.jp

では、今回は「Jujuで構築するKubernetesでGPUを使うには」と言う話を書きたいと思います。 と言っても割と簡単で、Kubernetes WorkerノードにNVIDIAのGPUを挿して、juju deploy kubernetesでドーンで終了です。

JujuでGPU対応Kubernetes環境を作る

前回の記事でも書いた通り、Jujuはアプリケーション単体の設定などが定義されているCharm、それを一つにまとめたBundleがあります。Kubernetes WorkerのCharmの設定一覧を見ると簡単に導入できる理由がわかると思います。

現在のKubernetes Workerのリビジョンは106が安定版なので、その設定は次のURLで確認できます(2018年3月28日現在)。

https://api.jujucharms.com/charmstore/v5/~containers/kubernetes-worker-106/archive/config.yaml

該当の部分を抜き出すとこれです。install-cudaのパラメーターがデフォルトでtrueになっています。このため、Kubernetes WorkerのホストにNVIDIAのGPUカードが接続されていると必要なGPUドライバーやCUDAなどがインストールされるわけです。

  "install-cuda":
    "type": "boolean"
    "default": !!bool "true"
    "description": |
      Install the CUDA binaries if capable hardware is present.

さて、DockerコンテナーでGPUを使うと言うと「NVIDIA Docker」を想像すると思います。実はKubernetesでGPUを取り扱う場合、NVIDIA Dockerは必須ではありません。JujuでKubernetesの環境を作った場合はGPU DriverとCUDAがインストールされるだけで、NVIDIA Dockerは自動的にインストールはされません。

アプリケーションの要件でNVIDIA Dockerが必要な場合はGPUが載ったKubernetes Workerノードにログインしてインストールする必要があります。juju sshコマンドでログインして、セットアップします。

github.com

GitHubサイトを確認すると、NVIDIA Dockerにはバージョン1と2が存在するのがわかります。バージョン1は開発終了しており、新しく導入するのであればバージョン2の導入をおススメします。

ところがQuick Startに従ってインストールしようとすると「docker-ceがインストールされていないので無理」といわれて詰みます。

% sudo apt-get install -y nvidia-docker2

JujuでKubernetes Workerを構築した場合、Ubuntuアーカイブのdocker.ioパッケージがインストールされます。nvidia-docker2をインストールするときに導入済み済みのDockerバージョンを指定するとうまくいきます。方法は次のページに書かれています。

github.com

まず、公開されているnvidia-docker2とnvidia-container-runtimeのバージョンを確認します。現在はnvidia-docker2はバージョン2.0.3、nvidia-container-runtimeは2.0.0が最新版のようです。

出力結果を見ればわかるように、Dockerのバージョンによって導入すべきパッケージが分かれていることがわかると思います。

% apt list -a nvidia-docker2 nvidia-container-runtime
Listing... Done
nvidia-container-runtime/xenial 2.0.0+docker18.03.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.12.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.12.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.09.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.09.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.06.2-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.03.2-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker1.13.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker1.12.6-1 amd64
...
nvidia-docker2/xenial 2.0.3+docker18.03.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.12.1-1 all
nvidia-docker2/xenial 2.0.3+docker17.12.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.09.1-1 all
nvidia-docker2/xenial 2.0.3+docker17.09.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.06.2-1 all
nvidia-docker2/xenial 2.0.3+docker17.03.2-1 all
nvidia-docker2/xenial 2.0.3+docker1.13.1-1 all 
nvidia-docker2/xenial 2.0.3+docker1.12.6-1 all

Ubuntu 16.04.4でインストールされるdocker.ioは次のように実行すると1.13.1であることがわかります。

% apt list -a docker.io
Listing... Done
docker.io/xenial-updates,now 1.13.1-0ubuntu1~16.04.2 amd64 [installed]
docker.io/xenial 1.10.3-0ubuntu6 amd64

というわけで、次のようにバージョンを指定してインストールすれば良いわけです。

% sudo apt install -y nvidia-docker2=2.0.3+docker1.13.1-1 nvidia-container-runtime=2.0.0+docker1.13.1-1

ついでに関連するパッケージのバージョンを固定しておくと良いでしょう。

% sudo apt-mark hold docker.io nvidia-docker2 nvidia-container-runtime

GPU Podを作ろう

それでは早速、GPUが使えるPodを作ってみます。KubernetesのGPU Scheduleについては次のページにまとまっています。

kubernetes.io

ここに書かれているサンプルファイルをちょっと書き換えて、次のようなYAMLを書いてみます。

apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  restartPolicy: OnFailure
  containers:
    - name: nvidia-cuda
      image: nvidia/cuda:9.1-base
      tty: true
      resources:
        limits:
          alpha.kubernetes.io/nvidia-gpu: 1 # requesting 1 GPU
      volumeMounts:
        - name: bin
          mountPath: /usr/local/nvidia/bin
        - name: lib 
          mountPath: /usr/local/nvidia/lib
  volumes:
      - hostPath:
          path: /usr/lib/nvidia-390/bin
        name: bin
      - hostPath:
          path: /usr/lib/nvidia-390
        name: lib

volumesではKubernetes Workerホストにインストール済みのNVIDIAツールの実行ファイルと関連ライブラリーを指定しています(当然ながらバージョンを指定していますので、バージョンが変わればここの記述も変える必要があります。)。これを上のcontainersのvolumeMountsでマウントしています。

このYAMLをfirst-gpupod.ymlという名前で保存して次のように実行しましょう。 GPU Podが作成できます。

% kubectl create -f first-gpupod.yml
% kubectl get pod testpod
NAME      READY     STATUS    RESTARTS   AGE
testpod   1/1       Running   0          2m

% kubectl exec -it testpod nvidia-smi
Wed Mar 28 01:33:02 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.30                 Driver Version: 390.30                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1080    Off  | 00000000:01:00.0 Off |                  N/A |
| 27%   29C    P8    11W / 180W |      0MiB /  8119MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

作成したPodは次のコマンドで削除できます。

% kubectl delete -f first-gpupod.yml

こんな形です。本日は以上です。 次回はChainerでGPUを使ってなにかやってみたいと思います。

Jujuで構築するKubernetes

最近弊社ではKubernetesの検証を始めています。

Kubernetesは、展開、スケーリング、コンテナー上で動くアプリケーションの管理を自動化するために設計されたオープンソースのプラットフォームです。2014年にKubernetesプロジェクトがGoogle主導のもと始まりました。

Kubernetesには次のような特徴があります。

  • 疎結合である
  • 負荷に応じてスケールできる
  • ホストOSから抽象化したレイヤーでアプリケーションを実行できる
  • 迅速にアプリケーションを展開できる
  • その場でアプリケーションをスケールできる
  • シームレスに新機能をロールアウトできる
  • 必要なリソースだけにハードウェアの使用率を制限できる

Kubernetesは色々なOS上で動かすことができますが、今回はUbuntu ServerとJuju、MAASを使って、Kubernetes環境を構築してみました。

Jujuはいわゆるアプリケーションの構成管理ツールの一つです。アプリケーションの構成管理ツールというと、AnsibleとかPuppetとかが知られていると思います。それらとJujuの相違点として、OSのデプロイメントから行う点、接続関連の設定も行う点が挙げられます。使い方も比較的簡単なので、ドキュメントさえ見れば初めての人でも簡単に小規模から大規模のアプリケーションを構成することができます。

Jujuは色々なノードにデプロイメントできますが、今回はベアメタルサーバー上に環境を構築するためにMAASを利用します。次のドキュメントに従って、それぞれが準備できていることが前提です。

Jujuのドキュメント

jujucharms.com

MAASのドキュメント

https://docs.ubuntu.com/maas/2.3/en/docs.ubuntu.com

MAASの必須要件

MAASでは組み込みのDHCPが提供したいネットワークセグメント上で動いていることが要件です。また、JujuとJujuによってデプロイするマシンとの関連づけのためにMAASのタグ機能を使います。識別しやすいタグを設定しておきましょう。

Jujuの必須要件

当たり前のことを言って恐縮ですが、JujuとMAASの組み合わせで利用する場合はJujuがMAASサーバーとネットワークの疎通があることが要件です。JujuはbootstrapというプロセスをMAASで管理されているノードにデプロイする必要があります。Jujuを操作するクライアント(CLI、GUI)からの命令をbootstrap経由でほかのノードに対して実行するような仕組みです。

Jujuとデプロイメント

JujuにはCharmとBundleというものがあります。Charmはアプリケーションと設定ファイルが含まれたパッケージで、GUIやCLIでアプリケーション単体をデプロイするものです。

一方Bundleはアプリケーションをデプロイするためのマシンの確保からOSのデプロイメントとアップデート、アプリケーションのデプロイメント、アプリケーションの設定、サービスの再起動、アプリケーション間の接続のための設定などを自動で行うことができるパッケージです。CharmもBundleもYAMLファイルで独自の設定を含めてデプロイメントできます。

JujuでKubernetesをデプロイしよう

環境さえ用意できれば次のコマンドだけでサーバー9台のマシンにKubernetes環境をデプロイメントできます。

% juju deploy canonical-kubernetes

設定はこちらのページに掲載されているファイル一覧のbundle.yamlに記載されており、ここを書き換えることでユーザーの好みの構成で環境をデプロイメントできます。

jujucharms.com

以下はYAMLの記述例です。ちなみにCharmストアのパッケージを使う場合、CharmやBundleのデプロイに必要なのは実はbundle.yamlだけです。このファイルをwgetやcurlコマンドで手元に持ってきて、後は好きな構成に書き換えれば公式のマシン数以外でのデプロイが可能になります。

さて、BundleのYAMLファイルの記述方法ですが、machinesにはどのようなスペックのマシンを何台、この環境構築に用いるのかを指定します。 servicesにはアプリケーションを記述しています。num_unitsにはそのアプリケーションをどれだけスケールするかを指定します。2以上を指定した場合はHA構成のための設定が自動的にセットアップされます。num_unitsの下のtoでデプロイ先のJuju Machineを指定します。数字だけを記述するとベアメタル上にアプリケーションを配備して、lxd:Xのように記述するとLXCコンテナー上にアプリケーションをデプロイメントします。relationsでアプリケーション間の「繋がり」を定義します。

description: A 3-machine Kubernetes cluster, appropriate for PoC. Includes a 2 Kubernetes worker nodes.
machines:
  '0':
    series: xenial
    constraints: "arch=amd64 tags=bay10" 
  '1':
    series: xenial
    constraints: "arch=amd64 tags=bay11"
  '2':
    series: xenial
    constraints: "arch=amd64 tags=bay12"
services:
  easyrsa:
    annotations:
      gui-x: '450'
      gui-y: '550'
    charm: cs:~containers/easyrsa-23
    num_units: 1
    to:
    - lxd:0
  etcd:
    annotations:
      gui-x: '800'
      gui-y: '550'
    charm: cs:~containers/etcd-59
    num_units: 1
    to:
    - '0'
  flannel:
    annotations:
      gui-x: '450'
      gui-y: '750'
    charm: cs:~containers/flannel-35
  kubeapi-load-balancer:
    annotations:
      gui-x: '450'
      gui-y: '250'
    charm: cs:~containers/kubeapi-load-balancer-37
    expose: true
    num_units: 1
    to:
    - '0'
  kubernetes-master:
    annotations:
      gui-x: '800'
      gui-y: '850'
    charm: cs:~containers/kubernetes-master-65
    num_units: 1
    options:
      channel: 1.9/stable
    to:
    - '0'
  kubernetes-worker:
    annotations:
      gui-x: '100'
      gui-y: '850'
    charm: cs:~containers/kubernetes-worker-69
    expose: true
    num_units: 2
    options:
      channel: 1.9/stable
    to:
    - '1' 
    - '2'
relations:
- - kubernetes-master:kube-api-endpoint
  - kubeapi-load-balancer:apiserver
- - kubernetes-master:loadbalancer
  - kubeapi-load-balancer:loadbalancer
- - kubernetes-master:kube-control
  - kubernetes-worker:kube-control
- - kubernetes-master:certificates
  - easyrsa:client
- - etcd:certificates
  - easyrsa:client
- - kubernetes-master:etcd
  - etcd:db
- - kubernetes-worker:certificates
  - easyrsa:client
- - kubernetes-worker:kube-api-endpoint
  - kubeapi-load-balancer:website
- - kubeapi-load-balancer:certificates
  - easyrsa:client
- - flannel:etcd
  - etcd:db
- - flannel:cni
  - kubernetes-master:cni
- - flannel:cni
  - kubernetes-worker:cni

独自のコンフィグレーションが終わったら、次のように実行して後は待つだけでKubernetes環境が出来上がります。デプロイの状況はJuju GUIやJuju CLIのjuju statusコマンドで確認できます。

% juju deploy ./deploy.yaml

最小構成のシステムを構成するならざっと四、五十分程度でできるでしょうか。Jujuもほかの構成管理ツールと同様、冪等性があるツールです。同じBundleを使えば同じ構成でシステムのコピーを作れますし、作ったり壊したりも容易です。

今回細かくは触れませんが、JujuはModelというもので「アプリケーション軍」を管理しています。モデルで環境を分ければ、Jujuを使ってKubernetes環境やOpenStack環境、MySQLのクラスター環境などを一元管理できたりします。その辺りの話はまた今度取り上げたいと思います。

構築した環境はkubernetes-masterにログインしてkubectlコマンドなどで操作します。Jujuでデプロイした環境へはjuju sshコマンドでログインできますので、次のように操作してください。

% juju ssh kubernetes-master/0
ubuntu@bay10:~$ kubectl get nodes
NAME           STATUS    ROLES     AGE       VERSION
bay11          Ready     <none>    4d        v1.9.2
bay12          Ready     <none>    4d        v1.9.2

ただ、Kubernetes環境でデプロイするたびにログインするのも少し面倒です。次のように実行すると、必要なコマンドが手元の環境に導入されている前提で、Kubernetesの操作ができます。マスターノードからクレデンシャルファイルをjuju scpコマンドで持ってくれば良いわけです。ちなみに転送してきたファイルをホームディレクトリーの同じパスにおけば、色々なところのクライアントでKubernetesを操作できます。

% juju scp kubernetes-master/0:config ~/.kube/config
% kubectl get nodes
NAME           STATUS    ROLES     AGE       VERSION
bay11          Ready     <none>    4d        v1.9.2
bay12          Ready     <none>    4d        v1.9.2

と、こんな感じで割と簡単にKubernetesの環境を作ることができます。YAMLファイルにきちんと「構成したい構成」を書いておけば、後はJujuとbootstrapがその通りの環境を作ってくれるわけです。Juju、すごい。

ちなみにKubernetes関連のBundleは私が使い始めた頃よりも充実してきました。コミュニティによるBundleも含めると、16個ほど色々な構成をデプロイすることができるBundleが用意されています。

jujucharms.com

日本仮想化技術では従来の仮想化だけではなく、OpenStackやKubernetesについても力を入れていきたいと思っています。導入や検証検討の際は是非ご用命ください。

Packstackで構築したOpenStackをOcataからPikeにアップグレードする

ここ数日、Packstackで構築したOpenStackをOcataからPikeにアップグレードする方法を調べていました。 昔と比べると、そんなに苦労することなくアップグレードできることが確認できました。情報を共有したいと思い、こちらのブログに書かせていただきました。

ちなみに手動インストールで構築した場合でも、CentOS 7でOVSを使ってインストールした環境であれば、同様にアップグレードできると思います。バージョンアップグレードの参考になれば幸いです。

前提条件

今回の環境構築の前提条件は次の通りです。

  • OpenStack Ocata
  • NeutronはOVSを利用
  • OpenStackを標準インストールしたCentOS 7.4上に構築
  • OpenStack OcataバージョンをPikeバージョンにアップグレードする

アップグレードの流れ

OpenStackバージョンのアップグレードの流れは基本的には

  • 新しいOpenStackリリースリポジトリーの有効化
  • 新しいOpenStackパッケージの「インストール」
  • なんちゃらマネージ db sync なんちゃら の実行
  • 関連サービスの再起動

で良いようです。インストールするパッケージや実行するdb syncのコマンドはインストールガイドを確認します。

OpenStack Docs: Install OpenStack services

アップグレードの前に

OpenStackは疎結合なシステムです。従って、コンポーネントごとに別のOpenStackバージョンを使うことも可能です。

実際のアップグレード作業に入る前に、次のサイトの情報を確認し、OpenStackのアップグレードについて理解を深めてください。

superuser.openstack.org

OpenStack Pikeリポジトリーの追加

CentOS 7ではOpenStackパッケージをRDOのリポジトリーか、CentOS Cloud SIGが提供するリポジトリーのパッケージを利用することができます。CentOS Cloud SIGが提供するパッケージを使いますので次のように実行します。

# yum install centos-release-openstack-pike

Keystoneのアップグレード

新しいパッケージをインストールします。

# yum install openstack-keystone httpd mod_wsgi

Keystoneのdb_syncを実行します。

# su -s /bin/sh -c "keystone-manage db_sync" keystone

現在のKeystoneはHTTPバックエンドで動いているため、Apacheを再起動します。

# systemctl restart httpd.service

正常に起動しない場合はKeystoneのログを確認します。

Glanceのアップグレード

新しいパッケージをインストールします。

# yum install openstack-glance

Glanceのdb_syncを実行します。変換が行われます。

# su -s /bin/sh -c "glance-manage db_sync" glance

/usr/lib/python2.7/site-packages/oslo_db/sqlalchemy/enginefacade.py:1328: OsloDBDeprecationWarning: EngineFacade is deprecated; please use oslo_db.sqlalchemy.enginefacade
  expire_on_commit=expire_on_commit, _conf=conf)
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade ocata01 -> pike01, drop glare artifacts tables
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
Upgraded database to: pike01, current revision(s): pike01

関連のサービスを再起動します。

# systemctl restart openstack-glance-api.service openstack-glance-registry.service

正常に起動しない場合はGlanceのログを確認します。

Novaのアップグレード

Packstackで作ったOcata環境はnova-manage.logをroot権限で読み書きしてしまいます。このままだとPikeでは不具合があるため、次のように実行して権限を書き換えてください。

# chown nova.nova /var/log/nova/nova-manage.log

本件に関しては次のバグを参照してください。

bugs.launchpad.net

新しいパッケージをインストールします。

# yum install openstack-nova-api openstack-nova-conductor openstack-nova-console openstack-nova-novncproxy   openstack-nova-scheduler openstack-nova-placement-api

Novaのnova-manageコマンドを各種実行します。

# su -s /bin/sh -c "nova-manage api_db sync" nova
# su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova
# su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova
# su -s /bin/sh -c "nova-manage db sync" nova

関連のサービスを再起動します。

# systemctl restart openstack-nova-api.service  openstack-nova-consoleauth.service openstack-nova-scheduler.service   openstack-nova-conductor.service openstack-nova-novncproxy.service

正常に起動しない場合はNovaのログを確認します。

Nova-Computeのアップグレード

新しいパッケージをインストールします。

# yum install openstack-nova-compute

関連のサービスを再起動します。

# systemctl restart libvirtd.service openstack-nova-compute.service

正常に起動しない場合はNova-Computeのログを確認します。

Neutron のインストール前に

公式のインストール手順書はLinux Bridgeを利用しています。 PackstackはOpenvSwitchを使うため、linuxbridgeをopenvswitchに置き換える必要があります。

Neutron (controller)側の設定

コントローラー側に必要なNeutronパッケージをインストールします。

# yum install openstack-neutron openstack-neutron-ml2 \
  openstack-neutron-openvswitch ebtables

neutron-db-manageを実施してNeutronデータベースを上書きします。

# su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \
  --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron

INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
  Running upgrade for neutron ...
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade a9c43481023c -> 804a3c76314c, Add data_plane_status to Port
INFO  [alembic.runtime.migration] Running upgrade 804a3c76314c -> 2b42d90729da, qos add direction to bw_limit_rule table
INFO  [alembic.runtime.migration] Running upgrade 2b42d90729da -> 62c781cb6192, add is default to qos policies
INFO  [alembic.runtime.migration] Running upgrade 62c781cb6192 -> c8c222d42aa9, logging api
INFO  [alembic.runtime.migration] Running upgrade c8c222d42aa9 -> 349b6fd605a6, Add dns_domain to portdnses
INFO  [alembic.runtime.migration] Running upgrade 349b6fd605a6 -> 7d32f979895f, add mtu for networks
  OK

nova-apiサービスを再起動します。

# systemctl restart openstack-nova-api.service

Neutronの関連サービスを再起動します。

# systemctl restart neutron-server.service \
  neutron-openvswitch-agent.service neutron-dhcp-agent.service \
  neutron-metadata-agent.service

Neutron L3サービスを再起動します。

# systemctl restart neutron-l3-agent.service

ステータスを確認します。

# systemctl status neutron-server.service \
  neutron-openvswitch-agent.service neutron-dhcp-agent.service \
  neutron-metadata-agent.service neutron-l3-agent.service

Neutron (compute)側の設定

次にコンピュート側のOVSエージェントプラグイン側のアップグレードをします。

関連するパッケージをインストールします。

# yum install openstack-neutron-openvswitch ebtables ipset

関連サービスを再起動します。

# systemctl restart openstack-nova-compute.service
# systemctl restart neutron-openvswitch-agent.service

CentOS 7+CentOS Cloud SIG版で構成するOpenStackのOcataバージョンからPikeバージョンへの最低限のアップグレードは以上で完成です。

その他のパッケージの更新

現在はRabbitMQ、MariaDB、OVS、openstack-dashboard、python-memcachedなどが古いバージョンの状態です。 弊社環境では全てアップグレードして関連サービスを再起動するだけでアップグレードがうまくできましたが、少しずつコンポーネント単位でアップグレードするにはYUMプラグインのversionlockを使うと便利です。

まず、次のようにコマンドを実行して、アップグレードの影響がありそうなパッケージをバージョンロックします。

# yum versionlock add openvswitch openstack-dashboard python-django-horizon python-memcached
# yum update

まずはDashboardを更新してみましょう。 yum versionlock deleteコマンドでバージョンロックしたパッケージをロック解除できます。

# yum versionlock delete openstack-dashboard python-django-horizon python-memcached
# yum update
# systemctl restart httpd.service memcached.service

最後にOVSを更新します。この手順で問題なく更新できましたが、正直言うと無理にアップグレードしないでも良いのかなと思っています。OVSサービスを再起動すると、ovs-vsctl statusの結果が新しいバージョンに更新されます。

# yum versionlock delete openvswitch
# yum update
# systemctl restart openvswitch

無事にアップグレードが成功することを祈っています。

GPUパススルーを利用したKVM仮想マシンが不安定なときのチェックポイント

前回は、KVM環境でGPUパススルーをする方法について構築手順を紹介しました。

しかしながら、環境によってはいくつかの要因が重なり手順どおりにはいかないことがあります。

ここでは、KVM仮想マシンでGPUパススルーが動作しない または 不安定なときの確認ポイントを紹介いたします。

BIOSのバージョン確認

BIOSの不具合等により最新のGPUカードが正しく認識しないことがあります。メーカーのリリースノート等を確認し、該当しそうな不具合が見つかったら最新版のBIOSへアップデートします。

BIOSの設定確認

複数のGPUを利用する場合、4GB以上のMemory mapped I/O addressがサポートされていないとホストシステム上でGPUカードが正しく認識されないことがあります。

BIOSの設定にabove 4G decodingという項目がある場合は設定を有効にします。

KVM仮想マシンのチップセット設定

仮想マシンのOSがLinuxでGPUパススルーを利用する場合はQ35が安定すると言われています。仮想マシンを作成するとき、特別な理由がない限りチップセットはQ35を選択することを推奨します。

(参考:https://wiki.lime-technology.com/UnRAID_Manual_6#Creating_Your_Own_Virtual_Machines

KVM仮想マシンのCPUモード設定

仮想マシンのCPUモードが適切なものに設定されていないと仮想マシン上でGPUが正しくに動作しない場合があります。ライブマイグレーション機能を利用しない場合は "host-model" にすることを推奨します。

$ virsh edit [仮想マシン名]

### CPU Mode 設定例 ###
 <cpu mode='host-model'>
   <model fallback='allow'/>
 </cpu>

KVMホスト側の設定

PCI Expressでのデータ破損を防止するACS(Access Control Service)が有効になっていると、KVM環境では逆に不具合の要因となる場合があります。動作が不安定なときは /etc/libvirt/qemu.conf (Ubuntu 16.04の場合)を開き、以下の設定を加えてACSを無効化してみます。

relaxed_acs_check = 1

認識されているPCI Expressの世代の確認

GPUが想定していたほど性能を出していないときは、ホスト上でPCI Expressの世代が低く認識されていたり、何らかの理由でPCI Expressの転送速度が落ちている場合があります。まずは PCI Express の世代が正しく認識されているか確認します。

$ nvidia-smi -q

--- コマンド結果から抜粋 --- 
        GPU Link Info
            PCIe Generation
                Max                 : 3
                Current             : 3
            Link Width
                Max                 : 16x
                Current             : 16x
        Bridge Chip
            Type                    : N/A
            Firmware                : N/A
        Replays since reset         : 0
        Tx Throughput               : 0 KB/s
        Rx Throughput               : 0 KB/s

ここで仮想マシン上の環境では結果がGen1となっていた場合でも、物理マシン上では本来の世代で認識されていて、転送スピードを測定するとGen1の規定値以上になることがあります。次項を参考にバススピードも測ってみます。

GPUバススピードの確認方法

バススピードの実測値を測定して適切な値となるか確認します。 前回も軽く触れましたが、バススピード測定ツールはCUDAに添付されているサンプルプログラムに含まれているので、それを実行してみます。

### サンプルプログラムをまだコンパイルしていない場合は make を実行
$ cd ~/NVIDIA_CUDA-8.0_Sample
$ make

### バススピードの測定
$ cd ~/NVIDIA_CUDA-8.0_Samples/bin/x86_64/linux/release/
$ ./bandwidthTest

<出力例>
[CUDA Bandwidth Test] - Starting...
Running on...

 Device 0: Tesla P40
 Quick Mode

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         11537.8

 Device to Host Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         12961.7

 Device to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         240433.7

Result = PASS

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

実測値が1世代前の制限値より低い場合は、ハードウェアやソフトウェアに何らかの問題が起きている可能性があります(ハードウェアの相性問題であることもあります)。

各世代の制限値(一方向)

  • Gen1: 4.0 GB/sec
  • Gen2: 8.0 GB/sec
  • Gen3: 16.0 GB/sec
  • Gen4: 32.0 GB/sec

(参考:https://ja.wikipedia.org/wiki/PCI_Express

ベンチマーク

バススピードに問題がない場合は、GPUへ直接負荷をかけてみます。ベンチマークを長時間稼働させたとき、処理数が一定量で増えない場合はなんらかの問題が発生していると考えられます。ベンチマークツールの一つとして、GPU Burnを紹介します。

なお、実行する際にはGPUの温度の変化に注意して下さい。

<実行例>

$ ./gpu_burn 60

GPU 0: Tesla P40 (UUID: GPU-1f4d9f28-51e7-065d-2db9-af4397809c49)
Initialized device 0 with 22912 MB of memory (22552 MB available, using 20297 MB of it), using FLOATS
13.3%  proc'd: 3798 (9453 Gflop/s)   errors: 0   temps: 51 C
    Summary at:   Tue Dec 19 11:47:57 JST 2017

25.0%  proc'd: 7596 (9443 Gflop/s)   errors: 0   temps: 54 C
    Summary at:   Tue Dec 19 11:48:04 JST 2017

40.0%  proc'd: 12660 (9438 Gflop/s)   errors: 0   temps: 58 C
    Summary at:   Tue Dec 19 11:48:13 JST 2017

51.7%  proc'd: 16458 (9444 Gflop/s)   errors: 0   temps: 60 C
    Summary at:   Tue Dec 19 11:48:20 JST 2017

63.3%  proc'd: 20256 (9451 Gflop/s)   errors: 0   temps: 60 C
    Summary at:   Tue Dec 19 11:48:27 JST 2017

75.0%  proc'd: 24054 (9441 Gflop/s)   errors: 0   temps: 61 C
    Summary at:   Tue Dec 19 11:48:34 JST 2017

90.0%  proc'd: 29118 (9446 Gflop/s)   errors: 0   temps: 63 C
    Summary at:   Tue Dec 19 11:48:43 JST 2017

100.0%  proc'd: 32916 (9440 Gflop/s)   errors: 0   temps: 64 C
Killing processes.. done

Tested 1 GPUs:
    GPU 0: OK

Kernelログの調査

NVIDIAドライバでなんらかしらの問題が発生したとき、syslogへXidメッセージが出力されることがあります。XidメッセージにはIDが振られており、そのIDを元に公式ドキュメントを調べることでメッセージの詳細を得ることができます。

<出力例>
NVRM: Xid (PCI:0000:00:09): 32, Channel ID 0000000e intr 00008000

上記の場合、Xidは32になります。

モジュールパラメーターの設定・確認

環境によってはNVIDIAドライバのモジュールパラメータを指定することで改善される場合があります。パラメーターの項目はNVIDIAドライバのヘッダーファイル内にドキュメントがあります。

現在のパラメータの設定は以下のコマンドで確認することができます

$ cat /proc/driver/nvidia/params

パラメータを任意の値に設定するにはUbuntuの場合、以下の手順で設定します。

1. パラメーターの指定

nvidiaモジュールの設定ファイルを新たに作成します。

  • ここでは、パラメータ NVreg_CheckPCIConfigSpace=0 と NVreg_EnableMSI=1 を設定しています。
  • XXXにはNVIDIAドライバーのバージョンが入ります。
$ vi /etc/modprobe.d/nvidia-params.conf  # ←ファイルは新規に作成します

--- ファイル内容 ---
options nvidia_XXX NVreg_CheckPCIConfigSpace=0 NVreg_EnableMSI=1
--- ここまで ---

2. Initramfsの更新

$ update-initramfs -u

3. VMの再起動

$ sudo shutdown -r now