KubernetesのマニフェストをMagnumで実行する

2016年2月12日(金)
西島 直
今回はKubernetesの「マニフェスト」を作成し、Magnumから実行してみます。

はじめに

2015年1月20日、コンテナサービスMagnumの最初のバージョンがリリースされました。Magnumは、Docker swarmやKubernetesなどのコンテナクラスタを提供するOpenStackのAPIサービスであり、これらの環境をコマンドで構築し、操作できます。本連載では、Fedora21とDevstackを用いてMagnum環境を構築し、Kubernetesの操作手順についてご紹介しています。

第3回では、Magnumの動作とKubernetesの概要を説明し、Magnumで構築したKubernetes上でnginxを動かします。

Magnumは何をしているのか

前回はMagnumをインストールして、Bayを作成しました。Bayを作る際にMagnumは下記のHeatのテンプレートを用いてKubernetes環境を作成しています。

$ ls /opt/stack/magnum/magnum/templates/heat-kubernetes/
COPYING                 kubemaster-coreos.yaml
README.md               kubemaster-fedora-ironic.yaml
elements/               kubemaster.yaml
fragments/              kubeminion-coreos.yaml
kubecluster-coreos.yaml kubeminion-fedora-ironic.yaml
kubecluster-fedora-ironic.yaml  kubeminion.yaml
kubecluster.yaml

これらのテンプレートは、Novaを呼び出して仮想マシンを作成し、Cinderを呼び出してdocker storageで必要になるボリュームを切り出し、Neutronを呼び出してネットワークを設定しています。そしてHeatのSoftwareConfig機能を用いてKubernetesに必要な設定を行っています。それらの設定は、fragmentsフォルダ以下のシェルスクリプトが行います。

$ ls /opt/stack/magnum/magnum/templates/heat-kubernetes/fragments/
add-proxy.sh                    kube-examples.yaml
configure-docker-registry.sh    kube-register.yaml
configure-docker-storage.sh     kube-user.yaml
configure-etcd.sh               make-cert-client.sh
configure-flannel.sh            make-cert.sh
configure-kubernetes-master.sh  network-config-service.sh
configure-kubernetes-minion.sh  network-service.sh
coreos.params.yaml              write-heat-params-master.yaml
disable-selinux.sh              write-heat-params.yaml
enable-docker-registry.sh       write-kube-os-config.sh
enable-etcd.sh                  write-kubeconfig.yaml
enable-services-master.sh       write-network-config.sh
enable-services-minion.sh

例えば、kubernetes masterの設定を行うconfigure-kubernetes-master.shは、以下のようになっています。

$ cat fragments/configure-kubernetes-master.sh
#!/bin/sh

. /etc/sysconfig/heat-params

echo "configuring kubernetes (master)"
sed -i '
  /^ETCD_LISTEN_CLIENT_URLS=/ s/=.*/="http:\/\/0.0.0.0:2379"/
' /etc/etcd/etcd.conf

sed -i '
  /^KUBE_ALLOW_PRIV=/ s/=.*/="--allow_privileged='"$KUBE_ALLOW_PRIV"'"/
' /etc/kubernetes/config

KUBE_API_ARGS="--runtime_config=api/all=true"
if [ "$TLS_DISABLED" == "True" ]; then
    KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0 --insecure-port=$KUBE_API_PORT"
else
    KUBE_API_ADDRESS="--bind_address=0.0.0.0 --secure-port=$KUBE_API_PORT"
    # insecure port is used internaly
    KUBE_API_ADDRESS="$KUBE_API_ADDRESS --insecure-port=8080"
    KUBE_API_ARGS="$KUBE_API_ARGS --tls_cert_file=/srv/kubernetes/server.crt"
    KUBE_API_ARGS="$KUBE_API_ARGS --tls_private_key_file=/srv/kubernetes/server.key"
    KUBE_API_ARGS="$KUBE_API_ARGS --client_ca_file=/srv/kubernetes/ca.crt"
fi

sed -i '
  /^KUBE_API_ADDRESS=/ s/=.*/='"${KUBE_API_ADDRESS}"'/
  /^KUBE_SERVICE_ADDRESSES=/ s|=.*|="--service-cluster-ip-range='"$PORTAL_NETWORK_CIDR"'"|
  /^KUBE_API_ARGS=/ s/KUBE_API_ARGS.//
  /^KUBE_ETCD_SERVERS=/ s/=.*/="--etcd_servers=http:\/\/127.0.0.1:2379"/
  /^KUBE_ADMISSION_CONTROL=/ s/=.*/=""/
' /etc/kubernetes/apiserver
cat << _EOC_ >> /etc/kubernetes/apiserver
#Uncomment the following line to disable Load Balancer feature
KUBE_API_ARGS="$KUBE_API_ARGS"
#Uncomment the following line to enable Load Balancer feature
#KUBE_API_ARGS="$KUBE_API_ARGS --cloud_config=/etc/sysconfig/kube_openstack_config --cloud_provider=openstack"
_EOC_

