EKS on EC2にHCP Consulを接続してみる

2023.06.22

「HCP Consulをさくっと試してみたい」

HCP Consulのサービスメッシュの機能を試してみたいことがありました。

サービスメッシュを試すのは、EKSクラスターを用意したりが必要で少し面倒です。

簡単に試せる方法はないかと思っていたら、いい感じのサンプルコードが用意されていました。

terraform-aws-hcp-consul/examples/hcp-eks-demo at main · hashicorp/terraform-aws-hcp-consul · GitHub

このサンプルコードは、EKSクラスターの作成~ConsulのインストールまでTerraformでやっています。

簡単にHCP Consulと接続したEKSクラスターを作成できたため、紹介します。

HCP Consulとは

ConsulはHashiCorpが提供しているネットワーク関連のツールです。

サービスディスカバリやサービスメッシュの機能等を提供しています。

Consulの概要については、HashiCorpのYoutubeで分かりやすく解説されています。

01 はじめてのConsul - YouTube

ConsulはOSSでも提供されていますが、HCP ConsulとしてSaas版も提供されています。

OSSのConsulは自前でKubernetesクラスター等にインストールする必要がありますが、HCP Consulではユーザー側でConsul Clusterのインフラ管理不要で使用できます。

HashiCorp Consul: Enterprise Pricing, Packages & Features

やってみた

HCPクライアントシークレット発行

サンプルコードのTerraform実行に必要なため、HCPクライアントシークレットを発行します。

クライアントシークレットは、Access control(IAM) -> Service principals内で作成できます。

Terraformコード確認

main.tfの中身は以下です。最新の状態やその他のファイル(variables.tf、output.tf等)はGitHubをご確認ください。

terraform-aws-hcp-consul/examples/hcp-eks-demo at main · hashicorp/terraform-aws-hcp-consul · GitHub

main.tf

# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

data "aws_availability_zones" "available" {
  filter {
    name   = "zone-type"
    values = ["availability-zone"]
  }
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.78.0"

  name                 = "${var.cluster_id}-vpc"
  cidr                 = "10.0.0.0/16"
  azs                  = data.aws_availability_zones.available.names
  public_subnets       = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnets      = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true
}

data "aws_eks_cluster" "cluster" {
  count = var.install_eks_cluster ? 1 : 0
  name  = module.eks[0].cluster_id
}

data "aws_eks_cluster_auth" "cluster" {
  count = var.install_eks_cluster ? 1 : 0
  name  = module.eks[0].cluster_id
}

module "eks" {
  count                  = var.install_eks_cluster ? 1 : 0
  source                 = "terraform-aws-modules/eks/aws"
  version                = "17.24.0"
  kubeconfig_api_version = "client.authentication.k8s.io/v1beta1"

  cluster_name    = "${var.cluster_id}-eks"
  cluster_version = "1.25"
  subnets         = module.vpc.private_subnets
  vpc_id          = module.vpc.vpc_id

  manage_aws_auth = false

  node_groups = {
    application = {
      name_prefix    = "hashicups"
      instance_types = ["t3a.medium"]

      desired_capacity = 3
      max_capacity     = 3
      min_capacity     = 3
    }
  }
}

# The HVN created in HCP
resource "hcp_hvn" "main" {
  hvn_id         = var.hvn_id
  cloud_provider = "aws"
  region         = var.hvn_region
  cidr_block     = var.hvn_cidr_block
}

# Note: Uncomment the below module to setup peering for connecting to a private HCP Consul cluster
# module "aws_hcp_consul" {
#   source  = "hashicorp/hcp-consul/aws"
#   version = "~> 0.12.1"
#
#   hvn                = hcp_hvn.main
#   vpc_id             = module.vpc.vpc_id
#   subnet_ids         = module.vpc.private_subnets
#   route_table_ids    = module.vpc.private_route_table_ids
#   security_group_ids = var.install_eks_cluster ? [module.eks[0].cluster_primary_security_group_id] : [""]
# }

resource "hcp_consul_cluster" "main" {
  cluster_id         = var.cluster_id
  hvn_id             = hcp_hvn.main.hvn_id
  public_endpoint    = true
  tier               = var.tier
  min_consul_version = "v1.14.0"
}

resource "hcp_consul_cluster_root_token" "token" {
  cluster_id = hcp_consul_cluster.main.id
}

module "eks_consul_client" {
  source  = "hashicorp/hcp-consul/aws//modules/hcp-eks-client"
  version = "~> 0.12.1"

  boostrap_acl_token = hcp_consul_cluster_root_token.token.secret_id
  cluster_id         = hcp_consul_cluster.main.cluster_id
  # strip out url scheme from the public url
  consul_hosts     = tolist([substr(hcp_consul_cluster.main.consul_public_endpoint_url, 8, -1)])
  consul_version   = hcp_consul_cluster.main.consul_version
  datacenter       = hcp_consul_cluster.main.datacenter
  k8s_api_endpoint = var.install_eks_cluster ? module.eks[0].cluster_endpoint : ""

  # The EKS node group will fail to create if the clients are
  # created at the same time. This forces the client to wait until
  # the node group is successfully created.
  depends_on = [module.eks]
}

module "demo_app" {
  count   = var.install_demo_app ? 1 : 0
  source  = "hashicorp/hcp-consul/aws//modules/k8s-demo-app"
  version = "~> 0.12.1"

  depends_on = [module.eks_consul_client]
}

ざっくり以下のリソースを作成しています。

  • AWS
    • VPC
    • EKS Cluste
  • HCP
    • HCP Consul Cluster
    • HVN
  • Kubernetes
    • デモアプリ用各種リソース

ちなみに、EKSとHCP Consulを接続するには、最低以下のステップが必要です。 (Consul ClusterをPrivateにする場合は、VPCピアリングなど必要)

手順
HCP Portal 1. HVN(Hashicorp Virtual Network)とHCP Consul Cluster作成
2. EKSからHCP Consulに通信するためのToken発行
Kubernetes(EKS) 3. HCP ConsulのTokenをSecrets登録
4. HelmでHCP Consulをインストール

Terraformのmodule等を使っていい感じに抽象化してくれていますね。

Terraform実行

発行したHCPクライアントシークレットを環境変数に設定します。

$ export HCP_CLIENT_ID=<クライアントID>
$ export HCP_CLIENT_SECRET=<クライアントシークレット>

AWS認証情報を設定します。

$ export AWS_ACCESS_KEY_ID=<AWSアクセスキー>
$ export AWS_SECRET_ACCESS_KEY=<AWSシークレットアクセスキー>
$ export AWS_SESSION_TOKEN=<(必要に応じて)AWSセッショントークン>

terraform applyでリソースをデプロイします。

$ git clone git@github.com:hashicorp/terraform-aws-hcp-consul.git
$ cd examples/hcp-eks-demo
$ terraform init
$ terraform apply

サンプルアプリケーションの確認

デプロイが成功すると、以下のようなサンプルアプリケーションが表示されます。(terraformのoutputsのhashicups_url)

Consul確認

terraformのoutputsのconsul_urlにアクセスしてみると、以下の画面が表示されます。

Serviceを選択すると、他のサービスとどう通信するかといったことも確認できます。

後片付け

以下コマンドで作成したリソースを削除します。

terraform destroy

まとめ

HCP ConsulをEKSに接続してみました。

Service Meshの製品ということで、設定が大変という印象を持っていました。

しかし、実際にやってみると思ったより導入ハードルは低いと感じました。

TerraformでHCPのProviderやConsulのModuleが提供されており、記述量を抑えつつ設定ができました。

以上、AWS事業本部の佐藤(@chari7311)でした。

参考