when is kubectl proxy necessary?

3/14/2019

I am going through the second module of the Kubernetes tutorial and I'm confused about when kubectl proxy is necessary.

The reason I'm confused is, in the tutorial it was possible to create a Deployment (i.e. deploy a Docker image as a container in a pod) with the command kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080 before we ever setup a proxy. Deploying an image seems like it would require access to the nodes.

The tutorial says that "By default [pods, i.e. groups of containers] are visible from other pods and services within the same kubernetes cluster, but not outside that network." For this reason it instructs us to setup a proxy with kubectl proxy before we attempt to curl a pod directly (e.g. with curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/). Yet we were already able to deploy those pods without a proxy. It seems strange that we could deploy them but not query them.

Similarly, the tutorial also has us setup the proxy before we attempt to get the version using the Kubernetes API with curl http://localhost:8001/version (I believe localhost:8001 is the proxy). And yet, earlier we were able to query the version without a proxy using kubectl version, which returns the versions of both kubectl and Kubernetes on the master node.

Can anybody shed some light on these apparent contradictions?

-- Stephen
kubernetes

4 Answers

3/21/2019

When the proxy server is running, you can explore the kubernetes API using curl, wget, or a browser.

Get the API versions:

curl http://localhost:8080/api/

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.2.15:8443"
    }
  ]
}

Get a list of pods:

curl http://localhost:8080/api/v1/namespaces/default/pods

{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/default/pods",
    "resourceVersion": "33074"
  },
  "items": [
    {
      "metadata": {
        "name": "kubernetes-bootcamp-2321272333-ix8pt",
        "generateName": "kubernetes-bootcamp-2321272333-",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/pods/kubernetes-bootcamp-2321272333-ix8pt",
        "uid": "ba21457c-6b1d-11e6-85f7-1ef9f1dab92b",
        "resourceVersion": "33003",
        "creationTimestamp": "2016-08-25T23:43:30Z",
        "labels": {
          "pod-template-hash": "2321272333",
          "run": "kubernetes-bootcamp"
        },
        ...
}

Also, you can hit some k8s-service to check if service if actually connected to desired deployment/pods

http://localhost:8001/api/v1/namespaces/<namespace-name>/services/<service-name>:<service-port>/proxy/
-- Abu Hanifa
Source: StackOverflow

3/20/2019

I usually use kubectl proxy to query API Server. as given below

kubectl proxy --port=8001 &

curl 127.0.0.1:8001/version
curl 127.0.0.1:8001/metrics
curl 127.0.0.1:8001/api/v1/namespaces
curl 127.0.0.1:8001/api/v1/namespaces/kube-system
curl 127.0.0.1:8001/api/v1/namespaces/kube-system/services
curl 127.0.0.1:8001/api/v1/namespaces/kube-system/services/kube-dns
-- P Ekambaram
Source: StackOverflow

3/22/2019

when is kubectl proxy necessary?

When applications need to communicate to the API Server without implementing the security logic and cluster configuration within the applications.


It prevents the client applications of:

  • Implement the authentication logic
  • Having access to the security credentials(certificates)
  • Cluster information to be passed to the App, the proxy will handle connection and the app acts on localhost
  • Restrict access to certain API paths
  • Enforce a secure SSL connection between Client and Server
  • Revoke access at any time without revoking the certificates

Not to confuse the kubectl proxy with other proxies listed on the docs

-- Diego Mendes
Source: StackOverflow

3/16/2019

When running kubectl commands, the CLI is determining the address of the Kubernetes API server, the CA to verify the server's certificate against (to ensure you're talking to a trusted server and not some man-in-the-middle, say) and your client credentials from the kubeconfig file (to establish an encrypted, authenticated connection to the server with mTLS), which is in ~/.kube/config by default. You can cat that file in the tutorial to see what's in it:

$ cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /root/.minikube/ca.crt
    server: https://172.17.0.26:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: /root/.minikube/client.crt
    client-key: /root/.minikube/client.key

You can do the equivalent of what is happening in the tutorial without the proxy, as follows:

$ curl \
    --cacert /root/.minikube/ca.crt \
    --cert /root/.minikube/client.crt \
    --key /root/.minikube/client.key \
    https://172.17.0.26:8443/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-6bf84cb898-5gzp5 | v=1

You can see that after running the proxy command, the resulting curl command you need to run is simpler and more convenient:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/

You don't need to bother figuring out the address of the API server or dealing with all these certificates and keys, you just connect to localhost and the local proxy running there handles making the secure, authenticated connection to the API and proxies the response from the API server back to you.


Now, most interactions with the Kubernetes API that you need to do can be done directly via kubectl commands, it's rare that you need to curl the API directly. You see this when you issued the kubectl run or kubectl version command. In fact, you observed that you later found the version information via a curl, but you don't really need to do that since you can directly run kubectl version.

So you would probably only use kubectl proxy when you need to curl the Kubernetes API directly because there is no native kubectl command that lets you do what you want and when you prefer the convenience of not having that more complicated curl command with all the cert flags, etc.


Okay, but when do you really need to curl the API directly? Again, usually never. However, one thing the API does in addition to being a RESTful API for creating and deleting Kubernetes resources (pods, deployments, services, pvcs, etc.) is it serves as a proxy into the internal container network. Out-of-the-box, there's no way to send traffic to the container you ran in the tutorial, except for via the proxy endpoints provided by the Kubernetes API located at /api/v1/namespaces/default/pods/$POD_NAME/proxy/.

The StackOverflow question that you link to in the comment to your question has an accepted answer that explains several other ways to send traffic to the running containers. For a real-world application, you're likely to want to use something other than the proxy endpoints on the Kubernetes API server itself, but the proxy endpoints are a quick and easy way to interact over the network with a deployed container, so it might be something you want to do early on in your development lifecycle before setting up more robust and complex infrastructure to handle ingress traffic to your containers.


So putting it all together: when you have deployed a web application to Kubernetes and you would like to send requests to it and you don't (yet) want to set up some of the more complex but robust ways to get ingress traffic to your containers, you can use the container network proxy API located at /api/v1/namespaces/default/pods/$POD_NAME/proxy/ of the Kubernetes API server. There is no kubectl command that will hit that endpoint for you, so you have to curl it (or open it in a browser) directly. When you want to curl any Kuberentes server API endpoint directly and you don't want to pass a bunch of flags to your curl command, then running kubectl proxy allows you to run simpler curl commands directed at that local proxy that will proxy your requests to the Kubernetes API.


One final note, there are two completely different proxies going on here. One is the local proxy proxying your requests to any endpoint of the Kuberentes API server. One such (type of) endpoint that the Kubernetes API server has is itself a proxy into the internal network where containers are deployed. (Further still, there are proxies internal to the container network that make things work under the hood but to keep it simple, there's no need to discuss them in this answer). Don't get those two proxies confused.

-- Amit Kumar Gupta
Source: StackOverflow