ExternalDNSとcert-managerでお家KubernetesとHTTPSな通信をする
はじめに
以前 kubespray を使ってお家 kubernetes を作成しました(前回の記事)。
その後遊んでいたのですが、kubectl port-forward
を使って通信している現状を変え、
通常のサーバのようにhogohoge.your.domain
でアクセスできないかな~といろいろ試していた所、うまくいったのでその記録を残しておきたいと思います。
完成系
以下のようなリソースを作成すると自動的にドメインおよび TLS が設定され、hogohoge.your.domain
と HTTPS 通信を行えるようになります。
MetalLB のインストール
MetalLB, bare metal load-balancer for Kubernetes (universe.tf)
まずkubectl port-forward
を使わずともクラスター内のサービスと通信できるように、
MetalLB をインストールします。インストール方法はいろいろあるようですが今回は Helm を使ってインストールします。
ここでいろいろ追加されるので訳が分からなくなるのを防ぐために Namespace を分けておきます。
続いて MetalLB が動作できるように設定を追加します。L2 モードと BGP モードというものがあるようなのですが、 私が BGP というものを詳しく知らないので L2 モードで設定してきます。
下のような設定ファイルを作成します。ただしip-address-pool.yaml
の spec.addresses は各自の環境に合わせて変更してください。
詳しくは以下リンクを確認お願いします。
https://metallb.universe.tf/configuration/
ip-address-pool.yaml
l2-advetisement.yaml
適当なサービスを作成して IPAddressPool に設定されたアドレスが割り当てられるかチェックします。
metallb.yaml
EXTERNAL-IP にアドレスが書いてあれば OK です。作成したサービスは片付けます。
Ingress-Nginx Controller のインストール
Installation Guide - Ingress-Nginx Controller (kubernetes.github.io)
ついでに L7 のロードバランサーも入れておきます。これも Helm を使ってインストールします。
インストールが完了したら動作しているか確かめるために、以下のようなリソースを作成します。
参考: Minikube 上で NGINX Ingress コントローラーを使用して Ingress をセットアップする | Kubernetes
ingress-nginx.yaml
Ingress が作成されていることを確かめたら curl でアクセスします。HOSTS が設定されていればいけると思います。
ホストを設定せずにアクセスすると Not Found になるので L7 レベルで分散が行われているようです。
確認ができたら作成したリソースを片付けます。
ExternalDNS
先ほどまでで L2 および L7 での分散およびアクセスが行えるようになりましたが、いまだに IP アドレスを使わないといけません。 これはお洒落じゃないですね(圧)。そこでドメインを自動的に発行できるように ExternalDNS を利用します。
ExternalDNS は作成された Ingress や Service の情報を見て、いい感じに DNS レコードを作成してくれるツールです。 そのためここら先は各自がドメインを持っている必要があります。持っていない方は適当なドメインを作成しておいてください。
私は DNS Server として Cloudflare を利用しているので以下の手順に沿って行います。
external-dns/docs/tutorials/cloudflare.md at master · kubernetes-sigs/external-dns · GitHub
その他対応しているプロバイダー一覧は以下です。
kubernetes-sigs/external-dns: Configure external DNS servers (AWS Route53, Google CloudDNS and others) for Kubernetes Ingresses and Services (github.com)
API トークン発行
はじめに Cloudflare の API を利用するための API トークンを発行します。下のページの Create Token をクリックしてください。
なんかいっぱいありますが、一番下の Custom token を選択します。
公式ドキュメントにあるようにいくつか権限を与えて作成します。
When using API Token authentication, the token should be granted Zone Read, DNS Edit privileges, and access to All zones.
ここで作成されたトークンを忘れないようにメモしておきます。
ExternalDNS デプロイ
続いて ExternalDNS をデプロイします。今回は以下のようなリソースを作成しました。Secret の部分は先ほど作成したトークンに置き換えてください。
external-dns.yaml
起動したかどうか確かめます。
動作チェック
適当な Ingress を作成し記載したドメインが登録されるか調べます。
dns-sample.yaml
1 分ほどすると DNS レコードが登録されているようなログが流れてきました。
確認しに行くと確かに DNS レコードが増えていることが確認できます。
この状態で nginx.your.domain にアクセスすると Nginx の Welcome メッセージが表示されます。
最後に作成した Ingress を削除し DNS レコードが削除されることを確かめます。
cert-manager
先ほどまでで DNS レコードが自動で作成されるようになりました。かなりいい感じですね。 ですが、まだ TLS 証明書を発行していないため通信は暗号化されておらずセキュアな通信ではありません。 そこで証明書の発行や更新を自動で行ってくれる cert-manager を利用します。
cert-manager - cert-manager Documentation
かなり多くの認証局を利用できるようですが、無料で利用できる Let’s Encrypt を使います。
インストール
Helm - cert-manager Documentation
今回も Helm を使ってインストールします。CRD をインストールする方法として kubectl を使う方法もあるようですが、
Recommended for ease of use & compatibility
と書かれている Helm を使う方法でいきます。
詳しくは上記のリンクを参照してください。
2~3 分程かかったのでコーヒーなどを飲んでいるといいと思います。
Issuer 作成
Cloudflare - cert-manager Documentation
今回は先ほど作成した ExternalDNS と連携して TLS 証明書を発行するようにするため Cloudflare 用の設定を行います。 ExternalDNS と同じようにこちらもいくつか権限を与えて作成します。詳しくは上記ドキュメントを参照してください。
先ほどメモしたトークンを使って以下のようなIssuer
を作成します。
Issuer
は実際に証明書を発行するリソースで、これにはIssuer
とClusterIssuer
の 2 つがあります。
違いはネームスペースをまたいで利用できるかどうかです。普通の環境ではIssuer
を使うべきですが、
お家 kubernetes で私しか使わないため今回はClusterIssuer
にしています。
cluster-issuer.yaml
spec.acme.privateKeySecretRef
に指定した名前の Secret が作成されそこに TLS の秘密鍵が保存されるようです。
また、Let’s Encrypt には制限が強い production と弱い staging の 2 つがあるので、それを使い分けられるように 2 つIssuer
を作成します。
- NGINX イングレスのセキュリティ保護 - 証明書マネージャーのドキュメント (cert-manager.io)
- ステージング環境 - Let’s Encrypt - フリーな SSL/TLS 証明書 (letsencrypt.org)
これらのリソースを apply します。
動作チェック
最後に動作チェックします。すべての設定が完了したので一番初めに示したリソースを利用できるはずです。
cert-sample.yaml
作成には時間がかかる場合があります。うまくいっていれば以下のような出力を得られるはずです。
以下のコマンドを実行することで発行された証明書の情報を確認できます。
今回は証明書の発行に annotation を用いましたが、直接証明書を表すCertificate
を作成してそれを適用させることもできます。
詳しくは公式ドキュメントをご覧ください。
- Frequently Asked Questions (FAQ) - cert-manager Documentation
- Securing Ingress Resources - cert-manager Documentation
最後にリソースを片付けます。自動で作成される Secret は削除されないので手動で消します。
終わりに
すばらしい OSS のおかげで内部の挙動をほぼわかっていなくてもここまで行うことができました。 ひとまず、お家 kubernetes が 1 ステップ成長したような気がしてうれしいです。
次の目標として以下を考えています。
- node や pod のメトリクスを自動収集してかっこいいダッシュボードで見られるようにする
- devcontainer のように kubernetes 内で開発できるようにする
- 外部からのアクセスをお家 kubernetes で処理できるようにする
まだまだ先は遠いですが 1 つづつこなして、僕の考えた最強の kubernetes に近づけていきたいと思います。
余談
普段の作業ログを Obsidian を使って記録しているのですが、画像をコピペした時に作られる場所をカスタムできるのをはじめて知りました。 めちゃくちゃ便利なこの機能をもっと早く知りたかった…