Blog
ブログ

2024年12月21日

IaC(Infrastructure as Code):Terraform、Coder CDEの紹介 – SOHOBB AI/BI Advent Calendar 2024

はじめに

こんにちは、
またAI/BI部のK.です。

本日は、TerraformとCoder CDEを活用してインフラ自動化についてご紹介します。

IaC(Infrastructure as Code)とは

インフラストラクチャ・アズ・コード(IaC)は、インフラストラクチャを手動のプロセスではなくコードを使用して管理およびプロビジョニングするプラクティスです。
アプリケーションコードと同様に、インフラストラクチャコードはバージョン管理システム(VCS)に保存され、
インフラストラクチャの変更が追跡可能でスケーラブルであることを保証します。
インフラストラクチャを記述的で機械可読なファイルで定義することにより、IaCは自動化、一貫性、および再現性を可能にし、人為的なエラーを減らします。

Terraformとは

Terraformとは、開発者がHCL(HashiCorp Configuration Language)と呼ばれる高水準の構成言語を使用して、
アプリケーションを実行するためのクラウドまたはオンプレミスのインフラストラクチャーの望ましい「最終状態」を記述できる宣言型コーディング・ツールです。

Coderとは

Coderは自己ホスト型のオープンソースのクラウド開発環境で、どのクラウド、IDE、OS、Gitプロバイダー、IDPとも連携します。

リモート開発の利点

  • 高速化: サーバーグレードのクラウドハードウェアで開発作業が迅速化。
  • 環境管理の簡素化: Terraform、nix、Dockerなどのツールで一貫した環境を提供。
  • セキュリティ向上: ソースコードやデータをプライベートサーバーやクラウドサービスに集中管理。
  • 互換性向上: 開発、ステージング、プロダクション環境とインフラ構成を共有。
  • アクセシビリティ向上: ブラウザベースのIDEやリモートIDE拡張でどのデバイスからでも接続可能。



Coderの特徴:

  • ARM、Windows、Linux、macOSワークスペースを同時にサポート。
  • VMや専用ワークスペースを使用し、カーネル機能を活用。
  • 永続的なワークスペースを提供。


CoderはGNU Affero General Public License v3.0の下で無料でオープンソースです。プレミアムライセンスも利用可能です。
Coderの動作:
⇒ CoderワークスペースはTerraformで表現され、AWS EC2、Azure、Google Cloud、Kubernetesなどのテンプレートが利用可能です。

Coderは以下のものではありません:

  • インフラストラクチャーコード(IaC)プラットフォーム
  • DevOps/CIプラットフォーム
  • オンラインIDE
  • コラボレーションプラットフォーム
  • SaaS/完全管理型サービス


Coderは自己ホスト型のソリューションで、プライベートデータセンターやAWS、Azure、GCPなどのクラウドサービスにホストする必要があります。
そして、なんでTerraformの紹介にCoderが入っているの?
⇒ TerraformはCoderで最初にサポートされたIaCプロビジョナーであり、Coder管理者がTerraformリソースをCoderワークスペースとして定義できます。

やってみよう

今回はCoderのインストールしたり、Terraformのベーシック構文を理解したり、簡単にDocker Containerで開発環境を構築してみようと思います。

Coderのインストール

まず、公式インストールガイドを目を通していただく: Coder/Docs/Install
今回Ubuntu 22.04環境でDocker Composeを使用して、Coderをインストールすることになります。

docker-compose.yamlGithub/coder/docker-compose.yaml)
services:
  coder:
    image: ghcr.io/coder/coder:${CODER_VERSION:-latest}
    ports:
      - "8080:8080"
    env_file:
      - ./.env
    environment:
      CODER_PG_CONNECTION_URL: "postgresql://${POSTGRES_USER:-username}:${POSTGRES_PASSWORD:-password}@database/${POSTGRES_DB:-coder}?sslmode=disable"
      CODER_HTTP_ADDRESS: "${CODER_HTTP_ADDRESS}"
      CODER_ACCESS_URL: "${CODER_ACCESS_URL}"
    user: root
    privileged: true
    group_add:
      - "999" # docker group on host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - coder_home:/home/coder
    depends_on:
      database:
        condition: service_healthy
  database:
    image: "postgres:16"
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-username}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
      POSTGRES_DB: ${POSTGRES_DB:-coder}
    volumes:
      - coder_data:/var/lib/postgresql/data
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -U ${POSTGRES_USER:-username} -d ${POSTGRES_DB:-coder}",
        ]
      interval: 5s
      timeout: 5s
      retries: 5
volumes:
  coder_data:
  coder_home:
