4 min read
Azure Kubernetes Service 1.24: New Features and Breaking Changes
Kubernetes 1.24 brings significant changes to Azure Kubernetes Service, including the removal of Dockershim and new security features. This post covers what you need to know for the upgrade.
Key Changes in 1.24
- Dockershim removal
- Seccomp by default
- Pod security admission
- Ephemeral containers GA
- Storage capacity tracking
Upgrading to AKS 1.24
# Check current version
az aks show --resource-group myResourceGroup --name myAKSCluster --query kubernetesVersion
# Check available versions
az aks get-versions --location eastus --output table
# Upgrade cluster
az aks upgrade \
--resource-group myResourceGroup \
--name myAKSCluster \
--kubernetes-version 1.24.0
# Verify upgrade
kubectl get nodes
Container Runtime Migration
With Dockershim removed, containerd is now the default:
# Check container runtime
apiVersion: v1
kind: Pod
metadata:
name: runtime-check
spec:
containers:
- name: check
image: alpine
command: ["sh", "-c", "cat /etc/os-release && sleep 3600"]
# Verify containerd
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'
# Output: containerd://1.6.x
Updating Docker-Specific Configurations
Replace Docker socket mounts:
# Old: Docker socket (no longer works)
# volumes:
# - name: docker-sock
# hostPath:
# path: /var/run/docker.sock
# New: Use containerd or avoid privileged access
apiVersion: v1
kind: Pod
metadata:
name: build-pod
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
args:
- "--dockerfile=Dockerfile"
- "--context=git://github.com/my-repo/app"
- "--destination=myregistry.azurecr.io/app:latest"
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker
volumes:
- name: kaniko-secret
secret:
secretName: regcred
items:
- key: .dockerconfigjson
path: config.json
Seccomp by Default
Kubernetes 1.24 enables Seccomp profiles by default:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault # Now default in 1.24
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
Custom Seccomp profile:
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"accept4",
"bind",
"clone",
"close",
"connect",
"epoll_create1",
"epoll_ctl",
"epoll_pwait",
"execve",
"exit_group",
"fcntl",
"fstat",
"futex",
"getdents64",
"getpid",
"getsockname",
"getsockopt",
"listen",
"mmap",
"mprotect",
"nanosleep",
"openat",
"read",
"recvfrom",
"rt_sigaction",
"rt_sigprocmask",
"sendto",
"setsockopt",
"socket",
"stat",
"write"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
Pod Security Admission
Replace Pod Security Policies with Pod Security Admission:
# Namespace-level enforcement
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.24
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.24
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.24
Compliant pod example:
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
namespace: production
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 65534
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Ephemeral Containers GA
Debug running pods without modification:
# Attach ephemeral container to running pod
kubectl debug -it myapp-pod --image=busybox:1.35 --target=myapp
# Debug with specific tools
kubectl debug -it myapp-pod \
--image=nicolaka/netshoot \
--target=myapp \
-- /bin/bash
# Create debug copy of pod
kubectl debug myapp-pod -it \
--copy-to=myapp-debug \
--container=debug \
--image=ubuntu
Using ephemeral containers programmatically:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp
image: myapp:latest
ephemeralContainers:
- name: debugger
image: busybox:1.35
command: ["sh"]
stdin: true
tty: true
targetContainerName: myapp
Storage Capacity Tracking
New storage features:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azure-disk-premium
provisioner: disk.csi.azure.com
parameters:
skuName: Premium_LRS
cachingMode: ReadOnly
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: azure-managed-disk
spec:
accessModes:
- ReadWriteOnce
storageClassName: azure-disk-premium
resources:
requests:
storage: 100Gi
Check storage capacity:
kubectl get csistoragecapacity -A
Migration Checklist
Before upgrading to 1.24:
#!/bin/bash
echo "=== Pre-upgrade Checklist for Kubernetes 1.24 ==="
# Check for Docker socket usage
echo "Checking for Docker socket mounts..."
kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.hostPath.path == "/var/run/docker.sock") | .metadata.name'
# Check for deprecated APIs
echo "Checking for deprecated APIs..."
kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis
# Check Pod Security Policies
echo "Checking Pod Security Policies..."
kubectl get psp
# Check for privileged containers
echo "Checking for privileged containers..."
kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[]?.securityContext.privileged == true) | .metadata | "\(.namespace)/\(.name)"'
# Verify container runtime compatibility
echo "Checking container images for Docker-specific features..."
# Manual review needed for Dockerfile SHELL instructions, etc.
echo "=== Checklist Complete ==="
Summary
Kubernetes 1.24 on AKS brings:
- Containerd as default runtime
- Seccomp profiles by default
- Pod Security Admission replacing PSPs
- GA ephemeral containers
- Storage improvements
Plan your upgrade carefully and test workloads before production migration.
References: