皆さんはGWを楽しんでいますか。せっかくの長期休暇をぐったりウィークとして無為に過ごしたりしていませんか。もちろん体を休めることは重要ですが、
そこで今回のRecipeでは、
コンテナを「いい感じ」に調整してくれるKubernetes
「Kubernetes」
- 複数のホストに複数のコンテナをデプロイするためのインフラストラクチャー
- コンテナが提供するサービスのスケーリング・
ロードバランシング - インスタンスのレプリケーション
- コンテナ間のネットワーク管理
- ロギング・
モニタリング - 上記の機能を利用するためのAPIや鍵の管理
Dockerは単にコンテナ内部でソフトウェアを実行するツールです。Dockerそのものには上記のような
Dockerコンテナを純粋なアプリコンテナとして使った場合、
複数のコンテナを管理するツールにDocker Composeがあります。Docker Composeは複数のコンテナの設定や関係をひとつのファイルにまとめて記述できるため、docker
コマンドにオプションとして渡していたような情報も設定ファイルとして記述できるため、
とどのつまりKubernetesは、
Kubernetes環境を「召喚」する
Kubernetes環境を用意すれば、
つまり管理対象の複数のホストに、
単にKubernetesの仕組みを勉強したいだけであればMinikubeを使うという手があります。Minikubeは単一ホスト上にKVMやVirtualBoxなどを用いて複数の仮想ホストを作成し、
そこで今回はより簡単に複数のホストにKubernetesを構築する方法としてconjure-upを使うことにしましょう。
conjure-upはホストを管理するバックエンドとしてJujuを使います。つまりホストの準備や個々のソフトウェアのデプロイそのものはJujuやその設定スクリプト群であるCharmが担います。conjure-upのSpellには、
簡単に言ってしまえば第341回で紹介したOpenStack Installerを、
conjure-upのインストールと実行
conjure-upを利用するためには、
- snapが動く環境
(この記事ではUbuntu 16. 04 LTSを使用しています) - Kubernetesを構築する環境
後者については、
conjure-upそのものはsnapパッケージとして提供されています。よってUbuntuでも、
$ sudo snap install conjure-up --classic conjure-up 2.1.5 from 'canonical' installed
conjure-upにはJujuのコマンドも同梱されています。このためJujuを別途インストールする必要なく、
$ conjure-up
以降はCUIから呪文を唱えることになります

conjure-upは独自のCUIツールキットを使っています。このため画面上の文字列のコピーアンドペースト操作が若干特殊です。まず文字列をコピーする場合は、
また、
なおプロキシ環境の場合はconjure-upコマンドに--http-proxy
」--help
」sshuttle
などで外への経路を確保した上でconjure-upを実行したほうがいいでしょう。
Kubernetes構築の流れ
Kubernetes環境を構築する場合は、
「The Canonical Distribution of Kubernetes」
- Kubernetes
- マスターノード1つに、
ワーカーノード2つ - ノード間通信にTLSを使用
- CNIプラグインとしてのFlannel
- マスターノードのHAとしてロードバランサー
- Nginx Ingress Controller
- Kubernetes Dashboard
- クラウドモニタリングツールとしてHeapster
- マスターノード1つに、
- EasyRSA
- 自己署名証明書の認証局
- Etcd
- 信頼性を高めるために3ノード構築
ノードの数などは構築時や構築後に調整可能です。では、

ホストマシンの構築にはJujuを使います。Jujuを使用するためにはどこかにJujuコントローラーが必要です。これまではjuju bootstrap
」
今回は従来通り、

Spellを展開する先のクラウドサービスを選択します。
今回は

Jujuがクラウドサービス上にインスタンスを立ち上げられるよう、
前述したとおりクリップボードの文字列をペーストするには

この画面で



最終的にデプロイが完了すると、kubectl
コマンドがインストールされます。ちなみにkubectl
コマンドはsnapパッケージとして提供されるので、
$ which kubectl /snap/bin/kubectl $ snap list Name Version Rev Developer Notes conjure-up 2.1.5 197 canonical classic core 16-2 1577 canonical - kubectl 1.6.1 7 canonical classic

