<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>knative | 伪架构师</title>
    <link>/tags/knative/</link>
      <atom:link href="/tags/knative/index.xml" rel="self" type="application/rss+xml" />
    <description>knative</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Tue, 16 Apr 2019 03:38:07 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>knative</title>
      <link>/tags/knative/</link>
    </image>
    
    <item>
      <title>Google Cloud Run 一瞥</title>
      <link>/post/a-first-look-at-google-cloud-run/</link>
      <pubDate>Tue, 16 Apr 2019 03:38:07 +0800</pubDate>
      <guid>/post/a-first-look-at-google-cloud-run/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://thenewstack.io/a-first-look-at-google-cloud-run/&#34; target=&#34;_blank&#34;&gt;A First Look at Google Cloud Run&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://thenewstack.io/author/marko-anastasov/&#34; target=&#34;_blank&#34;&gt;Marko Anastasov&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google 在 &lt;a href=&#34;https://cloud.withgoogle.com/next/sf&#34; target=&#34;_blank&#34;&gt;Cloud Next&amp;rsquo;19&lt;/a&gt; 上发布了基于 Docker 容器的的 Serverless 新方案。目前可以肯定的是，这是 Serverless 的重要进步——在 Cloud Run 上进行部署比在 Kubernetes 上运行容器简单多了。而且和 Lambda 不同，这一方案没有语言绑定的问题。&lt;/p&gt;

&lt;h2 id=&#34;什么是-google-cloud-run&#34;&gt;什么是 Google Cloud Run&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/run/&#34; target=&#34;_blank&#34;&gt;Google Cloud Run&lt;/a&gt; 是一个全托管平台，它以无状态、自动伸缩的 HTTP 服务的形式运行 Docker 容器镜像。&lt;/p&gt;

&lt;p&gt;Cloud Run 和第一代 Serverless 平台（例如 AWS Lambda、&lt;a href=&#34;https://cloud.google.com/functions/&#34; target=&#34;_blank&#34;&gt;Google Cloud functions&lt;/a&gt; 或 Azure Functions）不同，它允许你运行任意的应用，提供多个端点；而无需使用特定接口来运行小规模的函数。&lt;/p&gt;

&lt;p&gt;Cloud Run 的基础来自于 &lt;a href=&#34;https://www.knative.dev/&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt;，因此这一方案有可能被移植到其它的托管 Kubernetes 平台。&lt;/p&gt;

&lt;h2 id=&#34;我的项目能够在-google-cloud-run-上运行么&#34;&gt;我的项目能够在 Google Cloud Run 上运行么？&lt;/h2&gt;

&lt;p&gt;Google 发表了 &lt;a href=&#34;https://cloud.google.com/run/docs/reference/container-contract&#34; target=&#34;_blank&#34;&gt;容器运行时契约&lt;/a&gt;，其中说明了对容器的要求：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;容器是 64 位 Linux 平台；&lt;/li&gt;
&lt;li&gt;在 8080 端口监听 HTTP 请求；&lt;/li&gt;
&lt;li&gt;最多使用 2G 内存；&lt;/li&gt;
&lt;li&gt;容器实例必须在收到请求之后的 4 分钟内启动 HTTP 服务器；&lt;/li&gt;
&lt;li&gt;应用应该能够适应自动从 0 到多个运行实例的容器环境；&lt;/li&gt;
&lt;li&gt;所有的运算都应该是无状态的，限制在一个请求之内。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;只要你的项目能够符合上面的条件，不论使用什么语言开发，都能够在 Cloud Run 上面运行。&lt;/p&gt;

&lt;p&gt;Cloud Run 目前还在 Beta 阶段，因此这些需求可能会发生变动。&lt;/p&gt;

&lt;h2 id=&#34;上手流程&#34;&gt;上手流程&lt;/h2&gt;

&lt;p&gt;对于熟悉 Docker 或者 Heroku 传统 PaaS 解决方案的人来说，Cloud Run 应该很易上手。&lt;/p&gt;

&lt;p&gt;应用打包成 Docker 之后，剩下的任务包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;把镜像推送到 Google 镜像库。&lt;/li&gt;
&lt;li&gt;运行 &lt;code&gt;gcloud beta run deploy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;只要几分钟，Cloud Run 就会使用一个可定制、可开放的域名启动新应用了。&lt;/p&gt;

&lt;h3 id=&#34;示例-使用-semaphore-进行持续部署&#34;&gt;示例：使用 Semaphore 进行持续部署&lt;/h3&gt;

&lt;p&gt;下面的例子中，我们使用 &lt;a href=&#34;https://semaphoreci.com/&#34; target=&#34;_blank&#34;&gt;Semaphore&lt;/a&gt; 要为一个微服务配置 &lt;a href=&#34;https://thenewstack.io/why-cloud-native-success-depends-on-high-velocity-ci-cd/&#34; target=&#34;_blank&#34;&gt;Serverless CI/CD Pipeline&lt;/a&gt;，其中包含如下环节：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;运行自动测试；&lt;/li&gt;
&lt;li&gt;构建 Docker 容器；&lt;/li&gt;
&lt;li&gt;将容器镜像推入 Google 镜像库；&lt;/li&gt;
&lt;li&gt;提供到 Cloud Run 预备环境的一键部署；&lt;/li&gt;
&lt;li&gt;在对 Master 分支的构建成功之后；自动部署到 Cloud Run 生产环境。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&#34;images/dac19d8b-semaphore1-1024x533.png&#34; alt=&#34;semaphore&#34; /&gt;&lt;/p&gt;

&lt;p&gt;可以在 &lt;a href=&#34;https://github.com/semaphoreci-demos/semaphore-demo-cloud-run&#34; target=&#34;_blank&#34;&gt;Github&lt;/a&gt; 上找到相关的全部代码。&lt;/p&gt;

&lt;h3 id=&#34;启用-cloud-run&#34;&gt;启用 Cloud Run&lt;/h3&gt;

&lt;p&gt;官方的&lt;a href=&#34;https://cloud.google.com/run/docs/quickstarts/build-and-deploy&#34; target=&#34;_blank&#34;&gt;快速启动指南&lt;/a&gt;提供了一个 Cloud Run 的上手教程。&lt;/p&gt;

&lt;p&gt;第一步是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;在你的账号中&lt;a href=&#34;http://console.cloud.google.com/apis/library/run.googleapis.com&#34; target=&#34;_blank&#34;&gt;启用 Cloud Run API&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;安装 Google Cloud SDK；&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;gcloud components install beta&lt;/code&gt; 安装 Beta 组件。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;应用容器化&#34;&gt;应用容器化&lt;/h3&gt;

