Edit This Page

使用 Kubernetes API 访问集群

本页展示了如何使用 Kubernetes API 访问集群

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

要获知版本信息,请输入 kubectl version.

访问集群 API

使用 kubectl 进行首次访问

首次访问 Kubernetes API 时,请使用 Kubernetes 命令行工具 kubectl

要访问集群,您需要知道集群位置并拥有访问它的凭证。通常,当您完成入门指南时,这会自动设置完成,或者由其他人设置好集群并将凭证和位置提供给您。

使用此命令检查 kubectl 已知的位置和凭证:

kubectl config view

许多样例提供了使用 kubectl 的介绍。完整文档请见 kubectl 手册

直接访问 REST API

kubectl 处理对 API 服务器的定位和身份验证。如果您想通过 http 客户端(如 curlwget,或浏览器)直接访问 REST API,您可以通过多种方式对 API 服务器进行定位和身份验证:

  1. 以代理模式运行 kubectl(推荐)。 推荐使用此方法,因为它用存储的 apiserver 位置并使用自签名证书验证 API 服务器的标识。使用这种方法无法进行中间人(MITM)攻击。
  2. 另外,您可以直接为 http 客户端提供位置和身份认证。这适用于被代理混淆的客户端代码。为防止中间人攻击,您需要将根证书导入浏览器。

使用 Go 或 Python 客户端库可以在代理模式下访问 kubectl。

使用 kubectl 代理

下列命令使 kubectl 运行在反向代理模式下。它处理 API 服务器的定位和身份认证。

像这样运行它:

kubectl proxy --port=8080 &

参见 kubectl 代理 获取更多细节。

然后您可以通过 curl,wget,或浏览器浏览 API,像这样:

curl http://localhost:8080/api/

输出类似如下:

{
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

不使用 kubectl 代理

通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理,像这样:

使用 grep/cut 方式:

# Check all possible clusters, as you .KUBECONFIG may have multiple contexts:
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

# Select name of cluster you want to interact with from above output:
export CLUSTER_NAME="some_server_name"

# Point to the API server refering the cluster name
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")

# Gets the token value
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 -d)

# Explore the API with TOKEN
curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

输出类似如下:

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

使用 jsonpath 方式:

$ APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
$ TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

上面例子使用了 --insecure 标志位。这使它易受到 MITM 攻击。当 kubectl 访问集群时,它使用存储的根证书和客户端证书访问服务器。(已安装在 ~/.kube 目录下)。由于集群认证通常是自签名的,因此可能需要特殊设置才能让你的 http 客户端使用根证书。

在一些集群中,API 服务器不需要身份认证;它运行在本地,或由防火墙保护着。对此并没有一个标准。配置对 API 的访问 阐述了一个集群管理员如何对此进行配置。这种方法可能与未来的高可用性支持发生冲突。

编程方式访问 API

Kubernetes 官方支持 GoPython 的客户端库.

Go 客户端

  • 要获取库,运行下列命令:go get k8s.io/client-go/<version number>/kubernetes 参见 https://github.com/kubernetes/client-go 查看受支持的版本。
  • 基于 client-go 客户端编写应用程序。注意 client-go 定义了自己的 API 对象,因此如果需要,请从 client-go 而不是主仓库导入 API 定义,例如 import "k8s.io/client-go/1.4/pkg/api/v1" 是正确做法。

Go 客户端可以使用与 kubectl 命令行工具相同的 kubeconfig 文件 定位和验证 API 服务器。参见这个 例子

import (
   "fmt"
   "k8s.io/client-go/1.4/kubernetes"
   "k8s.io/client-go/1.4/pkg/api/v1"
   "k8s.io/client-go/1.4/tools/clientcmd"
)
...
   // uses the current context in kubeconfig
   config, _ := clientcmd.BuildConfigFromFlags("", "path to kubeconfig")
   // creates the clientset
   clientset, _:= kubernetes.NewForConfig(config)
   // access the API to list pods
   pods, _:= clientset.CoreV1().Pods("").List(v1.ListOptions{})
   fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
...

如果该应用程序部署为集群中的一个 Pod,请参阅 下一节

Python 客户端

要使用 Python 客户端,运行下列命令:pip install kubernetes 参见 Python 客户端库主页 查看更多安装选项。

Python 客户端可以使用与 kubectl 命令行工具相同的 kubeconfig 文件 定位和验证 API 服务器。参见这个 例子

from kubernetes import client, config

config.load_kube_config()

v1=client.CoreV1Api()
print("Listing pods with their IPs:")
ret = v1.list_pod_for_all_namespaces(watch=False)
for i in ret.items:
    print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))

其他语言

有许多 客户端库 可以用于从其他语言访问 API。请参阅其他库的文档了解它们的身份验证方式。

从 Pod 中访问 API

从 Pod 访问 API 时,对 API 服务器的定位和身份验证会有所不同。

从 Pod 使用 Kubernetes API 的最简单的方法就是使用一个官方的 客户端库。这些库可以自动发现 API 服务器并进行身份验证。

在运行在 Pod 中时,可以通过 default 命名空间中的名为 kubernetes 的服务访问 Kubernetes apiserver。也就是说,Pods 可以使用 kubernetes.default.svc 主机名来查询 API 服务器。官方客户端库自动完成这个工作。

从一个 Pod 内,向 API 服务器进行身份认证的推荐的做法是使用 服务账号 凭证。默认的,一个 Pod 与一个服务账号关联,该服务账户的凭证(令牌)放置在此 Pod 中每个容器的文件系统树中的 /var/run/secrets/kubernetes.io/serviceaccount/token 处。

如果可用,凭证包被放入每个容器的文件系统树中的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 处,并且将被用于验证 API 服务器的服务证书。

最后,用于命名空间 API 操作的默认的命名空间放置在每个容器中的 /var/run/secrets/kubernetes.io/serviceaccount/namespace 文件中。

从一个 Pod 内,连接 Kubernetes API 的推荐方法是:

  • 使用官方的 客户端库 因为他们会自动地完成 API 主机发现和身份认证。以 Go 客户端来说,rest.InClusterConfig() 可以帮助解决这个问题。参见 这里的一个例子
  • 如果您想要在没有官方客户端库的情况下查询 API,可以在 Pod 里以一个新的边车容器的 命令的方式运行 kubectl proxy 。此方式下,kubectl proxy 将对 API 进行身份验证并将其公开在 Pod 的 localhost 接口上,以便 Pod 中的其他容器可以直接使用它。

在每种情况下,Pod 的服务账号凭证被用于与 API 服务器的安全通信。