構築した環境の確認
まずは構築した環境を確認してみましょう。まずはJujuを使って、
$ juju status Model Controller Cloud/Region Version conjure-canonical-kubern-56a conjure-up-aws-59b aws/us-east-1 2.1.2 App Version Status Scale Charm Store Rev OS Notes easyrsa 3.0.1 active 1 easyrsa jujucharms 8 ubuntu etcd 2.3.8 active 3 etcd jujucharms 29 ubuntu flannel 0.7.0 active 4 flannel jujucharms 13 ubuntu kubeapi-load-balancer 1.10.0 active 1 kubeapi-load-balancer jujucharms 10 ubuntu exposed kubernetes-master 1.6.1 active 1 kubernetes-master jujucharms 17 ubuntu kubernetes-worker 1.6.1 active 3 kubernetes-worker jujucharms 22 ubuntu Unit Workload Agent Machine Public address Ports Message easyrsa/0* active idle 0 AAA.BBB.CCC.DD Certificate Authority connected. etcd/0* active idle 1 AAA.BBB.CCC.DD 2379/tcp Healthy with 3 known peers etcd/1 active idle 2 AAA.BBB.CCC.DD 2379/tcp Healthy with 3 known peers etcd/2 active idle 3 AAA.BBB.CCC.DD 2379/tcp Healthy with 3 known peers kubeapi-load-balancer/0* active idle 4 AAA.BBB.CCC.DD 443/tcp Loadbalancer ready. kubernetes-master/0* active idle 5 AAA.BBB.CCC.DD 6443/tcp Kubernetes master running. flannel/2 active idle AAA.BBB.CCC.DD Flannel subnet 10.1.103.1/24 kubernetes-worker/0 active idle 6 AAA.BBB.CCC.DD 80/tcp,443/tcp Kubernetes worker running. flannel/3 active idle AAA.BBB.CCC.DD Flannel subnet 10.1.2.1/24 kubernetes-worker/1* active idle 7 AAA.BBB.CCC.DD 80/tcp,443/tcp Kubernetes worker running. flannel/1 active idle AAA.BBB.CCC.DD Flannel subnet 10.1.20.1/24 kubernetes-worker/2 active idle 8 AAA.BBB.CCC.DD 80/tcp,443/tcp Kubernetes worker running. flannel/0* active idle AAA.BBB.CCC.DD Flannel subnet 10.1.62.1/24 Machine State DNS Inst id Series AZ 0 started AAA.BBB.CCC.DD i-0e621a5d06fcf0f6d xenial us-east-1a 1 started AAA.BBB.CCC.DD i-030519d511782fa14 xenial us-east-1a 2 started AAA.BBB.CCC.DD i-039478ca3d761b32f xenial us-east-1c 3 started AAA.BBB.CCC.DD i-04dff5a25d1bcc4a3 xenial us-east-1d 4 started AAA.BBB.CCC.DD i-0445ab5ce74c72197 xenial us-east-1e 5 started AAA.BBB.CCC.DD i-0cab289259c45b691 xenial us-east-1c 6 started AAA.BBB.CCC.DD i-083d7c7d8bea6a1c0 xenial us-east-1d 7 started AAA.BBB.CCC.DD i-0b28daa810f52c8a7 xenial us-east-1a 8 started AAA.BBB.CCC.DD i-06c25f726cfb48a37 xenial us-east-1c Relation Provides Consumes Type certificates easyrsa etcd regular certificates easyrsa kubeapi-load-balancer regular certificates easyrsa kubernetes-master regular certificates easyrsa kubernetes-worker regular cluster etcd etcd peer etcd etcd flannel regular etcd etcd kubernetes-master regular cni flannel kubernetes-master regular cni flannel kubernetes-worker regular loadbalancer kubeapi-load-balancer kubernetes-master regular kube-api-endpoint kubeapi-load-balancer kubernetes-worker regular cni kubernetes-master flannel subordinate kube-control kubernetes-master kubernetes-worker regular cni kubernetes-worker flannel subordinate
「Machine」
次にkubectl
コマンドを使ってみましょう
$ kubectl cluster-info Kubernetes master is running at https://(Kubernetes APIのIPアドレス):443 Heapster is running at https://(Kubernetes APIのIPアドレス):443/api/v1/proxy/namespaces/kube-system/services/heapster KubeDNS is running at https://(Kubernetes APIのIPアドレス):443/api/v1/proxy/namespaces/kube-system/services/kube-dns kubernetes-dashboard is running at https://(Kubernetes APIのIPアドレス):443/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard Grafana is running at https://(Kubernetes APIのIPアドレス):443/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana InfluxDB is running at https://(Kubernetes APIのIPアドレス):443/api/v1/proxy/namespaces/kube-system/services/monitoring-influxdb To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
「The Canonical Distribution of Kubernetes」

