sacloudプロダクトとの連携を強化したvagrant-sakuraの新機能
今日は最近開発が再開した、Vagrantで さくらのクラウドのサーバを操作するためのプロバイダーvagrant-sakuraについて、 最近追加された新機能についてご紹介します。
vagrant-sakuraって?
一言で言うと「Vagrantにさくらのクラウド上のサーバを操作する機能を追加するためのプラグイン」です。
基本的な機能は以下の記事が詳しいです。
vagrant-sakuraの開発再開
このvagrant-sakuraですが、元々はtsaharaさんが開発されたものです。
2016年5月にリリースされたv0.0.8以降は新規機能追加などの活動があまり行われていませんでしたが、
2018年7月にさくらのクラウド関連のユーザーコミュニティによるOSSを置いているGitHub上のオーガニゼーションsacloudにリポジトリ移転がなされ、
そこから開発を再開しいくつかの機能追加/改善を行ってきました。
sacloud配下にはVagrantをはじめ、PackerやTerraformといったHashiCorpプロダクトのさくらのクラウド向けプラグインや CLI Usacloudなどもあります。
vagrant-sakuraの新機能には、これらのプロダクトとの相互運用を楽にするための機能追加なども含まれています。
ということで早速新機能を紹介していきます。
sacloud/vagrant-sakuraの新機能
本日(2018/9/10)リリースした vagrant-sakura v0.1.0時点では以下のような機能が追加されています。
- 環境変数
SAKURACLOUD_xxx
からのAPIキーの読み込み機能 - Usacloudの設定ファイル(APIキー)の読み込み機能
- パケットフィルター/スタートアップスクリプト指定機能
- コピー元アーカイブを種別(
os_type
パラメータ)で指定する機能 - OSの再インストール機能
順にみていきます。
環境変数 SAKURACLOUD_xxx
からのAPIキーの読み込み機能
SAKURACLOUD_ACCESS_TOKEN
: APIアクセストークンSAKURACLOUD_ACCESS_TOKEN_SECRET
: APIアクセスシークレットSAKURACLOUD_ZONE
: 操作対象ゾーン
これまでもSAKURA_ACCESS_TOKEN
といった環境変数が利用できましたが、これはvagrant-sakura独自のものでした。
追加された環境変数はUsacloudやTerraform for さくらのクラウド、Packer for さくらのクラウドといったSacloudプロダクトと共通で利用できるもので、
既にSacloudのプロダクトをご利用中の方であれば設定していることの多い環境変数です。
Vagrantで開発してたものをPackerでパッケージングし、Terraformでproduction環境に反映、運用保守はUsacloudでといった場合に それぞれでAPIキーの設定をせずとも共通の環境変数が利用できるようになったのは地味ですが意外と便利です。
Usacloudの設定ファイル(APIキー)の読み込み機能
同じくAPIキーの設定関連の機能ですが、APIキーをUsacloudの設定ファイルから自動で読み込んでくれる機能です。 Usacloudは複数のアカウントを使い分けられるようにAPIキーを設定ファイルに複数保存しておき、必要に応じて切り替えて使う機能を持っています。
今回追加された機能により、この設定ファイルをvagrantでも認識できるようになりました。
前述の機能と合わせるとAPIキーの設定は以下3通りの設定方法があることになります。
複数の方法でAPIキーを指定した場合は、より上に記載されている方法が優先されます。
使い方
VagrantfileにAPIキーの指定を行っていない場合は自動的にUsacloud設定ファイルを読み込むようになっています。
Usacloudで複数のAPIキー設定がある場合はカレントの設定を利用しようとします。
(以下の例だとuser01
の設定を利用する)
# 登録されているAPIキー設定(コンフィグ)を一覧表示 $ usacloud config list default user01 user02 # 現在利用しているAPIキー設定を表示 $ usacloud config current user01
Usacloud側でカレントの設定を変更するとVagrant側も追随するようになっています。
# Usacloudでカレントを変更 $ usacloud config use user02 Current profile: "user02" # 現在利用しているAPIキー設定を表示 $ usacloud config current user02
Usacloudではconfig edit
機能で対話的にAPIキーの設定が可能となっています。複数のAPIキーを利用している場合は手軽に切り替えができるようになりますのでぜひご利用ください。
パケットフィルター/スタートアップスクリプト指定機能
結構要望があった機能です。サーバ作成時にパケットフィルタやスタートアップスクリプトを指定可能となっています。
使い方
VagrantfileにてそれぞれにIDを指定すればOKです。
Vagrant.configure("2") do |config| # ... config.vm.provider :sakura do |sakura, override| # ... #============================================ # スタートアップスクリプトの指定 #============================================ # IDで指定 sakura.startup_scripts = 123456789012 # 文字列でもOK # sakura.startup_scripts = "123456789012" # 複数指定する場合 # sakura.startup_scripts = [123456789012, xxx, yyy, ...] #============================================ # パケットフィルタの指定 #============================================ sakura.packet_filter = 123456789012 end end
コピー元アーカイブを種別(os_type
パラメータ)で指定する機能
これまではサーバ作成時にコピー元アーカイブのIDを指定する必要がありました。
Vagrant.configure("2") do |config| config.vm.box = "dummy" config.ssh.username = "root" config.vm.provider :sakura do |sakura| sakura.disk_source_archive = 111111111111 # アーカイブのIDを指定 sakura.use_insecure_key = true end end
アーカイブのIDを知るにはコントロールパネルで調べたり、vagrant-sakuraのsakura-list-id
コマンドやUsacloudでアーカイブを検索して調べるという作業が必要でした。
さくらのクラウドではいくつかのOSについてはパブリックアーカイブ
というアーカイブが提供されているため、これらのIDを指定することでサーバの作成が可能となっています。
しかし、厄介なことにパブリックアーカイブのIDはゾーンごとに異なります。
例えば石狩第2ゾーンでのCentOS7と東京第1ゾーンでのCentOS7では違うIDとなっています。
また、同じCentOS7でも、さくらのクラウド側でアップデートが行われることがあり、その際にはIDが変更されることが多いです。
なのでIDを直接指定する形だとある日突然サーバの作成が行えなくなるといったことが発生していました。
UsacloudやTerraform、Packerでも同様の問題が発生しますが、これらのプロダクトではos_type
というOSの種別を指定できる機能で対応しています。
これは、centos
やubuntu
といったOS種別を指定すると種別に対応する各ゾーンの最新安定板のアーカイブのIDを検索し設定してくれるものです。
例えばUbuntuパブリックアーカイブの場合は16.04.4や18.04といった複数のバージョンが存在するため、それらの中から最新安定板を選ぶようにしています
vagrant-sakuraでは以下の値が指定可能です。
ubuntu
(デフォルト)centos
centos6
debian
coreos
freebsd
rancheros
パブリックアーカイブを利用する場合はos_type
を用い、自分で作成したアーカイブ(マイアーカイブ)を利用する場合はdisk_source_archive
を利用するという使い分けがオススメです。
OSの再インストール機能
従来はvagrant-sakuraで作成したサーバのOS再インストールを行う場合は、一旦destroy
してから再度up
する必要がありました。
こうするとさくらのクラウドで割り当てられたグローバルIPが変更されてしまうことがあり、DNS登録していた場合はそちらも変更しなければいけないケースがありました。
そこで今回作成されたサーバはそのまま(もちろん割り当てられたグローバルIPは確保したまま)でOSの再インストールを行うためのサブコマンドを追加しました。
使い方
sakura-reinstall
というコマンドを実行することでOS再インストールが行えます。
$ vagrant sakura-reinstall
Ansibleなどのサーバ構成管理ツールを試行錯誤しながら作る際に便利だと思います。
終わりに
ということで、今後も様々な機能追加/改善を行う予定です。 質問やバグ報告、ご要望などはぜひGitHubにIssue/PRを投げてください。
なお、Sacloudプロダクトの使い方などが質問できるSlackワークスペースもあります。
どなたでも参加可能になっていますので、操作方法などでお困りの方はぜひご参加ください。
以上です。
TerraformのArukasプロバイダー再始動!!
TerraformのArukasプロバイダーが正式サービス版になって復活!
TerraformのArukasプロバイダーのArukas正式サービス版に対応したバージョン v1.0.0
をリリースしました。
Arukasプロバイダー復活までの経緯
ArukasプロバイダーはHashiCorp社がコードレビュー/テスト/リリース(配布)を行う、いわゆる公式プロバイダーとして2017年1月にリリースされました。
Arukasのβサービスが一旦終了…
しかし、当時のArukasはβサービスというお試し期間中であり、βサービスは2017年7月31日をもって一旦終了となりました。
これに伴い、Arukasプロバイダーについても更新を一時停止していました。
復活のArukas!
Arukasはその後半年近い充電?期間を経て2018年2月にβサービスを再開、翌3月には正式サービスとして課金が開始されました。
Arukasプロバイダーについてもすぐに復活させたかったのですが、当時と公式プロバイダーの公開手順などが変更されていたり、 ArukasのAPIがβサービスの時点から若干変更されていたりと様々な事情が重なった結果少々時間がかかってしまいました。
公式プロバイダーの公開までの手順はそのうち気が向いたら記事にします。
時間を見つけては細々と復活に向けた活動を行なってきましたが、とうとう先日(2018/9/4) Arukasプロバイダーの更新版である v1.0.0
のリリースを行うことができました。
Arukasが正式サービスとなったことでコンテナ起動までの待ち時間が短くなったりと、より安定したパワフルなサービスになったと思います。
今回は改めてArukas正式サービスに対応したArukasプロバイダー v1.0.0
の利用方法を紹介します。
Arukasプロバイダー(v1.0.0
)の使い方
AWSやAzure(RM)、GCPなどといった多くのTerraformプロバイダーと同様の手順で利用可能です。
すなわち、Terraform自体のインストール、ArukasのAPIキー発行&環境変数の設定、tfファイルの作成〜適用という流れです。
順に見ていきます。
Terraformのインストール
以下のページからTerraformの実行ファイルをダウンロードし、PATHの通った場所に置きます。
必要に応じて実行権を付与しておきます。
Arukas APIキー発行 & 環境変数への設定
ArukasのコントロールパネルからAPIキーを発行します。 以下の記事などが参考になると思います。
# APIキーを環境変数に設定 $ export ARUKAS_JSON_API_TOKEN=<発行したAPIキーのトークン> $ export ARUKAS_JSON_API_SECRET=<発行したAPIキーのシークレット>
tfファイル作成
次にtfファイルを作成します。以下のようなtfファイルを作成しておきます。
resource "arukas_container" "foobar" { name = "arukas-provider-example" image = "nginx:latest" ports = { protocol = "tcp" number = "80" } }
この例ではDockerHub上のnginx:latest
イメージを利用してArukas上にコンテナを起動します。
なお、Arukasには料金プランが4つ(Free、Hobby、Standard-1、Standard-2)とありますが、 tfファイルにプランを明示しなかった場合、デフォルトで無料のFreeプランが利用されるようになっています。 実際に利用する際は適切なプランをtfファイルにて指定してください。
tfファイルに記載できる項目については以下のArukasプロバイダーのドキュメントを参照してください。
Note: Freeプランでは起動できるインスタンスが1に制限されています。
もしすでにインスタンスが存在する場合は後ほどterraform apply
を実行する際にエラーとなりますのでご注意ください。
Note: v1.0.0以前のArukasプロバイダーを使われていた方はtfファイルの書き方が若干変更されている点にご注意ください。 変更点はCHANGELOGに記載されています。
適用
あとは通常のTerraformでの適用手順となります。
terraform init
を実行することで必要なプロバイダーがダウンロードされます。
その後terraform apply
を実行することでインフラの展開が行われます。
$ terraform init $ terraform apply
確認
無事に展開されると以下のようにArukas上にコンテナが起動しているのが確認できるはずです。
Arukasのβサービス中はコンテナの起動まで結構時間がかかることがありましたが、正式サービスになってからは割とサクサク動いている感じですね。
確認したら忘れずにterraform destroy
を実行して削除しておきましょう。
終わりに
ということで今回は復活したArukasプロバイダーについて紹介しました。
手軽に利用できますのでぜひご利用ください!!
以上です。
「Rio」- 古き良きDockerのUXをモダンなクラウドネイティブソフトウェア達に
2018/10/1更新:
- v0.0.3を使うように修正
- 文言を微修正
Twitterにて「Rio」のデモ動画が発表された
つい先日(2018/8/7)、TwitterにてRancher社のDarren Shepherd氏がRioというプロダクトのデモ動画を発表してました。
Early Preview of Rio, a new end-to-end container tool from Rancher. Basically this is what I've been doing for that last couple months. https://t.co/MQ8dwaaNT1
— Darren Shepherd (@ibuildthecloud) August 6, 2018
前々から氏のツイートなどでRioの開発をしてる旨を匂わせていましたがいよいよ動く段階まできたようです。
Rancher 2.0の開発もまだまだ継続してる中、新しいプロダクトはしばらく先じゃないかと思ってましたが 思っていたより早い段階で動く姿を見れたので結構驚きました。
もうGitHubからダウンロードできる状態でしたので早速動かしてみました。
注: 以降は先のデモ動画の内容をなぞっていっただけのものです。 動画を見た方は多分この先読まなくてOKです。
「Rio」って何?
Rancher社が開発している、新しいコンテナツールとのことです。
READMEでは以下のように紹介されています。
- Simple, fun, end-to-end container experience
- Cloud Native Container Distribution
Rio is a user oriented end-to-end container solution with a focus on keeping containers simple and combating the current trend of complexity.
It's kept fun and simple through it's familiar and opinionated user experience.
Additionally, Rio is a "Cloud Native Container Distribution" meaning is includes builtin Cloud Native technologies such as Kubernetes, Istio, Containerd, etc.
so that the user need not be an expert in installing, using, and maintaining these system.
Cloud Native Container Distribution
と掲げており、KubernetesやIstioをはじめとするCloud Nativeなプロダクトの組み合わせを
シンプルなフロントエンドを通じて利用できるようになっています。
どんなプロダクトが含まれるかはデモ動画の中で紹介されていました(もちろんGitHub上にも書かれてます)。
現在は基本となるコンテナランタイム(containerd
)、オーケストレーション(kubernetes
)、ネットワーク(flannel
)、サービスメッシュ(istio
)が組み込まれており、
今後はストレージ関連としてRancher社のLonghorn
、モニタリングにPrometheus
、イメージのビルドにBuildKit
、イメージスキャンにCoreOSのClair
なども組み込む予定のようです。
ということで早速動かしてみます。
Rioのインストール
Rioは既存のKubernetes(laptopの場合はMinikube or Docker for Win/Mac推奨とのこと)、またはLinux(4.x+)で動作するとのことです。
Prerequisites: If you want to run this on your laptop, then Minikube or Docker for Mac/Windows is recommended. If you don't have those then you need to run a Linux VM (or Linux itself, come to the darkside). We will make this easier in the future. Otherwise you can run this easily with any modern Linux server, nothing is needed to be installed except the kernel.
今回はクラウド上に立てたUbuntuで動かしてみます。
Rio本体以外はインストールする必要はないのですが、内部の調査をしたい方はkubectl
くらいは入れておくと便利です。
余談1: Linux上でスタンドアロンで動かした場合はembededなk8sを起動して動作する、Rancher 2.0などと同じような動きをしてました
余談2: Docker for Macで試してたのですが外部からのアクセスができない箇所があって調べるのめんどくさくなったのでUbuntuにしました
まずRioの実行ファイルをGitHubからダウンロードし展開しておきます。
# rio v0.0.3のダウンロード curl -L -o rio.tgz https://github.com/rancher/rio/releases/download/v0.0.3/rio-v0.0.3-linux-amd64.tar.gz # 展開 tar zxvf rio.tgz # PATHの通った場所に移動 mv rio-v0.0.3-linux-amd64/rio /usr/local/bin/
続いてRioのコンポーネント群を起動します。 今回はRioをスタンドアロンで起動します。もし既存のKubernetesクラスタを利用する場合はGitHub上のREADMEを参照してください。
# Rioサーバの起動(embeded-k8sモード) $ sudo rio server
少し待つとコンソール上に以下のようにログイン用のトークンが出力されるはずです。 これをコピペして別のターミナルを開き実行しましょう。
INFO[0010] To use CLI: rio login -s https://133.242.228.115:7443 -t xxxxxxxxxxxx::admin:xxxxxxxxxxxxxxxx
# 起動したRioサーバへログイン(先ほどの表示をコピペ) $ rio login -s https://133.242.228.115:7443 -t xxxxxxxxxxxx::admin:xxxxxxxxxxxxxxxx
なお、rio
コマンドをrootユーザで実行する場合はrio login
は不要とのことです。
以降はrio
コマンドで様々な操作が可能になっているはずです。
余談: Rioをスタンドアロンで起動した場合のkubectlの使い方
=== 2018/8/8 追記
rio -h
には出てこないですが、よく見たらrio kubectl
というサブコマンドがあるっぽいです。
なのでわざわざkubectl
をインストールしなくても良さそうですね。
=== 追記ここまで
Rioをスタンドアロンで起動するとRancher 2.0などと同じくembededモードでk8sを起動して利用するようになってました。
この場合、/var/lib/rancher/rio/server/cred/kubeconfig.yaml
にkubeconfigが出力されてますのでこれを使えばkubectl
も使えるようになります。
Rioを使うのであればkubectl
は不要ですがやっぱりIstioのCRがどうなってるの?とか気になりますよね?そんな方向けの設定です。
# embededモードで起動しているk8sに接続するためのkubeconfigを環境変数に指定 $ export KUBECONFIG=/var/lib/rancher/rio/server/cred/kubeconfig.yaml # kubectlが使えるはず $ kubectl get cs NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok $ kubectl get nodes #なんかバージョン表示がバグってるし NAME STATUS ROLES AGE VERSION node-conf-test Ready <none> 10m v0.0.0-master+$Format:%h$
Rioでコンテナを起動してみる
まずは動かしてみます。
docker run
するような感覚でrio run
を実行することでコンテナの起動が可能です。
$ rio run --name foobar nginx # --nameは省略可能
起動したか確認してみます。確認はrio ps
を実行します。
$ rio ps NAME IMAGE CREATED SCALE STATE ENDPOINT DETAIL foobar nginx 10 seconds ago 1 active
何か起動してるっぽいですね。 RioではDockerCompose風にServiceという単位でコンテナ(群)を管理しています。
Service
The main unit that is being dealt with in Rio are services. Services are just a collection of containers that provide a similar function. When you run containers in Rio you are really creating a Scalable Service. rio run and rio create will create a service. You can later scale that service with rio scale. Services are assigned a DNS name so that group of containers can be accessed from other services.
rio ps
で表示されるのはServiceの一覧ということですね。
さらにrio ps
に引数としてサービス名を与えることで詳細を確認可能です。
# サービスの詳細を確認 $ rio ps foobar NAME IMAGE CREATED NODE IP STATE DETAIL foobar/7946c5787c-l49rk nginx About a minute ago node-conf-test 10.1.0.8 running
コンテナへのattachやexecも可能です。
# コンテナ内でbashを実行(--interactive + --ttyオプションを指定 = dockerと同じ) $ rio exec -it foobar bash # *** ここはコンテナ内 *** root@foobar-7946c5787c-l49rk:/# # 以下のようにサービス名/コンテナ名まで指定してもOK # rio exec -it foobar/7946c5787c-l49rk bash
次にスケールアウトしてみます。
$ rio scale foobar=3 # 確認 $ rio ps NAME IMAGE CREATED SCALE STATE ENDPOINT DETAIL foobar nginx 3 minutes ago 3 active $ rio ps foobar NAME IMAGE CREATED NODE IP STATE DETAIL foobar/7946c5787c-qqdkr nginx 21 seconds ago node-conf-test 10.1.0.9 running foobar/7946c5787c-snclf nginx 21 seconds ago node-conf-test 10.1.0.10 running foobar/7946c5787c-l49rk nginx 3 minutes ago node-conf-test 10.1.0.8 running
端々がDockerっぽいですね。
他にもinspectといったおなじみのコマンドもありますので詳細はrio -h
を実行して確認してみてください。
次に進む前に一旦起動したサービスを削除しておきます。
$ rio rm foobar
注: 今回は説明を簡単にするためにWorkSpaceやStackといった概念をすっ飛ばしてます。 詳細はGitHub上のConceptsを確認しておいてください。
Rioでサービスメッシュを体験してみる
RioにはIstioが組み込まれており簡単に利用できるようになっているようです。 ここでは
- ステージング環境のデプロイ
- カナリアリリース
- ステージング環境を本番にプロモート
という流れで進めてみます。
サービスの起動 + 外部への公開
まずはサービスを起動し外部からアクセス可能にします。
ここではRioのREADME.mdに乗っているサンプルであるibuildthecloud/demo:v1
というイメージを利用してます。
このイメージはHTTPでアクセスするとHello World
という文字列を返すという単純なものです。
# -p(publish) オプションで80番ポートを公開 $ rio run -p 80/http --name rio-demo --scale=3 ibuildthecloud/demo:v1
確認しておきます。
$ rio ps NAME IMAGE CREATED SCALE STATE ENDPOINT DETAIL rio-demo ibuildthecloud/demo:v1 32 seconds ago 3 active http://rio-demo.default.cr2ch1.lb.rancher.cloud
なんだかエンドポイントとしてhttp://rio-demo.default.cr2ch1.lb.rancher.cloud
というのが割り当てられてますね。
これはRioが割り当ててくれたもので、ノードのIPアドレスに解決されるようになってます。
# ノードのIPアドレス(この例では133.242.228.115/24) $ ip a show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 9c:a3:ba:30:60:dd brd ff:ff:ff:ff:ff:ff inet 133.242.228.115/24 brd 133.242.228.255 scope global eth0 valid_lft forever preferred_lft forever # Aレコードを確認してみる $ dig rio-demo.default.cr2ch1.lb.rancher.cloud. A ; <<>> DiG 9.10.3-P4-Ubuntu <<>> rio-demo.default.cr2ch1.lb.rancher.cloud. A ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45513 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;rio-demo.default.cr2ch1.lb.rancher.cloud. IN A ;; ANSWER SECTION: rio-demo.default.cr2ch1.lb.rancher.cloud. 60 IN A 133.242.228.115 ;; Query time: 147 msec ;; SERVER: 133.242.0.3#53(133.242.0.3) ;; WHEN: Wed Aug 08 09:35:09 UTC 2018 ;; MSG SIZE rcvd: 85
エンドポイントのホスト名は<ServiceName>.<StackName>.<ClusterID>.<ROOT domain>
となってます。
RootドメインはRioをスタンドアロンで起動した場合はlb.rancher.cloud
、Docker for Macなどの場合は127.0.0.1.nip.io
が使われるようです。
この辺の処理は以下のあたりにありますので興味のある方はソース追ってみてください。
- https://github.com/rancher/rio/blob/master/controllers/backend/pod/pod_controller.go
- https://github.com/rancher/rancher/tree/7e581517d1d3f20a440a65abcdfcc43e58062156/pkg/controllers/user/approuter
そしてRioが裏でIstioをいい感じに設定してくれるようになっており、このエンドポイントを使えばサービスにアクセスできるようになっています。
(Istioがどうなってるのか気になる方は記事の末尾の「おまけ: 段階ごとのkubectlなどの詳細」を参照してください)
起動したサービスにアクセスしてみる
ということで確認してみましょう。
$ curl -s http://rio-demo.default.cr2ch1.lb.rancher.cloud Hello World
無事にHello World
と表示されるはずです。
ステージング環境のデプロイ
次にこのサービスを更新したイメージを用意し、ステージング環境をデプロイしてみます。
ここでは:v3
というタグをつけたイメージを更新したイメージとして準備しています。
$ rio stage --image=ibuildthecloud/demo:v3 rio-demo:v3
psもみておきましょう。
$ rio ps NAME IMAGE CREATED SCALE STATE ENDPOINT DETAIL rio-demo ibuildthecloud/demo:v1 32 minutes ago 3 active http://rio-demo.default.cr2ch1.lb.rancher.cloud rio-demo:v3 ibuildthecloud/demo:v3 32 minutes ago 3 active http://rio-demo-v3.default.cr2ch1.lb.rancher.cloud
rio-demo:v3
というサービスが作成され、専用のエンドポイントが割り当てられています。
このエンドポイントを使ってステージング環境での動作確認が可能です。
$ curl -s http://rio-demo-v3.default.cr2ch1.lb.rancher.cloud Hello World v3
カナリアリリース
ステージング環境での動作確認が済んだらカナリアリリースしてみます。
まずは元のサービス(この例だとhttp://rio-demo.default.cr2ch1.lb.rancher.cloud
)にアクセスした際、20%の確率でv3にアクセスされるようにしてみます。
$ rio weight rio-demo:v3=20%
その後元のサービスのエンドポイントにアクセスすると時折v3の方にアクセスするようになっています。
# URLは同じであることに注目 $ curl -s http://rio-demo.default.cr2ch1.lb.rancher.cloud Hello World $ curl -s http://rio-demo.default.cr2ch1.lb.rancher.cloud Hello World v3
ステージング -> 本番へプロモート
カナリアリリースの結果が良好だったのでいよいよステージング環境を本番環境に昇格させます。
$ rio promote rio-demo:v3
その後はv3の方にしかアクセスされなくなっています。
$ curl -s http://rio-demo.default.cr2ch1.lb.rancher.cloud Hello World v3
psをみてみるとステージング環境がなくなり、元のサービスと入れ替わっているのが確認できます。
$ rio ps NAME IMAGE CREATED SCALE STATE ENDPOINT DETAIL rio-demo ibuildthecloud/demo:v3 8 minutes ago 3 active http://rio-demo.default.cr2ch1.lb.rancher.cloud
ということでサービスメッシュ周りの確認をしてみました。
終わりに
Rancher社が発表した新しいツール「Rio」を試してみました。
Docker風の操作感なのでもともとDockerコマンドに慣れていた方には違和感なく取り組めそうな気がします。
今のところk8s+istioのラッパーといった感が強いですが、今後組み込みのプロダクトは順次増えていくはずです。
なお、現状ではまだまだ開発中ということもあり動作が不安定です。 随所にバグもみられますので今は雰囲気を感じてみる程度の使い方となります。
今後に期待しましょう。
以上です。
おまけ: 段階ごとのkubectlなどの詳細
ここからは各操作ごとにkubectlを実行してみた結果を貼っておきます。
どのようにistioを操作しているのかなどを見てフムフムしたい方向けです。
長いのでgistに貼っておきます。
- 01. Rioインストール直後のリソースたち(
kubectl get all
) - 02. Rioインストール直後のCRDs
- 03. Run(-pオプションあり)でサービスを公開した直後のリソースたち
- 04. Run(-pオプションあり)でサービスを公開した直後のIstio関連CR
- 05. Stageした後のリソースたち
- 06. Stageした後のIstio関連CR
- 07. カナリアリリース(weight)時のCR
途中で面倒になったので全ての変化を網羅したわけではないのでご注意ください。
Kubernetes完全ガイド (impress top gear)
- 作者: 青山真也
- 出版社/メーカー: インプレス
- 発売日: 2018/09/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
- 作者: 山田明憲
- 出版社/メーカー: 技術評論社
- 発売日: 2018/08/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
RKEでAWS上にKubernetes(v1.10)をデプロイする
Rancher Blogに新しい記事(RKE+AWS)が投稿されてた
今月半ばにRancher Labsのブログに以下の記事が投稿されていました。
Rancher Blog: How To Deploy Kubernetes Clusters On AWS Using RKE
AWS上にRKEを用いてKubernetesクラスタを構築するという内容です。
でもRKEの最新版だと動かない…
手順が丁寧に書かれていてわかりやすい内容なのですが、利用しているRKEのバージョン(v0.1.5)が古く、最新版を利用するとうまく動きませんでした。
そこで、最新版できちんと動かすために必要な作業についてこの記事にまとめてみました。
ついでにTerraformでコード化しました
記事を書くついでにこの構成を手軽に試せるようにTerraformとTerraformのRKEプロバイダーを利用してコマンド一発で構築できるようにもしました。
ということで早速RKEの最新版での動かし方をみていきます。
RKE(v0.1.7) + AWSでKubernetes
TL;DR
- 基本はRancher Blogに記載の手順でOK
- RKEの最新版であるv0.1.7はデフォルトではKubernetes v1.10がデプロイされる
- Kubernetes v1.10でAWS向けのCloud Controller Managerを利用する場合、ClusterIDが指定されていないとkubeletの起動に失敗する
- なので以下リソースにClusterID用のタグを付与すればOK
- サブネット
- セキュリティグループ
- EC2インスタンス
解説
RKEの最新版であるv0.1.7はデフォルトではKubernetes v1.10がデプロイされる
まず、Rancher Blogの該当記事で利用されているRKEのバージョンはv0.1.5です。
このバージョンではrke up
を実行すると(デフォルトでは)Kubernetes v1.8がデプロイされていました。
なので、後述するClusterIDが設定されていなくても問題なく利用できていたようですね。
Kubernetes v1.10でAWS向けのCloud-Controller-Managerを利用する場合、ClusterIDが指定されていないとkubeletの起動に失敗する
Kubernetes v1.10のCHANGE LOGを見ると、以下のPRによるものです。
対応: 各リソースにClusterID用のタグを付与する
ということで、Kubernetes v1.10を使う場合はClusterIDを指定すればOKということですね。
タグの付け方についてはRancherのドキュメントに記載がありました。
Rancher docs: Kubernetes - Cloud Providers / Configuring the ClusterID
このドキュメントによると、
- サブネット
- セキュリティグループ
- EC2インスタンス
に対してkubernetes.io/cluster/CLUSTERID=owned
のようなタグをつければ良いとのことでした。
IDはCLUSTERID
の部分を任意の値に書き換えることで設定可能です。
Terraform + RKEプロバイダーで構築する
ClusterID用のタグをつけるのは割と面倒な作業なのでTerraformでコード化しました。
以下のリポジトリでコードを公開しています。
なお、このコードではRKEプロバイダーを利用して、RKEでのKubernetesクラスタ構築までを一気に行なっています。
RKEプロバイダーについては以下の記事を参照ください。
以下コードのポイントを解説しておきます。
IAMプロファイルの作成
この辺りは以下のtfファイルにまとめています。
https://github.com/yamamoto-febc/k8s_on_aws_with_terraform/blob/master/aws/iam.tf
ClusterID用のタグ付与
サブネット/セキュリティグループ/EC2インスタンスに対してタグを指定しています。
以下のような感じです。
# タグの定義 locals { cluster_id_tag = "${map("kubernetes.io/cluster/${var.cluster_id}", "owned")}" } # 利用するリージョン内の全AZのデフォルトサブネットを対象にClusterID用のタグを付与 data "aws_availability_zones" "az" {} resource "aws_default_subnet" "default" { availability_zone = "${data.aws_availability_zones.az.names[count.index]}" count = "${length(data.aws_availability_zones.az.names)}" tags = "${local.cluster_id_tag}" #タグの指定 }
サブネットについてはデフォルトサブネットに対してタグ付与しています。
また、セキュリティグループについてはRancher Blogと同じく全許可のルールとしています。
ノードのプロビジョニング
Dockerをインストールして、SSH接続の際に利用するユーザー(記事ではubuntu
)をDockerグループに入れる必要があります。
tfファイル上はremote-exec
を利用して以下のようにしています。
resource "aws_instance" "rke-node" { count = 4 ami = "${data.aws_ami.ubuntu.id}" instance_type = "${var.instance_type}" key_name = "${aws_key_pair.rke-node-key.id}" iam_instance_profile = "${aws_iam_instance_profile.rke-aws.name}" vpc_security_group_ids = ["${aws_security_group.allow-all.id}"] tags = "${local.cluster_id_tag}" provisioner "remote-exec" { connection { user = "ubuntu" private_key = "${tls_private_key.node-key.private_key_pem}" } # Dockerのインストールとdockerグループへの追加 inline = [ "curl releases.rancher.com/install-docker/1.12.sh | bash", "sudo usermod -a -G docker ubuntu", ] } }
なお、インスタンスタイプは記事ではt2.large
が推奨されていますが、軽く試すだけならt2.micro
で十分でした。
(tfファイル上はデフォルトでt2.micro
にしました)
RKEの実行
RKEの実行はRKEプロバイダーに任せます。
以下のようなtfファイルとなります。
module "nodes" { source = "./aws" } resource rke_cluster "cluster" { cloud_provider { name = "aws" } nodes = [ { address = "${module.nodes.addresses[0]}" user = "${module.nodes.ssh_username}" ssh_key = "${module.nodes.private_key}" role = ["controlplane", "etcd"] }, { address = "${module.nodes.addresses[1]}" user = "${module.nodes.ssh_username}" ssh_key = "${module.nodes.private_key}" role = ["worker"] }, { address = "${module.nodes.addresses[2]}" user = "${module.nodes.ssh_username}" ssh_key = "${module.nodes.private_key}" role = ["worker"] }, { address = "${module.nodes.addresses[3]}" user = "${module.nodes.ssh_username}" ssh_key = "${module.nodes.private_key}" role = ["worker"] }, ] }
RKEコマンドを直接実行する場合は、rke up
実行後にカレントディレクトリにkube_config_cluster.yml
ファイルが作成されます。
RKEプロバイダーの場合はデフォルトでは作成されませんので、以下のようにlocal-file
機能でファイル出力しています。
resource "local_file" "kube_cluster_yaml" { filename = "./kube_config_cluster.yml" content = "${rke_cluster.cluster.kube_config_yaml}" }
terraform apply
実行後にexport KUBECONFIG=$PWD/kube\_config\_cluster.yml
を実行しておけばkubectl
が利用できるはずです。
後はRancher Blogの内容をそのまま進めていけるはずです。
ということでRancher Blogの補足をしつつ、Terraform + RKEプロバイダーで環境構築してみました。
なおこの構成は全通信許可などのガバガバ設定になっていますので検証などでのみ利用してくださいね!!
以上です。
Terraform + RKEでKubernetesクラスタ構築 - TerraformのRKEプロバイダー
2018/5/18に東京で開催されたRancher2.0リリースパーティで以下のLTをさせていただきました。
このLTで発表したTerraformのRKEプロバイダーについてご紹介いたします。
その前に: RKE(Rancher Kubernetes Engine)とは?
RKEとは、一言で言うと「Kubernetesクラスタのデプロイツール」です。
kubernetesクラスタのデプロイツールとしてはkubeadm
やkops
といったものもありますが、それらと比較するとRKEは以下のような特徴があります。
- 対象ノードに外部からSSH接続してプロビジョニングを行う
- kubernetesの各種コンポーネント(etcdやapiserverなど)をDockerコンテナとして起動する
- 最初からHAなクラスタを構築可能
RKEの使い方
ノードの準備
まずk8sクラスタをプロビジョニングするノードを用意しておく必要があります。 以下の条件を満たすノードを用意します。
Requirements
- Docker versions 1.11.2 up to 1.13.1 and 17.03.x are validated for Kubernetes versions 1.8, 1.9 and 1.10
- OpenSSH 7.0+ must be installed on each node for stream local forwarding to work.
- The SSH user used for node access must be a member of the docker group.
- Ports 6443, 2379, and 2380 should be opened between cluster nodes.
- Swap disabled on worker nodes.
RKEのドキュメントには記載されていませんが、以下のポートも必要に応じて開けておく必要があります。
(初回のみ)RKEのインストール
続いてRKEのインストールを行います。 RKEはGo言語で書かれており、実行ファイルをダウンロードして実行権を付与するだけでインストールできます。
以下のRKEのリリースページから各プラットフォーム向けのバイナリをダウンロードし実行権を付与しておきます。
https://github.com/rancher/rke/releases/latest
※当記事執筆時点での最新バージョンはv0.1.7
です。
定義ファイル(cluster.yml
)の作成
RKEではどのノードをプロビジョニングするかといった設定をcluster.yml
という定義ファイルで指定します。
(定義ファイル名はデフォルトではcluster.yml
ですが、別の名前でもOKです。その場合はrke up
時に--config
オプションを指定します)
最小の定義ファイルは以下のようになります。
nodes: - address: <用意したノードのIPアドレス または ホスト名> user: <SSH接続用のユーザー名> role: [controlplane,worker,etcd]
nodes
にはプロビジョニング対象となるノードをリストで指定します。
ここでは指定していませんが、SSH用にパスワードや秘密鍵、SSHエージェント利用有無なども指定可能です。
(RKE v0.1.7以降は踏み台ホスト(bastion_host
)も指定可能)
その他の指定できる項目についてはGitHub上にcluster.ymlのサンプルが公開されていますのでそちらを参照してみてください。
https://github.com/rancher/rke/blob/v0.1.7/cluster.yml
rke up
コマンドの実行
定義ファイルが用意できたらrke up
コマンドを実行することでk8sクラスタのプロビジョニングが行えます。
rke up
プロビジョニングが正常に終わるとkube_config_cluster.yml
というファイルが作成されます。
kubectl
コマンドを利用する場合はこのファイルを利用するようにします。
~/.kube/config
を上書きするか以下のようにすればOKです。
# 環境変数を使う場合
$ export KUBECONFIG=${PWD}/kube_config_cluster.yml
$ kubectl get cs
# --kubeconfigオプションを使う場合
$ kubectl --kubeconfig kube_config_cluster.yml get nodes
RKEについてはRancher Meetup大阪で発表したことがありますので、詳細はこちらも参照ください。
TerraformのRKEプロバイダー
ここまで見てきたように、RKEでクラスタをプロビジョニングするには
- あらかじめノードを用意し
- 定義ファイルを作成し
rke up
実行
というステップを踏む必要があります。
この辺を毎回手作業で行うのは大変なので、RKEをTerraformから直接扱えるようにしたのがTerraformのRKEプロバイダーです。
以下のようなtfファイルを用意してterraform apply
を実行することで、RKEでクラスタのプロビジョニングが行えます。
resource rke_cluster "cluster" { nodes = [ { address = "<用意したノードのIPアドレス または ホスト名>" user = "<SSH接続用のユーザー名>" role = ["controlplane", "worker", "etcd"] } ] }
RKEの定義ファイル(cluster.yml
)に書く内容をtfファイルに書けるようにしています。
tfファイルに書けるということは、${}
記法などのTerraformの強力な機能をそのまま利用できるということです。
例えばEC2インスタンスを作成し、そこに対しRKEでk8sクラスタのプロビジョニングを行いたい場合は以下のように書けます。
# EC2インスタンス(Ubuntu) resource "aws_instance" "rke-node" { // [...] ami = "${data.aws_ami.ubuntu.id}" // Dockerのインストール & ubuntuユーザーをdockerグループに追加 provisioner "remote-exec" { connection { user = "ubuntu" private_key = "${tls_private_key.node-key.private_key_pem}" } inline = [ "curl releases.rancher.com/install-docker/1.12.sh | bash", "sudo usermod -a -G docker ubuntu", ] } } # RKE resource rke_cluster "cluster" { nodes = [ { address = "${aws_instance.rke-node.public_dns}" user = "ubuntu" ssh_key = "${tls_private_key.node-key.private_key_pem}" role = ["controlplane", "etcd", "worker"] }, ] }
ここではノードとしてAWSを利用しましたが、DigitalOceanやさくらのクラウドなどのTerraformが対応しているプラットフォームであればもちろん利用可能です。
RKEプロダイバーの便利機能
kubeconfigファイルの出力
以下のようにlocal_file
を利用すればrkeコマンド実行時と同じくkube_config_cluster.yml
を取得できます。
resource "local_file" "kube_cluster_yaml" { filename = "${path.root}/kube_config_cluster.yml" content = "${rke_cluster.cluster.kube_config_yaml}" }
TerraformのKubernetesプロバイダーとの連携
TerraformのKubernetesプロバイダーと簡単に連携できるように認証情報などを参照可能な機能も用意しています。 以下のようにすることでRKEで作成したk8sクラスタの認証情報をKubernetesプロダイバーで利用可能です。
provider "kubernetes" { host = "${rke_cluster.cluster.api_server_url}" username = "${rke_cluster.cluster.kube_admin_user}" client_certificate = "${rke_cluster.cluster.client_cert}" client_key = "${rke_cluster.cluster.client_key}" cluster_ca_certificate = "${rke_cluster.cluster.ca_crt}" # デフォルトでは~/.kube/configをロードしてしまうので # 必要に応じて以下コメントアウトを解除 # load_config_file = false } # kubernetesプロバイダーを利用してネームスケースを作成する例 resource "kubernetes_namespace" "example" { metadata { name = "terraform-example-namespace" } }
まとめ
今回はTerraformのRKEプロバイダーをご紹介しました。
Terraformでノードの作成からkubernetesクラスタのプロビジョニングまで一気に行えることで環境構築が非常に楽になると思います。
一歩進んでk8sクラスタの使い捨て運用なども可能になるかもしれないですね。
と言うことでぜひRKEプロバイダーをお試しください。
以上です。
さくらのクラウド + Kubernetesでマネージドなロードバランサを使う
さくらのクラウドのマネージドなL4ロードバランサーをKubernetesから使えるようにCloud Controller Manager
を実装してみました。
Kubernetesでserviceを作成する際にtype: LoadBalancer
と指定することで動的にマネージドロードバランサーを作成してくれます。
今回はこの仕組みをどう実現しているか/どう使うのかについてご紹介します。
3/30 追記:
コメントで「ループバックへのVIP設定は不要」とのご指摘をいただきました。
改めて0からクラスタを再構築して試したところ上手くいきましたのでVIP関連の記述を修正しました。
id:masaya_aoyama さんご指摘ありがとうございました!
Kubernetesでtype: LoadBalancer
なserviceを作成するには
GKEやAKSではtype: LoadBalancer
と指定してserviceを作成することでマネージドなロードバランサーを利用可能となっています。
せっかくさくらのクラウドでKubernetesを使うならやっぱりtype: LoadBalancer
でマネージドなロードバランサでserviceを使いたいですよね。
でも単純にKubernetesクラスタをさくらのクラウド上にデプロイしただけではtype: LoadBalancer
は利用できません。
というのも、type: LoadBalancer
なserviceはKubernetesのCloud Controller Manager
というクラウド(等)のプラットフォームとのインテグレーションを担当する部分で
実装されており、各クラウドプラットフォームごとにCloud Controller Manager
を実装する必要があるためです。
参考:Kubernetes ドキュメント: Concepts Underlying the Cloud Controller Manager
Cloud Controller Manager
の実装としては、Kubernetesのソースツリー配下に以下のプラットフォーム向けの実装があります。(v1.10時点)
- aws
- azure
- cloudstack
- gce
- openstack
- ovirt
- photon
- vsphere
ここにないプラットフォームについては独自に実装することでKubernetesと統合可能となっています。 (実装すべきインターフェースはこちらに定義されています -> kubernetes/pkg/cloudprovider/cloud.go)
既にDigitalOceanやOracle Cloud Infrastructureといったプラットフォームについては実装が公開されていますし、既存の実装を改造することでオンプレミス向けにCloud Controller Manager
を実装した事例なども公開されています。
参考(スライド): Kubernetes meetup #7 スライド
参考(記事):Kubernetes をいじって Hardware LoadBalancer で “type LoadBalancer” を実現してみた @Kubernetes meetup #7
Cloud Controller Manager
の実装については↑↑の記事が素晴らしいですのでオススメです。
ということで、さくらのクラウドでtype: LoadBalancer
なサービスを使うにはCloud Controller Manager
が必要ということなので早速実装してみました。
さくらのクラウド向けのCloud Controlelr Manager
の実装
全体としては以下のようになります。
順番に解説していきます。
さくらのクラウドで利用できるロードバランサの仕様
まず、今回利用するさくらのクラウドのマネージドなロードバランサの主な仕様を押さえておきます。
主な仕様は以下の通りです。
- DSR(Direct Server Return)方式のL4ロードバランサ
ルータ+スイッチ
またはスイッチ
を使用して構築されたネットワーク内にのみ設置可能- VRRPを用いた冗長化に対応
- VIPは最大10個
- 実サーバはVIPあたり最大40台まで
Kubernetesと統合する上で特にポイントとなるのは以下2点です。
ルータ+スイッチ
またはスイッチ
を使用して構築されたネットワーク内にのみ設置可能- DSR方式であること
ルータ+スイッチ
とは、さくらのクラウドでグローバルIPをブロック単位(/28〜/24)で確保するためのもので、
割り当てられたブロック内のグローバルIPは配下に接続したサーバやロードバランサなどに自由に割り振り可能となっています。
このルータ+スイッチ
にサーバとロードバランサを接続することでDSRでのロードバランシングを実現しています。
DSR方式自体については以下の資料などを参照ください。
このDSR方式のロードバランサを使う場合は以下のような設定をサーバに対して行う必要があります。
- VIPに応答するためにループバックにVIPを設定
- VIP宛のARPに応答しない設定
3/30 修正 & 追記:
今回はロードバランサ作成時に動的にVIPを確保する仕組みとなっており、VIP確保時に各Workerノードに対してVIPをループバックに設定する必要があります。この辺りを動的に行うための仕組みも今回実装しています。
ループバックへのVIP設定はservice作成時にkube-proxy
によってiptablesに追加されるルールにより処理されるため設定不要です。
Cloud Controller Manager
の処理の流れ
今回中心となるのはControl Plane上で稼働するCloud Controller Manager
です。
service作成時に以下のような流れでロードバランサの作成やVIP割り当てなどを行ってくれます。
(1) serviceの作成
まずはkubectl expose
などでtype: LoadBalancer
と指定してserviceを作成します。
この時点ではまだロードバランサが作成されておらず、各WorkerノードにVIPが割り当てられていない状態です。
(2) ロードバランサの作成
serviceが作成されるとCloud Controller Manager
が動き出します。
まずスイッチ+ルータ
に割り当てられたグローバルIPブロックから未使用のグローバルIPを探します。
グローバルIPが見つかったらスイッチ+ルータ
の配下にロードバランサを作成します。
(3) VIPの割り当て & 実サーバの登録
次にロードバランサにserviceが利用するVIPを割り当てます。このVIPがkubectl get svc
などで見えるExternal IP
となります。
VIPを割り当てた後は振り分け先となる実サーバを登録します。現時点での実装だと全Workerノードあてに振り分けるようにしています(オプションで変更可能となる予定です。)
なおVIPはIPアドレス+ポート番号の組み合わせで登録するため、service作成時に複数のポートを公開するように指定されていた場合はポート番号ごとにVIPを登録します。
この時点でVIP宛てのリクエストが各Workerノードに振り分けられるようになりました。
しかしまだ各WorkerノードのループバックにVIPが割り当てられていないため、パケットが到着しても反応できない状態です。
3/30 追記:
serviceが作成されExternal IP
が割り当てられると、kube-proxy
によりVIP + 指定ポートへのパケットを処理するルールが各ノードのiptablesに追加されます。
このため、ループバックへのVIPの割り当ては不要です。
--- 3/30 修正: ここから不要 ---
VIP-Agent
が各WorkerノードにVIPを割り当てる
VIP-Agent
が各WorkerノードにVIPを割り当てる次に各WorkerノードにVIPを割り当てます。これはCloud Controller Manager
で実装しても良いのですが、今回は別途エージェントを用意しました。
エージェントはVIP-Agent
という名前で、Kubernetesオブジェクトの変更を監視するControllerとして実装しています。
画像: https://cdn-ak.f.st-hatena.com/images/fotolife/f/febc_yamamoto/20180329/20180329174211.png
VIP-Agent
は以下ようなyamlを用いて特権モード(privilege=true
)かつhostのネットワークを直接利用する形で起動します。
DaemonSet
ですので各Workerノードで起動し常駐することになります。
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: sakura-vip-agent namespace: kube-system spec: template: metadata: labels: name: sakura-vip-agent spec: serviceAccountName: sakura-vip-agent hostNetwork: true containers: - image: sacloud/sakura-vip-agent:0.0.1 name: sakura-vip-agent securityContext: privileged: true volumeMounts: - mountPath: /dev name: dev volumes: - name: dev hostPath: path: /dev
このような形にしておくことでserviceにExternal IP
が割り当てられたことを検知し、ホスト側のインターフェースの設定を変更することが可能となります。
今回はserviceのExternal IP
にはVIPが割り当てられますので、それをループバックに設定する役割となっています。
これでVIP宛てのリクエストを各workerが処理できるようになりました。
--- 3/30 修正: ここまで不要 ---
ここまでくれば後はkube-proxy
がPodまで届けてくれます。
(この辺の詳細はQiita:GKE/Kubernetes でなぜ Pod と通信できるのかが詳しいです)
さくらのクラウド向けCloud Controller Manager
の使い方
次に実際の利用方法についてです。さくらのクラウド向けのCloud Controller Manager
を利用するには以下の作業が必要です。
- 各workerノードを
スイッチ+ルータ
配下に作成 - 各workerノードでVIP宛てのarpに応答しないための設定
- kubeletの起動パラメータとして
--cloud-provider=external
を指定 Cloud Controller Manager
のデプロイ(今回はhelmを利用)
各workerノードをスイッチ+ルータ
配下に作成
Kubernetesクラスタ構築の際にworkerノードをスイッチ+ルータ
配下に配置します。
注意点としては、各ノードのホスト名をクラスタ内で一意にすることと、ホスト名とさくらのクラウド上のサーバ名を同じにしておくことがあります。
これはCloud Controller Manager
がworkerノードを検知するのに各ノードのホスト名を元にさくらのクラウドAPIで各サーバを探しに行くようにしているからです。
各workerノードでVIP宛てのarpに応答しないための設定
次にVIP宛てのarpに応答しないようにカーネルパラメータを設定します。
CentOSの場合だと以下のように指定します。
# /etc/sysctl.confに以下2行を追記
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
# 追記した内容を反映
$ sysctl -p
kubeletの起動パラメータとして--cloud-provider=external
を指定
次にkubeletの起動パラメータを追加します。Kubernetes本体のソースツリー配下にないCloud Controller Manager
を利用する場合は--cloud-provider=external
というパラメータを指定する必要があります。
Kubernetesクラスタのセットアップ方法によって設定方法は異なります。
例えばkubeadmの場合は各ノードの/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
にEnvironment="KUBELET_EXTRA_ARGS=--cloud-provider=external
を追記します。
(追記後にkubeletの再起動などで反映するのをお忘れなく!)
Cloud Controller Manager
のデプロイ
最後にCloud Controller Manager
をデプロイします。(3/30 修正: VIPの記述を除去)
デプロイは手動でyamlを投入しても良いですが、簡単にデプロイできるようにHelm Chartを用意しています。
まず、Cloud Controller Manager
はさくらのクラウドAPIを利用するためAPIキーの設定が必要になります。
helmでのインストール時にAPIキーを指定してください。
# helm initを実行(まだしていない場合のみ)
$ helm init
# helmにsacloudリポジトリを追加
$ helm repo add sacloud https://sacloud.github.io/helm-charts/
# デプロイ実行
$ helm install sacloud/sakura-cloud-controller-manager --name sakura-ccm \
--set sacloud.accessToken=<APIトークン> \
--set sacloud.accessTokenSecret=<APIシークレット> \
--set sacloud.zone=<ゾーン(is1a/is1b/tk1a)>
3/30 修正: VIP-Agent
の記述を除去
後は少し待てばCloud Controller Manager
とが起動するはずです。VIP-Agent
(kube-systemネームスペースにデプロイされますので、確認はkubectl get all -n kube-system
のようにしてください)
これで準備が整いました。 次に実際にserviceを作成してみます。
Podを作成しtype: LoadBalancer
なserviceを作成してみる
まずはserviceでexposeするコンテナを作成します。今回は例としてload-balancer-example
という名前でnginxを起動してみます。
kubectl run load-balancer-example --replicas=2 --labels="run=load-balancer-example" --image=nginx:latest --port=80
これでload-balancer-example
という名前のDeploymentが作成され、ReplicaSet/Podも作成されます。
次に作成されたDeploymentをexposeしてserviceを作成します。その際にtype: LoadBalancer
の指定をしておきます。
kubectl expose deployment load-balancer-example --type=LoadBalancer --name=load-balancer-example
service作成直後はExternal IP
が<pending>
となります。
$ kubectl get svc load-balancer-example
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
load-balancer-example LoadBalancer 10.107.97.231 <pending> 80:30900/TCP 1m
External IP
が割り当てられるまでしばらく待ちます。割り当てられると以下のような表示となるはずです。
$ kubectl get svc load-balancer-example
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
load-balancer-example LoadBalancer 10.107.97.231 nnn.nnn.nnn.nnn 80:30900/TCP 3m
後はブラウザなどでExternal IP
宛てにアクセスすると表示されるはずです。
後片付け
serviceを削除するとロードバランサも削除されます。(3/30 修正: VIPの記述を削除)
以下のコマンドでserviceとdeploymentを削除しておきましょう。
$ kubectl delete svc load-balancer-example
$ kubectl delete deploy load-balancer-example
終わりに
ということでさくらのクラウド+Kubernetesでもtype: LoadBalancer
なserviceが使えるようになりました。
今回実装したCloud Controller Manager
はまだ実験段階ですが、これからドッグフーディングということで実環境で使いつつブラッシュアップしていきたいと考えています。
さくらのクラウドでKubernetesを利用する際はぜひCloud Controller Manager
をお試しください〜!!
以上です。
etcdからkubernetesの動きを見る「kube-ectd-helper」
多分すごく限られた層にだけ響くツール「kube-etcd-helper」を作りました。
kube-etcd-helper
は、kube-apiserverが利用しているetcdに直接アクセスし、
データのダンプや変更の検知を行うためのツールです。
kubernetesの全体のデータの動きを知りたい方や、kubernetesを開発プラットフォームとして利用するインフラエンジニアの方などは便利にお使いいただけると思います。
Kubernetesオブジェクトの中身を見るには
Kubernetesオブジェクトとは、Kubernetesのクラスタの状態を表す永続化されるエンティティのことです。
podとかserviceとかdeploymentなどですね。
これらは通常kube-apiserverによって公開されるAPIを通じて操作します。
kube-apiserverの背後ではetcdが動いており、エンティティの永続化に使われています。
手っ取り早くKubernetesオブジェクトの中身を確認するにはkubectl get
コマンドを利用するのが楽です。
例えばpodオブジェクトの中身を見るには以下のようなコマンドを実行します。
$ kubectl get pod <pod名>
NAME READY STATUS RESTARTS AGE
hello-world-55c844bc5b-544h6 1/1 Running 0 3d
より詳細に見るには-o yaml
や-o json
といったオプションをつければOKです。
よく使うコマンドですので馴染みのある方も多いですよね。
さらに、--watch
というオプションをつけることで、指定オブジェクトの変更を追い続けることも可能です。
# --watchオプションをつけると、オブジェクトの変更を検知できる
$ kubectl get pod <pod名> --watch
NAME READY STATUS RESTARTS AGE
hello-world-55c844bc5b-544h6 1/1 Running 0 3d
また、kube-apiserverが提供するREST APIを直接利用する方法でもオブジェクトの内容を確認できます。
# kubectl proxyを併用する場合
$ kube proxy --port=8080 &
$ curl http://localhost:8080/api/v1/namespaces/<ネームスペース>/pods/<pod名>
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "<pod名>",
# 以下略
}
}
これらの方法以外にも、etcdctl
などのetcdクライアントツールで直接データの中身を覗く方法も取れそうなのですがこの方法には問題があります。
というのも、kubernetes 1.6以降はetcd v3がデフォルトとなりバイナリーフォーマット(protobuf)でシリアライズされたデータが格納されているため、
コマンドラインから覗いても(一部を除き)読めないデータとなっているからです。
ということで多くのケースではkubectl
またはREST APIを利用することになると思います。
問題となるケース
通常はkubectl
またはREST APIを利用すれば事足りると思いますが、いくつか面倒なケースというのもあります。
kubectl run
などの複数のオブジェクトにまたがる操作を追いたい場合- オブジェクトの変更履歴を比較し、どこが変わったのか確認したい場合
例えばkubectl run
を実行すると、Deployment/ReplicaSet/Podが作成されます。
これらの動きを追いたい場合--watch
オプションを利用することになるのですが、
現在はkubectl get all
に対しての--watch
オプションは残念ながらサポートされていないためそれぞれに対し個別にkubectl get --watch
しないといけません。
また、--watch
で変更履歴を追えますが、変更されるごとに個別のファイルに出力といったことはできないためどこが変わったのか比較するのがなかなかに面倒な作業です。
これらの問題を解決するためにkube-etcd-helper
を作りました。
kube-etcd-helperは何をするの?
kube-etcd-helper
は、kube-apiserverが利用しているetcdに直接アクセスしデータのダンプや変更の検知を行うためのツールです。
前述の通りkubectl
やREST APIからではネームスペース/オブジェクトを跨いだ全オブジェクトを追うのはなかなか手間ですが、kube-etcd-helper
を利用すれば簡単にできちゃいます。
kube-etcd-helperのインストール
kube-etcd-helper
はGoで書いているため、インストールは実行ファイルをダウンロードして実行権を付与するだけでOKです。
以下のGitHubリリースページからダウンロードしてください。
あとはetcdに接続できる環境で実行するだけです。
master上で直接kube-etcd-helper
を実行できる場合は問題ないですが、Docker for Macなどの直接etcdと通信できない環境の場合は
事前に以下のようにポートフォワードしておきます。
kubectl port-forward etcd-docker-for-desktop 2379:2379 --namespace=kube-system
なおデフォルトではlocalhost:2379
に対して通信しようとしますがオプションで変更も可能です。
同じく証明書の指定などもオプション指定可能です。
kube-etcd-helperの使い方
ダンプ
etcd内でのキー階層をそのままディレクトリ/ファイルにダンプが可能です。
# etcdのデータをoutディレクトリにダンプ
$ kube-etcd-helper dump -o out/ --pretty
変更の追跡(watch)
kubectl
の--watch
オプションと同じく、変更を検知するためのwatch
サブコマンドを用意しています。
これを利用すれば、全ネームスペースの全オブジェクトの動きを追うことが可能です。
# etcdのデータの変更を検知して標準出力に書き出し
$ kube-etcd-helper watch --pretty
watch
サブコマンドはディレクトリ/ファイルへの出力に対応しているため、diffコマンドなどを併用することでどこが変わったのかを追うことも容易です。
# ディレクトリ/ファイルへの出力
$ kube-etcd-helper watch -o out/ --pretty
この例はkubectl run
でhello-world
というdeploymentを作成した時の動きをwatch
サブコマンドで記録したところです。
deployment/replicaset/podそれぞれの配下にJSON形式で変更内容を保存しています。
diffコマンドなどを併用するとオブジェクトのどの値が変更されたのか確認できます。
この図はPodの作成〜schedulerがスケジューリングする部分ですね。Podのステータスがどう変わったのか一目瞭然です。
また、ファイル名はetcdのリビジョン番号を利用していますので、ファイル名順に並べればkubernetesがどの順番でetcdに対して操作を行なっているのか追うことも可能ですね。
その他のコマンド
その他にはlist
とget
サブコマンドがあります。
list
はetcdのキーのみを一覧表示します。get
は指定キーの内容を表示してくれます。
他にもいくつかオプションがありますので、詳細は--help
を参照してください。
終わりに
ということでkube-etcd-helper
の紹介でした。
カスタムのコントローラーを書く方やkubernetesの内部構造をもっと知りたいという方には便利だと思いますのでぜひご利用ください!!
以上です。