This is the multi-page printable view of this section. Click here to print.
Documentation
- 1: Kubernetes Documentation
- 2: Getting started
- 2.1: Learning environment
- 2.2: Production environment
- 2.2.1: Container Runtimes
- 2.2.2: Installing Kubernetes with deployment tools
- 2.2.2.1: Bootstrapping clusters with kubeadm
- 2.2.2.1.1: Installing kubeadm
- 2.2.2.1.2: Troubleshooting kubeadm
- 2.2.2.1.3: Creating a cluster with kubeadm
- 2.2.2.1.4: Customizing components with the kubeadm API
- 2.2.2.1.5: Options for Highly Available Topology
- 2.2.2.1.6: Creating Highly Available Clusters with kubeadm
- 2.2.2.1.7: Set up a High Availability etcd Cluster with kubeadm
- 2.2.2.1.8: Configuring each kubelet in your cluster using kubeadm
- 2.2.2.1.9: Dual-stack support with kubeadm
- 2.2.3: Turnkey Cloud Solutions
- 2.3: Best practices
- 3: Concepts
- 3.1: Overview
- 3.1.1: Kubernetes Components
- 3.1.2: Objects In Kubernetes
- 3.1.2.1: Kubernetes Object Management
- 3.1.2.2: Object Names and IDs
- 3.1.2.3: Labels and Selectors
- 3.1.2.4: Namespaces
- 3.1.2.5: Annotations
- 3.1.2.6: Field Selectors
- 3.1.2.7: Finalizers
- 3.1.2.8: Owners and Dependents
- 3.1.2.9: Recommended Labels
- 3.1.2.10: Storage Versions
- 3.1.3: The Kubernetes API
- 3.1.4: The kubectl command-line tool
- 3.2: Cluster Architecture
- 3.2.1: Nodes
- 3.2.2: Communication between Nodes and the Control Plane
- 3.2.3: Controllers
- 3.2.4: Leases
- 3.2.5: Cloud Controller Manager
- 3.2.6: About cgroup v2
- 3.2.7: Kubernetes Self-Healing
- 3.2.8: Garbage Collection
- 3.2.9: Mixed Version Proxy
- 3.3: Containers
- 3.3.1: Images
- 3.3.2: Container Environment
- 3.3.3: Runtime Class
- 3.3.4: Container Lifecycle Hooks
- 3.3.5: Container Runtime Interface (CRI)
- 3.4: Workloads
- 3.4.1: Pods
- 3.4.1.1: Pod Lifecycle
- 3.4.1.2: Pod Conditions
- 3.4.1.3: Init Containers
- 3.4.1.4: Sidecar Containers
- 3.4.1.5: Ephemeral Containers
- 3.4.1.6: Liveness, Readiness, and Startup Probes
- 3.4.1.7: Disruptions
- 3.4.1.8: Pod Hostname
- 3.4.1.9: Pod Quality of Service Classes
- 3.4.1.10: Scheduling Group
- 3.4.1.11: Static Pods
- 3.4.1.12: User Namespaces
- 3.4.1.13: Downward API
- 3.4.1.14: Advanced Pod Configuration
- 3.4.2: Workload API
- 3.4.2.1: Pod Group Disruption and Priority
- 3.4.2.2: PodGroup Scheduling Policies
- 3.4.2.3: Topology-Aware Workload Scheduling
- 3.4.2.4: Scheduling Building Block APIs and the workloadbuilder Library
- 3.4.3: Workload Management
- 3.4.3.1: Deployments
- 3.4.3.2: ReplicaSet
- 3.4.3.3: StatefulSets
- 3.4.3.4: DaemonSet
- 3.4.3.5: Jobs
- 3.4.3.6: Automatic Cleanup for Finished Jobs
- 3.4.3.7: CronJob
- 3.4.3.8: ReplicationController
- 3.4.4: CompositePodGroup API
- 3.4.4.1: CompositePodGroup Lifecycle
- 3.4.5: PodGroup API
- 3.4.5.1: PodGroup Lifecycle
- 3.4.6: Managing Workloads
- 3.4.7: Autoscaling Workloads
- 3.4.8: Horizontal Pod Autoscaling
- 3.4.9: Vertical Pod Autoscaling
- 3.5: Services, Load Balancing, and Networking
- 3.5.1: Service
- 3.5.2: Ingress
- 3.5.3: Ingress Controllers
- 3.5.4: Gateway API
- 3.5.5: EndpointSlices
- 3.5.6: Network Policies
- 3.5.7: DNS for Services and Pods
- 3.5.8: IPv4/IPv6 dual-stack
- 3.5.9: Topology Aware Routing
- 3.5.10: Networking on Windows
- 3.5.11: Service ClusterIP allocation
- 3.5.12: Service Internal Traffic Policy
- 3.6: Storage
- 3.6.1: Volumes
- 3.6.2: Persistent Volumes
- 3.6.3: Projected Volumes
- 3.6.4: Ephemeral Volumes
- 3.6.5: Storage Classes
- 3.6.6: Volume Attributes Classes
- 3.6.7: Dynamic Volume Provisioning
- 3.6.8: Volume Snapshots
- 3.6.9: Volume Snapshot Classes
- 3.6.10: CSI Volume Cloning
- 3.6.11: Volume Populators and Data Sources
- 3.6.12: Storage Capacity
- 3.6.13: Node-specific Volume Limits
- 3.6.14: Local ephemeral storage
- 3.6.15: Volume Health Monitoring
- 3.6.16: Windows Storage
- 3.7: Configuration
- 3.7.1: ConfigMaps
- 3.7.2: Secrets
- 3.7.3: Resource Management for Pods and Containers
- 3.7.4: Organizing Cluster Access Using kubeconfig Files
- 3.7.5: Resource Management for Windows nodes
- 3.8: Security
- 3.8.1: Cloud Native Security and Kubernetes
- 3.8.2: Pod Security Standards
- 3.8.3: Pod Security Admission
- 3.8.4: Service Accounts
- 3.8.5: Pod Security Policies
- 3.8.6: Security For Linux Nodes
- 3.8.7: Security For Windows Nodes
- 3.8.8: Controlling Access to the Kubernetes API
- 3.8.9: Role Based Access Control Good Practices
- 3.8.10: Good practices for Kubernetes Secrets
- 3.8.11: Multi-tenancy
- 3.8.12: Hardening Guide - Authentication Mechanisms
- 3.8.13: Hardening Guide - Dynamic Resource Allocation
- 3.8.14: Hardening Guide - Scheduler Configuration
- 3.8.15: Kubernetes API Server Bypass Risks
- 3.8.16: Linux kernel security constraints for Pods and containers
- 3.8.17: Security Checklist
- 3.8.18: Application Security Checklist
- 3.9: Policies
- 3.9.1: Limit Ranges
- 3.9.2: Resource Quotas
- 3.9.3: Process ID Limits And Reservations
- 3.10: Scheduling, Preemption and Eviction
- 3.10.1: Kubernetes Scheduler
- 3.10.2: Topology-Aware Workload Scheduling
- 3.10.3: Assigning Pods to Nodes
- 3.10.4: Pod Overhead
- 3.10.5: Pod Scheduling Readiness
- 3.10.6: Pod Topology Spread Constraints
- 3.10.7: Taints and Tolerations
- 3.10.8: Scheduling Framework
- 3.10.9: Gang Scheduling
- 3.10.10: Scheduler Performance Tuning
- 3.10.11: PodGroup Scheduling
- 3.10.12: Resource Bin Packing
- 3.10.13: Workload-Aware Preemption
- 3.10.14: Pod Priority and Preemption
- 3.10.15: Node-pressure Eviction
- 3.10.16: API-initiated Eviction
- 3.10.17: Node Declared Features
- 3.11: Resource Management
- 3.11.1: Resource managers
- 3.11.2: Dynamic Resource Allocation
- 3.11.2.1: DRA API Objects
- 3.11.2.2: How DRA Works
- 3.11.2.3: Observability of Dynamic Resources
- 3.11.2.4: DRA Features
- 3.11.2.5: Device Taints and Tolerations
- 3.11.3: Pod-level resource managers
- 3.12: Cluster Administration
- 3.12.1: Node Shutdowns
- 3.12.2: Swap memory management
- 3.12.3: Node Autoscaling
- 3.12.4: Certificates
- 3.12.5: Cluster Networking
- 3.12.6: Observability
- 3.12.7: Admission Webhook Good Practices
- 3.12.8: Good practices for Dynamic Resource Allocation as a Cluster Admin
- 3.12.9: Logging Architecture
- 3.12.10: Compatibility Version For Kubernetes Control Plane Components
- 3.12.11: Metrics For Kubernetes System Components
- 3.12.12: Metrics for Kubernetes Object States
- 3.12.13: System Logs
- 3.12.14: Traces For Kubernetes System Components
- 3.12.15: Proxies in Kubernetes
- 3.12.16: API Priority and Fairness
- 3.12.17: Installing Addons
- 3.12.18: Coordinated Leader Election
- 3.13: Windows in Kubernetes
- 3.14: Extending Kubernetes
- 3.14.1: Compute, Storage, and Networking Extensions
- 3.14.1.1: Network Plugins
- 3.14.1.2: Device Plugins
- 3.14.2: Extending the Kubernetes API
- 3.14.2.1: Custom Resources
- 3.14.2.2: Kubernetes API Aggregation Layer
- 3.14.3: Operator pattern
- 4: Tasks
- 4.1: Install Tools
- 4.1.1: Install and Set Up kubectl on Linux
- 4.1.2: Install and Set Up kubectl on macOS
- 4.1.3: Install and Set Up kubectl on Windows
- 4.2: Administer a Cluster
- 4.2.1: Administration with kubeadm
- 4.2.1.1: Adding Linux worker nodes
- 4.2.1.2: Adding Windows worker nodes
- 4.2.1.3: Upgrading kubeadm clusters
- 4.2.1.4: Upgrading Linux nodes
- 4.2.1.5: Upgrading Windows nodes
- 4.2.1.6: Certificate Management with kubeadm
- 4.2.1.7: Reconfiguring a kubeadm cluster
- 4.2.1.8: Changing The Kubernetes Package Repository
- 4.2.2: Overprovision Node Capacity For A Cluster
- 4.2.3: Migrating from dockershim
- 4.2.3.1: Changing the Container Runtime on a Node from Docker Engine to containerd
- 4.2.3.2: Find Out What Container Runtime is Used on a Node
- 4.2.3.3: Troubleshooting CNI plugin-related errors
- 4.2.3.4: Check whether dockershim removal affects you
- 4.2.3.5: Migrating telemetry and security agents from dockershim
- 4.2.4: Generate Certificates Manually
- 4.2.5: Manage Memory, CPU, and API Resources
- 4.2.5.1: Configure Default Memory Requests and Limits for a Namespace
- 4.2.5.2: Configure Default CPU Requests and Limits for a Namespace
- 4.2.5.3: Configure Minimum and Maximum Memory Constraints for a Namespace
- 4.2.5.4: Configure Minimum and Maximum CPU Constraints for a Namespace
- 4.2.5.5: Configure Memory and CPU Quotas for a Namespace
- 4.2.5.6: Configure a Pod Quota for a Namespace
- 4.2.6: Install a Network Policy Provider
- 4.2.6.1: Use Antrea for NetworkPolicy
- 4.2.6.2: Use Calico for NetworkPolicy
- 4.2.6.3: Use Cilium for NetworkPolicy
- 4.2.6.4: Use Kube-router for NetworkPolicy
- 4.2.7: Access Clusters Using the Kubernetes API
- 4.2.8: Enable Or Disable Feature Gates
- 4.2.9: Advertise Extended Resources for a Node
- 4.2.10: Autoscale the DNS Service in a Cluster
- 4.2.11: Change the Access Mode of a PersistentVolume to ReadWriteOncePod
- 4.2.12: Change the default StorageClass
- 4.2.13: Switching from Polling to CRI Event-based Updates to Container Status
- 4.2.14: Change the Reclaim Policy of a PersistentVolume
- 4.2.15: Cloud Controller Manager Administration
- 4.2.16: Configure a kubelet image credential provider
- 4.2.17: Configure Quotas for API Objects
- 4.2.18: Control CPU Management Policies on the Node
- 4.2.19: Control Memory Management Policies on a Node
- 4.2.20: Control Topology Management Policies on a node
- 4.2.21: Customizing DNS Service
- 4.2.22: Debugging DNS Resolution
- 4.2.23: Declare Network Policy
- 4.2.24: Developing Cloud Controller Manager
- 4.2.25: Enable Or Disable A Kubernetes API
- 4.2.26: Encrypting Confidential Data at Rest
- 4.2.27: Decrypt Confidential Data that is Already Encrypted at Rest
- 4.2.28: Guaranteed Scheduling For Critical Add-On Pods
- 4.2.29: IP Masquerade Agent User Guide
- 4.2.30: Limit Storage Consumption
- 4.2.31: Migrate Replicated Control Plane To Use Cloud Controller Manager
- 4.2.32: Operating etcd clusters for Kubernetes
- 4.2.33: Reserve Compute Resources for System Daemons
- 4.2.34: Running Kubernetes Node Components as a Non-root User
- 4.2.35: Safely Drain a Node
- 4.2.36: Securing a Cluster
- 4.2.37: Harden Dynamic Resource Allocation in Your Cluster
- 4.2.38: Set Kubelet Parameters Via A Configuration File
- 4.2.39: Share a Cluster with Namespaces
- 4.2.40: Upgrade A Cluster
- 4.2.41: Use Cascading Deletion in a Cluster
- 4.2.42: Using a KMS provider for data encryption
- 4.2.43: Using CoreDNS for Service Discovery
- 4.2.44: Using NodeLocal DNSCache in Kubernetes Clusters
- 4.2.45: Using sysctls in a Kubernetes Cluster
- 4.2.46: Verify Signed Kubernetes Artifacts
- 4.3: Configure Pods and Containers
- 4.3.1: Assign Memory Resources to Containers and Pods
- 4.3.2: Assign CPU Resources to Containers and Pods
- 4.3.3: Assign Devices to Pods and Containers
- 4.3.3.1: Set Up DRA in a Cluster
- 4.3.3.2: Allocate Devices to Workloads with DRA
- 4.3.3.3: Access DRA Device Metadata
- 4.3.4: Assign Pod-level CPU and memory resources
- 4.3.5: Configure GMSA for Windows Pods and containers
- 4.3.6: Resize CPU and Memory Resources assigned to Containers
- 4.3.7: Resize CPU and Memory Resources assigned to Pods
- 4.3.8: Configure RunAsUserName for Windows pods and containers
- 4.3.9: Create a Windows HostProcess Pod
- 4.3.10: Configure Quality of Service for Pods
- 4.3.11: Assign Extended Resources to a Container
- 4.3.12: Configure a Pod to Use a Volume for Storage
- 4.3.13: Configure a Pod to Use a Projected Volume for Storage
- 4.3.14: Configure a Security Context for a Pod or Container
- 4.3.15: Configure Service Accounts for Pods
- 4.3.16: Pull an Image from a Private Registry
- 4.3.17: Configure Liveness, Readiness and Startup Probes
- 4.3.18: Assign Pods to Nodes
- 4.3.19: Assign Pods to Nodes using Node Affinity
- 4.3.20: Configure Pod Initialization
- 4.3.21: Attach Handlers to Container Lifecycle Events
- 4.3.22: Configure a Pod to Use a ConfigMap
- 4.3.23: Share Process Namespace between Containers in a Pod
- 4.3.24: Use a User Namespace With a Pod
- 4.3.25: Use an Image Volume With a Pod
- 4.3.26: Set Permissions on an emptyDir Volume
- 4.3.27: Set Bind Mount Options on Volume Mounts
- 4.3.28: Create static Pods
- 4.3.29: Translate a Docker Compose File to Kubernetes Resources
- 4.3.30: Enforce Pod Security Standards by Configuring the Built-in Admission Controller
- 4.3.31: Enforce Pod Security Standards with Namespace Labels
- 4.3.32: Migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller
- 4.4: Monitoring, Logging, and Debugging
- 4.4.1: Logging in Kubernetes
- 4.4.2: Monitoring in Kubernetes
- 4.4.3: Troubleshooting Applications
- 4.4.3.1: Debug Pods
- 4.4.3.2: Debug Services
- 4.4.3.3: Debug a StatefulSet
- 4.4.3.4: Determine the Reason for Pod Failure
- 4.4.3.5: Debug Init Containers
- 4.4.3.6: Debug Running Pods
- 4.4.3.7: Get a Shell to a Running Container
- 4.4.4: Troubleshooting Clusters
- 4.4.4.1: Troubleshooting kubectl
- 4.4.4.2: Resource metrics pipeline
- 4.4.4.3: Tools for Monitoring Resources
- 4.4.4.4: Monitor Node Health
- 4.4.4.5: Debugging Kubernetes nodes with crictl
- 4.4.4.6: Troubleshooting Topology Management
- 4.4.4.7: Auditing
- 4.4.4.8: Debugging Kubernetes Nodes With Kubectl
- 4.4.4.9: Developing and debugging services locally using telepresence
- 4.4.4.10: Windows debugging tips
- 4.5: Manage Kubernetes Objects
- 4.5.1: Declarative Management of Kubernetes Objects Using Configuration Files
- 4.5.2: Declarative Management of Kubernetes Objects Using Kustomize
- 4.5.3: Managing Kubernetes Objects Using Imperative Commands
- 4.5.4: Imperative Management of Kubernetes Objects Using Configuration Files
- 4.5.5: Update API Objects in Place Using kubectl patch
- 4.5.6: Migrate Kubernetes Objects Using Storage Version Migration
- 4.6: Managing Secrets
- 4.6.1: Managing Secrets using kubectl
- 4.6.2: Managing Secrets using Configuration File
- 4.6.3: Managing Secrets using Kustomize
- 4.7: Inject Data Into Applications
- 4.7.1: Define a Command and Arguments for a Container
- 4.7.2: Define Dependent Environment Variables
- 4.7.3: Define Environment Variables for a Container
- 4.7.4: Define Environment Variable Values Using An Init Container
- 4.7.5: Expose Pod Information to Containers Through Environment Variables
- 4.7.6: Expose Pod Information to Containers Through Files
- 4.7.7: Distribute Credentials Securely Using Secrets
- 4.8: Run Applications
- 4.8.1: Run a Stateless Application Using a Deployment
- 4.8.2: Horizontal Manual Scaling for a Deployment
- 4.8.3: Update a Deployment Without Downtime
- 4.8.4: Run a Single-Instance Stateful Application
- 4.8.5: Run a Replicated Stateful Application
- 4.8.6: Scale a StatefulSet
- 4.8.7: Delete a StatefulSet
- 4.8.8: Force Delete StatefulSet Pods
- 4.8.9: HorizontalPodAutoscaler Walkthrough
- 4.8.10: Specifying a Disruption Budget for your Application
- 4.8.11: Accessing the Kubernetes API from a Pod
- 4.9: Run Jobs
- 4.9.1: Running Automated Tasks with a CronJob
- 4.9.2: Coarse Parallel Processing Using a Work Queue
- 4.9.3: Fine Parallel Processing Using a Work Queue
- 4.9.4: Indexed Job for Parallel Processing with Static Work Assignment
- 4.9.5: Job with Pod-to-Pod Communication
- 4.9.6: Parallel Processing using Expansions
- 4.9.7: Handling retriable and non-retriable pod failures with Pod failure policy
- 4.10: Access Applications in a Cluster
- 4.10.1: Deploy and Access the Kubernetes Dashboard
- 4.10.2: Accessing Clusters
- 4.10.3: Configure Access to Multiple Clusters
- 4.10.4: Use Port Forwarding to Access Applications in a Cluster
- 4.10.5: Use a Service to Access an Application in a Cluster
- 4.10.6: Connect a Frontend to a Backend Using Services
- 4.10.7: Create an External Load Balancer
- 4.10.8: List All Container Images Running in a Cluster
- 4.10.9: Communicate Between Containers in the Same Pod Using a Shared Volume
- 4.10.10: Configure DNS for a Cluster
- 4.10.11: Access Services Running on Clusters
- 4.11: Extend Kubernetes
- 4.11.1: Configure the Aggregation Layer
- 4.11.2: Use Custom Resources
- 4.11.2.1: Extend the Kubernetes API with CustomResourceDefinitions
- 4.11.2.2: Versions in CustomResourceDefinitions
- 4.11.3: Set up an Extension API Server
- 4.11.4: Configure Multiple Schedulers
- 4.11.5: Use an HTTP Proxy to Access the Kubernetes API
- 4.11.6: Use a SOCKS5 Proxy to Access the Kubernetes API
- 4.11.7: Set up Konnectivity service
- 4.12: TLS
- 4.12.1: Issue a Certificate for a Kubernetes API Client Using a CertificateSigningRequest
- 4.12.2: Configure Certificate Rotation for the Kubelet
- 4.12.3: Manage TLS Certificates in a Cluster
- 4.12.4: Manual Rotation of CA Certificates
- 4.13: Manage Cluster Daemons
- 4.13.1: Building a Basic DaemonSet
- 4.13.2: Perform a Rolling Update on a DaemonSet
- 4.13.3: Perform a Rollback on a DaemonSet
- 4.13.4: Running Pods on Only Some Nodes
- 4.14: Networking
- 4.14.1: Adding entries to Pod /etc/hosts with HostAliases
- 4.14.2: Extend Service IP Ranges
- 4.14.3: Kubernetes Default ServiceCIDR Reconfiguration
- 4.14.4: Validate IPv4/IPv6 dual-stack
- 4.15: Extend kubectl with plugins
- 4.16: Manage HugePages
- 4.17: Schedule GPUs
- 5: Tutorials
- 5.1: Hello Minikube
- 5.2: Learn Kubernetes Basics
- 5.2.1: Create a Cluster
- 5.2.1.1: Using Minikube to Create a Cluster
- 5.2.2: Deploy an App
- 5.2.2.1: Using kubectl to Create a Deployment
- 5.2.3: Explore Your App
- 5.2.3.1: Viewing Pods and Nodes
- 5.2.4: Expose Your App Publicly
- 5.2.4.1: Using a Service to Expose Your App
- 5.2.5: Scale Your App
- 5.2.6: Update Your App
- 5.2.6.1: Performing a Rolling Update
- 5.3: Configuration
- 5.3.1: Updating Configuration via a ConfigMap
- 5.3.2: Configuring Redis using a ConfigMap
- 5.3.3: Adopting Sidecar Containers
- 5.3.4: Configure a Pod to Use a PersistentVolume for Storage
- 5.4: Security
- 5.4.1: Apply Pod Security Standards at the Cluster Level
- 5.4.2: Apply Pod Security Standards at the Namespace Level
- 5.4.3: Restrict a Container's Access to Resources with AppArmor
- 5.4.4: Restrict a Container's Syscalls with seccomp
- 5.5: Stateless Applications
- 5.5.1: Deploy a Release Using a Canary Deployment
- 5.5.2: Exposing an External IP Address to Access an Application in a Cluster
- 5.5.3: Example: Deploying PHP Guestbook application with Redis
- 5.6: Stateful Applications
- 5.6.1: StatefulSet Basics
- 5.6.2: Example: Deploying WordPress and MySQL with Persistent Volumes
- 5.6.3: Example: Deploying Cassandra with a StatefulSet
- 5.6.4: Running ZooKeeper, A Distributed System Coordinator
- 5.7: Cluster Management
- 5.7.1: Running Kubelet in Standalone Mode
- 5.7.2: Configuring swap memory on Kubernetes nodes
- 5.7.3: Use Pod-Level Resources with kubelet Resource Managers
- 5.7.4: Install Drivers and Allocate Devices with DRA
- 5.7.5: Explore Validating and Mutating Admission Policies
- 5.7.6: Namespaces Walkthrough
- 5.8: Services
- 6: Reference
- 6.1: Glossary
- 6.2: API Overview
- 6.2.1: Declarative API Validation
- 6.2.2: Kubernetes API Concepts
- 6.2.3: Server-Side Apply
- 6.2.4: Client Libraries
- 6.2.5: Common Expression Language in Kubernetes
- 6.2.6: Deprecated API Migration Guide
- 6.2.7: Kubernetes API health endpoints
- 6.3: API Access Control
- 6.3.1: Authenticating
- 6.3.2: Authenticating with Bootstrap Tokens
- 6.3.3: Authorization
- 6.3.4: Using RBAC Authorization
- 6.3.5: Using Node Authorization
- 6.3.6: Webhook Mode
- 6.3.7: Using ABAC Authorization
- 6.3.8: Admission Control in Kubernetes
- 6.3.9: Dynamic Admission Control
- 6.3.10: Managing Service Accounts
- 6.3.11: User Impersonation
- 6.3.12: Certificates and Certificate Signing Requests
- 6.3.13: Mapping PodSecurityPolicies to Pod Security Standards
- 6.3.14: Kubelet authentication/authorization
- 6.3.15: TLS bootstrapping
- 6.3.16: Manifest-Based Admission Control
- 6.3.17: Mutating Admission Policy
- 6.3.18: Validating Admission Policy
- 6.4: Kubernetes Deprecation Policy
- 6.5: Well-Known Labels, Annotations and Taints
- 6.5.1: Audit Annotations
- 6.6: Kubernetes API
- 6.6.1: API Groups
- 6.6.2: Admissionregistration
- 6.6.2.1: MutatingAdmissionPolicy
- 6.6.2.2: MutatingAdmissionPolicyBinding
- 6.6.2.3: MutatingWebhookConfiguration
- 6.6.2.4: ValidatingAdmissionPolicy
- 6.6.2.5: ValidatingAdmissionPolicyBinding
- 6.6.2.6: ValidatingWebhookConfiguration
- 6.6.3: Apiextensions
- 6.6.3.1: CustomResourceDefinition
- 6.6.4: Apiregistration
- 6.6.4.1: APIService
- 6.6.5: Apiserverinternal
- 6.6.5.1: StorageVersion
- 6.6.6: Apps
- 6.6.6.1: ControllerRevision
- 6.6.6.2: DaemonSet
- 6.6.6.3: Deployment
- 6.6.6.4: ReplicaSet
- 6.6.6.5: StatefulSet
- 6.6.7: Autoscaling
- 6.6.7.1: HorizontalPodAutoscaler
- 6.6.8: Batch
- 6.6.9: Certificates
- 6.6.9.1: CertificateSigningRequest
- 6.6.9.2: ClusterTrustBundle
- 6.6.9.3: PodCertificateRequest
- 6.6.10: Coordination
- 6.6.10.1: Lease
- 6.6.10.2: LeaseCandidate
- 6.6.11: Discovery
- 6.6.11.1: EndpointSlice
- 6.6.12: Events
- 6.6.12.1: Event
- 6.6.13: Core
- 6.6.13.1: ComponentStatus
- 6.6.13.2: ConfigMap
- 6.6.13.3: Endpoints
- 6.6.13.4: Event
- 6.6.13.5: LimitRange
- 6.6.13.6: Namespace
- 6.6.13.7: Node
- 6.6.13.8: PersistentVolume
- 6.6.13.9: PersistentVolumeClaim
- 6.6.13.10: Pod
- 6.6.13.11: PodTemplate
- 6.6.13.12: ReplicationController
- 6.6.13.13: ResourceQuota
- 6.6.13.14: Secret
- 6.6.13.15: Service
- 6.6.13.16: ServiceAccount
- 6.6.14: Flowcontrol
- 6.6.14.1: FlowSchema
- 6.6.14.2: PriorityLevelConfiguration
- 6.6.15: Lifecycle
- 6.6.15.1: Eviction
- 6.6.15.2: EvictionRequest
- 6.6.16: Networking
- 6.6.16.1: IPAddress
- 6.6.16.2: Ingress
- 6.6.16.3: IngressClass
- 6.6.16.4: NetworkPolicy
- 6.6.16.5: ServiceCIDR
- 6.6.17: Node
- 6.6.17.1: RuntimeClass
- 6.6.18: Policy
- 6.6.18.1: PodDisruptionBudget
- 6.6.19: Rbac
- 6.6.19.1: ClusterRole
- 6.6.19.2: ClusterRoleBinding
- 6.6.19.3: Role
- 6.6.19.4: RoleBinding
- 6.6.20: Resource
- 6.6.20.1: DeviceClass
- 6.6.20.2: DeviceTaintRule
- 6.6.20.3: ResourceClaim
- 6.6.20.4: ResourceClaimTemplate
- 6.6.20.5: ResourcePoolStatusRequest
- 6.6.20.6: ResourceSlice
- 6.6.21: Scheduling
- 6.6.21.1: CompositePodGroup
- 6.6.21.2: PodGroup
- 6.6.21.3: PriorityClass
- 6.6.21.4: Workload
- 6.6.22: Storage
- 6.6.22.1: CSIDriver
- 6.6.22.2: CSINode
- 6.6.22.3: CSIStorageCapacity
- 6.6.22.4: StorageClass
- 6.6.22.5: VolumeAttachment
- 6.6.22.6: VolumeAttributesClass
- 6.6.23: Storagemigration
- 6.6.23.1: StorageVersionMigration
- 6.7: Instrumentation
- 6.7.1: Kubernetes Component SLI Metrics
- 6.7.2: CRI Pod & Container Metrics
- 6.7.3: Native Histogram Support for Kubernetes Metrics
- 6.7.4: Node metrics data
- 6.7.5: Understand Pressure Stall Information (PSI) Metrics
- 6.7.6: Kubernetes z-pages
- 6.7.7: Kubernetes Metrics Reference
- 6.8: Kubernetes Issues and Security
- 6.8.1: Kubernetes Issue Tracker
- 6.8.2: Kubernetes Security and Disclosure Information
- 6.8.3: Official CVE Feed
- 6.9: Node Reference Information
- 6.9.1: Kubelet Checkpoint API
- 6.9.2: Linux Kernel Version Requirements
- 6.9.3: Standard Device Attributes for Dynamic Resource Allocation
- 6.9.4: Articles on dockershim Removal and on Using CRI-compatible Runtimes
- 6.9.5: Kubelet Pods API
- 6.9.6: Pod-level resource managers reference
- 6.9.7: Node Labels Populated By The Kubelet
- 6.9.8: Kubelet Sync Loop
- 6.9.9: Local Files And Paths Used By The Kubelet
- 6.9.10: Kubelet Configuration Directory Merging
- 6.9.11: Kubelet Device Manager API Versions
- 6.9.12: Kubelet Systemd Watchdog
- 6.9.13: Node Status
- 6.9.14: Seccomp and Kubernetes
- 6.9.15: What Happens After A Node Restart
- 6.9.16: Linux Node Swap Behaviors
- 6.9.17:
- 6.10: Networking Reference
- 6.10.1: Protocols for Services
- 6.10.2: Ports and Protocols
- 6.10.3: Virtual IPs and Service Proxies
- 6.11: Setup tools
- 6.11.1: Kubeadm
- 6.11.1.1: Kubeadm Generated
- 6.11.1.1.1:
- 6.11.1.1.2:
- 6.11.1.1.2.1:
- 6.11.1.1.2.2:
- 6.11.1.1.2.3:
- 6.11.1.1.2.4:
- 6.11.1.1.2.5:
- 6.11.1.1.2.6:
- 6.11.1.1.2.7:
- 6.11.1.1.2.8:
- 6.11.1.1.2.9:
- 6.11.1.1.2.10:
- 6.11.1.1.2.11:
- 6.11.1.1.2.12:
- 6.11.1.1.2.13:
- 6.11.1.1.2.14:
- 6.11.1.1.2.15:
- 6.11.1.1.2.16:
- 6.11.1.1.3:
- 6.11.1.1.4:
- 6.11.1.1.4.1:
- 6.11.1.1.4.2:
- 6.11.1.1.4.3:
- 6.11.1.1.4.4:
- 6.11.1.1.4.5:
- 6.11.1.1.4.6:
- 6.11.1.1.4.7:
- 6.11.1.1.4.8:
- 6.11.1.1.4.9:
- 6.11.1.1.4.10:
- 6.11.1.1.5:
- 6.11.1.1.5.1:
- 6.11.1.1.5.2:
- 6.11.1.1.5.3:
- 6.11.1.1.5.4:
- 6.11.1.1.5.5:
- 6.11.1.1.5.6:
- 6.11.1.1.5.7:
- 6.11.1.1.5.8:
- 6.11.1.1.5.9:
- 6.11.1.1.5.10:
- 6.11.1.1.5.11:
- 6.11.1.1.5.12:
- 6.11.1.1.5.13:
- 6.11.1.1.5.14:
- 6.11.1.1.5.15:
- 6.11.1.1.5.16:
- 6.11.1.1.5.17:
- 6.11.1.1.5.18:
- 6.11.1.1.5.19:
- 6.11.1.1.5.20:
- 6.11.1.1.5.21:
- 6.11.1.1.5.22:
- 6.11.1.1.5.23:
- 6.11.1.1.5.24:
- 6.11.1.1.5.25:
- 6.11.1.1.5.26:
- 6.11.1.1.5.27:
- 6.11.1.1.5.28:
- 6.11.1.1.5.29:
- 6.11.1.1.5.30:
- 6.11.1.1.5.31:
- 6.11.1.1.5.32:
- 6.11.1.1.5.33:
- 6.11.1.1.5.34:
- 6.11.1.1.5.35:
- 6.11.1.1.5.36:
- 6.11.1.1.5.37:
- 6.11.1.1.5.38:
- 6.11.1.1.5.39:
- 6.11.1.1.5.40:
- 6.11.1.1.5.41:
- 6.11.1.1.5.42:
- 6.11.1.1.5.43:
- 6.11.1.1.5.44:
- 6.11.1.1.5.45:
- 6.11.1.1.5.46:
- 6.11.1.1.6:
- 6.11.1.1.6.1:
- 6.11.1.1.6.2:
- 6.11.1.1.6.3:
- 6.11.1.1.6.4:
- 6.11.1.1.6.5:
- 6.11.1.1.6.6:
- 6.11.1.1.6.7:
- 6.11.1.1.6.8:
- 6.11.1.1.6.9:
- 6.11.1.1.6.10:
- 6.11.1.1.6.11:
- 6.11.1.1.6.12:
- 6.11.1.1.6.13:
- 6.11.1.1.6.14:
- 6.11.1.1.6.15:
- 6.11.1.1.7:
- 6.11.1.1.8:
- 6.11.1.1.9:
- 6.11.1.1.10:
- 6.11.1.1.10.1:
- 6.11.1.1.10.2:
- 6.11.1.1.10.3:
- 6.11.1.1.10.4:
- 6.11.1.1.10.5:
- 6.11.1.1.10.6:
- 6.11.1.1.10.7:
- 6.11.1.1.10.8:
- 6.11.1.1.10.9:
- 6.11.1.1.10.10:
- 6.11.1.1.10.11:
- 6.11.1.1.10.12:
- 6.11.1.1.10.13:
- 6.11.1.1.10.14:
- 6.11.1.1.10.15:
- 6.11.1.1.10.16:
- 6.11.1.1.10.17:
- 6.11.1.1.10.18:
- 6.11.1.1.10.19:
- 6.11.1.1.10.20:
- 6.11.1.1.10.21:
- 6.11.1.1.10.22:
- 6.11.1.1.10.23:
- 6.11.1.1.10.24:
- 6.11.1.1.10.25:
- 6.11.1.1.10.26:
- 6.11.1.1.10.27:
- 6.11.1.1.11:
- 6.11.1.1.12:
- 6.11.1.2: kubeadm init
- 6.11.1.3: kubeadm join
- 6.11.1.4: kubeadm upgrade
- 6.11.1.5: kubeadm upgrade phases
- 6.11.1.6: kubeadm config
- 6.11.1.7: kubeadm reset
- 6.11.1.8: kubeadm token
- 6.11.1.9: kubeadm version
- 6.11.1.10: kubeadm alpha
- 6.11.1.11: kubeadm certs
- 6.11.1.12: kubeadm init phase
- 6.11.1.13: kubeadm join phase
- 6.11.1.14: kubeadm kubeconfig
- 6.11.1.15: kubeadm reset phase
- 6.11.1.16: Implementation details
- 6.12: Command line tool (kubectl)
- 6.12.1: Introduction to kubectl
- 6.12.2: kubectl Quick Reference
- 6.12.3: kubectl reference
- 6.12.3.1: kubectl
- 6.12.3.2: kubectl annotate
- 6.12.3.3: kubectl api-resources
- 6.12.3.4: kubectl api-versions
- 6.12.3.5: kubectl apply
- 6.12.3.5.1: kubectl apply edit-last-applied
- 6.12.3.5.2: kubectl apply set-last-applied
- 6.12.3.5.3: kubectl apply view-last-applied
- 6.12.3.6: kubectl attach
- 6.12.3.7: kubectl auth
- 6.12.3.7.1: kubectl auth can-i
- 6.12.3.7.2: kubectl auth reconcile
- 6.12.3.7.3: kubectl auth whoami
- 6.12.3.8: kubectl autoscale
- 6.12.3.9: kubectl certificate
- 6.12.3.9.1: kubectl certificate approve
- 6.12.3.9.2: kubectl certificate deny
- 6.12.3.10: kubectl cluster-info
- 6.12.3.10.1: kubectl cluster-info dump
- 6.12.3.11: kubectl completion
- 6.12.3.12: kubectl config
- 6.12.3.12.1: kubectl config current-context
- 6.12.3.12.2: kubectl config delete-cluster
- 6.12.3.12.3: kubectl config delete-context
- 6.12.3.12.4: kubectl config delete-user
- 6.12.3.12.5: kubectl config get-clusters
- 6.12.3.12.6: kubectl config get-contexts
- 6.12.3.12.7: kubectl config get-users
- 6.12.3.12.8: kubectl config rename-context
- 6.12.3.12.9: kubectl config set
- 6.12.3.12.10: kubectl config set-cluster
- 6.12.3.12.11: kubectl config set-context
- 6.12.3.12.12: kubectl config set-credentials
- 6.12.3.12.13: kubectl config unset
- 6.12.3.12.14: kubectl config use-context
- 6.12.3.12.15: kubectl config view
- 6.12.3.13: kubectl cordon
- 6.12.3.14: kubectl cp
- 6.12.3.15: kubectl create
- 6.12.3.15.1: kubectl create clusterrole
- 6.12.3.15.2: kubectl create clusterrolebinding
- 6.12.3.15.3: kubectl create configmap
- 6.12.3.15.4: kubectl create cronjob
- 6.12.3.15.5: kubectl create deployment
- 6.12.3.15.6: kubectl create ingress
- 6.12.3.15.7: kubectl create job
- 6.12.3.15.8: kubectl create namespace
- 6.12.3.15.9: kubectl create poddisruptionbudget
- 6.12.3.15.10: kubectl create priorityclass
- 6.12.3.15.11: kubectl create quota
- 6.12.3.15.12: kubectl create role
- 6.12.3.15.13: kubectl create rolebinding
- 6.12.3.15.14: kubectl create secret
- 6.12.3.15.15: kubectl create secret docker-registry
- 6.12.3.15.16: kubectl create secret generic
- 6.12.3.15.17: kubectl create secret tls
- 6.12.3.15.18: kubectl create service
- 6.12.3.15.19: kubectl create service clusterip
- 6.12.3.15.20: kubectl create service externalname
- 6.12.3.15.21: kubectl create service loadbalancer
- 6.12.3.15.22: kubectl create service nodeport
- 6.12.3.15.23: kubectl create serviceaccount
- 6.12.3.15.24: kubectl create token
- 6.12.3.16: kubectl debug
- 6.12.3.17: kubectl delete
- 6.12.3.18: kubectl describe
- 6.12.3.19: kubectl diff
- 6.12.3.20: kubectl drain
- 6.12.3.21: kubectl edit
- 6.12.3.22: kubectl events
- 6.12.3.23: kubectl exec
- 6.12.3.24: kubectl explain
- 6.12.3.25: kubectl expose
- 6.12.3.26: kubectl get
- 6.12.3.27: kubectl kuberc
- 6.12.3.27.1: kubectl kuberc set
- 6.12.3.27.2: kubectl kuberc view
- 6.12.3.28: kubectl kustomize
- 6.12.3.29: kubectl label
- 6.12.3.30: kubectl logs
- 6.12.3.31: kubectl options
- 6.12.3.32: kubectl patch
- 6.12.3.33: kubectl plugin
- 6.12.3.33.1: kubectl plugin list
- 6.12.3.34: kubectl port-forward
- 6.12.3.35: kubectl proxy
- 6.12.3.36: kubectl replace
- 6.12.3.37: kubectl rollout
- 6.12.3.37.1: kubectl rollout history
- 6.12.3.37.2: kubectl rollout pause
- 6.12.3.37.3: kubectl rollout restart
- 6.12.3.37.4: kubectl rollout resume
- 6.12.3.37.5: kubectl rollout status
- 6.12.3.37.6: kubectl rollout undo
- 6.12.3.38: kubectl run
- 6.12.3.39: kubectl scale
- 6.12.3.40: kubectl set
- 6.12.3.40.1: kubectl set env
- 6.12.3.40.2: kubectl set image
- 6.12.3.40.3: kubectl set resources
- 6.12.3.40.4: kubectl set selector
- 6.12.3.40.5: kubectl set serviceaccount
- 6.12.3.40.6: kubectl set subject
- 6.12.3.41: kubectl taint
- 6.12.3.42: kubectl top
- 6.12.3.42.1: kubectl top node
- 6.12.3.42.2: kubectl top pod
- 6.12.3.43: kubectl uncordon
- 6.12.3.44: kubectl version
- 6.12.3.45: kubectl wait
- 6.12.4: kubectl Commands
- 6.12.5: kubectl
- 6.12.6: JSONPath Support
- 6.12.7: kubectl for Docker Users
- 6.12.8: kubectl Usage Conventions
- 6.12.9: Kubectl user preferences (kuberc)
- 6.13: Encodings
- 6.13.1: KYAML Reference
- 6.14: Component tools
- 6.14.1: Feature Gates
- 6.14.2: Feature Gates (removed)
- 6.14.3: kube-apiserver
- 6.14.4: kube-controller-manager
- 6.14.5: kube-proxy
- 6.14.6: kube-scheduler
- 6.14.7: kubelet
- 6.15: Debug cluster
- 6.15.1: Flow control
- 6.16: Configuration APIs
- 6.16.1: Client Authentication (v1)
- 6.16.2: Client Authentication (v1beta1)
- 6.16.3: Event Rate Limit Configuration (v1alpha1)
- 6.16.4: Image Policy API (v1alpha1)
- 6.16.5: kube-apiserver Admission (v1)
- 6.16.6: kube-apiserver Audit Configuration (v1)
- 6.16.7: kube-apiserver Configuration (v1)
- 6.16.8: kube-apiserver Configuration (v1alpha1)
- 6.16.9: kube-apiserver Configuration (v1beta1)
- 6.16.10: kube-controller-manager Configuration (v1alpha1)
- 6.16.11: kube-proxy Configuration (v1alpha1)
- 6.16.12: kube-scheduler Configuration (v1)
- 6.16.13: kubeadm Configuration (v1beta3)
- 6.16.14: kubeadm Configuration (v1beta4)
- 6.16.15: kubeconfig (v1)
- 6.16.16: Kubelet Configuration (v1)
- 6.16.17: Kubelet Configuration (v1alpha1)
- 6.16.18: Kubelet Configuration (v1beta1)
- 6.16.19: Kubelet CredentialProvider (v1)
- 6.16.20: kuberc (v1alpha1)
- 6.16.21: kuberc (v1beta1)
- 6.16.22: WebhookAdmission Configuration (v1)
- 6.17: External APIs
- 6.17.1: Kubernetes Custom Metrics (v1beta2)
- 6.17.2: Kubernetes External Metrics (v1beta1)
- 6.17.3: Kubernetes Metrics (v1)
- 6.17.4: Kubernetes Metrics (v1beta1)
- 6.18: Kubelet APIs
- 6.18.1: Kubelet Summary API (v1alpha1)
- 6.19: Scheduling
- 6.19.1: Scheduler Configuration
- 6.19.2: Scheduling Policies
- 6.20: Other Tools
- 7: Contribute to Kubernetes
- 7.1: Contribute to Kubernetes Documentation
- 7.2: Contributing to Kubernetes blogs
- 7.2.1: Submitting articles to Kubernetes blogs
- 7.2.2: Blog guidelines
- 7.2.3: Blog article mirroring
- 7.2.4: Post-release communications
- 7.2.5: Helping as a blog writing buddy
- 7.3: Suggesting content improvements
- 7.4: Contributing new content
- 7.4.1: Opening a pull request
- 7.4.2: Previewing locally
- 7.4.3: Documenting a feature for a release
- 7.4.4: Submitting case studies
- 7.5: Reviewing changes
- 7.6: Localizing Kubernetes documentation
- 7.7: Participating in SIG Docs
- 7.7.1: Roles and responsibilities
- 7.7.2: Issue Wranglers
- 7.7.3: PR wranglers
- 7.8: Documentation style overview
- 7.8.1: Documentation Content Guide
- 7.8.2: Documentation Style Guide
- 7.8.3: Diagram Guide
- 7.8.4: Writing a new topic
- 7.8.5: Page content types
- 7.8.6: Content organization
- 7.8.7: Custom Hugo Shortcodes
- 7.9: Updating Reference Documentation
- 7.9.1: Reference Documentation Quickstart
- 7.9.2: Generating Reference Documentation for a Release
- 7.9.3: Contributing to the Upstream Kubernetes Code
- 7.9.4: Generating Reference Documentation for the Kubernetes API
- 7.9.5: Generating Reference Documentation for Configuration APIs
- 7.9.6: Generating Reference Documentation for kubectl Commands
- 7.9.7: Generating Reference Documentation for Metrics
- 7.9.8: Generating Reference Pages for Kubernetes Components and Tools
- 7.9.9:
- 7.10: Advanced contributing
- 7.11: Viewing Site Analytics
- 8: Docs smoke test page
1 - Kubernetes Documentation
1.1 - Available Documentation Versions
This website contains documentation for the current version of Kubernetes and the four previous versions of Kubernetes.
The availability of documentation for a Kubernetes version is separate from whether that release is currently supported. Read Support period to learn about which versions of Kubernetes are officially supported, and for how long.
2 - Getting started
This section lists the different ways to set up and run Kubernetes. When you install Kubernetes, choose an installation type based on: ease of maintenance, security, control, available resources, and expertise required to operate and manage a cluster.
You can download Kubernetes to deploy a Kubernetes cluster on a local machine, into the cloud, or for your own datacenter.
Several Kubernetes components such as kube-apiserver or kube-proxy can also be deployed as container images within the cluster.
It is recommended to run Kubernetes components as container images wherever that is possible, and to have Kubernetes manage those components. Components that run containers - notably, the kubelet - can't be included in this category.
If you don't want to manage a Kubernetes cluster yourself, you could pick a managed service, including certified platforms. There are also other standardized and custom solutions across a wide range of cloud and bare metal environments.
Learning environment
If you're learning Kubernetes, use the tools supported by the Kubernetes community, or tools in the ecosystem to set up a Kubernetes cluster on a local machine. See Learning environment
Production environment
When evaluating a solution for a production environment, consider which aspects of operating a Kubernetes cluster (or abstractions) you want to manage yourself and which you prefer to hand off to a provider.
For a cluster you're managing yourself, the officially supported tool for deploying Kubernetes is kubeadm.
What's next
- Download Kubernetes
- Download and install tools including
kubectl - Select a container runtime for your new cluster
- Learn about best practices for cluster setup
Kubernetes is designed for its control plane to run on Linux. Within your cluster you can run applications on Linux or other operating systems, including Windows.
- Learn to set up clusters with Windows nodes
2.1 - Learning environment
If you are learning Kubernetes, you need a place to practice. This page explains your options for setting up a Kubernetes environment where you can experiment and learn.
Installing kubectl
Before you set up a cluster, you need the kubectl command-line tool. This tool lets you communicate with a Kubernetes cluster and run commands against it.
See Install and Set Up kubectl for installation instructions.
Setting up local Kubernetes environments
Running Kubernetes locally gives you a safe environment to learn and experiment. You can set up and tear down clusters without worrying about costs or affecting production systems.
kind
kind (Kubernetes IN Docker) runs Kubernetes clusters using Docker containers as nodes. It is lightweight and designed specifically for testing Kubernetes itself, but works great for learning too.
To get started with kind, see the kind Quick Start.
minikube
minikube runs a single-node Kubernetes cluster on your local machine. It supports multiple container runtimes and works on Linux, macOS, and Windows.
To get started with minikube, see the minikube Get Started guide.
Other local options
There are several third-party tools that can also run Kubernetes locally. Kubernetes does not provide support for these tools, but they may work well for your learning needs:
- Docker Desktop can run a local Kubernetes cluster
- Podman Desktop can run a local Kubernetes cluster
- Rancher Desktop provides Kubernetes on your desktop
- MicroK8s runs a lightweight Kubernetes cluster
- Red Hat CodeReady Containers (CRC) runs a minimal OpenShift cluster locally (OpenShift is Kubernetes-conformant)
Refer to each tool's documentation for setup instructions and support.
Using online playgrounds
Online Kubernetes playgrounds let you try Kubernetes without installing anything on your computer. These environments run in your web browser:
- Killercoda provides interactive Kubernetes scenarios and a playground environment
These platforms are useful for quick experiments and following tutorials without local setup.
Practicing with production-like clusters
If you want to practice setting up a more production-like cluster, you can use kubeadm. Setting up a cluster with kubeadm is an advanced task that requires multiple machines (physical or virtual) and careful configuration.
For learning about production environments, see Production environment.
Note:
Setting up a production-like cluster is significantly more complex than the learning environments described above. Start with kind, minikube, or an online playground first.What's next
- Follow the Hello Minikube tutorial to deploy your first application
- Learn about Kubernetes components
- Explore kubectl commands
2.2 - Production environment
A production-quality Kubernetes cluster requires planning and preparation. If your Kubernetes cluster is to run critical workloads, it must be configured to be resilient. This page explains steps you can take to set up a production-ready cluster, or to promote an existing cluster for production use. If you're already familiar with production setup and want the links, skip to What's next.
Production considerations
Typically, a production Kubernetes cluster environment has more requirements than a personal learning, development, or test environment Kubernetes. A production environment may require secure access by many users, consistent availability, and the resources to adapt to changing demands.
As you decide where you want your production Kubernetes environment to live (on premises or in a cloud) and the amount of management you want to take on or hand to others, consider how your requirements for a Kubernetes cluster are influenced by the following issues:
Availability: A single-machine Kubernetes learning environment has a single point of failure. Creating a highly available cluster means considering:
- Separating the control plane from the worker nodes.
- Replicating the control plane components on multiple nodes.
- Load balancing traffic to the cluster’s API server.
- Having enough worker nodes available, or able to quickly become available, as changing workloads warrant it.
Scale: If you expect your production Kubernetes environment to receive a stable amount of demand, you might be able to set up for the capacity you need and be done. However, if you expect demand to grow over time or change dramatically based on things like season or special events, you need to plan how to scale to relieve increased pressure from more requests to the control plane and worker nodes or scale down to reduce unused resources.
Security and access management: You have full admin privileges on your own Kubernetes learning cluster. But shared clusters with important workloads, and more than one or two users, require a more refined approach to who and what can access cluster resources. You can use role-based access control (RBAC) and other security mechanisms to make sure that users and workloads can get access to the resources they need, while keeping workloads, and the cluster itself, secure. You can set limits on the resources that users and workloads can access by managing policies and container resources.
Before building a Kubernetes production environment on your own, consider handing off some or all of this job to Turnkey Cloud Solutions providers or other Kubernetes Partners. Options include:
- Serverless: Just run workloads on third-party equipment without managing a cluster at all. You will be charged for things like CPU usage, memory, and disk requests.
- Managed control plane: Let the provider manage the scale and availability of the cluster's control plane, as well as handle patches and upgrades.
- Managed worker nodes: Configure pools of nodes to meet your needs, then the provider makes sure those nodes are available and ready to implement upgrades when needed.
- Integration: There are providers that integrate Kubernetes with other services you may need, such as storage, container registries, authentication methods, and development tools.
Whether you build a production Kubernetes cluster yourself or work with partners, review the following sections to evaluate your needs as they relate to your cluster’s control plane, worker nodes, user access, and workload resources.
Production cluster setup
In a production-quality Kubernetes cluster, the control plane manages the cluster from services that can be spread across multiple computers in different ways. Each worker node, however, represents a single entity that is configured to run Kubernetes pods.
Production control plane
The simplest Kubernetes cluster has the entire control plane and worker node services running on the same machine. You can grow that environment by adding worker nodes, as reflected in the diagram illustrated in Kubernetes Components. If the cluster is meant to be available for a short period of time, or can be discarded if something goes seriously wrong, this might meet your needs.
If you need a more permanent, highly available cluster, however, you should consider ways of extending the control plane. By design, one-machine control plane services running on a single machine are not highly available. If keeping the cluster up and running and ensuring that it can be repaired if something goes wrong is important, consider these steps:
- Choose deployment tools: You can deploy a control plane using tools such as kubeadm, kops, and kubespray. See Installing Kubernetes with deployment tools to learn tips for production-quality deployments using each of those deployment methods. Different Container Runtimes are available to use with your deployments.
- Manage certificates: Secure communications between control plane services are implemented using certificates. Certificates are automatically generated during deployment or you can generate them using your own certificate authority. See PKI certificates and requirements for details.
- Configure load balancer for apiserver: Configure a load balancer to distribute external API requests to the apiserver service instances running on different nodes. See Create an External Load Balancer for details.
- Separate and backup etcd service: The etcd services can either run on the same machines as other control plane services or run on separate machines, for extra security and availability. Because etcd stores cluster configuration data, backing up the etcd database should be done regularly to ensure that you can repair that database if needed. See the etcd FAQ for details on configuring and using etcd. See Operating etcd clusters for Kubernetes and Set up a High Availability etcd cluster with kubeadm for details.
- Create multiple control plane systems: For high availability, the control plane should not be limited to a single machine. If the control plane services are run by an init service (such as systemd), each service should run on at least three machines. However, running control plane services as pods in Kubernetes ensures that the replicated number of services that you request will always be available. The scheduler should be fault tolerant, but not highly available. Some deployment tools set up Raft consensus algorithm to do leader election of Kubernetes services. If the primary goes away, another service elects itself and take over.
- Span multiple zones: If keeping your cluster available at all times is critical, consider creating a cluster that runs across multiple data centers, referred to as zones in cloud environments. Groups of zones are referred to as regions. By spreading a cluster across multiple zones in the same region, it can improve the chances that your cluster will continue to function even if one zone becomes unavailable. See Running in multiple zones for details.
- Manage on-going features: If you plan to keep your cluster over time, there are tasks you need to do to maintain its health and security. For example, if you installed with kubeadm, there are instructions to help you with Certificate Management and Upgrading kubeadm clusters. See Administer a Cluster for a longer list of Kubernetes administrative tasks.
To learn about available options when you run control plane services, see kube-apiserver, kube-controller-manager, and kube-scheduler component pages. For highly available control plane examples, see Options for Highly Available topology, Creating Highly Available clusters with kubeadm, and Operating etcd clusters for Kubernetes. See Backing up an etcd cluster for information on making an etcd backup plan.
Production worker nodes
Production-quality workloads need to be resilient and anything they rely on needs to be resilient (such as CoreDNS). Whether you manage your own control plane or have a cloud provider do it for you, you still need to consider how you want to manage your worker nodes (also referred to simply as nodes).
- Configure nodes: Nodes can be physical or virtual machines. If you want to
create and manage your own nodes, you can install a supported operating system,
then add and run the appropriate
Node services. Consider:
- The demands of your workloads when you set up nodes by having appropriate memory, CPU, and disk speed and storage capacity available.
- Whether generic computer systems will do or you have workloads that need GPU processors, Windows nodes, or VM isolation.
- Validate nodes: See Valid node setup for information on how to ensure that a node meets the requirements to join a Kubernetes cluster.
- Add nodes to the cluster: If you are managing your own cluster you can add nodes by setting up your own machines and either adding them manually or having them register themselves to the cluster’s apiserver. See the Nodes section for information on how to set up Kubernetes to add nodes in these ways.
- Scale nodes: Have a plan for expanding the capacity your cluster will eventually need. See Considerations for large clusters to help determine how many nodes you need, based on the number of pods and containers you need to run. If you are managing nodes yourself, this can mean purchasing and installing your own physical equipment.
- Autoscale nodes: Read Node Autoscaling to learn about the tools available to automatically manage your nodes and the capacity they provide.
- Set up node health checks: For important workloads, you want to make sure that the nodes and pods running on those nodes are healthy. Using the Node Problem Detector daemon, you can ensure your nodes are healthy.
Production user management
In production, you may be moving from a model where you or a small group of people are accessing the cluster to where there may potentially be dozens or hundreds of people. In a learning environment or platform prototype, you might have a single administrative account for everything you do. In production, you will want more accounts with different levels of access to different namespaces.
Taking on a production-quality cluster means deciding how you want to selectively allow access by other users. In particular, you need to select strategies for validating the identities of those who try to access your cluster (authentication) and deciding if they have permissions to do what they are asking (authorization):
- Authentication: The apiserver can authenticate users using client certificates, bearer tokens, an authenticating proxy, or HTTP basic auth. You can choose which authentication methods you want to use. Using plugins, the apiserver can leverage your organization’s existing authentication methods, such as LDAP or Kerberos. See Authentication for a description of these different methods of authenticating Kubernetes users.
- Authorization: When you set out to authorize your regular users, you will probably choose
between RBAC and ABAC authorization. See Authorization Overview
to review different modes for authorizing user accounts (as well as service account access to
your cluster):
- Role-based access control (RBAC): Lets you assign access to your cluster by allowing specific sets of permissions to authenticated users. Permissions can be assigned for a specific namespace (Role) or across the entire cluster (ClusterRole). Then using RoleBindings and ClusterRoleBindings, those permissions can be attached to particular users.
- Attribute-based access control (ABAC): Lets you create policies based on resource attributes in the cluster and will allow or deny access based on those attributes. Each line of a policy file identifies versioning properties (apiVersion and kind) and a map of spec properties to match the subject (user or group), resource property, non-resource property (/version or /apis), and readonly. See Examples for details.
As someone setting up authentication and authorization on your production Kubernetes cluster, here are some things to consider:
- Set the authorization mode: When the Kubernetes API server (kube-apiserver) starts, supported authorization modes must be set using an --authorization-config file or the --authorization-mode flag. For example, that flag in the kube-adminserver.yaml file (in /etc/kubernetes/manifests) could be set to Node,RBAC. This would allow Node and RBAC authorization for authenticated requests.
- Create user certificates and role bindings (RBAC): If you are using RBAC authorization, users can create a CertificateSigningRequest (CSR) that can be signed by the cluster CA. Then you can bind Roles and ClusterRoles to each user. See Certificate Signing Requests for details.
- Create policies that combine attributes (ABAC): If you are using ABAC authorization, you can assign combinations of attributes to form policies to authorize selected users or groups to access particular resources (such as a pod), namespace, or apiGroup. For more information, see Examples.
- Consider Admission Controllers: Additional forms of authorization for requests that can come in through the API server include Webhook Token Authentication. Webhooks and other special authorization types need to be enabled by adding Admission Controllers to the API server.
Set limits on workload resources
Demands from production workloads can cause pressure both inside and outside of the Kubernetes control plane. Consider these items when setting up for the needs of your cluster's workloads:
- Set namespace limits: Set per-namespace quotas on things like memory and CPU. See Manage Memory, CPU, and API Resources for details.
- Prepare for DNS demand: If you expect workloads to massively scale up, your DNS service must be ready to scale up as well. See Autoscale the DNS service in a Cluster.
- Create additional service accounts: User accounts determine what users can
do on a cluster, while a service account defines pod access within a particular
namespace. By default, a pod takes on the default service account from its namespace.
See Managing Service Accounts
for information on creating a new service account. For example, you might want to:
- Add secrets that a pod could use to pull images from a particular container registry. See Configure Service Accounts for Pods for an example.
- Assign RBAC permissions to a service account. See ServiceAccount permissions for details.
What's next
- Decide if you want to build your own production Kubernetes or obtain one from available Turnkey Cloud Solutions or Kubernetes Partners.
- If you choose to build your own cluster, plan how you want to handle certificates and set up high availability for features such as etcd and the API server.
- Choose from kubeadm, kops or Kubespray deployment methods.
- Configure user management by determining your Authentication and Authorization methods.
- Prepare for application workloads by setting up resource limits, DNS autoscaling and service accounts.
2.2.1 - Container Runtimes
You need to install a container runtime into each node in the cluster so that Pods can run there. This page outlines what is involved and describes related tasks for setting up nodes.
Kubernetes 1.37 requires that you use a runtime that conforms with the Container Runtime Interface (CRI).
See CRI version support for more information.
This page provides an outline of how to use several common container runtimes with Kubernetes.
Note:
Kubernetes releases before v1.24 included a direct integration with Docker Engine, using a component named dockershim. That special direct integration is no longer part of Kubernetes (this removal was announced as part of the v1.20 release). You can read Check whether Dockershim removal affects you to understand how this removal might affect you. To learn about migrating from using dockershim, see Migrating from dockershim.
If you are running a version of Kubernetes other than v1.37, check the documentation for that version.
Install and configure prerequisites
Network configuration
By default, the Linux kernel does not allow IPv4 packets to be routed between interfaces. Most Kubernetes cluster networking implementations will change this setting (if needed), but some might expect the administrator to do it for them. (Some might also expect other sysctl parameters to be set, kernel modules to be loaded, etc; consult the documentation for your specific network implementation.)
Enable IPv4 packet forwarding
To manually enable IPv4 packet forwarding:
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
Verify that net.ipv4.ip_forward is set to 1 with:
sysctl net.ipv4.ip_forward
cgroup drivers
On Linux, control groups are used to constrain resources that are allocated to processes.
Both the kubelet and the underlying container runtime need to interface with control groups to enforce resource management for pods and containers and set resources such as cpu/memory requests and limits. To interface with control groups, the kubelet and the container runtime need to use a cgroup driver. It's critical that the kubelet and the container runtime use the same cgroup driver and are configured the same.
There are two cgroup drivers available:
cgroupfs driver
The cgroupfs driver is the default cgroup driver in the kubelet.
When the cgroupfs driver is used, the kubelet and the container runtime directly interface with
the cgroup filesystem to configure cgroups.
The cgroupfs driver is not recommended when
systemd is the
init system because systemd expects a single cgroup manager on
the system. Additionally, if you use cgroup v2, use the systemd
cgroup driver instead of cgroupfs.
systemd cgroup driver
When systemd is chosen as the init
system for a Linux distribution, the init process generates and consumes a root control group
(cgroup) and acts as a cgroup manager.
systemd has a tight integration with cgroups and allocates a cgroup per systemd
unit. As a result, if you use systemd as the init system with the cgroupfs
driver, the system gets two different cgroup managers.
Two cgroup managers result in two views of the available and in-use resources in
the system. In some cases, nodes that are configured to use cgroupfs for the
kubelet and container runtime, but use systemd for the rest of the processes become
unstable under resource pressure.
The approach to mitigate this instability is to use systemd as the cgroup driver for
the kubelet and the container runtime when systemd is the selected init system.
To set systemd as the cgroup driver, edit the
KubeletConfiguration
option of cgroupDriver and set it to systemd. For example:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd
If you configure systemd as the cgroup driver for the kubelet, you must also
configure systemd as the cgroup driver for the container runtime. Refer to
the documentation for your container runtime for instructions. For example:
In Kubernetes 1.37, with the KubeletCgroupDriverFromCRI
feature gate
enabled and a container runtime that supports the RuntimeConfig CRI RPC,
the kubelet automatically detects the appropriate cgroup driver from the runtime,
and ignores the cgroupDriver setting within the kubelet configuration.
However, older versions of container runtimes (specifically,
containerd 1.y and below) do not support the RuntimeConfig CRI RPC, and
may not respond correctly to this query, and thus the Kubelet falls back to using the
value in its own --cgroup-driver flag.
In Kubernetes 1.38, this fallback behavior will be dropped, and older versions of containerd will fail with newer kubelets.
Caution:
Changing the cgroup driver of a Node that has joined a cluster is a sensitive operation. If the kubelet has created Pods using the semantics of one cgroup driver, changing the container runtime to another cgroup driver can cause errors when trying to re-create the Pod sandbox for such existing Pods. Restarting the kubelet may not solve such errors.
If you have automation that makes it feasible, replace the node with another using the updated configuration, or reinstall it using automation.
CRI version support
Your container runtime must support v1 of the container runtime interface.
Kubernetes starting v1.26 only works with v1 of the CRI API. If a container runtime does not support the v1 API, the kubelet will not register as a node.
Container runtimes
containerd
This section outlines the necessary steps to use containerd as CRI runtime.
To install containerd on your system, follow the instructions on
getting started with containerd.
Return to this step once you've created a valid config.toml configuration file.
You can find this file under the path /etc/containerd/config.toml.
You can find this file under the path C:\Program Files\containerd\config.toml.
On Linux the default CRI socket for containerd is /run/containerd/containerd.sock.
On Windows the default CRI endpoint is npipe://./pipe/containerd-containerd.
Configuring the systemd cgroup driver
To use the systemd cgroup driver in /etc/containerd/config.toml with runc,
set the following config based on your Containerd version
Containerd versions 1.x:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
Containerd versions 2.x:
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
...
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
SystemdCgroup = true
The systemd cgroup driver is recommended if you use cgroup v2.
Note:
If you installed containerd from a package (for example, RPM or .deb), you may find
that the CRI integration plugin is disabled by default.
You need CRI support enabled to use containerd with Kubernetes. Make sure that cri
is not included in thedisabled_plugins list within /etc/containerd/config.toml;
if you made changes to that file, also restart containerd.
If you experience container crash loops after the initial cluster installation or after
installing a CNI, the containerd configuration provided with the package might contain
incompatible configuration parameters. Consider resetting the containerd configuration
with containerd config default > /etc/containerd/config.toml as specified in
getting-started.md
and then set the configuration parameters specified above accordingly.
If you apply this change, make sure to restart containerd:
sudo systemctl restart containerd
In Kubernetes v1.28, you can enable automatic detection of the cgroup driver as an alpha feature. See systemd cgroup driver for more details.
Overriding the sandbox (pause) image
In your containerd config you can overwrite the sandbox image by setting the following config:
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.10"
You might need to restart containerd as well once you've updated the config file: systemctl restart containerd.
CRI-O
This section contains the necessary steps to install CRI-O as a container runtime.
To install CRI-O, follow CRI-O Install Instructions.
cgroup driver
CRI-O uses the systemd cgroup driver per default, which is likely to work fine
for you. To switch to the cgroupfs cgroup driver, either edit
/etc/crio/crio.conf or place a drop-in configuration in
/etc/crio/crio.conf.d/02-cgroup-manager.conf, for example:
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"
You should also note the changed conmon_cgroup, which has to be set to the value
pod when using CRI-O with cgroupfs. It is generally necessary to keep the
cgroup driver configuration of the kubelet (usually done via kubeadm) and CRI-O
in sync.
In Kubernetes v1.28, you can enable automatic detection of the cgroup driver as an alpha feature. See systemd cgroup driver for more details.
For CRI-O, the CRI socket is /var/run/crio/crio.sock by default.
Overriding the sandbox (pause) image
In your CRI-O config you can set the following config value:
[crio.image]
pause_image="registry.k8s.io/pause:3.10"
This config option supports live configuration reload to apply this change: systemctl reload crio or by sending
SIGHUP to the crio process.
Docker Engine
Note:
These instructions assume that you are using thecri-dockerd adapter to integrate
Docker Engine with Kubernetes.On each of your nodes, install Docker for your Linux distribution as per Install Docker Engine.
Install
cri-dockerd, following the directions in the install section of the documentation.
For cri-dockerd, the CRI socket is /run/cri-dockerd.sock by default.
Mirantis Container Runtime
Mirantis Container Runtime (MCR) is a commercially available container runtime that was formerly known as Docker Enterprise Edition.
You can use Mirantis Container Runtime with Kubernetes using the open source
cri-dockerd component, included with MCR.
To learn more about how to install Mirantis Container Runtime, visit MCR Deployment Guide.
Check the systemd unit named cri-docker.socket to find out the path to the CRI
socket.
Overriding the sandbox (pause) image
The cri-dockerd adapter accepts a command line argument for
specifying which container image to use as the Pod infrastructure container (“pause image”).
The command line argument to use is --pod-infra-container-image.
What's next
As well as a container runtime, your cluster will need a working network plugin.
2.2.2 - Installing Kubernetes with deployment tools
There are many methods and tools for setting up your own production Kubernetes cluster. For example:
Cluster API: A Kubernetes sub-project focused on providing declarative APIs and tooling to simplify provisioning, upgrading, and operating multiple Kubernetes clusters.
kops: An automated cluster provisioning tool. For tutorials, best practices, configuration options and information on reaching out to the community, please check the
kOpswebsite for details.kubespray: A composition of Ansible playbooks, inventory, provisioning tools, and domain knowledge for generic OS/Kubernetes clusters configuration management tasks. You can reach out to the community on Slack channel #kubespray.
2.2.2.1 - Bootstrapping clusters with kubeadm
2.2.2.1.1 - Installing kubeadm
This page shows how to install the kubeadm toolbox.
For information on how to create a cluster with kubeadm once you have performed this installation process,
see the Creating a cluster with kubeadm page.
This installation guide is for Kubernetes v1.37. If you want to use a different Kubernetes version, please refer to the following pages instead:
Before you begin
- A compatible Linux host. The Kubernetes project provides generic instructions for Linux distributions based on Debian and Red Hat, and those distributions without a package manager.
- 2 GB or more of RAM per machine (any less will leave little room for your apps).
- 2 CPUs or more for control plane machines.
- Full network connectivity between all machines in the cluster (public or private network is fine).
- Unique hostname, MAC address, and product_uuid for every node. See here for more details.
- Certain ports are open on your machines. See here for more details.
Note:
Thekubeadm installation is done via binaries that use dynamic linking and assumes that your target system provides glibc.
This is a reasonable assumption on many Linux distributions (including Debian, Ubuntu, Fedora, CentOS, etc.)
but it is not always the case with custom and lightweight distributions which don't include glibc by default, such as Alpine Linux.
The expectation is that the distribution either includes glibc or a
compatibility layer
that provides the expected symbols.Check your OS version
- The kubeadm project supports LTS kernels. See List of LTS kernels.
- You can get the kernel version using the command
uname -r
For more information, see Linux Kernel Requirements.
- The kubeadm project supports recent kernel versions. For a list of recent kernels, see Windows Server Release Information.
- You can get the kernel version (also called the OS version) using the command
systeminfo
For more information, see Windows OS version compatibility.
A Kubernetes cluster created by kubeadm depends on software that use kernel features. This software includes, but is not limited to the container runtime, the kubelet, and a Container Network Interface plugin.
To help you avoid unexpected errors as a result of an unsupported kernel version, kubeadm runs the SystemVerification
pre-flight check. This check fails if the kernel version is not supported.
You may choose to skip the check, if you know that your kernel provides the required features, even though kubeadm does not support its version.
Verify the MAC address and product_uuid are unique for every node
- You can get the MAC address of the network interfaces using the command
ip linkorifconfig -a - The product_uuid can be checked by using the command
sudo cat /sys/class/dmi/id/product_uuid
It is very likely that hardware devices will have unique addresses, although some virtual machines may have identical values. Kubernetes uses these values to uniquely identify the nodes in the cluster. If these values are not unique to each node, the installation process may fail.
Check network adapters
If you have more than one network adapter, and your Kubernetes components are not reachable on the default route, we recommend you add IP route(s) so Kubernetes cluster addresses go via the appropriate adapter.
Check required ports
These required ports need to be open in order for Kubernetes components to communicate with each other. You can use tools like netcat to check if a port is open. For example:
nc 127.0.0.1 6443 -zv -w 2
The pod network plugin you use may also require certain ports to be open. Since this differs with each pod network plugin, please see the documentation for the plugins about what port(s) those need.
Swap configuration
The default behavior of a kubelet is to fail to start if swap memory is detected on a node. This means that swap should either be disabled or tolerated by kubelet.
- To tolerate swap, add
failSwapOn: falseto kubelet configuration or as a command line argument. Note: even iffailSwapOn: falseis provided, workloads wouldn't have swap access by default. This can be changed by setting aswapBehavior, again in the kubelet configuration file. To use swap, set aswapBehaviorother than the defaultNoSwapsetting. See Swap memory management for more details. - To disable swap,
sudo swapoff -acan be used to disable swapping temporarily. To make this change persistent across reboots, make sure swap is disabled in config files like/etc/fstab,systemd.swap, depending how it was configured on your system.
Installing a container runtime
To run containers in Pods, Kubernetes uses a container runtime.
By default, Kubernetes uses the Container Runtime Interface (CRI) to interface with your chosen container runtime.
If you don't specify a runtime, kubeadm automatically tries to detect an installed container runtime by scanning through a list of known endpoints.
If multiple or no container runtimes are detected kubeadm will throw an error and will request that you specify which one you want to use.
See container runtimes for more information.
Note:
Docker Engine does not implement the CRI which is a requirement for a container runtime to work with Kubernetes. For that reason, an additional service cri-dockerd has to be installed. cri-dockerd is a project based on the legacy built-in Docker Engine support that was removed from the kubelet in version 1.24.The tables below include the known endpoints for supported operating systems:
| Runtime | Path to Unix domain socket |
|---|---|
| containerd | unix:///var/run/containerd/containerd.sock |
| CRI-O | unix:///var/run/crio/crio.sock |
| Docker Engine (using cri-dockerd) | unix:///var/run/cri-dockerd.sock |
| Runtime | Path to Windows named pipe |
|---|---|
| containerd | npipe:////./pipe/containerd-containerd |
| Docker Engine (using cri-dockerd) | npipe:////./pipe/cri-dockerd |
Installing kubeadm, kubelet and kubectl
You will install these packages on all of your machines:
kubeadm: the command to bootstrap the cluster.kubelet: the component that runs on all of the machines in your cluster and does things like starting pods and containers.kubectl: the command line util to talk to your cluster.
kubeadm will not install or manage kubelet or kubectl for you, so you will
need to ensure they match the version of the Kubernetes control plane you want
kubeadm to install for you. If you do not, there is a risk of a version skew occurring that
can lead to unexpected, buggy behaviour. However, one minor version skew between the
kubelet and the control plane is supported, but the kubelet version may never exceed the API
server version. For example, the kubelet running 1.7.0 should be fully compatible with a 1.8.0 API server,
but not vice versa.
For information about installing kubectl, see Install and set up kubectl.
Warning:
These instructions exclude all Kubernetes packages from any system upgrades. This is because kubeadm and Kubernetes require special attention to upgrade.For more information on version skews, see:
- Kubernetes version and version-skew policy
- Kubeadm-specific version skew policy
apt.kubernetes.io and yum.kubernetes.io) have been
deprecated and frozen starting from September 13, 2023.
Using the new package repositories hosted at pkgs.k8s.io
is strongly recommended and required in order to install Kubernetes versions released after September 13, 2023.
The deprecated legacy repositories, and their contents, might be removed at any time in the future and without
a further notice period. The new package repositories provide downloads for Kubernetes versions starting with v1.24.0.Note:
There's a dedicated package repository for each Kubernetes minor version. If you want to install a minor version other than v1.37, please see the installation guide for your desired minor version.These instructions are for Kubernetes v1.37.
Update the
aptpackage index and install packages needed to use the Kubernetesaptrepository:sudo apt-get update # apt-transport-https may be a dummy package; if so, you can skip that package sudo apt-get install -y apt-transport-https ca-certificates curl gpgDownload the public signing key for the Kubernetes package repositories. The same signing key is used for all repositories so you can disregard the version in the URL:
# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below. # sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.37/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
Note:
In releases older than Debian 12 and Ubuntu 22.04, directory/etc/apt/keyrings does not
exist by default, and it should be created before the curl command.Add the appropriate Kubernetes
aptrepository. Please note that this repository have packages only for Kubernetes 1.37; for other Kubernetes minor versions, you need to change the Kubernetes minor version in the URL to match your desired minor version (you should also check that you are reading the documentation for the version of Kubernetes that you plan to install).# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.37/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.listUpdate the
aptpackage index, install kubelet, kubeadm and kubectl, and pin their version:sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl(Optional) Enable the kubelet service before running kubeadm:
sudo systemctl enable --now kubelet
Set SELinux to
permissivemode:These instructions are for Kubernetes 1.37.
# Set SELinux in permissive mode (effectively disabling it) sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
Caution:
- Setting SELinux in permissive mode by running
setenforce 0andsed ...effectively disables it. This is required to allow containers to access the host filesystem; for example, some cluster network plugins require that. You have to do this until SELinux support is improved in the kubelet. - You can leave SELinux enabled if you know how to configure it but it may require settings that are not supported by kubeadm.
Add the Kubernetes
yumrepository. Theexcludeparameter in the repository definition ensures that the packages related to Kubernetes are not upgraded upon running a normaldnf updateas there's a special procedure that must be followed for upgrading Kubernetes. Please note that this repository has packages only for Kubernetes 1.37; for other Kubernetes minor versions, you need to change the Kubernetes minor version in the URL to match your desired minor version (you should also check that you are reading the documentation for the version of Kubernetes that you plan to install).# This overwrites any existing configuration in /etc/yum.repos.d/kubernetes.repo cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://pkgs.k8s.io/core:/stable:/v1.37/rpm/ enabled=1 gpgcheck=1 gpgkey=https://pkgs.k8s.io/core:/stable:/v1.37/rpm/repodata/repomd.xml.key exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni EOFInstall kubelet, kubeadm and kubectl:
For systems with DNF4 (Fedora < 41, RHEL/CentOS < 10)
sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetesFor Fedora systems with DNF5:
sudo dnf install -y kubelet kubeadm kubectl --setopt=disable_excludes=kubernetesFor RHEL/CentOS 10 and later, to avoid pulling in
iptablesas a dependency:sudo dnf install -y kubelet kubeadm kubectl --setopt=disable_excludes=kubernetes --setopt=install_weak_deps=False(Optional) Enable the kubelet service before running kubeadm:
sudo systemctl enable --now kubelet
Install CNI plugins (required for most pod network):
CNI_PLUGINS_VERSION="v1.3.0"
ARCH="amd64"
DEST="/opt/cni/bin"
sudo mkdir -p "$DEST"
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${ARCH}-${CNI_PLUGINS_VERSION}.tgz" | sudo tar -C "$DEST" -xz
Define the directory to download command files:
Note:
TheDOWNLOAD_DIR variable must be set to a writable directory.
If you are running Flatcar Container Linux, set DOWNLOAD_DIR="/opt/bin".DOWNLOAD_DIR="/usr/local/bin"
sudo mkdir -p "$DOWNLOAD_DIR"
Optionally install crictl (required for interaction with the Container Runtime Interface (CRI), optional for kubeadm):
CRICTL_VERSION="v1.31.0"
ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
Install kubeadm, kubelet and add a kubelet systemd service:
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
ARCH="amd64"
cd $DOWNLOAD_DIR
sudo curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet}
sudo chmod +x {kubeadm,kubelet}
RELEASE_VERSION="v0.16.2"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
Note:
Please refer to the note in the Before you begin section for Linux distributions that do not includeglibc by default.Install kubectl by following the instructions on Install Tools page.
Optionally, enable the kubelet service before running kubeadm:
sudo systemctl enable --now kubelet
Note:
The Flatcar Container Linux distribution mounts the/usr directory as a read-only filesystem.
Before bootstrapping your cluster, you need to take additional steps to configure a writable directory.
See the Kubeadm Troubleshooting guide
to learn how to set up a writable directory.The kubelet is now restarting every few seconds, as it waits in a crashloop for kubeadm to tell it what to do.
Troubleshooting
If you are running into difficulties with kubeadm, please consult our troubleshooting docs.
What's next
2.2.2.1.2 - Troubleshooting kubeadm
As with any program, you might run into an error installing or running kubeadm. This page lists some common failure scenarios and have provided steps that can help you understand and fix the problem.
If your problem is not listed below, please follow the following steps:
If you think your problem is a bug with kubeadm:
- Go to github.com/kubernetes/kubeadm and search for existing issues.
- If no issue exists, please open one and follow the issue template.
If you are unsure about how kubeadm works, you can ask on Slack in
#kubeadm, or open a question on StackOverflow. Please include relevant tags like#kubernetesand#kubeadmso folks can help you.
Not possible to join a v1.18 Node to a v1.17 cluster due to missing RBAC
In v1.18 kubeadm added prevention for joining a Node in the cluster if a Node with the same name already exists. This required adding RBAC for the bootstrap-token user to be able to GET a Node object.
However this causes an issue where kubeadm join from v1.18 cannot join a cluster created by kubeadm v1.17.
To workaround the issue you have two options:
Execute kubeadm init phase bootstrap-token on a control-plane node using kubeadm v1.18.
Note that this enables the rest of the bootstrap-token permissions as well.
or
Apply the following RBAC manually using kubectl apply -f ...:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeadm:get-nodes
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:get-nodes
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeadm:get-nodes
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:bootstrappers:kubeadm:default-node-token
ebtables or some similar executable not found during installation
If you see the following warnings while running kubeadm init
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
Then you may be missing ebtables, ethtool or a similar executable on your node.
You can install them with the following commands:
- For Ubuntu/Debian users, run
apt install ebtables ethtool. - For CentOS/Fedora users, run
dnf install ebtables ethtool.
kubeadm blocks waiting for control plane during installation
If you notice that kubeadm init hangs after printing out the following line:
[apiclient] Created API client, waiting for the control plane to become ready
This may be caused by a number of problems. The most common are:
- network connection problems. Check that your machine has full network connectivity before continuing.
- control plane containers are crashlooping or hanging. You can check this by running
docker psand investigating each container by runningdocker logs. For other container runtime, see Debugging Kubernetes nodes with crictl.
kubeadm blocks when removing managed containers
The following could happen if the container runtime halts and does not remove any Kubernetes-managed containers:
sudo kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
A possible solution is to restart the container runtime and then re-run kubeadm reset.
You can also use crictl to debug the state of the container runtime. See
Debugging Kubernetes nodes with crictl.
Pods in RunContainerError, CrashLoopBackOff or Error state
Right after kubeadm init there should not be any pods in these states.
- If there are pods in one of these states right after
kubeadm init, please open an issue in the kubeadm repo.coredns(orkube-dns) should be in thePendingstate until you have deployed the network add-on. - If you see Pods in the
RunContainerError,CrashLoopBackOfforErrorstate after deploying the network add-on and nothing happens tocoredns(orkube-dns), it's very likely that the Pod Network add-on that you installed is somehow broken. You might have to grant it more RBAC privileges or use a newer version. Please file an issue in the Pod Network providers' issue tracker and get the issue triaged there.
coredns is stuck in the Pending state
This is expected and part of the design. kubeadm is network provider-agnostic, so the admin
should install the pod network add-on
of choice. You have to install a Pod Network
before CoreDNS may be deployed fully. Hence the Pending state before the network is set up.
HostPort services do not work
The HostPort and HostIP functionality is available depending on your Pod Network
provider. Please contact the author of the Pod Network add-on to find out whether
HostPort and HostIP functionality are available.
Calico, Canal, and Flannel CNI providers are verified to support HostPort.
For more information, see the CNI portmap documentation.
If your network provider does not support the portmap CNI plugin, you may need to use the
NodePort feature of services
or use HostNetwork=true.
Pods are not accessible via their Service IP
Many network add-ons do not yet enable hairpin mode which allows pods to access themselves via their Service IP. This is an issue related to CNI. Please contact the network add-on provider to get the latest status of their support for hairpin mode.
If you are using VirtualBox (directly or via Vagrant), you will need to ensure that
hostname -ireturns a routable IP address. By default, the first interface is connected to a non-routable host-only network. A work around is to modify/etc/hosts, see this Vagrantfile for an example.
TLS certificate errors
The following error indicates a possible certificate mismatch.
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
Verify that the
$HOME/.kube/configfile contains a valid certificate, and regenerate a certificate if necessary. The certificates in a kubeconfig file are base64 encoded. Thebase64 --decodecommand can be used to decode the certificate andopenssl x509 -text -nooutcan be used for viewing the certificate information.Unset the
KUBECONFIGenvironment variable using:unset KUBECONFIGOr set it to the default
KUBECONFIGlocation:export KUBECONFIG=/etc/kubernetes/admin.confAnother workaround is to overwrite the existing
kubeconfigfor the "admin" user:mv $HOME/.kube $HOME/.kube.bak mkdir $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
Kubelet client certificate rotation fails
By default, kubeadm configures a kubelet with automatic rotation of client certificates by using the
/var/lib/kubelet/pki/kubelet-client-current.pem symlink specified in /etc/kubernetes/kubelet.conf.
If this rotation process fails you might see errors such as x509: certificate has expired or is not yet valid
in kube-apiserver logs. To fix the issue you must follow these steps:
Backup and delete
/etc/kubernetes/kubelet.confand/var/lib/kubelet/pki/kubelet-client*from the failed node.From a working control plane node in the cluster that has
/etc/kubernetes/pki/ca.keyexecutekubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf.$NODEmust be set to the name of the existing failed node in the cluster. Modify the resultedkubelet.confmanually to adjust the cluster name and server endpoint, or passkubeconfig user --config(see Generating kubeconfig files for additional users). If your cluster does not have theca.keyyou must sign the embedded certificates in thekubelet.confexternally.Copy this resulted
kubelet.confto/etc/kubernetes/kubelet.confon the failed node.Restart the kubelet (
systemctl restart kubelet) on the failed node and wait for/var/lib/kubelet/pki/kubelet-client-current.pemto be recreated.Manually edit the
kubelet.confto point to the rotated kubelet client certificates, by replacingclient-certificate-dataandclient-key-datawith:client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem client-key: /var/lib/kubelet/pki/kubelet-client-current.pemRestart the kubelet.
Make sure the node becomes
Ready.
Default NIC When using flannel as the pod network in Vagrant
The following error might indicate that something was wrong in the pod network:
Error from server (NotFound): the server could not find the requested resource
If you're using flannel as the pod network inside Vagrant, then you will have to specify the default interface name for flannel.
Vagrant typically assigns two interfaces to all VMs. The first, for which all hosts are assigned the IP address
10.0.2.15, is for external traffic that gets NATed.This may lead to problems with flannel, which defaults to the first interface on a host. This leads to all hosts thinking they have the same public IP address. To prevent this, pass the
--iface eth1flag to flannel so that the second interface is chosen.
Non-public IP used for containers
In some situations kubectl logs and kubectl run commands may return with the
following errors in an otherwise functional cluster:
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
This may be due to Kubernetes using an IP that can not communicate with other IPs on the seemingly same subnet, possibly by policy of the machine provider.
DigitalOcean assigns a public IP to
eth0as well as a private one to be used internally as anchor for their floating IP feature, yetkubeletwill pick the latter as the node'sInternalIPinstead of the public one.Use
ip addr showto check for this scenario instead ofifconfigbecauseifconfigwill not display the offending alias IP address. Alternatively an API endpoint specific to DigitalOcean allows you to query for the anchor IP from the droplet:curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/addressThe workaround is to tell
kubeletwhich IP to use using--node-ip. When using DigitalOcean, it can be the public one (assigned toeth0) or the private one (assigned toeth1) should you want to use the optional private network. ThekubeletExtraArgssection of the kubeadmNodeRegistrationOptionsstructure can be used for this.Then restart
kubelet:systemctl daemon-reload systemctl restart kubelet
coredns pods have CrashLoopBackOff or Error state
If you have nodes that are running SELinux with an older version of Docker, you might experience a scenario
where the coredns pods are not starting. To solve that, you can try one of the following options:
Upgrade to a newer version of Docker.
Modify the
corednsdeployment to setallowPrivilegeEscalationtotrue:
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
Another cause for CoreDNS to have CrashLoopBackOff is when a CoreDNS Pod deployed in Kubernetes detects a loop.
A number of workarounds
are available to avoid Kubernetes trying to restart the CoreDNS Pod every time CoreDNS detects the loop and exits.
Warning:
Disabling SELinux or settingallowPrivilegeEscalation to true can compromise
the security of your cluster.etcd pods restart continually
If you encounter the following error:
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
This issue appears if you run CentOS 7 with Docker 1.13.1.84. This version of Docker can prevent the kubelet from executing into the etcd container.
To work around the issue, choose one of these options:
Roll back to an earlier version of Docker, such as 1.13.1-75
dnf downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64Install one of the more recent recommended versions, such as 18.06:
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf install docker-ce-18.06.1.ce-3.el7.x86_64
Not possible to pass a comma separated list of values to arguments inside a --component-extra-args flag
kubeadm init flags such as --component-extra-args allow you to pass custom arguments to a control-plane
component like the kube-apiserver. However, this mechanism is limited due to the underlying type used for parsing
the values (mapStringString).
If you decide to pass an argument that supports multiple, comma-separated values such as
--apiserver-extra-args "enable-admission-plugins=LimitRanger,NamespaceExists" this flag will fail with
flag: malformed pair, expect string=string. This happens because the list of arguments for
--apiserver-extra-args expects key=value pairs and in this case NamespacesExists is considered
as a key that is missing a value.
Alternatively, you can try separating the key=value pairs like so:
--apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
but this will result in the key enable-admission-plugins only having the value of NamespaceExists.
A known workaround is to use the kubeadm configuration file.
kube-proxy scheduled before node is initialized by cloud-controller-manager
In cloud provider scenarios, kube-proxy can end up being scheduled on new worker nodes before the cloud-controller-manager has initialized the node addresses. This causes kube-proxy to fail to pick up the node's IP address properly and has knock-on effects to the proxy function managing load balancers.
The following error can be seen in kube-proxy Pods:
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
A known solution is to patch the kube-proxy DaemonSet to allow scheduling it on control-plane nodes regardless of their conditions, keeping it off of other nodes until their initial guarding conditions abate:
kubectl -n kube-system patch ds kube-proxy -p='{
"spec": {
"template": {
"spec": {
"tolerations": [
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
}
}
}'
The tracking issue for this problem is here.
/usr is mounted read-only on nodes
On Linux distributions such as Fedora CoreOS or Flatcar Container Linux, the directory /usr is mounted as a read-only filesystem.
For flex-volume support,
Kubernetes components like the kubelet and kube-controller-manager use the default path of
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/, yet the flex-volume directory must be writeable
for the feature to work.
Note:
FlexVolume was deprecated in the Kubernetes v1.23 release.To workaround this issue, you can configure the flex-volume directory using the kubeadm configuration file.
On the primary control-plane Node (created using kubeadm init), pass the following
file using --config:
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
controllerManager:
extraArgs:
- name: "flex-volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
On joining Nodes:
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
- name: "volume-plugin-dir"
value: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
Alternatively, you can modify /etc/fstab to make the /usr mount writeable, but please
be advised that this is modifying a design principle of the Linux distribution.
kubeadm upgrade plan prints out context deadline exceeded error message
This error message is shown when upgrading a Kubernetes cluster with kubeadm in
the case of running an external etcd. This is not a critical bug and happens because
older versions of kubeadm perform a version check on the external etcd cluster.
You can proceed with kubeadm upgrade apply ....
This issue is fixed as of version 1.19.
kubeadm reset unmounts /var/lib/kubelet
If /var/lib/kubelet is being mounted, performing a kubeadm reset will effectively unmount it.
To workaround the issue, re-mount the /var/lib/kubelet directory after performing the kubeadm reset operation.
This is a regression introduced in kubeadm 1.15. The issue is fixed in 1.20.
Cannot use the metrics-server securely in a kubeadm cluster
In a kubeadm cluster, the metrics-server
can be used insecurely by passing the --kubelet-insecure-tls to it. This is not recommended for production clusters.
If you want to use TLS between the metrics-server and the kubelet there is a problem, since kubeadm deploys a self-signed serving certificate for the kubelet. This can cause the following errors on the side of the metrics-server:
x509: certificate signed by unknown authority
x509: certificate is valid for IP-foo not IP-bar
See Enabling signed kubelet serving certificates to understand how to configure the kubelets in a kubeadm cluster to have properly signed serving certificates.
Also see How to run the metrics-server securely.
Upgrade fails due to etcd hash not changing
Only applicable to upgrading a control plane node with a kubeadm binary v1.28.3 or later, where the node is currently managed by kubeadm versions v1.28.0, v1.28.1 or v1.28.2.
Here is the error message you may encounter:
[upgrade/etcd] Failed to upgrade etcd: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced: static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
[upgrade/etcd] Waiting for previous etcd to become available
I0907 10:10:09.109104 3704 etcd.go:588] [etcd] attempting to see if all cluster endpoints ([https://172.17.0.6:2379/ https://172.17.0.4:2379/ https://172.17.0.3:2379/]) are available 1/10
[upgrade/etcd] Etcd was rolled back and is now available
static Pod hash for component etcd on Node kinder-upgrade-control-plane-1 did not change after 5m0s: timed out waiting for the condition
couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.rollbackOldManifests
cmd/kubeadm/app/phases/upgrade/staticpods.go:525
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.upgradeComponent
cmd/kubeadm/app/phases/upgrade/staticpods.go:254
k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade.performEtcdStaticPodUpgrade
cmd/kubeadm/app/phases/upgrade/staticpods.go:338
...
The reason for this failure is that the affected versions generate an etcd manifest file with unwanted defaults in the PodSpec. This will result in a diff from the manifest comparison, and kubeadm will expect a change in the Pod hash, but the kubelet will never update the hash.
There are two way to workaround this issue if you see it in your cluster:
The etcd upgrade can be skipped between the affected versions and v1.28.3 (or later) by using:
kubeadm upgrade {apply|node} [version] --etcd-upgrade=falseThis is not recommended in case a new etcd version was introduced by a later v1.28 patch version.
Before upgrade, patch the manifest for the etcd static pod, to remove the problematic defaulted attributes:
diff --git a/etc/kubernetes/manifests/etcd_defaults.yaml b/etc/kubernetes/manifests/etcd_origin.yaml index d807ccbe0aa..46b35f00e15 100644 --- a/etc/kubernetes/manifests/etcd_defaults.yaml +++ b/etc/kubernetes/manifests/etcd_origin.yaml @@ -43,7 +43,6 @@ spec: scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 - successThreshold: 1 timeoutSeconds: 15 name: etcd resources: @@ -59,26 +58,18 @@ spec: scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 - successThreshold: 1 timeoutSeconds: 15 - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs - dnsPolicy: ClusterFirst - enableServiceLinks: true hostNetwork: true priority: 2000001000 priorityClassName: system-node-critical - restartPolicy: Always - schedulerName: default-scheduler securityContext: seccompProfile: type: RuntimeDefault - terminationGracePeriodSeconds: 30 volumes: - hostPath: path: /etc/kubernetes/pki/etcd
More information can be found in the tracking issue for this bug.
2.2.2.1.3 - Creating a cluster with kubeadm
Using kubeadm, you can create a minimum viable Kubernetes cluster that conforms to best practices.
In fact, you can use kubeadm to set up a cluster that will pass the
Kubernetes Conformance tests.
kubeadm also supports other cluster lifecycle functions, such as
bootstrap tokens and cluster upgrades.
The kubeadm tool is good if you need:
- A simple way for you to try out Kubernetes, possibly for the first time.
- A way for existing users to automate setting up a cluster and test their application.
- A building block in other ecosystem and/or installer tools with a larger scope.
You can install and use kubeadm on various machines: your laptop, a set
of cloud servers, a Raspberry Pi, and more. Whether you're deploying into the
cloud or on-premises, you can integrate kubeadm into provisioning systems such
as Ansible or Terraform.
Before you begin
To follow this guide, you need:
- One or more machines running a deb/rpm-compatible Linux OS; for example: Ubuntu or CentOS.
- 2 GiB or more of RAM per machine--any less leaves little room for your apps.
- At least 2 CPUs on the machine that you use as a control-plane node.
- Full network connectivity among all machines in the cluster. You can use either a public or a private network.
You also need to use a version of kubeadm that can deploy the version
of Kubernetes that you want to use in your new cluster.
Kubernetes' version and version skew support policy
applies to kubeadm as well as to Kubernetes overall.
Check that policy to learn about what versions of Kubernetes and kubeadm
are supported. This page is written for Kubernetes v1.37.
The kubeadm tool's overall feature state is General Availability (GA). Some sub-features are
still under active development. The implementation of creating the cluster may change
slightly as the tool evolves, but the overall implementation should be pretty stable.
Note:
Any commands underkubeadm alpha are, by definition, supported on an alpha level.Objectives
- Install a single control-plane Kubernetes cluster
- Install a Pod network on the cluster so that your Pods can talk to each other
Instructions
Preparing the hosts
Component installation
Install a container runtime and kubeadm on all the hosts. For detailed instructions and other prerequisites, see Installing kubeadm.
Note:
If you have already installed kubeadm, see the first two steps of the Upgrading Linux nodes document for instructions on how to upgrade kubeadm.
When you upgrade, the kubelet restarts every few seconds as it waits in a crashloop for kubeadm to tell it what to do. This crashloop is expected and normal. After you initialize your control-plane, the kubelet runs normally.
Network setup
kubeadm similarly to other Kubernetes components tries to find a usable IP on the network interfaces associated with a default gateway on a host. Such an IP is then used for the advertising and/or listening performed by a component.
To find out what this IP is on a Linux host you can use:
ip route show # Look for a line starting with "default via"
Note:
If two or more default gateways are present on the host, a Kubernetes component will try to use the first one it encounters that has a suitable global unicast IP address. While making this choice, the exact ordering of gateways might vary between different operating systems and kernel versions.Kubernetes components do not accept custom network interface as an option, therefore a custom IP address must be passed as a flag to all components instances that need such a custom configuration.
Note:
If the host does not have a default gateway and if a custom IP address is not passed to a Kubernetes component, the component may exit with an error.To configure the API server advertise address for control plane nodes created with both
init and join, the flag --apiserver-advertise-address can be used.
Preferably, this option can be set in the kubeadm API
as InitConfiguration.localAPIEndpoint and JoinConfiguration.controlPlane.localAPIEndpoint.
For kubelets on all nodes, the --node-ip option can be passed in
.nodeRegistration.kubeletExtraArgs inside a kubeadm configuration file
(InitConfiguration or JoinConfiguration).
For dual-stack see Dual-stack support with kubeadm.
The IP addresses that you assign to control plane components become part of their X.509 certificates' subject alternative name fields. Changing these IP addresses would require signing new certificates and restarting the affected components, so that the change in certificate files is reflected. See Manual certificate renewal for more details on this topic.
Warning:
The Kubernetes project recommends against this approach (configuring all component instances with custom IP addresses). Instead, the Kubernetes maintainers recommend to setup the host network, so that the default gateway IP is the one that Kubernetes components auto-detect and use. On Linux nodes, you can use commands such asip route to configure networking; your operating
system might also provide higher level network management tools. If your node's default gateway
is a public IP address, you should configure packet filtering or other security measures that
protect the nodes and your cluster.Preparing the required container images
This step is optional and only applies in case you wish kubeadm init and kubeadm join
to not download the default container images which are hosted at registry.k8s.io.
Kubeadm has commands that can help you pre-pull the required images when creating a cluster without an internet connection on its nodes. See Running kubeadm without an internet connection for more details.
Kubeadm allows you to use a custom image repository for the required images. See Using custom images for more details.
Initializing your control-plane node
The control-plane node is the machine where the control plane components run, including etcd (the cluster database) and the API Server (which the kubectl command line tool communicates with).
- (Recommended) If you have plans to upgrade this single control-plane
kubeadmcluster to high availability you should specify the--control-plane-endpointto set the shared endpoint for all control-plane nodes. Such an endpoint can be either a DNS name or an IP address of a load-balancer. - Choose a Pod network add-on, and verify whether it requires any arguments to
be passed to
kubeadm init. Depending on which third-party provider you choose, you might need to set the--pod-network-cidrto a provider-specific value. See Installing a Pod network add-on. - (Optional)
kubeadmtries to detect the container runtime by using a list of well known endpoints. To use different container runtime or if there are more than one installed on the provisioned node, specify the--cri-socketargument tokubeadm. See Installing a runtime.
To initialize the control-plane node run:
kubeadm init <args>
Considerations about apiserver-advertise-address and ControlPlaneEndpoint
While --apiserver-advertise-address can be used to set the advertised address for this particular
control-plane node's API server, --control-plane-endpoint can be used to set the shared endpoint
for all control-plane nodes.
--control-plane-endpoint allows both IP addresses and DNS names that can map to IP addresses.
Please contact your network administrator to evaluate possible solutions with respect to such mapping.
Here is an example mapping:
192.168.0.102 cluster-endpoint
Where 192.168.0.102 is the IP address of this node and cluster-endpoint is a custom DNS name that maps to this IP.
This will allow you to pass --control-plane-endpoint=cluster-endpoint to kubeadm init and pass the same DNS name to
kubeadm join. Later you can modify cluster-endpoint to point to the address of your load-balancer in a
high availability scenario.
Turning a single control plane cluster created without --control-plane-endpoint into a highly available cluster
is not supported by kubeadm.
More information
For more information about kubeadm init arguments, see the kubeadm reference guide.
To configure kubeadm init with a configuration file see
Using kubeadm init with a configuration file.
To customize control plane components, including optional IPv6 assignment to liveness probe for control plane components and etcd server, provide extra arguments to each component as documented in custom arguments.
To reconfigure a cluster that has already been created see Reconfiguring a kubeadm cluster.
To run kubeadm init again, you must first tear down the cluster.
If you join a node with a different architecture to your cluster, make sure that your deployed DaemonSets have container image support for this architecture.
kubeadm init first runs a series of prechecks to ensure that the machine
is ready to run Kubernetes. These prechecks expose warnings and exit on errors. kubeadm init
then downloads and installs the cluster control plane components. This may take several minutes.
After it finishes you should see:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
To make kubectl work for your non-root user, run these commands, which are
also part of the kubeadm init output:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
Warning:
The kubeconfig file admin.conf that kubeadm init generates contains a certificate with
Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin. The group kubeadm:cluster-admins
is bound to the built-in cluster-admin ClusterRole.
Do not share the admin.conf file with anyone.
kubeadm init generates another kubeconfig file super-admin.conf that contains a certificate with
Subject: O = system:masters, CN = kubernetes-super-admin.
system:masters is a break-glass, super user group that bypasses the authorization layer (for example RBAC).
Do not share the super-admin.conf file with anyone. It is recommended to move the file to a safe location.
See
Generating kubeconfig files for additional users
on how to use kubeadm kubeconfig user to generate kubeconfig files for additional users.
Make a record of the kubeadm join command that kubeadm init outputs. You
need this command to join nodes to your cluster.
The token is used for mutual authentication between the control-plane node and the joining
nodes. The token included here is secret. Keep it safe, because anyone with this
token can add authenticated nodes to your cluster. These tokens can be listed,
created, and deleted with the kubeadm token command. See the
kubeadm reference guide.
Installing a Pod network add-on
Caution:
This section contains important information about networking setup and deployment order. Read all of this advice carefully before proceeding.
You must deploy a Container Network Interface (CNI) based Pod network add-on so that your Pods can communicate with each other. Cluster DNS (CoreDNS) will not start up before a network is installed.
Take care that your Pod network must not overlap with any of the host networks: you are likely to see problems if there is any overlap. (If you find a collision between your network plugin's preferred Pod network and some of your host networks, you should think of a suitable CIDR block to use instead, then use that during
kubeadm initwith--pod-network-cidrand as a replacement in your network plugin's YAML).By default,
kubeadmsets up your cluster to use and enforce use of RBAC (role based access control). Make sure that your Pod network plugin supports RBAC, and so do any manifests that you use to deploy it.If you want to use IPv6--either dual-stack, or single-stack IPv6 only networking--for your cluster, make sure that your Pod network plugin supports IPv6. IPv6 support was added to CNI in v0.6.0.
Note:
Kubeadm should be CNI agnostic and the validation of CNI providers is out of the scope of our current e2e testing. If you find an issue related to a CNI plugin you should log a ticket in its respective issue tracker instead of the kubeadm or kubernetes issue trackers.Several external projects provide Kubernetes Pod networks using CNI, some of which also support Network Policy.
See a list of add-ons that implement the Kubernetes networking model.
Please refer to the Installing Addons page for a non-exhaustive list of networking addons supported by Kubernetes. You can install a Pod network add-on with the following command on the control-plane node or a node that has the kubeconfig credentials:
kubectl apply -f <add-on.yaml>
Note:
Only a few CNI plugins support Windows. More details and setup instructions can be found in Adding Windows worker nodes.You can install only one Pod network per cluster.
Once a Pod network has been installed, you can confirm that it is working by
checking that the CoreDNS Pod is Running in the output of kubectl get pods --all-namespaces.
And once the CoreDNS Pod is up and running, you can continue by joining your nodes.
If your network is not working or CoreDNS is not in the Running state, check out the
troubleshooting guide
for kubeadm.
Managed node labels
By default, kubeadm enables the NodeRestriction
admission controller that restricts what labels can be self-applied by kubelets on node registration.
The admission controller documentation covers what labels are permitted to be used with the kubelet
--node-labels option.
Caution:
Because of the NodeRestriction admission controller, you cannot use the kubelet
--node-labels flag to apply restricted labels (such as node-role.kubernetes.io/*) during initialization.
If you attempt to add restricted labels by using this kubelet flag, the node will fail to register with the API server.
To apply these labels manually, you must use kubectl label after the node has joined the cluster.
Ensure you are using a privileged kubeconfig, such as the kubeadm-managed /etc/kubernetes/admin.conf.
Control plane node isolation
By default, your cluster will not schedule Pods on the control plane nodes for security reasons. If you want to be able to schedule Pods on the control plane nodes, for example for a single machine Kubernetes cluster, run:
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
The output will look something like:
node "test-01" untainted
...
This will remove the node-role.kubernetes.io/control-plane:NoSchedule taint
from any nodes that have it, including the control plane nodes, meaning that the
scheduler will then be able to schedule Pods everywhere.
Additionally, you can execute the following command to remove the
node.kubernetes.io/exclude-from-external-load-balancers label
from the control plane node, which excludes it from the list of backend servers:
kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers-
Adding more control plane nodes
See Creating Highly Available Clusters with kubeadm for steps on creating a high availability kubeadm cluster by adding more control plane nodes.
Adding worker nodes
The worker nodes are where your workloads run.
The following pages show how to add Linux and Windows worker nodes to the cluster by using
the kubeadm join command:
(Optional) Controlling your cluster from machines other than the control-plane node
In order to get a kubectl on some other computer (e.g. laptop) to talk to your cluster, you need to copy the administrator kubeconfig file from your control-plane node to your workstation like this:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes
Note:
The example above assumes SSH access is enabled for root. If that is not the
case, you can copy the admin.conf file to be accessible by some other user
and scp using that other user instead.
The admin.conf file gives the user superuser privileges over the cluster.
This file should be used sparingly. For normal users, it's recommended to
generate a unique credential to which you grant privileges. You can do
this with the kubeadm kubeconfig user --client-name <CN>
command. That command will print out a KubeConfig file to STDOUT which you
should save to a file and distribute to your user. After that, grant
privileges by using kubectl create (cluster)rolebinding.
(Optional) Proxying API Server to localhost
If you want to connect to the API Server from outside the cluster, you can use
kubectl proxy:
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy
You can now access the API Server locally at http://localhost:8001/api/v1
Clean up
If you used disposable servers for your cluster, for testing, you can
switch those off and do no further clean up. You can use
kubectl config delete-cluster to delete your local references to the
cluster.
However, if you want to deprovision your cluster more cleanly, you should first drain the node and make sure that the node is empty, then deconfigure the node.
Remove the node
Talking to the control-plane node with the appropriate credentials, run:
kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets
Before removing the node, reset the state installed by kubeadm:
kubeadm reset
The reset process does not reset or clean up iptables rules or IPVS tables. If you wish to reset iptables, you must do so manually:
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
If you want to reset the IPVS tables, you must run the following command:
ipvsadm -C
Now remove the node:
kubectl delete node <node name>
If you wish to start over, run kubeadm init or kubeadm join with the
appropriate arguments.
Clean up the control plane
You can use kubeadm reset on the control plane host to trigger a best-effort
clean up.
See the kubeadm reset
reference documentation for more information about this subcommand and its
options.
Version skew policy
While kubeadm allows version skew against some components that it manages, it is recommended that you match the kubeadm version with the versions of the control plane components, kube-proxy and kubelet.
kubeadm's skew against the Kubernetes version
kubeadm can be used with Kubernetes components that are the same version as kubeadm
or one version older. The Kubernetes version can be specified to kubeadm by using the
--kubernetes-version flag of kubeadm init or the
ClusterConfiguration.kubernetesVersion
field when using --config. This option will control the versions
of kube-apiserver, kube-controller-manager, kube-scheduler and kube-proxy.
Example:
- kubeadm is at 1.37
kubernetesVersionmust be at 1.37 or 1.36
kubeadm's skew against the kubelet
Similarly to the Kubernetes version, kubeadm can be used with a kubelet version that is the same version as kubeadm or three versions older.
Example:
- kubeadm is at 1.37
- kubelet on the host must be at 1.37, 1.36, 1.35 or 1.34
kubeadm's skew against kubeadm
There are certain limitations on how kubeadm commands can operate on existing nodes or whole clusters managed by kubeadm.
If new nodes are joined to the cluster, the kubeadm binary used for kubeadm join must match
the last version of kubeadm used to either create the cluster with kubeadm init or to upgrade
the same node with kubeadm upgrade. Similar rules apply to the rest of the kubeadm commands
with the exception of kubeadm upgrade.
Example for kubeadm join:
- kubeadm version 1.37 was used to create a cluster with
kubeadm init - Joining nodes must use a kubeadm binary that is at version 1.37
Nodes that are being upgraded must use a version of kubeadm that is the same MINOR version or one MINOR version newer than the version of kubeadm used for managing the node.
Example for kubeadm upgrade:
- kubeadm version 1.36 was used to create or upgrade the node
- The version of kubeadm used for upgrading the node must be at 1.36 or 1.37
To learn more about the version skew between the different Kubernetes component see the Version Skew Policy.
Limitations
Cluster resilience
The cluster created here has a single control-plane node, with a single etcd database running on it. This means that if the control-plane node fails, your cluster may lose data and may need to be recreated from scratch.
Workarounds:
Regularly back up etcd. The etcd data directory configured by kubeadm is at
/var/lib/etcdon the control-plane node.Use multiple control-plane nodes. You can read Options for Highly Available topology to pick a cluster topology that provides high-availability.
Platform compatibility
kubeadm deb/rpm packages and binaries are built for amd64, arm (32-bit), arm64, ppc64le, and s390x following the multi-platform proposal.
Multiplatform container images for the control plane and addons are also supported since v1.12.
Only some of the network providers offer solutions for all platforms. Please consult the list of network providers above or the documentation from each provider to figure out whether the provider supports your chosen platform.
Troubleshooting
If you are running into difficulties with kubeadm, please consult our troubleshooting docs.
What's next
- Verify that your cluster is running properly with Sonobuoy
- See Upgrading kubeadm clusters
for details about upgrading your cluster using
kubeadm. - Learn about advanced
kubeadmusage in the kubeadm reference documentation - Learn more about Kubernetes concepts and
kubectl. - See the Cluster Networking page for a bigger list of Pod network add-ons.
- See the list of add-ons to explore other add-ons, including tools for logging, monitoring, network policy, visualization & control of your Kubernetes cluster.
- Configure how your cluster handles logs for cluster events and from applications running in Pods. See Logging Architecture for an overview of what is involved.
Feedback
- For bugs, visit the kubeadm GitHub issue tracker
- For support, visit the #kubeadm Slack channel
- General SIG Cluster Lifecycle development Slack channel: #sig-cluster-lifecycle
- SIG Cluster Lifecycle SIG information
- SIG Cluster Lifecycle mailing list: kubernetes-sig-cluster-lifecycle
2.2.2.1.4 - Customizing components with the kubeadm API
This page covers how to customize the components that kubeadm deploys. For control plane components
you can use flags in the ClusterConfiguration structure or patches per-node. For the kubelet
and kube-proxy you can use KubeletConfiguration and KubeProxyConfiguration, accordingly.
All of these options are possible via the kubeadm configuration API. For more details on each field in the configuration you can navigate to our API reference pages.
Note:
To reconfigure a cluster that has already been created see Reconfiguring a kubeadm cluster.Customizing the control plane with flags in ClusterConfiguration
The kubeadm ClusterConfiguration object exposes a way for users to override the default
flags passed to control plane components such as the APIServer, ControllerManager, Scheduler and Etcd.
The components are defined using the following structures:
apiServercontrollerManagerscheduleretcd
These structures contain a common extraArgs field, that consists of name / value pairs.
To override a flag for a control plane component:
- Add the appropriate
extraArgsto your configuration. - Add flags to the
extraArgsfield. - Run
kubeadm initwith--config <YOUR CONFIG YAML>.
Note:
You can generate aClusterConfiguration object with default values by running kubeadm config print init-defaults
and saving the output to a file of your choice.Note:
TheClusterConfiguration object is currently global in kubeadm clusters. This means that any flags that you add,
will apply to all instances of the same component on different nodes. To apply individual configuration per component
on different nodes you can use patches.Note:
Duplicate flags (keys), or passing the same flag--foo multiple times, is currently not supported.
To workaround that you must use patches.APIServer flags
For details, see the reference documentation for kube-apiserver.
Example usage:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
apiServer:
extraArgs:
- name: "enable-admission-plugins"
value: "AlwaysPullImages,DefaultStorageClass"
- name: "audit-log-path"
value: "/home/johndoe/audit.log"
ControllerManager flags
For details, see the reference documentation for kube-controller-manager.
Example usage:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
controllerManager:
extraArgs:
- name: "cluster-signing-key-file"
value: "/home/johndoe/keys/ca.key"
- name: "deployment-controller-sync-period"
value: "50"
Scheduler flags
For details, see the reference documentation for kube-scheduler.
Example usage:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
scheduler:
extraArgs:
- name: "config"
value: "/etc/kubernetes/scheduler-config.yaml"
extraVolumes:
- name: schedulerconfig
hostPath: /home/johndoe/schedconfig.yaml
mountPath: /etc/kubernetes/scheduler-config.yaml
readOnly: true
pathType: "File"
Etcd flags
For details, see the etcd server documentation.
Example usage:
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
etcd:
local:
extraArgs:
- name: "election-timeout"
value: 1000
Customizing with patches
Kubeadm allows you to pass a directory with patch files to InitConfiguration,
JoinConfiguration and UpgradeConfiguration.
on individual nodes. These patches can be used as the last customization step before component configuration
is written to disk.
You can pass this file to kubeadm init with --config <YOUR CONFIG YAML>:
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
patches:
directory: /home/user/somedir
Note:
Forkubeadm init you can pass a file containing both a ClusterConfiguration and InitConfiguration
separated by ---.You can pass this file to kubeadm join with --config <YOUR CONFIG YAML>:
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
patches:
directory: /home/user/somedir
If you are using kubeadm upgrade apply and kubeadm upgrade node to upgrade your kubeadm
nodes, you must again provide the same patches, so that the customization is preserved after upgrade.
apiVersion: kubeadm.k8s.io/v1beta4
kind: UpgradeConfiguration
apply:
patches:
directory: /home/user/somedir
apiVersion: kubeadm.k8s.io/v1beta4
kind: UpgradeConfiguration
node:
patches:
directory: /home/user/somedir
The directory must contain files named target[suffix][+patchtype].extension.
For example, kube-apiserver0+merge.yaml or just etcd.json.
targetcan be one ofkube-apiserver,kube-controller-manager,kube-scheduler,etcd,kubeletconfigurationandcorednsdeployment.suffixis an optional string that can be used to determine which patches are applied first alpha-numerically.patchtypecan be one ofstrategic,mergeorjsonand these must match the patching formats supported by kubectl. The defaultpatchtypeisstrategic.extensionmust be eitherjsonoryaml.
Customizing the kubelet
To customize the kubelet you can add a KubeletConfiguration
next to the ClusterConfiguration or InitConfiguration separated by --- within the same configuration file.
This file can then be passed to kubeadm init and kubeadm will apply the same base KubeletConfiguration
to all nodes in the cluster.
For applying instance-specific configuration over the base KubeletConfiguration you can use the
kubeletconfiguration patch target.
Alternatively, you can use kubelet flags as overrides by passing them in the
nodeRegistration.kubeletExtraArgs field supported by both InitConfiguration and JoinConfiguration.
Some kubelet flags are deprecated, so check their status in the
kubelet reference documentation before using them.
For additional details see Configuring each kubelet in your cluster using kubeadm
Customizing kube-proxy
To customize kube-proxy you can pass a KubeProxyConfiguration next your ClusterConfiguration or
InitConfiguration to kubeadm init separated by ---.
For more details you can navigate to our API reference pages.
Note:
kubeadm deploys kube-proxy as a DaemonSet, which means that theKubeProxyConfiguration would apply to all instances of kube-proxy in the cluster.Customizing CoreDNS
kubeadm allows you to customize the CoreDNS Deployment with patches against the
corednsdeployment patch target.
Patches for other CoreDNS related API objects like the kube-system/coredns
ConfigMap are currently not supported.
You must manually patch any of these objects using kubectl and recreate the CoreDNS
Pods after that.
Alternatively, you can disable the kubeadm CoreDNS deployment by including the following
option in your ClusterConfiguration:
dns:
disabled: true
Also, by executing the following command:
kubeadm init phase addon coredns --print-manifest --config my-config.yaml`
you can obtain the manifest file kubeadm would create for CoreDNS on your setup.
2.2.2.1.5 - Options for Highly Available Topology
This page explains the two options for configuring the topology of your highly available (HA) Kubernetes clusters.
You can set up an HA cluster:
- With stacked control plane nodes, where etcd nodes are colocated with control plane nodes
- With external etcd nodes, where etcd runs on separate nodes from the control plane
You should carefully consider the advantages and disadvantages of each topology before setting up an HA cluster.
Note:
kubeadm bootstraps the etcd cluster statically. Read the etcd Clustering Guide for more details.Stacked etcd topology
A stacked HA cluster is a topology where the distributed data storage cluster provided by etcd is stacked on top of the cluster formed by the nodes managed by kubeadm that run control plane components.
Each control plane node runs an instance of the kube-apiserver, kube-scheduler, and kube-controller-manager.
The kube-apiserver is exposed to worker nodes using a load balancer.
Each control plane node creates a local etcd member and this etcd member communicates only with
the kube-apiserver of this node. The same applies to the local kube-controller-manager
and kube-scheduler instances.
This topology couples the control planes and etcd members on the same nodes. It is simpler to set up than a cluster with external etcd nodes, and simpler to manage for replication.
However, a stacked cluster runs the risk of failed coupling. If one node goes down, both an etcd member and a control plane instance are lost, and redundancy is compromised. You can mitigate this risk by adding more control plane nodes.
You should therefore run a minimum of three stacked control plane nodes for an HA cluster.
This is the default topology in kubeadm. A local etcd member is created automatically
on control plane nodes when using kubeadm init and kubeadm join --control-plane.
External etcd topology
An HA cluster with external etcd is a topology where the distributed data storage cluster provided by etcd is external to the cluster formed by the nodes that run control plane components.
Like the stacked etcd topology, each control plane node in an external etcd topology runs
an instance of the kube-apiserver, kube-scheduler, and kube-controller-manager.
And the kube-apiserver is exposed to worker nodes using a load balancer. However,
etcd members run on separate hosts, and each etcd host communicates with the
kube-apiserver of each control plane node.
This topology decouples the control plane and etcd member. It therefore provides an HA setup where losing a control plane instance or an etcd member has less impact and does not affect the cluster redundancy as much as the stacked HA topology.
However, this topology requires twice the number of hosts as the stacked HA topology. A minimum of three hosts for control plane nodes and three hosts for etcd nodes are required for an HA cluster with this topology.
What's next
2.2.2.1.6 - Creating Highly Available Clusters with kubeadm
This page explains two different approaches to setting up a highly available Kubernetes cluster using kubeadm:
- With stacked control plane nodes. This approach requires less infrastructure. The etcd members and control plane nodes are co-located.
- With an external etcd cluster. This approach requires more infrastructure. The control plane nodes and etcd members are separated.
Before proceeding, you should carefully consider which approach best meets the needs of your applications and environment. Options for Highly Available topology outlines the advantages and disadvantages of each.
If you encounter issues with setting up the HA cluster, please report these in the kubeadm issue tracker.
See also the upgrade documentation.
Caution:
This page does not address running your cluster on a cloud provider. In a cloud environment, neither approach documented here works with Service objects of type LoadBalancer, or with dynamic PersistentVolumes.Before you begin
The prerequisites depend on which topology you have selected for your cluster's control plane:
You need:
- Three or more machines that meet kubeadm's minimum requirements for
the control-plane nodes. Having an odd number of control plane nodes can help
with leader selection in the case of machine or zone failure.
- including a container runtime, already set up and working
- Three or more machines that meet kubeadm's minimum
requirements for the workers
- including a container runtime, already set up and working
- Full network connectivity between all machines in the cluster (public or private network)
- Superuser privileges on all machines using
sudo- You can use a different tool; this guide uses
sudoin the examples.
- You can use a different tool; this guide uses
- SSH access from one device to all nodes in the system
kubeadmandkubeletalready installed on all machines.
See Stacked etcd topology for context.
You need:
- Three or more machines that meet kubeadm's minimum requirements for
the control-plane nodes. Having an odd number of control plane nodes can help
with leader selection in the case of machine or zone failure.
- including a container runtime, already set up and working
- Three or more machines that meet kubeadm's minimum
requirements for the workers
- including a container runtime, already set up and working
- Full network connectivity between all machines in the cluster (public or private network)
- Superuser privileges on all machines using
sudo- You can use a different tool; this guide uses
sudoin the examples.
- You can use a different tool; this guide uses
- SSH access from one device to all nodes in the system
kubeadmandkubeletalready installed on all machines.
And you also need:
- Three or more additional machines, that will become etcd cluster members.
Having an odd number of members in the etcd cluster is a requirement for achieving
optimal voting quorum.
- These machines again need to have
kubeadmandkubeletinstalled. - These machines also require a container runtime, that is already set up and working.
- These machines again need to have
See External etcd topology for context.
Container images
Each host should have access read and fetch images from the Kubernetes container image registry,
registry.k8s.io. If you want to deploy a highly-available cluster where the hosts do not have
access to pull images, this is possible. You must ensure by some other means that the correct
container images are already available on the relevant hosts.
Command line interface
To manage Kubernetes once your cluster is set up, you should
install kubectl on your PC. It is also useful
to install the kubectl tool on each control plane node, as this can be
helpful for troubleshooting.
First steps for both methods
Create load balancer for kube-apiserver
Note:
There are many configurations for load balancers. The following example is only one option. Your cluster requirements may need a different configuration.Create a kube-apiserver load balancer with a name that resolves to DNS.
In a cloud environment you should place your control plane nodes behind a TCP forwarding load balancer. This load balancer distributes traffic to all healthy control plane nodes in its target list. The health check for an apiserver is a TCP check on the port the kube-apiserver listens on (default value
:6443).It is not recommended to use an IP address directly in a cloud environment.
The load balancer must be able to communicate with all control plane nodes on the apiserver port. It must also allow incoming traffic on its listening port.
Make sure the address of the load balancer always matches the address of kubeadm's
ControlPlaneEndpoint.Read the Options for Software Load Balancing guide for more details.
Add the first control plane node to the load balancer, and test the connection:
nc -zv -w 2 <LOAD_BALANCER_IP> <PORT>A connection refused error is expected because the API server is not yet running. A timeout, however, means the load balancer cannot communicate with the control plane node. If a timeout occurs, reconfigure the load balancer to communicate with the control plane node.
Add the remaining control plane nodes to the load balancer target group.
Stacked control plane and etcd nodes
Steps for the first control plane node
Initialize the control plane:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certsYou can use the
--kubernetes-versionflag to set the Kubernetes version to use. It is recommended that the versions of kubeadm, kubelet, kubectl and Kubernetes match.The
--control-plane-endpointflag should be set to the address or DNS and port of the load balancer.The
--upload-certsflag is used to upload the certificates that should be shared across all the control-plane instances to the cluster. If instead, you prefer to copy certs across control-plane nodes manually or using automation tools, please remove this flag and refer to Manual certificate distribution section below.
Note:
Thekubeadm initflags--configand--certificate-keycannot be mixed, therefore if you want to use the kubeadm configuration you must add thecertificateKeyfield in the appropriate config locations (underInitConfigurationandJoinConfiguration: controlPlane).Note:
Some CNI network plugins require additional configuration, for example specifying the pod IP CIDR, while others do not. See the CNI network documentation. To add a pod CIDR pass the flag--pod-network-cidr, or if you are using a kubeadm configuration file set thepodSubnetfield under thenetworkingobject ofClusterConfiguration.The output looks similar to:
... You can now join any number of control-plane node by running the following command on each as a root: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 Please note that the certificate-key gives access to cluster sensitive data, keep it secret! As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward. Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866Copy this output to a text file. You will need it later to join control plane and worker nodes to the cluster.
When
--upload-certsis used withkubeadm init, the certificates of the primary control plane are encrypted and uploaded in thekubeadm-certsSecret.To re-upload the certificates and generate a new decryption key, use the following command on a control plane node that is already joined to the cluster:
sudo kubeadm init phase upload-certs --upload-certsYou can also specify a custom
--certificate-keyduringinitthat can later be used byjoin. To generate such a key you can use the following command:kubeadm certs certificate-key
The certificate key is a hex encoded string that is an AES key of size 32 bytes.
Note:
Thekubeadm-certsSecret and the decryption key expire after two hours.Caution:
As stated in the command output, the certificate key gives access to cluster sensitive data, keep it secret!Apply the CNI plugin of your choice: Follow these instructions to install the CNI provider. Make sure the configuration corresponds to the Pod CIDR specified in the kubeadm configuration file (if applicable).
Note:
You must pick a network plugin that suits your use case and deploy it before you move on to next step. If you don't do this, you will not be able to launch your cluster properly.Type the following and watch the pods of the control plane components get started:
kubectl get pod -n kube-system -w
Steps for the rest of the control plane nodes
For each additional control plane node you should:
Execute the join command that was previously given to you by the
kubeadm initoutput on the first node. It should look something like this:sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07- The
--control-planeflag tellskubeadm jointo create a new control plane. - The
--certificate-key ...will cause the control plane certificates to be downloaded from thekubeadm-certsSecret in the cluster and be decrypted using the given key.
- The
Note:
As the cluster nodes are usually initialized sequentially, the CoreDNS Pods are likely to all run on the first control plane node. To provide higher availability, please rebalance the CoreDNS Pods withkubectl -n kube-system rollout restart deployment coredns after at least one new node is joined.External etcd nodes
Setting up a cluster with external etcd nodes is similar to the procedure used for stacked etcd with the exception that you should setup etcd first, and you should pass the etcd information in the kubeadm config file.
Set up the etcd cluster
Follow these instructions to set up the etcd cluster.
Set up SSH as described here.
Copy the following files from any etcd node in the cluster to the first control plane node:
export CONTROL_PLANE="ubuntu@10.0.0.7" scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}": scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":- Replace the value of
CONTROL_PLANEwith theuser@hostof the first control-plane node.
- Replace the value of
Set up the first control plane node
Create a file called
kubeadm-config.yamlwith the following contents:--- apiVersion: kubeadm.k8s.io/v1beta4 kind: ClusterConfiguration kubernetesVersion: stable controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" # change this (see below) etcd: external: endpoints: - https://ETCD_0_IP:2379 # change ETCD_0_IP appropriately - https://ETCD_1_IP:2379 # change ETCD_1_IP appropriately - https://ETCD_2_IP:2379 # change ETCD_2_IP appropriately caFile: /etc/kubernetes/pki/etcd/ca.crt certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt keyFile: /etc/kubernetes/pki/apiserver-etcd-client.keyNote:
The difference between stacked etcd and external etcd here is that the external etcd setup requires a configuration file with the etcd endpoints under theexternalobject foretcd. In the case of the stacked etcd topology, this is managed automatically.Replace the following variables in the config template with the appropriate values for your cluster:
LOAD_BALANCER_DNSLOAD_BALANCER_PORTETCD_0_IPETCD_1_IPETCD_2_IP
The following steps are similar to the stacked etcd setup:
Run
sudo kubeadm init --config kubeadm-config.yaml --upload-certson this node.Write the output join commands that are returned to a text file for later use.
Apply the CNI plugin of your choice.
Note:
You must pick a network plugin that suits your use case and deploy it before you move on to next step. If you don't do this, you will not be able to launch your cluster properly.
Steps for the rest of the control plane nodes
The steps are the same as for the stacked etcd setup:
- Make sure the first control plane node is fully initialized.
- Join each control plane node with the join command you saved to a text file. It's recommended to join the control plane nodes one at a time.
- Don't forget that the decryption key from
--certificate-keyexpires after two hours, by default.
Common tasks after bootstrapping control plane
Install workers
Worker nodes can be joined to the cluster with the command you stored previously
as the output from the kubeadm init command:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
Manual certificate distribution
If you choose to not use kubeadm init with the --upload-certs flag this means that
you are going to have to manually copy the certificates from the primary control plane node to the
joining control plane nodes.
There are many ways to do this. The following example uses ssh and scp:
SSH is required if you want to control all nodes from a single machine.
Enable ssh-agent on your main device that has access to all other nodes in the system:
eval $(ssh-agent)Add your SSH identity to the session:
ssh-add ~/.ssh/path_to_private_keySSH between nodes to check that the connection is working correctly.
When you SSH to any node, add the
-Aflag. This flag allows the node that you have logged into via SSH to access the SSH agent on your PC. Consider alternative methods if you do not fully trust the security of your user session on the node.ssh -A 10.0.0.7When using sudo on any node, make sure to preserve the environment so SSH forwarding works:
sudo -E -s
After configuring SSH on all the nodes you should run the following script on the first control plane node after running
kubeadm init. This script will copy the certificates from the first control plane node to the other control plane nodes:In the following example, replace
CONTROL_PLANE_IPSwith the IP addresses of the other control plane nodes.USER=ubuntu # customizable CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8" for host in ${CONTROL_PLANE_IPS}; do scp /etc/kubernetes/pki/ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/ca.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.key "${USER}"@$host: scp /etc/kubernetes/pki/sa.pub "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host: scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host: scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt # Skip the next line if you are using external etcd scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key doneCaution:
Copy only the certificates in the above list. kubeadm will take care of generating the rest of the certificates with the required SANs for the joining control-plane instances. If you copy all the certificates by mistake, the creation of additional nodes could fail due to a lack of required SANs.Then on each joining control plane node you have to run the following script before running
kubeadm join. This script will move the previously copied certificates from the home directory to/etc/kubernetes/pki:USER=ubuntu # customizable mkdir -p /etc/kubernetes/pki/etcd mv /home/${USER}/ca.crt /etc/kubernetes/pki/ mv /home/${USER}/ca.key /etc/kubernetes/pki/ mv /home/${USER}/sa.pub /etc/kubernetes/pki/ mv /home/${USER}/sa.key /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/ mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/ mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt # Skip the next line if you are using external etcd mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
2.2.2.1.7 - Set up a High Availability etcd Cluster with kubeadm
By default, kubeadm runs a local etcd instance on each control plane node. It is also possible to treat the etcd cluster as external and provision etcd instances on separate hosts. The differences between the two approaches are covered in the Options for Highly Available topology page.
This task walks through the process of creating a high availability external etcd cluster of three members that can be used by kubeadm during cluster creation.
Before you begin
- Three hosts that can talk to each other over TCP ports 2379 and 2380. This document assumes these default ports. However, they are configurable through the kubeadm config file.
- Each host must have systemd and a bash compatible shell installed.
- Each host must have a container runtime, kubelet, and kubeadm installed.
- Each host should have access to the Kubernetes container image registry (
registry.k8s.io) or list/pull the required etcd image usingkubeadm config images list/pull. This guide will set up etcd instances as static pods managed by a kubelet. - Some infrastructure to copy files between hosts. For example
sshandscpcan satisfy this requirement.
Setting up the cluster
The general approach is to generate all certs on one node and only distribute the necessary files to the other nodes.
Note:
kubeadm contains all the necessary cryptographic machinery to generate the certificates described below; no other cryptographic tooling is required for this example.Note:
The examples below use IPv4 addresses but you can also configure kubeadm, the kubelet and etcd to use IPv6 addresses. Dual-stack is supported by some Kubernetes options, but not by etcd. For more details on Kubernetes dual-stack support see Dual-stack support with kubeadm.Configure the kubelet to be a service manager for etcd.
Since etcd was created first, you must override the service priority by creating a new unit file that has higher precedence than the kubeadm-provided kubelet unit file.Note:
You must do this on every host where etcd should be running.cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf # Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs". # Replace the value of "containerRuntimeEndpoint" for a different container runtime if needed. # apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration authentication: anonymous: enabled: false webhook: enabled: false authorization: mode: AlwaysAllow cgroupDriver: systemd address: 127.0.0.1 containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock staticPodPath: /etc/kubernetes/manifests EOF cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf [Service] ExecStart= ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf Restart=always EOF systemctl daemon-reload systemctl restart kubeletCheck the kubelet status to ensure it is running.
systemctl status kubeletCreate configuration files for kubeadm.
Generate one kubeadm configuration file for each host that will have an etcd member running on it using the following script.
# Update HOST0, HOST1 and HOST2 with the IPs of your hosts export HOST0=10.0.0.6 export HOST1=10.0.0.7 export HOST2=10.0.0.8 # Update NAME0, NAME1 and NAME2 with the hostnames of your hosts export NAME0="infra0" export NAME1="infra1" export NAME2="infra2" # Create temp directories to store files that will end up on other hosts mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/ HOSTS=(${HOST0} ${HOST1} ${HOST2}) NAMES=(${NAME0} ${NAME1} ${NAME2}) for i in "${!HOSTS[@]}"; do HOST=${HOSTS[$i]} NAME=${NAMES[$i]} cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml --- apiVersion: "kubeadm.k8s.io/v1beta4" kind: InitConfiguration nodeRegistration: name: ${NAME} localAPIEndpoint: advertiseAddress: ${HOST} --- apiVersion: "kubeadm.k8s.io/v1beta4" kind: ClusterConfiguration etcd: local: serverCertSANs: - "${HOST}" peerCertSANs: - "${HOST}" extraArgs: - name: initial-cluster value: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380 - name: initial-cluster-state value: new - name: name value: ${NAME} - name: listen-peer-urls value: https://${HOST}:2380 - name: listen-client-urls value: https://${HOST}:2379 - name: advertise-client-urls value: https://${HOST}:2379 - name: initial-advertise-peer-urls value: https://${HOST}:2380 EOF doneGenerate the certificate authority.
If you already have a CA then the only action that is copying the CA's
crtandkeyfile to/etc/kubernetes/pki/etcd/ca.crtand/etc/kubernetes/pki/etcd/ca.key. After those files have been copied, proceed to the next step, "Create certificates for each member".If you do not already have a CA then run this command on
$HOST0(where you generated the configuration files for kubeadm).kubeadm init phase certs etcd-caThis creates two files:
/etc/kubernetes/pki/etcd/ca.crt/etc/kubernetes/pki/etcd/ca.key
Create certificates for each member.
kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml cp -R /etc/kubernetes/pki /tmp/${HOST2}/ # cleanup non-reusable certificates find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml cp -R /etc/kubernetes/pki /tmp/${HOST1}/ find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml # No need to move the certs because they are for HOST0 # clean up certs that should not be copied off this host find /tmp/${HOST2} -name ca.key -type f -delete find /tmp/${HOST1} -name ca.key -type f -deleteCopy certificates and kubeadm configs.
The certificates have been generated and now they must be moved to their respective hosts.
USER=ubuntu HOST=${HOST1} scp -r /tmp/${HOST}/* ${USER}@${HOST}: ssh ${USER}@${HOST} USER@HOST $ sudo -Es root@HOST $ chown -R root:root pki root@HOST $ mv pki /etc/kubernetes/Ensure all expected files exist.
The complete list of required files on
$HOST0is:/tmp/${HOST0} └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── ca.key ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.keyOn
$HOST1:$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.keyOn
$HOST2:$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.keyCreate the static pod manifests.
Now that the certificates and configs are in place it's time to create the manifests. On each host run the
kubeadmcommand to generate a static manifest for etcd.root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yamlOptional: Check the cluster health.
If
etcdctlisn't available, you can run this tool inside a container image. You would do that directly with your container runtime using a tool such ascrictl runand not through KubernetesETCDCTL_API=3 etcdctl \ --cert /etc/kubernetes/pki/etcd/peer.crt \ --key /etc/kubernetes/pki/etcd/peer.key \ --cacert /etc/kubernetes/pki/etcd/ca.crt \ --endpoints https://${HOST0}:2379 endpoint health ... https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms- Set
${HOST0}to the IP address of the host you are testing.
- Set
What's next
Once you have an etcd cluster with 3 working members, you can continue setting up a highly available control plane using the external etcd method with kubeadm.
2.2.2.1.8 - Configuring each kubelet in your cluster using kubeadm
The lifecycle of the kubeadm CLI tool is decoupled from the kubelet, which is a daemon that runs on each node within the Kubernetes cluster. The kubeadm CLI tool is executed by the user when Kubernetes is initialized or upgraded, whereas the kubelet is always running in the background.
Since the kubelet is a daemon, it needs to be maintained by some kind of an init system or service manager. When the kubelet is installed using DEBs or RPMs, systemd is configured to manage the kubelet. You can use a different service manager instead, but you need to configure it manually.
Some kubelet configuration details need to be the same across all kubelets involved in the cluster, while
other configuration aspects need to be set on a per-kubelet basis to accommodate the different
characteristics of a given machine (such as OS, storage, and networking). You can manage the configuration
of your kubelets manually, but kubeadm now provides a KubeletConfiguration API type for
managing your kubelet configurations centrally.
Kubelet configuration patterns
The following sections describe patterns to kubelet configuration that are simplified by using kubeadm, rather than managing the kubelet configuration for each Node manually.
Propagating cluster-level configuration to each kubelet
You can provide the kubelet with default values to be used by kubeadm init and kubeadm join
commands. Interesting examples include using a different container runtime or setting the default subnet
used by services.
If you want your services to use the subnet 10.96.0.0/12 as the default for services, you can pass
the --service-cidr parameter to kubeadm:
kubeadm init --service-cidr 10.96.0.0/12
Virtual IPs for services are now allocated from this subnet. You also need to set the DNS address used
by the kubelet, using the --cluster-dns flag. This setting needs to be the same for every kubelet
on every manager and Node in the cluster. The kubelet provides a versioned, structured API object
that can configure most parameters in the kubelet and push out this configuration to each running
kubelet in the cluster. This object is called
KubeletConfiguration.
The KubeletConfiguration allows the user to specify flags such as the cluster DNS IP addresses expressed as
a list of values to a camelCased key, illustrated by the following example:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDNS:
- 10.96.0.10
For more details on the KubeletConfiguration have a look at this section.
Providing instance-specific configuration details
Some hosts require specific kubelet configurations due to differences in hardware, operating system, networking, or other host-specific parameters. The following list provides a few examples.
The path to the DNS resolution file, as specified by the
--resolv-confkubelet configuration flag, may differ among operating systems, or depending on whether you are usingsystemd-resolved. If this path is wrong, DNS resolution will fail on the Node whose kubelet is configured incorrectly.The Node API object
.metadata.nameis set to the machine's hostname by default, unless you are using a cloud provider. You can use the--hostname-overrideflag to override the default behavior if you need to specify a Node name different from the machine's hostname.Currently, the kubelet cannot automatically detect the cgroup driver used by the container runtime, but the value of
--cgroup-drivermust match the cgroup driver used by the container runtime to ensure the health of the kubelet.To specify the container runtime you must set its endpoint with the
--container-runtime-endpoint=<path>flag.
The recommended way of applying such instance-specific configuration is by using
KubeletConfiguration patches.
Configure kubelets using kubeadm
It is possible to configure the kubelet that kubeadm will start if a custom
KubeletConfiguration
API object is passed with a configuration file like so kubeadm ... --config some-config-file.yaml.
By calling kubeadm config print init-defaults --component-configs KubeletConfiguration you can
see all the default values for this structure.
It is also possible to apply instance-specific patches over the base KubeletConfiguration.
Have a look at Customizing the kubelet
for more details.
Workflow when using kubeadm init
When you call kubeadm init, the kubelet configuration is marshalled to disk
at /var/lib/kubelet/config.yaml, and also uploaded to a kubelet-config
ConfigMap in the kube-system namespace of the cluster.
Additionally, the kubeadm tool detects the CRI socket on the node and writes its details
(including the socket path) into a local configuration, /var/lib/kubelet/instance-config.yaml.
A kubelet configuration file is also written to /etc/kubernetes/kubelet.conf
with the baseline cluster-wide configuration for all kubelets in the cluster. This configuration file
points to the client certificates that allow the kubelet to communicate with the API server. This
addresses the need to
propagate cluster-level configuration to each kubelet.
To address the second pattern of
providing instance-specific configuration details,
kubeadm writes an environment file to /var/lib/kubelet/kubeadm-flags.env, which contains a list of
flags to pass to the kubelet when it starts. The flags are presented in the file like this:
KUBELET_KUBEADM_ARGS="--flag1=value1 --flag2=value2 ..."
In addition to the flags used when starting the kubelet, the file also contains dynamic parameters such as the cgroup driver.
After marshalling these two files to disk, kubeadm attempts to run the following two commands, if you are using systemd:
systemctl daemon-reload && systemctl restart kubelet
If the reload and restart are successful, the normal kubeadm init workflow continues.
Workflow when using kubeadm join
When you run kubeadm join, kubeadm uses the Bootstrap Token credential to perform
a TLS bootstrap, which fetches the credential needed to download the
kubelet-config ConfigMap and writes it to /var/lib/kubelet/config.yaml.
Additionally, the kubeadm tool detects the CRI socket on the node and writes its details
(including the socket path) into a local configuration, /var/lib/kubelet/instance-config.yaml.
The dynamic environment file is generated in exactly the same way as kubeadm init.
Next, kubeadm runs the following two commands to load the new configuration into the kubelet:
systemctl daemon-reload && systemctl restart kubelet
After the kubelet loads the new configuration, kubeadm writes the
/etc/kubernetes/bootstrap-kubelet.conf KubeConfig file, which contains a CA certificate and Bootstrap
Token. These are used by the kubelet to perform the TLS Bootstrap and obtain a unique
credential, which is stored in /etc/kubernetes/kubelet.conf.
When the /etc/kubernetes/kubelet.conf file is written, the kubelet has finished performing the TLS Bootstrap.
Kubeadm deletes the /etc/kubernetes/bootstrap-kubelet.conf file after completing the TLS Bootstrap.
The kubelet drop-in file for systemd
kubeadm ships with configuration for how systemd should run the kubelet.
Note that the kubeadm CLI command never touches this drop-in file.
This configuration file installed by the kubeadm
package is written to
/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf and is used by systemd.
It augments the basic
kubelet.service.
If you want to override that further, you can make a directory /etc/systemd/system/kubelet.service.d/
(not /usr/lib/systemd/system/kubelet.service.d/) and put your own customizations into a file there.
For example, you might add a new local file /etc/systemd/system/kubelet.service.d/local-overrides.conf
to override the unit settings configured by kubeadm.
Here is what you are likely to find in /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf:
Note:
The contents below are just an example. If you don't want to use a package manager follow the guide outlined in the (Without a package manager) section.[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generate at runtime, populating
# the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably,
# the user should use the .NodeRegistration.KubeletExtraArgs object in the configuration files instead.
# KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
This file specifies the default locations for all of the files managed by kubeadm for the kubelet.
- The KubeConfig file to use for the TLS Bootstrap is
/etc/kubernetes/bootstrap-kubelet.conf, but it is only used if/etc/kubernetes/kubelet.confdoes not exist. - The KubeConfig file with the unique kubelet identity is
/etc/kubernetes/kubelet.conf. - The file containing the kubelet's ComponentConfig is
/var/lib/kubelet/config.yaml. - The dynamic environment file that contains
KUBELET_KUBEADM_ARGSis sourced from/var/lib/kubelet/kubeadm-flags.env. - The file that can contain user-specified flag overrides with
KUBELET_EXTRA_ARGSis sourced from/etc/default/kubelet(for DEBs), or/etc/sysconfig/kubelet(for RPMs).KUBELET_EXTRA_ARGSis last in the flag chain and has the highest priority in the event of conflicting settings.
Kubernetes binaries and package contents
The DEB and RPM packages shipped with the Kubernetes releases are:
| Package name | Description |
|---|---|
kubeadm | Installs the /usr/bin/kubeadm CLI tool and the kubelet drop-in file for the kubelet. |
kubelet | Installs the /usr/bin/kubelet binary. |
kubectl | Installs the /usr/bin/kubectl binary. |
cri-tools | Installs the /usr/bin/crictl binary from the cri-tools git repository. |
kubernetes-cni | Installs the /opt/cni/bin binaries from the plugins git repository. |
2.2.2.1.9 - Dual-stack support with kubeadm
Your Kubernetes cluster includes dual-stack networking, which means that cluster networking lets you use either address family. In a cluster, the control plane can assign both an IPv4 address and an IPv6 address to a single Pod or a Service.
Before you begin
You need to have installed the kubeadm tool, following the steps from Installing kubeadm.
For each server that you want to use as a node, make sure it allows IPv6 forwarding.
Enable IPv6 packet forwarding
To check if IPv6 packet forwarding is enabled:
sysctl net.ipv6.conf.all.forwarding
If the output is net.ipv6.conf.all.forwarding = 1 it is already enabled.
Otherwise it is not enabled yet.
To manually enable IPv6 packet forwarding:
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee -a /etc/sysctl.d/k8s.conf
net.ipv6.conf.all.forwarding = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
You need to have an IPv4 and IPv6 address range to use. Cluster operators typically
use private address ranges for IPv4. For IPv6, a cluster operator typically chooses a global
unicast address block from within 2000::/3, using a range that is assigned to the operator.
You don't have to route the cluster's IP address ranges to the public internet.
The size of the IP address allocations should be suitable for the number of Pods and Services that you are planning to run.
Note:
If you are upgrading an existing cluster with thekubeadm upgrade command,
kubeadm does not support making modifications to the pod IP address range
(“cluster CIDR”) nor to the cluster's Service address range (“Service CIDR”).Create a dual-stack cluster
To create a dual-stack cluster with kubeadm init you can pass command line arguments
similar to the following example:
# These address ranges are examples
kubeadm init --pod-network-cidr=10.244.0.0/16,2001:db8:42:0::/56 --service-cidr=10.96.0.0/16,2001:db8:42:1::/112
To make things clearer, here is an example kubeadm
configuration file
kubeadm-config.yaml for the primary dual-stack control plane node.
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
networking:
podSubnet: 10.244.0.0/16,2001:db8:42:0::/56
serviceSubnet: 10.96.0.0/16,2001:db8:42:1::/112
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "10.100.0.1"
bindPort: 6443
nodeRegistration:
kubeletExtraArgs:
- name: "node-ip"
value: "10.100.0.2,fd00:1:2:3::2"
advertiseAddress in InitConfiguration specifies the IP address that the API Server
will advertise it is listening on. The value of advertiseAddress equals the
--apiserver-advertise-address flag of kubeadm init.
Run kubeadm to initiate the dual-stack control plane node:
kubeadm init --config=kubeadm-config.yaml
The kube-controller-manager flags --node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6
are set with default values. See configure IPv4/IPv6 dual stack.
Note:
The--apiserver-advertise-address flag does not support dual-stack.Join a node to dual-stack cluster
Before joining a node, make sure that the node has IPv6 routable network interface and allows IPv6 forwarding.
Here is an example kubeadm configuration file
kubeadm-config.yaml for joining a worker node to the cluster.
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: 10.100.0.1:6443
token: "clvldh.vjjwg16ucnhp94qr"
caCertHashes:
- "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
# change auth info above to match the actual token and CA certificate hash for your cluster
nodeRegistration:
kubeletExtraArgs:
- name: "node-ip"
value: "10.100.0.2,fd00:1:2:3::3"
Also, here is an example kubeadm configuration file
kubeadm-config.yaml for joining another control plane node to the cluster.
apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
controlPlane:
localAPIEndpoint:
advertiseAddress: "10.100.0.2"
bindPort: 6443
discovery:
bootstrapToken:
apiServerEndpoint: 10.100.0.1:6443
token: "clvldh.vjjwg16ucnhp94qr"
caCertHashes:
- "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
# change auth info above to match the actual token and CA certificate hash for your cluster
nodeRegistration:
kubeletExtraArgs:
- name: "node-ip"
value: "10.100.0.2,fd00:1:2:3::4"
advertiseAddress in JoinConfiguration.controlPlane specifies the IP address that the
API Server will advertise it is listening on. The value of advertiseAddress equals
the --apiserver-advertise-address flag of kubeadm join.
kubeadm join --config=kubeadm-config.yaml
Create a single-stack cluster
Note:
Dual-stack support doesn't mean that you need to use dual-stack addressing. You can deploy a single-stack cluster that has the dual-stack networking feature enabled.To make things more clear, here is an example kubeadm
configuration file
kubeadm-config.yaml for the single-stack control plane node.
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
networking:
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/16
What's next
- Validate IPv4/IPv6 dual-stack networking
- Read about Dual-stack cluster networking
- Learn more about the kubeadm configuration format
2.2.3 - Turnkey Cloud Solutions
This page provides a list of Kubernetes certified solution providers. From each provider page, you can learn how to install and setup production ready clusters.
2.3 - Best practices
2.3.1 - Considerations for large clusters
A cluster is a set of nodes (physical or virtual machines) running Kubernetes agents, managed by the control plane. Kubernetes v1.37 supports clusters with up to 5,000 nodes. More specifically, Kubernetes is designed to accommodate configurations that meet all of the following criteria:
- No more than 110 pods per node
- No more than 5,000 nodes
- No more than 150,000 total pods
- No more than 300,000 total containers
You can scale your cluster by adding or removing nodes. The way you do this depends on how your cluster is deployed.
Cloud provider resource quotas
To avoid running into cloud provider quota issues, when creating a cluster with many nodes, consider:
- Requesting a quota increase for cloud resources such as:
- Computer instances
- CPUs
- Storage volumes
- In-use IP addresses
- Packet filtering rule sets
- Number of load balancers
- Network subnets
- Log streams
- Gating the cluster scaling actions to bring up new nodes in batches, with a pause between batches, because some cloud providers rate limit the creation of new instances.
Control plane components
For a large cluster, you need a control plane with sufficient compute and other resources.
Typically you would run one or two control plane instances per failure zone, scaling those instances vertically first and then scaling horizontally after reaching the point of falling returns to (vertical) scale.
You should run at least one instance per failure zone to provide fault-tolerance. Kubernetes nodes do not automatically steer traffic towards control-plane endpoints that are in the same failure zone; however, your cloud provider might have its own mechanisms to do this.
For example, using a managed load balancer, you configure the load balancer to send traffic that originates from the kubelet and Pods in failure zone A, and direct that traffic only to the control plane hosts that are also in zone A. If a single control-plane host or endpoint failure zone A goes offline, that means that all the control-plane traffic for nodes in zone A is now being sent between zones. Running multiple control plane hosts in each zone makes that outcome less likely.
etcd storage
To improve performance of large clusters, you can store Event objects in a separate dedicated etcd instance.
When creating a cluster, you can (using custom tooling):
- start and configure additional etcd instance
- configure the API server to use it for storing events
See Operating etcd clusters for Kubernetes and Set up a High Availability etcd cluster with kubeadm for details on configuring and managing etcd for a large cluster.
Addon resources
Kubernetes resource limits help to minimize the impact of memory leaks and other ways that pods and containers can impact on other components. These resource limits apply to addon resources just as they apply to application workloads.
For example, you can set CPU and memory limits for a logging component:
...
containers:
- name: fluentd-cloud-logging
image: fluent/fluentd-kubernetes-daemonset:v1
resources:
limits:
cpu: 100m
memory: 200Mi
Addons' default limits are typically based on data collected from experience running each addon on small or medium Kubernetes clusters. When running on large clusters, addons often consume more of some resources than their default limits. If a large cluster is deployed without adjusting these values, the addon(s) may continuously get killed because they keep hitting the memory limit. Alternatively, the addon may run but with poor performance due to CPU time slice restrictions.
To avoid running into cluster addon resource issues, when creating a cluster with many nodes, consider the following:
- Some addons scale vertically - there is one replica of the addon for the cluster or serving a whole failure zone. For these addons, increase requests and limits as you scale out your cluster.
- Many addons scale horizontally - you add capacity by running more pods - but with a very large cluster you may also need to raise CPU or memory limits slightly. The Vertical Pod Autoscaler can run in recommender mode to provide suggested figures for requests and limits.
- Some addons run as one copy per node, controlled by a DaemonSet: for example, a node-level log aggregator. Similar to the case with horizontally-scaled addons, you may also need to raise CPU or memory limits slightly.
Prioritizing cluster-essential components
To ensure cluster-essential components (such as CoreDNS, metrics-server, and other critical add-ons) are scheduled ahead of other workloads and are not preempted by lower-priority pods, run them with a system PriorityClass, such as system-cluster-critical or system-node-critical.
What's next
VerticalPodAutoscaleris a custom resource that you can deploy into your cluster to help you manage resource requests and limits for pods.
Learn more about Vertical Pod Autoscaler and how you can use it to scale cluster components, including cluster-critical addons.Read about Node autoscaling
The addon resizer helps you in resizing the addons automatically as your cluster's scale changes.
2.3.2 - Running in multiple zones
This page describes running Kubernetes across multiple zones.
Background
Kubernetes is designed so that a single Kubernetes cluster can run across multiple failure zones, typically where these zones fit within a logical grouping called a region. Major cloud providers define a region as a set of failure zones (also called availability zones) that provide a consistent set of features: within a region, each zone offers the same APIs and services.
Typical cloud architectures aim to minimize the chance that a failure in one zone also impairs services in another zone.
Control plane behavior
All control plane components support running as a pool of interchangeable resources, replicated per component.
When you deploy a cluster control plane, place replicas of control plane components across multiple failure zones. If availability is an important concern, select at least three failure zones and replicate each individual control plane component (API server, scheduler, etcd, cluster controller manager) across at least three failure zones. If you are running a cloud controller manager then you should also replicate this across all the failure zones you selected.
Note:
Kubernetes does not provide cross-zone resilience for the API server endpoints. You can use various techniques to improve availability for the cluster API server, including DNS round-robin, SRV records, or a third-party load balancing solution with health checking.Node behavior
Kubernetes automatically spreads the Pods for workload resources (such as Deployment or StatefulSet) across different nodes in a cluster. This spreading helps reduce the impact of failures.
When nodes start up, the kubelet on each node automatically adds labels to the Node object that represents that specific kubelet in the Kubernetes API. These labels can include zone information.
If your cluster spans multiple zones or regions, you can use node labels in conjunction with Pod topology spread constraints to control how Pods are spread across your cluster among fault domains: regions, zones, and even specific nodes. These hints enable the scheduler to place Pods for better expected availability, reducing the risk that a correlated failure affects your whole workload.
For example, you can set a constraint to make sure that the 3 replicas of a StatefulSet are all running in different zones to each other, whenever that is feasible. You can define this declaratively without explicitly defining which availability zones are in use for each workload.
Distributing nodes across zones
Kubernetes' core does not create nodes for you; you need to do that yourself, or use a tool such as the Cluster API to manage nodes on your behalf.
Using tools such as the Cluster API you can define sets of machines to run as worker nodes for your cluster across multiple failure domains, and rules to automatically heal the cluster in case of whole-zone service disruption.
Manual zone assignment for Pods
You can apply node selector constraints to Pods that you create, as well as to Pod templates in workload resources such as Deployment, StatefulSet, or Job.
Storage access for zones
When persistent volumes are created, Kubernetes automatically adds zone labels
to any PersistentVolumes that are linked to a specific zone.
The scheduler then ensures,
through its NoVolumeZoneConflict predicate, that pods which claim a given PersistentVolume
are only placed into the same zone as that volume.
Please note that the method of adding zone labels can depend on your cloud provider and the storage provisioner you’re using. Always refer to the specific documentation for your environment to ensure correct configuration.
You can specify a StorageClass for PersistentVolumeClaims that specifies the failure domains (zones) that the storage in that class may use. To learn about configuring a StorageClass that is aware of failure domains or zones, see Allowed topologies.
Networking
By itself, Kubernetes does not include zone-aware networking. You can use a
network plugin
to configure cluster networking, and that network solution might have zone-specific
elements. For example, if your cloud provider supports Services with
type=LoadBalancer, the load balancer might only send traffic to Pods running in the
same zone as the load balancer element processing a given connection.
Check your cloud provider's documentation for details.
For custom or on-premises deployments, similar considerations apply. Service and Ingress behavior, including handling of different failure zones, does vary depending on exactly how your cluster is set up.
Fault recovery
When you set up your cluster, you might also need to consider whether and how
your setup can restore service if all the failure zones in a region go
off-line at the same time. For example, do you rely on there being at least
one node able to run Pods in a zone?
Make sure that any cluster-critical repair work does not rely
on there being at least one healthy node in your cluster. For example: if all nodes
are unhealthy, you might need to run a repair Job with a special
toleration so that the repair
can complete enough to bring at least one node into service.
Kubernetes doesn't come with an answer for this challenge; however, it's something to consider.
What's next
To learn how the scheduler places Pods in a cluster, honoring the configured constraints, visit Scheduling and Eviction.
2.3.3 - Validate node setup
Node Conformance Test
Node conformance test is a containerized test framework that provides a system verification and functionality test for a node. The test validates whether the node meets the minimum requirements for Kubernetes; a node that passes the test is qualified to join a Kubernetes cluster.
Node Prerequisite
To run node conformance test, a node must satisfy the same prerequisites as a standard Kubernetes node. At a minimum, the node should have the following daemons installed:
- CRI-compatible container runtimes such as Docker, containerd and CRI-O
- kubelet
Running Node Conformance Test
To run the node conformance test, perform the following steps:
Work out the value of the
--kubeconfigoption for the kubelet; for example:--kubeconfig=/var/lib/kubelet/config.yaml. Because the test framework starts a local control plane to test the kubelet, usehttp://localhost:8080as the URL of the API server. There are some other kubelet command line parameters you may want to use:--cloud-provider: If you are using--cloud-provider=gce, you should remove the flag to run the test.
Run the node conformance test with command:
# $CONFIG_DIR is the pod manifest path of your kubelet. # $LOG_DIR is the test output path. sudo docker run -it --rm --privileged --net=host \ -v /:/rootfs -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \ registry.k8s.io/node-test:0.2
Running Node Conformance Test for Other Architectures
Kubernetes also provides node conformance test docker images for other architectures:
| Arch | Image |
|---|---|
| amd64 | node-test-amd64 |
| arm | node-test-arm |
| arm64 | node-test-arm64 |
Running Selected Test
To run specific tests, overwrite the environment variable FOCUS with the
regular expression of tests you want to run.
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e FOCUS=MirrorPod \ # Only run MirrorPod test
registry.k8s.io/node-test:0.2
To skip specific tests, overwrite the environment variable SKIP with the
regular expression of tests you want to skip.
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e SKIP=MirrorPod \ # Run all conformance tests but skip MirrorPod test
registry.k8s.io/node-test:0.2
Node conformance test is a containerized version of node e2e test. By default, it runs all conformance tests.
Theoretically, you can run any node e2e test if you configure the container and mount required volumes properly. But it is strongly recommended to only run conformance test, because it requires much more complex configuration to run non-conformance test.
Caveats
- The test leaves some docker images on the node, including the node conformance test image and images of containers used in the functionality test.
- The test leaves dead containers on the node. These containers are created during the functionality test.
2.3.4 - Enforcing Pod Security Standards
This page provides an overview of best practices when it comes to enforcing Pod Security Standards.
Using the built-in Pod Security Admission Controller
The Pod Security Admission Controller intends to replace the deprecated PodSecurityPolicies.
Configure all cluster namespaces
Namespaces that lack any configuration at all should be considered significant gaps in your cluster security model. We recommend taking the time to analyze the types of workloads occurring in each namespace, and by referencing the Pod Security Standards, decide on an appropriate level for each of them. Unlabeled namespaces should only indicate that they've yet to be evaluated.
In the scenario that all workloads in all namespaces have the same security requirements, we provide an example that illustrates how the PodSecurity labels can be applied in bulk.
Embrace the principle of least privilege
In an ideal world, every pod in every namespace would meet the requirements of the restricted
policy. However, this is not possible nor practical, as some workloads will require elevated
privileges for legitimate reasons.
- Namespaces allowing
privilegedworkloads should establish and enforce appropriate access controls. - For workloads running in those permissive namespaces, maintain documentation about their unique security requirements. If at all possible, consider how those requirements could be further constrained.
Adopt a multi-mode strategy
The audit and warn modes of the Pod Security Standards admission controller make it easy to
collect important security insights about your pods without breaking existing workloads.
It is good practice to enable these modes for all namespaces, setting them to the desired level
and version you would eventually like to enforce. The warnings and audit annotations generated in
this phase can guide you toward that state. If you expect workload authors to make changes to fit
within the desired level, enable the warn mode. If you expect to use audit logs to monitor/drive
changes to fit within the desired level, enable the audit mode.
When you have the enforce mode set to your desired value, these modes can still be useful in a
few different ways:
- By setting
warnto the same level asenforce, clients will receive warnings when attempting to create Pods (or resources that have Pod templates) that do not pass validation. This will help them update those resources to become compliant. - In Namespaces that pin
enforceto a specific non-latest version, setting theauditandwarnmodes to the same level asenforce, but to thelatestversion, gives visibility into settings that were allowed by previous versions but are not allowed per current best practices.
Third-party alternatives
Other alternatives for enforcing security profiles are being developed in the Kubernetes ecosystem:
The decision to go with a built-in solution (e.g. PodSecurity admission controller) versus a third-party tool is entirely dependent on your own situation. When evaluating any solution, trust of your supply chain is crucial. Ultimately, using any of the aforementioned approaches will be better than doing nothing.
2.3.5 - PKI certificates and requirements
Kubernetes requires PKI certificates for authentication over TLS. If you install Kubernetes with kubeadm, the certificates that your cluster requires are automatically generated. You can also generate your own certificates -- for example, to keep your private keys more secure by not storing them on the API server. This page explains the certificates that your cluster requires.
How certificates are used by your cluster
Kubernetes requires PKI for the following operations:
Server certificates
- Server certificate for the API server endpoint
- Server certificate for the etcd server
- Server certificates for each kubelet (every node runs a kubelet)
- Optional server certificate for the front-proxy
Client certificates
- Client certificates for each kubelet, used to authenticate to the API server as a client of the Kubernetes API
- Client certificate for each API server, used to authenticate to etcd
- Client certificate for the controller manager to securely communicate with the API server
- Client certificate for the scheduler to securely communicate with the API server
- Client certificates, one for each node, for kube-proxy to authenticate to the API server
- Optional client certificates for administrators of the cluster to authenticate to the API server
- Optional client certificate for the front-proxy
Kubelet's server and client certificates
To establish a secure connection and authenticate itself to the kubelet, the API Server requires a client certificate and key pair.
In this scenario, there are two approaches for certificate usage:
Shared Certificates: The kube-apiserver can utilize the same certificate and key pair it uses to authenticate its clients. This means that the existing certificates, such as
apiserver.crtandapiserver.key, can be used for communicating with the kubelet servers.Separate Certificates: Alternatively, the kube-apiserver can generate a new client certificate and key pair to authenticate its communication with the kubelet servers. In this case, a distinct certificate named
kubelet-client.crtand its corresponding private key,kubelet-client.keyare created.
Note:
front-proxy certificates are required only when using the API server aggregation layer
to support an extension API server.etcd also implements mutual TLS to authenticate clients and peers.
Where certificates are stored
If you install Kubernetes with kubeadm, most certificates are stored in /etc/kubernetes/pki.
All paths in this documentation are relative to that directory, with the exception of user account
certificates which kubeadm places in /etc/kubernetes.
Configure certificates manually
If you don't want kubeadm to generate the required certificates, you can create them using a single root CA or by providing all certificates. See Certificates for details on creating your own certificate authority. See Certificate Management with kubeadm for more on managing certificates.
Single root CA
You can create a single root CA, controlled by an administrator. This root CA can then create multiple intermediate CAs, and delegate all further creation to Kubernetes itself.
Required CAs:
| Path | Default CN | Description |
|---|---|---|
| ca.crt,key | kubernetes-ca | Kubernetes general CA |
| etcd/ca.crt,key | etcd-ca | For all etcd-related functions |
| front-proxy-ca.crt,key | kubernetes-front-proxy-ca | For the front-end proxy |
On top of the above CAs, it is also necessary to get a public/private key pair for service account
management, sa.key and sa.pub.
The following example illustrates the CA key and certificate files shown in the previous table:
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
All certificates
If you don't wish to copy the CA private keys to your cluster, you can generate all certificates yourself.
Required certificates:
| Default CN | Parent CA | O (in Subject) | kind | hosts (SAN) |
|---|---|---|---|---|
| kube-etcd | etcd-ca | server, client | <hostname>, <Host_IP>, localhost, 127.0.0.1 | |
| kube-etcd-peer | etcd-ca | server, client | <hostname>, <Host_IP>, localhost, 127.0.0.1 | |
| kube-etcd-healthcheck-client | etcd-ca | client | ||
| kube-apiserver-etcd-client | etcd-ca | client | ||
| kube-apiserver | kubernetes-ca | server | <hostname>, <Host_IP>, <advertise_IP>1 | |
| kube-apiserver-kubelet-client | kubernetes-ca | system:masters | client | |
| front-proxy-client | kubernetes-front-proxy-ca | client |
Note:
Instead of using the super-user groupsystem:masters for kube-apiserver-kubelet-client
a less privileged group can be used. kubeadm uses the kubeadm:cluster-admins group for
that purpose.where kind maps to one or more of the x509 key usage, which is also documented in the
.spec.usages of a CertificateSigningRequest
type:
| kind | Key usage |
|---|---|
| server | digital signature, key encipherment, server auth |
| client | digital signature, key encipherment, client auth |
Note:
Hosts/SAN listed above are the recommended ones for getting a working cluster; if required by a specific setup, it is possible to add additional SANs on all the server certificates.Note:
For kubeadm users only:
- The scenario where you are copying to your cluster CA certificates without private keys is referred as external CA in the kubeadm documentation.
- If you are comparing the above list with a kubeadm generated PKI, please be aware that
kube-etcd,kube-etcd-peerandkube-etcd-healthcheck-clientcertificates are not generated in case of external etcd.
Certificate paths
Certificates should be placed in a recommended path (as used by kubeadm). Paths should be specified using the given argument regardless of location.
| DefaultCN | recommendedkeypath | recommendedcertpath | command | keyargument | certargument |
|---|---|---|---|---|---|
| etcd-ca | etcd/ca.key | etcd/ca.crt | kube-apiserver | --etcd-cafile | |
| kube-apiserver-etcd-client | apiserver-etcd-client.key | apiserver-etcd-client.crt | kube-apiserver | --etcd-keyfile | --etcd-certfile |
| kubernetes-ca | ca.key | ca.crt | kube-apiserver | --client-ca-file | |
| kubernetes-ca | ca.key | ca.crt | kube-controller-manager | --cluster-signing-key-file | --client-ca-file,--root-ca-file,--cluster-signing-cert-file |
| kube-apiserver | apiserver.key | apiserver.crt | kube-apiserver | --tls-private-key-file | --tls-cert-file |
| kube-apiserver-kubelet-client | apiserver-kubelet-client.key | apiserver-kubelet-client.crt | kube-apiserver | --kubelet-client-key | --kubelet-client-certificate |
| front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-apiserver | --requestheader-client-ca-file | |
| front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-controller-manager | --requestheader-client-ca-file | |
| front-proxy-client | front-proxy-client.key | front-proxy-client.crt | kube-apiserver | --proxy-client-key-file | --proxy-client-cert-file |
| etcd-ca | etcd/ca.key | etcd/ca.crt | etcd | --trusted-ca-file,--peer-trusted-ca-file | |
| kube-etcd | etcd/server.key | etcd/server.crt | etcd | --key-file | --cert-file |
| kube-etcd-peer | etcd/peer.key | etcd/peer.crt | etcd | --peer-key-file | --peer-cert-file |
| etcd-ca | etcd/ca.crt | etcdctl | --cacert | ||
| kube-etcd-healthcheck-client | etcd/healthcheck-client.key | etcd/healthcheck-client.crt | etcdctl | --key | --cert |
Same considerations apply for the service account key pair:
| private key path | public key path | command | argument |
|---|---|---|---|
| sa.key | kube-controller-manager | --service-account-private-key-file | |
| sa.pub | kube-apiserver | --service-account-key-file |
The following example illustrates the file paths from the previous tables you need to provide if you are generating all of your own keys and certificates:
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/apiserver-etcd-client.key
/etc/kubernetes/pki/apiserver-etcd-client.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/apiserver.key
/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/apiserver-kubelet-client.key
/etc/kubernetes/pki/apiserver-kubelet-client.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-client.key
/etc/kubernetes/pki/front-proxy-client.crt
/etc/kubernetes/pki/etcd/server.key
/etc/kubernetes/pki/etcd/server.crt
/etc/kubernetes/pki/etcd/peer.key
/etc/kubernetes/pki/etcd/peer.crt
/etc/kubernetes/pki/etcd/healthcheck-client.key
/etc/kubernetes/pki/etcd/healthcheck-client.crt
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
Configure certificates for user accounts
You must manually configure these administrator accounts and service accounts:
| Filename | Credential name | Default CN | O (in Subject) |
|---|---|---|---|
| admin.conf | default-admin | kubernetes-admin | <admin-group> |
| super-admin.conf | default-super-admin | kubernetes-super-admin | system:masters |
| kubelet.conf | default-auth | system:node:<nodeName> (see note) | system:nodes |
| controller-manager.conf | default-controller-manager | system:kube-controller-manager | |
| scheduler.conf | default-scheduler | system:kube-scheduler |
Note:
The value of<nodeName> for kubelet.conf must match precisely the value of the node name
provided by the kubelet as it registers with the apiserver. For further details, read the
Node Authorization.Note:
In the above example <admin-group> is implementation specific. Some tools sign the
certificate in the default admin.conf to be part of the system:masters group.
system:masters is a break-glass, super user group can bypass the authorization
layer of Kubernetes, such as RBAC. Also some tools do not generate a separate
super-admin.conf with a certificate bound to this super user group.
kubeadm generates two separate administrator certificates in kubeconfig files.
One is in admin.conf and has Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin.
kubeadm:cluster-admins is a custom group bound to the cluster-admin ClusterRole.
This file is generated on all kubeadm managed control plane machines.
Another is in super-admin.conf that has Subject: O = system:masters, CN = kubernetes-super-admin.
This file is generated only on the node where kubeadm init was called.
For each configuration, generate an x509 certificate/key pair with the given Common Name (CN) and Organization (O).
Run
kubectlas follows for each configuration:KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name> KUBECONFIG=<filename> kubectl config use-context default-system
These files are used as follows:
| Filename | Command | Comment |
|---|---|---|
| admin.conf | kubectl | Configures administrator user for the cluster |
| super-admin.conf | kubectl | Configures super administrator user for the cluster |
| kubelet.conf | kubelet | One required for each node in the cluster. |
| controller-manager.conf | kube-controller-manager | Must be added to manifest in manifests/kube-controller-manager.yaml |
| scheduler.conf | kube-scheduler | Must be added to manifest in manifests/kube-scheduler.yaml |
The following files illustrate full paths to the files listed in the previous table:
/etc/kubernetes/admin.conf
/etc/kubernetes/super-admin.conf
/etc/kubernetes/kubelet.conf
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf
3 - Concepts
The Concepts section helps you learn about the parts of the Kubernetes system and the abstractions Kubernetes uses to represent your cluster, and helps you obtain a deeper understanding of how Kubernetes works.
3.1 - Overview
This page is an overview of Kubernetes.
The name Kubernetes originates from Greek, meaning helmsman or pilot. K8s as an abbreviation results from counting the eight letters between the "K" and the "s". Google open sourced the Kubernetes project in 2014. Kubernetes combines over 15 years of Google's experience running production workloads at scale with best-of-breed ideas and practices from the community.
Why you need Kubernetes and what it can do
Containers are a good way to bundle and run your applications. In a production environment, you need to manage the containers that run the applications and ensure that there is no downtime. For example, if a container goes down, another container needs to start. Wouldn't it be easier if this behavior was handled by a system?
That's how Kubernetes comes to the rescue! Kubernetes provides you with a framework to run distributed systems resiliently. It takes care of scaling and failover for your application, provides deployment patterns, and more. For example: Kubernetes can easily manage a canary deployment for your system.
Kubernetes provides you with:
- Service discovery and load balancing Kubernetes can expose a container using a DNS name or its own IP address. If traffic to a container is high, Kubernetes is able to load balance and distribute the network traffic so that the deployment is stable.
- Storage orchestration Kubernetes allows you to automatically mount a storage system of your choice, such as local storage, public cloud providers, and more.
- Automated rollouts and rollbacks You can describe the desired state for your deployed containers using Kubernetes, and it can change the actual state to the desired state at a controlled rate. For example, you can automate Kubernetes to create new containers for your deployment, remove existing containers and adopt all their resources to the new container.
- Automatic bin packing You provide Kubernetes with a cluster of nodes that it can use to run containerized tasks. You tell Kubernetes how much CPU and memory (RAM) each container needs. Kubernetes can fit containers onto your nodes to make the best use of your resources.
- Self-healing Kubernetes restarts containers that fail, replaces containers, kills containers that don't respond to your user-defined health check, and doesn't advertise them to clients until they are ready to serve.
- Secret and configuration management Kubernetes lets you store and manage sensitive information, such as passwords, OAuth tokens, and SSH keys. You can deploy and update secrets and application configuration without rebuilding your container images, and without exposing secrets in your stack configuration.
- Batch execution In addition to services, Kubernetes can manage your batch and CI workloads, replacing containers that fail, if desired.
- Horizontal scaling Scale your application up and down with a simple command, with a UI, or automatically based on CPU usage.
- IPv4/IPv6 dual-stack Allocation of IPv4 and IPv6 addresses to Pods and Services.
- Designed for extensibility Add features to your Kubernetes cluster without changing upstream source code.
What Kubernetes is not
Kubernetes is not a traditional, all-inclusive PaaS (Platform as a Service) system. Since Kubernetes operates at the container level rather than at the hardware level, it provides some generally applicable features common to PaaS offerings, such as deployment, scaling, load balancing, and lets users integrate their logging, monitoring, and alerting solutions. However, Kubernetes is not monolithic, and these default solutions are optional and pluggable. Kubernetes provides the building blocks for building developer platforms, but preserves user choice and flexibility where it is important.
Kubernetes:
- Does not limit the types of applications supported. Kubernetes aims to support an extremely diverse variety of workloads, including stateless, stateful, and data-processing workloads. If an application can run in a container, it should run great on Kubernetes.
- Does not deploy source code and does not build your application. Continuous Integration, Delivery, and Deployment (CI/CD) workflows are determined by organization cultures and preferences as well as technical requirements.
- Does not provide application-level services, such as middleware (for example, message buses), data-processing frameworks (for example, Spark), databases (for example, MySQL), caches, nor cluster storage systems (for example, Ceph) as built-in services. Such components can run on Kubernetes, and/or can be accessed by applications running on Kubernetes through portable mechanisms, such as the Open Service Broker.
- Does not dictate logging, monitoring, or alerting solutions. It provides some integrations as proof of concept, and mechanisms to collect and export metrics.
- Does not provide nor mandate a configuration language/system (for example, Jsonnet). It provides a declarative API that may be targeted by arbitrary forms of declarative specifications.
- Does not provide nor adopt any comprehensive machine configuration, maintenance, management, or self-healing systems.
- Additionally, Kubernetes is not a mere orchestration system. In fact, it eliminates the need for orchestration. The technical definition of orchestration is execution of a defined workflow: first do A, then B, then C. In contrast, Kubernetes comprises a set of independent, composable control processes that continuously drive the current state towards the provided desired state. It shouldn't matter how you get from A to C. Centralized control is also not required. This results in a system that is easier to use and more powerful, robust, resilient, and extensible.
Historical context for Kubernetes
Let's take a look at why Kubernetes is so useful by going back in time.
Traditional deployment era:
Early on, organizations ran applications on physical servers. There was no way to define resource boundaries for applications in a physical server, and this caused resource allocation issues. For example, if multiple applications run on a physical server, there can be instances where one application would take up most of the resources, and as a result, the other applications would underperform. A solution for this would be to run each application on a different physical server. But this did not scale as resources were underutilized, and it was expensive for organizations to maintain many physical servers.
Virtualized deployment era:
As a solution, virtualization was introduced. It allows you to run multiple Virtual Machines (VMs) on a single physical server's CPU. Virtualization allows applications to be isolated between VMs and provides a level of security as the information of one application cannot be freely accessed by another application.
Virtualization allows better utilization of resources in a physical server and allows better scalability because an application can be added or updated easily, reduces hardware costs, and much more. With virtualization you can present a set of physical resources as a cluster of disposable virtual machines.
Each VM is a full machine running all the components, including its own operating system, on top of the virtualized hardware.
Container deployment era:
Containers are similar to VMs, but they have relaxed isolation properties to share the Operating System (OS) among the applications. Therefore, containers are considered lightweight. Similar to a VM, a container has its own filesystem, share of CPU, memory, process space, and more. As they are decoupled from the underlying infrastructure, they are portable across clouds and OS distributions.
Containers have become popular because they provide extra benefits, such as:
- Agile application creation and deployment: increased ease and efficiency of container image creation compared to VM image use.
- Continuous development, integration, and deployment: provides reliable and frequent container image build and deployment with quick and efficient rollbacks (due to image immutability).
- Dev and Ops separation of concerns: create application container images at build/release time rather than deployment time, thereby decoupling applications from infrastructure.
- Observability: not only surfaces OS-level information and metrics, but also application health and other signals.
- Environmental consistency across development, testing, and production: runs the same on a laptop as it does in the cloud.
- Cloud and OS distribution portability: runs on Ubuntu, RHEL, CoreOS, on-premises, on major public clouds, and anywhere else.
- Application-centric management: raises the level of abstraction from running an OS on virtual hardware to running an application on an OS using logical resources.
- Loosely coupled, distributed, elastic, liberated micro-services: applications are broken into smaller, independent pieces and can be deployed and managed dynamically – not a monolithic stack running on one big single-purpose machine.
- Resource isolation: predictable application performance.
- Resource utilization: high efficiency and density.
What's next
- Take a look at the Kubernetes Components
- Take a look at the Kubernetes API
- Take a look at kubectl: the primary CLI for Kubernetes
- Take a look at the Cluster Architecture
- Ready to Get Started?
3.1.1 - Kubernetes Components
This page provides a high-level overview of the essential components that make up a Kubernetes cluster.
The components of a Kubernetes cluster
Core Components
A Kubernetes cluster consists of a control plane and one or more worker nodes. Here's a brief overview of the main components:
Control Plane Components
Manage the overall state of the cluster:
- kube-apiserver
- The core component server that exposes the Kubernetes HTTP API.
- etcd
- Consistent and highly-available key value store for all API server data.
- kube-scheduler
- Looks for Pods not yet bound to a node, and assigns each Pod to a suitable node.
- kube-controller-manager
- Runs controllers to implement Kubernetes API behavior.
- cloud-controller-manager (optional)
- Integrates with underlying cloud provider(s).
Node Components
Run on every node, maintaining running pods and providing the Kubernetes runtime environment:
- kubelet
- Ensures that Pods are running, including their containers.
- kube-proxy (optional)
- Maintains network rules on nodes to implement Services.
- Container runtime
- Software responsible for running containers. Read Container Runtimes to learn more.
Your cluster may require additional software on each node; for example, you might also run systemd on a Linux node to supervise local components.
Addons
Addons extend the functionality of Kubernetes. A few important examples include:
- DNS
- For cluster-wide DNS resolution.
- Web UI (Dashboard)
- For cluster management via a web interface.
- Container Resource Monitoring
- For collecting and storing container metrics.
- Cluster-level Logging
- For saving container logs to a central log store.
Flexibility in Architecture
Kubernetes allows for flexibility in how these components are deployed and managed. The architecture can be adapted to various needs, from small development environments to large-scale production deployments.
For more detailed information about each component and various ways to configure your cluster architecture, see the Cluster Architecture page.
3.1.2 - Objects In Kubernetes
This page explains how Kubernetes objects are represented in the Kubernetes API, and how you can
express them in .yaml format.
Understanding Kubernetes objects
Kubernetes objects are persistent entities in the Kubernetes system. Kubernetes uses these entities to represent the state of your cluster. Specifically, they can describe:
- What containerized applications are running (and on which nodes)
- The resources available to those applications
- The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance
A Kubernetes object is a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that the object exists. By creating an object, you're effectively telling the Kubernetes system what you want your cluster's workload to look like; this is your cluster's desired state.
To work with Kubernetes objects—whether to create, modify, or delete them—you'll need to use the
Kubernetes API. When you use the kubectl command-line
interface, for example, the CLI makes the necessary Kubernetes API calls for you. You can also use
the Kubernetes API directly in your own programs using one of the
Client Libraries.
Object spec and status
Almost every Kubernetes object includes two nested object fields that govern
the object's configuration: the object spec and the object status.
For objects that have a spec, you have to set this when you create the object,
providing a description of the characteristics you want the resource to have:
its desired state.
The status describes the current state of the object, supplied and updated
by the Kubernetes system and its components. The Kubernetes
control plane continually
and actively manages every object's actual state to match the desired state you
supplied.
For example: in Kubernetes, a Deployment is an object that can represent an
application running on your cluster. When you create the Deployment, you
might set the Deployment spec to specify that you want three replicas of
the application to be running. The Kubernetes system reads the Deployment
spec and starts three instances of your desired application--updating
the status to match your spec. If any of those instances should fail
(a status change), the Kubernetes system responds to the difference
between spec and status by making a correction--in this case, starting
a replacement instance.
For more information on the object spec, status, and metadata, see the Kubernetes API Conventions.
Describing a Kubernetes object
When you create an object in Kubernetes, you must provide the object spec that describes its
desired state, as well as some basic information about the object (such as a name). When you use
the Kubernetes API to create the object (either directly or via kubectl), that API request must
include that information as JSON in the request body.
Most often, you provide the information to kubectl in a file known as a manifest.
By convention, manifests are YAML (you could also use JSON format).
Tools such as kubectl convert the information from a manifest into JSON or another supported
serialization format when making the API request over HTTP.
Here's an example manifest that shows the required fields and object spec for a Kubernetes Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
One way to create a Deployment using a manifest file like the one above is to use the
kubectl apply command
in the kubectl command-line interface, passing the .yaml file as an argument. Here's an example:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
The output is similar to this:
deployment.apps/nginx-deployment created
Required fields
In the manifest (YAML or JSON file) for the Kubernetes object you want to create, you'll need to set values for the following fields:
apiVersion- Which version of the Kubernetes API you're using to create this objectkind- What kind of object you want to createmetadata- Data that helps uniquely identify the object, including anamestring,UID, and optionalnamespacespec- What state you desire for the object
The precise format of the object spec is different for every Kubernetes object, and contains
nested fields specific to that object. The Kubernetes API Reference
can help you find the spec format for all of the objects you can create using Kubernetes.
For example, see the spec field
for the Pod API reference.
For each Pod, the .spec field specifies the pod and its desired state (such as the container image name for
each container within that pod).
Another example of an object specification is the
spec field
for the StatefulSet API. For StatefulSet, the .spec field specifies the StatefulSet and
its desired state.
Within the .spec of a StatefulSet is a template
for Pod objects. That template describes Pods that the StatefulSet controller will create in order to
satisfy the StatefulSet specification.
Different kinds of objects can also have different .status; again, the API reference pages
detail the structure of that .status field, and its content for each different type of object.
See Kubernetes Configuration Best Practices for additional information on writing YAML configuration files.
Server side field validation
Starting with Kubernetes v1.25, the API server offers server side
field validation
that detects unrecognized or duplicate fields in an object. It provides all the functionality
of kubectl --validate on the server side.
The kubectl tool uses the --validate flag to set the level of field validation. It accepts the
values ignore, warn, and strict while also accepting the values true (equivalent to strict)
and false (equivalent to ignore). The default validation setting for kubectl is --validate=true.
Strict- Strict field validation, errors on validation failure
Warn- Field validation is performed, but errors are exposed as warnings rather than failing the request
Ignore- No server side field validation is performed
When kubectl cannot connect to an API server that supports field validation it will fall back
to using client-side validation. Kubernetes 1.27 and later versions always offer field validation;
older Kubernetes releases might not. If your cluster is older than v1.27, check the documentation
for your version of Kubernetes.
What's next
If you're new to Kubernetes, read more about the following:
- Pods which are the most important basic Kubernetes objects.
- Deployment objects.
- Controllers in Kubernetes.
- kubectl and kubectl commands.
Kubernetes Object Management
explains how to use kubectl to manage objects.
You might need to install kubectl if you don't already have it available.
To learn about the Kubernetes API in general, visit:
To learn about objects in Kubernetes in more depth, read other pages in this section:
3.1.2.1 - Kubernetes Object Management
The kubectl command-line tool supports several different ways to create and manage
Kubernetes objects. This document provides an overview of the different
approaches. Read the Kubectl book for
details of managing objects by Kubectl.
Management techniques
Warning:
A Kubernetes object should be managed using only one technique. Mixing and matching techniques for the same object results in undefined behavior.| Management technique | Operates on | Recommended environment | Supported writers | Learning curve |
|---|---|---|---|---|
| Imperative commands | Live objects | Development projects | 1+ | Lowest |
| Imperative object configuration | Individual files | Production projects | 1 | Moderate |
| Declarative object configuration | Directories of files | Production projects | 1+ | Highest |
Imperative commands
When using imperative commands, a user operates directly on live objects
in a cluster. The user provides operations to
the kubectl command as arguments or flags.
This is the recommended way to get started or to run a one-off task in a cluster. Because this technique operates directly on live objects, it provides no history of previous configurations.
Examples
Run an instance of the nginx container by creating a Deployment object:
kubectl create deployment nginx --image nginx
Trade-offs
Advantages compared to object configuration:
- Commands are expressed as a single action word.
- Commands require only a single step to make changes to the cluster.
Disadvantages compared to object configuration:
- Commands do not integrate with change review processes.
- Commands do not provide an audit trail associated with changes.
- Commands do not provide a source of records except for what is live.
- Commands do not provide a template for creating new objects.
Imperative object configuration
In imperative object configuration, the kubectl command specifies the operation (create, replace, etc.), optional flags and at least one file name. The file specified must contain a full definition of the object in YAML or JSON format.
See the API reference for more details on object definitions.
Warning:
The imperativereplace command replaces the existing
spec with the newly provided one, dropping all changes to the object missing from
the configuration file. This approach should not be used with resource
types whose specs are updated independently of the configuration file.
Services of type LoadBalancer, for example, have their externalIPs field updated
independently from the configuration by the cluster.Examples
Create the objects defined in a configuration file:
kubectl create -f nginx.yaml
Delete the objects defined in two configuration files:
kubectl delete -f nginx.yaml -f redis.yaml
Update the objects defined in a configuration file by overwriting the live configuration:
kubectl replace -f nginx.yaml
Trade-offs
Advantages compared to imperative commands:
- Object configuration can be stored in a source control system such as Git.
- Object configuration can integrate with processes such as reviewing changes before push and audit trails.
- Object configuration provides a template for creating new objects.
Disadvantages compared to imperative commands:
- Object configuration requires basic understanding of the object schema.
- Object configuration requires the additional step of writing a YAML file.
Advantages compared to declarative object configuration:
- Imperative object configuration behavior is simpler and easier to understand.
- As of Kubernetes version 1.5, imperative object configuration is more mature.
Disadvantages compared to declarative object configuration:
- Imperative object configuration works best on files, not directories.
- Updates to live objects must be reflected in configuration files, or they will be lost during the next replacement.
Declarative object configuration
When using declarative object configuration, a user operates on object
configuration files stored locally, however the user does not define the
operations to be taken on the files. Create, update, and delete operations
are automatically detected per-object by kubectl. This enables working on
directories, where different operations might be needed for different objects.
Note:
Declarative object configuration retains changes made by other writers, even if the changes are not merged back to the object configuration file. This is possible by using thepatch API operation to write only
observed differences, instead of using the replace
API operation to replace the entire object configuration.Examples
Process all object configuration files in the configs directory, and create or
patch the live objects. You can first diff to see what changes are going to be
made, and then apply:
kubectl diff -f configs/
kubectl apply -f configs/
Recursively process directories:
kubectl diff -R -f configs/
kubectl apply -R -f configs/
Trade-offs
Advantages compared to imperative object configuration:
- Changes made directly to live objects are retained, even if they are not merged back into the configuration files.
- Declarative object configuration has better support for operating on directories and automatically detecting operation types (create, patch, delete) per-object.
Disadvantages compared to imperative object configuration:
- Declarative object configuration is harder to debug and understand results when they are unexpected.
- Partial updates using diffs create complex merge and patch operations.
What's next
- Managing Kubernetes Objects Using Imperative Commands
- Imperative Management of Kubernetes Objects Using Configuration Files
- Declarative Management of Kubernetes Objects Using Configuration Files
- Declarative Management of Kubernetes Objects Using Kustomize
- Kubectl Command Reference
- Kubectl Book
- Kubernetes API Reference
3.1.2.2 - Object Names and IDs
Each object in your cluster has a Name that is unique for that type of resource. Every Kubernetes object also has a UID that is unique across your whole cluster.
For example, you can only have one Pod named myapp-1234 within the same namespace, but you can have one Pod and one Deployment that are each named myapp-1234.
For non-unique user-provided attributes, Kubernetes provides labels and annotations.
Names
A client-provided string that refers to an object in a resource
URL, such as /api/v1/pods/some-name.
Only one object of a given kind can have a given name at a time. However, if you delete the object, you can make a new object with the same name.
Names must be unique across all API versions of the same resource.
Kubernetes uniquely identifies objects using a combination of four attributes:
- API group (e.g.,
apps) - Resource type (e.g.,
deployments) - Namespace (for namespaced resources)
- Name
While you can access a resource through different API versions (such as v1 or v1beta1), the version is simply a different representation of the same underlying object. Because the version is not part of the unique identification, you cannot create two objects with the same name and resource type in the same namespace by using different API versions.
Note:
In cases when objects represent a physical entity, like a Node representing a physical host, when the host is re-created under the same name without deleting and re-creating the Node, Kubernetes treats the new host as the old one, which may lead to inconsistencies.The server may generate a name when generateName is provided instead of name in a resource create request.
When generateName is used, the provided value is used as a name prefix, which server appends a generated suffix
to. Even though the name is generated, it may conflict with existing names resulting in an HTTP 409 response. This
became far less likely to happen in Kubernetes v1.31 and later, since the server will make up to 8 attempts to generate a
unique name before returning an HTTP 409 response.
Below are four types of commonly used name constraints for resources.
DNS Subdomain Names
Most resource types require a name that can be used as a DNS subdomain name as defined in RFC 1123. This means the name must:
- contain no more than 253 characters
- contain only lowercase alphanumeric characters, '-' or '.'
- start with an alphanumeric character
- end with an alphanumeric character
RFC 1123 Label Names
Some resource types require their names to follow the DNS label standard as defined in RFC 1123. This means the name must:
- contain at most 63 characters
- contain only lowercase alphanumeric characters or '-'
- start with an alphabetic character
- end with an alphanumeric character
Note:
When theRelaxedServiceNameValidation feature gate is enabled,
Service object names are allowed to start with a digit.RFC 1035 Label Names
Some resource types require their names to follow the DNS label standard as defined in RFC 1035. This means the name must:
- contain at most 63 characters
- contain only lowercase alphanumeric characters or '-'
- start with an alphabetic character
- end with an alphanumeric character
Note:
While RFC 1123 technically allows labels to start with digits, the current Kubernetes implementation requires both RFC 1035 and RFC 1123 labels to start with an alphabetic character. The exception is when theRelaxedServiceNameValidation
feature gate is enabled for Service objects, which allows Service names to start with digits.Path Segment Names
Some resource types require their names to be able to be safely encoded as a path segment. In other words, the name may not be "." or ".." and the name may not contain "/" or "%".
Here's an example manifest for a Pod named nginx-demo.
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Note:
Some resource types have additional restrictions on their names.UIDs
A Kubernetes systems-generated string to uniquely identify objects.
Every object created over the whole lifetime of a Kubernetes cluster has a distinct UID. It is intended to distinguish between historical occurrences of similar entities.
Kubernetes UIDs are universally unique identifiers (also known as UUIDs). UUIDs are standardized as ISO/IEC 9834-8 and as ITU-T X.667.
What's next
- Read about labels and annotations in Kubernetes.
- See the Identifiers and Names in Kubernetes design document.
3.1.2.3 - Labels and Selectors
Labels are key/value pairs that are attached to objects such as Pods. Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but do not directly imply semantics to the core system. Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time. Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
Labels allow for efficient queries and watches and are ideal for use in UIs and CLIs. Non-identifying information should be recorded using annotations.
Motivation
Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store these mappings.
Service deployments and batch processing pipelines are often multi-dimensional entities (e.g., multiple partitions or deployments, multiple release tracks, multiple tiers, multiple micro-services per tier). Management often requires cross-cutting operations, which breaks encapsulation of strictly hierarchical representations, especially rigid hierarchies determined by the infrastructure rather than by users.
Example labels:
"release" : "stable","release" : "canary""environment" : "dev","environment" : "qa","environment" : "production""tier" : "frontend","tier" : "backend","tier" : "cache""partition" : "customerA","partition" : "customerB""track" : "daily","track" : "weekly"
These are examples of commonly used labels; you are free to develop your own conventions. Keep in mind that label Key must be unique for a given object.
Syntax and character set
Labels are key/value pairs. Valid label keys have two segments: an optional
prefix and name, separated by a slash (/). The name segment is required and
must be 63 characters or less, beginning and ending with an alphanumeric
character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.),
and alphanumerics between. The prefix is optional. If specified, the prefix
must be a DNS subdomain: a series of DNS labels separated by dots (.),
not longer than 253 characters in total, followed by a slash (/).
If the prefix is omitted, the label Key is presumed to be private to the user.
Automated system components (e.g. kube-scheduler, kube-controller-manager,
kube-apiserver, kubectl, or other third-party automation) which add labels
to end-user objects must specify a prefix.
The kubernetes.io/ and k8s.io/ prefixes are
reserved for Kubernetes core components.
Valid label value:
- must be 63 characters or less (can be empty),
- unless empty, must begin and end with an alphanumeric character (
[a-z0-9A-Z]), - could contain dashes (
-), underscores (_), dots (.), and alphanumerics between.
For example, here's a manifest for a Pod that has two labels
environment: production and app: nginx:
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Label selectors
Unlike names and UIDs, labels do not provide uniqueness. In general, we expect many objects to carry the same label(s).
Via a label selector, the client/user can identify a set of objects. The label selector is the core grouping primitive in Kubernetes.
The API currently supports two types of selectors: equality-based and set-based.
A label selector can be made of multiple requirements which are comma-separated.
In the case of multiple requirements, all must be satisfied so the comma separator
acts as a logical AND (&&) operator.
The semantics of empty or non-specified selectors are dependent on the context, and API types that use selectors should document the validity and meaning of them.
Note:
For some API types, such as ReplicaSets, the label selectors of two instances must not overlap within a namespace, or the controller can see that as conflicting instructions and fail to determine how many replicas should be present.Caution:
For both equality-based and set-based conditions there is no logical OR (||) operator.
Ensure your filter statements are structured accordingly.Equality-based requirement
Equality- or inequality-based requirements allow filtering by label keys and values.
Matching objects must satisfy all of the specified label constraints, though they may
have additional labels as well. Three kinds of operators are admitted =,==,!=.
The first two represent equality (and are synonyms), while the latter represents inequality.
For example:
environment = production
tier != frontend
The former selects all resources with key equal to environment and value equal to production.
The latter selects all resources with key equal to tier and value distinct from frontend,
and all resources with no labels with the tier key. One could filter for resources in production
excluding frontend using the comma operator: environment=production,tier!=frontend
One usage scenario for equality-based label requirement is for Pods to specify
node selection criteria. For example, the sample Pod below selects nodes where
the accelerator label exists and is set to nvidia-tesla-p100.
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "registry.k8s.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
nodeSelector:
accelerator: nvidia-tesla-p100
Set-based requirement
Set-based label requirements allow filtering keys according to a set of values.
Three kinds of operators are supported: in,notin and exists (only the key identifier).
For example:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
- The first example selects all resources with key equal to
environmentand value equal toproductionorqa. - The second example selects all resources with key equal to
tierand values other thanfrontendandbackend, and all resources with no labels with thetierkey. - The third example selects all resources including a label with key
partition; no values are checked. - The fourth example selects all resources without a label with key
partition; no values are checked.
Similarly the comma separator acts as an AND operator. So filtering resources
with a partition key (no matter the value) and with environment different
than qa can be achieved using partition,environment notin (qa).
The set-based label selector is a general form of equality since
environment=production is equivalent to environment in (production);
similarly for != and notin.
Set-based requirements can be mixed with equality-based requirements.
For example: partition in (customerA, customerB),environment!=qa.
API
LIST and WATCH filtering
For list and watch operations, you can specify label selectors to filter the sets of objects returned; you specify the filter using a query parameter. (To learn in detail about watches in Kubernetes, read efficient detection of changes). Both requirements are permitted (presented here as they would appear in a URL query string):
- equality-based requirements:
?labelSelector=environment%3Dproduction,tier%3Dfrontend - set-based requirements:
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
Both label selector styles can be used to list or watch resources via a REST client.
For example, targeting apiserver with kubectl and using equality-based one may write:
kubectl get pods -l environment=production,tier=frontend
or using set-based requirements:
kubectl get pods -l 'environment in (production),tier in (frontend)'
As already mentioned set-based requirements are more expressive. For instance, they can implement the OR operator on values:
kubectl get pods -l 'environment in (production, qa)'
or restricting negative matching via notin operator:
kubectl get pods -l 'environment,environment notin (frontend)'
Set references in API objects
Some Kubernetes objects, such as services
and replicationcontrollers,
also use label selectors to specify sets of other resources, such as
pods.
Service and ReplicationController
The set of pods that a service targets is defined with a label selector.
Similarly, the population of pods that a replicationcontroller should
manage is also defined with a label selector.
Label selectors for both objects are defined in json or yaml files using maps,
and only equality-based requirement selectors are supported:
"selector": {
"component" : "redis",
}
or
selector:
component: redis
This selector (respectively in json or yaml format) is equivalent to
component=redis or component in (redis).
Resources that support set-based requirements
Newer resources, such as Job,
Deployment,
ReplicaSet, and
DaemonSet,
support set-based requirements as well.
selector:
matchLabels:
component: redis
matchExpressions:
- { key: tier, operator: In, values: [cache] }
- { key: environment, operator: NotIn, values: [dev] }
matchLabels is a map of {key,value} pairs. A single {key,value} in the
matchLabels map is equivalent to an element of matchExpressions, whose key
field is "key", the operator is "In", and the values array contains only "value".
matchExpressions is a list of pod selector requirements. Valid operators include
In, NotIn, Exists, and DoesNotExist. The values set must be non-empty in the case of
In and NotIn. All of the requirements, from both matchLabels and matchExpressions
are ANDed together -- they must all be satisfied in order to match.
Selecting sets of nodes
One use case for selecting over labels is to constrain the set of nodes onto which a pod can schedule. See the documentation on node selection for more information.
Using labels effectively
You can apply a single label to any resources, but this is not always the best practice. There are many scenarios where multiple labels should be used to distinguish resource sets from one another.
For instance, different applications would use different values for the app label, but a
multi-tier application, such as the guestbook example,
would additionally need to distinguish each tier.
In the following examples, the app label is included for convenience in manual queries
and simple CLI usage. The app.kubernetes.io/name label follows the recommended Kubernetes
labeling conventions and is better suited for tooling and automation.
The frontend could carry the following labels:
labels:
app: guestbook
app.kubernetes.io/name: guestbook
tier: frontend
while the Redis master and replica would have different tier labels, and perhaps even an
additional role label:
labels:
app: guestbook
app.kubernetes.io/name: guestbook
tier: backend
role: master
and
labels:
app: guestbook
app.kubernetes.io/name: guestbook
tier: backend
role: replica
The labels allow for slicing and dicing the resources along any dimension specified by a label:
kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <none>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-replica-2q2yf 1/1 Running 0 1m guestbook backend replica
guestbook-redis-replica-qgazl 1/1 Running 0 1m guestbook backend replica
my-nginx-divi2 1/1 Running 0 29m nginx <none> <none>
my-nginx-o0ef1 1/1 Running 0 29m nginx <none> <none>
kubectl get pods -lapp=guestbook,role=replica
NAME READY STATUS RESTARTS AGE
guestbook-redis-replica-2q2yf 1/1 Running 0 3m
guestbook-redis-replica-qgazl 1/1 Running 0 3m
Updating labels
Sometimes you may want to relabel existing pods and other resources before creating
new resources. This can be done with kubectl label.
For example, if you want to label all your NGINX Pods as frontend tier, run:
kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled
This first filters all pods with the label "app=nginx", and then labels them with the "tier=fe". To see the pods you labeled, run:
kubectl get pods -l app=nginx -L tier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-2035384211-j5fhi 1/1 Running 0 23m fe
my-nginx-2035384211-u2c7e 1/1 Running 0 23m fe
my-nginx-2035384211-u3t6x 1/1 Running 0 23m fe
This outputs all "app=nginx" pods, with an additional label column of pods' tier
(specified with -L or --label-columns).
For more information, please see kubectl label.
What's next
3.1.2.4 - Namespaces
In Kubernetes, namespaces provide a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces. Namespace-based scoping is applicable only for namespaced objects (e.g. Deployments, Services, etc.) and not for cluster-wide objects (e.g. StorageClass, Nodes, PersistentVolumes, etc.).
When to Use Multiple Namespaces
Namespaces are intended for use in environments with many users spread across multiple teams, or projects. For clusters with a few to tens of users, you should not need to create or think about namespaces at all. Start using namespaces when you need the features they provide.
Namespaces provide a scope for names. Names of resources need to be unique within a namespace, but not across namespaces. Namespaces cannot be nested inside one another and each Kubernetes resource can only be in one namespace.
Namespaces are a way to divide cluster resources between multiple users (via resource quota).
It is not necessary to use multiple namespaces to separate slightly different resources, such as different versions of the same software: use labels to distinguish resources within the same namespace.
Note:
For a production cluster, consider not using thedefault namespace. Instead, make other namespaces and use those.Initial namespaces
Kubernetes starts with four initial namespaces:
default- Kubernetes includes this namespace so that you can start using your new cluster without first creating a namespace.
kube-node-lease- This namespace holds Lease objects associated with each node. Node leases allow the kubelet to send heartbeats so that the control plane can detect node failure.
kube-public- This namespace is readable by all clients (including those not authenticated). This namespace is mostly reserved for cluster usage, in case that some resources should be visible and readable publicly throughout the whole cluster. The public aspect of this namespace is only a convention, not a requirement.
kube-system- The namespace for objects created by the Kubernetes system.
Working with Namespaces
Creation and deletion of namespaces are described in the Admin Guide documentation for namespaces.
Note:
Avoid creating namespaces with the prefixkube-, since it is reserved for Kubernetes system namespaces.Viewing namespaces
You can list the current namespaces in a cluster using:
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-node-lease Active 1d
kube-public Active 1d
kube-system Active 1d
Setting the namespace for a request
To set the namespace for a current request, use the --namespace flag.
For example:
kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>
Setting the namespace preference
You can permanently save the namespace for all subsequent kubectl commands in that context.
kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view --minify | grep namespace:
Namespaces and DNS
When you create a Service,
it creates a corresponding DNS entry.
This entry is of the form <service-name>.<namespace-name>.svc.cluster.local, which means
that if a container only uses <service-name>, it will resolve to the service which
is local to a namespace. This is useful for using the same configuration across
multiple namespaces such as Development, Staging and Production. If you want to reach
across namespaces, you need to use the fully qualified domain name (FQDN).
As a result, all namespace names must be valid RFC 1123 DNS labels.
Warning:
By creating namespaces with the same name as public top-level domains, Services in these namespaces can have short DNS names that overlap with public DNS records. Workloads from any namespace performing a DNS lookup without a trailing dot will be redirected to those services, taking precedence over public DNS.
To mitigate this, limit privileges for creating namespaces to trusted users. If required, you could additionally configure third-party security controls, such as admission webhooks, to block creating any namespace with the name of public TLDs.
Not all objects are in a namespace
Most Kubernetes resources (e.g. Pods, Services, Deployments, and others) are in some namespaces. However namespace resources are not themselves in a namespace. And low-level resources, such as Nodes and PersistentVolumes, are not in any namespace.
To see which Kubernetes resources are and aren't in a namespace:
# In a namespace
kubectl api-resources --namespaced=true
# Not in a namespace
kubectl api-resources --namespaced=false
Automatic labelling
The Kubernetes control plane sets an immutable label
kubernetes.io/metadata.name on all namespaces.
The value of the label is the namespace name.
What's next
- Learn more about creating a new namespace.
- Learn more about deleting a namespace.
3.1.2.5 - Annotations
You can use Kubernetes annotations to attach arbitrary non-identifying metadata to objects. Clients such as tools and libraries can retrieve this metadata.
Attaching metadata to objects
You can use either labels or annotations to attach metadata to Kubernetes objects. Labels can be used to select objects and to find collections of objects that satisfy certain conditions. In contrast, annotations are not used to identify and select objects. The metadata in an annotation can be small or large, structured or unstructured, and can include characters not permitted by labels. It is possible to use labels as well as annotations in the metadata of the same object.
Annotations, like labels, are key/value maps:
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
Note:
The keys and the values in the map must be strings. In other words, you cannot use numeric, boolean, list or other types for either the keys or the values.Here are some examples of information that could be recorded in annotations:
Fields managed by a declarative configuration layer. Attaching these fields as annotations distinguishes them from default values set by clients or servers, and from auto-generated fields and fields set by auto-sizing or auto-scaling systems.
Build, release, or image information like timestamps, release IDs, git branch, PR numbers, image hashes, and registry address.
Pointers to logging, monitoring, analytics, or audit repositories.
Client library or tool information that can be used for debugging purposes: for example, name, version, and build information.
User or tool/system provenance information, such as URLs of related objects from other ecosystem components.
Lightweight rollout tool metadata: for example, config or checkpoints.
Phone or pager numbers of persons responsible, or directory entries that specify where that information can be found, such as a team web site.
Directives from the end-user to the implementations to modify behavior or engage non-standard features.
Instead of using annotations, you could store this type of information in an external database or directory, but that would make it much harder to produce shared client libraries and tools for deployment, management, introspection, and the like.
Syntax and character set
Annotations are key/value pairs. Valid annotation keys have two segments: an optional prefix and name, separated by a slash (/). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (.), not longer than 253 characters in total, followed by a slash (/).
If the prefix is omitted, the annotation Key is presumed to be private to the user. Automated system components (e.g. kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, or other third-party automation) which add annotations to end-user objects must specify a prefix.
The kubernetes.io/ and k8s.io/ prefixes are reserved for Kubernetes core components.
Valid annotation values have no character set restrictions — unlike label values, annotation values may contain any string, including special characters, whitespace, and structured data such as JSON or YAML. If you plan to store binary data (such as CBOR), the Kubernetes project recommends that you base64 encode it. However, the total size of all annotations on a single object (keys and values combined) must not exceed 256 KiB.
For example, here's a manifest for a Pod that has the annotation imageregistry: https://hub.docker.com/ :
apiVersion: v1
kind: Pod
metadata:
name: annotations-demo
annotations:
imageregistry: "https://hub.docker.com/"
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
What's next
- Learn more about Labels and Selectors.
- Find Well-known labels, Annotations and Taints
3.1.2.6 - Field Selectors
Field selectors let you select Kubernetes objects based on the value of one or more resource fields. Here are some examples of field selector queries:
metadata.name=my-servicemetadata.namespace!=defaultstatus.phase=Pending
This kubectl command selects all Pods for which the value of the status.phase field is Running:
kubectl get pods --field-selector status.phase=Running
Note:
Field selectors are essentially resource filters. By default, no selectors/filters are applied, meaning that all resources of the specified type are selected. This makes thekubectl queries kubectl get pods and kubectl get pods --field-selector "" equivalent.Supported fields
Supported field selectors vary by Kubernetes resource type. All resource types support the metadata.name and metadata.namespace fields. Using unsupported field selectors produces an error. For example:
kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
List of supported fields
| Kind | Fields |
|---|---|
| Pod | spec.nodeNamespec.restartPolicyspec.schedulerNamespec.serviceAccountNamespec.hostNetworkstatus.phasestatus.podIPstatus.podIPsstatus.nominatedNodeName |
| Event | involvedObject.kindinvolvedObject.namespaceinvolvedObject.nameinvolvedObject.uidinvolvedObject.apiVersioninvolvedObject.resourceVersioninvolvedObject.fieldPathreasonreportingComponentsourcetype |
| Secret | type |
| Service | spec.clusterIPspec.type |
| Namespace | status.phase |
| ReplicaSet | status.replicas |
| ReplicationController | status.replicas |
| Job | status.successful |
| Node | spec.unschedulable |
| CertificateSigningRequest | spec.signerName |
Custom resources fields
All custom resource types support the metadata.name and metadata.namespace fields.
Additionally, the spec.versions[*].selectableFields field of a CustomResourceDefinition
declares which other fields in a custom resource may be used in field selectors. See selectable fields for custom resources
for more information about how to use field selectors with CustomResourceDefinitions.
Supported operators
You can use the =, ==, and != operators with field selectors (= and == mean the same thing). This kubectl command, for example, selects all Kubernetes Services that aren't in the default namespace:
kubectl get services --all-namespaces --field-selector metadata.namespace!=default
Chained selectors
As with label and other selectors, field selectors can be chained together as a comma-separated list. This kubectl command selects all Pods for which the status.phase does not equal Running and the spec.restartPolicy field equals Always:
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
Multiple resource types
You can use field selectors across multiple resource types. This kubectl command selects all Statefulsets and Services that are not in the default namespace:
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default
3.1.2.7 - Finalizers
Finalizers are namespaced keys that tell Kubernetes to wait until specific conditions are met before it fully deletes resources that are marked for deletion. Finalizers alert controllers to clean up resources the deleted object owned.
When you tell Kubernetes to delete an object that has finalizers specified for
it, the Kubernetes API marks the object for deletion by populating .metadata.deletionTimestamp,
and returns a 202 status code (HTTP "Accepted"). The target object remains in a terminating state while the
control plane, or other components, take the actions defined by the finalizers.
After these actions are complete, the controller removes the relevant finalizers
from the target object. When the metadata.finalizers field is empty,
Kubernetes considers the deletion complete and deletes the object.
You can use finalizers to control garbage collection of resources. For example, you can define a finalizer to clean up related API resources or infrastructure before the controller deletes the object being finalized.
You can use finalizers to control garbage collection of objects by alerting controllers to perform specific cleanup tasks before deleting the target resource.
Finalizers don't usually specify the code to execute. Instead, they are typically lists of keys on a specific resource similar to annotations. Kubernetes specifies some finalizers automatically, but you can also specify your own.
How finalizers work
When you create a resource using a manifest file, you can specify finalizers in
the metadata.finalizers field. When you attempt to delete the resource, the
API server handling the delete request notices the values in the finalizers field
and does the following:
- Modifies the object to add a
metadata.deletionTimestampfield with the time you started the deletion. - Prevents the object from being removed until all items are removed from its
metadata.finalizersfield - Returns a
202status code (HTTP "Accepted")
The controller managing that finalizer notices the update to the object setting the
metadata.deletionTimestamp, indicating deletion of the object has been requested.
The controller then attempts to satisfy the requirements of the finalizers
specified for that resource. Each time a finalizer condition is satisfied, the
controller removes that key from the resource's finalizers field. When the
finalizers field is emptied, an object with a deletionTimestamp field set
is automatically deleted. You can also use finalizers to prevent deletion of unmanaged resources.
A common example of a finalizer is kubernetes.io/pv-protection, which prevents
accidental deletion of PersistentVolume objects. When a PersistentVolume
object is in use by a Pod, Kubernetes adds the pv-protection finalizer. If you
try to delete the PersistentVolume, it enters a Terminating status, but the
controller can't delete it because the finalizer exists. When the Pod stops
using the PersistentVolume, Kubernetes clears the pv-protection finalizer,
and the controller deletes the volume.
Note:
When you
DELETEan object, Kubernetes adds the deletion timestamp for that object and then immediately starts to restrict changes to the.metadata.finalizersfield for the object that is now pending deletion. You can remove existing finalizers (deleting an entry from thefinalizerslist) but you cannot add a new finalizer. You also cannot modify thedeletionTimestampfor an object once it is set.After the deletion is requested, you can not resurrect this object. The only way is to delete it and make a new similar object.
Note:
Custom finalizer names must be publicly qualified finalizer names, such asexample.com/finalizer-name.
Kubernetes enforces this format; the API server rejects writes to objects where the change does not use qualified finalizer names for any custom finalizer.Owner references, labels, and finalizers
Like labels, owner references describe the relationships between objects in Kubernetes, but are used for a different purpose. When a controller manages objects like Pods, it uses labels to track changes to groups of related objects. For example, when a Job creates one or more Pods, the Job controller applies labels to those pods and tracks changes to any Pods in the cluster with the same label.
The Job controller also adds owner references to those Pods, pointing at the Job that created the Pods. If you delete the Job while these Pods are running, Kubernetes uses the owner references (not labels) to determine which Pods in the cluster need cleanup.
Kubernetes also processes finalizers when it identifies owner references on a resource targeted for deletion.
In some situations, finalizers can block the deletion of dependent objects, which can cause the targeted owner object to remain for longer than expected without being fully deleted. In these situations, you should check finalizers and owner references on the target owner and dependent objects to troubleshoot the cause.
Note:
In cases where objects are stuck in a deleting state, avoid manually removing finalizers to allow deletion to continue. Finalizers are usually added to resources for a reason, so forcefully removing them can lead to issues in your cluster. This should only be done when the purpose of the finalizer is understood and is accomplished in another way (for example, manually cleaning up some dependent object).What's next
- Read Using Finalizers to Control Deletion on the Kubernetes blog.
3.1.2.8 - Owners and Dependents
In Kubernetes, some objects are owners of other objects. For example, a ReplicaSet is the owner of a set of Pods. These owned objects are dependents of their owner.
Ownership is different from the labels and selectors
mechanism that some resources also use. For example, consider a Service that
creates EndpointSlice objects. The Service uses labels to allow the control plane to
determine which EndpointSlice objects are used for that Service. In addition
to the labels, each EndpointSlice that is managed on behalf of a Service has
an owner reference. Owner references help different parts of Kubernetes avoid
interfering with objects they don’t control.
Owner references in object specifications
Dependent objects have a metadata.ownerReferences field that references their
owner object. A valid owner reference consists of the object name and a UID
within the same namespace as the dependent object. Kubernetes sets the value of
this field automatically for objects that are dependents of other objects like
ReplicaSets, DaemonSets, Deployments, Jobs and CronJobs, and ReplicationControllers.
You can also configure these relationships manually by changing the value of
this field. However, you usually don't need to and can allow Kubernetes to
automatically manage the relationships.
Dependent objects also have an ownerReferences.blockOwnerDeletion field that
takes a boolean value and controls whether specific dependents can block garbage
collection from deleting their owner object. Kubernetes automatically sets this
field to true if a controller
(for example, the Deployment controller) sets the value of the
metadata.ownerReferences field. You can also set the value of the
blockOwnerDeletion field manually to control which dependents block garbage
collection.
A Kubernetes admission controller controls user access to change this field for dependent resources, based on the delete permissions of the owner. This control prevents unauthorized users from delaying owner object deletion.
Note:
Cross-namespace owner references are disallowed by design. Namespaced dependents can specify cluster-scoped or namespaced owners. A namespaced owner must exist in the same namespace as the dependent. If it does not, the owner reference is treated as absent, and the dependent is subject to deletion once all owners are verified absent.
Cluster-scoped dependents can only specify cluster-scoped owners. In v1.20+, if a cluster-scoped dependent specifies a namespaced kind as an owner, it is treated as having an unresolvable owner reference, and is not able to be garbage collected.
In v1.20+, if the garbage collector detects an invalid cross-namespace ownerReference,
or a cluster-scoped dependent with an ownerReference referencing a namespaced kind, a warning Event
with a reason of OwnerRefInvalidNamespace and an involvedObject of the invalid dependent is reported.
You can check for that kind of Event by running
kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace.
Ownership and finalizers
When you tell Kubernetes to delete a resource, the API server allows the
managing controller to process any finalizer rules
for the resource. Finalizers
prevent accidental deletion of resources your cluster may still need to function
correctly. For example, if you try to delete a PersistentVolume that is still
in use by a Pod, the deletion does not happen immediately because the
PersistentVolume has the kubernetes.io/pv-protection finalizer on it.
Instead, the volume remains in the Terminating status until Kubernetes clears
the finalizer, which only happens after the PersistentVolume is no longer
bound to a Pod.
Kubernetes also adds finalizers to an owner resource when you use either
foreground or orphan cascading deletion.
In foreground deletion, it adds the foreground finalizer so that the
controller must delete dependent resources that also have
ownerReferences.blockOwnerDeletion=true before it deletes the owner. If you
specify an orphan deletion policy, Kubernetes adds the orphan finalizer so
that the controller ignores dependent resources after it deletes the owner
object.
What's next
- Learn more about Kubernetes finalizers.
- Learn about garbage collection.
- Read the API reference for object metadata.
3.1.2.9 - Recommended Labels
You can visualize and manage Kubernetes objects with more tools than kubectl and the dashboard. A common set of labels allows tools to work interoperably, describing objects in a common manner that all tools can understand.
In addition to supporting tooling, the recommended labels describe applications in a way that can be queried.
The metadata is organized around the concept of an application. Kubernetes is not a platform as a service (PaaS) and doesn't have or enforce a formal notion of an application. Instead, applications are informal and described with metadata. The definition of what an application contains is loose.
Note:
These are recommended labels. They make it easier to manage applications but aren't required for any core tooling.Shared labels and annotations share a common prefix: app.kubernetes.io. Labels
without a prefix are private to users. The shared prefix ensures that shared labels
do not interfere with custom user labels.
Labels
In order to take full advantage of using these labels, they should be applied on every resource object.
| Key | Description | Example | Type |
|---|---|---|---|
app.kubernetes.io/name | The name of the application | mysql | string |
app.kubernetes.io/instance | A unique name identifying the instance of an application | mysql-abcxyz | string |
app.kubernetes.io/version | The current version of the application (e.g., a SemVer 1.0, revision hash, etc.) | 5.7.21 | string |
app.kubernetes.io/component | The component within the architecture | database | string |
app.kubernetes.io/part-of | The name of a higher level application this one is part of | wordpress | string |
app.kubernetes.io/managed-by | The tool being used to manage the operation of an application | Helm | string |
To illustrate these labels in action, consider the following StatefulSet object:
# This is an excerpt
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxyz
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: Helm
Applications And Instances Of Applications
An application can be installed one or more times into a Kubernetes cluster and, in some cases, the same namespace. For example, WordPress can be installed more than once where different websites are different installations of WordPress.
The name of an application and the instance name are recorded separately. For
example, WordPress has a app.kubernetes.io/name of wordpress while it has
an instance name, represented as app.kubernetes.io/instance with a value of
wordpress-abcxyz. This enables the application and instance of the application
to be identifiable. Every instance of an application must have a unique name.
Examples
To illustrate different ways to use these labels the following examples have varying complexity.
A Simple Stateless Service
Consider the case for a simple stateless service deployed using Deployment and Service objects. The following two snippets represent how the labels could be used in their simplest form.
The Deployment is used to oversee the pods running the application itself.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxyz
...
The Service is used to expose the application.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxyz
...
Web Application With A Database
Consider a slightly more complicated application: a web application (WordPress) using a database (MySQL), installed using Helm. The following snippets illustrate the start of objects used to deploy this application.
The start to the following Deployment is used for WordPress:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxyz
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
The Service is used to expose WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxyz
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
MySQL is exposed as a StatefulSet with metadata for both it and the larger application it belongs to:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxyz
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
The Service is used to expose MySQL as part of WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxyz
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
With the MySQL StatefulSet and Service you'll notice information about both MySQL and WordPress, the broader application, are included.
3.1.2.10 - Storage Versions
The Kubernetes API server stores objects, relying on an etcd-compatible backing store (often, the backing storage is etcd itself). Each object is serialized using a particular version of that API type; for example, the v1 representation of a ConfigMap. Kubernetes uses the term storage version to describe how an object is stored in your cluster.
The Kubernetes API also relies on automatic conversion; for example, if you have a HorizontalPodAutoscaler, then you can interact with that HorizontalPodAutoscaler using any mix of the v1 and v2 versions of the HorizontalPodAutoscaler API. Kubernetes is responsible for converting each API call so that clients do not see what version is actually serialized.
For cluster administrators, object storage version is an important concept to understand since it is what links the API representation of the object to the actual encoding in the storage backend. This can be important for when the underlying binary encodings of the object matter, such as for encryption at rest, or API deprecation.
The same API may have multiple storage versions that the API Server can then convert to an object schema. A single object that is part of that resource must only have one storage version at any time. This means that the API Server is aware of the binary encodings of the objects and is able to convert between all the stored versions to the API Representation of the object dynamically.
The version of an object is separate from the storage version entirely. For
example, a v1alpha1 and v1beta1 API Object for the same Resource will be
encoded the same in storage as long as the storage version has not been updated
between the two objects.
Storage version to resource mapping
Every resource will have 1 active storage version at any point in time, meaning that any write to an object will store the object at that storage version. The storage version can be updated however, making it so that objects can be stored at differing versions. One object will only be stored at one storage version at any time.
Reads from the API Server will convert the stored data to the API representation of the object. This makes it so that old storage versions can sit indefinitely as long as no updates occur to the object. Writes, on the other hand, will convert the stored object to the new representation upon update.
Storage versions for custom resources
Custom resources are defined dynamically, and as such differ from built in Kubernetes types with their storage version. Builtin objects generally have their storage encoding defined separately from their API types, where the stored object acts as a hub and the specific version of the resource does not matter apart from being a field in the object schema.
However, for custom resources, a certain version of the resource must be set as the storage version. The schema defined by that specific version of the custom resource will be used as the encoding of the resource in the storage layer. See the advanced CRD featureset for more detailed information on the API setup and versioning.
For example see this CustomResourceDefinition for crontabs:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: