APIs and Access
Exercise 5.1: Configuring TLS Access
Overview
Using the Kubernetes API, kubectl makes API calls for you. With the appropriate TLS keys you could run curl as well use a golang client. Calls to the kube-apiserver get or set a PodSpec, or desired state. If the request represents a new state the Kubernetes Control Plane will update the cluster until the current state matches the specified state. Some end states may require multiple requests. For example, to delete a ReplicaSet, you would first set the number of replicas to zero, then delete the ReplicaSet.
An API request must pass information as JSON. kubectl converts .yaml to JSON when making an API request on your behalf. The API request has many settings, but must include apiVersion, kind and metadata, and spec settings to declare what kind of container to deploy. The spec fields depend on the object being created. We will begin by configuring remote access to the kube-apiserver then explore more of the API.
Configuring TLS Access
- Begin by reviewing the kubectl configuration file. We will use the three certificates and the API server address.
student@lfs458-node-1a0a:~$ less ~/.kube/config <output_omitted> - We will set the certificates as variables. You may want to double-check each parameter as you set it. Begin with setting
the client-certificate-data key.
student@lfs458-node-1a0a:~$ export client=$(grep client-cert ~/.kube/config |cut -d" " -f 6) student@lfs458-node-1a0a:~$ echo $client LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJ BZ0lJRy9wbC9rWEpNdmd3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0 ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4TnpFeU1UTXhOelEyTXpKY UZ3MHhPREV5TVRNeE56UTJNelJhTURReApGekFWQmdOVkJBb1REbk41YzNS <output_omitted> - Almost the same command, but this time collect the client-key-data as the key variable.
student@lfs458-node-1a0a:~$ export key=$(grep client-key-data ~/.kube/config |cut -d " " -f 6) student@lfs458-node-1a0a:~$ echo $key <output_omitted> - Finally set the auth variable with the certificate-authority-data key
student@lfs458-node-1a0a:~$ export auth=$(grep certificate-authority-data ~/.kube/config |cut -d " " -f 6) student@lfs458-node-1a0a:~$ echo $auth <output_omitted> - Now encode the keys for use with curl.
student@lfs458-node-1a0a:~$ echo $client | base64 -d - > ./client.pem student@lfs458-node-1a0a:~$ echo $key | base64 -d - > ./client-key.pem student@lfs458-node-1a0a:~$ echo $auth | base64 -d - > ./ca.pem - Pull the API server URL from the config file.
student@lfs458-node-1a0a:~$ kubectl config view |grep server server: https://10.128.0.3:6443 - Use curl command and the encoded keys to connect to the API server.
student@lfs458-node-1a0a:~$ curl --cert ./client.pem \ --key ./client-key.pem \ --cacert ./ca.pem \ https://10.128.0.3:6443/api/v1/pods { "kind": "PodList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/pods", "resourceVersion": "239414" }, <output_omitted> - If the previous command was successful, create a JSON file to create a new pod. Remember to look for this file in the
tarball output, it can save you some typing.
student@lfs458-node-1a0a:~$ vim curlpod.json { "kind": "Pod", "apiVersion": "v1", "metadata":{ "name": "curlpod", "namespace": "default", "labels": { "name": "examplepod" } }, "spec": { "containers": [{ "name": "nginx", "image": "nginx", "ports": [{"containerPort": 80}] }] } } - The previous curl command can be used to build a XPOST API call. There will be a lot of output, including the scheduler
and taints involved. Read through the output. In the last few lines the phase will probably show Pending, as it’s near the
beginning of the creation process.
student@lfs458-node-1a0a:~$ curl --cert ./client.pem \ --key ./client-key.pem --cacert ./ca.pem \ https://10.128.0.3:6443/api/v1/namespaces/default/pods \ -XPOST -H’Content-Type: application/json’ \ -d@curlpod.json { "kind": "Pod", "apiVersion": "v1", "metadata": { "name": "curlpod", <output_omitted> - Verify the new pod exists and shows a Running status.
student@lfs458-node-1a0a:~$ kubectl get pods NAME READY STATUS RESTARTS AGE curlpod 1/1 Running 0 45s
Exercise 5.2: Explore API Calls
- One way to view what a command does on your behalf is to use strace. In this case, we will look for the current
endpoints, or targets of our API calls.
student@lfs458-node-1a0a:~$ kubectl get endpoints NAME ENDPOINTS AGE kubernetes 10.128.0.3:6443 3h - Run this command again, preceded by strace. You will get a lot of output. Near the end you will note several openat
functions to a local directory, /home/student/.kube/cache/discovery/10.128.0.3_6443. If you cannot find the
lines, you may want to redirect all output to a file and grep for them.
student@lfs458-node-1a0a:~$ strace kubectl get endpoints execve("/usr/bin/kubectl", ["kubectl", "get", "endpoints"], [/*.... .... openat(AT_FDCWD, "/home/student/.kube/cache/discovery/10.128.0.3_6443.. <output_omitted> - Change to the parent directory and explore. Your endpoint IP will be different, so replace the following with one suited
to your system.
student@lfs458-node-1a0a:~$ cd /home/student/.kube/cache/discovery/ student@lfs458-node-1a0a:~/.kube/cache/discovery$ ls 10.128.0.3_6443 student@lfs458-node-1a0a:~/.kube/cache/discovery$ cd 10.128.0.3_6443/ - View the contents. You will find there are directories with various configuration information for kubernetes.
student@lfs458-node-1a0a:~/.kube/cache/discovery/10.128.0.3_6443$ ls admissionregistration.k8s.io batch policy apiextensions.k8s.io certificates.k8s.io rbac.authorization.k8s.io apiregistration.k8s.io coordination.k8s.io scheduling.k8s.io apps crd.projectcalico.org servergroups.json authentication.k8s.io events.k8s.io storage.k8s.io authorization.k8s.io extensions v1 autoscaling networking.k8s.io - Use the find command to list out the subfiles. The prompt has been modified to look better on this page.
student@lfs458-node-1a0a:./10.128.0.3_6443$ find . . ./events.k8s.io ./events.k8s.io/v1beta1 ./events.k8s.io/v1beta1/serverresources.json ./apps ./apps/v1 ./apps/v1/serverresources.json ./apps/v1beta1 ./apps/v1beta1/serverresources.json <output_omitted> - View the objects available in version 1 of the API. For each object, or kind:, you can view the verbs or actions for that
object, such as create seen in the following example. Note the prompt has been truncated for the command to fit on one
line. Some are HTTP verbs, such as GET, others are product specific options, not standard HTTP verbs.
student@lfs458-node-1a0a:.$ python -m json.tool v1/serverresources.json { "apiVersion": "v1", "groupVersion": "v1", "kind": "APIResourceList", "resources": [ { "kind": "Binding", "name": "bindings", "namespaced": true, "singularName": "", "verbs": [ "create" ] }, <output_omitted> - Some of the objects have shortNames, which makes using them on the command line much easier. Locate the
shortName for endpoints.
student@lfs458-node-1a0a:.$ python -m json.tool v1/serverresources.json | less . { "kind": "Endpoints", "name": "endpoints", "namespaced": true, "shortNames": [ "ep" ], "singularName": "", "verbs": [ "create", "delete", - Use the shortName to view the endpoints. It should match the output from the previous command.
student@lfs458-node-1a0a:.$ kubectl get ep NAME ENDPOINTS AGE kubernetes 10.128.0.3:6443 3h - We can see there are 37 objects in version 1 file.
student@lfs458-node-1a0a:.$ python -m json.tool v1/serverresources.json | grep kind "kind": "APIResourceList", "kind": "Binding", "kind": "ComponentStatus", "kind": "ConfigMap", "kind": "Endpoints", "kind": "Event", <output_omitted> - Looking at another file we find nine more.
student@lfs458-node-1a0a:$ python -m json.tool \ apps/v1beta1/serverresources.json | grep kind "kind": "APIResourceList", "kind": "ControllerRevision", "kind": "Deployment", <output_omitted> - Delete the curlpod to recoup system resources
student@lfs458-node-1a0a:$ kubectl delete po curlpod pod "curlpod" deleted - Take a look around the other files in this directory as time permits.
![]() |
