Skip to content

Lab 01 — Kubernetes Fundamentals

This lab moves you from Kubernetes theory into practical platform operations.

You will build and inspect a simple Kubernetes application while learning how the major resources connect.

The lab focuses on:

Cluster
Namespace
Deployment
Pods
Service
Configuration
Observability
Troubleshooting

The goal is not only to make an application run.

The goal is to understand:

What Kubernetes created
Why each resource exists
How the resources connect
How to verify application health
How to investigate failures

Difficulty: Beginner

Estimated Time: 60–90 minutes

Primary Skills:

Kubernetes Fundamentals
kubectl Operations
Workload Management
Service Networking
Configuration
Observability
Basic Troubleshooting

You have joined a platform engineering team.

The team is beginning to move a simple web application into Kubernetes.

Your task is to create an isolated training namespace, deploy the application, expose it through a Service, add configuration, inspect the running resources, scale the workload, and troubleshoot a controlled configuration problem.

You will operate only inside your authorized lab environment.

By the end of this lab, you should be able to:

  • Verify access to a Kubernetes cluster
  • Identify cluster nodes
  • Create and use a namespace
  • Understand Pods and Deployments
  • Deploy a basic application
  • Inspect Kubernetes resources
  • Expose a workload through a Service
  • Understand labels and selectors
  • Scale a Deployment
  • Review logs and events
  • Create a ConfigMap
  • Understand Kubernetes Secrets
  • Inspect health and readiness
  • Troubleshoot a simple Service failure
  • Clean up the lab environment

You will build:

Kubernetes Cluster
└── ghc-k8s-lab Namespace
├── Deployment
│ ↓
│ Pods
├── Service
│ ↓
│ Application Access
└── ConfigMap
Application Configuration

You need access to:

Authorized Kubernetes Cluster
kubectl
Terminal / Shell
Ability to Create Resources
in a Training Namespace

You can use:

Local Kubernetes Lab
Training Cluster
Cloud-Hosted Kubernetes Lab

Do not perform these exercises against production infrastructure.

Use only:

Your Own Cluster
Training Cluster
Explicitly Authorized Environment

Keep all resources inside the lab namespace whenever possible.

The lab uses benign application workloads and configuration changes only.

Start by checking that the Kubernetes client is available.

Terminal window
kubectl version --client

You should receive client version information.

kubectl is the primary command-line interface used to interact with Kubernetes.

Conceptually:

kubectl
Kubernetes API
Cluster Resources

Confirm:

  • kubectl is installed
  • The command runs successfully

Check your current Kubernetes context.

Terminal window
kubectl config current-context

Then inspect cluster information.

Terminal window
kubectl cluster-info

Before making changes, always verify:

Cluster
Context
Namespace

This becomes extremely important when working across:

Development
Testing
Production

Record:

Current Context:
Cluster:
Environment:

List the Kubernetes nodes.

Terminal window
kubectl get nodes

You may see output similar to:

NAME STATUS ROLES AGE
control-01 Ready control-plane ...
worker-01 Ready <none> ...
worker-02 Ready <none> ...

The exact output depends on your environment.

Nodes provide compute capacity for Kubernetes workloads.

Conceptually:

Cluster
├── Node 1
│ └── Pods
├── Node 2
│ └── Pods
└── Node 3
└── Pods

Choose one node and inspect it.

Terminal window
kubectl describe node <node-name>

Look for areas such as:

Labels
Conditions
Capacity
Allocatable Resources
Pods
Events

Identify:

Number of Nodes:
Ready Nodes:
Node Roles:
Approximate CPU Capacity:
Approximate Memory Capacity:

Nodes are critical security assets.

Later security labs will examine:

Node Hardening
Administrative Access
Runtime Security
Workload Isolation

Run:

Terminal window
kubectl get namespaces

You may see namespaces used for:

Default Workloads
System Components
Platform Services

Namespaces help organize resources.

Example:

Cluster
├── development
├── testing
├── production
└── security

They can also provide scope for:

RBAC
Policies
Resource Quotas

Create a dedicated namespace.

