使用 Kubernetes API 访问集群是一种常见的操作,它可以帮助我们管理和监控 Kubernetes 集群。通过 Kubernetes API,我们可以执行各种任务,如创建、更新和删除资源,以及查询集群状态等。本篇教程将介绍如何使用 Kubernetes API 访问集群。
一、准备
必须拥有一个 Kubernetes 的集群,同时必须配置 kubectl 命令行工具与集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果还没有集群,可以通过 Minikube 构建一个自己的集群,或者可以使用下面的 Kubernetes 练习环境之一:
- Killercoda
- 玩转 Kubernetes
要获知版本信息,请输入 kubectl version.
二、访问Kubernetes API
1、使用 kubectl 进行首次访问
首次访问 Kubernetes API 时,请使用 Kubernetes 命令行工具 kubectl 。
要访问集群,需要知道集群位置并拥有访问它的凭证。使用此命令检查 kubectl 已知的位置和凭证:
kubectl config view
2、直接访问REST API
kubectl 处理对 API 服务器的定位和身份验证。如果想通过 http 客户端(如 curl 或 wget, 或浏览器)直接访问 REST API,可以通过多种方式对 API 服务器进行定位和身份验证:
- 以代理模式运行 kubectl(推荐)。 推荐使用此方法,因为它用存储的 apiserver 位置并使用自签名证书验证 API 服务器的标识。 使用这种方法无法进行中间人(MITM)攻击;
- 另外,可以直接为 HTTP 客户端提供位置和身份认证。 这适用于被代理混淆的客户端代码。 为防止中间人攻击,需要将根证书导入浏览器。
使用 Go 或 Python 客户端库可以在代理模式下访问 kubectl。
3、使用kubectl代理
下列命令使 kubectl 运行在反向代理模式下。它处理 API 服务器的定位和身份认证。
像这样运行它:
kubectl proxy --port=8080 &
然后可以通过 curl,wget,或浏览器浏览 API,像这样:
curl http://localhost:8080/api/
输出类似如下:
{ "versions": [ "v1" ], "serverAddressByClientCIDRs": [ { "clientCIDR": "0.0.0.0/0", "serverAddress": "10.0.1.149:443" } ] }
4、不使用kubectl代理
通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理,像这样:
使用 grep/cut 方式:
<code class="language-shell" data-lang="shell"># 查看所有的集群,因为你的 .kubeconfig 文件中可能包含多个上下文 kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}' # 从上述命令输出中选择你要与之交互的集群的名称 export CLUSTER_NAME="some_server_name" # 指向引用该集群名称的 API 服务器 APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") # 创建一个 secret 来保存默认服务账户的令牌 kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: default-token annotations: kubernetes.io/service-account.name: default type: kubernetes.io/service-account-token EOF # 等待令牌控制器使用令牌填充 secret: while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do echo "waiting for token..." >&2 sleep 1 done # 获取令牌 TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode) # 使用令牌玩转 API 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" } ] }
上面例子使用了 –insecure 标志位。这使它易受到 MITM 攻击。 当 kubectl 访问集群时,它使用存储的根证书和客户端证书访问服务器。 (已安装在 ~/.kube 目录下)。 由于集群认证通常是自签名的,因此可能需要特殊设置才能让 http 客户端使用根证书。
在一些集群中,API 服务器不需要身份认证;它运行在本地,或由防火墙保护着。 对此并没有一个标准。 配置对 API 的访问 讲解了作为集群管理员可如何对此进行配置。
5、编程方式访问API
Kubernetes 官方支持 Go、Python、Java、 dotnet、JavaScript 和 Haskell 语言的客户端库。还有一些其他客户端库由对应作者而非 Kubernetes 团队提供并维护。
(1)Go 客户端
要获取库,运行下列命令:go get k8s.io/client-go/kubernetes-<kubernetes 版本号>;基于 client-go 客户端编写应用程序。client-go 定义了自己的 API 对象,因此如果需要,从 client-go 而不是主仓库导入 API 定义,例如 import “k8s.io/client-go/kubernetes” 是正确做法。
Go 客户端可以使用与 kubectl 命令行工具相同的 kubeconfig 文件定位和验证 API 服务器。参见这个例子:
package main import ( "context" "fmt" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" ) func main() { // 在 kubeconfig 中使用当前上下文 // path-to-kubeconfig -- 例如 /root/.kube/config config, _ := clientcmd.BuildConfigFromFlags("", "<path-to-kubeconfig>") // 创建 clientset clientset, _ := kubernetes.NewForConfig(config) // 访问 API 以列出 Pod pods, _ := clientset.CoreV1().Pods("").List(context.TODO(), v1.ListOptions{}) fmt.Printf("There are %d pods in the cluster\n", len(pods.Items)) }
(2)Python客户端
要使用 Python 客户端,运行下列命令: pip install kubernetes。
Python 客户端可以使用与 kubectl 命令行工具相同的 kubeconfig 文件 定位和验证 API 服务器。参见这个 例子:
<code class="language-python" data-lang="python">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))
(3)Java客户端
要安装 Java 客户端,运行:
<code class="language-shell" data-lang="shell"># 克隆 Java 库 git clone --recursive https://github.com/kubernetes-client/java # 安装项目文件、POM 等 cd java mvn install
Java 客户端可以使用 kubectl 命令行所使用的 kubeconfig 文件 以定位 API 服务器并向其认证身份。 参看此示例:
<code class="language-java" data-lang="java">package io.kubernetes.client.examples; import io.kubernetes.client.ApiClient; import io.kubernetes.client.ApiException; import io.kubernetes.client.Configuration; import io.kubernetes.client.apis.CoreV1Api; import io.kubernetes.client.models.V1Pod; import io.kubernetes.client.models.V1PodList; import io.kubernetes.client.util.ClientBuilder; import io.kubernetes.client.util.KubeConfig; import java.io.FileReader; import java.io.IOException; /** * A simple example of how to use the Java API from an application outside a kubernetes cluster * * <p>Easiest way to run this: mvn exec:java * -Dexec.mainClass="io.kubernetes.client.examples.KubeConfigFileClientExample" * */ public class KubeConfigFileClientExample { public static void main(String[] args) throws IOException, ApiException { // file path to your KubeConfig String kubeConfigPath = "~/.kube/config"; // loading the out-of-cluster config, a kubeconfig from file-system ApiClient client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build(); // set the global default api-client to the in-cluster one from above Configuration.setDefaultApiClient(client); // the CoreV1Api loads default api-client from global configuration. CoreV1Api api = new CoreV1Api(); // invokes the CoreV1Api client V1PodList list = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null); System.out.println("Listing all pods: "); for (V1Pod item : list.getItems()) { System.out.println(item.getMetadata().getName()); } } }
(4).Net 客户端
要使用.Net 客户端,运行下面的命令: dotnet add package KubernetesClient –version 1.6.1。
.Net 客户端可以使用与 kubectl CLI 相同的 kubeconfig 文件 来定位并验证 API 服务器。 参见样例:
<code class="language-csharp" data-lang="csharp">using System; using k8s; namespace simple { internal class PodList { private static void Main(string[] args) { var config = KubernetesClientConfiguration.BuildDefaultConfig(); IKubernetes client = new Kubernetes(config); Console.WriteLine("Starting Request!"); var list = client.ListNamespacedPod("default"); foreach (var item in list.Items) { Console.WriteLine(item.Metadata.Name); } if (list.Items.Count == 0) { Console.WriteLine("Empty!"); } } } }
(5)JavaScript 客户端
要安装 JavaScript 客户端,运行下面的命令: npm install @kubernetes/client-node。
JavaScript 客户端可以使用 kubectl 命令行所使用的 kubeconfig 文件 以定位 API 服务器并向其认证身份。 参见此例:
<code class="language-javascript" data-lang="javascript">const k8s = require('@kubernetes/client-node'); const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); k8sApi.listNamespacedPod('default').then((res) => { console.log(res.body); });
(6)Haskell 客户端
Haskell 客户端 可以使用 kubectl 命令行所使用的 kubeconfig 文件 以定位 API 服务器并向其认证身份。 参见此例:
<code class="language-haskell" data-lang="haskell">exampleWithKubeConfig :: IO () exampleWithKubeConfig = do oidcCache <- atomically $ newTVar $ Map.fromList [] (mgr, kcfg) <- mkKubeClientConfig oidcCache $ KubeConfigFile "/path/to/kubeconfig" dispatchMime mgr kcfg (CoreV1.listPodForAllNamespaces (Accept MimeJSON)) >>= print