K8s personal notes
If you create PV manually(static provisioning) the default reclaim policy is "retain" i.e if pvc is deleted PV is not deleted it will be in RELEASED state
If you create a PV using storage class(dynamic provisioning) then you need to specify reclaimPolicy: Retain or Delete in the specs. If you fail to specify then the default will be deleted i.e. if pvc is deleted then pv and actual data will be deleted.
When you create a Headless service then pods of stateful set will get unique names in local dns of k8.
<pod-name>.<headless-service-name>.<namespace>.svc.cluster.local
By default k8 stateful set doesn`t create these unique identities for pods. It will be created only when you create a headless service and specify thet service name in statefulset pod spec:Example:
The StatefulSet documentation often mentions the use of a headless service because it's a common and recommended practice when working with StatefulSets. But Kubernetes won't automatically create one for you. You'll need to define and create the headless service separately, and then reference it in your StatefulSet configuration.
Here's a basic workflow:
- Create a headless service. For example:
yamlCopy codeapiVersion: v1
kind: Service
metadata:
name: my-service
spec:
clusterIP: None
selector:
app: my-app
ports:
- protocol: TCP
port: 80
- Create a StatefulSet that uses the headless service for DNS naming:
yamlCopy codeapiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-statefulset
spec:
serviceName: my-service
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image
Notice the serviceName
field in the StatefulSet configuration. It references the headless service you created. This association ensures that the pods in the StatefulSet will have stable hostnames based on the service name.
given the above manifest files for the headless service (
my-service
) and the StatefulSet (my-statefulset
), the DNS names for the pods created by the StatefulSet will be in the following format:phpCopy code<pod-name>.<service-name>.<namespace>.svc.cluster.local
Let's break it down:
<pod-name>
: This is the name of the pod. For a StatefulSet, the pod names are based on an indexed naming scheme:<statefulset-name>-0
,<statefulset-name>-1
, and so on. Given the StatefulSet's name in the provided manifest (my-statefulset
), the pod names would bemy-statefulset-0
,my-statefulset-1
, etc.<service-name>
: This is the name of the headless service associated with the StatefulSet. In the provided manifest, this name ismy-service
.<namespace>
: This is the namespace in which both the service and the StatefulSet are created. If you don't specify a namespace in your manifests, it defaults to thedefault
namespace.svc.cluster.local
: This is a constant suffix used for services in the Kubernetes DNS resolution.
Given the above manifest files and assuming the default
namespace, the DNS names for the pods would be:
my-statefulset-0.my-service.default.svc.cluster.local
my-statefulset-1.my-service.default.svc.cluster.local
my-statefulset-2.my-service.default.svc.cluster.local
...and so on, based on the number of replicas you define in the StatefulSet. In the provided example, there are 3 replicas, so you'd get three pods with the names listed above.
If you create only a StatefulSet without a headless service, the pod naming convention remains the same, but you won't have the DNS hostname resolution provided by the headless service. The pods created by the StatefulSet will still follow the indexed naming scheme based on the StatefulSet's name.
For example, given the following StatefulSet manifest:
yamlCopy codeapiVersion: apps/v1 kind: StatefulSet metadata: name: my-statefulset spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: my-image
The pod names would be:
my-statefulset-0
my-statefulset-1
my-statefulset-2
However, without the associated headless service:
You won't have DNS hostname resolution in the format
<pod-name>.<service-name>.<namespace>.svc.cluster.local
.Other pods or applications in the cluster can't use those DNS hostnames to address individual pods of the StatefulSet. They would need to rely on other mechanisms, like directly using the pod IP.
Thus, while the pod naming remains consistent, you lose the DNS-based network identity benefits that the headless service provides for StatefulSets. For many stateful applications (like databases or distributed systems), this DNS-based identity is crucial for proper functioning.
Volume binding mode in Immediate vs WaitForFirstConsumer
In Kubernetes, the volume binding mode in storage classes determines when the Persistent Volume (PV) binding and dynamic provisioning should occur in relation to the Persistent Volume Claim (PVC) creation.
The
volumeBindingMode
field in the storage class has two possible values:Immediate (default):
When a PVC is created, the Kubernetes control plane immediately tries to find an available PV that matches the PVC's requirements. If it finds a matching PV, it binds them. If no PVs match, and the storage class is configured to allow dynamic provisioning, Kubernetes immediately provisions a new PV.
This mode can lead to suboptimal bindings when the first PV that matches some PVCs can't be bound because of the remaining ones.
WaitForFirstConsumer:
With this mode, the PV binding and provisioning are delayed until a pod that uses the PVC is created.
When the pod is created and scheduled to a specific node, the Kubernetes control plane looks for a suitable PV or dynamically provisions one on the same node (or in the same zone/topology domain depending on the setup and requirements).
This mode is particularly useful in multi-zone clusters to ensure that volumes are provisioned in the same zone where the pod is scheduled. It helps avoid unnecessary inter-zone data transfer costs and latency.
It's often used with StatefulSets, ensuring that each replica is provisioned with storage in the correct topology domain.
Here's an example of a storage class with WaitForFirstConsumer
:
yamlCopy codeapiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: my-storage-class
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
volumeBindingMode: WaitForFirstConsumer
Using the appropriate volume binding mode ensures optimal and efficient utilization of storage resources and can help in ensuring data locality, reducing costs, and improving performance.
API Groups
In Kubernetes, the term "API groups" is used to classify API endpoints based on functionality and versioning. The two terms you mentioned, "core" and "names[a]pis" (assuming you meant "namespaced APIs"), refer to different aspects of the Kubernetes API. Let's break them down:
Core API Group:
The Core API group, sometimes referred to as the "legacy group", is the original API group of Kubernetes. It doesn't have a named group like the other newer API groups.
Resources in the Core group include foundational objects like Pods, Services, and Nodes.
The API endpoint for Core resources looks like this:
/api/v1/<resource-name>
. For example, to access Pods in thedefault
namespace, you'd go to/api/v1/namespaces/default/pods
.
Namespaced vs Non-namespaced APIs:
Kubernetes resources can be categorized based on whether they exist within a namespace or cluster-wide. This distinction isn't related directly to the Core API group but rather to the nature of the resource itself.
Namespaced Resources: These resources exist within a namespace and are isolated from other namespaces. Examples include Pods, Services, Deployments, etc.
- Example endpoint:
/api/v1/namespaces/<namespace-name>/pods
- Example endpoint:
Non-namespaced (or Cluster-wide) Resources: These resources are not bound to any specific namespace and exist across the entire cluster. Examples include Nodes, PersistentVolumes, ClusterRoles, etc.
- Example endpoint (for a Core resource like Nodes):
/api/v1/nodes
- Example endpoint (for a Core resource like Nodes):
Other API Groups:
As Kubernetes evolved, newer resources were added under different API groups to logically segregate them based on functionality and to allow versioning of groups independently.
Examples of these groups include
apps
(which contains resources like Deployments and StatefulSets),batch
(which contains Jobs and CronJobs),rbac.authorization.k8s.io
(which contains role-based access control resources), and many more.The API endpoint for these groups generally looks like this:
/apis/<group-name>/<version>/<resource-name>
. For example, to access Deployments in thedefault
namespace in theapps
group, you'd go to/apis/apps/v1/namespaces/default/deployments
.
The organization into API groups, combined with the distinction between namespaced and non-namespaced resources, allows Kubernetes to have a structured and versioned API that can evolve over time without breaking existing workloads.
Kubectl proxy
kubectl proxy
provides a way to access the Kubernetes API server locally without needing to handle authentication yourself, as the proxy command uses your current kubeconfig settings to authenticate requests to the API server. It's a convenient tool for debugging and accessing cluster internals.Here's how you can access both core and named APIs using
curl
after you've startedkubectl proxy
.Starting the Proxy:
First, start the proxy. By default, it will listen on port
8001
.bashCopy codekubectl proxy
Accessing Core API Group:
Core, or the legacy group, contains foundational Kubernetes objects. To access resources in the core group, use:
bashCopy code# List Pods in a specific namespace (e.g., 'default') curl http://localhost:8001/api/v1/namespaces/default/pods # List all Nodes in the cluster curl http://localhost:8001/api/v1/nodes # List Services in a specific namespace (e.g., 'default') curl http://localhost:8001/api/v1/namespaces/default/services
Accessing Named API Groups:
Named API groups are newer classifications of resources, organized logically based on functionality.
bashCopy code# List Deployments in the 'default' namespace from the 'apps' group curl http://localhost:8001/apis/apps/v1/namespaces/default/deployments # List all ClusterRoles from the 'rbac.authorization.k8s.io' group curl http://localhost:8001/apis/rbac.authorization.k8s.io/v1/clusterroles # List all NetworkPolicies in the 'default' namespace from the 'networking.k8s.io' group curl http://localhost:8001/apis/networking.k8s.io/v1/namespaces/default/networkpolicies
Note that while kubectl proxy
is a handy tool for local debugging and exploration, it's not suitable for production use. It's designed primarily for development purposes. Always be cautious when accessing or modifying resources, especially when using the Kubernetes API directly.
Note: Refer kode kloud notes