&lt;p&gt;下面的 Dockerfile 将一个简单的 Sinatra 应用打包：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-dockerfile&#34;&gt;FROM ruby:2.5
RUN apt-get update -qq &amp;amp;amp;&amp;amp;amp; apt-get install -y build-essential
ENV APP_HOME /app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
ADD Gemfile* $APP_HOME/
RUN bundle install --without development test
ADD . $APP_HOME
EXPOSE 8080
CMD [&amp;quot;bundle&amp;quot;, &amp;quot;exec&amp;quot;, &amp;quot;rackup&amp;quot;, &amp;quot;--host&amp;quot;, &amp;quot;0.0.0.0&amp;quot;, &amp;quot;-p&amp;quot;, &amp;quot;8080&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;注意如果使用你自己的 Dockerfile，必须开放 8080 端口，否则可能会看到如下错误：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/4759c604-screen-shot-2019-04-10-at-22.38.51.png&#34; alt=&#34;execption&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;登录-google-cloud-和-gcr&#34;&gt;登录 Google Cloud 和 GCR&lt;/h3&gt;

&lt;p&gt;要在 CI/CD Pipeline 中自动地将&lt;a href=&#34;https://cloud.google.com/container-registry/docs/pushing-and-pulling&#34; target=&#34;_blank&#34;&gt;镜像推送到 GCR&lt;/a&gt;，需要在 Semaphore 中登录到 Google Cloud。为了安全起见，需要在 Semaphore 中根据 Google Cloud Service account 的认证密钥创建一个 Secret。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://cloud.google.com/iam/docs/creating-managing-service-account-keys#iam-service-account-keys-list-gcloud&#34; target=&#34;_blank&#34;&gt;获取认证密钥&lt;/a&gt;之后，在 Semaphore 中用 Secret 的形式上传到 Semaphore。假设文件名是 &lt;code&gt;.secrets.gcp.json&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sem create secret google-cloud-stg --file ~/Downloads/account-name-27f3a5bcea2d.json:.secrets.gcp.json
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;定义分发管线&#34;&gt;定义分发管线&lt;/h3&gt;

&lt;p&gt;接下来就可以编写一个 Pipeline 来构建、标记并推送镜像到 GCR 了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# .semaphore/docker-build.yml
# This pipeline runs after semaphore.yml
version: v1.0
name: Docker build
agent:
  machine:
    # Use a machine type with more RAM and CPU power for faster container
    # builds:
    type: e1-standard-4
    os_image: ubuntu1804
blocks:
  - name: Build
    task:
      # Mount a secret which defines an authentication key file.
      # For info on creating secrets, see:
      # - https://docs.semaphoreci.com/article/66-environment-variables-and-secrets
      # - https://docs.semaphoreci.com/article/72-google-container-registry-gcr
      secrets:
        - name: google-cloud-stg
      jobs:
      - name: Docker build
        commands:
          # Authenticate using the file injected from the secret
          - gcloud auth activate-service-account --key-file=.secrets.gcp.json
          # Configure access to container registry, silence confirmation prompts with -q
          - gcloud auth configure-docker -q

          - checkout

          # Tag your images with gcr.io/ACCOUNT_PROJECT_NAME/SERVICE_NAME pattern
          # Use Git SHA to produce unique artifacts
          - docker build -t &amp;quot;gcr.io/semaphore2-stg/semaphore-demo-cloud-run:${SEMAPHORE_GIT_SHA:0:7}&amp;quot; .
          - docker push &amp;quot;gcr.io/semaphore2-stg/semaphore-demo-cloud-run:${SEMAPHORE_GIT_SHA:0:7}&amp;quot;

promotions:
  # Deployment to staging can be trigger manually:
  - name: Deploy to staging
    pipeline_file: deploy-staging.yml

  # Automatically deploy to production on successful builds on master branch:
  - name: Deploy to production
    pipeline_file: deploy-production.yml
    auto_promote_on:
      - result: passed
        branch:
          - master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在 &lt;code&gt;deploy-staging.yml&lt;/code&gt; 和 &lt;code&gt;deploy-production.yml&lt;/code&gt; 中包含了同样的步骤，区别只是服务的名称。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# .semaphore/deploy-production.yml
# This pipeline runs after docker-build.yml
version: v1.0
name: Deploy to production
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Deploy to production
    task:
      secrets:
        - name: google-cloud-stg
      jobs:
      - name: run deploy
        commands:
          - gcloud auth activate-service-account --key-file=.secrets.gcp.json
          - gcloud auth configure-docker -q
          
          # Deploy to Cloud Run, using flags to avoid interactive prompt
          # See https://cloud.google.com/sdk/gcloud/reference/beta/run/deploy
          - gcloud beta run deploy markoci-demo-cloud-run --project semaphore2-stg --image gcr.io/semaphore2-stg/markoci-demo-cloud-run:${SEMAPHORE_GIT_SHA:0:7} --region us-central1
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;上线运行&#34;&gt;上线运行&lt;/h3&gt;

&lt;p&gt;在本地终端或者 Semaphore 作业的日志中，最后一行会包含一个应用运行的网址：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://semaphore-demo-cloud-run-ud2bmvsmda-uc.a.run.app.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;用浏览器打开这个网址会看到：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/08fefc9a-screen-shot-2019-04-10-at-22.30.52.png&#34; alt=&#34;forbidden&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这是因为还没有完成最后一步：在 Google Cloud Run 控制台中&lt;a href=&#34;https://cloud.google.com/run/docs/securing/managing-access#making_a_service_public&#34; target=&#34;_blank&#34;&gt;开放服务&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;完成之后的浏览页面：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/011b5a8f-semaphore2-1024x627.png&#34; alt=&#34;hello&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;整装待发&#34;&gt;整装待发&lt;/h3&gt;

&lt;p&gt;希望本文能够引起你使用 &lt;a href=&#34;https://thenewstack.io/why-a-well-oiled-ci-cd-pipeline-makes-for-a-happy-devops-team/&#34; target=&#34;_blank&#34;&gt;CI/CD Pipeline&lt;/a&gt; 在 Google Cloud Run 上构建和发布应用的兴趣。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Knative 0.5 发布</title>
      <link>/post/knative-0.50-release/</link>
      <pubDate>Thu, 11 Apr 2019 22:37:55 +0800</pubDate>
      <guid>/post/knative-0.50-release/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://medium.com/knative/announcing-knative-v0-5-release-cfe646ca8e30?nsukey=DmMa%2BnItgi6DqPeCf9uQWn%2BXbGw%2FmuvNjKfVx80KhnL0s9C1pHst%2BzTVnCy8Iax3n9bUNJjrkL9O0TDyf42Qi8z9p0XW4heqtF%2FgPlJrJo%2BNs5qBOkyV%2FyH3Gc%2FjOCwm57VEZYyZNZcFB796ezQwZnbUN06%2FvuNEMR7BpUCETzg9VPlHVOAPpHF6qAkOlfxPCH7iM5Kw1Y7FaL2zLKXXcg%3D%3D&#34; target=&#34;_blank&#34;&gt;Announcing Knative v0.5 Release&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://medium.com/@mchmarny_google&#34; target=&#34;_blank&#34;&gt;Mark Chmarny&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;再一次激动地宣布 &lt;a href=&#34;https://www.knative.dev/&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt; 的新版本发布了。Knative 是一个能帮助开发者在 Kubernetes 基础之上，构建、部署和管理现代 Serverless 工作负载的平台。&lt;/p&gt;

&lt;p&gt;更加频繁和符合预期的发布节奏，让我们有机会能够从真实世界中获得更快的反馈，这种节奏当然也意味着更小的、更多的功能进展。也不全是这样，Knative v0.5 中，Eventing 系统有了长足的进步。其中的 Trigger 和 Broker 对象的引入，让开发者基于 Knative 构建事件驱动系统时能够得到更好更强的开发体验。&lt;/p&gt;

&lt;p&gt;除了 Eventing，这个版本的 Knative 还增加了监控指标，提高了自动伸缩、队列代理以及 Istio 遥测的可观察性，下面做一个介绍，并对部分变更做出一点深入讲解。&lt;/p&gt;

&lt;h2 id=&#34;eventing&#34;&gt;Eventing&lt;/h2&gt;

&lt;p&gt;在 &lt;strong&gt;Eventing&lt;/strong&gt; 架构中加入了 &lt;strong&gt;Trigger&lt;/strong&gt; 和 &lt;strong&gt;Broker&lt;/strong&gt; 对象，开发者能够轻松的构建出复杂且健壮的事件驱动应用。通过对 &lt;strong&gt;Producing&lt;/strong&gt; 和 &lt;strong&gt;Consuming&lt;/strong&gt; 服务的解耦，对路由配置的需求大大降低。我们相信，社区将会使用这一新能力构建出新的事件和创新的解决方案。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;eventing-object-model.png&#34; alt=&#34;Knative Eventing Object Model&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trigger&lt;/strong&gt;：开发者不再需要手工的对事件进行转换并路由给下游的 Knative 服务。只要定义一个简单的事件触发器，选择源事件（可以使用任何方式进行过滤），然后发送到消费方服务即可。这一对象会给开发者的体验带来很大简化。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broker&lt;/strong&gt;：事件 Broker 充当了事件 Hub 的角色，所有的消息都会发送给它。开发者和用户简单的编写服务或者配置事件源发送时间给 Broker，Broker 会处理其它工作。消费方服务只需要创建一个触发器，从 Broker 中接收它们感兴趣的事件即可。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;新的事件源&lt;/strong&gt;：Kanative 中加入了 Kafka 的事件源，将 Kafka 生态系统的丰富功能带给了 Knative 和 Kubernetes。&lt;/p&gt;

&lt;h2 id=&#34;自动伸缩&#34;&gt;自动伸缩&lt;/h2&gt;

&lt;p&gt;自动伸缩功能增强，在重度工作负载的情况下，能够更平顺、更高效的完成伸缩动作。加入了更多的自动伸缩指标，增强了可观察性。&lt;/p&gt;

&lt;h2 id=&#34;核心-api&#34;&gt;核心 API&lt;/h2&gt;

&lt;p&gt;新版本中，具名子路由的 URL 暴露在 Service 和 Route 资源的状态之中，就不用再猜测如何标记流量的分配状况了。这是 &lt;code&gt;v1beta1 task force&lt;/code&gt; 中的第一个变化。后续版本中将会看到更多这方面的更新。&lt;/p&gt;

&lt;p&gt;另外我们的 Webhook 中，很多缺省值都可以使用名为 &lt;code&gt;config-defaults&lt;/code&gt; 的 Configmap 进行配置了。另外，在我们的控制器遇到内部错误时，会通过 Kubernetes 事件系统提供更好的可见性。最后，我们还扩展了我们的一致性测试，其中包含了对 &lt;code&gt;securityContext&lt;/code&gt; 和 &lt;code&gt;metadata.generateName&lt;/code&gt; 的支持。&lt;/p&gt;

&lt;h2 id=&#34;网络&#34;&gt;网络&lt;/h2&gt;

&lt;p&gt;这一版本中，针对 gRPC 服务的冷启动和客户端的认证头处理有了很大提升。&lt;/p&gt;

&lt;p&gt;Knative 0.5 的完整发布公告中包含了新功能和问题修复的完整列表，分别在 &lt;a href=&#34;https://github.com/knative/serving/releases/tag/v0.5.0&#34; target=&#34;_blank&#34;&gt;Serving&lt;/a&gt;、&lt;a href=&#34;https://github.com/knative/build/releases/tag/v0.5.0&#34; target=&#34;_blank&#34;&gt;Build&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/knative/eventing/releases/tag/v0.5.0&#34; target=&#34;_blank&#34;&gt;Eventing&lt;/a&gt; 代码库中。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Knative v0.2 发布</title>
      <link>/post/announcing-knative-v0.2-release/</link>
      <pubDate>Thu, 15 Nov 2018 00:40:06 +0800</pubDate>
      <guid>/post/announcing-knative-v0.2-release/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://medium.com/knative/https-medium-com-knative-v0-2-963f276af58e&#34; target=&#34;_blank&#34;&gt;Announcing Knative v0.2 Release&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://medium.com/@mchmarny_google&#34; target=&#34;_blank&#34;&gt;Mark Chmarny&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;增强的插接能力、自动伸缩、稳定性和性能。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knative 是一组用于在 Kubernetes 上构建现代应用的一组中间件组件，在此宣布，0.2 版本已经面世。从七月份该项目启动至今，0.2 版本是第一次显著更新。这次更新是整个 Knative 社区的几个月里的努力成果，体现了我们从日益增多的 Knative 部署数量中学到的新知识。&lt;/p&gt;

&lt;p&gt;0.2 版本中最令人激动的更新就是包含了 &lt;code&gt;eventing&lt;/code&gt;。Eventing 组件补充了另外两大组件：Build 和 Serving 留下的空白。我们希望社区会使用这一新功能来开发新的事件和解决方案。&lt;/p&gt;

&lt;p&gt;Serving 组件的内部实现做出了很大改进，新的内部 API 将 Knative 划分为了子系统，从而加入了对可插接网络、自动伸缩以及缓存的支持。&lt;/p&gt;

&lt;p&gt;完整的发布说明可以在 &lt;a href=&#34;https://github.com/knative/serving/releases/tag/v0.2.1&#34; target=&#34;_blank&#34;&gt;Serving&lt;/a&gt;、&lt;a href=&#34;https://github.com/knative/build/releases/tag/v0.2.0&#34; target=&#34;_blank&#34;&gt;Build&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/knative/eventing/releases/tag/v0.2.0&#34; target=&#34;_blank&#34;&gt;Eventing&lt;/a&gt; 仓库中找到。下面着重说一下其中的亮点：&lt;/p&gt;

&lt;h2 id=&#34;新的事件资源模型&#34;&gt;新的事件资源模型&lt;/h2&gt;

&lt;p&gt;Eventing 在资源模型方面发生了很大变化，将源码融入 CRD 之中。Eventing 现已采用 Kubernetes 的表尊概念，这样一来就可以更好的实现校验、清晰的接口以及 RBAC 支持。新架构使用了以 Channel 和订阅为中心的简化的对象模型。&lt;/p&gt;

&lt;h2 id=&#34;松耦合&#34;&gt;松耦合&lt;/h2&gt;

&lt;p&gt;在 v0.1 期间我们收到的正面评价之一就是在定义 Knative 组件安装时候的选择能力。v0.2 中 Knative 增强了这种能力，操作者可以独立安装 Build、Serving 以及 Eventing 组件。Knative 组件之间的松耦合使得第三方集成成为了可能，例如使用一个非 Knative 的 Build 来和 Serving 进行配合，或者用 Eventing 把事件分发给非 Serving 的部署。我们很高兴社区选择了这一方向。&lt;/p&gt;

&lt;h2 id=&#34;可插接的子系统&#34;&gt;可插接的子系统&lt;/h2&gt;

&lt;p&gt;我们还接到了很多希望能够定制 Knative 的反馈。目标就是支持某种程度的插接能力，所以 v0.2 中定制能力也有了显著提高。我们加入了三个新的内部 API，来把我们的核心资源模型从实现模块中分离出来：网络、自动伸缩和缓存。网络让开发人员可以用不同的 Ingress 实现来替代我们的 Istio 依赖。自动伸缩让开发人员能够把我们的自动伸缩机制替换为自己的方案。缓存让开发人员可以使用镜像缓存策略来在集群中进行镜像的提前载入（这是一个纯粹的扩展点，并没有内置绑定方案）。&lt;/p&gt;

&lt;h2 id=&#34;冷启动改进&#34;&gt;冷启动改进&lt;/h2&gt;

&lt;p&gt;决定冷启动性能的两个决定因素就是 Sidecar 注入和镜像拉取造成的延时。Istio 的 1.0.2 版本中在减少 Envoy 编程时间方面有了进步。另外我们还允许安装无 Sidecar 注入的 Knative。为了帮助用户降低镜像拉取延迟，我们开放了新的扩展点，称为 &amp;ldquo;Image&amp;rdquo; 资源（knative/caching 的一部分），其中包含了一个预载入镜像控制器所需要的所有信息。社区对缓存组件的建设让我们非常激动。&lt;/p&gt;

&lt;h2 id=&#34;自动伸缩&#34;&gt;自动伸缩&lt;/h2&gt;

&lt;p&gt;以前的自动伸缩器是每个版本一个，现在替换为单一的共享控制器。新的自动伸缩器和之前的版本具备同样的逻辑，但是进化到纯粹的指标驱动（包含 0-&amp;gt;1-&amp;gt;0），去掉了无用的 Revision servingState 字段。我们用一个整数 &lt;code&gt;ContainerConcurrency&lt;/code&gt; 字段替换了 &lt;code&gt;ConcurrencyModel&lt;/code&gt;。这样在一些情况下就可以限制并行数量为 1 以外的数值（例如限制线程池）。&lt;/p&gt;

&lt;h2 id=&#34;build&#34;&gt;Build&lt;/h2&gt;

&lt;p&gt;Knative Build 做了很多增强，包括新的 &lt;code&gt;ClusterBuildTemplate&lt;/code&gt; 资源。用户可以一次性安装一组 &lt;code&gt;BuildTemplates&lt;/code&gt;，而不是每个命名空间一次。Build 模板参数可以对构建步骤所用的镜像名称进行设置。Build Spec 的新功能包括用户可以指定 Build 一级的超时、节点选择器以及亲和性。另外 Build 状态得到了扩展，会报告每个步骤和 Build 的等候时间。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>在 Knative 中进行应用程序的构建和部署</title>
      <link>/post/building-and-deploying-applications-to-knative/</link>
      <pubDate>Tue, 13 Nov 2018 00:10:38 +0800</pubDate>
      <guid>/post/building-and-deploying-applications-to-knative/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://starkandwayne.com/blog/building-and-deploying-applications-to-knative/&#34; target=&#34;_blank&#34;&gt;Building and deploying applications to Knative&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/starkandwayne&#34; target=&#34;_blank&#34;&gt;Dr Nic Williams&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knative 有三个高级子系统：Serving 用来协调服务 Pod 的自动伸缩以及路由；Build 提供了将代码转换为镜像的工具链；Eventing 则会使用事件的发布订阅来触发松耦合服务。&lt;/p&gt;

&lt;p&gt;前一篇文章中我们将一个构件好的容器镜像发布到了 Knative Serving 中。&lt;/p&gt;

&lt;p&gt;本篇文章将使用 Knative Build 把我们的应用通过 Dockerfile 以及 Cloud Foundry buildpack 在发布过程中转化为容器镜像。我们还会尝试从本地文件系统以及远程 Git 仓库中进行部署的方式。&lt;/p&gt;

&lt;p&gt;前面的操作都很简单，看得出在 Kubernetes 环境中安装 Knative、运行现有容器镜像、使用 curl 与应用进行交互都不难。总结一下就是：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl install [--node-ports] [--exclude-monitoring]
knctl deploy --service &amp;lt;service-name&amp;gt; --image &amp;lt;image-name&amp;gt;
knctl curl --service &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;后面的两步 - 把镜像部署为 Kubernetes 并运行，为每个部署进行版本化处理，使用 HTTP 路由进行交互，都是 &lt;a href=&#34;https://github.com/knative/serving/blob/master/docs/spec/overview.md&#34; target=&#34;_blank&#34;&gt;Serving 子系统&lt;/a&gt;的功劳。&lt;/p&gt;

&lt;p&gt;Knative 还支持用于构建容器镜像的弹性子系统，构建生成的镜像将会以 Kubernetes Pod 的形式运行。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/knative/docs/tree/master/build&#34; target=&#34;_blank&#34;&gt;Knative Build&lt;/a&gt; 子系统非常有弹性。我们会探讨集中用例：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;上传一个本地目录，使用 Dockerfile 进行构建。&lt;/li&gt;
&lt;li&gt;上传一个本地目录，使用 Buildpack 进行构建。&lt;/li&gt;
&lt;li&gt;用上面两种方式来构建来自于远程 Git 仓库的代码。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;命名空间&#34;&gt;命名空间&lt;/h2&gt;

&lt;p&gt;前一篇文章中我们在每个 &lt;code&gt;knctl&lt;/code&gt; 命令中使用了 &lt;code&gt;--namespace helloworld&lt;/code&gt; 参数来显式的指定命名空间。对我来说这样显得更清晰。可能有别的用户希望设置一个缺省命名空间，从而能够缩短命令。&lt;/p&gt;

&lt;p&gt;可以给 &lt;code&gt;knctl&lt;/code&gt; 配置一个当前命名空间：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl create ns my-simple-app
export KNCTL_NAMESPACE=my-simple-app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;所有的 &lt;code&gt;knctl&lt;/code&gt; 命令都会使用这一命名空间。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ knctl service list
Services in namespace &#39;my-simple-app&#39;

Name  Domain  Annotations  Age

0 services
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以在 &lt;code&gt;kubectl&lt;/code&gt; 命令中复用 &lt;code&gt;$KNCTL_NAMESPACE&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get pods -n $KNCTL_NAMESPACE&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;上传一个带有-dockerfile-的本地目录&#34;&gt;上传一个带有 Dockerfile 的本地目录&lt;/h2&gt;

&lt;p&gt;在所有 Knative Build 的示例中，都会产生一个副产品——容器镜像。这些镜像必须放在什么地方，例如 &lt;a href=&#34;https://hub.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker Hub&lt;/a&gt;、&lt;a href=&#34;https://cloud.google.com/container-registry/&#34; target=&#34;_blank&#34;&gt;GCP 容器库&lt;/a&gt;、&lt;a href=&#34;https://azure.microsoft.com/en-au/services/container-registry/&#34; target=&#34;_blank&#34;&gt;Azure 容器库&lt;/a&gt;，或者借助 &lt;a href=&#34;https://goharbor.io/&#34; target=&#34;_blank&#34;&gt;Harbor&lt;/a&gt; 之类的软件自建的私库。&lt;/p&gt;

&lt;p&gt;我们需要在每个应用所在的 Kubernetes 命名空间中给 Knative 配置一个镜像库，然后 &lt;code&gt;knctl basic-auth-secret create&lt;/code&gt; 给 Knative 配置一个 Secret。&lt;/p&gt;

&lt;p&gt;以 Docker Hub 为例，使用 &lt;code&gt;--docker-hub&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --docker-hub -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;GCP 容器仓库可以使用 &lt;code&gt;--gcr&lt;/code&gt; 选项：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --gcr -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其它私库可以使用 &lt;code&gt;--type&lt;/code&gt; 和 &lt;code&gt;--url&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl basic-auth-secret create -s registry --type docker --url https://registry.domain.com/ -u &amp;lt;username&amp;gt; -p &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一步把镜像库 Secret 映射到 &lt;a href=&#34;https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/&#34; target=&#34;_blank&#34;&gt;Kubernetes Service account&lt;/a&gt;，它会在 Knative Build 的 Pod 中提供上面的登录信息。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl service-account create --service-account build -s registry
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这个操作会体现在 Kubernetes 的 Service account 中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get serviceaccount -n $KNCTL_NAMESPACE
NAME      SECRETS   AGE
build     2         37s
default   1         3h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样我们就准备好使用 Knative Build 创建新容器镜像所需的认证凭据了。&lt;/p&gt;

&lt;p&gt;Clone 一个 Go 应用作为样例，并从它的本地目录推送到 Docker hub：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;git clone https://github.com/cppforlife/simple-app
cd simple-app

DOCKER_IMAGE=index.docker.io/&amp;lt;your hub.docker.com org or user&amp;gt;/knative-simple-app

knctl deploy \
    --service simple-app \
    --directory=$PWD \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from local directory using Dockerfile&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;容器的显式命名事实上只是从 Build 到 Serve 的工作过程中的一个中间步骤的副产品，但是必须提供。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 的输出大概是这样的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  simple-app

Waiting for new revision to be created...

Tagging new revision &#39;simple-app-00001&#39; as &#39;latest&#39;

Tagging new revision &#39;simple-app-00001&#39; as &#39;previous&#39;

[2018-10-15T13:18:31+10:00] Uploading source code...

[2018-10-15T13:19:59+10:00] Finished uploading source code...

Watching build logs...

build-step-build-and-push | INFO[0000] Downloading base image golang:1.10.1
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:20:01.547607       1 metadata.go:142] while reading &#39;google-dockercfg&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:20:01.550268       1 metadata.go:159] while reading &#39;google-dockercfg-url&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg-url
build-step-build-and-push | INFO[0001] Executing 0 build triggers
build-step-build-and-push | INFO[0001] Extracting layer 0
build-step-build-and-push | INFO[0003] Extracting layer 1
build-step-build-and-push | INFO[0004] Extracting layer 2
build-step-build-and-push | INFO[0004] Extracting layer 3
build-step-build-and-push | INFO[0007] Extracting layer 4
build-step-build-and-push | INFO[0010] Extracting layer 5
build-step-build-and-push | INFO[0015] Extracting layer 6
build-step-build-and-push | INFO[0015] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0027] WORKDIR /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] cmd: workdir
build-step-build-and-push | INFO[0027] Changed working directory to /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] Creating directory /go/src/github.com/mchmarny/simple-app/
build-step-build-and-push | INFO[0027] COPY . .
build-step-build-and-push | INFO[0027] RUN CGO_ENABLED=0 GOOS=linux go build -v -o app
build-step-build-and-push | INFO[0027] cmd: /bin/sh
build-step-build-and-push | INFO[0027] args: [-c CGO_ENABLED=0 GOOS=linux go build -v -o app]
build-step-build-and-push | net
build-step-build-and-push | vendor/golang_org/x/net/lex/httplex
build-step-build-and-push | vendor/golang_org/x/net/proxy
build-step-build-and-push | net/textproto
build-step-build-and-push | crypto/x509
build-step-build-and-push | crypto/tls
build-step-build-and-push | net/http/httptrace
build-step-build-and-push | net/http
build-step-build-and-push | github.com/mchmarny/simple-app
build-step-build-and-push | INFO[0030] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0034] Storing source image from stage 0 at path /kaniko/stages/0
build-step-build-and-push | INFO[0038] trying to extract to /kaniko/0
build-step-build-and-push | INFO[0038] Extracting layer 0
build-step-build-and-push | INFO[0040] Extracting layer 1
build-step-build-and-push | INFO[0041] Extracting layer 2
build-step-build-and-push | INFO[0041] Extracting layer 3
build-step-build-and-push | INFO[0043] Extracting layer 4
build-step-build-and-push | INFO[0046] Extracting layer 5
build-step-build-and-push | INFO[0051] Extracting layer 6
build-step-build-and-push | INFO[0051] Extracting layer 7
build-step-build-and-push | INFO[0051] Deleting filesystem...
build-step-build-and-push | INFO[0053] No base image, nothing to extract
build-step-build-and-push | INFO[0053] Taking snapshot of full filesystem...
build-step-build-and-push | INFO[0062] COPY --from=0 /go/src/github.com/mchmarny/simple-app/app .
build-step-build-and-push | INFO[0063] Taking snapshot of files...
build-step-build-and-push | INFO[0063] EXPOSE 8080
build-step-build-and-push | INFO[0063] cmd: EXPOSE
build-step-build-and-push | INFO[0063] Adding exposed port: 8080/tcp
build-step-build-and-push | INFO[0063] ENTRYPOINT [&amp;quot;/app&amp;quot;]
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:21:04.751338       1 metadata.go:142] while reading &#39;google-dockercfg&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg
build-step-build-and-push | ERROR: logging before flag.Parse: E1015 03:21:04.753927       1 metadata.go:159] while reading &#39;google-dockercfg-url&#39; metadata: http status code: 404 while fetching url http://metadata.google.internal./computeMetadata/v1/instance/attributes/google-dockercfg-url
build-step-build-and-push | 2018/10/15 03:21:06 pushed blob sha256:72a682eea3309941d5e8e6f993a07ae4d33a413b8b7fa2762f8e969310b5996a
build-step-build-and-push | 2018/10/15 03:21:07 pushed blob sha256:9c24aa788ba416c5e1e631d8af3e3115519ad7ca0f659ac10f40682524c6d9cd
build-step-build-and-push | 2018/10/15 03:21:07 index.docker.io/drnic/knative-simple-app:latest: digest: sha256:b5823ead77d9544998b5bc844f049d1a7dfb0aefe7461b74b3e4f67fb5481fa1 size: 428
nop | Nothing to push

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;knative-build-的调试&#34;&gt;Knative Build 的调试&lt;/h2&gt;

&lt;p&gt;目前 &lt;code&gt;knctl deploy&lt;/code&gt; 没有显示任何来自 Knative Build 系统的内部错误或者警告。只需要看着 &lt;code&gt;Waiting for new revision to be created...&lt;/code&gt; 坐享其成就可以了。&lt;/p&gt;

&lt;p&gt;一个调试方法就是使用 &lt;a href=&#34;https://github.com/boz/kail&#34; target=&#34;_blank&#34;&gt;kail&lt;/a&gt; 工具处理来自 Knative Build 子系统的消息：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kail -n knative-build
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样就会看到大量的日志，可以再其中查找错误信息，例如 &lt;code&gt;&amp;quot;msg&amp;quot;:&amp;quot;Failed the resource specific validation{error 25 0 serviceaccounts \&amp;quot;build\&amp;quot; not found}&amp;quot;&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;使用-buildpack-进行构建&#34;&gt;使用 Buildpack 进行构建&lt;/h2&gt;

&lt;p&gt;我本人很喜欢 Cloud Foundry 和 Heroku 的镜像构建方式，幸运的是，Knative Build 通过&lt;a href=&#34;https://github.com/knative/build-templates/tree/master/buildpack&#34; target=&#34;_blank&#34;&gt;自定义构建模板&lt;/a&gt;的方式提供了这种支持。&lt;/p&gt;

