-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add an example for Talos on OCI
adds example Terraform code and documentation to deploy Talos on Oracle Cloud Signed-off-by: Andrey Smirnov <[email protected]> Signed-off-by: Caleb Woodbine <[email protected]>
- Loading branch information
1 parent
1be5874
commit 2346f82
Showing
12 changed files
with
1,046 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# Oracle Cloud Terraform Example | ||
|
||
Example of a highly available Kubernetes cluster with Talos on Oracle Cloud. | ||
|
||
## Prequisites | ||
|
||
**general** | ||
|
||
- a top-level tenancy | ||
|
||
**install things** | ||
|
||
``` bash | ||
brew install oci-cli hashicorp/tap/terraform siderolabs/tap/talosctl qemu | ||
``` | ||
|
||
## Notes | ||
|
||
- although not officially supported by Oracle Cloud, network LoadBalancers are provided through the Oracle Cloud Controller (only officially supported on OKE) | ||
- this guide will target arm64, though you can replace with amd64 if it doesn't suit your needs | ||
- instances will only launch with firmware set to UEFI_64 and lauch mode set to PARAVIRTUALIZED | ||
|
||
## Uploading an image | ||
|
||
Unfortunately due to upload constraints, this portion of the deployment is unable to be run using Terraform. This may change in the future. | ||
|
||
Prepare and upload a Talos disk image for Oracle Cloud, with | ||
|
||
1. create a storage bucket: https://cloud.oracle.com/object-storage/buckets | ||
2. using Talos Linux Image Factory, create a plan and generate an image to use. See this example: https://factory.talos.dev/?arch=arm64&cmdline=console%3DttyAMA0&cmdline-set=true&extensions=-&platform=oracle&target=cloud&version=1.8.0 | ||
3. download the disk image (ending in raw.xz) | ||
4. define the image metadata, with the steps under the section "**defining metadata**" | ||
5. repack the image, with steps under the section "**repacking the image**" | ||
6. upload the image to the storage bucket under objects | ||
7. under object and view object details, copy the dedicated endpoint url. Example: https://axe608t7iscj.objectstorage.us-phoenix-1.oci.customer-oci.com/n/axe608t7iscj/b/talos/o/talos-v1.8.0-oracle-arm64.oci | ||
|
||
### defining metadata | ||
|
||
create a file called `image_metadata.json` with contents such as | ||
|
||
``` json | ||
{ | ||
"version": 2, | ||
"externalLaunchOptions": { | ||
"firmware": "UEFI_64", | ||
"networkType": "PARAVIRTUALIZED", | ||
"bootVolumeType": "PARAVIRTUALIZED", | ||
"remoteDataVolumeType": "PARAVIRTUALIZED", | ||
"localDataVolumeType": "PARAVIRTUALIZED", | ||
"launchOptionsSource": "PARAVIRTUALIZED", | ||
"pvAttachmentVersion": 2, | ||
"pvEncryptionInTransitEnabled": true, | ||
"consistentVolumeNamingEnabled": true | ||
}, | ||
"imageCapabilityData": null, | ||
"imageCapsFormatVersion": null, | ||
"operatingSystem": "Talos", | ||
"operatingSystemVersion": "1.8.0", | ||
"additionalMetadata": { | ||
"shapeCompatibilities": [ | ||
{ | ||
"internalShapeName": "VM.Standard.A1.Flex", | ||
"ocpuConstraints": null, | ||
"memoryConstraints": null | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
|
||
### repacking the image | ||
|
||
decompress the downloaded disk image artifact from factory | ||
|
||
``` bash | ||
xz --decompress DISK_IMAGE.raw.xz | ||
``` | ||
|
||
use `qemu-img` to convert the image to qcow2 | ||
|
||
``` bash | ||
qemu-img convert -f raw -O qcow2 oracle-arm64.raw oracle-arm64.qcow2 | ||
``` | ||
|
||
repack the image as a tar file with the metadata | ||
|
||
``` bash | ||
tar zcf oracle-arm64.oci oracle-arm64.qcow2 image_metadata.json | ||
``` | ||
|
||
## Create a .tfvars file | ||
|
||
to configure authentication and namespacing, create a `.tfvars` file with values from the links placeholding in the example below | ||
|
||
``` hcl | ||
tenancy_ocid = "TENANCY OCID : https://cloud.oracle.com/tenancy" | ||
user_ocid = "YOUR USER OCID : https://cloud.oracle.com/identity/domains/my-profile" | ||
private_key_path = "YOUR PRIVATE KEY PATH : https://cloud.oracle.com/identity/domains/my-profile/api-keys" | ||
fingerprint = "THE FINGERPRINT FOR YOUR PRIVATE KEY : ^^" | ||
region = "YOUR PREFERRED REGION : https://cloud.oracle.com/regions" | ||
compartment_ocid = "YOUR COMPARTMENT OCID : https://cloud.oracle.com/identity/compartments" | ||
talos_image_oci_bucket_url = "YOUR DEDICATED BUCKET OBJECT URL : https://cloud.oracle.com/object-storage/buckets" | ||
``` | ||
|
||
## Bringing it up | ||
|
||
prepare the local direction for using Terraform | ||
|
||
``` bash | ||
terraform init | ||
``` | ||
|
||
verify the changes to provision | ||
|
||
``` bash | ||
terraform plan -var-file=.tfvars | ||
``` | ||
|
||
apply the changes | ||
|
||
``` bash | ||
terraform apply -var-file=.tfvars | ||
``` | ||
|
||
get the talosconfig | ||
|
||
``` bash | ||
terraform output -raw talosconfig > ./talosconfig | ||
``` | ||
|
||
get the kubeconfig | ||
|
||
``` bash | ||
terraform output -raw kubeconfig > ./kubeconfig | ||
``` | ||
|
||
destroy the worker nodes | ||
|
||
``` bash | ||
terraform destroy -var-file=.tfvars -target=random_pet.worker | ||
``` | ||
|
||
destroy | ||
|
||
``` bash | ||
terraform destroy -var-file=.tfvars | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
data "oci_identity_compartment" "this" { | ||
id = var.compartment_ocid | ||
} | ||
|
||
data "oci_identity_availability_domains" "availability_domains" { | ||
#Required | ||
compartment_id = var.tenancy_ocid | ||
} | ||
|
||
data "oci_core_image_shapes" "image_shapes" { | ||
depends_on = [oci_core_shape_management.image_shape] | ||
#Required | ||
image_id = oci_core_image.talos_image.id | ||
} | ||
|
||
data "talos_image_factory_extensions_versions" "this" { | ||
# get the latest talos version | ||
talos_version = var.talos_version | ||
filters = { | ||
names = var.talos_extensions | ||
} | ||
} | ||
|
||
data "talos_image_factory_urls" "this" { | ||
talos_version = var.talos_version | ||
schematic_id = talos_image_factory_schematic.this.id | ||
platform = "oracle" | ||
architecture = var.architecture | ||
} | ||
|
||
data "talos_client_configuration" "talosconfig" { | ||
cluster_name = var.cluster_name | ||
client_configuration = talos_machine_secrets.machine_secrets.client_configuration | ||
endpoints = [for k, v in oci_core_instance.controlplane : v.public_ip] | ||
nodes = concat( | ||
[for k, v in oci_core_instance.controlplane : v.public_ip], | ||
[for k, v in oci_core_instance.worker : v.private_ip] | ||
) | ||
} | ||
|
||
data "talos_machine_configuration" "controlplane" { | ||
cluster_name = var.cluster_name | ||
# cluster_endpoint = "https://${var.kube_apiserver_domain}:6443" | ||
cluster_endpoint = "https://${oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address}:6443" | ||
|
||
machine_type = "controlplane" | ||
machine_secrets = talos_machine_secrets.machine_secrets.machine_secrets | ||
|
||
talos_version = var.talos_version | ||
kubernetes_version = var.kubernetes_version | ||
|
||
docs = false | ||
examples = false | ||
|
||
config_patches = [ | ||
local.talos_base_configuration, | ||
<<-EOT | ||
machine: | ||
features: | ||
kubernetesTalosAPIAccess: | ||
enabled: true | ||
allowedRoles: | ||
- os:reader | ||
allowedKubernetesNamespaces: | ||
- kube-system | ||
EOT | ||
, | ||
yamlencode({ | ||
machine = { | ||
certSANs = concat([ | ||
var.kube_apiserver_domain, | ||
oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address, | ||
], | ||
[for k, v in oci_core_instance.controlplane : v.public_ip] | ||
) | ||
} | ||
cluster = { | ||
apiServer = { | ||
certSANs = concat([ | ||
var.kube_apiserver_domain, | ||
oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address, | ||
], | ||
[for k, v in oci_core_instance.controlplane : v.public_ip] | ||
) | ||
} | ||
} | ||
}), | ||
] | ||
} | ||
|
||
data "talos_machine_configuration" "worker" { | ||
cluster_name = var.cluster_name | ||
# cluster_endpoint = "https://${var.kube_apiserver_domain}:6443" | ||
cluster_endpoint = "https://${oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address}:6443" | ||
|
||
machine_type = "worker" | ||
machine_secrets = talos_machine_secrets.machine_secrets.machine_secrets | ||
|
||
talos_version = var.talos_version | ||
kubernetes_version = var.kubernetes_version | ||
|
||
docs = false | ||
examples = false | ||
|
||
config_patches = [ | ||
local.talos_base_configuration, | ||
<<EOF | ||
machine: | ||
disks: | ||
- device: /dev/sdb | ||
partitions: | ||
- mountpoint: /var/lib/longhorn | ||
kubelet: | ||
extraMounts: | ||
- destination: /var/lib/longhorn | ||
type: bind | ||
source: /var/lib/longhorn | ||
options: | ||
- bind | ||
- rshared | ||
- rw | ||
EOF | ||
, | ||
yamlencode({ | ||
machine = { | ||
certSANs = concat([ | ||
var.kube_apiserver_domain, | ||
oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address, | ||
], | ||
[for k, v in oci_core_instance.controlplane : v.public_ip] | ||
) | ||
} | ||
cluster = { | ||
apiServer = { | ||
certSANs = concat([ | ||
var.kube_apiserver_domain, | ||
oci_network_load_balancer_network_load_balancer.controlplane_load_balancer.ip_addresses[0].ip_address, | ||
], | ||
[for k, v in oci_core_instance.controlplane : v.public_ip] | ||
) | ||
} | ||
} | ||
}), | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
resource "oci_identity_dynamic_group" "oci-ccm" { | ||
#Required | ||
name = "${var.cluster_name}-oci-ccm" | ||
compartment_id = var.tenancy_ocid # tenancy_ocid, compartment_ocid and domain_ocid doesn't work | ||
description = "Instance access" | ||
matching_rule = "ALL {instance.compartment.id = '${var.compartment_ocid}'}" | ||
|
||
#Optional | ||
freeform_tags = local.common_labels | ||
} | ||
|
||
locals { | ||
ns_type_name = strcontains(var.compartment_ocid, ".tenancy.") ? "tenancy" : "compartment" | ||
ns_select_name = strcontains(var.compartment_ocid, ".compartment.") ? data.oci_identity_compartment.this.name : "" | ||
} | ||
|
||
resource "oci_identity_policy" "oci-ccm" { | ||
#Required | ||
name = "${var.cluster_name}-oci-ccm" | ||
compartment_id = var.tenancy_ocid | ||
description = "Instance access" | ||
statements = [ | ||
// LoadBalancer Services | ||
"Allow dynamic-group ${oci_identity_dynamic_group.oci-ccm.name} to read instance-family in ${local.ns_type_name} ${local.ns_select_name}", | ||
"Allow dynamic-group ${oci_identity_dynamic_group.oci-ccm.name} to use virtual-network-family in ${local.ns_type_name} ${local.ns_select_name}", | ||
"Allow dynamic-group ${oci_identity_dynamic_group.oci-ccm.name} to manage load-balancers in ${local.ns_type_name} ${local.ns_select_name}", | ||
] | ||
|
||
#Optional | ||
freeform_tags = local.common_labels | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
resource "oci_core_image" "talos_image" { | ||
#Required | ||
compartment_id = var.compartment_ocid | ||
|
||
#Optional | ||
display_name = "Talos ${var.talos_version}" | ||
freeform_tags = local.common_labels | ||
launch_mode = local.instance_mode | ||
|
||
image_source_details { | ||
source_type = "objectStorageUri" | ||
source_uri = var.talos_image_oci_bucket_url | ||
|
||
#Optional | ||
operating_system = "Talos Linux" | ||
operating_system_version = var.talos_version | ||
source_image_type = "QCOW2" | ||
} | ||
} | ||
|
||
resource "oci_core_shape_management" "image_shape" { | ||
#Required | ||
compartment_id = var.compartment_ocid | ||
image_id = oci_core_image.talos_image.id | ||
shape_name = var.instance_shape | ||
} |
Oops, something went wrong.