Accessing The Kubernetes API, sans The Proxy
For various reasons, I wanted to access the Kubernetes API from outside of the cluster, but I didn’t want to (couldn’t) use kubectl proxy
which is the easiest and recommended in various forums.
Here’s my memo. This is on Kubernetes 1.7, and please let me know if there are mistakes.
Where’s the Kubernetes API?
$ kubectl get endpoints | grep kubernetes
This will give you an IP address and a port number like 1.2.3.4:443
.
How Does One Access The API?
There are various ways, but I find the way using Service Accounts the most straight forward.
Basically, you create a Service Account on the Kubernetes Cluster, and find the JWT that is associated with this account. Then you include that in the Authorization HTTP header.
Create The Account
$ kubectl create serviceaccount my-service-account
Be sure to change my-service-account
to something more useful.
Find The Associated Secret
There are various ways to do this, but here I’m going to use jq.
$ kubectl get serviceaccount my-service-account -o json | jq -Mr '.secrets[].name'
This will give you the name of the secret
that contains the relevant information. Use that name to find the corresponding JWT.
$ kubectl get secrets $name-of-the-secret -o json | jq -Mr '.data.token' | base64 -D
The base64
bit is necessary, as secrets will be base64 encoded.
Using Curl (Attempt #1)
The token that you got in the previous step should be passed to the API via the “Authorization” header. Given the Kubernetes API server 1.2.3.4:443
, you would do:
$ curl https://1.2.3.4 -H "Authorization: Bearer $jwt-token"
This is almost right, but you probably got curl screaming at you saying something along the lines of:
curl: (60) SSL certificate problem: Invalid certificate chain
Well, duh. You either need use the --insecure
flag, or provide a CA certificate file. If you are in a hurry, and you know for sure — I mean, absolutely sure — that you are accessing the correct server, it’s okay to use the --insecure
flag. But don’t put it in any script, that’s just silly.
Using Curl (Attempt #2)
In order to fix the certificate problem properly, you need to get the CA certificate that Kubernetes provides you. Luckily, this can be obtained in almost the same way we obtained the JWT. Drum rolls… it’s in the same secret
as the JWT.
$ kubectl get secrets $name-of-the-secret -o json | jq -Mr '.data["ca.crt"]' | base64 -D > ca.crt
This will allow you to save the CA certificate in a file called ca.crt
. Now you just need to give curl the appropriate flags:
curl https://1.2.3.4 --cacert ca.crt -H "Authorization: Bearer $jwt-token"
Voila, you should start seeing something. Navigate to the desired API.