sed -i '
  /^KUBELET_ADDRESSES=/ s/=.*/="--machines='""'"/
  /^KUBE_CONTROLLER_MANAGER_ARGS=/ s/KUBE_CONTROLLER_MANAGER_ARGS.*/#Uncomment the following line to enable Kubernetes Load Balancer feature \n#KUBE_CONTROLLER_MANAGER_ARGS="--cloud_config=\/etc\/sysconfig\/kube_openstack_config --cloud_provider=openstack"/
' /etc/kubernetes/controller-manager

configure-kubernetes-master.shが行っていることは、設定ファイルの作成と、magnumコマンドの引数をその設定ファイルに代入することです。代入には、sedコマンドが用いられています。

Magnumは特に難しいことをしているわけではなく、Heatのテンプレートとシェルスクリプトを活用してコンテナクラスタを構築しています。現時点でのゲストのイメージは、KubernetesやDockerがインストールされたAtomic-hostもしくはCoreOSを前提として動いています。

Kubernetesの概要

KubernetesはDockerコンテナのオーケストレーションシステムを管理します。PodやService、Replication Controllerといった概念があり、Magnumからそれらを作成することが可能です。作成するためには「マニフェスト」と呼ばれるファイル(jsonまたはyaml形式で記述)を用意し、Magnumのコマンドに与える必要があります。

Podのマニフェスト

Podは複数のDockerコンテナをまとめた単位です。Pod内のコンテナは、Linuxネームスペースの以下のコンテキストを共有します。

  • PID名前空間
  • Network名前空間
  • IPC名前空間
  • UTS名前空間

例えばNetwork名前空間がコンテナ同士で共有されているので、Pod内のコンテナ同士はIPアドレスを共有します。またそれぞれのコンテナが同じ共有ディスクにアクセスできるので、同じノードで実行するのに適したアプリケーションのコンテナ群は、同じPodに入れます。

ここでは実験のため、NginxのPodを作成するマニフェストを書いてみます。

$ cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80

kindには作成したいPodやServiceなどのオブジェクトを記載します。metadataには、このPodの名前や、Podを特定するための付加情報のラベルを記載します。spec以下には、起動したいコンテナを記載します。上記の例ではimageにnginxを指定しています。この場合は「docker pull nginx」と同じ動作になるので、docker hubに登録されているnginxのdocker imageをpullして起動することを意味します。

Magnumで実行

上記のマニフェストを作成し、Magnumで実行してみます。

$ magnum pod-create --manifest pod.yaml --bay k8sbay

Nginxのdocker imageが起動したことを確認するためには、kubernetes masterのVMにログインしてkubectlコマンドを実行します。

$ nova list
(見やすいように整形しています)
|<ID1>|k8-aaa-kube_master-bbb|ACTIVE|Running|private=172.16.0.6, 10.0.0.26 |
|<ID2>|k8-ccc-kube_minion-ddd|ACTIVE|Running|private=172.16.0.7, 10.0.0.27 |
|<ID3>|k8-eee-kube_minion-fff|ACTIVE|Running|private=172.16.0.8, 10.0.0.28 |
$ ssh minion@10.0.0.26
[minion]$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
nginx     1/1       Running   0          6m

nginxのSTATUSがRunningになっていれば、Docker コンテナの立ち上げは成功です。

Replication Controllerのマニフェスト

Kubernetesには、Replication Controllerと呼ばれるPodの数を一定に保つようにする機能があります。この数は動的に変更可能なので、オートスケールにも使われます。またReplication ControllerはPodの数を維持するように動作するので、あるノードで障害が起きた際には、そのノード上のPodを他のノードで再度立ち上げてくれます。そのため、単一のPodを立ち上げる時もReplication Controllerの利用が推奨されています。

Replication Controller

http://kubernetes.io/v1.0/docs/user-guide/replication-controller.html

Replication Controller機能を試すために、まずは既存のPodを削除してから立ち上げます。現時点でPodを削除するmagnumコマンドのbayは、名前ではなくIDでPodを指定します。

$ magnum bay-list
+--------------------------------------+--------+…
| uuid                                 | name   | …
+--------------------------------------+--------+…
| 0c9e0d9d-0f2b-4a99-9160-1467c7f3e8ca | k8sbay |…
+--------------------------------------+--------+…
$ magnum pod-delete nginx 0c9e0d9d-0f2b-4a99-9160-1467c7f3e8ca

今回のReplication Controllerのマニフェストは、以下のものを使います。Podのものと似ていますが、specが入れ子になっており、最初の階層に複製数を指定するreplicasという項目があります。以下の例では3を指定しました。2段めの階層のspecは、Podで記述したものと同一です。

$ cat replication.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

以下のように、MagnumでReplication Controllerを作成します。

$ magnum rc-create --manifest replication.yaml --bay k8sbay

