はじめに
公式サイトがイカす
k3s とは
k8sの色々を削ぎ落としたものらしい
- 使われていないコードなど
バイナリ一枚で40MB程度で軽い、とのこと (はたして40MBは軽いと言えるのか)
基本の使い方
Linux 3.10以上のマシンの上で以下を実行
sh curl -sfL https://get.k3s.io | sh -
agent を追加する
これも簡単で、k3sのバイナリを以下のように実行する
$ sudo k3s agent --server https://参加したいクラスタのIP:6443 --token ${NODE_TOKEN} NAME STATUS ROLES AGE VERSION ip-172-31-38-39 Ready 21m v1.13.3-k3s.6 ip-172-31-38-54 Ready 97m v1.13.3-k3s.6
やったね、楽勝
リモートで使いたい
同じネットワーク内でk3sを立ち上げて使う
これは特に問題ないはず
k3sを立ち上げると /etc/rancher/k3s/k3s.yaml
にファイルが配置される
これは同じマシン上に存在するクラスタに接続するためのファイルで、別のマシンから接続するにはこのファイルの一部を同じネットワーク内のk3sが建っているマシンに向ける
apiVersion: v1 clusters: - cluster: certificate-authority-data: hogefuga - server: https://localhost:6443 + server: https://k3sが建っているマシンのプライベートIPを入れる:6443 name: default contexts: - context: cluster: default user: default name: default current-context: default kind: Config preferences: {} users: - name: default user: password: hogefuga username: admin
k3sが建っているマシンのプライベートIPを入れる
は 以降 (プライベートIP)
と表記する
あとはこのymlを指定しながら kubectl
を叩けばよさそう
kubectl --kubeconfig ~/.kube/k3s.yml get all
外部ネットワークからk3sのクラスタに接続する
頑張ってセキュア(?)なままアクセスしてみる
外部から愚直に(グローバルIPを直接指定して)接続する場合、上記手順だけでは接続できない
$ kubectl --kubeconfig ~/.kube/k3s.yml get all Unable to connect to the server: x509: certificate is valid for 127.0.0.1,(プライベートIP), not (グローバルIP)
どうやら証明書の対象が127.0.0.1とプライベートIPのみらしい 確認してみる
$ openssl s_client -connect localhost:6443 2>/dev/null | openssl x509 -text | grep -A 1 "Subject Alternative Name" X509v3 Subject Alternative Name: DNS:, IP Address:127.0.0.1, IP Address:(プライベートIP)
つまり、表示されたIP以外ではこの証明書は有効にならないのでクライアント側から通信を弾く状態となる
プライベートIPが動的にSANに割り当てられるところを見るとどうやらこの証明書はk3s内部で動的に生成しているようだ
どこで作成しているか追ってみる
k3s/server.go at f90cbed4081e7e1e6972861c196543b2d253bfcc · rancher/k3s · GitHub
func knownIPs() []string { ips := []string{ "127.0.0.1", } ip, err := net.ChooseHostInterface() if err == nil { ips = append(ips, ip.String()) } return ips }
IPアドレスの文字列の配列を返す関数が見つかる
(このオブジェクトは serverConfig.TLSConfig.KnownIPs
に渡され、追っていくと後に norman(rancher製のサーバーアプリケーションの実装?) に渡される)
net.ChooseHostInterface
というのはk8sでも使われているutilに生えている関数で、ネットワークインターフェイスからIPを1つ取得して返す (Golangわからんけど合ってるよね?)
- 先程まで雑に「プライベートIP」と読んでいたものの正体はこれっぽい
GoDoc k8s.io/apimachinery/pkg/util/net#ChooseHostInterface
apimachinery/interface.go at master · kubernetes/apimachinery · GitHub
この関数のIPのリストにグローバルIPを追加で書き込んでビルド、起動してみる (良い手ではないと思う)
func knownIPs() []string { ips := []string{ "127.0.0.1", + "グローバルIP", } ip, err := net.ChooseHostInterface() if err == nil { ips = append(ips, ip.String()) } return ips }
すると、SANにもグローバルIPが追加される事が分かる
$ openssl s_client -connect localhost:6443 2>/dev/null | openssl x509 -text | grep -A 1 "Subject Alternative Name" X509v3 Subject Alternative Name: DNS:, IP Address:127.0.0.1, IP Address:(グローバルIP), IP Address:(プライベートIP)
これで kubectl
を叩くと接続できるようになる
$ kubectl --kubeconfig ~/.kube/k3s.yml get all NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.43.0.1 443/TCP 49m
これ、手法としてだいぶダーティーだし、本当はもうちょっと別の手を取るべきなんだろうけど全然わからなかった
誰か正しい方法を教えてくれ〜
(もしこれが正しいのであれば何故k3sにはhostnameを受け取る起動引数が無いのだろうか…)
insecure-skip-tls-verify: true
する
単にこちら側が弾いているだけなので、tls verifyをスキップすることでクラスターにアクセスできるようになる
apiVersion: v1 clusters: - cluster: certificate-authority-data: hogefuga server: https://グローバルIP:6443 + insecure-skip-tls-verify: true name: default contexts: - context: cluster: default user: default name: default current-context: default kind: Config preferences: {} users: - name: default user: password: hogefuga username: admin
または
$ kubectl --kubeconfig ~/.kube/k3s.yml get all --insecure-skip-tls-verify=true
結局どうするのが正解なの??
k3sのユースケース
k3sリポジトリの記念すべき1つめのissueもユースケースを尋ねるものだった
製作者のDarren Shepherd曰く、これは軽量のk8sを作るためのプロダクトだとのこと
https://github.com/rancher/k3s/issues/1#issuecomment-424943047
軽く使えることが大きな理由となるような事に利用するものなのだろうと想像している
- 実際公式サイトの方でもEdgeとかIoTとかCIとか書かれている
個人的にとても良いと思っているのはk8sの練習台として使うユースケースがある
k8sの練習を行う場合、勿論ながら何かしらの形でクラスタを用意する必要がある
おおよそminikubeかDocker for Desktopに付属のk8sを使うことになると思うが、ここに第三の選択肢としてk3sを上げることが出来るようになった
これは上で説明したように簡単に立ち上げることが出来るし、他より動作が軽いために気軽さはとても大きいと思う
しかもノードの追加も容易なため、複数ノード構成の練習も簡単に出来る
- 多分先程挙げたminikube, Docker for Desktopのk8sで複数ノード構成を取るより容易
- そもそもこの2つで複数ノード構成出来るのか?
↓こんな docker-compose.yml もあるので、 github.com
$ docker-compose up -d $ kubectl get node --kubeconfig kubeconfig.yaml
とすればすぐにk8sの環境が立ち上がるの、普通に便利では?