Ref: https://github.com/rancher/terraform-provider-rancher2/issues/1009
Test Information
- Environment Rancher: v2.7.X
- Environment for Harvester: bare-metal or qemu
- Harvester Version: v1.1.X
- ui-source Option: Auto
- Rancher2 Terraform Provider Plugin: v3.0.X rancher2
Test Setup Rancher2 Terraform Provider:
- make sure terraform is installed at version equal or greater than 1.3.9, ie:
sudo apt install terraform
- utilize the setup-provider.sh script from the rancher2 terraform provider repo if testing an rc it would look something like
./setup-provider.sh rancher2 v3.0.0-rc1
- ensure the provider is installed, can cross check the directory structures under
~/.terraform.d/plugins/terraform.local
Setup Rancher v2.7.X
- build an API Key for Rancher utilizing this doc, keeping reference of the: access-key, secret-key, & bearer token
- import a harvester cluster into Rancher v2.7.X, keep reference of that Harvester cluster name
Additional Setup
- build out a temporary directory to preform this deep integration testing
- create the following two folders of something like:
harvester-setup
rancher-setup
- inside each folder create a:
main.tf
provider.tf
Harvester Setup
- download the Harvester kubeconfig file into the
harvester-setup
folder - inside the
harvester-setup
folder in theprovider.tf
file add:
terraform {
required_version = ">= 0.13"
required_providers {
harvester = {
source = "harvester/harvester"
version = "0.6.1"
}
}
}
provider "harvester" {
kubeconfig = "<the kubeconfig file path of the harvester cluster>"
}
- inside the
main.tf
file in theharvester-setup
folder add:
resource "harvester_image" "opensuse-leap" {
name = "opensuse-leap-15-4"
namespace = "harvester-public"
display_name = "openSUSE-Leap-15.4.x86_64-NoCloud.qcow2"
source_type = "download"
url = "https://download.opensuse.org/repositories/Cloud:/Images:/Leap_15.4/images/openSUSE-Leap-15.4.x86_64-NoCloud.qcow2"
}
data "harvester_clusternetwork" "mgmt" {
name = "mgmt"
}
resource "harvester_network" "mgmt-vlan1" {
name = "mgmt-vlan1"
namespace = "harvester-public"
vlan_id = 1
route_mode = "auto"
route_dhcp_server_ip = ""
cluster_network_name = data.harvester_clusternetwork.mgmt.name
}
(note: this will create an image to use by downloading from ubuntu and build a mgmt-vlan1 vm network, you may want to adjust this as needed if there are other naming conflicts etc) (additional note: opensuse leap images historically sometimes have problems, you may need to visit the repository to try to acquire the more-recent link for the NoCloud QCOW2 x86_64 based image, pagination is at the bottom of the page)
-
init and apply that terraform:
terraform init
(while in directory ofharvester-setup
)terraform plan
(while in directory ofharvester-setup
)terraform apply
(while in directory ofharvester-setup
)
-
validate the scripts where able to create the network and grab an image to utilize for testing
Rancher Setup
- inside the
rancher-setup
folder, in the respectiveprovider.tf
file add:
terraform {
required_providers {
rancher2 = {
source = "terraform.local/local/rancher2"
version = "3.0.0-rc2"
}
}
}
provider "rancher2" {
api_url = "<>"
access_key = "<>"
secret_key = "<>"
insecure = true
}
(note: the api_url, access_key, secret_key all reference the API key you created earlier in Rancher)
- inside the
rancher-setup
folder, in the respectivemain.tf
file add:
data "rancher2_cluster_v2" "foo-harvester" {
name = "foo-harvester"
}
# Create a new Cloud Credential for an imported Harvester cluster
resource "rancher2_cloud_credential" "foo-harvester" {
name = "foo-harvester"
harvester_credential_config {
cluster_id = data.rancher2_cluster_v2.foo-harvester.cluster_v1_id
cluster_type = "imported"
kubeconfig_content = data.rancher2_cluster_v2.foo-harvester.kube_config
}
}
# Create a new rancher2 machine config v2 using harvester node_driver
resource "rancher2_machine_config_v2" "foo-harvester-v2" {
generate_name = "foo-harvester-v2"
harvester_config {
vm_namespace = "default"
cpu_count = "2"
memory_size = "4"
disk_info = <<EOF
{
"disks": [{
"imageName": "harvester-public/opensuse-leap-15-4",
"size": 40,
"bootOrder": 1
}]
}
EOF
network_info = <<EOF
{
"interfaces": [{
"networkName": "harvester-public/mgmt-vlan1"
}]
}
EOF
ssh_user = "opensuse"
user_data = "I2Nsb3VkLWNvbmZpZwpwYWNrYWdlX3VwZGF0ZTogdHJ1ZQpwYWNrYWdlczoKICAtIHFlbXUtZ3Vlc3QtYWdlbnQKICAtIGlwdGFibGVzCnJ1bmNtZDoKICAtIC0gc3lzdGVtY3RsCiAgICAtIGVuYWJsZQogICAgLSAnLS1ub3cnCiAgICAtIHFlbXUtZ3Vlc3QtYWdlbnQuc2VydmljZQo="
}
}
resource "rancher2_cluster_v2" "foo-harvester-v2" {
name = "foo-harvester-v2"
kubernetes_version = "v1.24.11+rke2r1"
rke_config {
machine_pools {
name = "pool1"
cloud_credential_secret_name = rancher2_cloud_credential.foo-harvester.id
control_plane_role = true
etcd_role = true
worker_role = true
quantity = 1
machine_config {
kind = rancher2_machine_config_v2.foo-harvester-v2.kind
name = rancher2_machine_config_v2.foo-harvester-v2.name
}
}
machine_selector_config {
config = {
cloud-provider-name = ""
}
}
machine_global_config = <<EOF
cni: "calico"
disable-kube-proxy: false
etcd-expose-metrics: false
EOF
upgrade_strategy {
control_plane_concurrency = "10%"
worker_concurrency = "10%"
}
etcd {
snapshot_schedule_cron = "0 */5 * * *"
snapshot_retention = 5
}
chart_values = ""
}
}
(note: pay attention to change name
for the data
resource of the rancher2_cluster_v2 to your respective name that you gave your imported Harvester cluster in Rancher v2.7.X)
- init and apply that terraform:
terraform init
(while in directory ofharvester-setup
)terraform plan
(while in directory ofharvester-setup
)terraform apply
(while in directory ofharvester-setup
)
Verify Steps:
- Verify in Rancher that the RKE2 cluster is able to be provisioned and can be accessed
- Verify that the
rancher2_cluster_v2
setup can be destroyed as well w/terraform destroy
inside therancher-setup
folder - Verify VM Affinity rules work:
- in your harvester cluster of N nodes on 1 of the nodes create labels on the host, cross-reference: topology labels on harvester host
- then cultivate a JSON payload that looks something like:
{
"nodeAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{
"matchExpressions": [
{
"key": "topology.kubernetes.io/zone",
"operator": "In",
"values": [
"us-fremont-1a"
]
},
{
"key": "network.harvesterhci.io/mgmt",
"operator": "In",
"values": [
"true"
]
}
]
}
]
}
}
}
(note: replace the us-fremont-1a
for whatever zone value you provided as a topology label on the Host in your Harvester cluster)
- then base64 encode that JSON, and add it to the
main.tf
inrancher-setup
folder’sresource "rancher2_machine_config_v2" "foo-harvester-v2"
, with the property ofvm_affinity
as documented here - verify when terraform init, plan, apply, provisions the cluster, and that the cluster’s VM on Harvester is running on the respective Harvester host with the labels