Exploring the Kubernetes API and Key Metadata

Exploring Kubernetes API and Key Metadata
Exploring Kubernetes API and Key Metadata

In this section, we cover essential techniques for working with Kubernetes objects and the API. Every Kubernetes object, from deployments to nodes, has key fields like metadata, spec, and status.

The spec outlines the desired setup, and the status shows the current state, all managed by the Kubernetes API server. Our goal is to offer expert insights for efficiently handling your Kubernetes resources.

Discovering Kubernetes API Server Endpoints

Use Case

You need to find out the different API endpoints available on the Kubernetes API server.

Solution

Assuming you’re using a local development cluster like kind or Minikube, you can utilize kubectl proxy in a separate terminal window.

This command sets up a proxy that simplifies access to the Kubernetes server API via an HTTP client like curl, sidestepping the need for authentication and certificates. Once you run kubectl proxy, the API server becomes accessible on port 8001. For example:

$ curl http://localhost:8001/api/v1/
{
"kind": "APIResourceList",
"groupVersion": "v1",
"resources": [
{
"name": "bindings",
"singularName": "",
"namespaced": true,
"kind": "Binding",
"verbs": [
"create"
]
},
{
"name": "componentstatuses",
"singularName": "",
"namespaced": false,
...

This command returns a list of all objects the Kubernetes API exposes, including details like object types and available operations.

Additionally, the kubectl api-resources command is another straightforward method to discover API endpoints.

Discussion

To explore all API groups, use:

$ curl http://localhost:8001/apis/
{
"kind": "APIGroupList",
"apiVersion": "v1",
"groups": [
{
"name": "apiregistration.k8s.io",
"versions": [
{
"groupVersion": "apiregistration.k8s.io/v1",
"version": "v1"
}
],
"preferredVersion": {
"groupVersion": "apiregistration.k8s.io/v1",
"version": "v1"
}
},
{
"name": "apps",
"versions": [
...

This command lists available API groups. From here, you can dive into specific groups like /apis/apps, /apis/storage.k8s.io, /apis/flowcontrol.apiserver.k8s.io, and /apis/autoscaling, each representing different API functionalities.

API groups are structured with versioned objects (e.g., v1, v2beta1) indicating their stability and maturity. For instance, core API objects fall under /api/v1, while others, like deployments in apps/v1, belong to named groups under /apis/.

The apiVersion specified in an object’s definition corresponds to its API group, guiding you to the correct documentation in the API reference.

See Also

Understanding the Structure of a Kubernetes Manifest

Use Case

While Kubernetes offers quick commands like kubectl run and kubectl create for ease of use, mastering the art of writing Kubernetes manifests is crucial for fully leveraging its declarative approach to defining object specifications. To craft these manifests, you must grasp their general structure.

Solution

As explored in a previous recipe, discovering the API group of an object is the first step. Every API resource in Kubernetes is categorized as either an object or a list, each defined by a kind and an apiVersion.

Crucially, every object type requires metadata, which includes the object’s name, its namespace (if applicable), and, optionally, labels and annotations for further categorization and metadata.

For instance, a simple pod manifest in YAML format starts with its apiVersion and kind, followed by metadata that names the pod:

apiVersion: v1
kind: Pod
metadata:
name: mypod

To fully specify an object, the manifest typically includes a spec detailing the desired state, and once the object is created, Kubernetes assigns it a status reflecting its current state:

codeapiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
# Pod specification goes here
status:
# Status is managed by Kubernetes

Discussion

Kubernetes manifests are powerful tools for defining your cluster’s desired state. Being file-based, they can be version-controlled with systems like Git, enabling collaborative and asynchronous workflows among teams and supporting continuous integration and deployment pipelines.

This practice aligns with the GitOps philosophy, where system changes are enacted through version control, ensuring changes are traceable and states can be replicated or rolled back easily. This method exemplifies the “Infrastructure as Code” (IaC) approach, emphasizing the importance of managing infrastructure through declarative files.

See Also

Creating Namespaces to Avoid Name Collisions

Use Case

You need to create two objects with the same name in Kubernetes without causing name collisions.

Solution

The solution is to use namespaces, which act as isolated containers within a Kubernetes cluster, allowing you to have objects with the same name in different contexts. By default, objects are created in the default namespace. However, you can create additional namespaces to organize your resources effectively.

For instance, to create a new namespace named my-app, and then verify its creation alongside existing namespaces, you can use the following commands:

kubectl create namespace my-app
# This command creates a new namespace named my-app

kubectl get ns
# Lists all namespaces, including the newly created my-app

Note: You can also define a namespace using a manifest file. For example, creating a file named app.yaml with the following content:

apiVersion: v1
kind: Namespace
metadata:
name: my-app

Then, apply this manifest to create the namespace:

kubectl apply -f app.yaml

Discussion

Creating objects with identical names in the same namespace (e.g., the default namespace) will lead to a conflict, as Kubernetes does not allow duplicate names within a single namespace. Here’s an example scenario demonstrating a naming collision:

kubectl run foobar --image=nginx:latest
# This creates a pod named foobar in the default namespace

kubectl run foobar --image=nginx:latest
# This command fails because a pod with the name foobar already exists in the default namespace

kubectl run foobar --image=nginx:latest --namespace my-app
# Successfully creates another pod named foobar, but in the my-app namespace, avoiding the name collision

Note: Certain namespaces, like kube-system for cluster operations and kube-public for public resources accessible across the cluster, have specific purposes. It’s generally recommended to create custom namespaces for organizing your own applications and resources, keeping them separate from these system namespaces.

Setting Quotas Within a Kubernetes Namespace

Use Case

You want to restrict the resources available within a namespace—for instance, limiting the number of pods that can be run in a specific namespace.

Solution

To implement such limitations, you can use a ResourceQuota object, which allows you to set quotas for various resources on a per-namespace basis.

Here’s how you can create a resource quota for pods:

  1. Create a Resource Quota Manifest: First, define your resource quota in a YAML file named resource-quota-pods.yaml. This file specifies the maximum number of pods allowed in the namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: podquota
spec:
hard:
pods: "10"
  1. Create a Namespace (if not already existing): Before applying the quota, ensure you have a namespace where it will be enforced:
kubectl create namespace my-app
# This command creates a new namespace named my-app.
  1. Apply the Resource Quota: Next, apply the resource quota to your namespace:
kubectl apply -f resource-quota-pods.yaml --namespace=my-app
# This command applies the quota to the my-app namespace.
  1. Verify the Resource Quota: Finally, to see the details of the applied resource quota, use:
kubectl describe resourcequota podquota --namespace=my-app

This command provides an overview of the quota, showing how many resources are used and the total hard limit set.

Discussion

Resource quotas are versatile and can be set for various resources, not just pods. You can control the number of secrets, config maps, and other Kubernetes resources within a namespace, helping you manage resource consumption and prevent any single namespace from exhausting cluster resources.

See Also

  • Configure Quotas for API Objects: This resource provides further information on how to set and manage quotas for different Kubernetes resources, offering guidance on creating a balanced and efficient Kubernetes environment.


Labeling a Kubernetes Object

Use Case

You need to assign labels to an object in Kubernetes, enabling you to easily identify and select it for user queries or system automation later on.

Solution

To label an object, such as a pod, you can use the kubectl label command. For instance, to label a pod named foobar with a tier=frontend label, you can execute the following command:

kubectl label pods foobar tier=frontend
# This command adds the label tier=frontend to the pod named foobar.

Tip: For more options, including how to remove or overwrite labels and label all resources within a namespace, check the command’s help page by running kubectl label --help.

Discussion

Labels are a key feature in Kubernetes for organizing objects in a flexible and non-hierarchical way. They are simple key/value pairs that Kubernetes itself does not interpret, meaning the significance of a label is determined entirely by your usage and conventions within your organization.

Labels can be used to denote many aspects, such as the belonging of an object to a certain department, the environment it operates in (e.g., production, staging), or any other organizational scheme you may need.

While Kubernetes does not impose a strict meaning on labels, it does enforce certain limitations on their format, such as length and permissible characters. Additionally, the Kubernetes community provides guidelines for structuring label keys, helping maintain clarity and consistency across your infrastructure.

See Also

  • Kubernetes Documentation on Labels: This resource offers a deeper dive into the use of labels, including common patterns and best practices for labeling objects within your Kubernetes clusters, facilitating effective organization and selection of resources based on these labels.

Using Labels for Kubernetes Queries

Use Case

You need an efficient way to query Kubernetes objects based on specific criteria.

Solution

The kubectl get --selector command allows for querying objects based on their labels. For example, if you have a mix of pods with different labels, like the following:

kubectl get pods --show-labels

Output might look like this:

NAME     READY   STATUS    RESTARTS   AGE     LABELS
foobar 1/1 Running 0 18m run=foobar,tier=frontend
nginx1 1/1 Running 0 72s app=nginx,run=nginx1
nginx2 1/1 Running 0 68s app=nginx,run=nginx2
nginx3 1/1 Running 0 65s app=nginx,run=nginx3

To select all pods that are labeled as part of the NGINX app (app=nginx), you would use:

kubectl get pods --selector app=nginx

This would return all pods with the app=nginx label:

NAME     READY   STATUS    RESTARTS   AGE
nginx1 1/1 Running 0 3m45s
nginx2 1/1 Running 0 3m41s
nginx3 1/1 Running 0 3m38s

Discussion

Labels form a core part of an object’s metadata in Kubernetes and can be assigned to nearly any object within the system. They serve not only for user-defined queries but also play a critical role in Kubernetes’ own mechanisms, such as deployment pod selections and service targeting.

Labels can be applied in several ways:

  • Manually, using the kubectl label command.
  • Through specifications within an object’s manifest file.

Once labeled, objects can be queried with kubectl get using various selector flags:

  • -l or --selector for querying objects with specific key=value pairs.
  • --show-labels to display all labels of the returned objects.
  • -L to add a column in the output showing the value for a specific label.

Furthermore, Kubernetes supports set-based querying, enabling complex queries like selecting pods that belong to multiple potential environments.

Examples:

kubectl get pods --show-labels
kubectl get pods -L run
kubectl get pods -l run=foobar

This flexibility allows for precise control and organization of resources within a Kubernetes cluster.

See Also

Annotating a Kubernetes Resource with One Command

Use Case

You need to add a generic, possibly non-human-readable annotation to a Kubernetes resource. Annotations are key for non-identifying metadata that may be used by tools and libraries for automation purposes.

Solution

To annotate a resource, such as a pod named foobar, with a key/value pair, you can use the kubectl annotate command. For example, to add a description annotation, you would execute:

kubectl annotate pods foobar description='something that you can use for automation'

This command annotates the pod foobar with a description key.

Discussion

Annotations are a Kubernetes feature primarily designed for storing auxiliary data, especially useful for automation processes. They differ from labels in that they are not used to organize or select resources within Kubernetes. Instead, annotations provide a means to attach metadata that can be utilized by tools and applications managing or interfacing with Kubernetes resources.

A practical use case for annotations is recording the reason behind deployment changes. For example, starting with Kubernetes v1.6.0, if you wish to track changes made to a deployment, you can annotate the deployment with a kubernetes.io/change-cause key. Here’s how to annotate a deployment named foobar to record the reason for a revision:

kubectl annotate deployment foobar kubernetes.io/change-cause="Reason for creating a new revision"

With this annotation in place, subsequent changes to the deployment will include this change cause in the rollout history, offering clearer insight into the evolution of the deployment.

Key Takeaway

While both annotations and labels add metadata to Kubernetes objects, only labels can be used as selectors in queries. Therefore, if your metadata is not intended for filtering purposes, annotations are often the more appropriate choice for including it in your resources.

Author

  • Mohamed BEN HASSINE

    Mohamed BEN HASSINE is a Hands-On Cloud Solution Architect based out of France. he has been working on Java, Web , API and Cloud technologies for over 12 years and still going strong for learning new things. Actually , he plays the role of Cloud / Application Architect in Paris ,while he is designing cloud native solutions and APIs ( REST , gRPC). using cutting edge technologies ( GCP / Kubernetes / APIGEE / Java / Python )

    View all posts
0 Shares:
You May Also Like