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

# Equinix Metal

> Creating Talos clusters with Equinix Metal.

export const release_v1_13 = 'v1.13.0';

export const VersionWarningBanner = () => {
  const latestVersion = "v1.13";
  const [latestUrl, setLatestUrl] = useState(null);
  const [currentVersion, setCurrentVersion] = useState(null);
  const [isBeta, setIsBeta] = useState(false);
  const parseVersion = v => v.replace("v", "").split(".").map(Number);
  const isGreaterVersion = (a, b) => {
    const [aMajor, aMinor] = parseVersion(a);
    const [bMajor, bMinor] = parseVersion(b);
    if (aMajor > bMajor) return true;
    if (aMajor === bMajor && aMinor > bMinor) return true;
    return false;
  };
  useEffect(() => {
    if (typeof window === "undefined") return;
    const {pathname, hash, search} = window.location;
    const match = pathname.match(/\/talos\/(v\d+\.\d+)\//);
    if (!match) return;
    const detectedVersion = match[1];
    if (detectedVersion === latestVersion) return;
    setCurrentVersion(detectedVersion);
    if (isGreaterVersion(detectedVersion, latestVersion)) {
      setIsBeta(true);
    }
    const newPath = pathname.replace(`/talos/${detectedVersion}/`, `/talos/${latestVersion}/`);
    setLatestUrl(`${newPath}${search}${hash}`);
  }, []);
  if (!latestUrl || !currentVersion) return null;
  return <div className="not-prose sticky top-6 z-50 my-6">
      <div className="border border-yellow-500/30 bg-yellow-500/10 px-4 py-3 rounded-xl">
        <div className="text-sm">
          {isBeta ? <>
              ⚠️ You are viewing a <strong>beta version</strong> of Talos ({currentVersion}).
              This version may be unstable.
              <a href={latestUrl} className="ml-2 underline text-yellow-400 hover:text-yellow-300 font-medium">
                View latest stable version {latestVersion} →
              </a>
            </> : <>
              ⚠️ You are viewing an older version of Talos ({currentVersion}).
              <a href={latestUrl} className="ml-2 underline text-yellow-400 hover:text-yellow-300 font-medium">
                View the latest version {latestVersion} →
              </a>
            </>}
        </div>
      </div>
    </div>;
};

<VersionWarningBanner />

You can create a Talos Linux cluster on Equinix Metal in a variety of ways, such as through the EM web UI, or the `metal` command line tool.

Regardless of the method, the process is:

* Create a DNS entry for your Kubernetes endpoint.
* Generate the configurations using `talosctl`.
* Provision your machines on Equinix Metal.
* Push the configurations to your servers (if not done as part of the machine provisioning).
* Configure your Kubernetes endpoint to point to the newly created control plane nodes.
* Bootstrap the cluster.

## Define the Kubernetes endpoint

There are a variety of ways to create an HA endpoint for the Kubernetes cluster.
Some of the ways are:

* DNS
* Load Balancer
* BGP

Whatever way is chosen, it should result in an IP address/DNS name that routes traffic to all the control plane nodes.
We do not know the control plane node IP addresses at this stage, but we should define the endpoint DNS entry so that we can use it in creating the cluster configuration.
After the nodes are provisioned, we can use their addresses to create the endpoint A records, or bind them to the load balancer, etc.

## Create the machine configuration files

### Generating configurations

Using the DNS name of the loadbalancer defined above, generate the base configuration files for the Talos machines:

```bash theme={null}
$ talosctl gen config talos-k8s-em-tutorial https://<load balancer IP or DNS>:<port>
created controlplane.yaml
created worker.yaml
created talosconfig
```

> The `port` used above should be 6443, unless your load balancer maps a different port to port 6443 on the control plane nodes.

### Validate the configuration files

```bash theme={null}
talosctl validate --config controlplane.yaml --mode metal
talosctl validate --config worker.yaml --mode metal
```

> Note: Validation of the install disk could potentially fail as validation
> is performed on your local machine and the specified disk may not exist.

### Passing in the configuration as user data

You can use the metadata service provide by Equinix Metal to pass in the machines configuration.
It is required to add a shebang to the top of the configuration file.

The convention we use is `#!talos`.

## Provision the machines in Equinix Metal

Talos Linux can be PXE-booted on Equinix Metal using [Image Factory](../../learn-more/image-factory), using the `equinixMetal` platform: e.g.

<code>
  {`https://pxe.factory.talos.dev/pxe/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba/${release_v1_13}/equinixMetal-amd64`}
</code>

This URL references the default schematic for Talos version **{release_v1_13}** with an `amd64` architecture.

Follow the Image Factory guide to create a custom schematic, e.g. with CPU microcode updates.

The PXE boot URL can be used as the iPXE script URL.

### Using the Equinix Metal UI

Simply select the location and type of machines in the Equinix Metal web interface.
Select 'Custom iPXE' as the Operating System and enter the Image Factory PXE URL as the iPXE script URL, then select the number of servers to create, and name them (in lowercase only.)
Under *optional settings*, you can optionally paste in the contents of `controlplane.yaml` that was generated, above (ensuring you add a first line of `#!talos`).

You can repeat this process to create machines of different types for control plane and worker nodes (although you would pass in `worker.yaml` for the worker nodes, as user data).

If you did not pass in the machine configuration as User Data, you need to provide it to each machine, with the following command:

`talosctl apply-config --insecure --nodes <Node IP> --file ./controlplane.yaml`

### Creating a cluster via the Equinix Metal CLI

This guide assumes the user has a working API token,and the [Equinix Metal CLI](https://github.com/equinix/metal-cli/) installed.

> Note: Ensure you have prepended `#!talos` to the `controlplane.yaml` file.

<CodeBlock lang="sh">
  {`
    metal device create \\
    --project-id $PROJECT_ID \\
    --metro $METRO \\
    --operating-system "custom_ipxe" \\
    --ipxe-script-url "https://pxe.factory.talos.dev/pxe/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba/${release_v1_13}/equinixMetal-amd64" \\
    --plan $PLAN \\
    --hostname $HOSTNAME \\
    --userdata-file controlplane.yaml
    `}
</CodeBlock>

e.g. <code>{`metal device create -p <projectID> -f da11 -O custom_ipxe -P c3.small.x86 -H steve.test.11 --userdata-file ./controlplane.yaml --ipxe-script-url "https://pxe.factory.talos.dev/pxe/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba/${release_v1_13}/equinixMetal-amd64"`}</code>

Repeat this to create each control plane node desired: there should usually be 3 for a HA cluster.

## Update the Kubernetes endpoint

Now our control plane nodes have been created, and we know their IP addresses, we can associate them with the Kubernetes endpoint.
Configure your load balancer to route traffic to these nodes, or add `A` records to your DNS entry for the endpoint, for each control plane node.
e.g.

```bash theme={null}
host endpoint.mydomain.com
endpoint.mydomain.com has address 145.40.90.201
endpoint.mydomain.com has address 147.75.109.71
endpoint.mydomain.com has address 145.40.90.177
```

## Bootstrap etcd

Set the `endpoints` and `nodes` for `talosctl`:

```bash theme={null}
talosctl --talosconfig talosconfig config endpoint <control plane 1 IP>
talosctl --talosconfig talosconfig config node <control plane 1 IP>
```

Bootstrap `etcd`:

```bash theme={null}
talosctl --talosconfig talosconfig bootstrap
```

This only needs to be issued to one control plane node.

## Retrieve the `kubeconfig`

At this point we can retrieve the admin `kubeconfig` by running:

```bash theme={null}
talosctl --talosconfig talosconfig kubeconfig .
```