本来このDashboardはkubectl proxy
」
$ juju config kubernetes-master enable-dashboard-addons=false
Kubernetesではコンテナを動かすためのホストをkubectl get
」
$ kubectl get nodes NAME STATUS AGE VERSION ip-10-146-206-186 Ready 22h v1.6.1 ip-10-180-49-180 Ready 22h v1.6.1 ip-10-183-107-114 Ready 22h v1.6.1 $ kubectl get pods NAME READY STATUS RESTARTS AGE default-http-backend-x6f4f 1/1 Running 0 22h nginx-ingress-controller-100lz 1/1 Running 0 22h nginx-ingress-controller-8prr9 1/1 Running 0 22h nginx-ingress-controller-vcmz7 1/1 Running 0 22h $ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE default-http-backend 10.152.183.176 <none> 80/TCP 22h kubernetes 10.152.183.1 <none> 443/TCP 22h
前述したとおり、
Kubernetesでコンテナを立ち上げる
Kubernetes上にコンテナを立ち上げる場合も、kubectl
コマンドを使います。コンテナを立ち上げる方法はいくつか存在しますが、
Kubernetesのソースコードのexamples
ディレクトリにはPodのサンプルがいくつも存在します。ここではシンプルな
$ git clone https://github.com/kubernetes/kubernetes.git $ cd kuernetes
コンテナの作成はkubectl create
コマンドに、
$ kubectl create -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml service "redis-master" created deployment "redis-master" created service "redis-slave" created deployment "redis-slave" created service "frontend" created deployment "frontend" created
ステータスを確認すると、
$ kubectl get pods NAME READY STATUS RESTARTS AGE default-http-backend-x6f4f 1/1 Running 0 3d frontend-3823415956-0wvqq 1/1 Running 0 10s frontend-3823415956-w2m23 1/1 Running 0 10s frontend-3823415956-z9kb7 1/1 Running 0 10s nginx-ingress-controller-100lz 1/1 Running 0 1d nginx-ingress-controller-8prr9 1/1 Running 0 1d nginx-ingress-controller-vcmz7 1/1 Running 0 1d redis-master-1068406935-bhgdn 1/1 Running 0 13s redis-slave-2005841000-37qtz 1/1 Running 0 12s redis-slave-2005841000-jtvjx 1/1 Running 0 12s $ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE default-http-backend 10.152.183.176 <none> 80/TCP 2d frontend 10.152.183.132 <none> 80/TCP 10s kubernetes 10.152.183.1 <none> 443/TCP 2d redis-master 10.152.183.235 <none> 6379/TCP 13s redis-slave 10.152.183.222 <none> 6379/TCP 12s
ただしこのままだと外部からGuestbookサービスにアクセスできません。なぜならワーカーノードが動いているインスタンスの80番ポートをAWSが塞いでいますし、
- Jujuのコマンド経由でAWSのインスタンスのポートを開ける
- ワーカーノードへのアクセスをfrontendサービスに転送する
その前に、juju status
で表示されたUnit名を指定するだけです。
$ juju ssh kubernetes-worker/0 ubuntu@ip-10-183-107-114:~$ curl http://10.152.183.132/ <html ng-app="redis"> <head> <title>Guestbook</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script> <script src="controllers.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.js"></script> </head> <body ng-controller="RedisCtrl"> <div style="width: 50%; margin-left: 20px"> <h2>Guestbook</h2> <form> <fieldset> <input ng-model="msg" placeholder="Messages" class="form-control" type="text" name="input"><br> <button type="button" class="btn btn-primary" ng-click="controller.onRedis()">Submit</button> </fieldset> </form> <div> <div ng-repeat="msg in messages track by $index"> </div> </div> </div> </body> </html> ubuntu@ip-10-183-107-114:~$
kubectl get services
コマンドのfrontendサービスのIPアドレスへとアクセスすれば、
Jujuのコマンド経由でAWSのインスタンスのポートを開ける
AWSのインスタンスのポートは、
$ juju expose kubernetes-worker
もちろんGCPやAzureであっても同様です。Jujuが各種パブリッククラウドのAPIを使用してうまくやってくれます。juju status
で表示されているアプリケーション名です。複数のインスタンスにスケールしている場合は、
公開状態のアプリケーションはNotesフィールドに
$ juju show-status kubernetes-worker Model Controller Cloud/Region Version conjure-canonical-kubern-56a conjure-up-aws-59b aws/us-east-1 2.1.2 App Version Status Scale Charm Store Rev OS Notes flannel 0.7.0 active 3 flannel jujucharms 13 ubuntu kubernetes-worker 1.6.1 active 3 kubernetes-worker jujucharms 22 ubuntu exposed (後略)
ワーカーノードへのアクセスをfrontendサービスに転送する
ワーカーノードのポートをあけたら今度は、
Ingress Controllerでは、kubectl
コマンドに渡します。たとえばgbook.
」guestbook-ingress.
」
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: guestbook-ingress spec: rules: - host: gbook.example.com http: paths: - path: / backend: serviceName: frontend servicePort: 80
Nginx Ingress Controllerの場合は、
$ kubectl create -f guestbook-ingress.yaml $ kubectl get ingress NAME HOSTS ADDRESS PORTS AGE guestbook-ingress gbook.example.com 10.183.107.11... 80 11s
さらにDNSなどの設定で、gbook.
」juju status
の
この状態でウェブブラウザーでgbook.
」

コンテナにログインする
juju ssh
を使うとコンテナが動いているホストdocker
コマンドを使ってコンテナにログインしたり、
さらにkubectl exec
を使うと、
$ kubectl exec Pod名 -it /bin/bash
Podが複数のコンテナから形成される場合は-c
」
単純にコンテナのログを取得したいだけであれば、kubectl logs
コマンドを使いましょう。
$ kubectl logs Pod名
kubectl
には、
コンテナの削除
不要になったコンテナはkubectl delete
」
$ kubectl delete -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
「kubectl delete pod Pod名
」kubectl delete service Service名
」
不要になったIngress設定も同様に削除しておきましょう。
$ kubectl delete -f guestbook-ingress.yaml
他のホストでJuju/Kubernetesをコントロールするには
JujuやKubernetesのAPIにアクセスするための認証情報は、kubectl
を実行したい場合もあるかもしれません。認証情報をバックアップする手段もありますが、~/.local/
」
Jujuの認証情報をコピーした先でKubernetesの認証情報を復元するには、juju
コマンドをインストールします。これについても素直にconjure-upパッケージをインストールする方法がいちばん簡単でしょう。ついでにkubectl
もインストールしておきましょう。
$ sudo snap install conjure-up --classic $ sudo snap install kubectl --classic
あとはKubernetesの認証情報を、
$ mkdir ~/.kube $ juju scp kubernetes-master/0:config ~/.kube/config $ kubectl cluster-info
ちなみに別のホストでkubectl
を実行するだけであれば、~/.kube/
」
Juju GUIを利用する
Jujuには
標準では無効化されていますが、
$ juju gui GUI 2.5.2 for model "admin/conjure-canonical-kubern-56a" is enabled at: https://juju.example.com:17070/gui/u/admin/conjure-canonical-kubern-56a Your login credential is: username: admin password: (パスワード)
アドレスや認証情報が表示されますので、
