とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど

開催予定の勉強会

読者登録と各種SNSのフォローもよろしくお願いいたします。

オンプレミスでCircleCI Serverを動かそう(その4) Nomadクライアントの構築編

オンプレミスでCircleCI Serverを動かそうシリーズの第4回です。前回までで、CircleCI Serverのコントロールプレーンは動作しました。今回は実際にジョブを実行するNomadクライアントを構築します。

Terraform設定ファイルの取得

Nomadクライアントは、EKSクラスターとは別に、EC2のノード群を用意しなくてはなりません。様々なコンポーネントが必要になりますが、これらを一発で構築できるTerraform設定ファイルが用意されています。まずはこのリポジトリをクローンします。今回はバージョン3.4.0リリースを使用します。

$ git clone -b 3.4.0 --depth 1 https://github.com/CircleCI-Public/server-terraform.git

必要なパラメーターの取得

実際に構築を行うにあたり、様々なパラメーターを指定したmain.tfファイルが必要となります。サンプルがクローンしたディレクトリ内のnomad-aws/examples/basic/main.tfとして用意されていますので、このファイルをベースに作成するとよいでしょう。それに先立ち、まずはmain.tfに入力するためのパラメーターを調べます。

以下のコマンドを実行して、クラスターが動作しているVPCのIDを調べます。vpc-xxxxxといった文字列が得られるはずです。

$ aws eks describe-cluster --name=circleci-server --query 'cluster.resourcesVpcConfig.vpcId'

以下のコマンドを実行して、VPCが持っているCIDRブロックを調べます。本ブログの設定通りにeksctlを実行していれば、10.21.0.0/16というCIDRが得られるはずです。

$ aws ec2 describe-vpcs --filters Name=vpc-id,Values=(上で調べたVPCのID) --query 'Vpcs[0].CidrBlock'

以下のコマンドを実行して、eksctlが作成したプライベートサブネットを調べます。本ブログの設定通りにeksctlを実行していれば、subnet-xxxxxxというサブネットIDが3つ表示されるはずです。

$ aws ec2 describe-subnets --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=eksctl-circleci-server-cluster/SubnetPrivate*" --query 'Subnets[].SubnetId'

以下のコマンドを実行して、eksctlが作成したパブリックサブネットを調べます。subnet-xxxxxxというサブネットIDが3つ表示されるはずです。

$ aws ec2 describe-subnets --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=eksctl-circleci-server-cluster/SubnetPublic*" --query 'Subnets[].SubnetId'

以下のコマンドを実行して、Nomadサーバーのエンドポイントを調べます。これはnomad-server-externalというサービスの、External-IPです。xxxxxxxx.elb.ap-northeast-1.amazonaws.comといった文字列が得られるはずです。

$ kubectl get svc nomad-server-external -n circleci-server -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'

Terraformの実行

ここまでの情報が揃ったら、以下の内容でnomad-aws/examples/basic/main.tfを書き換えます。VPCは既に作成済みですので、サンプルにあるmodule "vpc"ブロックは不要なため、まるごと削除してしまってください。

terraform {
  required_version = ">=0.15.2"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>3.0"
    }
  }
}

provider "aws" {
  # EKSクラスターを作成したリージョンを指定
  region = "ap-northeast-1"
}

module "nomad-aws" {
  source = "../.."

  # 起動するノード数を指定
  nodes = 2

  # Nomadクライアントが動作するパブリックサブネットのリスト
  subnets = [
    "subnet-aaaaaa",
    "subnet-bbbbbb",
    "subnet-cccccc"
  ]

  # VPC IDを記述
  vpc_id = "vpc-xxxxxx"

  # Nomadサーバーのエンドポイントを記述
  server_endpoint = "xxxxxxxx.elb.ap-northeast-1.amazonaws.com:4647"

  # DNSサーバーのIPアドレスを記述
  # これはVPCが使用しているCIDRの3番目のIPアドレスになる
  dns_server = "10.21.0.2"

  # ジョブ内からのアクセスをブロックしたいプライベートサブネットのリスト
  blocked_cidrs = [
    "subnet-xxxxxx",
    "subnet-yyyyyy",
    "subnet-zzzzzz"
  ]

  nomad_auto_scaler = false
  max_nodes         = 5
}

output "nomad_module" {
  value = module.nomad-aws
}

main.tfが用意できたら、nomad-aws/examples/basic/ディレクトリ内で以下のコマンドを実行します。

$ terraform init
$ terraform plan
$ terraform apply

Terraformの実行が正常に終了すると、以下のようにNomadサーバーの設定に必要な証明書、秘密鍵、認証局証明書が出力されます。これらを控えておいてください。

Outputs:

nomad_module = {
  "mtls_enabled" = true
  "nomad_asg_arn" = ""
  "nomad_asg_name" = ""
  "nomad_asg_user_access_key" = ""
  "nomad_asg_user_secret_key" = ""
  "nomad_role" = ""
  "nomad_server_cert" = <<-EOT
  -----BEGIN CERTIFICATE-----
   ...略...
  -----END CERTIFICATE-----

CircleCI ServerにNomadを設定する

Nomadクライアントの構築が完了したら、CircleCI Serverの管理コンソールに戻ってください。ページ上部に表示されているConfigをクリックすると、初期設定を行った画面に遷移できます。ここで先ほどmTLSを無効にしたNomadの設定を改めて行いましょう。

「Nomad Load Balancer Hostname」には、先ほど調べたNomadサーバーのエンドポイントを入力します。「Enable mTLS」をEnabledに切替え、「Nomad Server Certificate」「Nomad Server Private Key」「Nomad Server CA Certificate」には、Terraformが出力した証明書や秘密鍵を貼り付けてください*1。なおTerraformのOutputには行頭に半角スペースが入っているため、削除しておいた方がいいかもしれません*2

CircleCI Serverの管理コンソールに戻り、Nomadの設定を行う

アウトプットプロセッサーを設定する

以下のコマンドを実行して、アウトプットプロセッサーのエンドポイントを取得します。Nomadサーバー同様、ELBのホスト名が得られるはずです。

$ kubectl get svc output-processor -n circleci-server -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'

得られた値を「Output Processor Load Balancer Hostname」に入力してください。

アウトプットプロセッサーのエンドポイントを設定する

変更した設定の反映

ページ最下部のSave Configをクリックしたら、表示されるダイアログでGo to updated versionをクリックします。

クリックすると、デプロイ画面に遷移する

コンフィグが変更されたバージョンが用意されますので、Deployボタンをクリックしてください。更新が反映されます。

新しいバージョンをデプロイしよう

ジョブを実行する

Nomadクライアントが正常に接続できていれば、コンテナ内でジョブが実行できる状態になっているはずです。クラウド版のCircleCIと同様にプロジェクトをセットアップして、ジョブを実行してみましょう。もしジョブがPendingのまま進まないといったことが起きているのであれば、こちらを参考に、Nomad Podに入ってステータスを確認してみてください。

正常にセットアップできていれば、このようにジョブが実行できるはず

なおNomadクライアントだけでは、Remote DockerやMachine Executorを利用することができません。そこで次回は仮想マシンでジョブを実行できる、VMサービスのセットアップ方法を紹介します。

*1:それぞれ-----BEGIN 〜 -----の行から-----END 〜-----の行までです

*2:試していませんが、そのままペーストだと動かないかもしれません