Terminal window
kubectl create namespace ghc-k8s-lab

Verify:

Terminal window
kubectl get namespace ghc-k8s-lab

This gives the lab a clear boundary.

Instead of mixing training resources with unrelated workloads:

Shared Namespace
Confusion

you use:

ghc-k8s-lab
Lab Resources Only
  • Namespace created
  • Namespace visible
  • Name recorded

You can specify the namespace with every command:

Terminal window
kubectl get pods -n ghc-k8s-lab

For convenience, you may also update the current context namespace:

Terminal window
kubectl config set-context --current --namespace=ghc-k8s-lab

Verify:

Terminal window
kubectl config view --minify

Remember to change the namespace back when you finish if you altered your current context.

Create a simple NGINX Deployment.

Terminal window
kubectl create deployment web-app --image=nginx

Verify:

Terminal window
kubectl get deployments

Then:

Terminal window
kubectl get pods

You requested:

Deployment

Kubernetes then created:

Deployment
ReplicaSet
Pod

Inspect all three:

Terminal window
kubectl get deployment
kubectl get replicaset
kubectl get pods

Record:

Deployment Name:
ReplicaSet Name:
Pod Name:
Pod Status:

Run:

Terminal window
kubectl describe deployment web-app

Look for:

Labels
Selector
Replicas
Pod Template
Image
Events

A Deployment describes desired application state.

Example:

Desired:
1 Pod Running nginx

Kubernetes works to maintain that condition.

List Pods with additional information:

Terminal window
kubectl get pods -o wide

Notice:

Pod Name
Status
Pod IP
Node

Now inspect the Pod.

Terminal window
kubectl describe pod <pod-name>

Look for:

Namespace
Labels
Node
Container
Image
State
Conditions
Events

When something goes wrong, the Pod description often provides the first useful evidence.

A common troubleshooting workflow is:

Pod Problem
Get Pod
Describe Pod
Review Events
Review Logs

Get the Pod name:

Terminal window
kubectl get pods

Then review logs:

Terminal window
kubectl logs <pod-name>

At first there may be little output because the web server may not yet have received traffic.

What did the application do?

Later, logs become essential for:

Troubleshooting
Security Monitoring
Incident Response

The Pod exists, but applications normally need a stable network abstraction.

Create a Service:

Terminal window
kubectl expose deployment web-app --port=80 --target-port=80 --name=web-service

Verify:

Terminal window
kubectl get services
Client
Service
Deployment Pods

Pods are replaceable.

A Pod may disappear and another may be created.

Therefore:

Pod IP

should not generally be treated as a permanent application endpoint.

The Service provides a stable abstraction.

Run:

Terminal window
kubectl describe service web-service

Look for:

Selector
Port
TargetPort
Endpoints

The Service finds Pods through labels.

Conceptually:

Service
Selector
Pod Labels

Inspect the labels:

Terminal window
kubectl get pods --show-labels

Then inspect the Service selector:

Terminal window
kubectl get service web-service -o yaml

Identify:

Service Selector:
Pod Label:
Service Port:
Target Port:

Run:

Terminal window
kubectl get endpoints web-service

or, depending on the environment:

Terminal window
kubectl get endpointslices

You should see backend information associated with the Service.

If you have:

Service

but:

No Backend Endpoints

the application will not function through the Service.

This becomes a very common troubleshooting scenario.

One simple lab method is port forwarding.

Run:

Terminal window
kubectl port-forward service/web-service 8080:80

Keep that terminal open.

In another terminal, access:

http://localhost:8080

or use a local HTTP client if available.

You should receive the default NGINX response.

Your Computer
Port Forward
Service
Pod
NGINX
  • Application reachable
  • Service functioning
  • Pod responding

After sending requests, run:

Terminal window
kubectl logs <pod-name>

You should now see web request activity.

You have now created:

User Request
Application
Log Entry

This is your first practical example of application telemetry.

Check current replicas:

Terminal window
kubectl get deployment web-app

Now scale to three:

Terminal window
kubectl scale deployment web-app --replicas=3

Verify:

Terminal window
kubectl get pods

You should see three Pods.

You changed desired state:

Before:
1 Replica
After:
3 Replicas

The controller reconciled:

Desired = 3
Actual = 1
Create 2 More
Actual = 3

Record:

Desired Replicas:
Available Replicas:
Number of Running Pods:

Run:

Terminal window
kubectl get pods -o wide

Observe which nodes are running your Pods.

In a multi-node environment, they may be distributed across available nodes.

New Pod
Scheduler
Suitable Node

The scheduler considers cluster conditions and workload requirements.

Choose one Pod and delete it:

Terminal window
kubectl delete pod <pod-name>

Immediately watch:

Terminal window
kubectl get pods -w

You should observe a replacement Pod being created.

The Deployment still says:

Desired Replicas:
3

After deletion:

Actual:
2

Kubernetes detects the mismatch and reconciles it.

Desired = 3
Actual = 2
Controller
Creates Replacement

This is:

Self-Healing Through Reconciliation

Create a simple ConfigMap:

Terminal window
kubectl create configmap web-config \
--from-literal=environment=training \
--from-literal=application=gohackerscloud

Verify:

Terminal window
kubectl get configmaps

Inspect:

Terminal window
kubectl describe configmap web-config

A ConfigMap stores non-sensitive application configuration.

Examples:

Environment Name
Feature Flags
Service URLs
Application Mode

Do not use ConfigMaps for credentials.

Use:

ConfigMap

for:

Non-Sensitive Data

Run:

Terminal window
kubectl get configmap web-config -o yaml

Observe:

metadata
data

Identify:

ConfigMap Name:
Configuration Keys:
Configuration Values:

Create a training-only Secret.

Use a fake value only.

Terminal window
kubectl create secret generic demo-secret \
--from-literal=username=training-user \
--from-literal=password=training-password

Verify:

Terminal window
kubectl get secrets

These are deliberately fake lab credentials.

Never place real passwords, API keys, tokens, or production credentials into course examples.

Use:

Terminal window
kubectl describe secret demo-secret

Notice that describe does not simply print the secret value in normal output.

A Kubernetes Secret is still sensitive.

Security depends on:

RBAC
Cluster Storage Protection
Workload Access
Logging
Rotation

Do not assume:

Secret Resource
=
Automatically Safe
ConfigMap Secret
Non-sensitive configuration Sensitive configuration
App settings Credentials
Feature flags Tokens
Service endpoints Certificates/keys

Ask:

Would exposure of this value
create security impact?

If yes, treat it as sensitive information.

Part 23 — Add Environment Configuration to the Deployment

Section titled “Part 23 — Add Environment Configuration to the Deployment”

Set a training environment variable:

Terminal window
kubectl set env deployment/web-app ENVIRONMENT=training

Verify:

Terminal window
kubectl describe deployment web-app

Look for the environment variable in the container definition.

Changing the Deployment template may cause Kubernetes to create replacement Pods.

Conceptually:

Deployment Configuration Changed
New ReplicaSet / Updated Pods
New Desired State

Observe:

Terminal window
kubectl get replicaset

Compare the ReplicaSets before and after the Deployment change.

Run:

Terminal window
kubectl rollout status deployment/web-app

Then:

Terminal window
kubectl rollout history deployment/web-app

Application changes should be:

Tracked
Validated
Recoverable

Run:

Terminal window
kubectl get deployment web-app -o yaml

Do not try to memorize everything.

Identify major sections:

metadata
spec
status

Then within the Pod template:

containers
image
environment
labels

The YAML represents desired configuration.

The cluster maintains runtime status separately.

Think:

Spec
What You Want
Status
What Kubernetes Observes

List Deployment and Pod labels:

Terminal window
kubectl get deployment web-app --show-labels
kubectl get pods --show-labels

Labels help Kubernetes associate related resources.

Example:

app=web-app
Organization
Selection
Services
Policies
Scheduling

Part 27 — Controlled Troubleshooting Exercise

Section titled “Part 27 — Controlled Troubleshooting Exercise”

