febc技術メモ

Japanese version of http://febc-yamamoto.hatenablog.com

RKEでAWS上にKubernetes(v1.10)をデプロイする

f:id:febc_yamamoto:20180529205711p:plain

Rancher Blogに新しい記事(RKE+AWS)が投稿されてた

今月半ばにRancher Labsのブログに以下の記事が投稿されていました。

Rancher Blog: How To Deploy Kubernetes Clusters On AWS Using RKE

AWS上にRKEを用いてKubernetesクラスタを構築するという内容です。

でもRKEの最新版だと動かない…

手順が丁寧に書かれていてわかりやすい内容なのですが、利用しているRKEのバージョン(v0.1.5)が古く、最新版を利用するとうまく動きませんでした。

そこで、最新版できちんと動かすために必要な作業についてこの記事にまとめてみました。

ついでにTerraformでコード化しました

記事を書くついでにこの構成を手軽に試せるようにTerraformTerraformのRKEプロバイダーを利用してコマンド一発で構築できるようにもしました。

Terraform + RKEプロバイダーのtfファイル

ということで早速RKEの最新版での動かし方をみていきます。

RKE(v0.1.7) + AWSでKubernetes

TL;DR

  • 基本はRancher Blogに記載の手順でOK
  • RKEの最新版であるv0.1.7はデフォルトではKubernetes v1.10がデプロイされる
  • Kubernetes v1.10でAWS向けのCloud Controller Managerを利用する場合、ClusterIDが指定されていないとkubeletの起動に失敗する
  • なので以下リソースにClusterID用のタグを付与すればOK

解説

RKEの最新版であるv0.1.7はデフォルトではKubernetes v1.10がデプロイされる

まず、Rancher Blogの該当記事で利用されているRKEのバージョンはv0.1.5です。
このバージョンではrke upを実行すると(デフォルトでは)Kubernetes v1.8がデプロイされていました。

なので、後述するClusterIDが設定されていなくても問題なく利用できていたようですね。

Kubernetes v1.10でAWS向けのCloud-Controller-Managerを利用する場合、ClusterIDが指定されていないとkubeletの起動に失敗する

Kubernetes v1.10のCHANGE LOGを見ると、以下のPRによるものです。

kubernetes/kubernetes #60125

対応: 各リソースにClusterID用のタグを付与する

ということで、Kubernetes v1.10を使う場合はClusterIDを指定すればOKということですね。
タグの付け方についてはRancherのドキュメントに記載がありました。

Rancher docs: Kubernetes - Cloud Providers / Configuring the ClusterID

このドキュメントによると、 - サブネット - セキュリティグループ - EC2インスタンス に対してkubernetes.io/cluster/CLUSTERID=ownedのようなタグをつければ良いとのことでした。
IDはCLUSTERIDの部分を任意の値に書き換えることで設定可能です。

Terraform + RKEプロバイダーで構築する

ClusterID用のタグをつけるのは割と面倒な作業なのでTerraformでコード化しました。
以下のリポジトリでコードを公開しています。

GitHub: yamamoto-febc/k8s_on_aws_with_terraform

なお、このコードではRKEプロバイダーを利用して、RKEでのKubernetesクラスタ構築までを一気に行なっています。

RKEプロバイダーについては以下の記事を参照ください。

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

以下コードのポイントを解説しておきます。

IAMプロファイルの作成

(※Rancher Blogでの該当部分)

この辺りは以下のtfファイルにまとめています。

https://github.com/yamamoto-febc/k8s_on_aws_with_terraform/blob/master/aws/iam.tf

ClusterID用のタグ付与

サブネット/セキュリティグループ/EC2インスタンスに対してタグを指定しています。
以下のような感じです。

# タグの定義
locals {
  cluster_id_tag = "${map("kubernetes.io/cluster/${var.cluster_id}", "owned")}"
}

# 利用するリージョン内の全AZのデフォルトサブネットを対象にClusterID用のタグを付与
data "aws_availability_zones" "az" {}
resource "aws_default_subnet" "default" {
  availability_zone = "${data.aws_availability_zones.az.names[count.index]}"
  count             = "${length(data.aws_availability_zones.az.names)}"
  
  tags              = "${local.cluster_id_tag}" #タグの指定
}

サブネットについてはデフォルトサブネットに対してタグ付与しています。
また、セキュリティグループについてはRancher Blogと同じく全許可のルールとしています。

ノードのプロビジョニング

(※Rancher Blogでの該当部分)

Dockerをインストールして、SSH接続の際に利用するユーザー(記事ではubuntu)をDockerグループに入れる必要があります。

tfファイル上はremote-execを利用して以下のようにしています。

resource "aws_instance" "rke-node" {
  count = 4

  ami                    = "${data.aws_ami.ubuntu.id}"
  instance_type          = "${var.instance_type}"
  key_name               = "${aws_key_pair.rke-node-key.id}"
  iam_instance_profile   = "${aws_iam_instance_profile.rke-aws.name}"
  vpc_security_group_ids = ["${aws_security_group.allow-all.id}"]
  tags                   = "${local.cluster_id_tag}"

  provisioner "remote-exec" {
    connection {
      user        = "ubuntu"
      private_key = "${tls_private_key.node-key.private_key_pem}"
    }

    # Dockerのインストールとdockerグループへの追加
    inline = [
      "curl releases.rancher.com/install-docker/1.12.sh | bash",
      "sudo usermod -a -G docker ubuntu",
    ]
  }
}

なお、インスタンスタイプは記事ではt2.largeが推奨されていますが、軽く試すだけならt2.microで十分でした。
(tfファイル上はデフォルトでt2.microにしました)

RKEの実行

(※Rancher Blogでの該当部分)

RKEの実行はRKEプロバイダーに任せます。
以下のようなtfファイルとなります。

module "nodes" {
  source = "./aws"
}

resource rke_cluster "cluster" {
  cloud_provider {
    name = "aws"
  }

  nodes = [
    {
      address = "${module.nodes.addresses[0]}"
      user    = "${module.nodes.ssh_username}"
      ssh_key = "${module.nodes.private_key}"
      role    = ["controlplane", "etcd"]
    },
    {
      address = "${module.nodes.addresses[1]}"
      user    = "${module.nodes.ssh_username}"
      ssh_key = "${module.nodes.private_key}"
      role    = ["worker"]
    },
    {
      address = "${module.nodes.addresses[2]}"
      user    = "${module.nodes.ssh_username}"
      ssh_key = "${module.nodes.private_key}"
      role    = ["worker"]
    },
    {
      address = "${module.nodes.addresses[3]}"
      user    = "${module.nodes.ssh_username}"
      ssh_key = "${module.nodes.private_key}"
      role    = ["worker"]
    },
  ]
}

RKEコマンドを直接実行する場合は、rke up実行後にカレントディレクトリにkube_config_cluster.ymlファイルが作成されます。
RKEプロバイダーの場合はデフォルトでは作成されませんので、以下のようにlocal-file機能でファイル出力しています。

resource "local_file" "kube_cluster_yaml" {
  filename = "./kube_config_cluster.yml"
  content  = "${rke_cluster.cluster.kube_config_yaml}"
}

terraform apply実行後にexport KUBECONFIG=$PWD/kube\_config\_cluster.ymlを実行しておけばkubectlが利用できるはずです。

後はRancher Blogの内容をそのまま進めていけるはずです。


ということでRancher Blogの補足をしつつ、Terraform + RKEプロバイダーで環境構築してみました。

なおこの構成は全通信許可などのガバガバ設定になっていますので検証などでのみ利用してくださいね!!

以上です。