Skip to content

Environment Setup & First Steps

Duration: 35 minutes (25 minutes theory + 10 minutes lab)

Learning Objectives

  • Create your first Kubernetes cluster using kind
  • Verify kubectl connectivity
  • Explore the cluster with k9s
  • Understand kubeconfig and contexts
  • Run your first Pod

What is kind?

kind stands for Kubernetes IN Docker. It runs each Kubernetes node as a Docker container on your local machine instead of a full virtual machine or physical server.

How it works

kind packages all the Kubernetes node components (kubelet, containerd, etc.) into a single Docker image. When you create a cluster, kind starts one or more containers — one per node — and bootstraps a fully functional Kubernetes cluster inside them.

Your machine
└── Docker
    ├── Container: workshop-control-plane  (Kubernetes control plane)
    └── Container: workshop-worker         (Kubernetes worker node)

Why we use kind in this workshop

  • No cloud account required — everything runs locally inside the dev container
  • Fast setup — a cluster is ready in under two minutes
  • Lightweight — uses minimal resources, ideal for a laptop or a shared lab environment
  • Reproducible — clusters are created from a config file, so everyone starts from the same state
  • Easy reset — delete and recreate a cluster in seconds if something goes wrong

Why kind is not for production

kind is a development and testing tool only. You should not run production workloads on it because:

  • Nodes are containers, not real machines — a container crash or Docker restart wipes the entire cluster
  • No persistent storage by default — data does not survive a cluster restart
  • No real network isolation — all nodes share the host's Docker network, which differs from how production networking works
  • No high-availability guarantees — there is no support for rolling upgrades, node auto-repair, or production SLAs
  • Resource limits — it is constrained by your local machine's available CPU and memory

Creating Your First Cluster

Step 1: Verify Workshop Environment

Make sure you're inside the workshop container:

# You should see this prompt:
vscode  /workspaces/compose-to-kubernetes (main) $

# Verify tools are available
kubectl version --client
kind version
k9s version

Step 2: Create a Cluster

# Create a simple cluster (1 control-plane, 1 worker)
kind create cluster --config /workspaces/compose-to-kubernetes/setup/kind/simple.yaml

# This takes 1-2 minutes
# You'll see output like:
# Creating cluster "workshop" ...
# ✓ Ensuring node image (kindest/node:vX.XX.X)
# ✓ Preparing nodes
# ✓ Writing configuration
# ✓ Starting control-plane
# ✓ Installing CNI
# ✓ Installing StorageClass
# ✓ Joining worker nodes
# ✓ Ready after Xs

Step 3: Verify the Cluster

# Check cluster info
kubectl cluster-info

# Expected output:
# Kubernetes control plane is running at https://127.0.0.1:XXXXX
# CoreDNS is running at https://...

# List nodes
kubectl get nodes

# Expected output:
# NAME                     STATUS   ROLES           AGE   VERSION
# workshop-control-plane   Ready    control-plane   1m    v1.XX.X
# workshop-worker          Ready    <none>          1m    v1.XX.X

What you see:

  • workshop-control-plane: The node running control plane components
  • workshop-worker: The node where your Pods will run
  • STATUS: Ready: Both nodes are healthy
  • ROLES: Identifies the node's role in the cluster

Understanding kubeconfig

What is kubeconfig?

kubeconfig is a configuration file that tells kubectl:

  • Where the cluster is (API server address)
  • Who you are (authentication)
  • What you can do (authorization/context)

View Your kubeconfig

# Default location: ~/.kube/config
kubectl config view

# You'll see (simplified):
# clusters:
#   - cluster:
#       server: https://127.0.0.1:XXXXX
#     name: kind-workshop
# contexts:
#   - context:
#       cluster: kind-workshop
#       user: kind-workshop
#     name: kind-workshop
# current-context: kind-workshop
# users:
#   - name: kind-workshop

Contexts

A context combines:

  • A cluster (where to connect)
  • A user (how to authenticate)
  • A namespace (optional default)
# List contexts
kubectl config get-contexts

# Current context (marked with *)
# * kind-workshop   kind-workshop   kind-workshop   default

# Switch contexts (if you have multiple clusters)
kubectl config use-context kind-workshop

# Set default namespace for context
kubectl config set-context --current --namespace=kube-system

Introduction to kubectl

Basic kubectl Structure

kubectl [command] [resource type] [resource name] [flags]

Essential Commands

# Get resources
kubectl get nodes
kubectl get pods
kubectl get services
kubectl get all

# Describe (detailed info)
kubectl describe node workshop-worker
kubectl describe pod <pod-name>

# Create resources
kubectl create deployment nginx --image=nginx
kubectl apply -f myfile.yaml

# Delete resources
kubectl delete pod <pod-name>
kubectl delete deployment nginx

# Logs
kubectl logs <pod-name>
kubectl logs <pod-name> -f  # Follow logs

# Execute commands in Pod
kubectl exec <pod-name> -- ls /
kubectl exec -it <pod-name> -- /bin/bash  # Interactive shell

