Posted on
Artificial Intelligence

Artificial Intelligence Infrastructure Automation Best Practices

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence Infrastructure Automation Best Practices (for Bash-first DevOps)

AI stacks are evolving faster than most teams can manually keep up with. One missed driver version, an unpinned container tag, or a snowflake node can burn days of GPU time—and your budget. The fix is not just better scripts; it’s disciplined automation across the entire AI lifecycle.

This guide distills field-tested best practices you can apply today from a Linux terminal. You’ll get practical Bash-friendly workflows, IaC patterns, and install commands for apt, dnf, and zypper wherever tools are cited.

Why this matters

  • Reproducibility: AI experiments must be easy to rerun months later.

  • Velocity: Provision GPUs, storage, and networks in minutes—not weeks.

  • Cost control: Automation makes it easy to right-size and tear down.

  • Compliance: Versioned, reviewable code beats ad-hoc shell history.

5 best practices you can implement now

1) Describe everything as code (IaC + CaC)

Keep infra and configuration in version control so you can audit, roll back, and clone environments predictably.

  • Infra as Code (IaC): Terraform for cloud/GPU nodes, VPCs, security groups.

  • Config as Code (CaC): Ansible for packages, runtime config, users, and hardening.

  • Repo hygiene: Use Makefiles or small Bash wrappers to standardize operations.

Minimal repo skeleton:

ai-infra/
├─ terraform/         # networks, subnets, GPU nodes, EBS/NFS, ...
├─ ansible/
│  ├─ inventories/
│  ├─ roles/
│  └─ playbooks/
├─ containers/
│  └─ training/
├─ k8s/
│  ├─ base/
│  └─ overlays/
└─ Makefile

Install core tooling:

  • apt (Debian/Ubuntu):
sudo apt update
sudo apt install -y git make ansible jq
# Terraform (HashiCorp apt repo)
sudo apt install -y gnupg software-properties-common wget
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt install -y terraform
  • dnf (Fedora/RHEL/CentOS Stream):
sudo dnf install -y git make ansible jq dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/$(. /etc/os-release && echo $ID)/hashicorp.repo
sudo dnf install -y terraform
  • zypper (openSUSE/SLES):
sudo zypper refresh
sudo zypper install -y git make ansible jq gpg2
sudo rpm --import https://rpm.releases.hashicorp.com/gpg
# openSUSE repo for HashiCorp
sudo zypper addrepo https://rpm.releases.hashicorp.com/opensuse/hashicorp.repo
sudo zypper refresh
sudo zypper install -y terraform

Example: minimal Terraform for a GPU VM (cloud-agnostic pseudo, adapt to your provider):

# terraform/main.tf (example with variables)
terraform {
  required_version = ">= 1.6.0"
}

provider "aws" { region = var.region }

resource "aws_instance" "gpu" {
  ami           = var.gpu_ami
  instance_type = "g5.2xlarge"
  subnet_id     = var.subnet_id
  tags = { role = "ai-gpu", env = var.env }
}

output "gpu_ip" { value = aws_instance.gpu.public_ip }

2) Standardize containers and pin versions

Containers are the contract between data scientists and ops. Pin everything (CUDA, cuDNN, PyTorch/TensorFlow, OS) to avoid “works on my machine.”

Prefer rootless Podman for security, or Docker if required.

Install Podman (recommended):

  • apt:
sudo apt update
sudo apt install -y podman buildah skopeo
  • dnf:
sudo dnf install -y podman buildah skopeo
  • zypper:
sudo zypper refresh
sudo zypper install -y podman buildah skopeo

Optional: Install Docker Engine

  • apt:
sudo apt update
sudo apt install -y docker.io
sudo usermod -aG docker $USER
  • dnf (Fedora often packages Docker as moby):
sudo dnf install -y moby-engine docker-compose-plugin
sudo usermod -aG docker $USER
  • zypper:
sudo zypper refresh
sudo zypper install -y docker
sudo usermod -aG docker $USER

Enable GPU in containers via NVIDIA Container Toolkit:

  • apt:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
 | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
 | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
  • dnf:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
 | sed 's#rpm https://#rpm [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
 | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
sudo dnf clean expire-cache
sudo dnf install -y nvidia-container-toolkit
  • zypper:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
 | sed 's#rpm https://#rpm [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
 | sudo tee /etc/zypp/repos.d/nvidia-container-toolkit.repo
sudo zypper refresh
sudo zypper install -y nvidia-container-toolkit

Example pinned Dockerfile for PyTorch:

# containers/training/Dockerfile
FROM nvcr.io/nvidia/pytorch:24.05-py3       # pin exact tag
ENV PIP_NO_CACHE_DIR=1 \
    PYTHONUNBUFFERED=1
RUN pip install --no-deps --upgrade pip==24.0 \
 && pip install torchmetrics==1.4.0 hydra-core==1.3.2

Build and run (Podman):

cd containers/training
podman build -t registry.example.com/ai/train:24.05 .
podman run --rm --security-opt=label=disable --hooks-dir=/usr/share/containers/oci/hooks.d \
  --device nvidia.com/gpu=all \
  -v $PWD:/workspace -w /workspace \
  registry.example.com/ai/train:24.05 python your_script.py

With Docker:

docker build -t registry.example.com/ai/train:24.05 containers/training
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
docker run --rm --gpus all -v $PWD:/workspace -w /workspace registry.example.com/ai/train:24.05 python your_script.py

Real-world payoff: Pinning base images and deps stopped a team’s “Monday works, Friday breaks” problem after upstream PyPI updates changed default solver behavior.

3) Make GPU node setup idempotent

Avoid snowflake servers. Use Ansible to converge hosts to a known-good state—repeatably.

