拉丁家 發表於 2019-5-14 18:49:00

使用Kubernetes的java-client实现Deployment的部署及更新操作

<h1 id="1-背景介绍">1. 背景介绍</h1>
<p>需求: 针对多种协议<code>SDK</code>构造探针,测试公司接入机服务状况(每一个探针应对单一接入机,接入机数量可能会动态变化).<br>
难点: 大多数协议<code>SDK</code>均不支持多实例运行,且部分<code>SDK</code>通过生成文件保存内部状态;各协议<code>SDK</code>处于迭代状态,不能对其进行魔改.<br>
分析:<br>
(1) 基于以上原因,无法选择多线程或者多进程,在单一物理机或容器内完成探针相应功能;<br>
(2) 尝试通过<code>Kubernetes</code>部署探针容器,通过容器完成不同协议<code>SDK</code>的进程隔离乃至<code>文件隔离</code>;<br>
(3) 通过<code>Deployment</code>设置容器<code>环境参数</code>的方式,给不同容器设置对应的启动参数;<br>
(4) <code>Kubernetes</code>控制程序通过<code>Apollo</code>动态获取配置,更新相应协议的<code>Deployment</code>,从而更新相关容器镜像.</p>
<h1 id="2-依赖设置">2. 依赖设置</h1>
<p><code>pom</code>文件中添加<code>kubernetes</code>以及<code>apollo</code>依赖:</p>
<pre><code class="language-shell">      &lt;dependency&gt;
            &lt;groupId&gt;io.kubernetes&lt;/groupId&gt;
            &lt;artifactId&gt;client-java&lt;/artifactId&gt;
            &lt;version&gt;4.0.0&lt;/version&gt;
            &lt;scope&gt;compile&lt;/scope&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;com.ctrip.framework.apollo&lt;/groupId&gt;
            &lt;artifactId&gt;apollo-client&lt;/artifactId&gt;
            &lt;version&gt;1.1.0&lt;/version&gt;
      &lt;/dependency&gt;
</code></pre>
<h1 id="3-部署deployment">3. 部署<code>Deployment</code></h1>
<h2 id="31-获取api-client">3.1 获取<code>api client</code></h2>
<p>注意,此处我们使用<code>ExtensionsV1beta1Api </code>,对应<code>api version: extensions/v1beta1</code>.<br>
在实际操作中,可以通过<code>kubectl version</code>获取<code>api server</code>支持的版本.</p>
<pre><code class="language-java">      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);
</code></pre>
<h2 id="32-创建deployment">3.2 创建<code>Deployment</code></h2>
<p><code>Deployment</code>创建需要设置如下内容:</p>
<ul>
<li><code>api version</code>;</li>
<li><code>kind</code>;</li>
<li><code>meta data</code>;</li>
<li><code>spec info</code>.</li>
</ul>
<p>不熟悉以上元素的,可以查阅<em>官方文档</em>,或者通过<em><code>Kubernetes inAction</code></em>一书了解.</p>
<pre><code class="language-java">      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());
      }
</code></pre>
<p>至此,可以通过<code>kubectl</code>相关命令查看<code>Deployment</code>的创建情况.</p>
<h1 id="4-更新deployment">4. 更新<code>Deployment</code></h1>
<p><code>Deployment</code>的更新操作比较晦涩,需要先构建<code>ArrayList&lt;JsonObject&gt;</code>存放更新操作以及相应数值(此处使用<code>Gson</code>),进而调用相应接口完成操作.</p>
<pre><code class="language-java">    /**
   * 构造Deployment的更新信息(json格式,需要指定操作类型,更新元素路径,以及更新后的数值)
   * 此处,仅示范如何更新pod中第一个容器(filebeta)的镜像ID
   * @return json信息
   */
    public ArrayList&lt;JsonObject&gt; getInspectorImagePatchElements() {
      // k8s java-client官方示例使用Gson
      Gson gson = new Gson();
      ArrayList&lt;JsonObject&gt; result = new ArrayList&lt;&gt;();
      // 更新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&lt;JsonObject&gt; 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());
      }
    }
</code></pre>
<h1 id="5-手动更新deployment">5. 手动更新<code>Deployment</code></h1>
<p>(1) <code>kubectl</code>仿照调用<code>api</code></p>
<pre><code class="language-shell">kubectl patch deployment your_deployment -p \
'{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":31}}}}'
</code></pre>
<p>(2) 通过<code>HTTP</code>请求</p>
<pre><code>curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \
http://k8s-master:8080/api/v1/nodes/k8s-node-1/status
</code></pre>
<p>(3) <code>kubectl</code>设置</p>
<p>带*信息,请根据实际情况进行替换.</p>
<pre><code class="language-shell">kubectl set image deployment/composer app=hub.***.com/online/composer:pro2019051602 --context=devops* -n qos*
</code></pre>
<p>(4) 直接编辑<code>Deployment</code></p>
<pre><code class="language-shell">kubectl edit deployment composer -n qos* --context=devops*
</code></pre>
<blockquote>
<p>PS:<br>
如果您觉得我的文章对您有帮助,请关注我的个人博客网站<br>
本文同步发布于个人博客网站,《使用Kubernetes的java-client实现Deployment的部署及更新操作》。</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/jason1990/p/10862666.html
頁: [1]
查看完整版本: 使用Kubernetes的java-client实现Deployment的部署及更新操作