# Port forwarding (access Pod locally)
kubectl port-forward pod/<pod-name> 8080:80

Exploring with k9s

What is k9s?

k9s is a terminal UI for Kubernetes that provides:

  • Visual cluster navigation
  • Real-time updates
  • Quick access to logs, events, and descriptions
  • No need to remember kubectl commands

Launch k9s

# Start k9s
k9s

# You'll see a colorful interface!

k9s Navigation

Key Action
:pods View Pods
:deployments View Deployments
:services View Services
:nodes View Nodes
/ Filter/search
d Describe selected resource
l View logs
s Shell into Pod
Ctrl+d Delete
? Help
:q or Ctrl+c Quit

Try It Out

  1. Launch k9s: k9s
  2. Type :nodes and press Enter
  3. Use arrow keys to select a node
  4. Press d to describe it
  5. Press Esc to go back
  6. Type :q to quit

Your First Pod

Let's create and interact with a Pod:

# Create a Pod running nginx
kubectl run my-nginx --image=nginx:latest

# Wait for it to be ready
kubectl get pods -w
# Press Ctrl+C to stop watching

# Check its status
kubectl get pod my-nginx

# Get detailed information
kubectl describe pod my-nginx

# View logs
kubectl logs my-nginx

# Execute a command in the Pod
kubectl exec my-nginx -- nginx -v

# Get an interactive shell
kubectl exec -it my-nginx -- /bin/bash
# Try: ls, cat /etc/nginx/nginx.conf, exit

# Expose it locally
kubectl port-forward pod/my-nginx 8080:80 &

# Test it (in another terminal or stop port-forward first)
curl http://localhost:8080

# Clean up
kill %1  # Stop port-forward
kubectl delete pod my-nginx

Exploring the Cluster

System Pods

Kubernetes runs its own Pods for cluster functionality:

# View system Pods
kubectl get pods -n kube-system

# You'll see:
# - coredns-*: DNS server for the cluster
# - etcd-*: Key-value store
# - kube-apiserver-*: API server
# - kube-controller-manager-*: Controller manager# - kube-proxy-*: Network proxy
# - kube-scheduler-*: Scheduler

Namespaces

Namespaces provide logical separation:

# List namespaces
kubectl get namespaces

# Default namespaces:
# - default: Default namespace for resources
# - kube-system: System components
# - kube-public: Public resources
# - kube-node-lease: Node heartbeat information

# Get resources from specific namespace
kubectl get pods -n kube-system

# Get resources from ALL namespaces
kubectl get pods --all-namespaces
# or
kubectl get pods -A

Cluster Information

Comprehensive Cluster View

# Cluster info
kubectl cluster-info
kubectl cluster-info dump  # Very detailed (lots of output!)

# Node resources
kubectl top nodes  # Requires metrics-server (not in kind by default)

# API resources available
kubectl api-resources

# API versions
kubectl api-versions

# Check component status
kubectl get componentstatuses
# or
kubectl get cs

Cleanup (Optional)

If you want to start fresh:

# Delete the cluster
kind delete cluster --name workshop

# Recreate it
kind create cluster --config /workspaces/compose-to-kubernetes/setup/kind/simple.yaml

Tips

Alias kubectl to k:

alias k=kubectl
k get nodes  # Much faster!

Watch resources in real-time:

kubectl get pods -w
# or
watch kubectl get pods

Use bash completion:

# Already configured in the workshop container
kubectl get <Tab><Tab>  # Auto-complete resource types

Quick describe:

# Shorthand for describe
kubectl describe node/<node-name>
kubectl describe pod/<pod-name>

Troubleshooting

"Connection refused" error

# Check cluster is running
kind get clusters

# If not listed, recreate
kind create cluster --config /workspaces/compose-to-kubernetes/setup/kind/simple.yaml

"No resources found"

# Make sure you're in the right namespace
kubectl get pods -A  # Check ALL namespaces

# Check current context
kubectl config current-context

k9s shows errors

# Make sure cluster is healthy
kubectl get nodes

# Check k9s config
k9s info

Key takeaways

  • kind creates local Kubernetes clusters using containers as nodes
  • kubectl is the command-line tool to interact with the cluster
  • kubeconfig tells kubectl where and how to connect
  • contexts allow switching between clusters
  • k9s provides a visual interface for cluster management
  • Namespaces provide logical separation of resources

Check your understanding

  1. What command lists all nodes in your cluster?
  2. How do you view logs from a Pod?
  3. What's the difference between kubectl get and kubectl describe?
  4. What does a context contain?
  5. How do you view Pods in all namespaces?
Solution
  1. kubectl get nodes
  2. kubectl logs <pod-name>
  3. get shows a list/table view; describe shows detailed information about a specific resource
  4. A cluster, a user, and optionally a default namespace
  5. kubectl get pods --all-namespaces or kubectl get pods -A

Hands-on

Apply the concepts from this section in the lab exercises.

Next section

Once you've reviewed the content and completed the lab, proceed to the next section.