.env
POSTGRES_USER=coder
POSTGRES_PASSWORD=<openssl rand -hex 16>
POSTGRES_DB=coder
CODER_ACCESS_URL=http://192.168.0.99:8080
CODER_HTTP_ADDRESS=0.0.0.0:8080
CODER_TLS_ENABLE=false
CODER_TLS_ADDRESS=0.0.0.0:8443
CODER_REDIRECT_TO_ACCESS_URL=true
CODER_TELEMETRY_ENABLE=false

 

そして、 docker compose up -d

 

 

 

管理者(admin)の情報を登録すると、ホーム画面に入れます。

 

 

ワークスペースを作成します

 

 

Dockerテンプレートを選択し、Docker Containerをプロバイダーとしてワークスペースを作成できます。

 

 

Docker Containerのところ、Use templateボタンを押下

 

そして、Create templateを押下すると、プロビジョニングが開始される

 

プロビジョニングが完了したと、TemplatesにDocker Containersというテンプレートが表示されます。

 

そして、Create Workspaceを押下

 

そして、ワークスペースのDockerイメージをビルドされる:

 

すべて完了したら、ワークスペースのプレビュー画面が表示される:

 

ワークスペースに接続するためのオプションから選択すると、こちらは code-server 選択し、WebバージョンのVSCodeが開いてきました。

 

Terraform(HCL)構文の説明とCoder Workspace Templateカスタマイズ

Coder上、Templatesのところを開いて、ワークスペースリストが表示される

 

Source Codeのタブに遷移して、main.tfというファイルにEditを押下する

 

今出てきた画面だと、Terraform(HCL)のソースコードです。

 