You will now intentionally create a safe Service misconfiguration.

First record the current Service:

Terminal window
kubectl get service web-service -o yaml

Pay attention to its selector.

Temporarily change the Service selector so it no longer matches the Pods.

Edit the Service:

Terminal window
kubectl edit service web-service

Locate the selector and change the label value to something that does not match the Pods.

For example, conceptually:

Correct:
app=web-app
Temporary Incorrect:
app=broken-web-app

Save the change.

Check the Service:

Terminal window
kubectl describe service web-service

Then:

Terminal window
kubectl get endpoints web-service

You should notice that the Service no longer has the expected backend endpoints.

You now have:

Deployment:
Healthy
Pods:
Healthy
Service:
Exists
Application:
Unavailable Through Service

What is wrong?

Use:

01 Check Pods
02 Check Service
03 Check Service Selector
04 Check Pod Labels
05 Check Endpoints
Terminal window
kubectl get pods

If healthy:

Problem Probably Not Pod Availability
Terminal window
kubectl get pods --show-labels
Terminal window
kubectl describe service web-service

Compare:

Service Selector
vs
Pod Labels

You should identify the mismatch.

Edit the Service again:

Terminal window
kubectl edit service web-service

Restore the original correct selector.

Then verify:

Terminal window
kubectl get endpoints web-service

The backend endpoints should return.

Run port forwarding again if required:

Terminal window
kubectl port-forward service/web-service 8080:80

Test the application.

You have just followed:

Symptom
Inspect Workload
Inspect Service
Inspect Selector
Inspect Labels
Identify Root Cause
Repair
Validate

This is a professional troubleshooting workflow.

Run:

Terminal window
kubectl get events --sort-by=.metadata.creationTimestamp

Events may reveal information about:

Pod Scheduling
Image Pulling
Container Startup
Workload Changes

When troubleshooting Kubernetes, events can often quickly explain:

What Kubernetes Tried to Do

and:

Why It Failed

Part 31 — Inspect Application Resource Relationships

Section titled “Part 31 — Inspect Application Resource Relationships”

At this stage, map what you created.

Namespace
Deployment
ReplicaSet
Pods

Networking:

Service
Label Selector
Pods

Configuration:

ConfigMap
Secret

Observability:

Pod Logs
Events

Draw this relationship yourself without referring to the lesson.

If you can explain each connection, you understand the core Kubernetes workload model.

Now review the environment with a security mindset.

Ask:

Which Namespace?
Which Image?
Which Service Account?
Which Service Exposure?
Which ConfigMaps?
Which Secrets?
Which Permissions?

Inspect the Pod:

Terminal window
kubectl describe pod <pod-name>

Identify the service account being used.

Ask:

Does this application actually need
Kubernetes API permissions?

This question will become central in the Kubernetes RBAC lab.

Check:

Terminal window
kubectl get deployment web-app -o yaml

Identify the image.

Record:

Image:
Registry:
Image Tag:

Ask:

Is the image trusted?
Where did it come from?
Is the version controlled?
Has it been assessed for vulnerabilities?

You will examine these topics more deeply later.

Check:

Terminal window
kubectl get services

Determine whether the Service is:

Internal
or
Externally Exposed

In this lab, keep exposure limited to the training requirement.

Do not make a service public just because it is technically easy.

Ask:

Does this workload
need external connectivity?

Part 35 — Review Sensitive Configuration

Section titled “Part 35 — Review Sensitive Configuration”

List:

Terminal window
kubectl get secrets

Then ask:

Which workloads need each Secret?
Who should be able to read it?

Later labs will connect Secret protection to:

RBAC
Workload Identity
Policy Enforcement

Check:

Terminal window
kubectl get pods

A Pod may show:

Running

but application health requires more context.

In production systems, Kubernetes may use:

Startup Probes
Readiness Probes
Liveness Probes
Startup
Application Initialized
Readiness
Can Receive Traffic
Liveness
Still Healthy

These concepts become more important in CKA and CKAD-style operations.

Part 37 — Delete the Deployment and Observe the Service

