varu3/techBlog

IT infrastructure technology memo.

Kopsでnodesが64つ以上認識しない問題

Kopsを使うに当たって、少しレアなケースに遭遇しましたので残しておきます。事象としては、いざKubernetesのノードを増台するぞ!となった時に64つ以上認識されないという問題。

$ kubectl get nodes | grep Ready | wc -l
64

あれ、100つくらい指定したはずなのにな、おかしいなと思って各ノードのログを見てみると以下のようにエラーが吐かれ続けていました。

sudo journalctl -b -f
I05XX XX:XX:XX.497565    9194 glogger.go:31] ->[XX.XX.XX.XX:3999] error during connection attempt: Connection limit reached (64)

Connection limit reached!!!!つまりKopsで立ち上がるのには64つ以上はつなげられないよ、ということらしい。この時点でかなり焦りましたが、落ち着いてコードを読みます。

kops/gossip.go at master · kubernetes/kops · GitHub

func NewMeshGossiper(listen string, channelName string, nodeName string, password []byte, seeds gossip.SeedProvider) (*MeshGossiper, error) {
    meshConfig := mesh.Config{
        ProtocolMinVersion: mesh.ProtocolMinVersion,
        Password:           password,
        ConnLimit:          64,
        PeerDiscovery:      true,
        //TrustedSubnets:     []*net.IPNet{},
    }

今回、構成したクラスタはゴシッププロトコルを使っていました。その場合のConnLimitが確かに64にハードコーディングされていることがわかります。

さらにkopsのリポジトリを漁ってみると、これに関するPRも送られているようでした。

というわけなんですが、どうやらこれらはまだMergeされていない様子。どうしようか考えあぐねた挙句、Mergeされるのを待つよりはこれを自前でBuildして使うことにしました。

protokube

kopsではkopsコマンドで立ち上がったnodeがnodeupという独自のプロビジョニングツールが起動して、protokubeというkubernetes関連のデーモンをよしなに起動してくれるプロセスが立ち上がります。

ドキュメントはこちら

Kopsではゴシッププロトコルでマスターをクラスタリングしていたのですがが、その制御もこのprotokubeがやってくれているとのこと。

独自のkops(protokube)をbuildする手順

それではこのprotokubeをビルドしてみます。kopsはgoで書かれているので、Goとビルドするためのdockerがインストールされている必要があります。今回はAWSのS3上にbuildしたバイナリを配置して、ノードが立ち上がる際はそこを参照して持ってくるというようにします。

mkdir ~/kops
cd ~/kops
export GOPATH=`pwd`
go get -d k8s.io/kops
cd ${GOPATH}/src/k8s.io/kops/
export S3_BUCKET_NAME={{保存したいS3バケット名}}
export KOPS_STATE_STORE=s3://${S3_BUCKET_NAME}
export KOPS_BASE_URL=https://${S3_BUCKET_NAME}.s3.amazonaws.com/kops/{バージョン名}/
make kops-install upload S3_BUCKET=s3://${S3_BUCKET_NAME} VERSION={バージョン名}

kopsとprotokube, nodeupのビルドが実行され、正常に完了したらS3にアップロードされます。

aws s3 ls s3://{指定したバケット名}/kops/{VERSION名}/images/                           2018-XX-XX XX:XX:XX   75691605 protokube.tar.gz
2018-XX-XX XX:XX:XX         41 protokube.tar.gz.sha1

protokubeがアップロードされていることがわかりますね。 続いて、これを使うためにはkopsが実行できるサーバで以下の環境変数を用意する必要があります。

export PROTOKUBE_IMAGE=https://${S3_BUCKET_NAME}.s3.amazonaws.com/kops/{バージョン名}/images/protokube.tar.gz
export PROTOKUBE_VERSION={VERSION名}

上記のコマンドで環境変数を設定した状態で、'kops update cluster'を実行します。すると、LaunchConfigurationが編集されて、指定したS3のバケットが指定されていることがわかると思います。既存のマスターが存在している場合は、kops update後にkops rolling-update clusterを実行しますので、マスターが再作成されます。

これで独自のkops(protokube)を指定しての構築が可能です。

protokubeのGOSSIP_DNS_CONN_LIMITを設定する。

上記のMRでは、独自にGOSSIP_DNS_CONN_LIMITを設定する必要がありますので、マスターに入って以下のファイルに変数を書き込みます。

/etc/environment
GOSSIP_DNS_CONN_LIMIT=100

今回はLIMITを100に設定しました。その後、この設定を反映するために再度、プロビジョニングする必要があります。手動でプロビジョニングするためには以下のコマンドを実行します。

$ cd /var/cache/kubernetes-install
$ ./nodeup --conf=/var/cache/kubernetes-install/kube_env.yaml --v=8

コマンドが実行されて、ノードが100まで認識されるようになったはずです。

終わりに

 いざノードを増やすという時にこのエラーが発生したため、とても焦りました。ドキュメントにも記載がなかったため、手探りながらissueとか眺めながらこのように対応しました。おそらく、このPRがマージされたkops 1.10.Xではこのような問題は起こらなるとは思うので、備忘録的にこの手順を残しておきます。