BlueAlly SA Training Package
No NKP cluster, no Prism Central, no online lab access required. NKP is a curated bundle of upstream CNCF projects, so you can build the muscle memory for most of the exam's hands-on objectives on your own laptop with kind and free tooling. Every command here was run on macOS (Apple Silicon) with colima before publishing.
Covered (the upstream mechanics NKP is built on): Kubernetes architecture and kubectl, RBAC, the Cluster API object model, GitOps with Flux, OPA Gatekeeper admission policy, the Prometheus monitoring stack, and Velero backup and restore. That is roughly 70% of the exam's hands-on territory, taught with the exact tools NKP ships.
Not covered (stays book-knowledge from the study guides and NKPA videos): the Nutanix infrastructure provider parameters (Prism Central endpoint, subnets, KIB images), the Kommander UI and its workspaces, projects, and platform-app catalog, and the NKP licensing flow. Those need a real NKP estate. The labs build the foundation; the guides carry the product specifics.
Three verified primers, in order, before you start. Basics, then exam-grade Kubernetes, then the NKP product itself.
Install the toolchain, start a container runtime, and create a local cluster. The cluster you create is a kind (Kubernetes in Docker) cluster, which is exactly what NKP uses for its temporary bootstrap cluster (Section 1).
# install the toolchain (Homebrew) brew install colima docker kind helm clusterctl fluxcd/tap/flux velero kubectl # start a container runtime (no Docker Desktop license needed) colima start --cpu 6 --memory 12 --disk 60 # create the lab cluster, then confirm the node is Ready kind create cluster --name ncpcn-lab kubectl --context kind-ncpcn-lab get nodes
Maps to Section 1 / 2 · the bootstrap cluster (Q5, Q6), NotReady troubleshooting (Q22)
Deploy and expose an app, then look at what is actually running. The kube-system namespace shows the control plane the exam keeps testing sideways: etcd, kube-apiserver, kube-scheduler, kube-controller-manager, kube-proxy.
kubectl --context kind-ncpcn-lab create namespace demo
kubectl -n demo create deployment web --image=nginx:stable --replicas=2
kubectl -n demo expose deployment web --port=80 --type=ClusterIP
kubectl -n demo rollout status deployment/web
# the control plane, live
kubectl -n kube-system get pods
// Observe: kind is Kubernetes in Docker. No container runtime, no kind cluster, no NKP install. That is the literal reason the install host needs a runtime (Q6).
Maps to Section 3 · in-cluster RBAC vs fleet RBAC (Q34, Q35)
Grant a service account read-only pod access in one namespace, then prove the boundary with kubectl auth can-i. This is the in-cluster Kubernetes RBAC side of the distinction; the Kommander workspace and project roles are the fleet-plane side that federates downward.
kubectl create namespace team-a kubectl -n team-a create serviceaccount dev kubectl -n team-a create role pod-reader --verb=get,list,watch --resource=pods kubectl -n team-a create rolebinding dev-pod-reader --role=pod-reader --serviceaccount=team-a:dev kubectl auth can-i list pods --as=system:serviceaccount:team-a:dev -n team-a # yes kubectl auth can-i list pods --as=system:serviceaccount:team-a:dev -n default # no (Role is namespaced) kubectl auth can-i delete pods --as=system:serviceaccount:team-a:dev -n team-a # no (verb not granted)
// Note: kubectl auth can-i exits non-zero on a "no". Handy in scripts, and a small detail worth knowing.
Maps to Section 2 · management cluster (Q7), KubeadmControlPlane vs MachineDeployment (Q21, Q23), the generate/dry-run workflow (Q20)
Install the Cluster API controllers with the Docker provider. The exam tests the CAPI object model, which is provider-agnostic: the Nutanix provider swaps in for Docker, but the objects are identical. After init, the management cluster manages itself, exactly as NKP pivots CAPI state into the management cluster.
clusterctl init --infrastructure docker # the CAPI object model, now live as CRDs: kubectl get crds | grep cluster.x-k8s.io # clusters -> the top-level cluster object # kubeadmcontrolplanes -> owns control-plane replicas + k8s version (Q21) # machinedeployments -> one per worker pool, owns worker replicas (Q23) # machinesets / machines -> the layers beneath a MachineDeployment # dockermachinetemplates -> machine shapes (NutanixMachineTemplate on real NKP) # the provider controllers (management cluster is self-managing, Q7): kubectl get deploy -A | grep -E 'capi-|capd-' # the customization workflow (Q20): render editable manifests instead of applying clusterctl generate cluster my-cluster --kubernetes-version v1.31.0 \ --control-plane-machine-count=1 --worker-machine-count=2 > my-cluster.yaml
// Note: on a default kind cluster the Docker provider will not boot real worker nodes without mounting the host Docker socket, which is a Docker-provider quirk, not exam content. The exam tests the object model and the generate-then-apply workflow, which is what this lab makes concrete. On real NKP the same clusterctl and CAPI objects drive Nutanix nodes through Prism Central.
Maps to Section 4 · GitOps CD (Q72), Flux reconciliation and HelmReleases (Q29)
Install Flux, point it at a Git repo, and watch it reconcile the manifests into the cluster automatically. This is exactly the project-level Continuous Delivery mechanism NKP exposes, and the Flux HelmReleases you inspect when Kommander platform apps misbehave.
flux install
flux create source git podinfo \
--url=https://github.com/stefanprodan/podinfo --branch=master --interval=1m
flux create kustomization podinfo \
--source=GitRepository/podinfo --path="./kustomize" --prune=true \
--interval=5m --target-namespace=default --wait
flux get kustomizations
kubectl -n default get deploy podinfo # deployed straight from Git
Maps to Section 3 · OPA Gatekeeper "no privileged containers" admission rule (Q37)
Install Gatekeeper, write a constraint that forbids privileged containers, and watch the admission webhook block one. Scope it to a single namespace so it cannot interfere with system pods.
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.22.2/deploy/gatekeeper.yaml kubectl -n gatekeeper-system rollout status deploy/gatekeeper-controller-manager # the policy: a ConstraintTemplate (the rule) + a Constraint (where it applies) kubectl apply -f - <<'EOF' apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8sdenyprivileged spec: crd: spec: names: kind: K8sDenyPrivileged targets: - target: admission.k8s.gatekeeper.sh rego: | package k8sdenyprivileged violation[{"msg": msg}] { c := input.review.object.spec.containers[_] c.securityContext.privileged == true msg := sprintf("Privileged container not allowed: %v", [c.name]) } EOF kubectl wait --for condition=established crd/k8sdenyprivileged.constraints.gatekeeper.sh --timeout=90s kubectl create namespace policy-demo kubectl apply -f - <<'EOF' apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sDenyPrivileged metadata: name: no-privileged spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] namespaces: ["policy-demo"] EOF # this is DENIED by the admission webhook: kubectl -n policy-demo run priv --image=nginx:stable --restart=Never \ --overrides='{"spec":{"containers":[{"name":"priv","image":"nginx:stable","securityContext":{"privileged":true}}]}}' # Error: admission webhook "validation.gatekeeper.sh" denied the request: # [no-privileged] Privileged container not allowed: priv # a normal pod is ALLOWED: kubectl -n policy-demo run ok --image=nginx:stable --restart=Never
Maps to Section 3 · the monitoring trio (Q47), ServiceMonitor (Q49), vs the logging stack
Install kube-prometheus-stack and confirm the trio the exam loves to swap with logging components: Prometheus collects metrics, Alertmanager routes alerts, Grafana shows dashboards. Logging is the other stack (Loki stores, Grafana views, the Logging Operator collects).
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install kps prometheus-community/kube-prometheus-stack -n monitoring --create-namespace # the trio, live kubectl -n monitoring get pods | grep -E 'prometheus-kps|grafana|alertmanager' # the CRD behind scraping a custom app's metrics (Q49) kubectl get crd servicemonitors.monitoring.coreos.com
// Note: install without a blocking --wait and poll readiness instead; this chart pulls many images and a blocking wait can stall.
Maps to Section 3 · backup to object storage (Q41), velero backup (Q44), velero restore (Q45)
Stand up MinIO as S3-compatible object storage, install Velero against it, then back up a namespace, delete it, and restore it. Backups land in object storage with working credentials, which is one of Velero's two foundational dependencies.
kubectl apply -f https://raw.githubusercontent.com/vmware-tanzu/velero/main/examples/minio/00-minio-deployment.yaml kubectl -n velero rollout status deploy/minio printf '[default]\naws_access_key_id = minio\naws_secret_access_key = minio123\n' > minio-creds velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.12.0 \ --bucket velero --secret-file minio-creds --use-volume-snapshots=false \ --backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://minio.velero.svc:9000 # back up the demo namespace from Lab 0, delete it, restore it velero backup create demo-bak --include-namespaces demo --wait kubectl delete ns demo velero restore create demo-restore --from-backup demo-bak --wait kubectl -n demo get deploy web # back from the backup
kind delete cluster --name ncpcn-lab
colima stop # frees the VM; colima start brings it back