Section titled “Part 37 — Delete the Deployment and Observe the Service”

Before doing this, make sure you understand what will happen.

Delete:

Terminal window
kubectl delete deployment web-app

Now inspect:

Terminal window
kubectl get pods
kubectl get service
kubectl get endpoints web-service

You should observe:

Deployment Removed
ReplicaSet / Pods Removed
Service Still Exists
No Application Backend

Kubernetes resources are related, but they are still distinct objects.

Deleting:

Deployment

does not automatically mean:

Delete Every Unrelated Resource

Recreate:

Terminal window
kubectl create deployment web-app --image=nginx

Scale it:

Terminal window
kubectl scale deployment web-app --replicas=3

Now inspect:

Terminal window
kubectl get pods --show-labels

Then verify the Service selector still matches.

Terminal window
kubectl get endpoints web-service

If the labels and selector align, the Service should regain backends.

You should now understand:

Cluster
Namespace
Deployment
ReplicaSet
Pods

Application networking:

Client
Service
Pods

Configuration:

ConfigMap
Application
Secret
Sensitive Application Configuration

Operations:

Status
+
Events
+
Logs
Troubleshooting

Use this framework in future Kubernetes labs.

Deployment
ReplicaSet
Pod
Events
Logs
Service
Selector
Endpoints
Pod
Port
ConfigMap / Secret
Pod Configuration
Application
Logs

Lab Challenge 01 — Identify the Broken Layer

Section titled “Lab Challenge 01 — Identify the Broken Layer”

Suppose:

Pods:
Running
Service:
Exists
Endpoints:
Empty

What should you check first?

Answer:

Service Selector
vs
Pod Labels

Suppose:

Pod:
Pending

Investigate:

Describe Pod
Events
Scheduling
Resources
Storage

Do not immediately delete and recreate the Pod.

Find the cause first.

Lab Challenge 03 — Application Is Running but Unavailable

Section titled “Lab Challenge 03 — Application Is Running but Unavailable”

Check:

Pod Ready?
Service Selector Correct?
Endpoints Present?
Correct Port?
Application Listening?

Lab Challenge 04 — Configuration Change Caused Failure

Section titled “Lab Challenge 04 — Configuration Change Caused Failure”

Review:

Deployment Change
ConfigMap
Environment Variables
Application Logs
Rollout History

For your final running workload, answer:

Which image is running?
Which namespace?
Which service account?
Which Service exposes it?
Which ConfigMaps exist?
Which Secrets exist?
Which Pod labels are used?

Capture evidence for your lab notes.

Include:

Cluster Context
Node List
Namespace
Deployment
ReplicaSet
Pods
Pod Distribution
Service
Endpoints
ConfigMap
Secret Metadata
Application Logs
Events
Troubleshooting Finding
Lab:
Kubernetes Fundamentals
Date:
Cluster:
Namespace:
Deployment:
Replicas:
Service:
Configuration:
Troubleshooting Scenario:
Root Cause:
Remediation:
Validation:

Document the intentionally broken Service as though it were an operational finding.

Finding:
Service selector does not match application Pod labels.
Affected Resource:
web-service
Observation:
The Service existed but contained no expected backend endpoints.
Impact:
Application traffic could not be routed
to the running workload.
Root Cause:
Incorrect Service selector.
Recommendation:
Maintain consistent labels and selectors
and validate Service endpoints after changes.

Notice that:

Pods Were Healthy

but:

Application Was Unavailable

because Kubernetes applications depend on connected resources.

This teaches an important principle:

Resource Healthy
Service Healthy

You must understand the full dependency path.

The same relationship-based thinking applies to security.

Example:

Secure Pod
Over-Privileged Service Account
Security Risk

or:

Secure Application
Public Service
Unnecessary Exposure

Never assess Kubernetes resources only in isolation.

When finished, delete the entire lab namespace:

Terminal window
kubectl delete namespace ghc-k8s-lab

This removes the resources created inside the namespace.

Verify:

Terminal window
kubectl get namespaces

Restore your preferred namespace or context configuration.

For example:

Terminal window
kubectl config set-context --current --namespace=default

Validate:

Terminal window
kubectl config view --minify
  • Verified kubectl
  • Verified current context
  • Inspected cluster nodes
  • Created dedicated namespace
  • Created Deployment
  • Inspected ReplicaSet
  • Inspected Pods
  • Scaled application
  • Observed Pod replacement
  • Created Service
  • Reviewed selectors
  • Reviewed Pod labels
  • Reviewed endpoints
  • Accessed application
  • Created ConfigMap
  • Created training Secret
  • Understood ConfigMap vs Secret
  • Reviewed Deployment configuration
  • Reviewed Pod logs
  • Reviewed Kubernetes events
  • Reviewed Deployment rollout
  • Created controlled Service failure
  • Identified selector mismatch
  • Repaired configuration
  • Validated recovery
  • Identified container image
  • Identified service account
  • Reviewed Service exposure
  • Reviewed Secret presence
  • Considered application attack surface
  • Removed lab resources
  • Verified namespace deletion
  • Restored preferred context settings

You have now worked with:

kubectl
Cluster Contexts
Nodes
Namespaces
Deployments
ReplicaSets
Pods
Services
Labels
Selectors
Endpoints
ConfigMaps
Secrets
Scaling
Logs
Events
Troubleshooting

These are foundational skills for:

Kubernetes Administrator
DevOps Engineer
Cloud Engineer
Platform Engineer
Site Reliability Engineer
Cloud Security Engineer
Kubernetes Security Engineer

For security-focused roles, understanding normal Kubernetes operation is essential before analyzing abnormal or malicious behavior.

  1. What is a Kubernetes cluster?
  2. What is a node?
  3. What is a namespace?
  4. Why would you use namespaces?
  5. What is a Pod?
  6. What is a Deployment?
  7. What is a ReplicaSet?
  8. How are Deployments, ReplicaSets, and Pods related?
  9. What is desired state?
  10. What is reconciliation?
  11. What happens when you delete a Pod managed by a Deployment?
  12. What is a Kubernetes Service?
  13. Why should applications not normally depend directly on Pod IP addresses?
  14. How does a Service identify backend Pods?
  15. What are labels?
  16. What is a selector?
  17. What are Service endpoints?
  18. What would cause a Service to have no endpoints?
  19. How would you troubleshoot a Service that cannot reach Pods?
  20. What is a ConfigMap?
  21. What is a Kubernetes Secret?
  22. What is the difference between a ConfigMap and Secret?
  23. Why are Kubernetes Secrets still security-sensitive?
  24. What does scaling a Deployment do?
  25. What role does the scheduler play?
  26. Why are Kubernetes events useful?
  27. How do you view application logs?
  28. What is the difference between Pod status and application health?
  29. What are readiness probes used for?
  30. What are liveness probes used for?
  31. Why should Kubernetes workloads use trusted images?
  32. What is a service account?
  33. Why does workload identity matter?
  34. Why should unnecessary Services not be externally exposed?
  35. Why are relationships between Kubernetes resources important during troubleshooting?

Remember:

CLUSTER
NAMESPACE
DEPLOYMENT
REPLICASET
PODS

Then:

SERVICE
SELECTOR
POD LABELS
APPLICATION

Supported by:

CONFIGURATION
SECRETS
LOGS
EVENTS

This is your first practical Kubernetes operational model.

Before this lab:

You knew what Kubernetes resources were.

After this lab:

You created them,
connected them,
observed them,
changed them,
broke them safely,
troubleshot them,
and restored them.

That is the transition from:

Kubernetes Theory

to:

Kubernetes Hands-On Skills

➡️ Lab 02 — Kubernetes RBAC

In the next lab, you will focus on Kubernetes identity and authorization.

You will work with:

Service Accounts
Roles
ClusterRoles
RoleBindings
ClusterRoleBindings
Permissions
Least Privilege

The progression is:

Lab 01
Understand Kubernetes Resources
Lab 02
Control Who Can Access Them

You will begin moving from general Kubernetes administration into practical Kubernetes security.