4. The K8s REST API

In addition to the kubectl command-line tool, K8s provides a JSON-based REST API.

4.1. Install jq and yq

jq is a tool for pretty-formatting JSON data in the console, and yq is the corresponding tool for YAML. They can also be used to filter and manipulate keys and values within the JSON or YAML document. We install them as follows:

sudo snap install jq
sudo snap install yq

4.2. Accessing the K8s API

Expose the API server as follows:

kubectl proxy

In a seperate shell:

curl -s http://localhost:8001/version | jq

The -s flag above suppresses progress information from curl, showing only the downloaded content, which is then piped to jq. You should see something like the following:

{
  "major": "1",
  "minor": "30",
  "gitVersion": "v1.30.0",
  "gitCommit": "7c48c2bd72b9bf5c44d21d7338cc7bea77d0ad2a",
  "gitTreeState": "clean",
  "buildDate": "2024-04-17T17:27:03Z",
  "goVersion": "go1.22.2",
  "compiler": "gc",
  "platform": "linux/amd64"
}

4.3. Client keys and tokens

First, terminate the proxy from above. In this subsection, we will access the API server using its IP address on the minikube network.

Note

When using the “docker” engine (the default), Minikube runs as a Docker container on the newly created minikube network.

$ docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
0037aa7cdd27   bridge     bridge    local
0f889a755b8e   host       host      local
5f97f356041c   minikube   bridge    local
58197f5f288c   none       null      local

$ # IP address of the minikube container on the `minikube` network
$ docker network inspect minikube | jq '.[].Containers | to_entries[].value.IPv4Address'
"192.168.49.2/24"

$ # IP address of the host machine on the `minikube` network
$ docker network inspect minikube | jq '.[].IPAM.Config[0].Gateway'
"192.168.49.1"

To authenticate ourselves properly while using the REST API, we examine our K8s configuration:

kubectl config view | yq

Example output:

apiVersion: v1
clusters:
  - cluster:
      certificate-authority: /home/yinchi/.minikube/ca.crt
      extensions:
        - extension:
            last-update: Fri, 02 Aug 2024 18:35:48 BST
            provider: minikube.sigs.k8s.io
            version: v1.33.1
          name: cluster_info
      server: https://192.168.49.2:8443
    name: minikube
contexts:
  - context:
      cluster: minikube
      extensions:
        - extension:
            last-update: Fri, 02 Aug 2024 18:35:48 BST
            provider: minikube.sigs.k8s.io
            version: v1.33.1
          name: context_info
      namespace: default
      user: minikube
    name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
  - name: minikube
    user:
      client-certificate: /home/yinchi/.minikube/profiles/minikube/client.crt
      client-key: /home/yinchi/.minikube/profiles/minikube/client.key

Save the API server’s IP address and authentication file paths to environment variables:

$ cat minikube.sh
export MINIKUBE_SERVER=$(kubectl config view | yq '.clusters[] | select(.name == "minikube") | .cluster.server')
export MINIKUBE_CA=$(kubectl config view | yq '.clusters[] | select(.name == "minikube") | .cluster.certificate-authority')
export MINIKUBE_CLIENT_CERT=$(kubectl config view | yq '.users[] | select(.name == "minikube") | .user.client-certificate')
export MINIKUBE_CLIENT_KEY=$(kubectl config view | yq '.users[] | select(.name == "minikube") | .user.client-key')

$ . minikube.sh

Test the above configuration by fetching from the API root:

curl -s $MINIKUBE_SERVER --cert $MINIKUBE_CLIENT_CERT \
  --key $MINIKUBE_CLIENT_KEY --cacert $MINIKUBE_CA | jq -C | head
{
  "paths": [
    "/.well-known/openid-configuration",
    "/api",
    "/api/v1",
    "/apis",
    "/apis/",
    "/apis/admissionregistration.k8s.io",
    "/apis/admissionregistration.k8s.io/v1",
    "/apis/apiextensions.k8s.io",

Supplying a -C flag to jq in the command above forces color output, which is disabled by default if the output is piped.

Note

Without supplying our certificates/keys, we need to supply an --insecure or -k flag to curl. Nevertheless, the above API endpoint will not work:

$ curl -s $MINIKUBE_SERVER -k | jq
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}