Terraformの基本的な構文について説明しましょう。コードを見ながら、主要な部分を解説します。

  • 基本的なブロック構造 Terraformは主にブロックで構成され、以下のような形式を取ります:
    ブロック名 "リソース名" "識別子" {
        設定項目 = 値
    }
  • 主要なブロックタイプ:
    # プロバイダーの設定
    terraform {
      required_providers {
        プロバイダー名 = {
          source = "ソース/プロバイダー"
        }
      }
    }
    
    # 変数の定義
    variable "変数名" {
      type        = string  # 型の指定
      default     = "デフォルト値"
      description = "説明"
    }
    
    # ローカル変数
    locals {
      変数名 = 値
    }
    
    # リソースの定義
    resource "タイプ" "名前" {
      設定項目 = 値
    }
  • よく使う式や関数:
    # 文字列補間
    name = "${var.環境名}-instance"
    
    # 条件式
    value = 条件 ? 真の場合の値 : 偽の場合の値
    
    # データ参照
    data.データソース名.識別子.属性
  • カスタマイズの例:

     

    ベーシック
    # コンテナのリソースを追加
    resource "docker_container" "custom_app" {
      name  = "my-custom-app"
      image = "nginx:latest"
      ports {
        internal = 80
        external = 8080
      }
    }
    
    # 環境変数の追加
    variable "app_environment" {
      type    = string
      default = "development"
    }
    
    # メタデータの追加
    metadata {
      display_name = "Custom Metric"
      key          = "custom_metric"
      script       = "echo 'Custom metric value'"
      interval     = 30
      timeout      = 1
    }

     

    コンテナの設定変更
    # メモリとCPUの制限を追加
    resource "docker_container" "workspace" {
      count = data.coder_workspace.me.start_count
      image = "codercom/enterprise-base:ubuntu"
      name  = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
      
      # リソース制限の追加
      cpu_shares = 1024        # CPU共有の相対値
      memory     = 2048        # メモリ制限(MB)
      
      # ヘルスチェックの追加
      healthcheck {
        test     = ["CMD", "curl", "-f", "http://localhost:13337/healthz"]
        interval = "30s"
        timeout  = "10s"
        retries  = 3
      }
      
      # 追加のマウントポイント
      volumes {
        container_path = "/workspace"
        host_path      = "/path/to/workspace"
        read_only      = false
      }
      
      # ネットワーク設定
      networks_advanced {
        name = "development-network"
      }
      
      # 環境変数の拡張
      env = [
        "CODER_AGENT_TOKEN=${coder_agent.main.token}",
        "ENVIRONMENT=development",
        "DEBUG=true"
      ]
      
      # 既存の設定はそのまま維持
      host {
        host = "host.docker.internal"
        ip   = "host-gateway"
      }
      
      # 既存のラベル設定を維持しつつ、新しいラベルを追加
      labels {
        label = "coder.owner"
        value = data.coder_workspace_owner.me.name
      }
      labels {
        label = "environment"
        value = "development"
      }
      labels {
        label = "project"
        value = "coder-workspace"
      }
    }

     

    新しいアプリケーションの追加
    # Jupyterノートブックの追加
    resource "coder_app" "jupyter" {
      agent_id     = coder_agent.main.id
      slug         = "jupyter"
      display_name = "Jupyter Notebook"
      url          = "http://localhost:8888"
      icon         = "/icon/jupyter.svg"
      subdomain    = false
      share        = "owner"
    
      healthcheck {
        url       = "http://localhost:8888/api/health"
        interval  = 5
        threshold = 6
      }
    }
    
    # Jupyterのインストールスクリプトをagentの起動スクリプトに追加
    resource "coder_agent" "main" {
      # 既存の設定を維持
      startup_script = <<-EOT
        set -e
    
        # 既存のcode-serverのインストールと設定
        curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
        /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
    
        # Jupyterのインストールと設定
        pip3 install jupyter
        jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --NotebookApp.token='' --NotebookApp.password='' &
      EOT
    }

     

    モニタリング設定の変更
    # カスタムメタデータの追加
    resource "coder_agent" "main" {
      # 既存のメタデータを維持しつつ、新しいメタデータを追加
      metadata {
        display_name = "Network I/O"
        key          = "8_network_io"
        script       = <

     

    ストレージ設定のカスタマイズ
    # 追加のボリューム設定
    resource "docker_volume" "workspace_data" {
      name = "coder-${data.coder_workspace.me.id}-data"
      
      # バックアップドライバーの設定
      driver = "local"
      
      driver_opts = {
        type   = "none"
        device = "/path/to/backup/location"
        o      = "bind"
      }
    
      # ラベル設定
      labels {
        label = "coder.owner"
        value = data.coder_workspace_owner.me.name
      }
      labels {
        label = "coder.owner_id"
        value = data.coder_workspace_owner.me.id
      }
      labels {
        label = "coder.workspace_id"
        value = data.coder_workspace.me.id
      }
      labels {
        label = "backup.enabled"
        value = "true"
      }
      
      # ライフサイクル設定
      lifecycle {
        prevent_destroy = true
        ignore_changes  = [driver_opts]
      }
    }
    
    # 永続的なキャッシュボリューム
    resource "docker_volume" "workspace_cache" {
      name = "coder-${data.coder_workspace.me.id}-cache"
      
      labels {
        label = "coder.owner"
        value = data.coder_workspace_owner.me.name
      }
      labels {
        label = "coder.type"
        value = "cache"
      }
    }
    
    # コンテナにボリュームをマウント
    resource "docker_container" "workspace" {
      # 既存の設定に加えて、新しいボリュームをマウント
      volumes {
        container_path = "/data"
        volume_name    = docker_volume.workspace_data.name
        read_only      = false
      }
      
      volumes {
        container_path = "/cache"
        volume_name    = docker_volume.workspace_cache.name
        read_only      = false
      }
    }
また、これらの設定を実際に適用する前に、以下の点に注意することをお勧めします:
  • バックアップのパスやマウントポイントは環境に合わせて適切に設定する
  • リソース制限値は実際の環境に合わせて調整する
  • 新しいアプリケーションを追加する場合は、必要なポートの開放やネットワーク設定を確認する
  • モニタリング設定のインターバルは負荷に応じて調整する

最後に

Infrastructure as CodeとTerraformを活用したCoder Cloud Development Environmentの構築は、開発環境の標準化と自動化において大きな可能性を秘めています。
この記事で見てきたように、HCLの直感的な構文と柔軟なカスタマイズ性により、以下のような利点が得られます:
  • 環境の一貫性と再現性
    • リストコードによる環境定義により、全ての開発者が同じ環境で作業できる
    • リストバージョン管理により、環境の変更履歴を追跡可能
  • 効率的な環境管理
    • インフラストラクチャの変更を自動化し、人的ミスを削減
    • リソースの使用状況を可視化し、効率的な運用が可能
  • 拡張性と柔軟性
    • 必要に応じて環境をカスタマイズ可能
    • 新しいツールや要件に応じて環境を進化させることができる
  • 開発生産性の向上
    • 環境構築の時間を大幅に削減
    • チーム全体で統一された開発体験を提供
これらのツールと手法を組み合わせることで、モダンな開発環境の構築と運用が可能になり、
開発チームの生産性と品質の向上に大きく貢献することが期待できます。
今後は、コンテナ技術やクラウドサービスの進化に合わせて、さらなる機能の拡張や利便性の向上が見込まれます。
開発者は、これらのツールを活用することで、より効率的で信頼性の高い開発環境を実現できるでしょう。

このページの先頭へ