先ほどと同じようにPodの起動を確認します。

$ ssh minion@10.0.0.26
[minion] $ kubectl get rc
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR    REPLICAS
nginx        nginx          nginx      app=nginx   3
[minion] $ kubectl get po
NAME          READY     STATUS    RESTARTS   AGE
nginx-1o41m   1/1       Running   0          9m
nginx-wgnt4   1/1       Running   0          9m
nginx-yor5x   1/1       Running   0          9m

「kubectl describe pod <pod name>」を各Podに対して実行すると、異なるNodeが表示されます。

Serviceのマニフェスト

最後に、他のPodや外部からアクセスするための抽象レイヤであるServiceを定義します。Podは作成時にIPアドレスが割り当てられますが、Replication ControllerによってPodは動的に作成・削除され、再作成の際には異なるIPアドレスが割り当てられます。そのため、IPアドレスでは安定的に通信を行うことができません。

そこでServiceという抽象レイヤをPodとセットにすることで、他のPodからはServiceにアクセスするだけで、安定的に通信が行えます。Serviceを作成すると、各Podに次の環境変数が追加されます。

  • {service name}_SERVICE_HOST
  • {service name}_SERVICE_PORT

この環境変数を使うことで、Podは他のPodと安定的に通信できるようになります。Serviceを作成するマニフェストは、以下のようになります。

$ cat service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
    - port: 8080
      targetPort: 80
      nodePort: 30080
  selector:
    name: nginx
  type: LoadBalancer

このマニフェストは、名前がnginxのPodの80番ポートを外部のPodに8080で公開します。selectorは、Podを指定するために利用します。今回はnameで指定しましたが、Replication Controllerマニフェストのlabelsに「app:nginx」と記述したので「app: nginx」と指定することも可能です。このラベルは他のものから識別するためのもので、好きなラベルを付けることができます。詳しくは参考文献2を参照してください。

またこのマニフェストは、外部からのアクセスも許可しています。Nova listコマンドで表示された、kube-minionのVMのFloating IP(10.0.0.27)にnodePortのポート番号30080を加えてアクセスすると、Nginxのwelcomeページが表示されます。

マニフェストで作成したNginxのWelcomeページにアクセス

図1 マニフェストで作成したNginxのWelcomeページにアクセス

今回は単純なマニフェストを書きましたが、複数のDockerイメージを用いた複雑なシステムを記述することも可能です。下記のリンクを参考に、ぜひマニフェストを書いてみてください。

Basics Tutorials

http://kubernetes.io/v1.0/basicstutorials.html

まとめ

3回にわたり、Magnumを紹介してきました。Magnumは現在とても注目されているプロジェクトであり、様々な機能が日々追加されており、執筆中にも増えています!Kubernetesだけでなく、Docker SwarmやMesosも構築できますし、VMではなくIronicも使えるよう、開発が勧められています。

Dockerを中心に多様なソフトウェアが増えています。今後さらにDocker関連のソフトウェアが増えたとしても、Magnumはそれらを吸収し統一されたAPIを提供していくでしょう。今後は、Dockerを中心にシステムが組まれることもあると思います。ぜひみなさんもMagnumを使ってみてください。

  • Linuxは、Linus Torvalds氏の日本およびその他の国における登録商標または商標です。
  • OpenStack?の文字表記とOpenStackのロゴは、米国とその他の国におけるOpenStack Foundationの登録商標/サービスマークまたは商標/サービスマークのいずれかであり,OpenStack Foundationの許諾を得て使用しています。日立製作所は,OpenStack FoundationやOpenStackコミュニティの関連企業ではなく、また支援や出資を受けていません。
  • その他、記載の商標やロゴは、各社の商標または登録商標です。

参考文献

1.「Pods」Kubernetes

http://kubernetes.io/v1.0/docs/user-guide/walkthrough/README.html

2.「Labels」Kubernetes

http:// kubernetes.io/v1.0/docs/user-guide/labels.html

株式会社日立製作所

研究開発グループ デジタルテクノロジーイノベーションセンタ OSSテクノロジーラボラトリ員
OSSの評価・検証・機能開発、upstream活動、社内外へのOSS普及に従事。
Linux KernelやKVM、OpenStackでOSSコミュニティの参加した経験を持つ。
現在はHyperledgerコミュニティに参加しブロックチェーンの普及に勤めている。

連載バックナンバー

業務アプリ技術解説

KubernetesのマニフェストをMagnumで実行する

2016/2/12
今回はKubernetesの「マニフェスト」を作成し、Magnumから実行してみます。
OSS技術解説

Openstack Magnumの環境を構築する

2015/11/30
Fedora 21とDevstackを用いて、Openstack Magnum環境を構築する手順をご紹介します。
OSS技術解説

OpenStack Magnumとコンテナ

2015/10/27
OpenStackがコンテナを取り扱うための課題と、Magnumの概要についてご紹介します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています