使用Kubernetes客户端连接到OpenShift (Kubernetes)
首先
本次我要介紹的是Kubernetes官方提供的Javascript版本的Kubernetes客戶端。
上述的版本可以在Javascript或Typescript中使用,但也有支持Python、Go等語言的版本。
在某个应用中,我们正在寻找一个能够在OpenShift上获取各种资源的状态并进行创建/修改/删除操作的库。在尝试了这个Kubernetes客户端后,我们发现它在OpenShift上也能很好地使用,因此我们在这篇文章中向大家介绍一下。
虽然官方文档等已经整理得很好,但由于是英文,所以我们将在本文中进行说明!
通过阅读本文,您将能够理解Kubernetes客户端的引入和使用方法。
图书馆的使用方法 de
-
- 安装kubernetes-client模块
-
- 请执行以下命令。
-
- npm install @kubernetes/client-node
OpenShift集群连接设置
需要设置要连接的集群。
虽然可以按照README中所述将其转换为JavaScript并进行设置,但是我认为直接复制和使用kubeconfig文件更简单,因此本次介绍该方法。
由于kubeconfig文件的位置取决于使用的环境,请根据各自的方法下载并将其复制到适当的目录中。
此外,使用此方法,可以轻松实现根据文件名更改连接地址以适应多个环境的功能。
有关详细信息,请参考下一章中的示例代码。
通过示例代码确认能够成功连接到集群
请使用下一章中的示例代码确认能够顺利连接。
此外,官方还在examples目录下提供了示例供您参考。
确认所需实现方法的实现方式
通过查看src/gen目录下的swagger.json,您可以查看可用的API列表。
找到目标API后,请抽取出在实现时将使用的tags(例如:core_v1)和operationId(例如:deleteNamespacedPod)。
然后,只需参考示例代码,将makeApiClient(k8s.CoreV1)和k8s.deleteNamespacedPod(“<project名>”)进行修改即可。
※在OpenShift中,project相当于Kubernetes的namespace。
Kubernetes 客户端的示例代码
在Next.js(Typescript)的App Router中,我们将使用该库来发送API请求。如果在Next.js的App Router中实现,您可以在http://localhost/3000/api/<目录名>中查看API的返回值。
获取Kubernetes资源
通过使用 @kubernetes/client-node,可以获取k8s的本地资源(例如 Deployment 和 Namespace)的信息。
下面是使用k8s原生资源Pod获取信息的示例代码。
import { NextResponse } from "next/server";
import path from "path";
import * as k8s from "@kubernetes/client-node";
// 1. kubeconfig.yamlファイルの読み込みを行います。
// <project_root>/serverにkubeconfig.yamlファイルが配置されていることを想定しています。
const filePath = path.join(process.cwd(), "server", "kubeconfig.yaml");
export function GET() {
// 2. kubeConfigオブジェクトを作成します。
const kc = new k8s.KubeConfig();
kc.loadFromFile(filePath);
// 3. configを元にAPIリクエストを行うクライアントを作成します
const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
// 4. 対象とするnamespaceを定義します
const namespace = "default";
try {
// 5. 指定したnamespaceに存在するPodリソースを取得します
const response = await k8sApi.listNamespacedPod(namespace);
// 6. レスポンスを返します
return NextResponse.json({ body: response.body });
} catch (err) {
// 7. エラー処理を行います。
// 必要に応じてエラー処理を追加してください。
console.error(err);
return NextResponse.json({ err });
}
}
获取OpenShift特有资源的信息
通过使用 @kubernetes/client-node,不仅可以获取 k8s 的原生资源(如 Deployment 和 Namespace),还可以获取自定义资源。
以下是获取OpenShift特定资源(Route)信息的示例代码。
import { NextResponse } from "next/server";
import path from "path";
import * as k8s from "@kubernetes/client-node";
// 1. kubeconfig.yamlファイルの読み込みを行います
// <project_root>/serverにkubeconfig.yamlファイルが配置されていることを想定しています
const filePath = path.join(process.cwd(), "server", "kubeconfig.yaml");
export async function GET() {
// 2. kubeConfigオブジェクトを作成します
const kc = new k8s.KubeConfig();
kc.loadFromFile(filePath);
// 3. configを元にAPIリクエストを行うクライアントを作成します
const k8sApi = kc.makeApiClient(k8s.CustomObjectsApi);
// 4. 取得したいリソース名などを定義します
// リソース名を確認する方法は「補足」を参照ください
const resource = "route.openshift.io";
const version = "v1";
const resourcePlural = "routes"; // リソース名の複数形を指定します。「route」であれば「routes」になります。
const namespace = "openshift-console";
try {
// 5. 指定したnamespaceに存在するRouteリソースを取得します
const response = await k8sApi.listNamespacedCustomObject(
resource,
version,
namespace,
resourcePlural,
);
// 6. レスポンスを返します
return NextResponse.json({ body: response.body });
} catch (err) {
// 7. エラー処理を行います
// 必要に応じてエラー処理を追加してください
console.error(err);
return NextResponse.json({ err });
}
}
增加、填補、彌補
您可以通过以下任一方法在上述示例代码中检查自定义资源名称。
自定义资源定义(Custom Resource Definition)在以下CRD中表示。
-
- 列出集群中存在的CRD
-
- 在OpenShift集群中登录状态下,执行以下命令可以查看集群中存在的自定义资源列表。
-
- 但是,一些特定于OpenShift的资源可能不是以CRD形式实现的,而是作为API资源实现的。
-
- 在这种情况下,请尝试使用2. 列出集群中存在的API资源的命令来检查资源是否存在。
-
- $ kubectl get crds
-
- 或者
-
- $ oc get crds
列出集群中存在的API资源
在OpenShift集群中登录状态下,通过执行以下命令可以查看集群中存在的API资源列表。
$ kubectl api-resources
或者
$ oc api-resources
稍微调整了一下空间使其更易读,以下是查找route的示例。
示例执行
$ oc api-resources | grep route
名称 简称 API版本 命名空间 类型
egressrouters network.operator.openshift.io/v1 true EgressRouter
routes route.openshift.io/v1 true Route
使用清单文件创建/更新资源。
可以使用上述提供的API来创建资源等,也可以使用自己准备的清单文件来创建/更新/删除。
下面是一个应用路由(Route)的示例描述。
const routePath = path.join(process.cwd(), "server", 'route.yaml');
const client = k8s.KubernetesObjectApi.makeApiClient(getKubeConfig());
// 作成したいリソース名を指定します
// 実際は本関数の呼び出し元で指定するイメージ
const appDomain = "app-b";
const specRouteString = await fs.readFile(routePath, "utf8");
const specsRoute: k8s.KubernetesObject[] = yaml.loadAll(specRouteString);
const createRoute = async function(specs: k8s.KubernetesObject[]) {
for (const spec of specs) {
// without metadata out
spec.metadata = spec.metadata || {};
spec.metadata.annotations = spec.metadata.annotations || {};
delete spec.metadata.annotations[
"kubectl.kubernetes.io/last-applied-configuration"
];
spec.metadata.annotations[
"kubectl.kubernetes.io/last-applied-configuration"
] = JSON.stringify(spec);
spec.metadata.name = appDomain;
spec.spec.to.name = appDomain;
try {
await client.read(spec);
const response = await client.patch(spec);
created.push(response.body);
} catch (e) {
const response = await client.create(spec);
created.push(response.body);
}
}
}
await createRoute(specsRoute);
路由.yaml的示例
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: app-a
namespace: turbo
annotations:
haproxy.router.openshift.io/timeout: 3m
spec:
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect
to:
kind: Service
name: app-a
weight: 100
附加内容:在处理Pod状态时需要注意的要点。
我有一个情况,想要在Pod停机时确认状态是否发生了变化,但是在状态的返回值中却返回了”running”。
我使用OpenShift管理控制台或oc get pods进行检索,发现它处于”terminating”状态,所以我尝试从其他返回值中找出是否为”terminating”。
runningと表示されてしまう原因は、Pod LifeCycleにある通り、Podのステータスにはterminatingは含まれないからです。
代替手段として、metadata.deletionTimestampが表示されることが分かりましたので、こちらで判別してAPIを返却するといいと思います。
参考記事
最後に
因为这次介绍的只是其中的一小部分,所以如果您感兴趣的话,请务必亲自尝试一下。
余談ではありますが、OpenShift用のClientライブラリを作成している方がいるようなので、気になる方はこちらも確認してみてください。
本文是与石井一起合作撰写的。