仮想化通信

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

Jujuで構築するKubernetes

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

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

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

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

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

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

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

Jujuのドキュメント

Getting started with Juju | Juju documentation

MAASのドキュメント

What is MAAS? | MAAS documentation

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についても力を入れていきたいと思っています。導入や検証検討の際は是非ご用命ください。