&lt;p&gt;首先用 &lt;code&gt;buildpack&lt;/code&gt; 这个名字在活动命名空间中注册一个&lt;a href=&#34;https://github.com/knative/build-templates/blob/master/buildpack/buildpack.yaml&#34; target=&#34;_blank&#34;&gt;构建模板&lt;/a&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl -n $KNCTL_NAMESPACE apply -f \
https://raw.githubusercontent.com/knative/build-templates/master/buildpack/buildpack.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;加入 &lt;code&gt;--template buildpack&lt;/code&gt; 就可以使用这一自定义模板了。构建模板所需的附加环境变量都可以用 &lt;code&gt;--template-env NAME=value&lt;/code&gt; 的方式进行植入。&lt;/p&gt;

&lt;p&gt;例如 Cloud Foundry Go Buildpack 需要 &lt;code&gt;$GOPACKNAME&lt;/code&gt;（&lt;a href=&#34;https://docs.cloudfoundry.org/buildpacks/go/index.html#pushing_Apps_with_native_Go_vendoring&#34; target=&#34;_blank&#34;&gt;参考文档&lt;/a&gt;）：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl deploy \
    --service simple-app \
    --directory=$PWD \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from local directory using Buildpack template&amp;quot; \
    --template buildpack \
    --template-env GOPACKAGENAME=main
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;输出内容和 Cloud Foundry buildpack 是一致的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  simple-app

