> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure cluster logging

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    <p>Cluster logging collects container and system logs, storing them in OpenSearch Dashboards for analysis and debugging. Logging is a paid feature.</p>

    <Steps>
      <Step title="Open the cluster">
        <Frame>
          <img src="https://mintcdn.com/gcore/c2W3cwtGjSbFG_V1/images/docs/edge-ai/managed-kubernetes/configure-cluster-logging/configure-cluster-logging-image1.png?fit=max&auto=format&n=c2W3cwtGjSbFG_V1&q=85&s=85ded34b923f5d56a0afac1101b5a026" alt="Kubernetes Clusters list with doc-k8s-test cluster in Provisioned status" width="1024" height="327" data-path="images/docs/edge-ai/managed-kubernetes/configure-cluster-logging/configure-cluster-logging-image1.png" />
        </Frame>
      </Step>

      <Step title="Navigate to the Logging tab">
        <Frame>
          <img src="https://mintcdn.com/gcore/c2W3cwtGjSbFG_V1/images/docs/edge-ai/managed-kubernetes/configure-cluster-logging/configure-cluster-logging-image2.png?fit=max&auto=format&n=c2W3cwtGjSbFG_V1&q=85&s=42e9dd90c6fb8491d681987e736b6177" alt="Cluster detail page with the Logging tab highlighted" width="1024" height="271" data-path="images/docs/edge-ai/managed-kubernetes/configure-cluster-logging/configure-cluster-logging-image2.png" />
        </Frame>
      </Step>

      <Step title="Toggle Enable Logging" />

      <Step title="Select a log topic">
        Select an existing log topic or create a new one.
      </Step>

      <Step title="Click Save" />
    </Steps>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>Cluster logging forwards container and system logs to Gcore Logging-as-a-Service (LaaS), where they are stored in OpenSearch Dashboards. Logging requires a destination region — a Gcore region that hosts a LaaS instance — which may differ from the cluster region.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required, along with a
      [project ID](/api-reference/cloud/projects/list-projects)
      and a [region ID](/api-reference/cloud/regions/list-regions).
    </Info>

    <p>Set the following environment variables before running the examples:</p>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    export CLUSTER_NAME="{YOUR_CLUSTER_NAME}"
    ```

    ## List available destination regions

    <p>Each cluster region has a set of LaaS destination regions where logs can be forwarded. Retrieve the list before enabling logging to get the correct `destination_region_id`.</p>

    ```bash theme={null}
    curl "https://api.gcore.com/cloud/v1/laas/$GCORE_CLOUD_REGION_ID/destination_regions" \
      -H "Authorization: APIKey $GCORE_API_KEY"
    ```

    <p>The API returns:</p>

    ```json theme={null}
    {
      "count": 1,
      "results": [
        {
          "region_id": 76,
          "region_name": "Luxembourg-2"
        }
      ]
    }
    ```

    <p>Use the `region_id` from this response as `destination_region_id` in the enable call below.</p>

    ## Enable logging

    <p>Pass the destination region, a topic name, and an optional retention period. The topic is created automatically if it does not exist.</p>

    | Field                     | Required | Description                               |
    | ------------------------- | -------- | ----------------------------------------- |
    | `enabled`                 | Yes      | Set to `true` to start log forwarding     |
    | `destination_region_id`   | Yes      | LaaS region from the list above           |
    | `topic_name`              | No       | Topic to write logs to; created if absent |
    | `retention_policy.period` | No       | Log retention in days                     |

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import os
        import time
        import gcore

        client = gcore.Gcore()
        cluster_name = os.environ["CLUSTER_NAME"]

        result = client.cloud.k8s.clusters.update(
            cluster_name=cluster_name,
            logging={
                "enabled": True,
                "destination_region_id": 76,  # from the destination regions list
                "topic_name": "my-cluster-logs",
                "retention_policy": {"period": 30},
            },
        )

        task_id = result.tasks[0]
        while True:
            task = client.cloud.tasks.get(task_id)
            if task.state in ("FINISHED", "ERROR"):
                break
            time.sleep(5)

        print("Logging enabled:", task.state)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"
            "time"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            projectID, _ := strconv.ParseInt(os.Getenv("GCORE_CLOUD_PROJECT_ID"), 10, 64)
            regionID, _ := strconv.ParseInt(os.Getenv("GCORE_CLOUD_REGION_ID"), 10, 64)
            clusterName := os.Getenv("CLUSTER_NAME")

            client := gcore.NewClient()
            ctx := context.Background()

            result, err := client.Cloud.K8S.Clusters.Update(ctx, clusterName, cloud.K8SClusterUpdateParams{
                ProjectID: gcore.Int(projectID),
                RegionID:  gcore.Int(regionID),
                Logging: cloud.K8SClusterUpdateParamsLogging{
                    Enabled:             gcore.Bool(true),
                    DestinationRegionID: gcore.Int(76), // from the destination regions list
                    TopicName:           gcore.String("my-cluster-logs"),
                    RetentionPolicy: cloud.LaasIndexRetentionPolicyParam{
                        Period: gcore.Int(30),
                    },
                },
            })
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            taskID := result.Tasks[0]
            for {
                task, _ := client.Cloud.Tasks.Get(ctx, taskID)
                if task.State == "FINISHED" || task.State == "ERROR" {
                    fmt.Println("Logging enabled:", task.State)
                    break
                }
                time.Sleep(5 * time.Second)
            }
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X PATCH "https://api.gcore.com/cloud/v2/k8s/clusters/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$CLUSTER_NAME" \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{
            "logging": {
              "enabled": true,
              "destination_region_id": 76,
              "topic_name": "my-cluster-logs",
              "retention_policy": {"period": 30}
            }
          }'
        ```

        Response:

        ```json theme={null}
        {"tasks": ["84162eb4-2555-4348-bead-dbc0c578d2de"]}
        ```
      </Tab>
    </Tabs>

    <p>The API returns a task ID. Poll <code>GET /cloud/v1/tasks/{task_id}</code> every five seconds until `state` is `FINISHED`.</p>

    ## Disable logging

    <p>Set `enabled` to `false` to stop log forwarding. The existing log topic and its data are preserved in OpenSearch Dashboards.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import os
        import time
        import gcore

        client = gcore.Gcore()
        cluster_name = os.environ["CLUSTER_NAME"]

        result = client.cloud.k8s.clusters.update(
            cluster_name=cluster_name,
            logging={"enabled": False},
        )

        task_id = result.tasks[0]
        while True:
            task = client.cloud.tasks.get(task_id)
            if task.state in ("FINISHED", "ERROR"):
                break
            time.sleep(5)

        print("Logging disabled:", task.state)
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "os"
            "strconv"
            "time"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            projectID, _ := strconv.ParseInt(os.Getenv("GCORE_CLOUD_PROJECT_ID"), 10, 64)
            regionID, _ := strconv.ParseInt(os.Getenv("GCORE_CLOUD_REGION_ID"), 10, 64)
            clusterName := os.Getenv("CLUSTER_NAME")

            client := gcore.NewClient()
            ctx := context.Background()

            result, err := client.Cloud.K8S.Clusters.Update(ctx, clusterName, cloud.K8SClusterUpdateParams{
                ProjectID: gcore.Int(projectID),
                RegionID:  gcore.Int(regionID),
                Logging: cloud.K8SClusterUpdateParamsLogging{
                    Enabled: gcore.Bool(false),
                },
            })
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            taskID := result.Tasks[0]
            for {
                task, _ := client.Cloud.Tasks.Get(ctx, taskID)
                if task.State == "FINISHED" || task.State == "ERROR" {
                    fmt.Println("Logging disabled:", task.State)
                    break
                }
                time.Sleep(5 * time.Second)
            }
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl -X PATCH "https://api.gcore.com/cloud/v2/k8s/clusters/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$CLUSTER_NAME" \
          -H "Authorization: APIKey $GCORE_API_KEY" \
          -H "Content-Type: application/json" \
          -d '{"logging": {"enabled": false}}'
        ```

        Response:

        ```json theme={null}
        {"tasks": ["task-uuid"]}
        ```
      </Tab>
    </Tabs>

    <p>The API returns a task ID. Poll <code>GET /cloud/v1/tasks/{task_id}</code> every five seconds until `state` is `FINISHED`.</p>
  </MethodSection>

  <MethodSection id="terraform" label="Terraform">
    <p>Configure log forwarding for an existing GPU Kubernetes cluster using the [`gcore_cloud_k8s_cluster`](https://registry.terraform.io/providers/G-Core/gcore/latest/docs/resources/cloud_k8s_cluster) resource from the [Terraform provider](/developer-tools/terraform/overview) v2. The `logging` attribute is a nested block — import the cluster before making changes.</p>

    <Info>
      An [API token](/account-settings/api-tokens), a [project ID](/api-reference/cloud/projects/list-projects), and a [region ID](/api-reference/cloud/regions/list-regions) are required. To find valid `destination_region_id` values, query <code>GET /cloud/v1/laas/{region_id}/destination\_regions</code>.
    </Info>

    ## Enable logging

    <p>Add the `logging` block with `enabled = true`, a destination region, and a topic name. Run `terraform import` first if the cluster is not yet under Terraform management.</p>

    ```hcl theme={null}
    resource "gcore_cloud_k8s_cluster" "example" {
      project_id    = var.project_id
      region_id     = var.region_id
      name          = "my-gpu-k8s"
      version       = "v1.35.3"
      keypair       = "my-ssh-key"
      fixed_network = var.network_id
      fixed_subnet  = var.subnet_id

      logging = {
        enabled               = true
        destination_region_id = 76  # from GET /cloud/v1/laas/{region_id}/destination_regions
        topic_name            = "my-cluster-logs"
        retention_policy = {
          period = 30
        }
      }

      pools = [
        {
          name                 = "gpu-pool"
          flavor_id            = "bm3-ai-1xlarge-a100-80-8"
          min_node_count       = 1
          max_node_count       = 3
          auto_healing_enabled = true
        }
      ]
    }
    ```

    ```bash theme={null}
    terraform import gcore_cloud_k8s_cluster.example '<project_id>/<region_id>/<cluster_name>'
    terraform apply
    ```

    ## Disable logging

    <p>Set `enabled = false` to stop log forwarding. The log topic and its data in OpenSearch Dashboards are preserved.</p>

    ```hcl theme={null}
    resource "gcore_cloud_k8s_cluster" "example" {
      project_id    = var.project_id
      region_id     = var.region_id
      name          = "my-gpu-k8s"
      version       = "v1.35.3"
      keypair       = "my-ssh-key"
      fixed_network = var.network_id
      fixed_subnet  = var.subnet_id

      logging = {
        enabled = false
      }

      pools = [
        {
          name                 = "gpu-pool"
          flavor_id            = "bm3-ai-1xlarge-a100-80-8"
          min_node_count       = 1
          max_node_count       = 3
          auto_healing_enabled = true
        }
      ]
    }
    ```
  </MethodSection>
</MethodSwitch>
