Terraform + RKEでKubernetesクラスタ構築 - TerraformのRKEプロバイダー

f:id:febc_yamamoto:20180528165306p:plain

2018/5/18に東京で開催されたRancher2.0リリースパーティで以下のLTをさせていただきました。

このLTで発表したTerraformのRKEプロバイダーについてご紹介いたします。

その前に: RKE(Rancher Kubernetes Engine)とは?

RKEとは、一言で言うと「Kubernetesクラスタのデプロイツール」です。

f:id:febc_yamamoto:20180528155207p:plain

kubernetesクラスタのデプロイツールとしてはkubeadmkopsといったものもありますが、それらと比較すると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.

https://github.com/rancher/rke#requirements

RKEのドキュメントには記載されていませんが、以下のポートも必要に応じて開けておく必要があります。

f:id:febc_yamamoto:20180528155213p:plain

(初回のみ)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プロバイダーです。

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プロバイダーをお試しください。

以上です。