UsacloudでエンハンスドロードバランサのLet's Encrypt設定を行う
昨日の記事ではTerraformでエンハンスドロードバランサのLet's Encrypt設定を行えるようになったことを紹介しました。
昨日に続き、本日Usacloud v0.24.0がリリースされ、UsacloudにてエンハンスドロードバランサのLet's Encrypt設定が行えるようになりました。
本日はUsacloud v0.24で行われたエンハンスドロードバランサ関連の機能拡充について紹介します。
Usacloud v0.24.0
v0.24.0では以下のようなエンハンスドロードバランサ関連の機能拡充が行われました。
- 100/500CPS対応
- HTTPSへのリダイレクト対応
- HTTP/2のサポート
- Let's Encrypt対応
100/500CPS対応
enhanced-load-balancer create
またはplan-change
で100/500CPSプランを指定可能となりました。
$ usacloud enhanced-load-balancer create --plan 100 ...
HTTPSへのリダイレクト対応
公開ポートの設定時にリダイレクトの有効化ができるようになりました。
$ usacloud enhanced-load-balancer bind-port-add --mode http --port 80 --redirect-to-https <ID or Name>
--mode
がhttpの時のみ指定可能ですのでご注意ください。
HTTP/2のサポート
公開ポートの設定時にリダイレクトの有効化ができるようになりました。
$ usacloud enhanced-load-balancer bind-port-add --mode https --port 443 --support-http2 <ID or Name>
こちらは--mode
がhttpsの時のみ指定可能ですのでご注意ください。
Let's Encrypt対応
Let's Encrypt設定の有効化/証明書取得が行えるようになりました。
# Let's Encrypt設定の有効化 $ usacloud enhanced-load-balancer acme-setting --accept-tos --common-name www.example.com <ID or Name> # 証明書の取得/更新 $ usacloud enhanced-load-balancer acme-renew <ID or Name> # 証明書の確認 $ usacloud enhanced-load-balancer cert-info <ID or Name>
Let's Encrypt設定を有効化するには--accept-tos
というフラグを指定する必要がある点に注意してください。
これはLet's Encrypt側の利用規約に同意するというフラグで、明示的に指定しないと有効化出来ないようにしています。
また、証明書発行対象のコモンネームが名前解決できるようになっている必要があります。
この辺りの詳細はさくらのクラウドのマニュアルを参照してください。
ということでUsacloudでのエンハンスドロードバランサ関連機能拡充について紹介しました。 Terraformと上手く使い分けてみてくださいね。
以上です。
TerraformでさくらのクラウドのエンハンスドロードバランサのLet's Encrypt設定を行う
Terraform for さくらのクラウド v1.13.0リリース
本日リリースのTerraformさくらのクラウド向けプロバイダー v1.13.0にてエンハンスドロードバランサ関連の機能拡充が行われました。
- 100/500CPSプランのサポート
- HTTPSへのリダイレクト機能
- HTTP/2のサポート
- Let's Encrypt設定
Release v1.13.0 · sacloud/terraform-provider-sakuracloud · GitHub
新プラン/HTTPSへのリダイレクト/HTTP2のサポート
これらについては以下のようなtfファイルで利用可能となっています。
resource "sakuracloud_proxylb" "foobar" { name = "terraform-test-proxylb-acme" # 100CPSプランを利用 plan = 100 vip_failover = true health_check { protocol = "http" delay_loop = 10 host_header = "usacloud.jp" path = "/" } bind_ports { proxy_mode = "http" port = 80 # HTTPSへのリダイレクトを有効化 redirect_to_https = true } bind_ports { proxy_mode = "https" port = 443 # HTTP/2サポートの有効化 support_https = true } servers { ipaddress = "${sakuracloud_server.server01.ipaddress}" port = 80 } }
Let's Encryptの利用
Let's Encryptを利用するには新設されたリソースsakuracloud_proxylb_acme
を利用する必要があります。
# エンハンスドロードバランサでのLet's Encrypt設定 resource sakuracloud_proxylb_acme "foobar" { proxylb_id = sakuracloud_proxylb.foobar.id accept_tos = true # 規約への同意 common_name = "www.example.com" update_delay_sec = 120 }
注意点としてはさくらのクラウドのマニュアルに記載の条件を満たす必要があるという点があります。
2番目の条件である、DNSレコードの設定を含めたtfファイルの例は以下の通りです。
# エンハンスドロードバランサの定義 resource "sakuracloud_proxylb" "foobar" { name = "terraform-test-proxylb-acme" plan = 100 vip_failover = true health_check { protocol = "http" delay_loop = 10 path = "/" } # Let's Encryptを利用するにはhttp/https両方のbind_portsが必要 bind_ports { proxy_mode = "http" port = 80 redirect_to_https = true } bind_ports { proxy_mode = "https" port = 443 support_https = true } servers { ipaddress = "${sakuracloud_server.server01.ipaddress}" port = 80 } } # エンハンスドロードバランサでのLet's Encrypt設定 resource sakuracloud_proxylb_acme "foobar" { proxylb_id = sakuracloud_proxylb.foobar.id accept_tos = true # 規約への同意 common_name = "www.example.com" update_delay_sec = 120 } resource sakuracloud_server "server01" { name = "terraform-test-server01" graceful_shutdown_timeout = 10 } # エンハンスドロードバランサのVIP/FQDNを解決するためのDNSレコード設定 data sakuracloud_dns "zone" { name_selectors = ["example.com"] } resource "sakuracloud_dns_record" "record" { dns_id = data.sakuracloud_dns.zone.id name = "www" type = "CNAME" value = "${sakuracloud_proxylb.foobar.fqdn}." ttl = 10 }
この例ではエンハンスドロードバランサのFQDNを証明書発行対象のFQDNのCNAMEとして登録しています。
注意点として、DNSレコード登録直後は証明書発行対象のFQDNが解決できない場合があります。
このためにsakuracloud_proxylb_acme
にはupdate_delay_sec
という項目を設けています。
これはリソース作成時に指定秒数待つための項目です。手元の環境では120秒くらいに設定すると上手くいっていました。
終わりに
TerraformからLet's Encryptの設定〜設定を行うためのレコードの登録まで一括して行えるのは非常に楽だと思います。
ぜひご活用ください。
以上です。
ConftestでOpenPolicyAgent/Regoを使いTerraformのコードにポリシーを適用してみる
今日はConftestを用いてTerraformでのインフラコードにポリシーを適用してみます。
TerraformでのインフラコードのUnitTest
terraform validate
での構文チェック
Terraformではtfファイルの構文チェックを行ってくれるterraform validate
コマンドが提供されています。
実行するとtfファイルの構文誤りやパラメータ名間違いなどを検出してくれます。
$ terraform validate Error: Unsupported argument ← パラメータ名間違い on test.tf line 6, in data "sakuracloud_server" "server": 6: name_selectorsa = ["sakura-dev"] An argument named "name_selectorsa" is not expected here. Did you mean "name_selectors"?
これを利用すれば最低限tfファイルとして正しく書けているかのテストが行えます。
特にTerraform v0.12からは以下のように変数に型情報を与えることが出来るようになっており、モジュール利用時などにより厳密なチェックが行えるようになりました。
# var.nodesはaddressとuserというフィールドを持つオブジェクトのリストしか指定できない variable "nodes" { type = list(object({ address = string, user = string, })) }
ポリシーの適用
テストの際、terraform validate
での構文チェック以外にも様々な制約を課したい/ポリシーを適用したいことが多々あります。
例えば、
といった場合です。
Terraform EnterpriseであればSentinelを用いてポリシーの適用が行えるのですが、OSS版の場合、現時点ではSentinelを利用できません。
そこで今回はConftestを用いてポリシーの適用を行ってみました。
Conftest
Conftestについてはこちらの記事が詳しいです。
ConftestはYAMLあるいはJSONで定義された設定ファイルに対してテストを書けるというツールです。
面白いのは、テストに使うのがOpen Policy AgentのRegoというポリシー用の言語だという点です。
ConftestでOpenPolicyAgent/Regoを用いてポリシーを定義しておいてCIでConftestを実行すればポリシーの適用/強制ができそうです。
ConftestのリポジトリにはTerraformのコードをテストする例がありますのでそちらを参考にポリシーを書いてみます。
conftestでのterraformインフラコードのテスト
Conftestはコマンドラインツールとなっており、以下のように実行することでYAML/JSONファイルのテストが行えます。
$ conftest test <file>
デフォルトではカレントディレクトリのpolicy
ディレクトリ配下を参照するようになっていますのでこちらにポリシーファイル(.rego)を作成していきます。
(この挙動は-p
または--policy
オプションで変更可能です)
tfファイルをどうやってテストするの?
TerraformでのインフラコードはJSONでも記載できますが、通常はHCL(.tf)で記載していると思います。 conftestはHCLを読んでくれませんのでどうにかしてJSON/YAMLに変換する必要があります。
ConftestのリポジトリにあるTerraformの例ではplanファイルを出力した上でterraform show
にJSON出力オプションを指定して実行することでtfファイルを間接的にテストするという方法を取っています。
例えば、以下のようなtfファイルがある場合、
resource sakuracloud_server "server" { name = "example" core = 1 memory = 1 }
これを元にplanファイル生成〜terraform show
をJSON出力すると以下のようになります。
# planファイルを出力 $ terraform plan --out plan.tfplan # terraform showをJSONで出力 $ terraform show -json plan.tfplan | jq . { "format_version": "0.1", "terraform_version": "0.12.1", "planned_values": { "root_module": { "resources": [ { "address": "sakuracloud_server.server", "mode": "managed", "type": "sakuracloud_server", "name": "server", "provider_name": "sakuracloud", "schema_version": 1, "values": { "additional_nics": null, "commitment": "standard", "core": 2, "description": null, "disable_pw_auth": null, "graceful_shutdown_timeout": 60, "hostname": null, "icon_id": null, "interface_driver": "virtio", "memory": 4, "name": "test", "nic": "shared", "note_ids": null, "password": null, "private_host_id": null, "ssh_key_ids": null } } ] } }, "resource_changes": [ { "address": "sakuracloud_server.server", "mode": "managed", "type": "sakuracloud_server", "name": "server", "provider_name": "sakuracloud", "change": { "actions": [ "create" ], "before": null, "after": { "additional_nics": null, "commitment": "standard", "core": 2, "description": null, "disable_pw_auth": null, "graceful_shutdown_timeout": 60, "hostname": null, "icon_id": null, "interface_driver": "virtio", "memory": 4, "name": "test", "nic": "shared", "note_ids": null, "password": null, "private_host_id": null, "ssh_key_ids": null }, "after_unknown": { "additional_display_ipaddresses": true, "cdrom_id": true, "disks": true, "display_ipaddress": true, "dns_servers": true, "gateway": true, "id": true, "ipaddress": true, "macaddresses": true, "nw_address": true, "nw_mask_len": true, "packet_filter_ids": true, "private_host_name": true, "tags": true, "vnc_host": true, "vnc_password": true, "vnc_port": true, "zone": true } } } ], "configuration": { "root_module": { "resources": [ { "address": "sakuracloud_server.server", "mode": "managed", "type": "sakuracloud_server", "name": "server", "provider_config_key": "sakuracloud", "expressions": { "core": { "constant_value": 2 }, "memory": { "constant_value": 4 }, "name": { "constant_value": "test" } }, "schema_version": 1 } ] } } }
これをconftestコマンドに読ませることでテストを行います。
ポリシーの作成
今回は試しにサーバのコア数は2以上、メモリは4GB以上を指定しないといけないというポリシーにしてみます。
ポリシーファイルは以下の内容でpolicy/instance_type.rego
というファイルを作成します。
package main # コア数は2以上であること deny[msg] { resource := input.resource_changes[index] resource.type == "sakuracloud_server" resource.change.after.core < 2 msg = "sakuracloud_server.core must be greater than 2" } # メモリは4GB以上であること deny[msg] { resource := input.resource_changes[index] resource.type == "sakuracloud_server" resource.change.after.memory < 4 msg = "sakuracloud_server.memory must be greater than 4" }
テスト実行(ポリシー適用)
それでは早速conftestでテストを実行(ポリシーを適用)してみます。
Makefileの作成
プランファイルの出力~JSONへの変換は毎回コマンド入力するのも大変なのでMakefileでまとめておきます。
NAME := myproject COMMAND := terraform PLAN = $(NAME)-plan.tfplan SHOW = $(NAME)-show.json CODE = $(NAME).tf all: test plan: $(PLAN) $(PLAN): $(CODE) $(COMMAND) plan -out $(PLAN) show: $(SHOW) $(SHOW): plan $(COMMAND) show -json $(PLAN) > $(SHOW) test: show cat $(SHOW) | conftest test - clean: @rm -f $(PLAN) $(SHOW) .PHONY: plan show test all clean
これでmake
するだけでテスト可能になります。
なお、このMakefileだと中間ファイルが作成されますので必要に応じてcleanを実行したり.gitignoreに追記したりしておいてください。
実行
現時点でのtfファイルは以下の通りです。
resource sakuracloud_server "server" { name = "example" core = 1 memory = 1 }
ポリシーである2コア以上かつ4GBメモリ以上に反しているのでエラーとなるはずです。
$ make # [中略] cat example-show.json | conftest test - sakuracloud_server.core must be greater than 2 sakuracloud_server.memory must be greater than 4 make: *** [test] Error 1
エラーになりましたね!
今度はtfファイルを修正して実行してみます。
resource sakuracloud_server "server" { name = "example" core = 2 memory = 4 }
# [中略] cat example-show.json | conftest test -
今度はエラーとなりませんでしたね。
あとは必要に応じてポリシーを充実させ、CIに組み込めば良さそうです。
終わりに
Open Policy Agent/Regoを初めて使ってみましたがなかなか面白いですね。 TerraformのようなインフラコードのテストでShift left testing出来ると効率がグッと上がりますのでどんどん活用していきたいです。
以上です。
参考情報
- Conftest: https://github.com/instrumenta/conftest
- Open Policy Agent: https://www.openpolicyagent.org/
- Rego Deep Dive: https://www.slideshare.net/TorinSandall/rego-deep-dive
- Open Policy Agentを始めてみよう: https://kenfdev.hateblo.jp/entry/2019/03/19/092927
- Unit Test好きにはたまらない!Conftestで設定ファイルのテストをしてみた: https://kenfdev.hateblo.jp/entry/2019/05/31/194614
TerraformでのプロビジョニングにVNCを使う
TerraformでVNCでのプロビジョニングを行えるようにするプラグインterraform-provisioner-vncを公開しました。
Terraformでのプロビジョニング
Terraformではリソースの初期設定や削除時のクリーンアップ処理などを行えるようにプロビジョナーという仕組みが用意されています。
Terraform v0.12.1の時点では以下のようなプロビジョナーが利用可能となっています。
- chef Provisioner
- file Provisioner
- habitat Provisioner
- local-exec Provisioner
- remote-exec Provisioner
- salt-masterless Provisioner
SSH/WinRMが利用できないリソースのプロビジョニングは?
プロビジョナーのうちlocal-exec以外はSSHまたはWinRM(SSHのみの場合もある)でリモートに接続してなんらかの処理を行うようになっています。 これはSSH/WinRMが利用できないリソース、例えば初期状態ではリモート接続を許可していないようなリソースではこれらを利用できないということです。
この問題の解決方法の一つとして、VNC経由でコマンドを実行するのが今回公開したterraform-provisioner-vnc
です。
Packerでいうboot_commandを実行するものとなっており、主にSSH/WinRM出来るまでの環境を整えることを目的としています。
terraform-provisioner-vncの使い方
通常のプロビジョナーと同じく、対象のリソースやnull_resourceにprovisionerブロックを記載することで利用します。 例えばさくらのクラウドのサーバだと以下のように使います。
resource sakuracloud_server "example" { name = "example" # ...中略 provisioner vnc { host = self.vnc_host port = self.vnc_port password = self.vnc_password boot_wait = "10s" # ここに実行したいコマンドを記載していく inline = [ "<tab><wait>", "text ks=http://${var.ip}:${var.port}/anaconda-ks.cfg<enter>", ] } }
remote-execと同じく、inline
(文字列リストで指定)、script
(スクリプトファイルのパスで指定)、またはscripts
(ファイルパスのリストで指定)で実行するスクリプトを指定できます。
記載できる内容はPackerでのboot_commandと互換性があり、<enter>
などの特殊キーもサポートしています。(入力処理はPackerそのものを利用してます)
指定できるスクリプトについてはPackerのQEMU Builderのboot_commandについてのドキュメントを参照してください。
terraform-provisioner-vncのインストール
リリースページからバイナリファイルをダウンロードし~/.terraform.d/plugins
配下に配置すればOKです。
利用例
利用例として、さくらのクラウド上のサーバでk3OSを起動〜ディスクへのインストールまでを行う例を挙げておきます。
参考: k3os on さくらのクラウド - febc技術メモ
k3OSをISOイメージから起動した場合、公開鍵を登録する or rancherユーザーのパスワードを設定するまでSSH接続できません。
このため、VNCプロビジョナーを用いてOSのインストール処理〜GitHubから公開鍵の取得/登録などを行います。
OSのインストール後はSSHプロビジョナーで接続して任意のプロビジョニングが実行できます。
この例ではkubectl
コマンドを実行してみています。
variable server_name { default = "example" } variable github_username { default = "yamamoto-febc" } provider sakuracloud { zone = "is1b" } data sakuracloud_cdrom k3os { name_selectors = ["k3OS"] } resource sakuracloud_disk "disk" { name = var.server_name } resource sakuracloud_server "k3os" { name = var.server_name core = 2 memory = 4 disks = [sakuracloud_disk.disk.id] cdrom_id = data.sakuracloud_cdrom.k3os.id # VNC経由でOSのインストール処理 provisioner vnc { host = self.vnc_host port = self.vnc_port password = self.vnc_password boot_wait = "40s" inline = [ "rancher<enter>", "<wait5>", "sudo os-config<enter>", "<wait5>", "<enter>", "<wait5>", "<enter>", "<wait5>", "y<enter>", "<wait5>", "${var.github_username}<enter>", # terraformの$記法も使えるしコメントも書ける "<wait10s>", "<enter>", "<wait5>", "<enter>", "<wait5>", "<enter>", "<wait10s>", "y<enter>", "<wait5>", ] } # VNCでプロビジョニング後はSSHで接続してプロビジョニング connection { type = "ssh" host = self.ipaddress user = "rancher" private_key = file("/Users/kaz/.ssh/id_rsa") script_path = "/home/rancher/bootstrap.sh" } provisioner "remote-exec" { inline = [ "echo ${self.ipaddress} `hostname` | sudo tee -a /etc/hosts", # /etc/hostsに自身のホスト名を追記 "kubectl cluster-info", "kubectl get cs", "kubectl version", ] } }
終わりに
使い所は限られますが、Packerを使うまでもないちょっとしたコマンドを実行しておきたいケースに便利だと思います。
なお、TerraformでのCustom Provisionerの仕組みはこちらにコメントされているように将来的に大きく変わる可能性もある点は注意しておいてください。
(利用する側としてはあまり関係ないかもしれませんが)
以上です。
Rioにビルトインされているサービスを確認する - GrafanaとKiali
前回はRioでGitリポジトリを指定してのRunを試してみました。
rio run
の引数としてGitリポジトリを指定するだけでリポジトリの変更検知〜イメージのビルド〜公開という仕組みが利用できました。
今回はそれらを実現している、Rioにビルドインされているサービスを確認していきます。
なお、今回はこちらのTerraformモジュールを使ってさくらのクラウド+RKEクラスタ上にRioをインストールしました。
Rioでどのようなサービスが動いているか確認する。
RioはKubernetes上にデプロイされるため、kubectl
などでワークロードを確認(例えばkubectl get pod -n rio-system
を実行)することでどのようなサービスが動いているか調べることができます。
が、より簡単に確認できるコマンドrio --system ps
が提供されていますので今回はこちらを利用します。
(なお、この--system
オプションは省略形(-s
)も利用可能です。またrio logs
などにも対応しています。)
ということで早速確認してみます。
rio --system ps
の実行
実行結果は以下の通りでした。
$ rio --system ps NAME CREATED ENDPOINT REVISIONS SCALE WEIGHT DETAIL rio-system/autoscaler 3 minutes ago v0 1 100% rio-system/build-controller 2 minutes ago v0 1 100% rio-system/buildkit 3 minutes ago v0 1 100% rio-system/cert-manager 2 minutes ago v0 1 100% rio-system/grafana 2 minutes ago https://grafana-rio-system.6y9oo6.on-rio.io:9443 v0 1 100% rio-system/istio-citadel 2 minutes ago v0 1 100% rio-system/istio-gateway 2 minutes ago v0 1 100% rio-system/istio-pilot 2 minutes ago v0 1 100% rio-system/istio-telemetry 2 minutes ago v0 1 100% rio-system/kiali 2 minutes ago https://kiali-rio-system.6y9oo6.on-rio.io:9443 v0 1 100% rio-system/prometheus 3 minutes ago v0 1 100% rio-system/registry 2 minutes ago https://registry-rio-system.6y9oo6.on-rio.io:9443 v0 1 100% rio-system/webhook 2 minutes ago https://webhook-rio-system.6y9oo6.on-rio.io:9443 v0 1 100%
ENDPOINTにURLが表示されているものがありますね。
Grafana
まずは試しにgrafanaのENDPOINTをブラウザで開いてみます。
お、grafanaのダッシュボードが表示されましたね。
Istio関連のダッシュボードがありますね。
いい感じです。
kiali
kialiはIstio向けの可視化ツールです。
これもENDPOINTをブラウザで開いてみます。
これも表示できましたね。早速ログインしてみましょう。
ユーザー名/パスワードともadmin
でログインできます。
いい感じですね。
その他のENDPOINT
他にはイメージレジストリとWebhookにENDPOINTが表示されてますね。 レジストリは試したらイメージのpushなどもできました。
# 適当なイメージをビルド $ docker image build -t registry-rio-system.6y9oo6.on-rio.io:9443/test . # pushしてみる $ docker push registry-rio-system.6y9oo6.on-rio.io:9443/test
Webhookは試そうとしたのですが疲れちゃったのでまた今度。
終わりに
今回はここまで。以上です。
sakura-cloud-controller-managerのデプロイ&トラブルシューティング
さくらのクラウドでKubernetesを利用する場合、マネージドなLBなどを扱うためのcloud-controller-manager実装として sakura-cloud-controller-managerというものがあります。
こちらのデプロイでよく引っかかる点やトラブルシューティング方法についてメモを発掘したので整理がてら残しておきます。
さくらのクラウド上のリソースの構成
Kubernetesクラスタで利用するさくらのクラウド上のリソースの構成は以下の点に注意が必要です。
- ネットワーク構成
- スイッチ(ルータ)への
@k8s
タグ設定
ネットワーク構成
sakura-cloud-controller-managerはサーバをスイッチ+ルータ or スイッチに接続する必要があります。
共有セグメント(共有回線)はサポートしていませんので注意してください。
スイッチ(ルータ)への@k8s
タグ設定
sakura-cloud-controller-managerはさくらのクラウドAPIで取得したスイッチ(ルータ)の情報を元にどのスイッチを利用するかを決定します。
その際に@k8s
タグの付けられたリソースかで判定を行なっています。
タグの付け忘れにご注意ください。
クラスタの構成
次にKubernetesクラスタの構成についてですが、以下2点に注意する必要があります。
順番にみていきます。
--cloud-provider
オプションを適切に指定すること
Kubernetesでexternalなcloud-controller-managerを起動するには--cloud-provider
オプションを適切に指定する必要があります。
参考: Kubernetes Cloud Controller Manager - Kubernetes
具体的には以下2点です。
- kubeletのパラメータとして
--cloud-provider=external
を指定しておくこと - kube-apiserverとkube-controller-managerには
--cloud-provider
を指定しないこと
kubeadmを利用してクラスタのデプロイを行う場合は/var/lib/kubelet/kubeadm-flags.env
ファイルや/etc/default/kubelet
ファイルなどで適切に指定しましょう。
参考: Installing kubeadm - Kubernetes
Nodeに付与されるtaintsへの対応
先ほどの参考ドキュメントに書いてありますが、kubeletに--cloud-provider=external
を指定するとノードに対し以下のようなtaintsが設定されます。
- apiVersion: v1 kind: Node spec: taints: - effect: NoSchedule key: node.cloudprovider.kubernetes.io/uninitialized value: "true"
sakura-cloud-controller-managerをデプロイする際はこのtaintsに対するtolerationsが適切に設定されている必要があります。
# tolerationsの設定例 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: sakura-cloud-controller-manager namespace: kube-system spec: replicas: 1 template: spec: containers: - name: sakura-cloud-controller-manager image: "sacloud/sakura-cloud-controller-manager:0.3.0" tolerations: # tolerationsを設定しておく - key: node.cloudprovider.kubernetes.io/uninitialized value: "true" effect: NoSchedule
もしkubeletに--cloud-provider
を指定しなかったらどうなるの?
この場合でもsakura-cloud-controller-managerのデプロイ自体はうまくいくように見えます。
が、ノードのExternalIPが適切に設定されないため、type: LoadBalancer
なサービスを作ってもロードバランサが作成されるものの実サーバが登録されないという状態になります。
serviceは作成されるけど、、、
実サーバは登録されていない
クラスタ内のノード名とさくらのクラウド上でのサーバ名が一致していること
これはsakura-cloud-controller-manager側の制約です。
sakura-cloud-controller-managerではノード名を条件にさくらのクラウドAPIで対象サーバの情報を取得しています。
このため、ノード名とサーバ名が異なるとうまくいきません。
kubeletの--hostname-override
オプションなどで適切に設定しましょう。
(kubeadmの場合は--node-name
フラグが利用できます。 参考: kubeadm init - Kubernetes)
もしノード名とサーバ名が違うとどうなるの?
sakura-cloud-controller-managerでのノード情報の取得が行えず、ノードのtaintsが残り続けます。
このためPodを起動しようとしてもPendingのままとなります。
(まずkube-dnsなどの主要コンポーネントについてもPendingのままとなっているはずです。)
# Podを起動しようとしてもPendingのまま $ kubectl get pod NAME READY STATUS RESTARTS AGE nginx-7cdbd8cdc9-8g8mw 0/1 Pending 0 3m1s # 主要コンポーネントもPendingのまま $ kubectl get pod -n kube-system --selector k8s-app=kube-dns NAME READY STATUS RESTARTS AGE kube-dns-58bd5b8dd7-swrlg 0/3 Pending 0 7m39s
さらにこの状態だとノードのInternalIP/ExternalIPが設定されず、kubectl logs
を実行するとError from server: no preferred addresses found; known addresses: []
などというエラーになります。
sakura-cloud-controller-managerのデプロイ
DeploymentまたはDaemonSetとしてデプロイしてください。
(現在Helmでデプロイする場合はDaemonSetのみサポートしています)
Deploymentとする場合のマニフェスト例は以下の通りです。 (この例はRKEを使ってデプロイしたKubernetesクラスタを利用しています。tolerationsやnodeSelectorsは環境に応じて適切に指定してください)
apiVersion: v1 kind: Secret metadata: name: sakuracloud-api-keys namespace: kube-system type: Opaque data: access-token: "<APIアクセストークン>" access-token-secret: "<APIアクセスシークレット>" --- --- apiVersion: v1 kind: ServiceAccount metadata: name: sakura-cloud-controller-manager namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" name: system:sakura-cloud-controller-manager rules: - apiGroups: - "" resources: - events verbs: - create - patch - update - apiGroups: - "" resources: - nodes verbs: - '*' - apiGroups: - "" resources: - nodes/status verbs: - patch - apiGroups: - "" resources: - services verbs: - list - patch - update - watch - apiGroups: - "" resources: - services/status verbs: - list - patch - update - watch - apiGroups: - "" resources: - serviceaccounts verbs: - create - apiGroups: - "" resources: - persistentvolumes verbs: - get - list - update - watch - apiGroups: - "" resources: - configmaps verbs: - get - list - watch - apiGroups: - "" resources: - endpoints verbs: - create - get - list - watch - update --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: system:sakura-cloud-controller-manager roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:sakura-cloud-controller-manager subjects: - kind: ServiceAccount name: sakura-cloud-controller-manager namespace: kube-system --- apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: k8s-app: cloud-controller-manager name: sakura-cloud-controller-manager namespace: kube-system spec: replicas: 1 selector: matchLabels: k8s-app: cloud-controller-manager template: metadata: labels: k8s-app: cloud-controller-manager spec: dnsPolicy: Default hostNetwork: true serviceAccountName: sakura-cloud-controller-manager containers: - name: sakura-cloud-controller-manager image: "sacloud/sakura-cloud-controller-manager:0.3.0" resources: requests: cpu: 100m memory: 128Mi limits: cpu: 256m memory: 256Mi command: - /usr/local/bin/sakura-cloud-controller-manager - --cloud-provider=sakuracloud - --allocate-node-cidrs=false - --configure-cloud-routes=false env: - name: SAKURACLOUD_ACCESS_TOKEN valueFrom: secretKeyRef: name: sakuracloud-api-keys key: access-token - name: SAKURACLOUD_ACCESS_TOKEN_SECRET valueFrom: secretKeyRef: name: sakuracloud-api-keys key: access-token-secret - name: SAKURACLOUD_ZONE value: "<対象ゾーン(is1a or is1b or tk1a)>" - name: SAKURACLOUD_CLUSTER_ID value: "default" tolerations: - key: node.cloudprovider.kubernetes.io/uninitialized value: "true" effect: NoSchedule - key: "CriticalAddonsOnly" operator: "Exists" nodeSelector: node-role.kubernetes.io/controlplane: "true"
実行時によくあるトラブル
よくあるトラブルとして、Serviceを作成してもいつまでもPendingのままというものがあります。
この場合、sakura-cloud-controller-managerのログを参照すると何かヒントが得られることがあります。
# ログの参照例 $ kubectl logs -f -n kube-system sakura-cloud-controller-managerのpod名
私も引っかかったことがあるのは次のようなエラーメッセージが出るケースです。
Improper request. The parameters of the specified error or input rule violation. Please check your entries.\n実サーバのIPアドレス(xxx.xxx.xxx.xxx)は同一ネットワークである必要があります
このケースは@k8s
タグのついたスイッチ+ルータが複数存在している場合に発生します。
複数のスイッチ+ルータを使い分けたい場合はそれぞれのスイッチに対し識別用のタグを付与した上でk8s.usacloud.jp/router-selector
アノテーションをServiceに対して指定するようにすればOKです。
おまけ: RKEでデプロイするTerraformモジュール
こちらにTerraformのさくらのクラウドプロバイダー+RKEプロバイダーでクラスタ構築やsakura-cloud-controller-managerのデプロイまで行うモジュールを置いておきます。
以上です。
k3OSのISOイメージがさくらのクラウドに追加された
さくらのクラウドのパブリックISOイメージにk3OSが追加されましたね!
前回の記事ではk3OSのISOイメージをダウンロード&アップロードして試しました。
これが本日パブリックISOイメージが追加されたことでISOイメージのダウンロード/アップロードが不要となりより簡単にk3OSを試せるようになりました。
パブリックISOイメージから起動してみる(ディスクレス)
前回はCLIを利用した方法を紹介しましたので、今回はコントロールパネルからの操作を紹介します。
前回はディスクにインストールする手順でしたが、今回はディスクレスでISOイメージから起動してそのまま使う方法にしてみました。
(ディスクを作成しない分お安くなっています)
コントロールパネルからサーバの追加
まずコントロールパネルからサーバ追加画面へ移動します。
サーバ追加画面ではシンプルモード
のチェックを外すのがポイントです。
(サーバ作成時にISOイメージを挿入するには非シンプルモードである必要があります)
その後、ディスクレス
を選択した上で挿入するISOイメージとしてk3OS v0.2.0 amd64
を選択します。
もしディスクを接続したい場合は新規ディスクを作成
を選択し、ディスクソースにブランク
を指定すればISOイメージ選択欄が出てきます。
次のNICの設定はデフォルトのインターネットに接続
を選択しておきます。
これは共有セグメント(共有回線)経由でインターネット接続を行うという指定です。 共有セグメントではDHCPによるグローバルIPの割り当てが利用可能となっています。
なお、k3OSのドキュメントによると、サーバのコア数/メモリはデフォルトの1コア/1GBで大丈夫なようです。
Live install (boot from ISO) requires at least 1GB of RAM.
GitHub - rancher/k3os: Purpose built OS for Kubernetes, fully managed by Kubernetes.
しかし1GBメモリだとイメージのpullなどでエラーになる場合があったため手元の環境ではメモリ2GBで試しました。 (他の要因もあるかもしれませんが調べてません)
参考: CLIでサーバ作成する場合
CLIの場合は以下のコマンドでOKです。
$ usacloud server build --name k3os --disk-mode diskless --iso-image-id `usacloud iso-image read -q k3OS` --memory 2
起動してコンソール接続
サーバを作成&起動後、コントロールパネルからコンソールを開きます。
後は前回と同じくユーザー名rancher
(パスワードなし)でログイン可能です。
ログイン後の設定
SSH
このまま試しても良いのですが、コンソール接続だとコピペができない(ペーストはコンパネ経由でできる)など色々不便なのでSSH接続できるようにします。
今回はGitHubからユーザーの公開鍵を取得して利用します。
以下のコマンドをコンソールで実行します。ユーザー名部分は任意のものに変更してください。
# GitHubのユーザー名が"yamamoto-febc"の場合 $ curl -L -o /home/rancher/.ssh/authorized_keys https://github.com/yamamoto-febc.keys $ chmod 0600 /home/rancher/.ssh/authorized_keys
なお、コンソール接続している時点ではキーボードがUS配列になっていると思います。 普段US配列以外をお使いの場合は記号の入力の際にご注意ください。
この後SSHで接続できるようになっているはずです。
$ ssh rancher@サーバのグローバルIPアドレス
なお公開鍵を用意するのが面倒な方は以下のコマンドでrancherユーザーにパスワードを設定する方法もあります。
$ sudo passwd rancher
/etc/hosts
/etc/hostsを編集し自身のホスト名を解決できるようにします。
ホスト名はhostname
コマンドなどで、IPアドレスはip a show dev eth0
コマンドなどで確認しておきます。
今回は/etc/hostsを以下のようにしました。
127.0.0.1 localhost localhost.localdomain 127.0.1.1 k3os-14500 k3os-14500.localdomain ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters # これを追記(IPアドレス/ホスト名は適宜修正) 153.120.168.44 sv-113100883194
これでひとまず利用できる環境が整いました。 後は色々動かしてみましょう。
終わりに
ISOイメージを用意してくれてるのは楽ですね。 とりあえず雰囲気を確認したいというような場合に手軽に使えて良いと思います。
以上です。