diff --git a/ml-platform/README.md b/ml-platform/README.md index 672ed7df6..d6a1058fb 100644 --- a/ml-platform/README.md +++ b/ml-platform/README.md @@ -57,18 +57,46 @@ This is the quick-start deployment guide. It can be used to set up an environmen ### Requirements -- New Google Cloud Project, preferably with no APIs enabled +In this guide you can choose to bring your project (BYOP) or have Terraform create a new project for you. The requirements are difference based on the option that you choose. + +#### Bring your own project (BYOP) + +- Project ID of a new Google Cloud Project, preferably with no APIs enabled - `roles/owner` IAM permissions on the project - GitHub Personal Access Token, steps to create the token are provided below -### Configuration +#### Terraform managed project + +- Billing account ID +- Organization or folder ID +- `roles/billing.user` IAM permissions on the billing account specified +- `roles/resourcemanager.projectCreator` IAM permissions on the organization or folder specified +- GitHub Personal Access Token, steps to create the token are provided below + +### Pull the source code + +- Clone the repository and change directory to the guide directory + + ``` + git clone https://github.com/GoogleCloudPlatform/ai-on-gke + cd ai-on-gke/ml-platform + ``` + +- Set environment variables + + ``` + export MLP_BASE_DIR=$(pwd) && \ + echo "export MLP_BASE_DIR=${MLP_BASE_DIR}" >> ${HOME}/.bashrc + ``` + +### GitHub Configuration - Create a [Personal Access Token][personal-access-token] in [GitHub][github]: Note: It is recommended to use a [machine user account][machine-user-account] for this but you can use a personal user account just to try this reference architecture. **Fine-grained personal access token** - + - Go to https://github.com/settings/tokens and login using your credentials - Click "Generate new token" >> "Generate new token (Beta)". - Enter a Token name. @@ -106,17 +134,6 @@ This is the quick-start deployment guide. It can be used to set up an environmen nano ${HOME}/secrets/mlp-github-token ``` -- Set the project environment variables in Cloud Shell - - Replace the following values - - - `` is the ID of your existing Google Cloud project - - ``` - export MLP_PROJECT_ID="" - export MLP_STATE_BUCKET="${MLP_PROJECT_ID}-tf-state" - ``` - - Set the GitHub environment variables in Cloud Shell Replace the following values: @@ -131,6 +148,31 @@ This is the quick-start deployment guide. It can be used to set up an environmen export MLP_GITHUB_EMAIL="" ``` +- Set the configuration variables + + ``` + sed -i "s/YOUR_GITHUB_EMAIL/${MLP_GITHUB_EMAIL}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars + sed -i "s/YOUR_GITHUB_ORG/${MLP_GITHUB_ORG}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars + sed -i "s/YOUR_GITHUB_USER/${MLP_GITHUB_USER}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars + ``` + +### Project Configuration + +You only need to complete the section for the option that you have selected. + +#### Bring your own project (BYOP) + +- Set the project environment variables in Cloud Shell + + Replace the following values + + - `` is the ID of your existing Google Cloud project + + ``` + export MLP_PROJECT_ID="" + export MLP_STATE_BUCKET="${MLP_PROJECT_ID}-tf-state" + ``` + - Set the default `gcloud` project ``` @@ -149,33 +191,56 @@ This is the quick-start deployment guide. It can be used to set up an environmen gcloud storage buckets create gs://${MLP_STATE_BUCKET} --project ${MLP_PROJECT_ID} ``` -### Run Terraform - -- Clone the repository and change directory to the guide directory +- Set the configuration variables ``` - git clone https://github.com/GoogleCloudPlatform/ai-on-gke - cd ai-on-gke/ml-platform + sed -i "s/YOUR_STATE_BUCKET/${MLP_STATE_BUCKET}/g" ${MLP_BASE_DIR}/terraform/backend.tf + sed -i "s/YOUR_PROJECT_ID/${MLP_PROJECT_ID}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars ``` -- Set environment variables +#### Terraform managed project + +- Set the configuration variables ``` - export MLP_BASE_DIR=$(pwd) && \ - echo "export MLP_BASE_DIR=${MLP_BASE_DIR}" >> ${HOME}/.bashrc + nano ${MLP_BASE_DIR}/terraform/initialize/initialize.auto.tfvars ``` -- Set the configuration variables + ``` + project = { + billing_account_id = "XXXXXX-XXXXXX-XXXXXX" + folder_id = "############" + name = "mlp" + org_id = "############" + } + ``` + + > `project.billing_account_id` the billing account ID + > + > Enter either `project.folder_id` **OR** `project.org_id` + > `project.folder_id` the folder ID + > `project.org_id` the organization ID + +- Authorize `gcloud` ``` - sed -i "s/YOUR_STATE_BUCKET/${MLP_STATE_BUCKET}/g" ${MLP_BASE_DIR}/terraform/backend.tf + gcloud auth login --activate --no-launch-browser --quiet --update-adc + ``` - sed -i "s/YOUR_GITHUB_EMAIL/${MLP_GITHUB_EMAIL}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars - sed -i "s/YOUR_GITHUB_ORG/${MLP_GITHUB_ORG}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars - sed -i "s/YOUR_GITHUB_USER/${MLP_GITHUB_USER}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars - sed -i "s/YOUR_PROJECT_ID/${MLP_PROJECT_ID}/g" ${MLP_BASE_DIR}/terraform/mlp.auto.tfvars +- Create a new project + + ``` + cd ${MLP_BASE_DIR}/terraform/initialize + terraform init && \ + terraform plan -input=false -out=tfplan && \ + terraform apply -input=false tfplan && \ + rm tfplan && \ + terraform init -force-copy -migrate-state && \ + rm -rf state ``` +### Run Terraform + - Create the resources ``` @@ -277,15 +342,37 @@ Open Cloud Shell to execute the following commands: ``` cd ${MLP_BASE_DIR}/terraform && \ terraform init && \ - terraform destroy -auto-approve -var github_token="$(tr --delete '\n' < ${HOME}/secrets/mlp-github-token)" + terraform destroy -auto-approve -var github_token="$(tr --delete '\n' < ${HOME}/secrets/mlp-github-token)" && \ + rm -rf .terraform .terraform.lock.hcl ``` +#### Project + +You only need to complete the section for the option that you have selected. + +##### Bring your own project (BYOP) + - Delete the project ``` gcloud projects delete ${MLP_PROJECT_ID} ``` +#### Terraform managed project + +- Destroy the project + + ``` + cd ${MLP_BASE_DIR}/terraform/initialize && \ + TERRAFORM_BUCKET_NAME=$(grep bucket backend.tf | awk -F"=" '{print $2}' | xargs) && \ + cp backend.tf.local backend.tf && \ + terraform init -force-copy -lock=false -migrate-state && \ + gsutil -m rm -rf gs://${TERRAFORM_BUCKET_NAME}/* && \ + terraform init && \ + terraform destroy -auto-approve && \ + rm -rf .terraform .terraform.lock.hcl + ``` + [gitops]: https://about.gitlab.com/topics/gitops/ [repo-sync]: https://cloud.google.com/anthos-config-management/docs/reference/rootsync-reposync-fields [root-sync]: https://cloud.google.com/anthos-config-management/docs/reference/rootsync-reposync-fields diff --git a/ml-platform/terraform/modules/projects/outputs.tf b/ml-platform/terraform/initialize/backend.tf similarity index 89% rename from ml-platform/terraform/modules/projects/outputs.tf rename to ml-platform/terraform/initialize/backend.tf index a1cc68f91..8d5d67421 100644 --- a/ml-platform/terraform/modules/projects/outputs.tf +++ b/ml-platform/terraform/initialize/backend.tf @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -output "project_id" { - value = local.project_id +terraform { + backend "local" { + path = "state/default.tfstate" + } } diff --git a/ml-platform/terraform/initialize/backend.tf.bucket b/ml-platform/terraform/initialize/backend.tf.bucket new file mode 100644 index 000000000..991e86976 --- /dev/null +++ b/ml-platform/terraform/initialize/backend.tf.bucket @@ -0,0 +1,20 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + backend "gcs" { + prefix = "terraform/initialize" + bucket = "" + } +} diff --git a/ml-platform/terraform/initialize/initialize.auto.tfvars b/ml-platform/terraform/initialize/initialize.auto.tfvars new file mode 100644 index 000000000..8ef26e4b0 --- /dev/null +++ b/ml-platform/terraform/initialize/initialize.auto.tfvars @@ -0,0 +1,7 @@ +environment_name = "dev" +project = { + billing_account_id = "" + folder_id = "" + name = "mlp" + org_id = "" +} diff --git a/ml-platform/terraform/initialize/main.tf b/ml-platform/terraform/initialize/main.tf new file mode 100644 index 000000000..2232ad86a --- /dev/null +++ b/ml-platform/terraform/initialize/main.tf @@ -0,0 +1,131 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +locals { + backend_file = "../backend.tf" + project_id_prefix = "${var.project.name}-${var.environment_name}" + project_id_suffix_length = 29 - length(local.project_id_prefix) + tfvars_file = "../mlp.auto.tfvars" +} + +resource "random_string" "project_id_suffix" { + length = local.project_id_suffix_length + lower = true + numeric = true + special = false + upper = false +} + +resource "google_project" "environment" { + billing_account = var.project.billing_account_id + folder_id = var.project.folder_id == "" ? null : var.project.folder_id + name = local.project_id_prefix + org_id = var.project.org_id == "" ? null : var.project.org_id + project_id = "${local.project_id_prefix}-${random_string.project_id_suffix.result}" +} + + +resource "google_storage_bucket" "mlp" { + force_destroy = false + location = var.storage_bucket_location + name = "${google_project.environment.project_id}-mlp" + project = google_project.environment.project_id + uniform_bucket_level_access = true + + versioning { + enabled = true + } +} + +resource "null_resource" "write_environment_name" { + triggers = { + md5 = var.environment_name + tfvars_file = local.tfvars_file + } + + provisioner "local-exec" { + command = <