Waiting for new revision (after revision &#39;simple-app-00001&#39;) to be created...

Tagging new revision &#39;simple-app-00002&#39; as &#39;latest&#39;

Tagging older revision &#39;simple-app-00001&#39; as &#39;previous&#39;

[2018-10-15T13:40:41+10:00] Uploading source code...

[2018-10-15T13:42:08+10:00] Finished uploading source code...

Watching build logs...

build-step-build | -----&amp;gt; Go Buildpack version 1.8.26
build-step-build | -----&amp;gt; Installing godep 80
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/godep/godep-v80-linux-x64-cflinuxfs2-06cdb761.tgz]
build-step-build | -----&amp;gt; Installing glide 0.13.1
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/glide/glide-v0.13.1-linux-x64-cflinuxfs2-aab48c6b.tgz]
build-step-build | -----&amp;gt; Installing dep 0.5.0
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/dep/dep-v0.5.0-linux-x64-cflinuxfs2-52c14116.tgz]
build-step-build | -----&amp;gt; Installing go 1.8.7
build-step-build |        Download [https://buildpacks.cloudfoundry.org/dependencies/go/go1.8.7.linux-amd64-cflinuxfs2-fff10274.tar.gz]
build-step-build |        **WARNING** Installing package &#39;.&#39; (default)
build-step-build | -----&amp;gt; Running: go install -tags cloudfoundry -buildmode pie .
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:1124eb40dd68654b8ca8f5d9ec7e439988a4be752a58c8f4e06d60ab1589abdb
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:6be38da025345ffb57d1ddfcdc5a2bc052be5b9491825f648b49913d51e41acb
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:a5733e6358eec8957e81b1eb93d48ef94d649d65c69a6b1ac49f616a34a74ac1
build-step-export | 2018/10/15 03:47:58 mounted blob: sha256:21324a9f04e76c93078f3a782e3198d2dded46e4ec77958ddd64f701aecb69c0
build-step-export | 2018/10/15 03:47:59 pushed blob sha256:efa2d34b82bc07588a1a8fd4526322257408109547ee089a792b3f51c383f8e6
build-step-export | 2018/10/15 03:47:59 pushed blob sha256:d495696b33936c79216ec8178726b9fbe915fafbffdd0911a7fdabce4297d9a4
build-step-export | 2018/10/15 03:48:00 index.docker.io/drnic/knative-simple-app:latest: digest: sha256:e5ef1d4d255b4bcbb38d4b43bb6302423c33e6eeabd0e20d5fda4e5ce4c46668 size: 1082
nop | Nothing to push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在就能看到应用已经部署成功：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl -s simple-app
&amp;lt;h1&amp;gt;Built from local directory using Buildpack template&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;私有-git-secret&#34;&gt;私有 Git Secret&lt;/h2&gt;

&lt;p&gt;前面两节我们从本地上传了源码然后构建了 Docker 镜像（使用 Dockerfile 或 Cloud Foundry buildpack），最后运行应用。&lt;/p&gt;

&lt;p&gt;Knative 还能从 Git 仓库获取源码（正式的说法是，Knative Build 只支持从 Git 仓库获取源码，本地代码的支持是 &lt;code&gt;knctl&lt;/code&gt; 提供的）。&lt;/p&gt;

&lt;p&gt;让 Knative Build 获取 Git 仓库中的代码，需要用 &lt;code&gt;--git-url&lt;/code&gt; 和 &lt;code&gt;--git-revision&lt;/code&gt; 来取代 &lt;code&gt;--directory=$PWD&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果你的 Git 仓库是私有的，那就还需要在 Service account（在上面的例子中的 &lt;code&gt;build&lt;/code&gt;）里包含 Git ssh 凭据。&lt;code&gt;knctl ssh-auth-secret create&lt;/code&gt; 能够协助用户创建一个 kubernetes.io/ssh-auth secret。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl ssh-auth-secret create --secret git --github --private-key &amp;quot;$(cat ~/.ssh/id_rsa)&amp;quot;
Name  git
Type  kubernetes.io/ssh-auth

$ kubectl get secrets -n $KNCTL_NAMESPACE
NAME                  TYPE                                  DATA   AGE
...
git                   kubernetes.io/ssh-auth                1      5m
registry              kubernetes.io/basic-auth              2      3h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在需要把 &lt;code&gt;git&lt;/code&gt; secret 加入到我们的 &lt;code&gt;build&lt;/code&gt; Service account 之中了。&lt;/p&gt;

&lt;p&gt;在成文之时，&lt;code&gt;knctl&lt;/code&gt; 还没有提供 &lt;code&gt;knctl serviceaccounts update&lt;/code&gt; 这样的命令，所以需要删除重新创建：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl delete serviceaccounts -n $KNCTL_NAMESPACE build
knctl service-account create --service-account build -s registry -s git
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;从-git-部署&#34;&gt;从 Git 部署&lt;/h2&gt;

&lt;p&gt;用 &lt;code&gt;--git-url&lt;/code&gt; 和 &lt;code&gt;--git-revision&lt;/code&gt; 替代 &lt;code&gt;--directory&lt;/code&gt; 来进行 Git 部署：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;knctl deploy \
    --service simple-app \
    --git-url git@github.com:cppforlife/simple-app.git \
    --git-revision master \
    --service-account build \
    --image ${DOCKER_IMAGE:?required} \
    --env SIMPLE_MSG=&amp;quot;Built from Git repo using Buildpack template&amp;quot; \
    --template buildpack \
    --template-env GOPACKAGENAME=main
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 命令在 Knative 的基础上提供了创建新镜像的良好体验，可以从本地目录或者 Git 仓库开始，使用 Dockerfile 或 Cloud Foundry buildpack 进行构建，并支持不同的镜像仓库。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>在 Knative 上部署 12 要素应用程序</title>
      <link>/post/deploying-12-factor-apps-to-knative/</link>
      <pubDate>Mon, 12 Nov 2018 00:35:24 +0800</pubDate>
      <guid>/post/deploying-12-factor-apps-to-knative/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://starkandwayne.com/blog/introduction-to-knative/&#34; target=&#34;_blank&#34;&gt;Deploying 12 Factor Apps to Knative&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/starkandwayne&#34; target=&#34;_blank&#34;&gt;Dr Nic Williams&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;我尝试按照本文内容在 Azure 上使用 ACS-Engine 部署的 Kubernetes 上进行了测试，版本部分的案例得到了相反结果，不过还是按照原文发了出来，作为一个获取感性认识的入门还是不错的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google Next18 活动中，Google 宣称将会把 GKE 上的无服务器插件以 &lt;a href=&#34;https://github.com/knative/&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt; 的名称进行开源。当时它被描述为无服务器平台的构建块，由此推断，Knative 可能需要 Google、Pivotal 或者 RedHat 的协助才能使用。这可能是开源的古怪时机。从我最初的摸索来看，Knative 能工作；当我把 Heroku/Cloud Foundry buildpacks 加入进来之后，整个系统变得越来越像 Heroku/Cloud Foundry，相对于原始 Kubernetes，我更加了解和喜爱这一系统。&lt;/p&gt;

&lt;p&gt;本文中我们会将 Knative 安装到你自己的 Kubernetes 集群中（&lt;code&gt;knctl install&lt;/code&gt;），然后用 Knative 做些有趣的事情（&lt;code&gt;knctl deploy&lt;/code&gt;）。&lt;/p&gt;

&lt;p&gt;Knative 能够为在 Kubernetes 集群上运行无状态应用的运维人员带来很多惊喜。对我来说，最引人入胜的一点就是伸缩性：在高负载时候进行扩容，没人喜欢你的应用了，就会一直缩容到 0。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/cppforlife/knctl/releases&#34; target=&#34;_blank&#34;&gt;下载和安装&lt;/a&gt; Knative 客户端工具 &lt;code&gt;knctl&lt;/code&gt;，然后就可以在你的 Kubernetes 上部署 Knative，然后发布你的应用了。&lt;/p&gt;

&lt;p&gt;在 MacOS 中，可以利用我们的 Homebrew tap 进行安装：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install starkandwayne/kubernetes/knctl&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这里我假设你再使用 Minikube。在 Minikube 中，可以使用 Node Port 代替 Load balancer：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;minikube start --memory=8192 --cpus=3 \
  --kubernetes-version=v1.11.3 \
  --vm-driver=hyperkit \
  --bootstrapper=kubeadm

knctl install --node-ports --exclude-monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以参考 &lt;a href=&#34;https://github.com/knative/docs/tree/master/install&#34; target=&#34;_blank&#34;&gt;Knative 文档&lt;/a&gt;来获取在其它类型 Kubernetes 集群上进行部署的要点。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;knctl install&lt;/code&gt; 命令可能要花上几分钟，甚至是十分钟或者更多。这个过程中需要下载大概一打镜像。不管是互联网带宽还是镜像尺寸都可能有变化，所以坐下放松一会，或者出去走走也好。&lt;/p&gt;

&lt;p&gt;如果 &lt;code&gt;knctl install&lt;/code&gt; 失败了，可能是你的 Internet 比较慢，Docker 镜像在命令超时之前还没能完成下载。运行 &lt;code&gt;kubectl get pods --all-namespaces&lt;/code&gt; 直到所有 Pod 都在运行，然后再次运行 &lt;code&gt;knctl install&lt;/code&gt; 命令继续完成安装过程。&lt;/p&gt;

&lt;p&gt;现在你的 Kubernetes 就是无服务器架构了，不错吧。&lt;/p&gt;

&lt;p&gt;可以运行 &lt;code&gt;kubectl get pods --all-namespaces&lt;/code&gt; 看看原始的 Knative 的 Pod 们。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ kubectl get pods --all-namespaces
NAMESPACE         NAME                                        READY   STATUS      RESTARTS   AGE
istio-system      istio-citadel-7d8f9748c5-zgm9x              1/1     Running     0          21m
istio-system      istio-cleanup-secrets-j4pkx                 0/1     Completed   0          21m
istio-system      istio-egressgateway-676c8546c5-dnwsd        1/1     Running     0          21m
istio-system      istio-galley-5669f7c9b-g774b                1/1     Running     0          21m
istio-system      istio-ingressgateway-5475685bbb-q5f2x       1/1     Running     0          21m
istio-system      istio-pilot-5795d6d695-9klrz                2/2     Running     0          21m
istio-system      istio-policy-7f945bf487-2wh88               2/2     Running     0          21m
istio-system      istio-sidecar-injector-d96cd9459-7knkm      1/1     Running     0          21m
istio-system      istio-statsd-prom-bridge-549d687fd9-lcmb7   1/1     Running     0          21m
istio-system      istio-telemetry-6c587bdbc4-t4jql            2/2     Running     0          21m
istio-system      knative-ingressgateway-7f4477dd99-n9wz2     1/1     Running     0          4m
knative-build     build-controller-7dcc4b7544-rkgwb           1/1     Running     0          4m
knative-build     build-webhook-fb6484576-sr4fk               1/1     Running     0          4m
knative-serving   activator-77d46b585d-b6g8n                  2/2     Running     0          4m
knative-serving   controller-85768cfd45-t8ktc                 1/1     Running     0          4m
knative-serving   webhook-56dd548f8-hjw44                     1/1     Running     0          4m
...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;部署预构建的应用&#34;&gt;部署预构建的应用&lt;/h2&gt;

&lt;p&gt;接下来我们试试用一个现有的 Docker 镜像来作为自动伸缩的无状态应用运行到 Knative 上，在当前 Kubernetes 命令空间中：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;kubectl create ns helloworld

knctl deploy \
      --namespace helloworld \
      --service hello \
      --image gcr.io/knative-samples/helloworld-go \
      --env TARGET=Rev1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;命令执行后会输出一些信息，表明 &lt;code&gt;hello&lt;/code&gt; 服务已经创建，它的第一个版本 &lt;code&gt;hello-00001&lt;/code&gt; 已经创建，并且被标记为 &lt;code&gt;latest&lt;/code&gt; 和 &lt;code&gt;previous&lt;/code&gt;（第一个版本）。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Name  hello

Waiting for new revision to be created...

Tagging new revision &#39;hello-00001&#39; as &#39;latest&#39;

Tagging new revision &#39;hello-00001&#39; as &#39;previous&#39;

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我们可以用一个 curl 请求，发送到 Knative 的路由层，来调用我们的 &lt;code&gt;hello&lt;/code&gt; 服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl --namespace helloworld --service hello
Running: curl &#39;-H&#39; &#39;Host: hello.helloworld.example.com&#39; &#39;http://192.168.64.8:32380&#39;

Hello World: Rev1!

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果没有马上显示 &lt;code&gt;Hello World: Rev1!&lt;/code&gt;，可能是因为你的系统还在下载应用镜像、可以稍后重试。&lt;/p&gt;

&lt;p&gt;我使用的是 Minikube 中的 NodePort Ingress，这意味着我不能设置漂亮的 DNS 路由。以后我会讨论一下公共负载均衡、DNS、Knative 路由以及 &lt;code&gt;https://github.com/cppforlife/kwt&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;knctl deploy&lt;/code&gt; 之后，我们的 Kubernetes 用单 Pod 的形式运行这一服务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          15s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Knative 中，服务的版本是一个重要特性。我们可以看到我们的唯一版本的服务正在处理 100% 的流量：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl revisions list --namespace helloworld --service hello
Revisions for service &#39;hello&#39;

Name         Tags      Allocated Traffic %  Serving State  Annotations  Age
hello-00001  latest    100%                 Active         -            3m
             previous

1 revisions
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一步我们使用 &lt;code&gt;knctl deploy&lt;/code&gt; 创建一个新的版本，然后把所有流量分配到新版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl deploy \
      --namespace helloworld \
      --service hello \
      --image gcr.io/knative-samples/helloworld-go \
      --env TARGET=Rev2

Name  hello

Waiting for new revision (after revision &#39;hello-00001&#39;) to be created...

Tagging new revision &#39;hello-00002&#39; as &#39;latest&#39;

Tagging older revision &#39;hello-00001&#39; as &#39;previous&#39;

Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;现在请求被发送到了我们的新版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl revisions list --namespace helloworld --service hello
Revisions for service &#39;hello&#39;

Name         Tags      Allocated Traffic %  Serving State  Annotations  Age
hello-00002  latest    100%                 Active         -            1m
hello-00001  previous  0%                   Active         -            10m

$ knctl curl --namespace helloworld --service hello
Running: curl &#39;-H&#39; &#39;Host: hello.helloworld.example.com&#39; &#39;http://192.168.64.8:32380&#39;

Hello World: Rev2!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;部署第二个版本之后，起初两个版本的 Pod 都会持续运行：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          1m
hello-00002-deployment-7874bf89b8-4b4k5   3/3     Running   0          29s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我们会看到 Knative 自动将没有路由指向的版本缩容到 0。&lt;/p&gt;

&lt;h2 id=&#34;路由&#34;&gt;路由&lt;/h2&gt;

&lt;p&gt;下图展示了路由到服务某版本的过程中所涉及到的 &lt;a href=&#34;https://github.com/knative/serving/blob/master/docs/spec/overview.md&#34; target=&#34;_blank&#34;&gt;Knative Serving&lt;/a&gt; 模块：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/object_model.png&#34; alt=&#34;Object Model&#34; /&gt;&lt;/p&gt;

&lt;p&gt;版本是代码、依赖和配置的的只读快照。没有被路由引用的版本会被放弃，其中的 Kubernetes 资源会被删除。&lt;/p&gt;

&lt;p&gt;我们可以看到当前的路由：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl routes list --namespace helloworld
Routes in namespace &#39;helloworld&#39;

Name   Traffic         All Traffic Assigned  Ready  Domain                        Age
hello  100% -&amp;gt; hello:  true                  true   hello.helloworld.example.com  2h
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;缩容至-0&#34;&gt;缩容至 0&lt;/h2&gt;

&lt;p&gt;如果离开五分钟再回来，你会发现 &lt;code&gt;hello-00002&lt;/code&gt; Pod 正在被终结或者已经不见了：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS        RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running       0          6m
hello-00002-deployment-7874bf89b8-4b4k5   2/3     Terminating   0          5m
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;下一次 &lt;code&gt;knctl curl&lt;/code&gt;，Knative 会动态的启动一个 Pod 来满足这一请求。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ knctl curl --namespace helloworld --service hello
$ kubectl get pods --namespace helloworld
NAME                                      READY   STATUS    RESTARTS   AGE
hello-00001-deployment-5864685cbc-v8r7n   3/3     Running   0          8m
hello-00002-deployment-7874bf89b8-kfbm2   3/3     Running   0          10s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我还不太清楚为什么 &lt;code&gt;hello-00001-deployment-...&lt;/code&gt; Pod 没有被缩容和终结。&lt;/p&gt;

&lt;h2 id=&#34;未完待续&#34;&gt;未完待续&lt;/h2&gt;

&lt;p&gt;后续文章中将会尝试：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knative Build 组件：使用 &lt;code&gt;Dockerfile&lt;/code&gt; 或者 Cloud Foundry buildpack 自动从定制代码构建容器镜像（代码可以保存本地或者 Git 仓库之中）。&lt;/li&gt;
&lt;li&gt;为 Kubernetes 的负载均衡设置 DNS，从而为 Knative 路由和服务提供公共 URL。&lt;/li&gt;
&lt;li&gt;在不同版本之间进行流量分割（例如 10% 到最新版本，90% 到前一版本；然后将 100% 分配给新版本，老版本流量降低到 0%）。&lt;/li&gt;
&lt;li&gt;Knative Eventing：在应用中进行 &lt;a href=&#34;https://github.com/cloudevents/spec&#34; target=&#34;_blank&#34;&gt;CloudEvents&lt;/a&gt;的绑定和分发。让你的服务更加“无服务器”。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;社区&#34;&gt;社区&lt;/h2&gt;

&lt;p&gt;Knative 核心团队有自己的 &lt;a href=&#34;https://knative.slack.com/&#34; target=&#34;_blank&#34;&gt;Knative Slack&lt;/a&gt;，可以在 &lt;a href=&#34;https://slack.knative.dev&#34; target=&#34;_blank&#34;&gt;https://slack.knative.dev&lt;/a&gt; 申请加入。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://groups.google.com/forum/#!forum/knative-dev&#34; target=&#34;_blank&#34;&gt;knative-dev Group&lt;/a&gt; 中包含了总结和提议。&lt;/p&gt;

&lt;h2 id=&#34;鸣谢&#34;&gt;鸣谢&lt;/h2&gt;

&lt;p&gt;感谢 Google 的 &lt;a href=&#34;https://m.chmarny.com/&#34; target=&#34;_blank&#34;&gt;Mark Chmarny&lt;/a&gt;，在 2018 Spring One 上首先回应了我的问题。&lt;/p&gt;

&lt;p&gt;感谢 Pivotal 的 &lt;a href=&#34;https://github.com/cppforlife&#34; target=&#34;_blank&#34;&gt;Dmitriy Kalinin&lt;/a&gt; 花时间帮助我将 Knative 运行起来，并给我展示了他的 &lt;a href=&#34;https://github.com/cppforlife/knctl&#34; target=&#34;_blank&#34;&gt;knctl Knative CLI&lt;/a&gt;，以及 &lt;a href=&#34;https://github.com/cppforlife/kwt&#34; target=&#34;_blank&#34;&gt;kwt Kubernetes Workstation Tools&lt;/a&gt;。相对于 YAML + &lt;code&gt;kubectl&lt;/code&gt; 组合来说，一个好用的客户端工具更能够帮助 Knative 走向实用。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Knative：在 Kubernetes 上构建可移植 Serverless 平台</title>
      <link>/post/knative-enables-portable-serverless/</link>
      <pubDate>Thu, 20 Sep 2018 17:13:03 +0800</pubDate>
      <guid>/post/knative-enables-portable-serverless/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;https://thenewstack.io/knative-enables-portable-serverless-platforms-on-kubernetes-for-any-cloud/&#34; target=&#34;_blank&#34;&gt;Knative Enables Portable Serverless Platforms on Kubernetes, for Any Cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://thenewstack.io/author/dan-baskette/&#34; target=&#34;_blank&#34;&gt;Dan Baskette&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://kubernetes.io/&#34; target=&#34;_blank&#34;&gt;Kubernetes&lt;/a&gt; 目前如日中天，这一项目不仅在容器编排方面独占鳌头，还给基础设施自动化进程提供了可实践的原语。&lt;/p&gt;

&lt;p&gt;但是我们注意到，开发团队在进行基于 Kubernetes 的应用部署时常有困扰。Kubernetes 毕竟只会推送容器——要想推送应用代码或者 Function，很明显就不是 Kubernetes 的能力所在了。&lt;/p&gt;

&lt;p&gt;这样一来，就有不少厂商以 K8S 作为基础设施，展开了高级抽象方面的竞争。这也是 &lt;a href=&#34;http://github.com/knative&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt; 的着眼点。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/kelseyhightower&#34; target=&#34;_blank&#34;&gt;Kelsey Hightower&lt;/a&gt;：Kubernetes 是一个用来构建平台的平台。它是起跑线，不是目的地。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;function-是值得注意的下一次抽象&#34;&gt;Function 是值得注意的下一次抽象&lt;/h2&gt;

&lt;p&gt;读者可能已经注意到分布式系统世界的新晋成员：FaaS（Functions/Serverless）。Function 是一种新的抽象方式，让开发人员能够轻松的运行部署代码片段，并具备根据事件进行伸缩的能力。&lt;/p&gt;

&lt;p&gt;这对开发人员来说是非常有吸引力的。为什么？把所有的基础设施和应用启动之前的事件处理都抽象之后，开发人员能够完全专注于解决如何使用 Function 的代码处理事件的问题。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://storage.googleapis.com/cdn.thenewstack.io/media/2018/07/26b7e88b-danb1.png&#34; alt=&#34;抽象策略&#34; /&gt;&lt;/p&gt;

&lt;p&gt;天下自然是没有免费的午餐了，FaaS 的问题在哪里呢？&lt;/p&gt;

&lt;p&gt;市场上有很多 FaaS 方案，每个都是独一无二的，他们有自己的 Function 触发方式，自己的可接受事件格式范围，独特的伸缩功能以及从各自角度触发，为开发人员作出的各种抽象。&lt;/p&gt;

&lt;p&gt;如果有要用到的抽象，可以寄希望于云供应商将其打包并为你提供服务。Azure Functions、Lambda 以及 Google Cloud Function 就是这样工作的：根据事件运行 Function 代码，按需伸缩。这类产品按照用量进行计费——根据调用量收取费用。&lt;/p&gt;

&lt;p&gt;开源社区的开发者们也加入了 FaaS 的盛宴，OpenFaaS、Fission、Kubeless 以及 Project Riff 这些项目都是构建在 Kubernetes 之上的 FaaS。这一共同的基础，也有了大同小异的产品。&lt;/p&gt;

&lt;p&gt;在三个核心领域，每个项目都有些许差异：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;都有自己的构建服务，也就是把 Function 进行容器式构建和部署的功能。&lt;/li&gt;
&lt;li&gt;都有一种按调用需要进行扩容（或者缩容）的实现。&lt;/li&gt;
&lt;li&gt;都提供了根据事件调用 Function 的能力，事件可能是 HTTP 或者是事件中间件的发布、订阅方式。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这些细微差异会造成平台采用的巨大障碍。在企业开发者眼里，这一领域功能破碎，竞品众多。所以只能静观其变。&lt;/p&gt;

&lt;h2 id=&#34;knative-适时出现&#34;&gt;Knative 适时出现&lt;/h2&gt;

&lt;p&gt;Google 看到这种碎片化的现状，也注意到了开发人员在 Kubernetes 上进行 Function 开发的过程中对通用工具集的需求。&lt;a href=&#34;http://pivotal.io/knative&#34; target=&#34;_blank&#34;&gt;Knative&lt;/a&gt; 就是基于这种需求产生的。&lt;/p&gt;

&lt;p&gt;Knative 是一个开源软件层，帮助云服务供应商和企业平台在任意云上为开发者提供 Serverless 体验。&lt;/p&gt;

&lt;p&gt;Pivotal 也身在其中，不但向 Knative 贡献了来自 &lt;a href=&#34;https://projectriff.io/&#34; target=&#34;_blank&#34;&gt;riff&lt;/a&gt; 项目的事件模型，还和 Google 一起，在其它方面贡献了开发人员和代码。我们为这一项目的未来欢欣鼓舞，将 riff 和 Knative 结合在一起，酝酿成我们的新项目 &lt;a href=&#34;https://pivotal.io/platform/pivotal-function-service&#34; target=&#34;_blank&#34;&gt;Pivotal Function Service&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;所以对于 Knative 来说，还需要知道点什么呢？这个项目使用 Kubernetes 作为容器编排层。它使用大家熟知的 Kubernetes 对象（Pod、Replica Set 以及 Deployment）构建应用。Istio？是的，Knative 使用 Istio 来进行网格内的路由以及 Ingress 入口管理。&lt;/p&gt;

&lt;p&gt;但是仅仅有 Kubernetes 和 Istio 还是不够的。因此 Knative 同时还引入了三个松耦合的组件，协同对外提供一个完整的 Serverless 平台：Build、Eventing 以及 Serving。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build：提供了一个可插入模型，用于从源码构建容器。&lt;/li&gt;
&lt;li&gt;Eventing：让应用或者 Function 发布到或订阅事件流，事件流包括 Google Cloud Pub/Sub 以及 Apache Kafka。&lt;/li&gt;
&lt;li&gt;Serving：为应用或 Function 提供运行和扩容以及缩容至 0 的能力。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;上述元素融合形成的 Knative 又有何神通？它提供了一种较为简化的部署和运行 function 的方式，包括这些模式：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;从源码构建应用和 Function。&lt;/li&gt;
&lt;li&gt;包含多种构建方法（Cloud Foundry Buildpacks、Bazel、Kaniko、Dockerfiles，并可以扩展支持其他方式）。&lt;/li&gt;
&lt;li&gt;开发者能够轻松部署新的（可路由的）应用和 Function。&lt;/li&gt;
&lt;li&gt;允许应用的不间断升级。&lt;/li&gt;
&lt;li&gt;应用实例的自动伸缩。&lt;/li&gt;
&lt;li&gt;把事件绑定到 Function、应用或者容器上。&lt;/li&gt;
&lt;li&gt;当发生 HTTP 请求时触发 Function。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;稍微深入一点看看这几个组件。&lt;/p&gt;

&lt;h2 id=&#34;build-源码到容器的弹性和可扩展过程&#34;&gt;Build：源码到容器的弹性和可扩展过程&lt;/h2&gt;

&lt;p&gt;开发人员编写源码。Kubernetes 操作容器。如何完成联动？Cloud Foundry 使用 buildpack 来完成这一场景。Knative 提供一个插件模型来完成从代码到容器的构建过程。这一模型通过 CRD 实现，也就是一组 Kubernetes API 对象。这种方式提供了一个构建块，能够作为一个 CI/CD 之类的更大系统的一部分，完成源码的构建。&lt;/p&gt;

&lt;p&gt;Knative 的 Build 组件包含 4 个主要组成部分。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;描述如何获取待构建的源码。位置在 &lt;code&gt;/workspace&lt;/code&gt; 卷中存储，这个内容会在后面的步骤中沿用。通常情况下，源码会保存在 git gcs 之类的版本控制系统中，也可以用自定义容器来访问源码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;步骤或模板&lt;/strong&gt;：这是构建容器的实际工作。这个过程简单说来就是根据 Build 规范完成一系列步骤。换句话说，这一过程由一组可插接构建器组成，被设计用来从源码构建容器，目前这个模型支持五种构建模板，提供了可共享的构建过程：&lt;a href=&#34;https://docs.cloudfoundry.org/buildpacks/&#34; target=&#34;_blank&#34;&gt;Cloud Foundry Buildpacks&lt;/a&gt;、&lt;a href=&#34;https://cloud.google.com/container-builder/docs/&#34; target=&#34;_blank&#34;&gt;Google Container Builder&lt;/a&gt;、Bazel、Kaniko 以及 Jib。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Account&lt;/strong&gt;：用来运行构建过程的账号。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存储卷&lt;/strong&gt;：可以定义多个卷，来提供对构建步骤的支持。这些卷可以有很多用途，例如共享 Secret 或者在多个步骤间提供缓存。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;serving-按需伸缩以及版本为基础的高级运维&#34;&gt;Serving：按需伸缩以及版本为基础的高级运维&lt;/h2&gt;

&lt;p&gt;自动化升级了开发者的工作流。Serving 的自动化范围覆盖了从容器到运行中的 Function 部分。它还提供了容器的快速部署，以及根据进入请求完成扩容到 N 或缩容到 0 的能力支持。Istio 在版本之间进行路由，这使得不间断升级、蓝绿部署、金丝雀测试以及回滚都成为了可能。&lt;/p&gt;

&lt;p&gt;Serving 包含了四个 CRD：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;管理应用和 Function 的生命周期以及提供控制点。它可以处理对象的生成，来保障应用或者 Function 的任何版本更新都具备网络路由、配置以及版本支持。&lt;/li&gt;
&lt;li&gt;代码和配置的固定快照。一个版本会引用一个容器以及创建这个容器所需的内容。历史中可以包含多个版本，这样就能够支持一些蓝绿部署或者回退之类的高级运维工作。&lt;/li&gt;
&lt;li&gt;网络端点到一或多个应用版本的映射。&lt;/li&gt;
&lt;li&gt;定义了部署的最新版本以及各版本的状态。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&#34;images/7346ed16-danb2.png&#34; alt=&#34;serving&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;eventing-把订阅-发布操作进行抽象-简化开发人员工作&#34;&gt;Eventing：把订阅/发布操作进行抽象，简化开发人员工作&lt;/h2&gt;

&lt;p&gt;Function 的基本存在价值就是用来响应事件。FaaS 项目和受管服务的区别就是事件的接收以及消费方式。Knative Eventing 组件用来对事件系统的后端进行抽象，从而解放开发人员。开发人员无需了解消息平台、不用关注数据复制等问题。&lt;/p&gt;

&lt;p&gt;Knative 提供了 CRD 用于事件的生产和消费。Eventing 组件由两类 CRD 组成：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Channel&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;发布/订阅模型中发布者发送消息的目标。一般来说，Channel 是一组位置用于获取或存储事件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bus&lt;/strong&gt;：Channel 的后端。这是为事件提供消息平台支持的底层，可以是 Google Cloud PubSub、Apache Kafka 以及 RabbitMQ 等。&lt;/li&gt;
&lt;li&gt;这些结合起来告知 Knative 服务，特定 Channel 的消息会被哪个应用或者 Function 消费。这是应用和 Function 的入口地址。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feeds&lt;/strong&gt;：事件携带的附件。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&#34;images/88636989-danb3.png&#34; alt=&#34;eventing&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;试用你能掌控的最高级抽象&#34;&gt;试用你能掌控的最高级抽象&lt;/h2&gt;

&lt;p&gt;Knative 是一个全新事物，但是已经有了很多资源可供学习和参考。企业开发软件数量暴涨，意味着典型情况下，公司都会谋求试用应用平台、容器编排以及 Function。Pivotal 希望在所有不同抽象中驱动开源软件的发展。Cloud Foundry、Kubernetes 以及 Knative 会成为大公司的软件构建和运行过程中的主要推手。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/knative/docs&#34; target=&#34;_blank&#34;&gt;Knative 文档&lt;/a&gt;是该项目的主要信息源。每个组件都在仓库中有自己的一席之地，让用户可以跟进最新进展。&lt;/li&gt;
&lt;li&gt;可以阅读 &lt;a href=&#34;https://content.pivotal.io/blog&#34; target=&#34;_blank&#34;&gt;Pivotal 博客&lt;/a&gt;，Ryan Morgan 在其中发布了关于 Pivotal 在 Knative 项目中贡献的相关内容，会涉及企业应用 Serverless 的更多案例。&lt;/li&gt;
&lt;li&gt;在 Google Cloud 也有很多资料：

&lt;ul&gt;
&lt;li&gt;Knative &lt;a href=&#34;https://cloud.google.com/knative&#34; target=&#34;_blank&#34;&gt;概览页面&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knative &lt;a href=&#34;https://cloudplatform.googleblog.com/2018/07/bringing-the-best-of-serverless-to-you.html&#34; target=&#34;_blank&#34;&gt;博客&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;如果想要知道 &lt;a href=&#34;https://projectriff.io/&#34; target=&#34;_blank&#34;&gt;riff 项目&lt;/a&gt; 的信息，官方网站是最好的起步地点。其中包含了所有的文档和对 &lt;a href=&#34;https://github.com/projectriff/riff&#34; target=&#34;_blank&#34;&gt;riff 仓库&lt;/a&gt;的引用。&lt;/li&gt;
&lt;li&gt;想要了解更多？&lt;a href=&#34;https://springoneplatform.io/2018/sessions&#34; target=&#34;_blank&#34;&gt;SpringOne 平台有一套 Serverless 课程&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
