1. 程式人生 > >使用Kubernetes的java-client實現Deployment的部署及更新操作

使用Kubernetes的java-client實現Deployment的部署及更新操作

type 配置 mage 應對 ext ber 指定 查看 fault

1. 背景介紹

需求: 針對多種協議SDK構造探針,測試公司接入機服務狀況(每一個探針應對單一接入機,接入機數量可能會動態變化).
難點: 大多數協議SDK均不支持多實例運行,且部分SDK通過生成文件保存內部狀態;各協議SDK處於叠代狀態,不能對其進行魔改.
分析:

(1) 基於以上原因,無法選擇多線程或者多進程,在單一物理機或容器內完成探針相應功能;

(2) 嘗試通過Kubernetes部署探針容器,通過容器完成不同協議SDK的進程隔離乃至文件隔離;

(3) 通過Deployment設置容器環境參數的方式,給不同容器設置對應的啟動參數;

(4) Kubernetes控制程序通過Apollo動態獲取配置,更新相應協議的Deployment

,從而更新相關容器鏡像.

2. 依賴設置

pom文件中添加kubernetes以及apollo依賴:

        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>4.0.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.1.0</version>
        </dependency>

3. 部署Deployment

3.1 獲取api client

註意,此處我們使用ExtensionsV1beta1Api,對應api version: extensions/v1beta1.
在實際操作中,可以通過kubectl version獲取api server支持的版本.

        ApiClient client;
        try {
            client = Config.defaultClient();
        } catch (IOException ex) {
            log.error("get k8s default client failed, error: [{}]", ex.getMessage());
            throw new UserException(AppStatus.INTERNAL_SERVER_ERROR, "can not get k8s default client.");
        }
        Configuration.setDefaultApiClient(client);
        ExtensionsV1beta1Api api = new ExtensionsV1beta1Api(client);

3.2 創建Deployment

Deployment創建需要設置如下內容:

  • api version;
  • kind;
  • meta data;
  • spec info.

不熟悉以上元素的,可以查閱官方文檔,或者通過Kubernetes inAction一書了解.

        ExtensionsV1beta1Deployment edpDeployment = new ExtensionsV1beta1Deployment();
        edpDeployment.setApiVersion("extensions/v1beta1");
        edpDeployment.setKind("Deployment");
        edpDeployment.setMetadata(createDeploymentMeta(namespace, ProtocolType.EDP, config));
        edpDeployment.setSpec(createDeploymentSpec(ProtocolType.EDP, config));
        try {
            appsV1Api.createNamespacedDeployment(Common.INSPECTOR_NAMESPACE, edpDeployment, false, null, null);
        } catch (ApiException e) {
            log.error(e.getMessage());
        }

至此,可以通過kubectl相關命令查看Deployment的創建情況.

4. 更新Deployment

Deployment的更新操作比較晦澀,需要先構建ArrayList<JsonObject>存放更新操作以及相應數值(此處使用Gson),進而調用相應接口完成操作.

    /**
     * 構造Deployment的更新信息(json格式,需要指定操作類型,更新元素路徑,以及更新後的數值)
     * 此處,僅示範如何更新pod中第一個容器(filebeta)的鏡像ID
     * @return json信息
     */
    public ArrayList<JsonObject> getInspectorImagePatchElements() {
        // k8s java-client官方示例使用Gson
        Gson gson = new Gson();
        ArrayList<JsonObject> result = new ArrayList<>();
        // 更新Deployment中的filebeta容器鏡像ID
        DeploymentPatchJson patchJson = new DeploymentPatchJson("replace",
                "/spec/template/spec/containers/0/image", appConfig.geFilebetaImageId());
        result.add((gson.fromJson(gson.toJson(patchJson), JsonElement.class)).getAsJsonObject());
        return result;
    }

    /**
     * 更新指定的Deployment
     *
     */
    public void patchCurrentDeployment(ExtensionsV1beta1Api api, ExtensionsV1beta1Deployment deployment) {
        ArrayList<JsonObject> patchElements = inspectorService.getInspectorImagePatchElements();
        try {
            api.patchNamespacedDeployment(deployment.getMetadata().getName(),
                    deployment.getMetadata().getNamespace(), patchElements, "true", null);
        } catch (ApiException e) {
            log.error("patch deployment failed, error: [{}]", e.getMessage());
        }
    }

使用Kubernetes的java-client實現Deployment的部署及更新操作