Kubernetes-Client-C

KubernetesC-SDK

https://github.com/kubernetes-client/c
告诉编译器:

“这些函数是 C 写的,别给它们加花哨的 C++ 名字修饰,用纯 C 风格导出。”

extern "C" {
#include <kubernetes/config/kube_config.h>
#include <kubernetes/api/CoreV1API.h>
}

结构体之间的关系

image-20251014213300727

这套结构的目的是:
让不同类型的 Kubernetes 对象(Pod、Service、Namespace等)都能用统一的链表容器 list_t 来保存,从而方便解析与遍历。

  • v1_pod_list_t 只是“某一类对象”的容器(这里是 Pod)

  • list_t通用链表容器

  • listEntry_t 是链表节点结构


​ 1️⃣ v1_pod_list_t

typedef struct v1_pod_list_t {
    char *api_version;          // 版本,如 "v1"
    list_t *items;              // 这里是一个链表,存放多个 v1_pod_t 对象
    char *kind;                 // 类型,如 "PodList"
    struct v1_list_meta_t *metadata; // 元数据,如继续分页的 token
    int _library_owned;         // 标记内存是否由库管理
} v1_pod_list_t;


​ 2️⃣ list_t(链表头)

typedef struct list_t {
    listEntry_t *firstEntry;  // 第一个节点
    listEntry_t *lastEntry;   // 最后一个节点
    long count;               // 节点数量
} list_t;

​ 3️⃣ listEntry_t(链表节点)

typedef struct listEntry_t {
    listEntry_t *nextListEntry;  // 指向下一个节点
    listEntry_t *prevListEntry;  // 指向上一个节点
    void *data;                  // 指向实际数据(这里是 v1_pod_t*)
} listEntry_t;

遍历宏的设计

#define list_ForEach(element, list) \
    for (element = (list != NULL) ? (list)->firstEntry : NULL; \
         element != NULL; \
         element = element->nextListEntry)

等价写法:

listEntry_t *element = list->firstEntry;
while (element != NULL) {
    ...
    element = element->nextListEntry;
}

Creating API Clients

常见的连接方式有两种

  1. 从kubeconfig 文件和使用集群内置配置,这是在 Kubernetes 集群之外运行应用程序时最常见的方法:

image-20251015085656866

// Initialize variables
char *basePath = NULL;
sslConfig_t *sslConfig = NULL;
list_t *apiKeys = NULL;
apiClient_t *apiClient = NULL;

// Load configuration from kubeconfig file (typically ~/.kube/config)
int rc = load_kube_config(&basePath, &sslConfig, &apiKeys, NULL);
if (rc != 0) {
    // Handle error
    return -1;
}

// Create API client with loaded configuration
apiClient = apiClient_create_with_base_path(basePath, sslConfig, apiKeys);
if (!apiClient) {
    // Handle error
    return -1;
}

// Use the API client...

// Clean up resources
apiClient_free(apiClient);
free_client_config(basePath, sslConfig, apiKeys);
apiClient_unsetupGlobalEnv();
  1. 使用集群内配置,在 Kubernetes Pod 中运行时,可以使用集群内配置,该配置会自动检测和使用服务帐户令牌

image-20251015085825038

// Initialize variables
char *basePath = NULL;
sslConfig_t *sslConfig = NULL;
list_t *apiKeys = NULL;
apiClient_t *apiClient = NULL;

// Load in-cluster configuration
int rc = load_incluster_config(&basePath, &sslConfig, &apiKeys);
if (rc != 0) {
    // Handle error
    return -1;
}

// Create API client with loaded configuration
apiClient = apiClient_create_with_base_path(basePath, sslConfig, apiKeys);
if (!apiClient) {
    // Handle error
    return -1;
}

// Use the API client...

// Clean up resources
apiClient_free(apiClient);
free_client_config(basePath, sslConfig, apiKeys);
apiClient_unsetupGlobalEnv();
  • basePath: The base URL of the Kubernetes API server
    basePath:Kubernetes API 服务器的基本 URL
  • sslConfig: SSL/TLS configuration for secure connections
    sslConfig:用于安全连接的 SSL/TLS 配置
  • dataReceived: Buffer containing the response data
    dataReceived:包含响应数据的缓冲区
  • dataReceivedLen: Length of the received data
    dataReceivedLen:接收数据的长度
  • response_code: HTTP response code from the last request
    response_code:上次请求的 HTTP 响应代码
  • apiKeys_BearerToken: Authentication tokens for the API server
    apiKeys_BearerToken:API 服务器的身份验证令牌

面向对象设计

#include <iostream>
#include <string>

extern "C"
{
#include <kubernetes/config/kube_config.h>
#include <kubernetes/api/CoreV1API.h>
}

using namespace std;

struct kube_params_t
{
    char *_basePath;
    sslConfig_t *_sslConfig;
    list_t *_apiKeys;

    kube_params_t() : _basePath(nullptr), _sslConfig(nullptr), _apiKeys(nullptr) {}
    ~kube_params_t()
    {
        if (_basePath || _sslConfig || _apiKeys)
        {
            free_client_config(_basePath, _sslConfig, _apiKeys);
            _basePath = nullptr;
            _sslConfig = nullptr;
            _apiKeys = nullptr;
        }
    }
};

class K8sCluster
{
private:
    kube_params_t *_params;
    apiClient_t *_apiClient;
    bool _connected;

    void initClient()
    {
        int rc = load_kube_config(&_params->_basePath, &_params->_sslConfig, &_params->_apiKeys, nullptr);
        if (rc != 0)
        {
            cerr << "Cannot to connected k8s" << endl;
            return;
        }
        _apiClient = apiClient_create_with_base_path(_params->_basePath, _params->_sslConfig, _params->_apiKeys);
        if (!_apiClient)
        {
            cerr << "Create apiclient Failed" << endl;
            return;
        }
        _connected = true;
    }

public:
    K8sCluster() : _params(new kube_params_t), _apiClient(nullptr), _connected(false) { initClient(); }

    K8sCluster(kube_params_t *params) : _params(params), _apiClient(nullptr), _connected(false)
    {
        if (_params)
        {
            initClient();
        }
    }

    ~K8sCluster()
    {
        apiClient_free(_apiClient);
        delete _params;
    }

    void list_pod(const char *);
    bool isConnected() const { return _connected; }
};

void K8sCluster::list_pod(const char *ns)
{
    if (!_apiClient)
    {
        printf("[-] apiClient is null, cannot list pods.\n");
        return;
    }

    v1_pod_list_t *pod_list = CoreV1API_listNamespacedPod(
        _apiClient, (char *)ns, nullptr, nullptr, nullptr,
        nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
        nullptr, nullptr);

    printf("HTTP response code = %ld\n", _apiClient->response_code);

    if (!pod_list)
    {
        printf("Cannot get any pod.\n");
        return;
    }

    listEntry_t *listEntry = nullptr;
    v1_pod_t *pod = nullptr;

    list_ForEach(listEntry, pod_list->items)
    {
        pod = static_cast<v1_pod_t *>(listEntry->data);
        if (pod && pod->metadata && pod->metadata->name)
            printf("  Pod: %s Namespace: %s\n", pod->metadata->name, pod->metadata->_namespace);
    }

    v1_pod_list_free(pod_list);
}

int main()
{
    kube_params_t *params = new kube_params_t;
    K8sCluster info(params);
    const char *ns = "kube-system";
    info.list_pod(ns);
    apiClient_unsetupGlobalEnv();
    return 0;
}

CMake 编译文件配置

cmake_minimum_required(VERSION 3.16.3)
project(k8scon)
set(CXX_STANDARD 11)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 如果 include 不在默认路径,还要加上
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
add_executable(case case1.cc)
# 如果库在 /usr/local/lib 下
target_link_libraries(case
    kubernetes           # <-- 核心 SDK
    curl                 # SDK 使用 libcurl
    ssl                  # OpenSSL
    crypto               # OpenSSL
    pthread              # 网络请求线程安全
)
posted @ 2025-11-03 17:45  loca7h9st  阅读(10)  评论(0)    收藏  举报