Kubernetes 1.18 was an important release because it introduced or previewed several capabilities that eventually became standard parts of modern Kubernetes administration. But a Kubernetes 1.18 tutorial is now historical. Kubernetes 1.36 is the current minor release as of this update, while 1.18 has been unsupported for years.
The useful lesson today is not what was new in Kubernetes 1.18. It is how those features evolved and how administrators and developers use their modern equivalents.
Use kubectl run to create Pods
One change introduced with Kubernetes 1.18 remains important: kubectl run is focused on creating Pods rather than acting as a general-purpose imperative generator for Deployments, Jobs and other workload resources.
For example, create a Pod with:
kubectl run my-pod \
--image=nginx:latest \
--port=80Then inspect it with:
kubectl get pod my-pod
kubectl describe pod my-podFor a Deployment, use the resource-specific command instead:
kubectl create deployment my-app \
--image=nginx:latestFor production workloads, declarative YAML or another configuration-management approach is generally preferable because the desired state can be reviewed, versioned and reproduced.
Modern Kubernetes debugging with kubectl debug
The early kubectl debug functionality discussed when Kubernetes 1.18 arrived has matured substantially. Modern kubectl debug can add an ephemeral debugging container to a running Pod, create a modified copy of a Pod, or create a debugging Pod for a node.
Suppose a running Pod contains a minimal application image without tools such as curl, ps or a shell. You can attach an ephemeral debugging container without rebuilding the application's image:
kubectl debug -it my-pod \
--image=busybox:1.37 \
--target=my-containerYou can also create a debugging copy of an existing Pod:
kubectl debug my-pod -it \
--copy-to=my-pod-debug \
--container=my-container \
-- shNode debugging is supported as well:
kubectl debug node/my-node -it \
--image=ubuntu:24.04This makes kubectl debug useful for troubleshooting workloads whose production images intentionally omit diagnostic utilities.
Use declarative Kubernetes manifests
A modern Pod manifest uses ordinary YAML with no HTML entities or formatting mixed into the code:
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
app: web
spec:
containers:
- name: web
image: nginx:latest
ports:
- name: http
containerPort: 80
protocol: TCPApply the manifest with:
kubectl apply -f my-pod.yamlServer-Side Apply is now stable
Server-Side Apply was still evolving when Kubernetes 1.18 was released. It became stable in Kubernetes 1.22 and remains an important declarative resource-management mechanism.
Use it explicitly with:
kubectl apply --server-side -f deployment.yamlServer-Side Apply lets the Kubernetes API server track which field manager owns individual resource fields. That is more precise than simply recording who last changed an entire object, and it helps multiple users and controllers safely manage different parts of the same resource.
You can inspect managed fields with:
kubectl get deployment my-app \
-o yaml \
--show-managed-fieldsModern kubectl also supports user preferences through kuberc, including a preference that makes Server-Side Apply the default for kubectl apply.
Windows worker nodes in modern Kubernetes
Kubernetes supports clusters with Linux and Windows worker nodes. The control plane runs on Linux, while Windows Server nodes can host Windows container workloads.
For many applications, scheduling a Windows workload starts with the standard operating-system node label:
apiVersion: v1
kind: Pod
metadata:
name: windows-app
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: app
image: mcr.microsoft.com/windows/nanoserver:ltsc2022
command:
- ping
- -t
- localhostReal Windows deployments must also account for Windows version compatibility, networking, storage and Windows-specific security behavior. RuntimeClass remains available when a workload needs a particular container runtime configuration, but it is not necessary simply to express that a Pod requires a Windows node.
Immutable Kubernetes Secrets
The immutable field first appeared as an emerging capability around the Kubernetes 1.18 era. Immutable Secrets and ConfigMaps became stable in Kubernetes 1.21.
A modern immutable Secret looks like this:
apiVersion: v1
kind: Secret
metadata:
name: database-credentials
type: Opaque
immutable: true
stringData:
username: admin
password: change-meFor a simple command-line example, avoid putting production passwords directly into shell history. One convenient development approach is:
kubectl create secret generic database-credentials \
--from-literal=username=admin \
--from-file=password=./password.txtA Kubernetes Secret is not automatically encrypted merely because it is a Secret. Base64 encoding is not encryption. Protect Secret data with appropriate RBAC, encryption at rest and secure external secret-management practices where required.
Once a Secret is marked immutable, its data cannot be changed in place. To change the value, create a replacement Secret and update the workloads that reference it.
Immutable ConfigMaps
ConfigMaps can also be immutable:
apiVersion: v1
kind: ConfigMap
metadata:
name: application-config-v1
immutable: true
data:
environment: production
log.level: INFOImmutable configuration protects applications from accidental changes and can reduce API server load because kubelets do not need to continuously watch immutable Secrets and ConfigMaps for updates.
If the configuration changes, create a new object, such as application-config-v2, and update the workload to reference the new name. This also makes configuration changes explicit and easier to roll back.
What changed since Kubernetes 1.18?
kubectl runremains a convenient way to create a Pod, while resource-specific commands and declarative manifests handle other workload types.kubectl debugmatured into a powerful troubleshooting command for Pods, workloads and nodes.- Server-Side Apply graduated to stable and provides field ownership and conflict detection for declarative resource management.
- Windows worker-node support matured substantially and now has dedicated scheduling, security, networking, storage and debugging guidance.
- Immutable Secrets and ConfigMaps graduated to stable and are useful both for safety and cluster efficiency.
Modern Kubernetes administration
Kubernetes 1.18 deserves credit for introducing several ideas that became important parts of the platform. But administrators should not copy Kubernetes 1.18 commands and manifests blindly into a current cluster.
Modern Kubernetes favors declarative configuration, Server-Side Apply where appropriate, purpose-built debugging with kubectl debug, explicit workload scheduling and carefully managed immutable configuration. Those practices provide a much better foundation for current production clusters than the experimental Kubernetes 1.18 examples from 2020.