diff --git a/.github/workflows/build-future-node-image.yml b/.github/workflows/build-future-node-image.yml new file mode 100644 index 000000000..1829034bc --- /dev/null +++ b/.github/workflows/build-future-node-image.yml @@ -0,0 +1,95 @@ +name: Build Image for VMs to Use as EC Nodes +on: + schedule: + - cron: '0 10 * * *' # everyday at 10am + push: + branches: + - main + paths: + - 'packer/future-node/**' + - .github/workflows/build-future-node-image.yaml + pull_request: + branches: + - main + paths: + - 'packer/future-node/**' + - .github/workflows/build-future-node-image.yaml + workflow_dispatch: + +jobs: + build_and_push_future-node: + name: Build Jumpbox GCP Compute Image + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v3 + + - name: Authenicate to Google Cloud + uses: google-github-actions/auth@v0 + with: + credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }} + + - name: Setup Google Cloud SDK + id: auth + uses: google-github-actions/setup-gcloud@v0 + with: + project_id: kots-field-labs + + # initialize + - name: Initialize Packer + uses: hashicorp/packer-github-actions@master + with: + command: init + working_directory: ./packer + target: future-node + env: + PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # validate templates + - name: Validate Packer Template + uses: hashicorp/packer-github-actions@master + with: + command: validate + arguments: -syntax-only + working_directory: ./packer + target: future-node + env: + PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # build artifact for push/merge (use default name) + - name: Build VM Image + uses: hashicorp/packer-github-actions@master + if: ${{ github.event_name != 'pull_request' }} + with: + command: build + arguments: "-force" + working_directory: ./packer + target: future-node + env: + PACKER_LOG: 1 + PKR_VAR_service_account_key: ${{secrets.GCP_SERVICE_ACCOUNT_KEY}} + PKR_VAR_zone: europe-west1-b + PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # build artifact for PRs (need to assign image name) + - name: Build VM Image + uses: hashicorp/packer-github-actions@master + if: ${{ github.event_name == 'pull_request' }} + with: + command: build + arguments: "-force" + working_directory: ./packer + target: future-node + env: + PACKER_LOG: 1 + PKR_VAR_service_account_key: ${{secrets.GCP_SERVICE_ACCOUNT_KEY}} + PKR_VAR_image_name: airgap-future-node-${{github.sha}} + PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # delete built artifact for PRs (save storage costs) + - name: Delete VM Image + if: ${{ github.event_name == 'pull_request' }} + run: gcloud compute images delete --quiet airgap-future-node-${{github.sha}} + shell: bash diff --git a/.github/workflows/build-jumpbox-image.yaml b/.github/workflows/build-jumpbox-image.yaml index 6b87eadf2..87dbb0e9b 100644 --- a/.github/workflows/build-jumpbox-image.yaml +++ b/.github/workflows/build-jumpbox-image.yaml @@ -14,7 +14,6 @@ on: paths: - 'packer/jumpbox/**' - .github/workflows/build-jumpbox-image.yaml - jobs: build_and_push_jumpbox: name: Build Jumpbox GCP Compute Image diff --git a/instruqt/delivering-as-an-appliance/config.yml b/instruqt/delivering-as-an-appliance/config.yml index 6cd4ebb24..525565ce9 100644 --- a/instruqt/delivering-as-an-appliance/config.yml +++ b/instruqt/delivering-as-an-appliance/config.yml @@ -2,6 +2,9 @@ version: "3" containers: - name: shell image: gcr.io/kots-field-labs/shell +virtualmachines: +- name: node + image: kots-field-labs/future-cluster-node shell: tmux new-session -A -s shell su - replicant virtualmachines: - name: cluster diff --git a/packer/future-node/jumpbox.pkr.hcl b/packer/future-node/jumpbox.pkr.hcl new file mode 100644 index 000000000..36e1f0631 --- /dev/null +++ b/packer/future-node/jumpbox.pkr.hcl @@ -0,0 +1,34 @@ +packer { + required_plugins { + googlecompute = { + version = ">= 0.0.1" + source = "github.com/hashicorp/googlecompute" + } + } +} + +source "googlecompute" "future-node" { + project_id = var.project + image_name = var.image_name + zone = var.zone + + source_image_family = var.source_image_family + machine_type = var.machine_type + disk_size = var.disk_size + + metadata = { + "user-data" = file("user-data.yaml") + } + ssh_username = var.ssh_username + account_file = var.service_account_key +} + +build { + sources = ["sources.googlecompute.future-node"] + + provisioner "shell" { + inline = [ + "cloud-init status --wait", + ] + } +} diff --git a/packer/future-node/user-data.yaml b/packer/future-node/user-data.yaml new file mode 100644 index 000000000..f66e00aec --- /dev/null +++ b/packer/future-node/user-data.yaml @@ -0,0 +1,78 @@ +#cloud-config + +# This is the user-data configuration file for cloud-init. By default this sets +# +# up an initial user called "ubuntu" with password "ubuntu", which must be +# changed at first login. However, many additional actions can be initiated on +# first boot from this file. The cloud-init documentation has more details: +# +# https://cloudinit.readthedocs.io/ +# +# Some additional examples are provided in comments below the default +# configuration. + +## don't require a password change since we just set it +chpasswd: + expire: false + +## add user `replicant` +users: +- default +- name: replicant + gecos: "Replicated Lab Participant" + groups: + - users + sudo: "ALL=(ALL) NOPASSWD:ALL" + lock_passwd: true + +## Update apt database and upgrade packages on first boot +package_update: true +package_upgrade: true + +## Install additional packages on first boot +packages: +- ca-certificates +- curl +- tmux +- jq + +# install snaps on first boot +snap: + commands: + - snap install git-ubuntu --classic + - snap install kubectl --classic + - snap install helm --classic + - snap install google-cloud-cli --classic + +runcmd: +- wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && chmod +x /usr/bin/yq +- chsh -s /usr/bin/bash replicant +- curl https://kots.io/install | bash +- | + bash -c "( + set -x + export KREW_ROOT=/usr/local/libexec/krew + export PATH=${KREW_ROOT}/bin:${PATH} + curl -L https://krew.sh | bash + curl -L https://krew.sh/ns | bash + curl -L https://krew.sh/ctx | bash + curl -L https://krew.sh/preflight | bash + curl -L https://krew.sh/support-bundle | bash + echo 'export KREW_ROOT=/usr/local/libexec/krew' >> /home/replicant/.profile + echo 'export PATH="${KREW_ROOT}/bin:$PATH"' >> /home/replicant/.profile + )" +- | + bash -c "( + set -x + cd "$(mktemp -d)" + wget -O replicated.tar.gz -q "$(curl -s https://api.github.com/repos/replicatedhq/replicated/releases/latest | yq '.assets[] | select(.browser_download_url | contains("linux_amd64")).browser_download_url')" + tar -C /usr/local/bin -xzvf replicated.tar.gz replicated + )" +- | + bash -c "( + curl -s https://api.github.com/repos/replicatedhq/sbctl/releases/latest \ + | jq -r '.assets[] | select ( .name == \"sbctl_linux_amd64.tar.gz\").browser_download_url' \ + | xargs curl --location \ + | tar -C /usr/local/bin -xzvf - sbctl \ + && chmod 755 /usr/local/bin/sbctl + )" diff --git a/packer/future-node/variables.pkr.hcl b/packer/future-node/variables.pkr.hcl new file mode 100644 index 000000000..af277cb9c --- /dev/null +++ b/packer/future-node/variables.pkr.hcl @@ -0,0 +1,38 @@ +variable "project" { + type = string + default = "kots-field-labs" +} + +variable "image_name" { + type = string + default = "airgap-jumpbox" +} + +variable "zone" { + type = string + default = "europe-west1-b" +} + +variable "source_image_family" { + type = string + default = "ubuntu-2204-lts" +} + +variable "machine_type" { + type = string + default = "n1-standard-2" +} + +variable "disk_size" { + type = string + default = "50" +} + +variable "ssh_username" { + type = string + default = "ubuntu" +} + +variable "service_account_key" { + type = string +}