Simplified Ansible playbook to enable containerized GPU workloads:

# ansible/playbooks/gpu-node.yml

- hosts: gpu_nodes
  become: true
  tasks:
    - name: Ensure baseline packages
      package:
        name: [curl, git, jq]
        state: present

    - name: Install NVIDIA Container Toolkit repo and package (Debian/Ubuntu)
      when: ansible_pkg_mgr == "apt"
      shell: |
        set -euo pipefail
        distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
        curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor | tee /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg >/dev/null
        curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
         | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
         | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
        apt-get update
        apt-get install -y nvidia-container-toolkit

    - name: Install NVIDIA Container Toolkit (RPM: Fedora/RHEL/CentOS)
      when: ansible_pkg_mgr == "dnf"
      shell: |
        set -euo pipefail
        distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
        curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor | tee /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg >/dev/null
        curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
         | sed 's#rpm https://#rpm [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
         | tee /etc/yum.repos.d/nvidia-container-toolkit.repo
        dnf clean expire-cache
        dnf install -y nvidia-container-toolkit

    - name: Install NVIDIA Container Toolkit (SUSE/openSUSE)
      when: ansible_pkg_mgr == "zypper"
      shell: |
        set -euo pipefail
        distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
        curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor | tee /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg >/dev/null
        curl -fsSL https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list \
         | sed 's#rpm https://#rpm [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' \
         | tee /etc/zypp/repos.d/nvidia-container-toolkit.repo
        zypper -n refresh
        zypper -n install nvidia-container-toolkit

Verification helpers:

nvidia-smi || echo "Driver not found (ensure vendor-supported driver is installed)"
podman run --rm --device nvidia.com/gpu=all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
# or with Docker:
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

Tip: Keep the OS driver lifecycle documented and automated per distro using vendor-supported repos. Apply changes via Ansible and test on a canary GPU node first.

4) Orchestrate GPUs with Kubernetes (and schedule sanely)

Kubernetes gives you bin-packing, isolation, and repeatability. Add the NVIDIA device plugin so Pods can request GPUs explicitly.

Install kubectl:

  • apt:
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubectl
  • dnf:
sudo dnf install -y kubernetes-client || sudo dnf install -y kubectl
  • zypper:
sudo zypper refresh
sudo zypper install -y kubectl

Install Helm:

  • apt:
curl -fsSL https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | \
  sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt update
sudo apt install -y helm
  • dnf:
sudo dnf install -y helm
  • zypper:
sudo zypper refresh
sudo zypper install -y helm

Deploy NVIDIA device plugin:

helm repo add nvidia https://nvidia.github.io/k8s-device-plugin
helm repo update
helm upgrade --install nvidia-device-plugin nvidia/k8s-device-plugin -n kube-system

Request a GPU in a Pod:

# k8s/base/pod-gpu.yaml
apiVersion: v1
kind: Pod
metadata: { name: cuda-vectoradd }
spec:
  restartPolicy: Never
  containers:
    - name: cuda
      image: nvidia/cuda:12.2.0-base-ubuntu22.04
      command: ["bash","-lc","nvidia-smi && sleep 5"]
      resources:
        limits:
          nvidia.com/gpu: 1

Apply and check:

kubectl apply -f k8s/base/pod-gpu.yaml
kubectl logs -f pod/cuda-vectoradd

Real-world payoff: Moving ad-hoc training to K8s with GPU requests and per-namespace quotas reduced preemption fights and boosted cluster GPU utilization by 20–35%.

5) Build observability and cost guardrails

If you can’t measure it, you can’t optimize it. Track GPU health, memory, and utilization; alert on idle or thrashing jobs.

Install Prometheus stack and NVIDIA DCGM exporter:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add nvidia-dcgm https://nvidia.github.io/dcgm-exporter
helm repo update

# Prometheus + Grafana
helm upgrade --install o11y prometheus-community/kube-prometheus-stack -n monitoring --create-namespace

# GPU metrics
helm upgrade --install dcgm-exporter nvidia-dcgm/dcgm-exporter -n monitoring

Quick check for a metric from Prometheus:

export PROM=$(kubectl get svc -n monitoring -l app=kube-prometheus-stack-prometheus -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}{.items[0].status.loadBalancer.ingress[0].ip}')
curl -s "http://$PROM/api/v1/query?query=DCGM_FI_PROF_GR_ENGINE_ACTIVE" | jq .

Policy examples:

  • Alert on nodes with GPUs < 10% utilized for > 30 minutes.

  • Kill or requeue jobs exceeding VRAM thresholds.

  • Auto-scale node groups by GPU queue depth.

Real-world payoff: One team cut cloud GPU costs ~28% by alerting on idle GPUs and auto-scaling down nights/weekends.

Common pitfalls to avoid

  • Floating tags like latest for CUDA/PyTorch images.

  • Manual driver installs without documenting the exact repo and version.

  • Mixing container runtimes on the same node without testing GPU hooks.

  • Skipping e2e tests for provisioning changes (run a tiny GPU workload after every infra change).

Conclusion and next steps (CTA)

Small, consistent automation steps compound into reliable, fast, and cost-effective AI platforms.

Your 60-minute starter plan: 1) Install Terraform, Ansible, and Podman/Docker using the commands above. 2) Create a repo skeleton and commit a pinned training container. 3) Provision one GPU VM with Terraform and converge it with your Ansible playbook. 4) Run a smoke test: nvidia-smi in a container. 5) If you use Kubernetes, install the NVIDIA device plugin and deploy the sample Pod.

Want a jump-start? Wrap these into a Makefile with targets like make up, make test-gpu, and make down so anyone on your team can reproduce the stack with two commands.