K8S 生态周报| 2019.04.01~2019.04.07

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。Kubernetes client-go v11.0.0 正式发布这是最后一个使用 dep 作为依赖管理的版本,后续版本将转向使用 go modules.Kubernetes 生态中的相关项目大多都已转向或正在转向使用 go modules 了,这也是一个技术风向,理性选择。Releasecontainerd 1.2.6 正式发布这是 containerd 1.2 的第 6 个 patch 版本,主要更新:在默认的 seccomp profile 白名单增加了 io_pgetevents 和 statx 这两个系统调用;修复了在 1.2.5 中自定义 cgroup path 无法工作的 bug;更新 CNI 插件到 v0.7.5 以修复 CVE-2019-9946;更新 runc 版本,修复在无 SELinux 系统下的失败情况;当然还有一些其他的改进和修复,比如修复了 pod 的 UTS namespace 等,建议阅读 ReleaseNote。Docker CE 19.03.0-beta1 版本发布这是 Docker CE 修改发布周期后,第二个发布的版本,上个版本是 Docker CE 18.09 。从发布周期来看,由原先的季度发布改成半年发布,也意味着 Docker 的日渐成熟。正式版估计会在 5 月发布,从 beta 版中能看到一些主要更新:API 更新至 v1.40;允许以非 root 用户运行 dockerd (Rootless mode),这将更有利于容器安全(这也是我最期待的一个特性);移除 v1 manifest 支持;移除 AuFS 存储驱动支持,会有提示信息(当前是废弃,还未完全移除,在上个版本中 devicemapper 也已被标记为废弃);实验性的对 compose 和 Kubernetes 提供一些额外支持,比如 x-pull-secret 和 x-pull-policy;实验性的对 Windows 和 LCOW 提供一些支持:比如提供对 cpu 和 内存的限制;除此之外,在 builder 和 API 方面也都有一些修复和改进,建议阅读 ReleaseNote。推荐阅读: Linkerd v2 从产品中吸取的教训Linkerd v2 使用 Go 和 Rust 进行了重写,这篇文章是在 Linkerd v2 发布 6 个月之后写的,该团队认为使用 Go 和 Rust 重写是非常值得的,并且也已经在生产中得到了验证。文章内容不错,推荐阅读。文章地址 Linkerd v2: How Lessons from Production Adoption Resulted in a Rewrite of the Service Mesh。可以通过下面二维码订阅我的文章公众号【MoeLove】 ...

April 8, 2019 · 1 min · jiezi

容器环境下的持续集成最佳实践:构建基于 Drone + GitFlow + K8s 的云原生语义化 CI 工作流

云原生 (Cloud Native) 是伴随的容器技术发展出现的的一个词,最早出自 Pivotal 公司(即开发了 Spring 的公司)的一本技术小册子 Migrating to Cloud-Native Application Architectures, 其中定义了云原生应用应当具备的一些特质,如无状态、可持续交付、微服务化等。随后云原生概念被广为引用,并围绕这一概念由数家大厂牵头,成立了 CNCF 基金会来推进云原生相关技术的发展,主要投资并孵化云原生生态内的若干项目,包括了如 Kubernetes / etcd / CoreDNS 等耳熟能详的重要项目。而这张大大的云原生版图仍然在不断的扩展和完善。从个人理解来说,传统的应用由于年代久远,更多会考虑单机部署、进程间通信等典型的“单机问题”,虽然也能工作在容器下,但由于历史包袱等原因,架构上已经很难做出大的调整。而“云原生”的应用大都是从一开始就为容器而准备,很少考虑在单机环境下使用,有些甚至无法脱离容器环境工作;考虑的场景少,从而更轻量,迭代更快。比如 etcd 之于 zookeeper , traefik 之于 nginx 等,相信只要在容器环境下实现一次同样的功能,就能强烈的体会到云原生应用所特有的便捷之处。在 CNCF 的版图下,持续集成与持续交付(Continuous Integration & Delivery)板块一直缺少一个钦定的主角,虽然也不乏 Travis CI、GitLab、Jenkins 这样的知名项目,但最能给人云原生应用感觉的,应该还是 Drone 这个项目,本文将围绕 Drone 结合 GitFlow 及 Kubernetes 介绍一些容器环境下持续集成、持续发布 (CI/CD) 方面的实践经验。主流 CI/CD 应用对比之前我也介绍过基于 Travis CI 的一些持续集成实践。后来经过一些比较和调研,最终选择了 Drone 作为主力 CI 工具。截止本文,团队已经使用 Drone 有 2 年多的时间,从 v0.6 一路用到现在即将发布的 v1.0,虽然也踩了不少坑,但总的来说 Drone 还是可以满足大部分需求,并以不错的势头在完善和发展的。下面这张表总结了主流的几个 CI/CD 应用的特点项目名称开发语言配置语言公有云服务私有部署备注Travis CIRubyYAML有不支持公共项目免费,私有项目 $69/单进程, $129/2 进程CircleCIClojureYAML有不支持单进程免费,$50/加 1 进程Gitlab CIRubyYAML有支持绑定 Gitlab 代码管理JenkinsJavaGroovy无支持 DroneGoYAML有支持Cloud 版本不支持私有项目,自建版本无此限制Travis CI 和 CircleCI 是目前占有率最高的两个公有云 CI,易用性上相差无几,只是收费方式有差异。由于不支持私有部署,如果并行的任务量一大,按进程收费其实并不划算;而且由于服务器位置的原因,如果推送镜像到国内,速度很不理想。Gitlab CI 虽然好用,但和 Gitlab 是深度绑定的,我们的代码托管在 Github,整体迁移代码库的成本太大,放弃。Jenkins 作为老牌劲旅,也是目前市场占有率最高的 CI,几乎可以覆盖所有 CI 的使用场景,由于使用 Java 编写,配置文件使用 Groovy 语法,非常适合 Java 为主语言的团队。Jenkins 显然是可以满足我们需要的,只是团队并非 Java 为主,又已经习惯了使用 YAML 书写 CI 配置,抱着尝鲜的心态,将 Jenkins 作为了保底的选择。综上,最终选择 Drone 的结论也就不难得出了,Drone 即开源,又可以私有化部署,同时作为云原生应用,官方提供了针对 Docker、Docker Swarm、K8s 等多种容器场景下的部署方案,针对不同容器场景还有特别优化,比如在 Docker Swarm 下 Drone 是以 agent 方式运行 CI 任务的,而在 K8s 下则通过创建 K8s Job 来实现,显然充分利用了容器的优势所在,这也是 Drone 优于其他 CI 应用之处。个人还觉得 Drone 的语法是所有 CI 中最容易理解和掌握的,由于 Drone 每一个步骤都是运行一个 Docker 容器,本地模拟或调试也非常容易。一句话概况 Drone,可以将其看做是可以支持私有化部署的开源版 CircleCI,并且目前仍然没有看到有其他主打这个定位的 CI 工具,因此个人认为 Drone 是 CI/CD 方面云原生应用头把交椅的有力竞争者。容器环境下一次规范的发布应该包含哪些内容技术选型完成后,我想首先演示一下最终的成果,希望能直观的体现出 CI 对自动化效率起到的提升,不过这就涉及到一个问题:在容器环境下,一次发布应该包含哪些内容,其中有哪些部分是可以被 CI 自动化完成的。这个问题虽然每家公司各不相同,不过按经验来说,容器环境下一次版本发布通常包含这样一个 Checklist:[ ] 代码的下载构建及编译[ ] 运行单元测试,生成单元测试报告及覆盖率报告等[ ] 在测试环境对当前版本进行测试[ ] 为待发布的代码打上版本号[ ] 编写 ChangeLog 说明当前版本所涉及的修改[ ] 构建 Docker 镜像[ ] 将 Docker 镜像推送到镜像仓库[ ] 在预发布环境测试当前版本[ ] 正式发布到生产环境看上去很繁琐对吗,如果每次发布都需要人工去处理上述的所有内容,不仅容易出错,而且也无法应对 DevOps 时代一天至少数次的发布频率,那么下面就来使用 CI 来解决所有问题吧。CI 流程演示为了对 CI 流程有最直观的认识,我创建了一个精简版的 Github 项目 AlloVince/drone-ci-demo 来演示完整的流程,同时项目对应的 CI 地址是 cloud.drone.io/AlloVince/drone-ci-demo ,项目自动构建的 Docker 镜像会推送到 docker registry 的 allovince/drone-ci-demo,。为了方便说明,假设这个项目的核心文件只有 index.html 一个静态页面。单人开发模式目前这个项目背后的 CI 都已经配置部署好,假设我是这个项目的唯一开发人员,如何开发一个新功能并发布新版本呢?Clone 项目到本地, 修改项目代码, 如将 Hello World 改为 Hello World V2。git add .,然后书写符合约定的 Commit 并提交代码, git commit -m “feature: hello world v2”推送代码到代码库git push,等待数分钟后,开发人员会看到单元测试结果,Github 仓库会产生一次新版本的 release,release 内容为当前版本的 ChangeLog, 同时线上已经完成了新功能的发布。虽然在开发者看来,一次发布简单到只需 3 个指令,但背后经过了如下的若干次交互,这是一次发布实际产生交互的时序图,具体每个环节如何工作将在后文中详细说明。多人开发模式一个项目一般不止一个开发人员,比如我是新加入这个项目的成员,在这个 Demo 中应该如何上线新功能呢?同样非常简单:Clone 项目到本地,创建一个分支来完成新功能的开发, git checkout -b feature/hello-world-v3。在这个分支修改一些代码,比如将Hello World V2修改为Hello World V3git add .,书写符合规范的 Commit 并提交代码, git commit -m “feature: hello world v3”将代码推送到代码库的对应分支, git push origin feature/hello-world如果功能已经开发完毕,可以向 Master 分支发起一个 Pull Request,并让项目的负责人 Code ReviewReview 通过后,项目负责人将分支合并入主干,Github 仓库会产生一次新版本的 release,同时线上已经完成了新功能的发布。这个流程相比单人开发来多了 2 个环节,很适用于小团队合作,不仅强制加入了 Code Review 把控代码质量,同时也避免新人的不规范行为对发布带来影响。实际项目中,可以在 Github 的设置界面对 master 分支设置写入保护,这样就从根本上杜绝了误操作的可能。当然如果团队中都是熟手,就无需如此谨慎,每个人都可以负责 PR 的合并,从而进一步提升效率。GitFlow 开发模式在更大的项目中,参与的角色更多,一般会有开发、测试、运维几种角色的划分;还会划分出开发环境、测试环境、预发布环境、生产环境等用于代码的验证和测试;同时还会有多个功能会在同一时间并行开发。可想而知 CI 的流程也会进一步复杂。能比较好应对这种复杂性的,首选 GitFlow 工作流, 即通过并行两个长期分支的方式规范代码的提交。而如果使用了 Github,由于有非常好用的 Pull Request 功能,可以将 GitFlow 进行一定程度的简化,最终有这样的工作流:以 dev 为主开发分支,master 为发布分支开发人员始终从 dev 创建自己的分支,如 feature-afeature-a 开发完毕后创建 PR 到 dev 分支,并进行 code reviewreview 后 feature-a 的新功能被合并入 dev,如有多个并行功能亦然待当前开发周期内所有功能都合并入 dev 后,从 dev 创建 PR 到 masterdev 合并入 master,并创建一个新的 release上述是从 Git 分支角度看代码仓库发生的变化,实际在开发人员视角里,工作流程是怎样的呢。假设我是项目的一名开发人员,今天开始一期新功能的开发:Clone 项目到本地,git checkout dev。从 dev 创建一个分支来完成新功能的开发, git checkout -b feature/feature-a。在这个分支修改一些代码,比如将Hello World V3修改为Hello World Feature Agit add .,书写符合规范的 Commit 并提交代码, git commit -m “feature: hello world feature A"将代码推送到代码库的对应分支, git push origin feature/feature-a:feature/feature-a由于分支是以feature/命名的,因此 CI 会运行单元测试,并自动构建一个当前分支的镜像,发布到测试环境,并自动配置一个当前分支的域名如 test-featue-a.avnpc.com联系产品及测试同学在测试环境验证并完善新功能功能通过验收后发起 PR 到 dev 分支,由 Leader 进行 code reviewCode Review 通过后,Leader 合并当前 PR,此时 CI 会运行单元测试,构建镜像,并发布到测试环境此时 dev 分支有可能已经积累了若干个功能,可以访问测试环境对应 dev 分支的域名,如 test.avnpc.com,进行集成测试。集成测试完成后,由运维同学从 Dev 发起一个 PR 到 Master 分支,此时会 CI 会运行单元测试,构建镜像,并发布到预发布环境测试人员在预发布环境下再次验证功能,团队做上线前的其他准备工作运维同学合并 PR,CI 将为本次发布的代码及镜像自动打上版本号并书写 ChangeLog,同时发布到生产环境。由此就完成了上文中 Checklist 所需的所有工作。虽然描述起来看似冗长,但不难发现实际作为开发人员,并没有任何复杂的操作,流程化的部分全部由 CI 完成,开发人员只需要关注自己的核心任务:按照工作流规范,写好代码,写好 Commit,提交代码即可。接下来将介绍这个以 CI 为核心的工作流,是如何一步步搭建的。Step by Step 构建 CI 工作流Step.0: 基于 K8s 部署 Drone v1.0.0以 Github 为例,截止本文完成时间(2019 年 3 月 28 日), Drone 刚刚发布了第一个正式版本 v1.0.0。官方文档已经提供了分别基于 Docker、K8s 的 Drone 部署说明,不过比较简略,因此这里给出一个相对完整的配置文件。首先需要在 Github 创建一个 Auth App,用于 repo 的访问授权。应用创建好之后,会得到 Client ID 和 Client Secret 。同时 Authorization callback URL 应填写 Drone 服务对应域名下的 /login,如https://ci.avnpc.com/loginDrone 支持 SQLite、MySQL、Postgres、S3 等多种后端存储,主要用于记录 build logs 等文本信息,这些信息并不是特别重要,且我们的 CI 有可能做迁移,因此个人更推荐使用 SQLite。而在 K8s 环境下,SQLite 更适合用挂载 NAS 的方式供节点使用,因此首先将存储的部分独立为文件drone-pvc.yml,可以根据实际情况配置 nfs.path 和 nfs.serverkubectl apply -f drone-pvc.yamlDrone 的配置主要涉及两个镜像:drone/kubernetes-secrets 加密数据服务,用于读取 K8s 的 secretsdrone/drone:1.0.0-rc.6 就是 Drone 的 server 端,由于在 K8s 下 Drone 利用了 Job 机制,因此不需要部署 agent。这部分配置较长,可以直接参考示例 drone.yaml主要涉及到的配置项包括:drone/kubernetes-secrets 镜像中SECRET_KEY: 数据加密传输所用的 key,可以使用 openssl rand -hex 16 生成一个drone/drone镜像中DRONE_KUBERNETES_ENABLED: 开启 K8s 模式DRONE_KUBERNETES_NAMESPACE: Drone 所使用的 Namespace, 这里使用 defaultDRONE_GITHUB_SERVER: Github 服务器地址,一般为 https://github.comDRONE_GITHUB_CLIENT_ID: 上文创建 Github Auth App 得到的 Client IDDRONE_GITHUB_CLIENT_SECRET: 上文创建 Github Auth App 得到的 Client SecretDRONE_SERVER_HOST: Drone 服务所使用的域名DRONE_SERVER_PROTO: http 或 httpsDRONE_DATABASE_DRIVER: Drone 使用的数据库类型,这里为 sqlite3DRONE_DATABASE_DATASOURCE: 这里为 SQLite 数据库的存放路径DRONE_SECRET_SECRET: 对应上文的 SECRET_KEYDRONE_SECRET_ENDPOINT: 加密数据服务的地址,这里通过 k8s service 暴露,无需修改最后部署即可kubectl apply -f drone.yaml部署后首次登录 Drone 就会跳转到 Github Auth App 进行授权,授权完毕后可以看到所有能读写的 Repo,选择需要开启 CI 的 Repo,点击 ACTIVATE 即可。 如果开启成功,在 Github Repo 的 Settings > Webhooks 下可以看到 Drone 的回调地址。Step.1: Hello World for Drone在正式开始搭建工作流之前,首先可以测试一下 Drone 是否可用。Drone 默认的配置文件是 .drone.yml, 在需要 CI 的 repo 根目录下创建.drone.yml, 内容如下,提交并git push到代码仓库即可触发 Drone 执行 CI。kind: pipeline name: deploy steps: - name: hello-world image: docker commands: - echo “hello world"Drone v1 的语法主要参考的 K8s 的语法,非常直观,无需阅读文档也可以知道,我们首先定义了一个管道 (pipeline),管道由若干步骤 (step) 组成,Drone 的每个步骤是都基于容器实现的,因此 Step 的语法就回到了我们熟悉的 Docker,一个 Step 会拉取 image 定义的镜像,然后运行该镜像,并顺序执行 commands 定义的指令。 在上例中,Drone 首先 clone git repo 代码到本地,然后根据 .drone.yml 所定义的,拉取 Docker 的官方镜像,然后运行该进行并挂载 git repo 的代码到 /drone/src 目录。在 Drone 的界面中,也可以清楚的看到这一过程。本阶段对应代码部分: https://github.com/AlloVince/...Drone 构建记录: https://cloud.drone.io/AlloVi...Docker 镜像: 无Step.2: 单人工作流,自动化单元测试与 Docker 镜像构建有了 Hello World 的基础,接下来我们尝试将这个工作流进行扩充。为了方便说明,这里假设项目语言为 js,项目内新增了test/index.js文件用于模拟单元测试,一般在 CI 中,只要程序的返回值为 0,即代表运行成功。这个文件中我们仅仅输出一行 Log Unit test passed用于模拟单元测试通过。 我们希望将代码打包成 Docker 镜像,根目录下增加了 Dockerfile 文件,这里直接使用 Nginx 的官方镜像,构建过程只有 1 行COPY index.html /usr/share/nginx/html/, 这样镜像运行后可以通过 http 请求看到index.html的内容。至此我们可以将工作流改进为:当 master 分支接收到 push 后,运行单元测试当 github 发布一次 release, 构建 Docker 镜像,并推送到镜像仓库对应的 Drone 配置文件如下kind: pipeline name: deploy steps: - name: unit-test image: node:10 commands: - node test/index.js when: branch: master event: push - name: build-image image: plugins/docker settings: repo: allovince/drone-ci-demo username: allovince password: from_secret: DOCKER_PASSWORD auto_tag: true when: event: tag虽然比 Hello World 复杂了一些,但是可读性仍然很好,配置文件中出现了几个新概念:Step 运行条件, 即 when 部分,上例中展示了当代码分支为 master,且收到一个 push;以及当代码被标记 tag 这两种情况。Drone 还支持 repo、运行结果等很多其他条件,可以参考 Drone Conditions 文档。Plugin 插件,上例中用于构建和推送镜像的是 plugins/docker 这个 Plugin, 一个 Plugin 本质上仍然是一个 Docker 镜像,只是按照 Drone 的规范接受特定的输入,并完成特定的操作。所以完全可以将 Plugin 看做一个无法更改 command 的 Docker 镜像。Docker 这个 Plugin 由 Drone 官方提供,用于 Docker 镜像的构建和推送,具体的用法可以查看Docker 插件的文档 。例子中演示的是将镜像推送到私有仓库,如果不做特殊配置,镜像将被推送到 Docker 的官方仓库。 此外 Docker 插件还有一个很方便的功能,如果设置 auto_tag: true,将根据代码的版本号自动规划 Docker 镜像的标签,如代码版本为1.0.0,将为 Docker 镜像打三个标签 1, 1.0, 1.0.0。如果代码版本号不能被解析,则镜像标签为 latest。目前 Drone 的插件已经有很多,可以覆盖主流的云服务商和常见的工作流,并且自己制作插件的成本也不高。Secret 加密数据,镜像仓库的用户名和密码都属于敏感信息,因此可以使用 from_secret 获取加密数据。一条加密数据就是一个 key / value 对,如上例中的 DOCKER_PASSWORD 就是我们自己定义的加密数据 key。即便加密数据在 log 中被打印,UI 也只能看到 。加密数据的 value 需要提前保存好,保存的方式有 3 种:通过 Drone UI 界面中, repo -> Settings -> Secrets 添加,所添加的加密数据将保存在 Drone 的数据库中,仅能在当前 repo 中使用。通过Drone cli 加密后保存在 .drone.yml文件中, 使用范围仅限 yaml 文件内通过 K8s 保存为K8s Secret,称为 External Secrets,所有的 repo 都可以共享。如果是团队使用的话,这种保存方式显然是最方便的,但也要注意安全问题,因此 External Secrets 还支持 repo 级别的权限管理, 可以只让有当前 repo 写入权限的人才能使用对应 secret。这个阶段对应代码仓库: https://github.com/AlloVince/...push 时触发的 Drone CI: https://cloud.drone.io/AlloVi...release 时触发的 Drone CI: https://cloud.drone.io/AlloVi...release 后 CI 构建的 Docker 镜像: allovince/drone-ci-demo:latestStep.3: GitFlow 多分支团队工作流上面的工作流已经基本可以应付单人的开发了,而在团队开发时,这个工作流还需要一些扩展。不需要引入 Drone 的新功能,只需要在上文基础上根据分支做一点调整即可。首先保证单元测试位于 steps 的第一位,并且限定团队工作的分支,在 push 和 pull_request 时,都能触发单元测试。- name: unit-test image: node:10 commands: - node test/index.js when: branch: include: - feature/ - master - dev event: include: - push - pull_request然后根据 Gitflow 的流程对于不同的分支构建 Docker 镜像并打上特定标签,以 feature 分支为例,下面的配置约定了当分支名满足 feature/,并收到 push 时,会构建 Docker 镜像并打标签,标签名称为当前分支名去掉 feature/。如分支 feature/readme, 对应 docker 镜像为 allovince/drone-ci-demo:readme,考虑到 feature 分支一般都出于开发阶段,因此新的镜像会覆盖旧的。配置如下- name: build-branch-image image: plugins/docker settings: repo: allovince/drone-ci-demo username: allovince password: from_secret: DOCKER_PASSWORD tag: - ${DRONE_BRANCH##feature/} when: branch: feature/ event: push镜像的 Tag 处不再使用自动方式,其中DRONE_BRANCH是 Drone 的内置环境变量 (Environment),对应当前的分支名。##feature/是执行了一个字符串的替换操作 (Substitution)。更多的环境变量和字符串操作都可以在文档中找到。以此类推,可以查看这个阶段的完整 .drone.yml ,此时我们的工作流示例如下:团队成员从 dev 分支 checkout 自己的分支 feature/readme向feature/readme提交代码并 push, CI 运行单元测试,构建镜像allovince/drone-ci-demo:readme功能开发完成后,团队成员向 dev 分支 发起 pull request , CI 运行单元测试团队其他成员 merge pull request, CI 运行单元测试,构建镜像allovince/drone-ci-demo:test运维人员从 dev 向 master 发起 pull request,CI 运行单元测试,并构建镜像allovince/drone-ci-demo:latest运维人员 merge pull request, 并 release 新版本 pre-0.0.2, CI 构建镜像allovince/drone-ci-demo:pre-0.0.2可能细心的同学会发现 dev -> master 的 pull request 时,构建镜像失败了,这是由于 Drone 出于安全考虑限制了在 pull request 时默认无法读取加密数据,因此无法得到 Docker Registry 密码。如果是私有部署的话,可以在 Repo Settings 中勾选Allow Pull Requests,此处就可以构建成功。Step.4: 语义化发布上面基本完成了一个支持团队协作的半自动 CI 工作流,如果不是特别苛刻的话,完全可以用上面的工作流开始干活了。不过基于这个工作流工作一段时间,会发现仍然存在痛点,那就是每次发布都要想一个版本号,写 ChangeLog,并且人工去 release。标记版本号涉及到上线后的回滚,追溯等一系列问题,应该是一项严肃的工作,其实如何标记早已有比较好的方案,即语义化版本。在这个方案中,版本号一共有 3 位,形如 1.0.0,分别代表:主版本号:当你做了不兼容的 API 修改,次版本号:当你做了向下兼容的功能性新增,修订号:当你做了向下兼容的问题修正。虽然有了这个指导意见,但并没有很方便的解决实际问题,每次发布要搞清楚代码的修改到底是不是向下兼容的,有哪些新的功能等,仍然要花费很多时间。而语义化发布 (Semantic Release) 就能很好的解决这些问题。语义化发布的原理很简单,就是让每一次 Commit 所附带的 Message 格式遵守一定规范,保证每次提交格式一致且都是可以被解析的,那么进行 Release 时,只要统计一下距离上次 Release 所有的提交,就分析出本次提交做了何种程度的改动,并可以自动生成版本号、自动生成 ChangeLog 等。语义化发布中,Commit 所遵守的规范称为约定式提交 (Conventional Commits)。比如 node.js、 Angular、Electron 等知名项目都在使用这套规范。语义化发布首先将 Commit 进行分类,常用的分类 (Type) 有:feat: 新功能fix: BUG 修复docs: 文档变更style: 文字格式修改refactor: 代码重构perf: 性能改进test: 测试代码chore: 工具自动生成每个 Commit 可以对应一个作用域(Scope),在一个项目中作用域一般可以指不同的模块。当 Commit 内容较多时,可以追加正文和脚注,如果正文起始为BREAKING CHANGE,代表这是一个破坏性变更。以下都是符合规范的 Commit:feat: 增加重置密码功能fix(邮件模块): 修复邮件发送延迟BUGfeat(API): API重构BREAKING CHANGE: API v3上线,API v1停止支持有了这些规范的 Commit,版本号如何变化就很容易确定了,目前语义化发布默认的规则如下Commit版本号变更BREAKING CHANGE主版本号feat次版本号fix / perf修订号因此在 CI 部署 semantic-release 之后,作为开发人员只需要按照规范书写 Commit 即可,其他的都由 CI 完成。具体如何将语义化发布加入 CI 流程中呢, semantic-release 是 js 实现的,如果是 js 的项目,可以直接在package.json中增加配置项,而对于任意语言的项目,推荐像 Demo 中一样,在根目录下增加 配置文件release.config.js。这个配置目的是为了禁用默认开启的 npm 发布机制,可以直接套用。semantic-release 要执行 Github release,因此我们需要在 CI 中配置自己的 Personal access tokens 让 CI 有 Github repo 的读写权限, 可以通过 Github 点击自己头像 -> Settings -> Developer settings -> Personal access tokens -> Generate new token 生成一个 Token。 然后在 Drone 的 repo 设置界面新增一个 Secret, key 为 GITHUB_TOKEN, value 填入刚生成的 Token。最后在 .drone.yml 中增加这样一段就可以了。- name: semantic-release image: gtramontina/semantic-release:15.13.3 environment: GITHUB_TOKEN: from_secret: GITHUB_TOKEN entrypoint: - semantic-release when: branch: master event: push来再次模拟一下流程,feature 分支部分与上文相同从 dev 向 master 发起 pull request,CI 运行单元测试,并构建镜像allovince/drone-ci-demo:latestmerge pull request,CI 会执行单元测试并运行 semantic-release , 运行成功的话能看到 Github 新增 release v1.0.0Github release 再次触发CI 构建生产环境用 Docker 镜像allovince/drone-ci-demo:1.0.0最终我们能得到这样一个赏心悦目的 releaseStep.5: Kubernetes 自动发布Docker 镜像推送到仓库后,我们还剩最后一步就可以完成全自动发布的闭环,即通知 Kubernetes 将镜像发布到生产环境。这一步实现比较灵活,因为很多云服务商在容器服务都会提供 Trigger 机制,一般是提供一个 URL,只要请求这个 URL 就可以触发容器服务的发布。Demo 中我们使用更为通用的方法,就是将 kubectl 打包为容器,以客户端调用 K8s 集群 Master 节点 API ( kube-apiserver ) 的形式完成发布。假设我们在生产环境下 drone-ci-demo 项目的 K8s 发布文件如下— apiVersion: extensions/v1beta1 kind: Deployment metadata: name: ci-demo-deployment namespace: default spec: replicas: 1 template: spec: containers: - image: allovince/drone-ci-demo name: ci-demo restartPolicy: Always对应 .drone.yml 中增加 step 如下。这里使用的插件是honestbee/drone-kubernetes, 插件中kubectl 连接 API 使用的是证书+ Token 的方式鉴权,因此需要先获得证书及 Token, 已经授权的 Token 保存于 k8s secret,可以通过kubectl get secret [ your default secret name ] -o yaml | egrep ‘ca.crt:|token:‘获得并配置到 drone 中,注意插件要求 token 是明文的,需要 base64 解码一下:echo [ your token ] | base64 -d && echo ‘’- name: k8s-deploy image: quay.io/honestbee/drone-kubernetes settings: kubernetes_server: from_secret: KUBERNETES_SERVER kubernetes_cert: from_secret: KUBERNETES_CERT kubernetes_token: from_secret: KUBERNETES_TOKEN namespace: default deployment: ci-demo-deployment repo: allovince/drone-ci-demo container: ci-demo tag: - ${DRONE_TAG} when: event: tag在示例)中,可以看到在语义化发布之后 CI 会将新版本的 Docker 镜像自动发布到 K8s),这里为了演示仅打印了指令并未实际运行。相当于运行了如下的指令:kubectl -n default set image deployment/ci-demo-deployment ci-demo=allovince/drone-ci-demo:v1.0.2由于自动发布的环节势必要接触到生产服务器,需要格外注意安全问题,首推的方式当然是将 CI 和 K8s 集群放于同一内网中,同时可以使用 K8s 的 RBAC 权限控制,为自动发布单独创建一个用户),并删除不必要的权限。后话总结一下,本文展示了从 Hello World 到 单人单分支手动发布 到 团队多分支 GitFlow 工作流 到 团队多分支 semantic-release 语义化发布 到 通知 K8s 全自动发布,如何从零开始一步一步搭建 CI 将团队开发、测试、发布的流程全部自动化的过程,最终能让开发人员只需要认真提交代码就可以完成日常的所有 DevOps 工作。最终 Step 的完成品可以适配之前的所有 Step,如果不太在意实现细节的话,可以在此基础上稍作修改,直接使用。然而写好每一个 Commit 这个看似简单的要求,其实对于大多数团队来说并不容易做到,在实施过程中,经常会遇到团队成员不理解为什么要重视 Commit 规范,每个 Commit 都要深思熟虑是否过于吹毛求疵等等疑问。以 Commit 作为 CI 的核心,个人认为主要会带来以下几方面的影响:一个好的 Commit,代表着开发人员对当前改动之于整个系统的影响,有非常清楚的认识,代码的修改到底算 feat 还是 fix ,什么时候用 BREAKING CHANGE 等都是要仔细斟酌的,每个 Commit 都会在 ChangeLog 里“留底”,从而约束团队不随意提交未经思考的代码,提高代码质量一个好的 Commit 也代表开发人员有能力对所实现功能进行精细的划分,一个分支做的事情不宜过多,一个提交也应该专注于只解决一个问题,每次提交(至少是每次 push )都应该保持系统可构建、可运行、可测试,如果能坚持做到这些,对于合并代码时的冲突解决,以及集成测试都有很大帮助。由于每次发布能清楚的看到所有关联的 Commit 以及 Commit 的重要程度,那么线上事故的回滚也会非常轻松,回滚到哪个版本,回滚后哪些功能会受到影响,只要看 CI 自动生成的 Release 记录就一目了然。如果没有这些,回滚误伤到预期外的功能从而引发连锁反应的惨痛教训,可能很多运维都有过类似经历吧。因此 CI 自动化其实是锦上添花而非雪中送炭,如果团队原本就无视规范,Commit 全是空白或者没有任何意义的单词,分支管理混乱,发布困难,奢望引入一套自动化 CI 来能解决所有这些问题,无疑是不现实的。而只有原本就重视代码质量,有一定规范意识,再通过自动化 CI 来监督约束,团队在 CI 的帮助下代码质量提高,从而有机会进一步改进 CI 的效率,才能形成良性循环。愿天下不再有难发布的版本。References:云原生应用之路相关讨论可以在我的 Telegram Group 给我留言。 ...

April 8, 2019 · 7 min · jiezi

Kubernetes的几种主流部署方式02-kubeadm部署1.14版本高可用集群

在上篇文章minikube部署中,有提到Minikube部署Kubernetes的核心就是Kubeadm,这篇文章来详细说明下Kubeadm原理及部署步骤。写这篇文章的时候,Kubernetes1.14刚刚发布,所以部署步骤以1.14版为主。Kubeadm原理简述Kubeadm工具的出发点很简单,就是尽可能简单的部署一个生产可用的Kubernetes集群。实际也确实很简单,只需要两条命令:# 创建一个 Master 节点$ kubeadm init# 将一个 Node 节点加入到当前集群中$ kubeadm join <Master 节点的 IP 和端口 >kubeadm做了这些事执行 kubeadm init时:自动化的集群机器合规检查自动化生成集群运行所需的各类证书及各类配置,并将Master节点信息保存在名为cluster-info的ConfigMap中。通过static Pod方式,运行API server, controller manager 、scheduler及etcd组件。生成Token以便其他节点加入集群执行 kubeadm join时:节点通过token访问kube-apiserver,获取cluster-info中信息,主要是apiserver的授权信息(节点信任集群)。通过授权信息,kubelet可执行TLS bootstrapping,与apiserver真正建立互信任关系(集群信任节点)。简单来说,kubeadm做的事就是把大部分组件都容器化,通过StaticPod方式运行,并自动化了大部分的集群配置及认证等工作,简单几步即可搭建一个可用Kubernetes的集群。这里有个问题,为什么不把kubelet组件也容器化呢,是因为,kubelet在配置容器网络、管理容器数据卷时,都需要直接操作宿主机,而如果现在 kubelet 本身就运行在一个容器里,那么直接操作宿主机就会变得很麻烦。比如,容器内要做NFS的挂载,需要kubelet先在宿主机执行mount挂载NFS。如果kubelet运行在容器中问题来了,如果kubectl运行在容器中,要操作宿主机的Mount Namespace是非常复杂的。所以,kubeadm选择把kubelet运行直接运行在宿主机中,使用容器部署其他Kubernetes组件。所以,Kubeadm部署要安装的组件有Kubeadm、kubelet、kubectl三个。上面说的是kubeadm部署方式的一般步骤,kubeadm部署是可以自由定制的,包括要容器化哪些组件,所用的镜像,是否用外部etcd,是否使用用户证书认证等以及集群的配置等等,都是可以灵活定制的,这也是kubeadm能够快速部署一个高可用的集群的基础。详细的说明可以参考官方Reference。但是,kubeadm最重要的作用还是解决集群部署问题,而不是集群配置管理的问题,官方也建议把Kubeadm作为一个基础工具,在其上层再去量身定制适合自己的集群的管理工具(例如minikube)。Kubeadm部署一个高可用集群Kubernetes的高可用Kubernetes的高可用主要指的是控制平面的高可用,简单说,就是有多套Master节点组件和Etcd组件,工作节点通过负载均衡连接到各Master。HA有两种做法,一种是将etcd与Master节点组件混布在一起:另外一种方式是,使用独立的Etcd集群,不与Master节点混布:两种方式的相同之处在于都提供了控制平面的冗余,实现了集群高可以用,区别在于:Etcd混布方式:所需机器资源少部署简单,利于管理容易进行横向扩展风险大,一台宿主机挂了,master和etcd就都少了一套,集群冗余度受到的影响比较大。Etcd独立部署方式:所需机器资源多(按照Etcd集群的奇数原则,这种拓扑的集群关控制平面最少就要6台宿主机了)。部署相对复杂,要独立管理etcd集群和和master集群。解耦了控制平面和Etcd,集群风险小健壮性强,单独挂了一台master或etcd对集群的影响很小。部署环境 由于机器资源不足,下面的部署测试,只会以混布的方式部署一个1haproxy,2master,2*node,共5台机器的集群,实际上由于etcd选举要过半数,至少要3台master节点才能构成高可用,在生产环境,还是要根据实际情况,尽量选择风险低的拓扑结构。机器:master-1:192.168.41.230 (控制平面节点1)master-2:192.168.41.231 (控制平面节点2)node-1:172.16.201.108 (工作节点1)node-2:172.16.201.109 (工作节点2)haproxy:192.168.41.231 (haproxy)系统内核版本:# cat /etc/redhat-releaseCentOS Linux release 7.6.1810 (Core) # uname -r 5.0.5-1.el7.elrepo.x86_64集群版本kubeadm:1.14.0Kubernetes:1.14.0Docker:Community 18.09.4haproxy: 1.5.18部署步骤机器准备在所有节点上操作:关闭selinux,firewallsetenforce 0sed -i ’s/SELINUX=enforcing/SELINUX=permissive/’ /etc/selinux/config systemctl stop firewalldsystemctl disable firewalld关闭swap,(1.8版本后的要求,目的应该是不想让swap干扰pod可使用的内存limit)swapoff -a修改下面内核参数,否则请求数据经过iptables的路由可能有问题cat <<EOF > /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1EOFsysctl –system安装kubeadm、docker在除了haproxy以外所有节点上操作将Kubernetes安装源改为阿里云,方便国内网络环境安装cat << EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/enabled=1gpgcheck=1repo_gpgcheck=1gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF安装docker-cewget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum install -y docker-ce安装kubelet kubeadm kubectl yum install -y kubelet kubeadm kubectl安装配置负载均衡在haproxy节点操作:# 安装haproxyyum install haproxy -y # 修改haproxy配置cat << EOF > /etc/haproxy/haproxy.cfgglobal log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemondefaults mode tcp log global retries 3 timeout connect 10s timeout client 1m timeout server 1mfrontend kube-apiserver bind :6443 # 指定前端端口 mode tcp default_backend masterbackend master # 指定后端机器及端口,负载方式为轮询 balance roundrobin server master-1 192.168.41.230:6443 check maxconn 2000 server master-2 192.168.41.231:6443 check maxconn 2000EOF# 开机默认启动haproxy,开启服务systemctl enable haproxysystemctl start haproxy# 检查服务端口情况:# netstat -lntup | grep 6443tcp 0 0 0.0.0.0:6443 0.0.0.0: LISTEN 3110/haproxy部署Kubernetes在master-1节点操作:准备集群配置文件,目前用的api版本为v1beta1,具体配置可以参考官方referencecat << EOF > /root/kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta1kind: ClusterConfigurationkubernetesVersion: v1.14.0 # 指定1.14版本controlPlaneEndpoint: 192.168.41.232:6443 # haproxy地址及端口imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers # 指定镜像源为阿里源networking: podSubnet: 10.244.0.0/16 # 计划使用flannel网络插件,指定pod网段及掩码EOF执行节点初始化systemctl enable kubeletsystemctl start kubeletkubeadm config images pull –config kubeadm-config.yaml # 通过阿里源预先拉镜像kubeadm init –config=kubeadm-config.yaml –experimental-upload-certs安装成功,可以看到输出You can now join any number of the control-plane node running the following command on each as root:# master节点用以下命令加入集群: kubeadm join 192.168.41.232:6443 –token ocb5tz.pv252zn76rl4l3f6 \ –discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 \ –experimental-control-plane –certificate-key 20366c9cdbfdc1435a6f6d616d988d027f2785e34e2df9383f784cf61bab9826Then you can join any number of worker nodes by running the following on each as root:# 工作节点用以下命令加入集群:kubeadm join 192.168.41.232:6443 –token ocb5tz.pv252zn76rl4l3f6 \ –discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 原来的kubeadm版本,join命令只用于工作节点的加入,而新版本加入了 –experimental-contaol-plane 参数后,控制平面(master)节点也可以通过kubeadm join命令加入集群了。加入另外一个master节点在master-2操作:kubeadm join 192.168.41.232:6443 –token ocb5tz.pv252zn76rl4l3f6 --discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 --experimental-control-plane –certificate-key 20366c9cdbfdc1435a6f6d616d988d027f2785e34e2df9383f784cf61bab9826mkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/configchown $(id -u):$(id -g) $HOME/.kube/config 现在,在任何一个master 节点,执行kubectl get no,可以看到,集群中已经有2台master节点了# kubectl get noNAME STATUS ROLES AGE VERSIONmaster-1 NotReady master 34m v1.14.0master-2 NotReady master 4m52s v1.14.0加入两个工作节点分别在两个node节点操作:kubeadm join 192.168.41.232:6443 –token ocb5tz.pv252zn76rl4l3f6 \ –discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 再次执行kubectl get no# kubectl get noNAME STATUS ROLES AGE VERSIONmaster-1 NotReady master 45m v1.14.0master-2 NotReady master 15m v1.14.0node-1 NotReady <none> 6m19s v1.14.0node-2 NotReady <none> 4m59s v1.14.0可以看到两个node节点都加入集群了。可是,各个节点状态为什么都是NotReady呢。通过执行kubectl describe master-1,可以看到这样的提示:runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized原来是因为网络插件没有就绪导致的。所以 ,我们来安装一波kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml再次查看节点状态,可以看到所有节点都已经ready了。# kubectl get noNAME STATUS ROLES AGE VERSIONmaster-1 Ready master 134m v1.14.0master-2 Ready master 104m v1.14.0node-1 Ready <none> 94m v1.14.0node-2 Ready <none> 93m v1.14.0至此,一个2主节点2工作节点的k8s集群已经搭建完毕。如果要加入更多的master或node节点,只要多次执行kubeadm join命令加入集群就好,不需要额外配置,非常方便。集群测试跟上篇文章minikube部署一样,这里部署一个简单的goweb服务来测试集群,运行时暴露8000端口,同时访问/info路径会显示容器的主机名。准备deployment和svc的yaml:# deployment-goweb.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: gowebspec: selector: matchLabels: app: goweb replicas: 4 template: metadata: labels: app: goweb spec: containers: - image: lingtony/goweb name: goweb ports: - containerPort: 8000# svc-goweb.yamlapiVersion: v1kind: Servicemetadata: name: gowebsvcspec: selector: app: goweb ports: - name: default protocol: TCP port: 80 targetPort: 8000部署服务kubectl apply -f deployment-goweb.yamlkubectl apply -y svc-goweb.yaml查看pod及服务[root@master-1 ~]# kubectl get po -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESgoweb-6c569f884-67z89 1/1 Running 0 25m 10.244.1.2 node-1 <none> <none>goweb-6c569f884-bt4p6 1/1 Running 0 25m 10.244.1.3 node-1 <none> <none>goweb-6c569f884-dltww 1/1 Running 0 25m 10.244.1.4 node-1 <none> <none>goweb-6c569f884-vshkm 1/1 Running 0 25m 10.244.3.4 node-2 <none> <none># 可以看到,4个pod分布在不同的node上[root@master-1 ~]# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEgowebsvc ClusterIP 10.106.202.0 <none> 80/TCP 11mkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21h# 暴露80端口测试访问[root@master-1 ~]# curl http://10.106.202.0/infoHostname: goweb-6c569f884-bt4p6[root@master-1 ~]# curl http://10.106.202.0/infoHostname: goweb-6c569f884-67z89[root@master-1 ~]# curl http://10.106.202.0/infoHostname: goweb-6c569f884-vshkm#可以看到,对SVC的请求会在pod间负载均衡。小结本文简单介绍了kubeadm工具原理,以及如何用它部署一个高可用的kubernetes集群。需要注意的是,kubeadm工具总体已经GA,可以在生产环境使用了。但是文中通过"kubeadm join -experimental-contaol-plane"参数增加主节点的方式,还是在alpha阶段,实际在生产环境还是用init方式来增加主节点比较稳定。kubeadm更多详细配置可以参考官方文档 ...

April 2, 2019 · 3 min · jiezi

Kubernetes 中如何保证优雅地停止 Pod

作者:吴叶磊一直以来我对优雅地停止 Pod 这件事理解得很单纯:不就利用是 PreStop hook 做优雅退出吗?但最近发现很多场景下 PreStop Hook 并不能很好地完成需求,这篇文章就简单分析一下“优雅地停止 Pod”这回事儿。何谓优雅停止?优雅停止(Graceful shutdown)这个说法来自于操作系统,我们执行关机之后都得 OS 先完成一些清理操作,而与之相对的就是硬中止(Hard shutdown),比如拔电源。到了分布式系统中,优雅停止就不仅仅是单机上进程自己的事了,往往还要与系统中的其它组件打交道。比如说我们起一个微服务,网关把一部分流量分给我们,这时:假如我们一声不吭直接把进程杀了,那这部分流量就无法得到正确处理,部分用户受到影响。不过还好,通常来说网关或者服务注册中心会和我们的服务保持一个心跳,过了心跳超时之后系统会自动摘除我们的服务,问题也就解决了;这是硬中止,虽然我们整个系统写得不错能够自愈,但还是会产生一些抖动甚至错误。假如我们先告诉网关或服务注册中心我们要下线,等对方完成服务摘除操作再中止进程,那不会有任何流量受到影响;这是优雅停止,将单个组件的启停对整个系统影响最小化。按照惯例,SIGKILL 是硬终止的信号,而 SIGTERM 是通知进程优雅退出的信号,因此很多微服务框架会监听 SIGTERM 信号,收到之后去做反注册等清理操作,实现优雅退出。PreStop Hook回到 Kubernetes(下称 K8s),当我们想干掉一个 Pod 的时候,理想状况当然是 K8s 从对应的 Service(假如有的话)把这个 Pod 摘掉,同时给 Pod 发 SIGTERM 信号让 Pod 中的各个容器优雅退出就行了。但实际上 Pod 有可能犯各种幺蛾子:已经卡死了,处理不了优雅退出的代码逻辑或需要很久才能处理完成。优雅退出的逻辑有 BUG,自己死循环了。代码写得野,根本不理会 SIGTERM。因此,K8s 的 Pod 终止流程中还有一个“最多可以容忍的时间”,即 grace period(在 Pod 的 .spec.terminationGracePeriodSeconds 字段中定义),这个值默认是 30 秒,我们在执行 kubectl delete 的时候也可通过 –grace-period 参数显式指定一个优雅退出时间来覆盖 Pod 中的配置。而当 grace period 超出之后,K8s 就只能选择 SIGKILL 强制干掉 Pod 了。很多场景下,除了把 Pod 从 K8s 的 Service 上摘下来以及进程内部的优雅退出之外,我们还必须做一些额外的事情,比如说从 K8s 外部的服务注册中心上反注册。这时就要用到 PreStop Hook 了,K8s 目前提供了 Exec 和 HTTP 两种 PreStop Hook,实际用的时候,需要通过 Pod 的 .spec.containers[].lifecycle.preStop 字段为 Pod 中的每个容器单独配置,比如:spec: contaienrs: - name: my-awesome-container lifecycle: preStop: exec: command: ["/bin/sh","-c","/pre-stop.sh"]/pre-stop.sh 脚本里就可以写我们自己的清理逻辑。最后我们串起来再整个表述一下 Pod 退出的流程(官方文档里更严谨哦):用户删除 Pod。2.1. Pod 进入 Terminating 状态。2.2. 与此同时,K8s 会将 Pod 从对应的 service 上摘除。2.3. 与此同时,针对有 PreStop Hook 的容器,kubelet 会调用每个容器的 PreStop Hook,假如 PreStop Hook 的运行时间超出了 grace period,kubelet 会发送 SIGTERM 并再等 2 秒。2.4. 与此同时,针对没有 PreStop Hook 的容器,kubelet 发送 SIGTERM。grace period 超出之后,kubelet 发送 SIGKILL 干掉尚未退出的容器。这个过程很不错,但它存在一个问题就是我们无法预测 Pod 会在多久之内完成优雅退出,也无法优雅地应对“优雅退出”失败的情况。而在我们的产品 TiDB Operator 中,这就是一个无法接受的事情。有状态分布式应用的挑战为什么说无法接受这个流程呢?其实这个流程对无状态应用来说通常是 OK 的,但下面这个场景就稍微复杂一点:TiDB 中有一个核心的分布式 KV 存储层 TiKV。TiKV 内部基于 Multi-Raft 做一致性存储,这个架构比较复杂,这里我们可以简化描述为一主多从的架构,Leader 写入,Follower 同步。而我们的场景是要对 TiKV 做计划性的运维操作,比如滚动升级,迁移节点。在这个场景下,尽管系统可以接受小于半数的节点宕机,但对于预期性的停机,我们要尽量做到优雅停止。这是因为数据库场景本身就是非常严苛的,基本上都处于整个架构的核心部分,因此我们要把抖动做到越小越好。要做到这点,就得做不少清理工作,比如说我们要在停机前将当前节点上的 Leader 全部迁移到其它节点上。得益于系统的良好设计,大多数时候这类操作都很快,然而分布式系统中异常是家常便饭,优雅退出耗时过长甚至失败的场景是我们必须要考虑的。假如类似的事情发生了,为了业务稳定和数据安全,我们就不能强制关闭 Pod,而应该停止操作过程,通知工程师介入。 这时,上面所说的 Pod 退出流程就不再适用了。小心翼翼:手动控制所有流程这个问题其实 K8s 本身没有开箱即用的解决方案,于是我们在自己的 Controller 中(TiDB 对象本身就是一个 CRD)与非常细致地控制了各种操作场景下的服务启停逻辑。抛开细节不谈,最后的大致逻辑是在每次停服务前,由 Controller 通知集群进行节点下线前的各种迁移操作,操作完成后,才真正下线节点,并进行下一个节点的操作。而假如集群无法正常完成迁移等操作或耗时过久,我们也能“守住底线”,不会强行把节点干掉,这就保证了诸如滚动升级,节点迁移之类操作的安全性。但这种办法存在一个问题就是实现起来比较复杂,我们需要自己实现一个控制器,在其中实现细粒度的控制逻辑并且在 Controller 的控制循环中不断去检查能否安全停止 Pod。另辟蹊径:解耦 Pod 删除的控制流复杂的逻辑总是没有简单的逻辑好维护,同时写 CRD 和 Controller 的开发量也不小,能不能有一种更简洁,更通用的逻辑,能实现“保证优雅关闭(否则不关闭)”的需求呢?有,办法就是 ValidatingAdmissionWebhook。这里先介绍一点点背景知识,Kubernetes 的 apiserver 一开始就有 AdmissionController 的设计,这个设计和各类 Web 框架中的 Filter 或 Middleware 很像,就是一个插件化的责任链,责任链中的每个插件针对 apiserver 收到的请求做一些操作或校验。举两个插件的例子:DefaultStorageClass,为没有声明 storageClass 的 PVC 自动设置 storageClass。ResourceQuota,校验 Pod 的资源使用是否超出了对应 Namespace 的 Quota。虽然说这是插件化的,但在 1.7 之前,所有的 plugin 都需要写到 apiserver 的代码中一起编译,很不灵活。而在 1.7 中 K8s 就引入了 Dynamic Admission Control 机制,允许用户向 apiserver 注册 webhook,而 apiserver 则通过 webhook 调用外部 server 来实现 filter 逻辑。1.9 中,这个特性进一步做了优化,把 webhook 分成了两类: MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook,顾名思义,前者就是操作 api 对象的,比如上文例子中的 DefaultStroageClass,而后者是校验 api 对象的,比如 ResourceQuota。拆分之后,apiserver 就能保证在校验(Validating)之前先做完所有的修改(Mutating),下面这个示意图非常清晰:而我们的办法就是,利用 ValidatingAdmissionWebhook,在重要的 Pod 收到删除请求时,先在 webhook server 上请求集群进行下线前的清理和准备工作,并直接返回拒绝。这时候重点来了,Control Loop 为了达到目标状态(比如说升级到新版本),会不断地进行 reconcile,尝试删除 Pod,而我们的 webhook 则会不断拒绝,除非集群已经完成了所有的清理和准备工作。下面是这个流程的分步描述:用户更新资源对象。controller-manager watch 到对象变更。controller-manager 开始同步对象状态,尝试删除第一个 Pod。apiserver 调用外部 webhook。webhook server 请求集群做 tikv-1 节点下线前的准备工作(这个请求是幂等的),并查询准备工作是否完成,假如准备完成,允许删除,假如没有完成,则拒绝,整个流程会因为 controller manager 的控制循环回到第 2 步。好像一下子所有东西都清晰了,这个 webhook 的逻辑很清晰,就是要保证所有相关的 Pod 删除操作都要先完成优雅退出前的准备,完全不用关心外部的控制循环是怎么跑的,也因此它非常容易编写和测试,非常优雅地满足了我们“保证优雅关闭(否则不关闭)”的需求,目前我们正在考虑用这种方式替换线上的旧方案。后记其实 Dynamic Admission Control 的应用很广,比如 Istio 就是用 MutatingAdmissionWebhook 来实现 envoy 容器的注入的。从上面的例子中我们也可以看到它的扩展能力很强,而且常常能站在一个正交的视角上,非常干净地解决问题,与其它逻辑做到很好的解耦。当然了,Kubernetes 中还有 非常多的扩展点,从 kubectl 到 apiserver,scheduler,kubelet(device plugin,flexvolume),自定义 Controller 再到集群层面的网络(CNI),存储(CSI)可以说是处处可以做事情。以前做一些常规的微服务部署对这些并不熟悉也没用过,而现在面对 TiDB 这样复杂的分布式系统,尤其在 Kubernetes 对有状态应用和本地存储的支持还不够好的情况下,得在每一个扩展点上去悉心考量,做起来非常有意思,因此后续可能还有一些 TiDB Operator 中思考过的解决方案分享。 ...

April 2, 2019 · 2 min · jiezi

基于OVN的Kubernetes网络架构解析

【编者的话】Kubernetes经过了几年的发展,存在着很多的网络方案。然而网络虚拟化在Kubernetes出现前就一直在发展,其中基于OpenVswitch的方案在OpenStack中已经有了很成熟的方案。其中OVN作为OVS的控制器提供了构建分布式虚拟网络的完整控制平面,并已经成为了最新的OpenStack网络标准。我们将OVN的网络架构和Kubernetes的容器平台进行结合,将业界成熟的网络架构引入Kubernetes大幅增强现有容器网络的能力。Kubernetes网络的局限性Kubernetes提出了很多网络概念,很多开源项目都有自己的实现。然而由于各个网络功能都是在不同的项目中实现,功能和性能也各有千秋,缺乏统一的解决方案,在使用过程中经常会陷入到底该用哪个的抉择中。同时CNI、DNS、Service的实现又在不同的项目,一旦网络出现问题,排查也会在多个组件间游走,是一个十分痛苦的过程。尽管Kubernetes提出了很多网络的概念,但是在真实应用中很多人会有这样的感觉:网络这块还是很薄弱,很多功能缺乏,方案也不够灵活。尤其是和搞传统基础设施网络的人沟通会发现,在他们眼里,Kubernetes的网络还很初级。我们熟悉的Kubernetes网络是CNI、Service、DNS、Ingress、Network Policy这样的模式。而做IaaS的视角完全不同,他们每次提起是VPC、Subnet、VNIC、 Floating IP,在此之上有DHCP,路由控制,安全组,QoS,负载均衡,域名解析这样的基础网络功能。从IaaS的视角来看,Kubernetes的网络功能确实比较单薄。经常碰到来自传统网络部门的挑战,诸如子网划分VLAN隔离,集群内外网络打通,容器NAT设置,带宽动态调节等等。现有的开源网络方案很难完美支持,最简单的一个例子,比如提及容器的固定IP功能通常就要上升到意识形态斗争的层面去讨论。这本质上还是Kubernetes的网络功能不足,模型也不够灵活导致的。从更高层面来说,Kubernetes中抽象类一层网络虚拟化的内容,然而网络虚拟化或者SDN并不是Kubernetes带来的新东西,相关技术已经发展很久。尤其是在IaaS领域里已经有着比较成熟且完善的一整套网络方案。传统网络部门的人都会问,为什么不用OVS来做网络方案,很多需求用只要容器网络接入OVS网络,剩下事情网络部门自己就知道怎么去做了,都不用我们实现太多额外的功能。也有很多人向我们推荐了OVN,用这个能很方便地实现这些功能。也正由此我们开始去关注OVS/OVN这种之前主要应用于OpenStack生态系统的网络工具。下面我就来介绍一下OVS和OVN。OVS和OVN网络方案的能力网络的概念比较晦涩一些,但是好在大家都对Docker和Kubernetes比较熟悉,可以做个类比。如果说Docker是对单机计算资源的虚拟化,那么OVS就是对单机网络进行虚拟化的一个工具。它最基本的功能是实现了虚拟交换机,可以把虚拟网卡和虚拟交换机的端口连接,这样一个交换机下的多个网卡网络就打通了,类似Linux Bridge的功能。在此之上,OVS很重要的一点就是支持OpenFlow,这是一种可编程的流量控制语言,可以方便我们以编程的方式对流量进行控制,例如转发,拒绝,更改包信息,NAT,QoS 等等。此外OVS还支持多中网络流量监控的协议,方便我们可视化监控并跟踪整个虚拟网络的流量情况。但是,OVS只是一个单机软件,它并没有集群的信息,自己无法了解整个集群的虚拟网络状况,也就无法只通过自己来构建集群规模的虚拟网络。这就好比是单机的Docker,而OVN就相当于是OVS的Kubernetes,它提供了一个集中式的OVS控制器。这样可以从集群角度对整个网络设施进行编排。同时OVN也是新版OpenStack中Neutron的后端实现,基本可以认为未来的OpenStack网络都是通过OVN来进行控制的。01.jpeg上图是一个OVN的架构,从下往上看:ovs-vswitchd和ovsdb-server可以理解为单机的Docker负责单机虚拟网络的真实操作。ovn-controller类似于kubelet,负责和中心控制节点通信获取整个集群的网络信息,并更新本机的流量规则。Southbound DB类似于etcd(不太准确),存储集群视角下的逻辑规则。Northbound DB类似apiserver,提供了一组高层次的网络抽象,这样在真正创建网络资源时无需关心负责的逻辑规则,只需要通过Northoboud DB的接口创建对应实体即可。CMS可以理解为OpenStacke或者Kubernetes这样的云平台,而 CMS Plugin是云平台和OVN对接的部分。下面我们具体介绍一下OVN提供的网络抽象,这样大家就会有比较清晰的认知了。Logical_Switch最基础的分布式虚拟交换机,这样可以将多台机器上的容器组织在一个二层网络下,看上去就好像所有容器接在一台交换机上。之后可以在上面增加诸如ACL、LB、QoS、DNS、VLAN等等二层功能。Logical_Router虚拟路由器,提供了交换机之间的路由,虚拟网络和外部网络连接,之后可以在路由器层面增加DHCP、NAT、Gateway等路由相关的功能。Loadbalancer,L2和L3的Loadbalancer,可以类比公有云上的内部LB和外部LB的功能。ACL基于L2到L4的所有控制信息进行管控的一组DSL,可以十分灵活,例如:outport == “port1” && ip4 && tcp && tcp.src >= 10000 && tcp.dst <= 1000。QoS,可以基于和ACL同样的DSL进行带宽的控制。NAT,同时提供DNAT和SNAT的控制方便内外网络通信。DNS,内置的分布式DNS,可以在本机直接返回内部DNS的请求。Gateway控制内部和外部之间的集中式通信。了解了这些,大家应该就能发现,Kubernetes目前的网络从功能层面其实只是OVN支持的一个子集,基本上所有Kubernetes的网络需求都能在OVN中找到映射关系,我们简单来看下他们之间的映射。OVN和Kubernetes的结合Switch/Router -> Kubernetes基本的东西向互通容器网络。这块OVN的能力其实是大大超出,毕竟OVN的这套模型是针对多租户进行设计的,而Kubernetes现在只需要一个简单的二层网络。Loadbalancer → ClusterIP以及Loadbalancer类型的Service,可以取代kube-proxy的功能,OVN本身也可以实现云上ELB的功能。ACL -> Networkpolicy本质上更灵活因为可以从L2控制到L4并且DSL也支持更多的语法规则。DNS -> 可以取代Kube-DNS/CoreDNS,同时由于OVN实现的是分布式DNS,整体的健壮性会比现在的Kubernetes方案要好。可以看到Kubernetes的CNI、kube-proxy、Kube-DNS、NetworkPolicy、Service等等概念OVN都有对应的方案,而且在功能或者稳定性上还有增强。更不要说还有QoS、NAT、Gateway等等现在Kubernetes中没有的概念。可以看到如果能把IaaS领域的网络能力往Kubernetes平移,我们还有很多的提升空间。Kubernetes网络未来增强的方向最后来说说我认为的未来Kubernetes网络可能的增强方向。Kubernetes网络功能和IaaS网络功能打平现在的Kubernetes网络模型很类似之前公有云上的经典网络,所有用户大二层打通,通过安全策略控制访问。我们现在也都知道公有云多租户不能这么做VPC肯定是标配。因此未来Kubernetes网络可能也会向着多租户方向前进,在VPC的基础上有更多的路由控制、NAT控制、带宽控制、浮动IP等等现在IaaS上很常见的功能。性能现有的开源方案其实主要还是依赖原有的Linux网络栈,没有针对性的优化。理论上容器的密度比传统虚拟化高,网络压力会更大。OVS现在有DPDK等Kernel bypass的DataPath,绕过Linux内核栈来实现低延迟和大吞吐网络。未来随着容器的密度越来越大,我认为会出现这种针对容器架构专门优化的网络方案,而不是依旧依赖Linux网络栈。监控和问题排查现有的网络问题排查十分困难,如果所有的数据平面都由一个项目完成,比如OVN,那么学习成本和排障都会容易一些。此外OVS社区已经有了很多成熟的监控,追踪,排障方案,随着容器的使用场景变多,我认为外围的工具也需要能够很好的支撑这种模式的网络运维问题。Q&AQ:OVS方案与基于三层交换机方案对比,各有什么优缺点?A:OVS最大的优点在于可编程,灵活性比较好。虚拟网络不用手动插网线,而且有OpenFlow加持,可以实现一些普通交换机无法实现的流量控制。物理交换机的主要有点就是性能好,而且比较稳定,不容易出问题。Q:OVN不支持ECMP,貌似现在还是active-standby机制,你们怎么解决Gateway瓶颈问题?A:有几种方式:1. Gateway用DPDK这样的高速DataPath;2. 多Gateway,用策略路不同的IP段走不同Gateway,可以分担流量;3. 不使用OVN概念的Gateway,自己做一些手脚从每台宿主机直接出去,也是分担流量降低单点的风险。Q:OVN-Kubernetes好像只支持每个部署节点一个虚拟网络网段。如何避免IP池浪费和不均衡?A:这个其实是这个项目实现的网络模型的一个局限性。在我们的实现里是以namespace为粒度划分子网,可以对每个namespace进行控制,情况会好很多。Q:OVN如果有不同的Chassis,但是相同IP就会造成网络异常(比如物理机,VM装上OVN,注册到远端后,被重建,后面又注册到远端,但是Chassis已经改变),会导致大量节点Geneve网络异常。你们怎么解决这个问题?A:暂时没碰到这个问题,但是我们在实现的一个原则就是尽可能保证所有的操作都是幂等的。向这种可能需要在重连前做一个检查,判断是否有过期的数据需要清理,再连接,或者复用旧的连接信息去连接。Q:如何debug OVN逻辑拓扑是否配置有问题?A:目前debug确实很多情况只能靠眼看,也可以使用ovn-trace这个工具可以打印数据包在逻辑流里的链路来排查。Q:OVS跟Calico等有啥区别?A:Calico主要依赖Linux的路由功能做网络打通,OVS是在软件交换机层面实现网络打通,并提供了更丰富的网络功能。Q:OVS的封包支持有STT和Geneve,你们选用哪种,为什么?A:其实还支持VXLAN,我们选的Geneve。原因比较简单,Geneve是第一个OVN支持的封包协议,而且看了一些评测,据说在搞内核开启UDP Checksum的情况下性能会比VXLAN要好一些。Q:OVS如何实现固定容器IP?A:这个其实OVS有对应的设置可以给每个端口设定IP和MACE,这样网卡启动时配置相同的信息就可以了,难点其实是如何控制OVN来分配 IP,感觉这个话题可以再开一场分享来讨论了。Q:可以简单介绍下你们准备开源的网络功能吗?A:每个namespace和一个logical_switch绑定,支持子网分配,支持固定 IP,支持 QoS,支持NetworkPolicy,内置的LB,内置的DNS,大致就是把OVN的概念映射到Kubernetes。Q:想了解一下,如果采用OVN,是不是意味着使用OpenStack平台和Kubernetes网络可以直接互通?完成业务在虚拟机和Pod之间的全新负载方式?A:是这样的,如果涉及的合理可以做到容器和VM使用同一个底层网络基础设施,VM和容器之间可以IP直达,所有的ACL、LB都是打通的。Q:直接把OpenShift OVS抽出来做Kubernetes的网络插件和灵雀云做的这个区别在哪?A:功能上有很多是相同的,因为底层都是OVS。如果关注Roadmap会发现OpenShift之后也会采用OVS的模式。从架构的角度来看,现在openshift-multitenant的实现很类似Neutron之前那一套,各种Agent,之后会统一到OVN。另一方面OpenShift的网络插件绑定的太死了,所以我们决定还是自己抽出来,顺便能实现我们的一些特殊功能,比如固定IP,子网共享,以及一些网关控制层面的功能。Q:请问Geneve和VXLAN的区别有哪些?A:Geneve可以理解为下一代VXLAN,VXLAN相对VLAN来说头部更长可以支持更多的VLAN,但是由于是固定长度的封装头,不能任意加控制信息。Geneve采用变长的封装头,可以加很多自定义的控制信息,方便之后做更复杂的网络管控。Q:Docker CNM也支持固定IP,和你说的固定IP是一回事吗?另外,基于OVS建立的网络是CNI还是CNM的呢?A:基于CNI,因为我们依赖Kubernetes的模型。不过话说回来我很喜欢Docker CNM那套模型,比CNI要实用很多。固定IP其实只是个功能,各种模型下都可以实现,效果就是可以给Pod指定IP启动,Workload下的多个Pod实用的是一组固定的地址。Q:目前你们对企业的解决方案里会默认采用这种网络模式么?A:这个方案是我们这几年需求和碰到坑的一个积累吧,现在还不会直接给企业用,我们还需要一些功能的开发和测试,但是之后Overlay的场景这个肯定是主推了,主要是取代原来的Flannel VXLAN网络。Q:你了解Contiv网络方案吗,和贵公司的实现有哪些区别?A:Contiv是思科做的,也是OVS实现的,不过它的实现比较早,自己手动实现了整个控制平面,可以认为自己写了个跟OVN类似的东西来控制 OVS。不过看它最近已经很少更新了。用OVN能用很少的代码就实现基本相同的功能。Contiv有个比较独特的功能就是支持BGP的网络间通信,这个是OVN暂时不支持的。以上内容根据2019年3月26日晚微信群分享内容整理。分享人刘梦馨,灵雀云高级工程师。2014年加入灵雀云容器团队,长期参与容器调度平台和容器网络架构的产品研发和技术架构演进,参与自研容器网络和容器应用网关。目前主要专注于容器网络功能的拓展和架构优化。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesd,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

April 1, 2019 · 1 min · jiezi

Kubernetes新近kubectl及CNI漏洞修复,Rancher 2.2.1发布

今天,Kubernetes发布了一系列补丁版本,修复新近发现的两个安全漏洞CVE-2019-1002101(kubectl cp命令安全漏洞)和CVE-2019-9946(CNI端口映射插件漏洞)。Rancher也紧急更新,发布一系列新版以支持Kubernetes补丁版本。本文将介绍CVE-2019-1002101和CVE-2019-9946的详情、原理、受影响版本及升级建议,以及Rancher提供给用户的应对之策。CVE-2019-1002101漏洞详情及原理CVE-2019-1002101是kubectl cp命令中存在的安全漏洞,严重等级为【高】,攻击者可以使用kubectl cp命令替换或删除用户工作站上的文件,在用户计算机的任何路径上写入恶意文件。kubectl cp命令允许在容器和用户计算机之间复制文件。为了从容器中复制文件,Kubernetes会在容器内创建一个tar,通过网络复制它,然后kubectl会在用户的机器上解压缩它。而如果容器中的tar二进制文件是恶意的,它可以运行任何代码并输出意外的恶意结果。在用户调用kubectl cp时,攻击者可以使用它将文件写入用户计算机上的任何路径,只有本地用户的系统权限有可能限制这一操作。受影响的版本及升级建议什么版本用户会被此次漏洞影响?试着运行kubectl version—client进行查看,除了1.11.9、1.12.7、1.13.5、1.14.0或更新版本之外,其他均为易受攻击的版本。所有使用易受攻击版本的用户,都被建议升级至Kubernetes今天发布的补丁版本:1.11.9、1.12.7、1.13.5、1.14.0。kubectl的安装和设置方法,可以参照这一链接的说明教程:https://kubernetes.io/docs/ta…CVE-2019-9946漏洞详情及原理CVE-2019-9946是Kubernetes CNI框架中的安全漏洞,0.7.5之前版本的CNI插件端口映射和Kubernetes之间的交互中发现了安全问题,严重等级为【中等】。因为CNI 端口映射插件是嵌入到Kubernetes版本中的,只有升级至新版本的Kubernetes才能解决此问题。在此修复之前,当我们配置HostPorts端口映射方式时CNI插件会在iptables nat链之前插入规则,这将优先于KUBE- SERVICES链。因此,传入流量时,流量会优先经过HostPort的规则,即使之后在链中出现了更适合、更具体的服务定义规则(例如NodePorts),依然会由HostPort 的规则来匹配传入的流量。现在修复之后,将端口映射插件的规则由“最优先”变为“附加”,则可以让流量优先由KUBE-SERVICES规则处理。只有当流量与服务不匹配时,才会考虑使用HostPorts。受影响的版本及升级建议因为这会影响插件界面,因此如果你不完全了解自己的Kubernetes配置,很难确定自己是否会受此漏洞影响。IPVS模式下的kube-proxy配置加上使用HostPort端口映射类型的pod,是肯定会被这一漏洞影响的。但同样需要注意的是,其他网络配置方式也有可能使用了CNI 的portmap端口映射插件。运行kubectl version –short | grep Server,如果它显示你使用的不是1.11.9、1.12.7、1.13.5和1.14.0或更新的版本,且如果你的Kubernetes与使用了端口映射插件的CNI配置配对,那么你极有可能会受这一漏洞影响。但无需特别担心的是,只需按照管理工具或供应商的说明,升级到最新补丁版本的Kubernetes(1.11.9、1.12.7、1.13.5和1.14.0)即可。Rancher已发布最新版本应对此次漏洞此次也一如既往,在Kubernetes自身爆出漏洞之后,Rancher Labs团队都第一时间响应,保障使用Rancher平台管理Kubernetes集群的用户的安全。如果你是使用Rancher平台管理Kubernetes集群,不用担心,Rancher已于今日发布了最新版本,支持包含漏洞修复的Kubernetes版本(1.11.9、1.12.7和1.13.5),保障所有Rancher用户的Kubernetes集群不受此次漏洞困扰。若您使用的版本可能受此次两个漏洞影响,可以升级至今天发布的以下三个最新Rancher版本:Rancher 2.2.1Rancher 2.1.8Rancher 2.0.13对于Rancher 1.6.x的用户,我们已在Rancher v1.6.26的Catalog(应用程序目录)中添加了对Kubernetes v1.11.9和v1.12.7的支持。您可以升级至Rancher v1.6.26,新版本将在下一次目录自动刷新时可用。为用户的Docker & K8S之旅护航Rancher Kubernetes平台拥有着超过一亿次下载量,我们深知安全问题对于用户而言的重要性,更遑论那些通过Rancher平台在生产环境中运行Docker及Kubernetes的数千万用户。2018年年底Kubernetes被爆出的首个严重安全漏洞CVE-2018-1002105,就是由Rancher Labs联合创始人及首席架构师Darren Shepherd发现的。2019年1月Kubernetes被爆出仪表盘和外部IP代理安全漏洞CVE-2018-18264时,Rancher Labs也是第一时间向用户响应,确保所有Rancher 2.x和1.6.x的用户都完全不被漏洞影响。2019年2月爆出的严重的runc容器逃逸漏洞CVE-2019-5736,影响到大多数Docker与Kubernetes用户,Rancher Kubernetes管理平台和RancherOS操作系统均在不到一天时间内紧急更新,是业界第一个紧急发布新版本支持Docker补丁版本的平台,还帮忙将修复程序反向移植到所有版本的Docker并提供给用户,且提供了连Docker官方都不支持的针对Linux 3.x内核的修复方案。负责、可靠、快速响应、以用户为中心,是Rancher始终不变的初心;在每一次业界出现问题时,严谨踏实为用户提供相应的应对之策,也是Rancher一如既往的行事之道。未来,Rancher也将一如既往支持与守护在用户的Kubernetes之路左右,确保所有企业用户都能安全、稳妥、无虞地继续前进。

April 1, 2019 · 1 min · jiezi

K8S 生态周报| 2019.03.25~2019.03.31

「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」。Kubernetes 1.14 正式发布1.14 的主要更新:对 Windows Node 和 container 的支持达到生产级别,支持 Windows Server 2019;本地持久化数据卷正式可用,这可以方便使用本地 SSD 之类的存储,但注意这个特性容错性较差;Pod 优先级和抢占机制正式可用,(建议慎重使用);Pod Ready++ (Pod Readiness Gates) 达到稳定,可以更好的判断 Pod 及其需要的资源是否均已就绪;当然还有很多的改进和很多被废弃的功能特性等,建议阅读 ReleaseNote。Minikube 1.0.0 正式发布Minikube 是一个用于本地搭建 Kubernetes 环境的工具,使用方法可参考 使用 Minikube 搭建本地 Kubernetes 环境。1.0.0 的主要更新:默认 Kubernetes 版本更新至 1.14.0;新增 –image-repository 参数,方便国内用户使用镜像解决网络问题;其他特性请阅读 ReleaseNoterunc 1.0-rc7 发布注意,低版本内核(尤其是 3.x)的系统,请不要升级至此版本这个版本主要为解决之前的漏洞及修正一些规范等,版本说明请参考 runc 1.0-rc7 发布之际。其他特性请阅读 ReleaseNoteBrigade 1.0 正式发布Brigade 是一个使用 JavaScript 来为 Kubernetes 构建 pipeline 的工具,现在是 CNCF 的 sandbox 项目。详细内容请阅读 ReleaseNoteKind 0.2.1 发布Kind 是 Kubernetes In Docker 的缩写,是一款便于在本地和 CI 环境中进行 Kubernetes 环境搭建的工具,具体用法请参考 使用 Kind 搭建你的本地 Kubernetes 集群0.2.1 是 kind 的首个 patch 版本,主要为了修复一个偶发的 panic , 建议尽快升级。可以通过下面二维码订阅我的文章公众号【MoeLove】 ...

April 1, 2019 · 1 min · jiezi

runc 1.0-rc7 发布之际

在 18 年 11 月底时,我写了一篇文章 《runc 1.0-rc6 发布之际》 。如果你还不了解 runc 是什么,以及如何使用它,请参考我那篇文章。本文中,不再对其概念和用法等进行说明。在 runc 1.0-rc6 发布之时,给版本的别名为 “For Real This Time”,当时我们原定计划是发布 1.0 的,但是作为基础依赖软件,我们认为当时的版本还有几个问题:不够规范;发布周期不明确;为了给相关的 runtime 足够的时间进行修正/升级,以及规范版本生命周期等,最终决定了发布 runc 1.0-rc6。为何有 runc 1.0-rc7 存在前面已经基本介绍了相关背景,并且也基本明确了 rc6 就是在 1.0 正式发布之前的最后一个版本,那 rc7 为什么会出现呢?CVE-2019-5736我们首先要介绍今年 runc 的一个提权漏洞 CVE-2019-5736 。2019 年 2 月 11 日在 oss-security 邮件组正式批露该漏洞,攻击者可以利用恶意容器覆盖主机上的 runc 文件,从而达到攻击的目的;(具体的攻击方式此处略过),注意不要轻易使用来源不可信的镜像创建容器便可有效避免被攻击的可能。简单补充下可能被攻击的方式:运行恶意的 Docker 镜像在主机上执行 docker exec 进入容器内关于容器安全或者容器的运行机制,其实涉及的点很多,我在去年的一次线上分享 《基于 GitLab 的 CI 实践》 有提到过 Linux Security Modules(LSM)等相关的内容,对容器安全感兴趣的朋友可以对 LSM 多了解下。不过本文主要看的是 runc 如何修复该漏洞的,以及后续产生的影响。修复方式// 对 memfd_create 系统调用做了个封装 省略部分代码#if !defined(SYS_memfd_create) && defined(__NR_memfd_create)# define SYS_memfd_create __NR_memfd_create#endif#ifdef SYS_memfd_create# define HAVE_MEMFD_CREATE# ifndef MFD_CLOEXEC# define MFD_CLOEXEC 0x0001U# define MFD_ALLOW_SEALING 0x0002U# endifint memfd_create(const char *name, unsigned int flags){ return syscall(SYS_memfd_create, name, flags);}// 一个简单的只读缓存区static char *read_file(char *path, size_t *length){ int fd; char buf[4096], *copy = NULL; if (!length) return NULL; fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return NULL; *length = 0; for (;;) { int n; n = read(fd, buf, sizeof(buf)); if (n < 0) goto error; if (!n) break; copy = must_realloc(copy, (*length + n) * sizeof(*copy)); memcpy(copy + *length, buf, n); *length += n; } close(fd); return copy;error: close(fd); free(copy); return NULL;}// 将复制后的 fd 重赋值/执行static int clone_binary(void){ int binfd, memfd; ssize_t sent = 0;#ifdef HAVE_MEMFD_CREATE memfd = memfd_create(RUNC_MEMFD_COMMENT, MFD_CLOEXEC | MFD_ALLOW_SEALING);#else memfd = open("/tmp", O_TMPFILE | O_EXCL | O_RDWR | O_CLOEXEC, 0711);#endif if (memfd < 0) return -ENOTRECOVERABLE; binfd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC); if (binfd < 0) goto error; sent = sendfile(memfd, binfd, NULL, RUNC_SENDFILE_MAX); close(binfd); if (sent < 0) goto error;#ifdef HAVE_MEMFD_CREATE int err = fcntl(memfd, F_ADD_SEALS, RUNC_MEMFD_SEALS); if (err < 0) goto error;#else int newfd; char *fdpath = NULL; if (asprintf(&fdpath, “/proc/self/fd/%d”, memfd) < 0) goto error; newfd = open(fdpath, O_RDONLY | O_CLOEXEC); free(fdpath); if (newfd < 0) goto error; close(memfd); memfd = newfd;#endif return memfd;error: close(memfd); return -EIO;}int ensure_cloned_binary(void){ int execfd; char **argv = NULL, **envp = NULL; int cloned = is_self_cloned(); if (cloned > 0 || cloned == -ENOTRECOVERABLE) return cloned; if (fetchve(&argv, &envp) < 0) return -EINVAL; execfd = clone_binary(); if (execfd < 0) return -EIO; fexecve(execfd, argv, envp); return -ENOEXEC;}省略掉了部分代码,完整代码可直接参考 runc 代码仓库 。整个的修复逻辑我在上面的代码中加了备注,总结来讲其实就是:创建了一个只存在于内存中的 memfd ;将原本的 runc 拷贝至这个 memfd ;在进入 namespace 前,通过这个 memfd 重新执行 runc ; (这是为了确保之后即使被攻击/替换也操作的还是内存中的这个只读的 runc)经过以上的操作,就基本修复了 CVE-2019-5736 。影响内核相关在上面讲完修复方式后,我们来看下会产生哪些影响。涉及到了系统调用 memfd_create(2) 和 fcntl(2)增加了系统调用,那自然就要看内核是否支持了。实际上,这些函数是在 2015 年 2 月(距这次修复整整 4 年,也挺有趣)被加入到 Linux 3.17 内核中的。换句话说就是 凡是在此内核版本之前的系统,均无法正常使用该功能,对我们的影响就是,如果你在此版本内核之前的机器上使用了包含上述修复代码的 runc 或构建在其之上的 containerd、 Docker 等都无法正常工作 。 以 Docker 举例:安装 docker-ce-18.09.2 或 docker-ce-18.06.3 可避免受 CVE-2019-5736 影响,但如果内核版本较低,在运行容器时可能会有如下情况出现: (不同版本/内核可能出现其他情况)[tao@moelove ~]# docker run –rm my-registry/os/debian echo Hello docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting containerprocess caused “process_linux.go:293: copying bootstrap data to pipe caused "write init-p: broken pipe"”: unknown.解决办法升级内核;这是最直接的办法,而且使用一个新版本的内核也能省去很多不必要的麻烦:)rancher 提供了一个 runc-cve 的 patch,可兼容部分 3.x 内核的系统(我没有测试过)如果你不升级 runc/containerd/Docker 等版本的话,那建议你 1. 将 runc 可执行程序放到只读文件系统上,可避免被覆盖;2. 启动容器时,启用 SELinux; 3. 在容器内使用低权限用户或者采用映射的方式,但保证用户对主机上的 runc 程序无写权限。注意: memfd_create 等相关系统调用,也被加入到了 Debian 3.16 和 Ubuntu 14.04 updates 中,当然也被反向移植到了 CentOS 7.3 内核 3.10.0-514 版本之后。 (Red Hat 给 CentOS 7.x 的 3.10 内核上反向移植了很多特性)内存相关从上面的说明中,也很容易可以看到, 内存的使用上会有所增加,不过之后已做了修复。这里不再进行展开。其他偶尔可能触发一些内核 bug 之类的(总之建议升级 :)等待 rc8 发布上面已经介绍了 1.0-rc7 出现的主要原因 CVE-2019-5736;当然这个版本中也有一些新特性和一些 bugfix 不过不是本文的主要内容,不再赘述。值得一提的是这次的版本命名:runc 1.0-rc7 – “The Eleventh Hour” 后面这个别名其实来自于一部英剧,感兴趣也可以去看看。至于下个版本是不是会是 1.0 正式版呢?目前来看应该不是,有极大可能会发布 runc 1.0-rc8 做一些 bugfix,让我们拭目以待。可以通过下面二维码订阅我的文章公众号【MoeLove】 ...

March 31, 2019 · 3 min · jiezi

使用 Kind 搭建你的本地 Kubernetes 集群

Kind 是我很喜欢也一直在参与的项目,我计划将 Kind 相关的文章写成一个系列。(flag++) 这是第一篇。Kind 介绍Kind 是 Kubernetes In Docker 的缩写,顾名思义是使用 Docker 容器作为 Node 并将 Kubernetes 部署至其中的一个工具。官方文档中也把 Kind 作为一种本地集群搭建的工具进行推荐。安装二进制安装Kind 使用 Golang 进行开发,在仓库的 Release 页面,已经上传了构建好的二进制,支持多种操作系统,可直接按需下载进行使用。e.g.# 下载最新的 0.2.0 版本wget -O /usr/local/bin/kind https://github.com/kubernetes-sigs/kind/releases/download/0.2.0/kind-linux-amd64 && chmod +x /usr/local/bin/kind通过源码安装如果你本地已经配置好了 Golang 的开发环境,那你可以直接通过源码进行安装。e.g.go get -u sigs.k8s.io/kind运行完上述命令后,会将 kind 的可执行文件放到 $(go env GOPATH)/bin 文件夹内,你可能需要将此目录加入到 $PATH 中。或者也可以先 clone 源代码再通过 go build 进行构建。依赖Kind 的主要功能目前需要有 Docker 环境的支持,可参考 Docker 官方文档进行安装。如果需要操作集群,则需要安装 kubectl 命令行。安装方法可参考官方文档搭建单节点集群以下的演示均使用最新的代码(即通过源码安装)。基础用法搭建单节点集群是 Kind 最基础的功能。e.g.master $ kind create cluster –name moeloveCreating cluster “moelove” … ✓ Ensuring node image (kindest/node:v1.13.4) ???? ✓ Preparing nodes ???? ✓ Creating kubeadm config ???? ✓ Starting control-plane ????️Cluster creation complete. You can now use the cluster with:export KUBECONFIG="$(kind get kubeconfig-path –name=“moelove”)“kubectl cluster-info以上命令中, –name 是可选参数,如不指定,默认创建出来的集群名字为 kind。我们根据命令执行完的输出进行操作:master $ export KUBECONFIG="$(kind get kubeconfig-path –name=“moelove”)“master $ kubectl cluster-infoKubernetes master is running at https://localhost:34458KubeDNS is running at https://localhost:34458/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyTo further debug and diagnose cluster problems, use ‘kubectl cluster-info dump’.master $ kubectl get nodesNAME STATUS ROLES AGE VERSIONmoelove-control-plane Ready master 2m v1.13.4以上命令中,kind get kubeconfig-path –name=“moelove” 会返回该指定集群配置文件所在的路径。可以看到单节点的 Kubernetes 已经搭建成功。注意默认情况下,Kind 会先下载 kindest/node:v1.13.4 镜像,该镜像目前托管于 Docker Hub 上,下载时间取决于网络状况。Kind 实际使用 kubeadm 进行集群的创建,对 kubeadm 有所了解的人都知道它默认使用的镜像在国内下载不到,所以需要自己解决网络问题。或者参考下面的方式:Kind 在创建集群的时候,支持通过 –config 的参数传递配置文件给 Kind,在国内,我们可以通过使用国内镜像源的方式来加速集群的创建。(这个方法也适用于直接通过 kubeadm 搭建 Kubernetes 集群)我们先通过以下命令删除刚才搭建的集群:master $ kind delete cluster –name moeloveDeleting cluster “moelove” …$KUBECONFIG is still set to use /root/.kube/kind-config-moelove even though that file has been deleted, remember to unset it接下来,将下面的配置内容保存至一个 YAML 文件中,比如名为 kind-config.yamlkind: ClusterapiVersion: kind.sigs.k8s.io/v1alpha3kubeadmConfigPatches:- | apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration metadata: name: config networking: serviceSubnet: 10.0.0.0/16 imageRepository: registry.aliyuncs.com/google_containers nodeRegistration: kubeletExtraArgs: pod-infra-container-image: registry.aliyuncs.com/google_containers/pause:3.1- | apiVersion: kubeadm.k8s.io/v1beta1 kind: InitConfiguration metadata: name: config networking: serviceSubnet: 10.0.0.0/16 imageRepository: registry.aliyuncs.com/google_containersnodes:- role: control-plane我们使用该配置文件搭建集群。master $ kind create cluster –name moelove –config kind.yamlCreating cluster “moelove” … ✓ Ensuring node image (kindest/node:v1.13.4) ???? ✓ Preparing nodes ???? ✓ Creating kubeadm config ???? ✓ Starting control-plane ????️Cluster creation complete. You can now use the cluster with:export KUBECONFIG="$(kind get kubeconfig-path –name=“moelove”)“kubectl cluster-info上面通过 –config 将我们的配置文件传递给 Kind 用于搭建集群,推荐国内用户使用这种方式。搭建高可用集群Kind 也支持搭建高可用的 K8S 集群,不过只能通过配置文件来实现。可以直接将下面的内容保存至文件中,再将配置文件传递给 Kind 即可。e.g.kind: ClusterapiVersion: kind.sigs.k8s.io/v1alpha3kubeadmConfigPatches:- | apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration metadata: name: config networking: serviceSubnet: 10.0.0.0/16 imageRepository: registry.aliyuncs.com/google_containers nodeRegistration: kubeletExtraArgs: pod-infra-container-image: registry.aliyuncs.com/google_containers/pause:3.1- | apiVersion: kubeadm.k8s.io/v1beta1 kind: InitConfiguration metadata: name: config networking: serviceSubnet: 10.0.0.0/16 imageRepository: registry.aliyuncs.com/google_containersnodes:- role: control-plane- role: control-plane- role: control-plane- role: worker- role: worker- role: worker我们使用以下的命令来搭建高可用的 Kubernetes 集群:master $ kind create cluster –name moelove-ha –config kind-ha-config.yamlCreating cluster “moelove-ha” … ✓ Ensuring node image (kindest/node:v1.13.4) ???? ✓ Preparing nodes ???????????????????????????? ✓ Starting the external load balancer ⚖️ ✓ Creating kubeadm config ???? ✓ Starting control-plane ????️ ✓ Joining more control-plane nodes ???? ✓ Joining worker nodes ????Cluster creation complete. You can now use the cluster with:export KUBECONFIG="$(kind get kubeconfig-path –name=“moelove-ha”)“kubectl cluster-infomaster $ export KUBECONFIG="$(kind get kubeconfig-path –name=“moelove-ha”)“master $ kubectl cluster-infoKubernetes master is running at https://localhost:44019KubeDNS is running at https://localhost:44019/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyTo further debug and diagnose cluster problems, use ‘kubectl cluster-info dump’.可以做下简单的验证:master $ kubectl get nodesNAME STATUS ROLES AGE VERSIONmoelove-ha-control-plane Ready master 3m42s v1.13.4moelove-ha-control-plane2 Ready master 3m24s v1.13.4moelove-ha-control-plane3 Ready master 2m13s v1.13.4moelove-ha-worker Ready <none> 96s v1.13.4moelove-ha-worker2 Ready <none> 98s v1.13.4moelove-ha-worker3 Ready <none> 95s v1.13.4可以看到已经成功创建了多 master 的 Kubernetes 集群。总结这是使用 Kind 搭建本地 Kubernetes 集群的第一篇,同时本篇的内容也是《Kubernetes 从上手到实践》第 4 节内容的补充,搭配食用效果更佳 :)可以通过下面二维码订阅我的文章公众号【MoeLove】 ...

March 31, 2019 · 3 min · jiezi

Kubernetes CNI网络最强对比:Flannel、Calico、Canal和Weave

本文将在介绍技术原理和相应术语的基础上,再集中探索与详细对比目前最流行的CNI插件:Flannel、Calico、Weave和Canal,对比介绍它们的原理、使用方法、适用场景和优缺点等。介 绍网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求,但在实现方面也具有一定的灵活性。因此,业界已有不少不同的网络方案,来满足特定的环境和要求。CNI意为容器网络接口,它是一种标准的设计,为了让用户在容器创建或销毁时都能够更容易地配置容器网络。在本文中,我们将集中探索与对比目前最流行的CNI插件:Flannel、Calico、Weave和Canal(技术上是多个插件的组合)。这些插件既可以确保满足Kubernetes的网络要求,又能为Kubernetes集群管理员提供他们所需的某些特定的网络功能。背 景容器网络是容器选择连接到其他容器、主机和外部网络(如Internet)的机制。容器的runtime提供了各种网络模式,每种模式都会产生不同的体验。例如,Docker默认情况下可以为容器配置以下网络:none:将容器添加到一个容器专门的网络堆栈中,没有对外连接。host:将容器添加到主机的网络堆栈中,没有隔离。default bridge:默认网络模式。每个容器可以通过IP地址相互连接。自定义网桥:用户定义的网桥,具有更多的灵活性、隔离性和其他便利功能。Docker还可以让用户通过其他驱动程序和插件,来配置更高级的网络(包括多主机覆盖网络)。CNI的初衷是创建一个框架,用于在配置或销毁容器时动态配置适当的网络配置和资源。下面链接中的CNI规范概括了用于配制网络的插件接口,这个接口可以让容器运行时与插件进行协调:https://github.com/containern…插件负责为接口配置和管理IP地址,并且通常提供与IP管理、每个容器的IP分配、以及多主机连接相关的功能。容器运行时会调用网络插件,从而在容器启动时分配IP地址并配置网络,并在删除容器时再次调用它以清理这些资源。运行时或协调器决定了容器应该加入哪个网络以及它需要调用哪个插件。然后,插件会将接口添加到容器网络命名空间中,作为一个veth对的一侧。接着,它会在主机上进行更改,包括将veth的其他部分连接到网桥。再之后,它会通过调用单独的IPAM(IP地址管理)插件来分配IP地址并设置路由。在Kubernetes中,kubelet可以在适当的时间调用它找到的插件,来为通过kubelet启动的pod进行自动的网络配置。术 语在对CNI插件们进行比较之前,我们可以先对网络中会见到的相关术语做一个整体的了解。不论是阅读本文,还是今后接触到其他和CNI有关的内容,了解一些常见术语总是非常有用的。一些最常见的术语包括:第2层网络: OSI(Open Systems Interconnections,开放系统互连)网络模型的“数据链路”层。第2层网络会处理网络上两个相邻节点之间的帧传递。第2层网络的一个值得注意的示例是以太网,其中MAC表示为子层。第3层网络: OSI网络模型的“网络”层。第3层网络的主要关注点,是在第2层连接之上的主机之间路由数据包。IPv4、IPv6和ICMP是第3层网络协议的示例。VXLAN:代表“虚拟可扩展LAN”。首先,VXLAN用于通过在UDP数据报中封装第2层以太网帧来帮助实现大型云部署。VXLAN虚拟化与VLAN类似,但提供更大的灵活性和功能(VLAN仅限于4096个网络ID)。VXLAN是一种封装和覆盖协议,可在现有网络上运行。Overlay网络:Overlay网络是建立在现有网络之上的虚拟逻辑网络。Overlay网络通常用于在现有网络之上提供有用的抽象,并分离和保护不同的逻辑网络。封装:封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在overlay网络中,封装被用于从虚拟网络转换到底层地址空间,从而能路由到不同的位置(数据包可以被解封装,并继续到其目的地)。网状网络:网状网络(Mesh network)是指每个节点连接到许多其他节点以协作路由、并实现更大连接的网络。网状网络允许通过多个路径进行路由,从而提供更可靠的网络。网状网格的缺点是每个附加节点都会增加大量开销。BGP:代表“边界网关协议”,用于管理边缘路由器之间数据包的路由方式。BGP通过考虑可用路径,路由规则和特定网络策略,帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP有时被用作CNI插件中的路由机制,而不是封装的覆盖网络。了解了技术术语和支持各类插件的各种技术之后,下面我们可以开始探索一些最流行的CNI插件了。CNI比较Flannel链接:https://github.com/coreos/fla…由CoreOS开发的项目Flannel,可能是最直接和最受欢迎的CNI插件。它是容器编排系统中最成熟的网络结构示例之一,旨在实现更好的容器间和主机间网络。随着CNI概念的兴起,Flannel CNI插件算是早期的入门。与其他方案相比,Flannel相对容易安装和配置。它被打包为单个二进制文件flanneld,许多常见的Kubernetes集群部署工具和许多Kubernetes发行版都可以默认安装Flannel。Flannel可以使用Kubernetes集群的现有etcd集群来使用API存储其状态信息,因此不需要专用的数据存储。Flannel配置第3层IPv4 overlay网络。它会创建一个大型内部网络,跨越集群中每个节点。在此overlay网络中,每个节点都有一个子网,用于在内部分配IP地址。在配置pod时,每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信,而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中,以便路由到适当的目标。Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN,因为VXLAN性能更良好并且需要的手动干预更少。总的来说,Flannel是大多数用户的不错选择。从管理角度来看,它提供了一个简单的网络模型,用户只需要一些基础知识,就可以设置适合大多数用例的环境。一般来说,在初期使用Flannel是一个稳妥安全的选择,直到你开始需要一些它无法提供的东西。Calico链接:https://github.com/projectcal…Calico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。在满足系统要求的新配置的Kubernetes集群上,用户可以通过应用单个manifest文件快速部署Calico。如果您对Calico的可选网络策略功能感兴趣,可以向集群应用其他manifest,来启用这些功能。尽管部署Calico所需的操作看起来相当简单,但它创建的网络环境同时具有简单和复杂的属性。与Flannel不同,Calico不使用overlay网络。相反,Calico配置第3层网络,该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时,不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包,而无需额外在流量层中打包流量。除了性能优势之外,在出现网络问题时,用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案,但该过程处理数据包的方式同场难以追踪。使用Calico,标准调试工具可以访问与简单环境中相同的信息,从而使更多开发人员和管理员更容易理解行为。除了网络连接外,Calico还以其先进的网络功能而闻名。 网络策略是其最受追捧的功能之一。此外,Calico还可以与服务网格Istio集成,以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则,描述pod应如何发送和接受流量,提高安全性并控制网络环境。如果对你的环境而言,支持网络策略是非常重要的一点,而且你对其他性能和功能也有需求,那么Calico会是一个理想的选择。此外,如果您现在或未来有可能希望得到技术支持,那么Calico是提供商业支持的。一般来说,当您希望能够长期控制网络,而不是仅仅配置一次并忘记它时,Calico是一个很好的选择。Canal链接:https://github.com/projectcal…Canal也是一个有趣的选择,原因有很多。首先,Canal 是一个项目的名称,它试图将Flannel提供的网络层与Calico的网络策略功能集成在一起。然而,当贡献者完成细节工作时却发现,很明显,如果Flannel和Calico这两个项目的标准化和灵活性都已各自确保了话,那集成也就没那么大必要了。结果,这个官方项目变得有些“烂尾”了,不过却实现了将两种技术部署在一起的预期能力。出于这个原因,即使这个项目不复存在,业界还是会习惯性地将Flannel和Calico的组成称为“Canal”。由于Canal是Flannel和Calico的组合,因此它的优点也在于这两种技术的交叉。网络层用的是Flannel提供的简单overlay,可以在许多不同的部署环境中运行且无需额外的配置。在网络策略方面,Calico强大的网络规则评估,为基础网络提供了更多补充,从而提供了更多的安全性和控制。确保集群满足必要的系统要求(https://docs.projectcalico.or…)后,用户需要应用两个manifest才能部署Canal,这使得其配置比单独的任何一个项目都困难。如果企业的IT团队计划改变他们的网络方案,且希望在实施改变之前能先对网络策略进行一些实验并获取一些经验,那么Canal是一个不错的选择。一般来说,如果你喜欢Flannel提供的网络模型,但发现Calico的一些功能很诱人,那么不妨尝试一下Canal。从安全角度来看,定义网络策略规则的能力是一个巨大的优势,并且在许多方面是Calico的杀手级功能。能够将该技术应用到熟悉的网络层,意味着您可以获得更强大的环境,且可以省掉大部分的过渡过程。Weave链接:https://www.weave.works/oss/net/Weave是由Weaveworks提供的一种Kubernetes CNI网络选项,它提供的模式和我们目前为止讨论的所有网络方案都不同。Weave在集群中的每个节点之间创建网状overlay网络,参与者之间可以灵活路由。这一特性再结合其他一些独特的功能,在某些可能导致问题的情况下,Weave可以智能地路由。为了创建网络,Weave依赖于网络中每台主机上安装的路由组件。然后,这些路由器交换拓扑信息,以维护可用网络环境的最新视图。当需要将流量发送到位于不同节点上的pod时,Weave路由组件会自动决定是通过“快速数据路径”发送,还是回退到“sleeve”分组转发的方法。快速数据路径依靠内核的本机Open vSwitch数据路径模块,将数据包转发到适当的pod,而无需多次移入和移出用户空间。Weave路由器会更新Open vSwitch配置,以确保内核层具有有关如何路由传入数据包的准确信息。相反,当网络拓扑不适合快速数据路径路由时,sleeve模式可用作备份。它是一种较慢的封装模式,在快速数据路径缺少必要的路由信息或连接的情况下,它可以来路由数据包。当流量通过路由器时,它们会了解哪些对等体与哪些MAC地址相关联,从而允许它们以更少的跳数、更智能地路由后续流量。当网络更改导致可用路由改变时,这一相同的机制可以帮助每个节点进行自行更正。与Calico一样,Weave也为Kubernetes集群提供网络策略功能。设置Weave时,网络策略会自动安装和配置,因此除了添加网络规则之外,用户无需进行其他配置。一个其他网络方案都没有、Weave独有的功能,是对整个网络的简单加密。虽然这会增加相当多的网络开销,但Weave可以使用NaCl加密(http://nacl.cr.yp.to)来为sleeve流量自动加密所有路由流量,而对于快速数据路径流量,因为它需要加密内核中的VXLAN流量,Weave会使用IPsec ESP来加密快速数据路径流量。对于那些寻求功能丰富的网络、同时希望不要增加大量复杂性或管理难度的人来说,Weave是一个很好的选择。它设置起来相对容易,提供了许多内置和自动配置的功能,并且可以在其他解决方案可能出现故障的场景下提供智能路由。网状拓扑结构确实会限制可以合理容纳的网络的大小,不过对于大多数用户来说,这也不是一个大问题。此外,Weave也提供收费的技术支持,可以为企业用户提供故障排除等等技术服务。结 语Kubernetes采用的CNI标准,让Kubernetes生态系统中的网络解决方案百花齐放。更多样的选择,意味着大多数用户将能够找到适合其当前需求和部署环境的CNI插件,同时还可以在环境发生变化时也能找到新的解决方案。不同企业之间的运营要求差异很大,因此拥有一系列具有不同复杂程度和功能丰富性的成熟解决方案,大大有助于Kubernetes在满足不同用户独特需求的前提下,仍然能够提供一致的用户体验。

March 29, 2019 · 1 min · jiezi

Kubernetes 如何打赢容器之战?

阿里妹导读:Kubernetes 近几年很热门,在各大技术论坛上被炒的很火。它提供了强大的容器编排能力,与此同时 DevOps 的概念也来到大家身边,广大的开发同学也能简单地运维复杂的商业化分布式系统,打破了传统开发和运维之间的界限。本文会以初学者的视角,希望能让读者更好地理解 Kubernetes 出现的背景、超前的设计理念和优秀的技术架构。背景PaaSPaaS 技术,一句话概括就是:它提供了“应用托管”的能力。早期的主流做法基本上是租 AWS 或者 OpenStack 的虚拟机,然后把这些虚拟机当作物理机一样,用脚本或者手工的方式在上面部署应用。这个过程中如何保证本地环境和云端环境的一致性是一个很大的课题,而提供云计算服务的公司的核心竞争力就是比拼谁做的更好。从某种意义上来说 PaaS 的出现,算是一个比较好的解决方案。以 Cloud Foundry 为例,在虚拟机上部署上 Cloud Foundry 项目后,用户可以很方便地把自己的应用上云。以上帝视角来看这个过程:Cloud Foundry 最核心的是提供了一套应用的打包和分发机制,它为不同的编程语言定义了不同的打包格式,它能把可执行文件、启动参数等等一起打包成压缩包然后上传至 Cloud Foundry 存储中心,最后由调度器选择虚拟机,由虚拟机上的 Agent 下载并启动应用。分布式系统随着软件的规模越来越大,业务模式越来越复杂,用户量的上升、地区的分布、系统性能的苛刻要求都促成服务架构从最初的单体变成 SOA 再到如今的微服务,未来还可能演变为 Service Mesh ,Serverless 等等。如今,一个完整的后端系统不再是单体应用架构了,多年前的 DDD 概念重新回到大家的视线中。现在的系统被不同的职责和功能拆成多个服务,服务之间复杂的关系以及单机的单点性能瓶颈让部署和运维变得很复杂,所以部署和运维大型分布式系统的需求急迫待解决。容器技术前面提到诸如 Cloud Foundry 的 PaaS,用户必须为不同语言、不同框架区分不同的打包方式,这个打包过程是非常具有灾难性的。而现实往往更糟糕,当在本地跑的好好的应用,由于和远端环境的不一致,在打包后却需要在云端各种调试,最终才能让应用“平稳”运行。而 Docker 的出现改变了一切,它凭借镜像解决了这个问题。Docker 一不做二不休,干脆把完整的操作系统目录也打包进去,如此高的集成度,保证了云端和本地环境的高度一致,并且随时随地轻易地移植。谁也不知道就因为“镜像”这个简单的功能,Docker 完成了对 PaaS 的降维打击,占有了市场。此时,一些聪明的技术公司纷纷跟进 Docker,推出了自家的容器集群管理项目,并且称之为 CaaS。容器技术利用 Namespace 实现隔离,利用 Cgroups 实现限制;在 Docker 实现上,通过镜像,为容器提供完整的系统执行环境,并且通过 UnionFS 实现 Layer 的设计。Docker 容器是完全使用沙箱机制,相互之间不会有任何接口。通过 Docker,实现进程、网络、挂载点和文件隔离,更好地利用宿主机资源。Docker 强大到不需要关心宿主机的依赖,所有的一切都可以在镜像构建时完成,这也是 Docker 目前成为容器技术标准的原因。所以我们能看到在 Kubernetes 中默认使用 Docker 作为容器(也支持 rkt)。Kubernetes铺垫了这么多,终于说到本文的主角了。说 Kubernetes 之前,不得不提 Compose、Swarm、Machine 三剑客,其实在 Kubernetes 还未一统江湖之前,它们已经能实现大部分容器编排的能力了。但是在真正的大型系统上,它们却远远不如 Mesosphere 公司出品的大型集群管理系统,更别说之后的 Kubernetes 了。在容器化和微服务时代,服务越来越多,容器个数也越来越多。Docker 如它 Logo 所示一样,一只只鲸鱼在大海里自由地游荡,而 Kubernetes 就像一个掌舵的船长,带着它们,有序的管理它们,这个过程其实就是容器编排。Kubernetes 起源于 Google,很多设计都是源自于 Borg,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效,并且提供了应用部署,规划,更新,维护的一种机制。小结至此,读者了解了 Kubernetes 的前世今生,由 PaaS 的火热,引爆了容器技术的战争,而赢得这场战争中最关键的即是拥有强大的容器编排的能力,而 Kubernetes 无疑是这场战争的胜利者。设计理念这一部分,我们会围绕 Kubernetes 的四个设计理念看看这些做法能给我们带来什么。声明式 VS 命令式声明式和命令式是截然不同的两种编程方式,在命令式 API 中,我们可以直接发出服务器要执行的命令,例如: “运行容器”、“停止容器”等;在声明式 API 中,我们声明系统要执行的操作,系统将不断向该状态驱动。我们常用的 SQL 就是一种声明式语言,告诉数据库想要的结果集,数据库会帮我们设计获取这个结果集的执行路径,并返回结果集。众所周知,使用 SQL 语言获取数据,要比自行编写处理过程去获取数据容易的多。apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: etcd-operatorspec: replicas: 1 template: metadata: labels: name: etcd-operator spec: containers: - name: etcd-operator image: quay.io/coreos/etcd-operator:v0.2.1 env: - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name我们来看看相同设计的 YAML,利用它,我们可以告诉 Kubernetes 最终想要的是什么,然后 Kubernetes 会完成目标。声明式 API 使系统更加健壮,在分布式系统中,任何组件都可能随时出现故障。当组件恢复时,需要弄清楚要做什么,使用命令式 API 时,处理起来就很棘手。但是使用声明式 API ,组件只需查看 API 服务器的当前状态,即可确定它需要执行的操作。显式的 APIKubernetes 是透明的,它没有隐藏的内部 API。换句话说 Kubernetes 系统内部用来交互的 API 和我们用来与 Kubernetes 交互的 API 相同。这样做的好处是,当 Kubernetes 默认的组件无法满足我们的需求时,我们可以利用已有的 API 实现我们自定义的特性。无侵入性感谢 Docker 容器技术的流行,使得 Kubernetes 为大家提供了无缝的使用方式。在容器化的时代,我们的应用达到镜像后,不需要改动就可以遨游在 Kubernetes 集群中。Kubernetes 还提供存储 Secret、Configuration 等包含但不局限于密码、证书、容器镜像信息、应用启动参数能力。如此,Kubernetes 以一种友好的方式将这些东西注入 Pod,减少了大家的工作量,而无需重写或者很大幅度改变原有的应用代码。有状态的移植在有状态的存储场景下,Kubernetes 如何做到对于服务和存储的分离呢?假设一个大型分布式系统使用了多家云厂商的存储方案,如何做到开发者无感于底层的存储技术体系,并且做到方便的移植?为了实现这一目标,Kubernetes 引入了 PersistentVolumeClaim(PVC)和 PersistentVolume(PV)API 对象。这些对象将存储实现与存储使用分离。PersistentVolumeClaim 对象用作用户以与实现无关的方式请求存储的方法,通过它来抹除对底层 PersistentVolume 的差异性。这样就使 Kubernetes 拥有了跨集群的移植能力。架构首先要提及的是 Kubernetes 使用很具代表性的 C/S 架构方式,Client 可以使用 kubectl 命令行或者 RESTful 接口与 Kubernetes 集群进行交互。下面这张图是从宏观上看 Kubernetes 的整体架构,每一个 Kubernetes 集群都由 Master 节点 和 很多的 Node 节点组成。MasterMaster 是 Kubernetes 集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有 Etcd 存储服务,运行 API Server 进程,Controller Manager 服务进程及 Scheduler 服务进程,关联工作节点 Node。Kubernetes API Server 提供 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增、删、改、查等操作的唯一入口。也是集群控制的入口进程; Kubernetes Controller Manager 是 Kubernetes 所有资源对象的自动化控制中心,它驱使集群向着我们所需要的最终目的状态; Kubernetes Schedule 是负责 Pod 调度的进程。NodeNode 是 Kubernetes 集群架构中运行 Pod 的服务节点。Node 是 Kubernetes 集群操作的单元,用来承载被分配 Pod 的运行,是 Pod 运行的宿主机。关联 Master 管理节点,拥有名称和 IP、系统资源信息。运行 Docker Runtime、kubelet 和 kube-proxy。kubelet 负责对 Pod 对于的容器的创建、启停等任务,发送宿主机当前状态; kube-proxy 实现 Kubernetes Service 的通信与负载均衡机制的重要组件; Docker Runtime 负责本机容器的创建和管理工作。实现原理为了尽可能地让读者能明白 Kubernetes 是如何运作的,这里不会涉及到具体的细节实现,如有读者感兴趣可以自行参阅官网文档。这里以一个简单的应用部署示例来阐述一些概念和原理。创建 Kubernetes 集群介绍架构的时候我们知道,Kubernetes 集群由 Master 和 Node 组成。Master 管理集群的所有行为例如:应用调度、改变应用的状态,扩缩容,更新/降级应用等。Node 可以是是一个虚拟机或者物理机,它是应用的“逻辑主机”,每一个 Node 拥有一个 Kubelet,Kubelet 负责管理 Node 节点与 Master 节点的交互,同时 Node 还需要有容器操作的能力,比如 Docker 或者 rkt。理论上来说,一个 Kubernetes 为了应对生产环境的流量,最少部署3个 Node 节点。当我们需要在 Kubernetes 上部署应用时,我们告诉 Master 节点,Master 会调度容器跑在合适的 Node 节点上。我们可以使用 Minikube 在本地搭一个单 Node 的 Kubernetes 集群。部署应用当创建好一个 Kubernetes 集群后,就可以把容器化的应用跑在上面了。我们需要创建一个 Deployment,它会告诉 Kubernetes Master 如何去创建应用,也可以来更新应用。当应用实例创建后,Deployment 会不断地观察这些实例,如果 Node 上的 Pod 挂了,Deployment 会自动创建新的实例并且替换它。相比传统脚本运维的方式,这种方式更加优雅。我们能通过 kubectl 命令或者 YAML 文件来创建 Deployment,在创建的时候需要指定应用镜像和要跑的实例个数,之后 Kubernetes 会自动帮我们处理。查看 Pods 和 Nodes下面来介绍下 Pod 和 Node:当我们创建好 Deployment 的时候,Kubernetes 会自动创建 Pod 来承载应用实例。Pod 是一个抽象的概念,像一个“逻辑主机”,它代表一组应用容器的集合,这些应用容器共享资源,包括存储,网络和相同的内部集群 IP。任何一个 Pod 都需要跑在一个 Node 节点上。Node 是一个“虚拟机器”,它可以是虚拟机也可以是物理机,一个 Node 可以有多个 Pods,Kubernetes 会自动调度 Pod 到合适的 Node 上。Service 与 LabelSelectorPods 终有一死,也就是说 Pods 也有自己的生命周期,当一个 Pod 挂了的时候,ReplicaSet 会创建新的,并且调度到合适的 Node 节点上。考虑下访问的问题,Pod 替换伴随着 IP 的变化,对于访问者来说,变化的 IP 是合理的;并且当有多个 Pod 节点时,如何 SLB 访问也是个问题,Service 就是为了解决这些问题的。Service 是一个抽象的概念,它定义了一组逻辑 Pods,并且提供访问它们的策略。和其他对象一样,Service 也能通过 kubectl 或者 YAML 创建。Service 定义的 Pod 可以写在 LabelSelector 选项中(下文会介绍),也存在不指定 Pods 的情况,这种比较复杂,感兴趣的读者可以自行查阅资料。Service 有以下几种类型:ClusterIP(默认):在集群中内部IP上暴露服务,此类型使Service只能从群集中访问;NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务;LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务;ExternalName:通过返回 CNAME 和它的值,(适用于外部 DNS 的场景)Labels 和 Selectors 能够让 Kubernetes 拥有逻辑运算的能力,有点像 SQL。举个例子:可以查找 app=hello_word 的所有对象,也可以查找 app in (a,b,c) abc的所有对象。Labels是一个绑定在对象上的 K/V 结构,它可以在创建或者之后的时候的定义,在任何时候都可以改变。扩容应用前文提到我们可以使用 Deployment 增加实例个数,下图是原始的集群状态:我们可以随意的更改 replicas (实例个数)来扩容,当我们更改了 Deployment 中的 replicas 值时,Kubernetes 会自动帮我们达到想要的目标实例个数,如下图:更新应用更新应用和扩容类似,我们可以更改 Deployment 中的容器镜像,然后 Kubernetes 会帮住我们应用更新(蓝绿、金丝雀等方式),通过此功能,我们还可以实现切换应用环境、回滚、不停机 CI/CD。下面是部署的过程,需要注意的是我们可以指定新创建的 Pod 最大个数和不可用 Pod 最大个数:总结到了最后,大家对 Kubernetes 有个大概的了解了,但 Kubernetes 远远不止本文所介绍的这些内容。在云原生概念逐渐清晰的今天,Kubernetes 作为 CNCF 中一个接地气的落地项目,其重要性不言而喻。本文作者: 淘敏阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

March 28, 2019 · 3 min · jiezi

Rancher 2.2 GA:企业进入应用跨多K8S集群、混合云部署新时代

Rancher 2.2 GA版本引入的创造性新功能,将进一步实现Kubernetes-as-a-service,使企业用户能够专注于加速创新和推动业务价值。2019年3月26日,业界领先的容器管理软件提供商Rancher Labs正式发布Rancher 2.2 GA版本。Rancher 2.2中创造性的新功能,将极大简化IT运维人员对企业级Kubernetes的配置与管理工作,同时让企业IT开发人员对其应用程序拥有更强把控。通过Rancher 2.2,企业的IT团队可以极大减少对基础架构的担忧,更多地关注于加速创新和推动业务价值。“随着Kubernetes的采用呈指数级增长,企业IT人员一直在寻求一种简单、可靠和可重复的方式来配置、管理和支持企业级Kubernetes集群,且越来越多企业的Kubernetes集群是跨本地环境与云环境混合部署的,”梁胜,Rancher Labs联合创始人及CEO表示。 “Rancher 2.2正式版本中有很多功能来满足这些需求,包括用于灾备和恢复的etcd自动备份和恢复,用于提高敏感项目隐私的多租户应用程序目录,以及为跨多个集群的应用程序提供高可用性的Global DNS功能。”简化Kubernetes,加速混合云场景的企业创新Rancher 2.2 GA版本是Rancher Labs迄今为止最重要的产品版本,在先前发布过的2.2技术预览版本中,已经释出了诸如支持多集群应用程序、集成的Prometheus高级监控等功能。Rancher 2.2 GA的主要新功能亮点包括:Rancher Global DNS集群的灾备与恢复多集群、多租户的进阶版监控功能单一应用跨多Kubernetes集群的部署与管理多租户应用程序目录Rancher Global DNS相信没有人会喜欢先自动化部署应用程序、然后手动添加或者更改DNS记录。Rancher Global DNS能配置和维护与应用程序的Kubernetes Ingress的IP地址对应的外部DNS记录,从而解决上述问题。这本身并非一个新奇的概念,但Rancher的创新之处在于它可以为部署在多个集群中的应用程序执行这一操作。用户现在可以根据需要,将应用程序部署到任意数量的集群,并且让DNS自动更新,以指向所有集群的应用程序入口。Rancher将通过自动将服务的主机名编程到公共DNS,对部署在多个集群中的应用程序或同一集群中的多个项目提供公共访问。 此次发布的版本包含对Route53和AliDNS的支持,以及对CloudFlare的alpha支持。对其他提供商的支持也正在开发中,会在后续小版本更新中与大家见面。集群的灾备与恢复Rancher 2.2直接在Rancher UI/API和Kubernetes API当中添加了对etcd数据存储的备份恢复的支持。Rancher会从Rancher UI/API或Kubernetes API执行etcd的预定和临时备份,写入本地存储、NFS或任何与S3兼容的对象库。此处值得一提的是Rancher 2.2以终端形式支持兼容S3协议的存储,因此,用户无需使用NFS,也可以立刻从主机上获取备份。当意外情况发生时,用户通过UI即可简单快速地将这些备份直接还原到集群当中。多集群、多租户的进阶版监控功能Rancher的一大功能亮点是单集群多租户,一个或者多个用户可以访问某个Project且只能查看该Project内的资源,即使集群中还有其他用户或其他Project 。Rancher一直使用Prometheus进行监控和告警。在Rancher 2.2中,监控功能更进一步加强,是唯一一个在多集群、多租户环境中支持Prometheus的解决方案。Rancher 2.2 GA版本中,Rancher的进阶版监控功能以尊重多租户环境边界的方式部署了Prometheus和Grafana。Grafana安装了预构建的集群和项目仪表板。用户只需选中相应复选框来激活高级指标,不出几分钟就能查看有效的图表。Rancher的监控覆盖了从每个项目中的集群节点到Pod的所有内容,如果应用程序公开了自己的指标,Prometheus将抓取这些内容并供用户使用。多集群应用程序Rancher是为多集群管理而生的,它通过自己的应用程序目录(Catalog)与Helm进行了强而有力的集成。Rancher的Catalog采用了Helm的键/值YAML,并将其转换为了直观、简单、任何人都可以快速使用的形式。在Rancher2.2中,应用程序目录也存在于全局级别,您可以通过Helm将应用程序无缝部署到任意数量集群中的多个Project里。这为需要在不同环境中维护应用程序的人节省了大量的时间,特别是在升级所有这些应用程序时,Rancher将使用Helm的atomic releases功能批量升级和回滚。由于多集群应用程序是构建在Helm之上的,因此它们还可以和CI/CD系统或其他任何自动配置程序一起开箱即用。多租户应用程序目录在Rancher的早期版本中,应用程序目录和任何外部Helm仓库的配置都存在于全局级别,然后传播到集群当中。这意味着每个集群都可以访问相同的Helm chart,虽然这对大多数安装都有效,但并不是适用于所有情况。Rancher 2.2为应用目录程序提供了特定于集群和项目的配置。用户可以完全删除它,或更改特定集群或项目可以访问的内容,或者为用户批准的那些应用程序添加新的Helm仓库。有了多租户的应用程序目录,用户可以按集群或项目对应用程序目录进行隔离。这种更加精细的隔离,即使应用程序的名称也不能跨项目共享。一切开源,欢迎使用Rancher 2.2的一切功能都以可靠性、可重复性和易用性为中心,帮助企业IT人员加速创新,为企业业务带来价值。秉承一如既往的开源理念,欢迎在Docker Hub下载使用Rancher 2.2:https://hub.docker.com/r/ranc…欢迎在GitHub上查看Rancher 2.2的完整Release Notes,了解全部新功能及升级建议:https://github.com/rancher/ra…如您有任何疑问,欢迎发送邮件至info@rancher.com,或添加官方微信助手(微信号:Rancher2)为好友进行咨询。Kubernetes Master Class在线培训启航为了帮助大家完成Kubernetes从入门到进阶的全过程,让企业IT人员能更快上手并落地Kubernetes,Rancher Labs全新一季在线培训课程【Kubernetes Master Class】将于下周开始正式启航!整季培训将有共计8期课程,为期两个月,每周三(除5月1日)晚20:30开课。全部课程现已上线,坐席有限,欢迎及早预约报名。第1期:Kubernetes入门之快速创建集群(4月3日)观看地址:http://live.vhall.com/910031185第2期:如何快速部署Kubernetes应用(4月10日)观看地址:http://live.vhall.com/810844440第3期:Kubernetes应用商店:Harbor与Istio(4月17日)观看地址:http://live.vhall.com/231749318第4期:企业如何构建CI/CD流水线(4月24日)观看地址:http://live.vhall.com/729465809第5期:Kubernetes中的日志、监控与告警(5月8日)观看地址:http://live.vhall.com/317569561第6期:在Kubernetes中创建高可用应用(5月15日)观看地址:http://live.vhall.com/847710932第7期:创建生产级别的Kubernetes集群(5月22日)观看地址:http://live.vhall.com/456248926第8期:Kubernetes中的安全、灾备与恢复(5月29日)观看地址:http://live.vhall.com/118924683About Rancher LabsRancher Labs由硅谷云计算泰斗、CloudStack之父梁胜创建,致力于打造创新的开源软件,帮助企业在生产环境中运行容器与Kubernetes。旗舰产品Rancher是一个开源的企业级Kubernetes平台,是业界首个且唯一可以管理所有云上、所有发行版、所有Kubernetes集群的平台。解决了生产环境中企业用户可能面临的基础设施不同的困境,改善Kubernetes原生UI易用性不佳以及学习曲线陡峭的问题,是企业落地Kubernetes的不二之选。Rancher在全球拥有超过一亿的下载量,超过20000家企业客户。全球知名企业如中国人寿、华为、中国平安、民生银行、兴业银行、上汽集团、海尔、米其林、天合光能、丰田、本田、霍尼韦尔、金风科技、普华永道、海南航空、厦门航空、恒大人寿、中国太平、巴黎银行、美国银行、HSCIS恒生指数、中国水利、暴雪、CCTV等均是Rancher的付费客户。

March 28, 2019 · 1 min · jiezi

CNCF案例研究:AppDirect

AppDirect:AppDirect如何通过Kubernetes支持其工程人员的10倍增长公司:AppDirect地点:旧金山,加利福尼亚工业:软件挑战AppDirect为基于云的产品和服务提供端到端的商务平台。当软件开发总监Pierre-Alexandre Lacerte于2014年开始在那里工作时,该公司在“tomcat基础架构上部署了一个单体应用程序,整个发布过程非常复杂。”他说。“涉及有很多手动步骤,一个工程师构建一个功能,然后另一个团队接手更改。所以你有一个瓶颈,将一个功能发送给生产。”与此同时,工程团队也在不断发展,公司意识到需要一个更好的基础设施来支持这种增长并提高速度。解决方法“我的想法是:让我们创建一个团队可以更快地部署他们的服务的环境,他们会说,‘好吧,我不想再建立单体。我想建立一个服务’。”Lacerte说。在决定于2016年初采用Kubernetes之前,他们考虑并制作了几种不同技术的原型。Lacerte的团队还将Prometheus监控集成到平台中;下一布是追踪。如今,AppDirect已在生产中部署了50多个微服务,在AWS和全球各地部署了15个Kubernetes集群。影响Kubernetes平台帮助支持了工程团队在过去几年中的10倍增长。加上他们不断增加新功能的事实,Lacerte说,“如果我们没有这种新的基础设施,我认为我们的速度会慢下来。”迁移到Kubernetes和服务意味着部署变得更快,因为减小了对SCP命令的定制以及脆弱shell脚本的依赖性。部署新版本的时间从4小时缩短到几分钟。此外,该公司投入了大量精力为开发者提供自助服务。“上线新服务不需要Jira门票或与三个不同的团队会面。”Lacerte说。今天,该公司每周可以看到1,600次部署,而之前是1-30次。该公司还通过将其市场和计费单块,从传统的EC2主机迁移到Kubernetes,以及利用自动缩放来实现成本节约,因为在工作时间内流量更高。“这是一个巨大的工程文化转变,但在规模和速度方面的好处是不可否认的。” - ALEXANDRE GERVAIS,软件开发者,APPDIRECT凭借其基于云的产品和服务的端到端商务平台,AppDirect自2009年以来一直在帮助Comcast和GoDaddy等组织简化数字供应链。当软件开发总监Pierre-Alexandre Lacerte于2014年开始在那里工作时,该公司在“tomcat基础架构上部署了一个单体应用程序,整个发布过程非常复杂。”他说。“涉及有很多手动步骤,一个工程师构建一个功能,然后创建一个拉取请求,之后一个QA或另一个工程师验证该功能。然后合并,其他人将负责部署。所以我们将一项功能运送到生产有瓶颈。”与此同时,40人的工程团队正在发展壮大,该公司希望为其产品增加越来越多的功能。作为平台团队的一员,Lacerte开始听取多个团队的意见,他们希望使用不同的框架和语言部署应用程序,从Node.js到Spring Boot Java。他很快意识到,为了支持增长和提高速度,公司需要一个更好的基础设施,一个团队自治的系统,可以自己进行部署,并为他们自己的生产服务负责。“我们在正确的时间做出了正确的决定。Kubernetes和云原生技术现在被视为事实上的生态系统。我们知道在哪里集中精力来应对我们在扩展时面临的新一轮挑战。社区是如此活跃和充满活力,这是我们卓越的内部团队的重要补充。” - ALEXANDRE GERVAIS,软件开发者,APPDIRECT从一开始,Lacerte说:“我的想法是:让我们创建一个团队可以更快地部署服务的环境,他们会说,‘好吧,我不想再建立单体。我想建立一个服务。’”(Lacerte在2019年离开了公司。)通过与运营团队合作,Lacerte的团队获得了对公司AWS基础架构的更多控制权和使用权,并开始了几种编排技术的原型设计。“当时,Kubernetes有点地下,不为人知。”他说。“但我们看了社区,拉动请求的数量,GitHub上的速度,我们看到它正在变得越来越有吸引力。我们发现管理比其他技术更容易。”他们使用Chef和Terraform配置在Kubernetes上跑了前几个服务,并且随着更多服务的增加,也有更多的自动化。“我们在世界各地都有集群 - 在韩国、澳大利亚、德国和美国。”Lacerte说。“自动化对我们至关重要。”他们现在主要使用Kops,并且正在寻找来自多家云提供商的托管Kubernetes产品。今天,虽然单体应用仍然存在,但提交和功能越来越少。所有团队都部署在新的基础架构,服务是常态。AppDirect现在拥有50多个微服务器,在AWS和全球各地部署了15个Kubernetes集群。Lacerte的策略最终奏效,因为Kubernetes平台对部署时间产生了非常实际的影响。由于减小了对SCP命令的定制以及脆弱shell脚本的依赖性,部署新版本的时间从4小时缩短到几分钟。此外,该公司投入了大量精力为开发者提供自助服务。“上线新服务不需要Jira门票或与三个不同的团队会面。”Lacerte说。今天,该公司每周可以看到1,600次部署,而之前是1-30次。“如果我们没有这种新的基础设施,我认为我们的速度会放慢很多。” - PIERRE-ALEXANDRE LACERTE,软件开发总监,APPDIRECT此外,Kubernetes平台在过去几年中帮助支持了工程团队10倍的增长。“所有权,AppDirect的核心价值,反映了我们独立于单体代码库提供服务的能力。”与Lacerte合作的软件开发者Alexandre Gervais说道。“小型团队现在拥有我们业务领域模型的关键部分,他们在专业知识的分离领域运营,对整个代码库知之甚少。这减少并隔离了一些复杂性。”加上他们不断增加新功能的事实,Lacerte说,“如果我们没有这种新的基础设施,我认为我们的速度会慢下来。”该公司还通过将其市场和计费单块从传统的EC2主机,迁移到Kubernetes,以及利用自动缩放来实现成本节约,因为在工作时间内流量更高。AppDirect的云原生堆栈还包括gRPC和Fluentd,该团队目前正在设置OpenCensus。该平台已经集成了Prometheus,因此“当团队部署他们的服务时,他们会收到通知、警报和配置。”Lacerte说。“例如,在测试环境中,我想在Slack上收到一条消息,在生产中,我想要一条Slack消息,我也希望收到传呼。我们已经与PagerDuty集成。团队对他们的服务拥有更多的所有权。”“我们从’推送代码分支’的文化转到代码库之外的令人兴奋的新职责:功能和配置的部署;应用程序和业务指标的监控;以及在中断情况下的随叫随到的支持。一个巨大的工程文化转变,但在规模和速度方面的好处是不可否认的。” - PIERRE-ALEXANDRE LACERTE,软件开发总监,APPDIRECT这当然也意味着更多的责任。“我们要求工程师扩大他们的视野。”Gervais说。“我们从’推送代码分支’的有限度工作文化,转到代码库之外的令人兴奋的新职责:功能和配置的部署;应用程序和业务指标的监控;以及在中断情况下的随叫随到的支持。一个巨大的工程文化转变,但在规模和速度方面的好处是不可否认的。”随着工程队伍的不断增长,平台团队面临着新的挑战,即确保Kubernetes平台可供所有人访问和使用。“我们怎样才能确保当我们为团队增加更多人员时,他们能提高效率,提高工作效率,并知道如何在平台上开发?”Lacerte 说。“所以我们有布道者、文档、一些项目实例。我们做演示,我们有AMA会议。我们尝试不同的策略来引起所有人的注意。”在他们Kubernetes之旅的三年半时间里,Gervais认为AppDirect“在合适的时间做出了正确的决定”,他说。“Kubernetes和云原生技术现在被视为事实上的生态系统。我们知道在哪里集中精力来应对我们在扩展时面临的新一轮挑战。社区是如此活跃和充满活力,这是我们卓越的内部团队的重要补充。展望未来,我们的重点将是通过在日常运营中提供额外的商业价值来从生态系统中获益。”KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 28, 2019 · 1 min · jiezi

Kubernetes Ingress 日志分析与监控的最佳实践

Ingress 主要提供 HTTP 层(7 层)路由功能,是目前 K8s 中 HTTP/HTTPS 服务的主流暴露方式。为简化广大用户对于 Ingress 日志分析与监控的门槛,阿里云容器服务和日志服务将 Ingress 日志打通,只需要应用一个 yaml 资源即可完成日志采集、分析、可视化等一整套 Ingress 日志方案的部署。前言目前 Kubernetes(K8s)已经真正地占领了容器编排市场,是默认的云无关计算抽象,越来越多的企业开始将服务构建在K8s集群上。在 K8s 中,组件通过 Service 对外暴露服务,常见的包括 NodePort、LoadBalancer、Ingress 等。其中 Ingress 主要提供 HTTP 层(7 层)路由功能,相比 TCP(4 层)的负载均衡具备非常多的优势(路由规则更加灵活、支持金丝雀、蓝绿、A/B Test 发布模式、SSL 支持、日志、监控、支持自定义扩展等),是目前 K8s 中 HTTP/HTTPS 服务的主流暴露方式。Ingress 简介K8s 中 Ingress 只是一种 API 资源的声明,具体的实现需要安装对应的 Ingress Controller,由 Ingress Controller 接管 Ingress 定义,将流量转发到对应的 Service。目前 Ingress Controller 的实现有非常多种(具体可以参考 Ingress Controller官方文档),比较流行的有 Nginx、Traefik、Istio、Kong 等,在国内接受度最高的是 Nginx Ingress Controller。日志与监控日志和监控是所有 Ingress Controller 都会提供的基础功能,日志一般包括访问日志(Access Log)、控制日志(Controller Log)和错误日志(Error Log),监控主要从日志以及 Controller 中提取部分 Metric 信息。这些数据中访问日志的量级最大、信息最多、价值也最高,一般7层的访问日志包括:URL、源 IP、UserAgent、状态码、入流量、出流量、响应时间等,对于 Ingress Controller 这种转发型的日志,还包括转发的 Service 名、Service 响应时间等额外信息。从这些信息中,我们能够分析出非常多的信息,例如:网站访问的 PV、UV;访问的地域分布、设备端分布;网站访问的错误比例;后端服务的响应延迟;不同 URL 访问分布。我们的开发、运维、运营、安全等人员可以基于这些信息完成各自的需求,例如:新老版本发布前后的数据指标对比;网站质量监控、集群状态监控;恶意攻击检测、反作弊;网站访问量统计、广告转化率统计。然而手动搭建、运维一整套的 Ingress 日志分析与监控系统非常复杂,系统所需要的模块有:部署日志采集 Agent 并配置采集、解析规则;由于 K8s 集群中,访问量相对较大,因此需要搭建一个缓冲队列,例如 Redis、Kafka 等;部署实时数据分析引擎,例如 Elastic Search、clickhouse 等;部署可视化组件并搭建报表,例如 grafana、kibana 等;部署告警模块并配置告警规则,例如 ElastAlert、alertmanager 等。阿里云日志服务Ingress解决方案为简化广大用户对于 Ingress 日志分析与监控的门槛,阿里云容器服务和日志服务将 Ingress 日志打通(官方文档https://help.aliyun.com/document_detail/86532.html)),只需要应用一个 yaml 资源即可完成日志采集、分析、可视化等一整套 Ingress 日志方案的部署。Ingress 可视化分析日志服务默认为 Ingress 创建 5 个报表,分别是:Ingress 概览、Ingress 访问中心、Ingress 监控中心、Ingress 蓝绿发布监控中心、Ingress 异常检测中心。不同角色的人员可根据需求使用不同的报表,同时每个报表均提供筛选框用于筛选特定的 Service、URL、状态码等。所有的报表均基于日志服务提供的基础可视化组件实现,可根据公司实际场景进行定制化调整。Ingress 概览Ingress 概览报表主要展示当前 Ingress 的整体状态,主要包括以下几类信息:整体架构状态(1 天),包括:PV、UV、流量、响应延迟、移动端占比、错误比例等;网站实时状态(1 分钟),包括:PV、UV、成功率、5XX 比例、平均延迟、P95/P99 延迟等;用户请求类信息(1 天),包括:1天/7天访问PV对比、访问地域分布、TOP访问省份/城市、移动端占比、Android/IOS 占比等;TOPURL 统计(1 小时),包括:访问 TOP10、延迟 TOP10、5XX 错误 TOP10、404 错误 TOP10。Ingress 访问中心Ingress 访问中心主要侧重于用于访问请求相关的统计信息,一般用于运营分析,包括:当日 UV/PV、UV/PV 分布、UV/PV 趋势、TOP 访问省份/城市、TOP 访问浏览器、TOP 访问IP、移动端占比、Android/IOS 占比等。Ingress 监控中心Ingress 监控中心主要侧重于网站实时监控数据,一般用于实时监控与告警,包括:请求成功率、错误比例、5XX 比例、请求未转发比例、平均延迟、P95/P99/P9999 延迟、状态码分布、Ingress 压力分布、Service 访问 TOP10、Service 错误 TOP10、Service 延迟 TOP10、Service 流量 TOP10 等。Ingress 蓝绿发布监控中心Ingress 蓝绿发布监控中心主要用于版本发布时的实时监控与对比(版本前后对比以及蓝绿版本当前对比),以便在服务发布时快速检测异常并进行回滚。在该报表中需要选择进行对比的蓝绿版本(ServiceA 和 ServiceB),报表将根据选择动态显示蓝绿版本相关指标,包括:PV、5XX 比例、成功率、平均延迟、P95/P99/P9999 延迟、流量等。Ingress 异常检测中心Ingress 异常检测中心基于日志服务提供的机器学习算法,通过多种时序分析算法从 Ingress 的指标中自动检测异常点,提高问题发现的效率。实时监控与告警Ingress 作为 K8s 网站请求的主要入口,实时监控与告警是必不可少的 Ops 手段之一。在日志服务上,基于上述的报表,只需 3 个简单的步骤即可完成告警的创建。下述示例为 Ingress 配置 5XX 比例的告警,告警每 5 分钟执行一次,当 5XX 比例超过 1% 时触发。除了通用的告警功能外,日志服务还额外支持:多维度数据关联,即通过多组 SQL 结果交叉判断进行告警,增加告警准确度;除支持短信、语音、通知中心、email 外,还支持钉钉机器人通知、自定义 WebHook 扩展;告警的记录也以日志的形式记录,可以实现对告警失败进行告警的双保险。订阅报告日志服务除支持通过告警方式通知外,还支持报表订阅功能,可使用该功能将报表定期渲染成图片并通过邮件、钉钉群等方式发送。例如每天早上 10 点向运营群中发送昨日网站访问情况、每周发送报告到邮件组中存档、新版本发布时每 5 分钟发送一次监控报表…自定义分析如果容器服务 Kubernetes 版提供的默认报表无法满足你的分析需求,可以直接使用日志服务 SQL、仪表盘等功能进行自定义的分析和可视化。尝鲜为了让大家可以体验 Kubernetes 审计日志功能,我们特别开通了体验中心,大家可以通过 https://promotion.aliyun.com/ntms/act/logdoclist.html 进入,该页面提供了非常多和 Kubernetes相关的报表。参考文档[1]https://www.aliyun.com/product/sls[2]https://www.aliyun.com/product/kubernetes[3]https://help.aliyun.com/document_detail/86532.html[4]https://help.aliyun.com/document_detail/48162.html[5]https://help.aliyun.com/document_detail/107758.html[6]https://kubernetes.io/docs/concepts/services-networking/ingress/[7]https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 27, 2019 · 1 min · jiezi

智能扩展:成功使用云原生技术扩展基础架构的4个关键技巧

作者:Reda Benzair今天的帖子来自CNCF大使兼Streamroot工程副总裁Reda Benzair。文章最初在Streamroot技术开发者的博客上发布。在这篇文章中,我想与工程经理和后端团队分享一些高级别的要点,以帮助他们成功扩展业务,同时避免一些最常见的陷阱和短视决策。本文伴随Streamroot首席后端工程师Jordan Pittier发布的第一篇文章,以及我们去年11月在HighLoad Moscow的历程演讲。这些分享了我们在从基于VM的架构迁移到基于容器的架构,以及将我们的基础架构迁移到运行在Google Cloud上的Kubernetes的整个过程中所面临的经验和挑战。介绍和背景首先,我将向你介绍Streamroot的一些背景知识,以及为什么我们花时间调整我们的Kubernetes Engine架构,不仅要扩展规模,还要使我们的架构更具容错性。Streamroot是一家为主要内容所有者提供服务的技术供应商 - 媒体集团、电视网络和视频平台。我们的点对点视频传输解决方案为广播者提供了更高的质量和更低的成本,并与现有的CDN基础设施协同工作。去年我们(以及我们客户)面临的最大挑战之一是扩大到FIFA世界杯的破纪录的观众。事实证明,2018年世界杯是有史以来规模最大的直播赛事,Akamai在峰值时的记录的速度为22 Tbps,超过了之前超级碗记录的两倍。Akamai测量的峰值量超过22 Tbps。这是他们在2014年看到的峰值的3倍。Streamroot为法国最大的私人广播公司TF1,以及南美洲的国家电视网络提供了世界杯。为了能够以这种规模为我们的客户服务,我们需要扩展我们自己的Kubernetes引擎并能够更快地扩展。我们需要:处理大量流量,每分钟有数十万个请求到我们的后端在每届世界杯比赛开始时,在几分钟内达到巨大的峰值确保100%防故障、完全容错、坚固的后端能够承受任何故障。作为一名体育爱好者,我知道在现场直播期间甚至有两分钟的停机时间是完全不可接受的…最后但并非最不重要的是,我们必须通过只有少数后端工程师的创业规模团队完成所有这些工作…如果你对我们过去几个月的扩展历程感兴趣,并希望深入了解技术细节,你可以在Jordan Pittier和Nikolay Rodionov在莫斯科举行的HighLoad++会议演讲,以及我们的幻灯片中查看。技巧#1:新事物并不总是好事:使用云原生技术轻装上阵。自加入云原生计算基金会(CNCF)以来,Kubernetes已呈指数级增长,对这一复杂解决方案的兴趣日益浓厚,这是一种开源云原生技术的组合。去年12月,CNCF的KubeCon + CloudNativeCon在西雅图集合了来自世界各地的8000多名与会者。Kubernetes是云原生技术组件之一。还存在许多其他组件,有一些在CNCF托管(https://landscape.cncf.io/),有一些在CNCF之外,如Istio。云原生技术还很年轻,每月在不同领域涌现出各种新组件:存储、安全性、服务发现、软件包管理等。我们的建议:谨慎使用这些新组件,并保持简单(、傻瓜)。这些技术是新的,有时仍然比较粗糙,并以令人难以置信的速度发展。尝试使用所有最新的闪亮技术是没有意义的,特别是在生产中,除非这些技术是出于真正的需要。即使你拥有庞大的优秀工程师团队,你也需要考虑维护、运营和调试这些有时缺乏稳定性的新技术的成本(资源和时间)。作为经理和CNCF大使,我建议遵循CNCF分类(https://www.cncf.io/projects/)来选择具有足够成熟度级别的原生组件。CNCF定义的标准包括采用率、寿命以及是否可以依赖开源项目来构建生产工具。今天,Streamroot只利用了3个项目(Kubernetes、Prometheus和Envoy),这些项目处于成熟水平,并根据CNCF基金会已经“毕业”。那里的大量组件仍处于孵化阶段或沙箱阶段。你仍然可以使用这些,但请记住,你将面临一些风险:稳定性、错误、有限的社区、学习曲线等。最重要的是,要明白,即使可能普遍相信孵化或沙箱阶段的所有原生项目都可以填补空白并成熟生产,但这也需要考虑不会增加架构复杂性的问题。在从CNCF或CNCF外部添加任何新组件之前,请务必先问自己以下事项:我真的需要这个组件吗?我在解决一个真正的基础设施问题吗?我的工程师现在和从长远来看能够应付它吗?图:CNCF分类技巧#2:控制你的成本当启动一个重要的项目,比如将服务从基于VM的服务,转移到Kubernetes支持的基于容器的体系结构时,你的主要关注点可能不是成本,而是成功迁移。虽然你的后端成本可能不是一个即时或中期的问题,但从第一天开始就要考虑到这一点。我强烈建议你尽早跟踪Kubernetes Engine扩展成本,原因如下:清楚地了解你的资源使用情况和软件效率。后端团队的主要关注点是交付,从管理角度来看,通常很难传达高效软件和资源使用的重要性。在你的架构中发现改进的空间。对来自监控和成本进展的信息进行三角测量,有助于我们确定架构的改进。通过简单地使我们的实例适应我们的使用,并更好地了解资源的使用和消耗方式,我们能够将成本降低22%。利用基于数量的成本节约。大多数云供应商(包括Google Cloud和Amazon AWS)都会为提交的实例提供有趣的折扣。不要犹豫,为你的利益使用基础设施成本核算(和减少)。一旦达到一定的支出,即使降低10%的成本,也可以在预算中增加几千甚至几十万美元,这可以用来派遣你的团队参加会议,甚至可以雇用一个新资源来构建你的产品更快!为了说明我的第三点,GCP提供持续使用折扣选项,为长期承诺的实例提供显着折扣。例如,如果你承诺一整年的资源,你可以获得30%的折扣(就只一次,实际上很高兴在月底看到账单!)。这些折扣最高可达57%(!),为期3年。当然,我建议在承诺任何内容之前至少等待6个月,以便确定你最少使用的平均CPU和RAM资源。别怕!你无需成为公司财务或计费方面的专家即可有效跟踪你的成本。例如,如果你希望跟踪每月使用情况,则可以默认为每个项目启用费用提醒,然后使用CSV导出功能输入你喜欢的电子表格工具。或者,在GCP上,你可以启用Bigquery Billing Export选项,以便每日导出资源消耗的所有详细信息。然后,花几分钟时间构建一个带有SQL导出或Excel的简单仪表板(不要忘记让工程师正确设置资源标签以识别不同的行)。技巧#3:隔离并保持你的生产安全许多博客和文章建议你仅使用一个K8群集,但为不同的环境使用不同的命名空间(例如,Dev、Staging和Production)。命名空间是一个非常强大的功能,可以帮助你组织Kubernetes资源并提高团队的速度。但是这种设置并不容易:你需要确保有一个完善的CI/CD环境,以避免你的staging和prod环境之间的任何干扰,以及像部署错误组件在错误的命名空间中的“愚蠢”错误。读到这篇文章时,你可能会想:“当然,但我们有一个超级聪明的团队,所以我们能够处理它。”在那里停一停:每个人都犯愚蠢的错误,错误越愚蠢,它会发生的机会越多…所以,除非你想要在生产中救火过最紧张的日子,只因为你在那里推动了一个Staging版本,如果使用命名空间的选项,你必须花几周的时间建立一个顶级的CI/CD工作流程。在我们这边,我们选择了另一个选项来保持我们的环境分离:我们决定为我们的登台(Staging)和生产环境创建完全自治的集群。这消除了人为错误和安全性故障传播的所有风险,因为两个集群都是完全隔离的。这种方法的缺点是它会增加你的固定成本:你需要更多的计算机来保持两个集群的正常运行。但它带来的安全和安心对我们来说是非常值得的。此外,你可以通过使用GCP的短暂实例来降低成本开销,这比普通实例便宜80%。当然,这有一个问题:如果Google Cloud需要其他客户,那么这些实例可能会随时关闭。但是当我们仅将它们用于我们的临时环境时,丢失一台机器并不会真正影响我们,我们甚至学会了利用它来发挥我们的优势。对我们来说,完美的测试是看看我们的架构如何对我们的一个组件的随机故障作出反应:一种完全不可预测的红队试图摧毁系统,由Google Cloud免费提供给你技巧#4:从一开始就统一并自动化你的工作流程当你开始一个新项目时,你考虑的最后一件事是如何与其他开发者共享代码,或者在需要执行紧急回滚时如何在生产和Staging之间推送构建。这是正常而且非常明智:在你真正构建了可以向世界展示的任何东西之前,没有必要进行过度优化。但另一方面,让这些问题潜伏在永恒中是一个常见的错误。因为你没有时间,需要发布下一个功能,使你的产品最终跨越鸿沟并神奇地带来数百万用户。我对此的建议是花时间尽早创建一个简单有效的工作流程。首先,一旦你开始与其他人合作,你应该退后一步,创建一个统一且易于转移的开发环境。10年前,这不是一件容易的事:你需要在每个人的计算机上配置特殊虚拟机,或者在Mac和Windows用户之间进行修改。这是一场真正的噩梦,并引发了许多不必要的和调试不了的问题。今天,多得了像Docker这样的容器化工具,它可以在不到几天的时间内完成,那么为什么不从一开始就实现呢?这将大大简化所有开发者的生活,并使新员工的入职变得简单直接。对于你将节省的所有调试和设置周数来说,这是一笔非常小的投资。其次,一旦你有生产流量,就应该考虑创建一个简单但有效的QA/CI/CD工作流程。不需要过早设计过度,但我们非常幸运地生活在自动化和CI工具的黄金时代,这使你可以毫无困难地实现自动化的一流CI和CD。符合kubernetes API的CI工具列表很长,例如10.1版GitLab引入了与Kubernetes或Jenkins X的集成。大多数公司为小规模项目提供低成本计划,并为开源项目提供免费计划,所以你真的没有任何借口不使用它们!这不是火箭科学,它将为你节省时间、精力和无数头痛,让你的开发者的生活更轻松!总结一下Kubernetes和云原生提供了出色的技术,可以简化和支持在云上构建可扩展且灵活的解决方案。不久之后,我们将Kubernetes视为云技术中无处不在的一部分,就像我们现在使用Linux和TCP/IP等技术。由于我们成功地迁移到这些服务,我们能够将我们的基础设施持续扩展到世界杯观众及其他人。在历史上规模最大的体育赛事中,我们提供超过1.2 Tbps的流量,零停机时间 - 所有这一切都只有两名后端工程师。我们现在能够处理数百万观众的视频流,峰值每秒有数万个新请求到达。归功我在本文中讨论过的最佳实践,我们不仅能够从架构、成本和资源角度实现我们的短期交付目标,还能实现基础架构的长期可扩展性。总结我们的主要内容:当工具符合实际需要时,请小心谨慎地使用Kubernetes和云原生。今天就想想未来,无论是成本、分离环境还是实施自动化工作流程。从第一天开始就把这些挑战有效地融入你的项目中,当这些考虑成为关键任务时,你将浪费更少的时间资源进行调整。作为一家初创公司,我们一直在努力不断改进我们的技术和工作流程,并且在我们的扩展过程中学到的所有经验教训之后,我们期待着应对下一个挑战:构建多云架构!KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 27, 2019 · 1 min · jiezi

为每个人提供Kubernetes端到端测试

作者:Patrick Ohly(英特尔)越来越多过去是Kubernetes组件的一部分,现在搬到在Kubernetes之外开发。例如,存储驱动程序曾经被编译成Kubernetes二进制文件,然后被转移到主机上的独立Flexvolume二进制文件中,现在作为容器存储接口(Container Storage Interface,CSI)驱动程序提供,这些驱动程序部署在Kubernetes集群内部的pod中。这对于处理此类组件的开发者来说是一个挑战:如何在这样的外部组件上对Kubernetes集群进行端到端(E2E)测试?用于测试Kubernetes本身的E2E框架具有所有必要的功能。但是,尝试在Kubernetes之外使用它很困难,只有通过仔细选择大量依赖项的正确版本才能实现。在Kubernetes 1.13中,E2E测试变得更加简单。这篇博客文章总结了Kubernetes 1.13的变化。对于CSI驱动程序开发者,它将涵盖使存储测试可用于测试第三方CSI驱动程序。如何使用它们将基于两个Intel CSI驱动程序显示:开放式基础架构经理(Open Infrastructure Manager,OIM)PMEM-CSI测试这些驱动程序是大多数这些增强功能的主要动机。E2E概述E2E测试包括几个阶段:实现测试套件。这是本篇博文的主要焦点。Kubernetes E2E框架是用Go编写的。它依赖于Ginkgo来管理测试,而断言(assertion)则依赖于Gomega。这些工具支持“行为驱动开发”,它描述了“规范”中的预期行为。在这篇博客文章中,“test”用于引用个别Ginkgo.It规范。测试使用client-go与Kubernetes集群进行交互。启动测试集群。像kubetest这样的工具可以帮忙。针对该群集运行E2E测试套件。Ginkgo测试套件可以使用ginkgo工具运行,也可以使用go test进行正常的Go测试。没有任何参数,Kubernetes E2E测试套件将基于环境变量(如KUBECONFIG)连接到默认集群,与kubectl完全相同。 Kubetest还知道如何运行Kubernetes E2E套件。Kubernetes 1.13中的E2E框架增强功能所有以下增强都遵循相同的基本模式:它们使E2E框架在Kubernetes之外更有用和更容易使用,而不会改变原始Kubernetes e2e.test二进制文件的行为。拆分供应商支持使用Kubernetes <= 1.12的E2E框架很困难的主要原因是依赖于特定于提供者的SDK,这些SDK使用了大量的软件包。只是编译它已经不简单。许多这些软件包仅在某些测试中需要。例如,测试预配置卷的安装必须首先通过一些非Kubernetes API,直接与特定存储后端通信,以管理员相同的方式配置这样的卷。现在有尝试从核心Kubernetes中删除特定于云供应商的测试。在PR#68483中采用的方法可以看作是朝着这个目标迈出的一步:不是立即剥离代码并打破所有依赖它的测试,所有特定于云供应商的代码都被移动到test/e2e/framework/providers下的可选包中。然后,E2E框架通过每个供应商包单独实现的接口访问它。E2E测试套件的作者决定将哪些软件包导入测试套件。然后通过–provider命令行标志激活供应商支持。1.13和1.14中的Kubernetes e2e.test二进制文件仍然支持与1.12中相同的供应商程序。也可以不包含任何包,这意味着只有通用供应上程序可用:“skeleton”:通过Kubernetes API访问集群,没有别的“local”:跟“skeleton”差不多,但是另外kubernetes/kubernetes/cluster中的脚本可以在运行测试套件后通过ssh检索日志外部文件测试可能必须在运行时读取其他文件,例如.yaml清单。但是Kubernetes e2e.test二进制文件应该是可用的并且完全独立,因为这简化了发布和运行它。Kubernetes构建系统中的解决方案是使用go-bindata将test/e2e/testing-manifests下的所有文件链接到二进制文件中。E2E框架过去对go-bindata的输出有很强的依赖性,现在bindata支持是可选的。通过testfiles包访问文件时,将从不同的源检索文件:相对于使用–repo-root参数指定的目录零个或多个bindata块测试参数e2e.test二进制文件采用控制测试执行的附加参数。2016年,开始尝试用Viper配置文件替换所有E2E命令行参数。但是这种努力停滞不前,这使得开发者没有明确指导他们应该如何处理特定于测试的参数。v1.12中的方法是将所有标志添加到中央test/e2e/framework/test_context.go,这对于独立于框架开发的测试不行。自PR#69105以来,建议使用普通标志包在其自己的源代码中定义其参数。标记名称必须是分层的,点分隔不同的级别,例如my.test.parameter,并且必须是唯一的。标志包强制执行唯一性,第二次注册标志时会发生混乱。新的配置包简化了多个选项的定义,这些选项存储在单个结构中。总而言之,这就是现在如何处理参数:测试包中的init代码定义了测试和参数。实际参数值尚不可用,因此测试定义不能使用它们。测试套件的init代码解析参数和配置文件(可选)。测试运行并可以使用参数值。但是,最近有人指出,比较可取且有可能不将测试设置公开为命令行标志,只能通过配置文件设置它们。关于这个有一个开放的bug和一个待定的PR。Viper支持得到了增强。与供应商支持一样,它是完全可选的。它通过导入viperconfig包被拉入e2e.test二进制文件,并在解析正常的命令行标志后调用它。这已经实现,以便当标志出现在Viper配置文件中时,也可以设置所有可以通过命令行标志设置的变量。例如,Kubernetes v1.13 e2e.test二进制文件接受–viper-config=/tmp/my-config.yaml,该文件将my.test.parameter设置为具有此内容的值:my: test: parameter: value在较旧的Kubernetes版本中,该选项只能从当前目录加载文件,后缀必须省略,实际上只能通过这种方式设置几个参数。请注意Viper的一个限制仍然存在:它通过匹配已知标志的配置文件条目,而不会发出有关未知配置文件条目的警告,从而不会检测到错别字。Kubernetes的更好的配置文件解析器仍在开发中。从.yaml创建项目清单在Kubernetes 1.12中,有一些支持从.yaml文件加载单个项目,但是然后创建该项目必须通过手写代码完成。现在,框架提供新方法加载具有多个项目的.yaml文件、修补这些项目(例如,设置为当前测试创建的命名空间)以及创建它们。这目前用于为每个测试重新部署CSI驱动程序,这些驱动程序来自完全相同的.yaml文件,这些文件也用于通过kubectl进行部署。如果CSI驱动程序支持以不同的名称运行,则测试完全独立并且可以并行运行。但是,重新部署驱动程序会降低测试执行速度,并且不会涵盖针对驱动程序的并发操作。更现实的测试场景是在启动测试集群时部署驱动程序一次,然后针对该部署运行所有测试。最终,Kubernetes E2E测试将转移到该模型,一旦更清楚如何扩展测试集群的启动,包括安装CSI驱动程序等其他实体。Kubernetes 1.14推出的增强功能重用存储测试能够使用Kubernetes之外的框架可以构建自定义测试套件。但是没有测试的测试套件仍然没用。一些现有的测试,特别是用于存储的测试,可以应用于树外组件。感谢Masaki Kimura所做的工作,Kubernetes 1.13中的存储测试被定义为可以针对不同的驱动程序多次实例化它们。但历史有重复的习惯。与供应商程序一样,定义这些测试的程序包也提取了所有树内存储后端的驱动程序定义,这反过来又拉取了比所需更多的附加程序包。这在Kubernetes 1.14进行了修复。跳过不支持的测试某些存储测试依赖于群集的功能(如在支持XFS的主机上运行)或驱动程序(如支持块卷)。在测试运行时检查这些条件,导致在不满意时跳过测试。好的是这记录解释了为什么测试没有运行。开始测试很慢,特别是当它必须首先部署CSI驱动程序时,在其他情况下也差不多。在快速集群上测量为测试创建命名空间的时间为5秒,并且会产生大量噪声测试输出。本来可以解决这个问题,通过跳过不支持的测试的定义,然后报告为什么测试甚至不是测试套件的一部分变得棘手。这种方法已不被考虑,而是采用重新组织存储测试套件的方式,以便在进行更昂贵的测试设置步骤之前首先检查条件。更易读的测试定义同样的PR还将测试重写,接近传统的Ginkgo测试,测试用例及其局部变量在一个函数中。测试外部驱动程序构建自定义E2E测试套件仍然是相当多的工作。将在Kubernetes 1.14测试档案中分发的e2e.test二进制文件将能够测试已安装的存储驱动程序,而无需重建测试套件。有关详细说明,请参阅本自述文件。E2E测试套件HOWTO测试套件初始化第一步是设置定义测试套件的必要样板代码。在Kubernetes E2E中,这是在e2e.go和e2e_test.go文件中完成的。它也可以在e2e_test.go文件中完成。Kubernetes在e2e_test.go中导入所有各种供应商程序、树内测试、Viper配置支持和bindata文件。e2e.go控制实际执行,包括一些集群准备和指标收集。一个更简单的起点是来自PMEM-CSI的e2e_[test].go文件。它不使用任何供应商程序,没有Viper,没有bindata,只导入存储测试。与PMEM-CSI一样,OIM会丢弃所有额外功能,但有点复杂,因为它将自定义集群启动直接集成到测试套件中,在这种情况下非常有用,因为一些额外的组件必须在主机端运行。通过直接在E2E二进制文件中运行它们,使用dlv进行交互式调试变得更加容易。这两个CSI驱动程序都遵循Kubernetes示例,并使用test/e2e目录作为其测试套件,但也可以使用任何其他目录和其他文件名。添加E2E存储测试测试由导入测试套件的包定义。E2E测试唯一特有的是,它们使用framework.NewDefaultFramework实例化一个framework.Framework指针(通常称为f)。此变量在每个测试的BeforeEach中重新初始化,并在AfterEach中释放。它在运行时有一个f.ClientSet和f.Namespace(并且只在运行时!),可以由测试使用。PMEM-CSI存储测试导Kubernetes存储测试套件,并为必须已安装在测试集群中的PMEM-CSI驱动程序设置一个供应测试实例。存储测试套件更改存储类以使用不同的文件系统类型运行测试。由于此要求,存储类是从.yaml文件创建的。解释框架中可用的所有各种实用方法超出了本博文的范围。阅读现有测试和框架的源代码是一个很好的入门方法。提供代码即使消除了许多不必要的依赖关系,提供Kubernetes代码仍然不是一件容易的事。k8s.io/kubernetes并不意味着包含在其他项目中,也没有以dep等工具理解的方式定义其依赖关系。其他k8s.io包应包含在内,但不遵循语义版本控制或不标记任何版本(k8s.io/kube-openapi,k8s.io/utils)。PMEM-CSI使用dep。它的Gopkg.toml文件是一个很好的起点。它启用了修剪(默认情况下未在dep中启用)并将某些项目锁定到与所使用的Kubernetes版本兼容的版本上。当dep没有选择兼容的版本时,检查Kubernetes的Godeps.json有助于确定哪个版本可能是正确的版本。编译并运行测试套件go test ./test/e2e -args -help是测试测试套件编译的最快方法。一旦编译完成并且已经设置了集群,go test -timeout=0 -v ./test/e2e -ginkgo.v命令将运行所有测试。要并行运行测试,请使用ginkgo -p ./test/e2e命令。如何参与Kubernetes E2E框架由测试SIG的testing-commons子项目所有。请参阅该页面以获取联系信息。有各种任务,包括但不限于:将test/e2e/framework移动到staging仓库并重组它以使其更加模块化(#74352)。通过将更多代码移入test/e2e/framework(#74353)来简化e2e.go。从Kubernetes E2E测试套件中删除特定于供应商程序的代码(#70194)。鸣谢特别感谢本文的审阅者:Olev Kartau(https://github.com/okartau)Mary Camp(https://github.com/MCamp859)KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 27, 2019 · 1 min · jiezi

Kubernetes 1.14 正式发布 Windows 节点全新增强

3月26日, Kubernetes1.14版本正式发布,自v1.13 发布仅仅过去了112天,这也是 kubernetes 在2019年的首次发布。此次发布的内容包括:Windows 节点生产级支持、kubectl 更新、持久局部卷 GA。让我们来看一下 v1.14 的发布团队是怎样形容这次发布的:“我们很高兴地宣布发布 Kubernetes 1.14,这是我们2019年的第一个版本! Kubernetes 1.14包含31个增强:10项稳定版功能,12项 beta 测试功能,以及7项全新功能。该版本的主要内容是:可扩展性和支持 Kubernetes上的更多工作负载,其中三项主要功能迁移到通用版本,以及一个重要的安全功能进入测试阶段。”对 Windows 节点的全新增强截至到目前,Kubernetes 中的 Windows 节点支持已经处于测试阶段,许多用户实验并查看了 Windows 容器性能。Kubernetes 现在正式支持将 Windows 节点添加为工作节点并编排 Windows 容器,从而使庞大的 Windows 应用程序生态系统能够利用 Kubernetes 的强大功能。从而提高整个部署的效率,无论你使用的是什么操作系统。具体 Windows 和 kubectl 的增强包括:1.对 Windows 节点的支持逐渐趋于稳定 (#116)支持工作节点和容器可使用 Windows Server 2019。支持与 Azure-CNI、OVN-Kubernetes、Flannel 网络。改进了对 pod、服务类型、工作负载控制器、指标/配额的支持。kubernetes/enhancements [kep]。2.更新的 kubectl 插件机制逐步稳定 (#579)扩展 kubectl,支持添加新命令的扩展以及覆盖特定子命令。3.持久化本地存储管理已经 GA (#121)使本地附加(非网络附加)存储可用作持久卷源。允许用户使用本地存储。kubernetes/kubernetes:#73525 #74391 #747694.进程 ID(PID)正在升级为 beta 版 (#757)防止 pod 耗尽 pid 资源。管理员能够通过默认每个 Pod 的 PID 数量来提供 pod-to-pod PID 隔离。kubernetes/kubernetes:#73651kubernetes/enhancements:[kep]5.Pod 优先级和抢占机制Pod 优先级和抢占机制 Kubernetes 调度程序可以先调度更重要的 Pod,当集群没有资源时,它删除不那么重要的 Pod,为更重要的 Pod 创建空间。重要性由优先级指定。kubernetes/kubernetes:#73498 #74465 #73555 kubernetes/enhancements:#564 [kep]两个已知问题1.在 coredns 1.3.1 有一个已知的问题 coredns/coredns#2629,如果 Kubernetes API 在连接 CoreDNS 时关闭,CoreDNS 将崩溃。这个问题在 CoreDNS 1.4.0 中修复 CoreDNS/CoreDNS#2529。如果现有的安装在 flexvolume 上的 pvc 包含大量目录或目录已满,Kubelet 可能无法重新启动 #75019。Kubernetes的 未来方向Kubernetes 自成立以来一直支持 Linux 操作系统,但在 1.14 版本中,Windows 节点的生产支持现在被标记为稳定的功能。通过 Windows 节点支持,可以使用 Kubernetes 计划和管理 Windows 操作系统容器。Aaron Crickenberger(Google高级测试工程师,此次发布团队领导者)表示,在不同的操作系统和不同的运行时环境中,Windows 支持将有助于更好地阐明 Kubernetes 是什么。在他看来,如果真的希望能够在混合操作系统集群上编排工作负载,那将是非常好的一个结果。未来Crickenberger 预计将从 Kubernetes 核心中提取出更多的可扩展组件,包括存储、CSI、DNI 和容器网络,以及更多的云提供商工作。BoCloud博云一直注重深度参与Kubernetes社区开发工作,确保对kubernetes底层有深度理解,BeyondContainer容器PaaS平台更配备专业的底层开发和维护团队,确保从能力和人力上保证对Kubernetes和Docker的掌控和服务能力。后续博云将持续关注kubernetes技术动态,并将基于kubernetes新功能发布并验证更多用户使用场景,为企业级用户体统稳定、安全、可靠的PaaS服务。参考:https://kubernetes.io/blog/20…https://www.eweek.com/cloud/k...https://thenewstack.io/kubern… ...

March 27, 2019 · 1 min · jiezi

Kubernetes 1.14 正式发布,Windows节点生产级支持!

Kubernetes 1.14现已正式发布,这是Kubernetes在2019年的首次更新!Kubernetes 1.14由31个增强功能组成:10个功能现进入Stable阶段,12个功能进入Beta测试阶段,还有7个全新新增功能。Kubernetes 1.14的主题是“可扩展性”,相较于此前发布的任何Kubernetes版本,此版本拥有最多的进入Stable阶段的增强功能。此次新版的最重大更新无疑为对Windows节点的生产级支持。除此之外还有Kubectl、Persistent Local Volumes、PID限制等等的更新,下文中我们将逐一道来。Windows节点的生产级支持随着Kubernetes 1.14的发布,Kubernetes中的Windows节点支持现已处于Beta测试阶段,用户可以更多地进行实验,进一步体验到“Kubernetes for Windows容器”的价值。Kubernetes现在正式支持将Windows节点添加为工作节点,并可以调度Windows容器。庞大的Windows应用程序生态系统,现在也能够利用Kubernetes平台的强大功能了。同时使用Windows应用程序和Linux应用程序的企业,不必再寻找两种单独的编排方案来分别管理其Windows和Linux工作负载, 整个部署的运营效率都能得到极大提高。此次更新,Kubernetes中的Windows容器支持的主要功能包括:工作节点和容器可以使用Windows Server 2019使用Azure-CNI、OVN-Kubernetes和Flannel支持树外网络连接改进了对pod、服务类型、工作负载控制器和指标/配额的支持,以便与Linux容器提供的功能紧密匹配在Kubernetes Windows网络连接方面,目前支持的Azure-CNI、OVN-Kubernetes和Flannel三种网络插件中,Azure-CNI只能在Azure使用,OVN-Kubernetes需要硬件支持,因而大多数用户都会使用Flannel,Flannel也是社区主推的网络插件。Flannel对Windows的支持是Rancher Labs的工程师Frank Mai实现的,他对Windows网络支持的贡献包含两个方面,一个是对CNI的支持,包括win-bridge和win-overlay,以及meta/flannel的支持;另外一方面是对Flannel的Windows支持。Rancher Labs工程师Frank是Windows Flannel网络的主要贡献者Kubectl 的重要更新全新的Kubectl文档和Logokubectl的文档已经从头开始重写,重点关注于使用声明性Resource Config来管理资源。该文档已以独立书籍格式、作为独立站点发布,其格式为书籍,链接可从k8s.io文档获得:https://kubectl.docs.kubernet…。同时,kubectl拥有了新的徽标和吉祥物(发音为kubee-cuddle):Kustomize集成用户现在可以通过-k标志(例如apply、get等命令)和kustomize子命令,在kubectl中获得kustomize的声明性资源配置创建功能。Kustomize使用Kubernetes原生概念帮助用户创建和重用Resource Config。用户现在可以使用kubectl apply -k dir /将目录与kustomization.yaml一起应用于集群。 用户还可以直接向stdout发出自定义的资源配置,而无需再通过kubectl kustomize dir /才能应用它们。 新功能都可以在文档中进一步查看:https://kubectl.docs.kubernet…kustomize子命令将继续在Kubernetes所拥有的kustomize repo中开发。最新的kustomize功能将以独立的kustomize二进制文件形式(发布到kustomize repo)、以更频繁的节奏进行发布,并将在每次Kubernetes发布之前在kubectl中更新。kubectl插件机制逐迈入Stable状态kubectl插件机制让开发人员可以以独立二进制文件的形式发布自己的自定义kubectl子命令。开发人员可以使用新的更高级的功能和额外的porcelain(例如,添加set-ns命令)来进一步扩展kubectl了。插件必须具有kubectl-名称前缀并存在于用户的$ PATH中。 此次GA,插件机制已经大大简化,并且和git插件系统类似。Persistent Local Volumes现已GAPersistent Local Volumes功能现已迈入Stable状态,用户可以使用本地连接存储来作为持久卷源。持久化本地存储的最主要用例是分布式文件系统和数据库,主要是由于性能和成本的原因 。在云提供商上,本地SSD与远程磁盘相比拥有着更好的性能。在裸机上,除了性能之外,本地存储通常也更便宜,并且使用它是配置分布式文件系统的必要条件。PID限制已迈入Beta阶段进程ID(PID)是Linux主机上的基本资源。在其他资源尚未达到最大限制值的情况下,大多数用户并不希望因为达到任务限制而导致主机不稳定。管理员需要一些机制来确保用户pod不会导致PID耗尽,因为PID耗尽会阻止主机守护进程(如runtime、kubelet等)运行。此外,在pod之间限制PID,以确保它们对节点上的其他工作负载不会造成太大影响,这一点是很重要的。管理员现在可以通过默认每个pod的PID数量来提供pod-to-pod的PID隔离,这一功能已是Beat状态。此外,管理员还可以通过可分配的节点为用户pod保留大量可分配的PID,从而将节点到pod的PID隔离作为alpha功能启用。在Kubernetes的下一个新版本中,该功能有望转为Beta版。其他值得关注的功能更新Pod优先级与抢占机制:这一功能使Kubernetes调度程序能够首先调度更重要的Pod,当集群资源不足时,它会删除不太重要的pod,以便为更重要的Pod创建空间。Pod的重要性由优先级指定。Pod Readiness Gates:为pod的准备就绪提供了外部反馈的扩展点。加强默认的RBAC discovery clusterrolebindings:从API集中移除discovery,现在默认情况下不再允许进行未经身份验证的访问,从而提高CRD的隐私性以及默认集群的默认安全状态。下载使用Kubernetes 1.14Kubernetes 1.14包含的有所功能更新,请查看Release Notes:https://github.com/kubernetes…你可以在GitHub上下载使用全新的Kubernetes 1.14:https://github.com/kubernetes…Rancher作为一个开源的企业级Kubernetes平台,可以统一管理所有云上、所有发行版、所有Kubernetes集群。优化简洁的UI,简单易用的操作体验,同时还拥有集成的CI/CD、监控、日志、RBAC等等增强功能,是企业落地Kubernetes的不二之选。Rancher将在四月发布的Rancher 2.2.1版本将添加对Kubernetes 1.14的支持,敬请期待!后续我们还将分享更多有关Kubernetes 1.14中Windows容器及网络的技术文章,记得保持关注哟

March 27, 2019 · 1 min · jiezi

Kubernetes1.14版本亮点新功能

部分翻译自https://sysdig.com/blog/whats…Kubernetes 1.14的亮点新功能:支持Windows容器服务可以通过kubeadm动态地创建一个高可用集群将kustomize整合进了kubectl为kubectl更新了插件机制说明#116 支持Windows容器服务器(Windows Server Containers)阶段:接近Stable功能组:WindowsSIG-Windows这个提案花了接近3年时间,进入了接近稳定的阶段。当Windows服务器可以作为k8s节点以后,用户可以在Kubernetes容器中运行基于Windows平台的应用了(比如.Net程序等)这也使得Kubernetes成为第一个全功能的跨平台集群管理工具。更详细的说明可以参考这里 #357 Ability to create dynamic HA clusters with kubeadm阶段:Alpha功能组:Cluster Lifecycle要创建一个高可用的Kubernetes集群,有两种方式:etcd节点与控制平面的节点(Master节点)部署在一起额外单独部署etcd节点,不与控制平面的节点(Master节点)混布这个版本的kubeadm提供了在节点间自动拷贝证书的功能。不需要像之前的版本那样,在创建高可用集群的时候还需要手动的在不同节点间去拷贝证书。同时,新解决方案还采用了临时密钥来加强节点间证书传递的安全性。需要了解更多信息可以参考这里#633 Integrate Kustomize into Kubectl阶段:Stable功能组: ClientKubernetes声明式API对象规范是管理工作负载的推荐方法,但是kubectl工具对于这些规范文件(也就是yaml文件)比较难管理,经常要用户自己开发小工具来管理规范文件或生成模板文件。kustomize试图解决上面的问题,上图是一个典型的工作流,示意了kustomize通过deployment和service的配置文件自动创建ConfigMaps或Secrets对象。通过使用kustomize子命令,用户可以使用kustomization.yaml文件来引用配置文件,从这些文件生成配置,并允许用户应用配置转换。 需要了解更多信息可以参考这里以及中文介绍#579 Updated plugin mechanism for kubectl进度:接近Stable功能组:ClientAlpha版本的插件(子命令)功能目前有一些功能限制:插件脚本和可执行文件必须放在预定义好的目录中每个插件都要有原数据文件对于没有一个明确的方式如何去用新的子命令插件去覆盖特定的子命令经过重新设计的插件系统去除了这些限制,使用者只需要在自己的路径中增加插件的可执行路径,就可以通过kubectl执行这些子命令,插件必须具有kubectl- 为命名的前缀,插件的名字描述了插件的目的,例如kubectl-sysdig_capture插件可以通过以下命令调用:kubectl sysdig-capture <pod_name>

March 26, 2019 · 1 min · jiezi

阿里工程师开发了一款免费工具,提升Kubernetes应用开发效率

对于使用了Kubernetes作为应用运行环境的开发者而言,在同一个集群中我们可以使用命名空间(Namespace)快速创建多套隔离环境,在相同命名空间下,服务间使用Service的内部DNS域名进行相互访问。 基于Kubernetes强大的隔离以及服务编排能力,可以实现一套定义编排(YAML)多处部署的能力。不过,一般来说Kubernetes使用的容器网络与开发者的所在的办公网络直接并不能直接连通。 因此,如何高效的利用Kubernetes进行服务间的联调测试,成为在日常开发工作中一道绕不开的坎。本文我们就来聊一聊,如何加速基于Kubernetes的研发效率。使用自动流水线为了能够让开发者能够更快的将修改的代码部署到集群测试环境中,一般来说我们会引入持续交付流水线,将代码的编译,镜像的打包上传以及部署通过自动化的方式来解决。如下所示:从一定程度上来说,这种方式可以避免开发人员进行大量重复性的工作。但是,虽然整个过程自动化了,但是开发人员也不得不每次进行代码变更之后都需要等待流水线的运行。对于开发人员来说,每次代码变更后等待流水线运行或许已经成为整个开发任务过程中体验最糟糕的部分。打破网络限制,本地联调理想状态下是开发者可以直接在本地启动服务,并且这个服务就可以无缝的和远程的kubernetes集群中的各个其它服务实现互相调用。需要解决两个问题:我依赖了其它的服务:运行在本地的代码可以直接通过podIP,clusterIP甚至是Kubernetes集群内的DNS地址访问到部署在集群中的其它应用,如下图左;其它的服务依赖了我:运行在Kubernetes集群中的其它应用可以在不做任何改变的情况下访问我到运行的本地的代码,如下图右。要实现刚才说的两种本地联调方式,主要需要解决以下3个问题:本地网络与Kubernetes集群网络直接的连通问题在本地实现Kubernetes中内部服务的DNS解析;如果将对集群中其它Pod访问的流量转移到本地;云效开发者工具KT为了简化在Kubernetes下进行联调测试的复杂度,云效在SSH隧道网络的基础上并结合Kubernetes特性构建了一款面向开发者的免费辅助工具KT(点击前往下载),如下所示:当本地运行的服务C’希望能够直接访问集群中default命名空间下的Service A和Service B时,运行如下命令:$ ktctl -namespace=defaultKT会自动在集群中部署SSH/DNS代理容器,并构建本地到Kubernetes集群的VPN网络并通过DNS代理实现集群服务DNS域名解析,在运行KT之后,开发者的本地程序可以直接像运行在集群中的服务一样通过service名字调用集群中部署的其它应用:而如果希望集群中的其它Pod(比如图中的PodD和PodE)能够通过ServiceC访问到本地运行的程序C‘,通过如下命令,指定需要替换的目标Deployment以及指定本地服务端口:#-swap-deployment指定需要替换的目标Deployment # -expose 指定本地服务运行的端口 ktctl -swap-deployment c-deployment -expose=8080KT在构建VPN网络的同时,还会自动通过代理容器接管集群原有的PodC实例,并直接转发的本地的8080端口。实现集群应用联调本地。经过上述两个命令,开发者就可以真正的使用云原生的方式来开发调试Kubernetes中的应用了。工作原理下面解析KT的工作原理,如果你已经迫不及待的想尝试KT的功能,可以直接前往下载KT工具。KT主要由两部分组成:在本地运行的命令行工具ktctl运行在集群中的SSH/DNS代理容器。在工作原理上KT实际上是结合Kubernetes自身能力实现的一个基于SSH的VPN网络。这这部分,笔者将详细介绍云效Kubernetes开发者工具KT的工作原理:打通SSH协议通道在Kubernetes命令行工具kubectl中内置的port-forward命令可以帮助用户建立本地端口到Kubernetes集群中特定Pod实例端口间的网络转发。当我们在集群中部署一个包含sshd服务的容器后,通过port-forward可以将容器的SSH服务端口映射到本地:# 将对本地2222端口转发到kt-porxy实例的22端口 $ kubectl port-forward deployments/kt-proxy 2222:22 Forwarding from 127.0.0.1:8080 -> 8080 Forwarding from [::1]:8080 -> 8080在运行端口转发后,就可以直接通过本地的2222端口通过SSH协议进入到Kubernetes集群的kt-proxy实例中。从而打通本地与集群之间的SSH网络链路。本地动态端口转发与VPN在打通SSH网络之后,我们就可以利用SSH通道实现本地到集群的网络请求,其中最基本的方式就是使用SSH动态端口转发的能力。使用如下命令,通过本地2000运行的代理,可以将网络请求通过集群中运行的kt-proxy容器进行转发,从而实现本地到集群网络请求的转发:# ssh -D [本地网卡地址:]本地端口 name@ip -p映射到kt-proxy的22端口的本地端口 ssh -D 2000 root@127.0.0.1 -p2222在启用SSH动态端口转发后,通过设置http_proxy环境变量后,即可直接在命令行中访问集群网络:# export http_proxy=socks5://127.0.0.1:ssh动态端口转发的代理端口 export http_proxy=socks5://127.0.0.1:2000不过原生SSH动态端口转发也有一定的限制那就是无法直接使用UDP协议,这里我们选择了一个替代方案sshuttle. 如下命令所示:# export http_proxy=socks5://127.0.0.1:ssh动态端口转发的代理端口 export http_proxy=socks5://127.0.0.1:2000 sshuttle –dns –to-ns 172.16.1.36 -e ‘ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null’ -r root@127.0.0.1:2222 172.16.1.0/16 172.19.1.0/16 -vvsshuttle工具在SSH协议之上构建了一个简易的VPN网络,同时支持DNS协议转发。因此,接下来的问题就是实现一个自定义的DNS服务即可,而该服务在KT中是直接内置在KT代理镜像中。远程端口转发在本地到集群的链路打通之后。 接下来需要解决的就是从集群到本地的访问链路。这部分,我们会使用到SSH的远程端口转发能力,如下所示,指定所有对kt-proxy的8080端口的网络请求都会通过SSH隧道直接转发到本地的8080端口:# ssh -R 8080:localhost:8080 root@127.0.0.1 -p2222 ssh -R 8080:localhost:8080 root@127.0.0.1 -p2222因此,在KT的实现过程之中,结合Kubernetes基于标签的松耦合能力,我们只需要克隆原有应用实例的YAML描述,并将容器替换为kt-proxy即可。从而将对集群中原有应用的请求通过SSH远程端口转发到本地。综上,通过利用Kubernetes原生能力以及适度的扩展,开发者可以快速在本地利用KT打破本地网络与Kubernetes网络之间的界限,大大提升使用Kubernetes进行联调测试的效率。小结工具承载了对特定问题的解决方案,而工程技术实践则是对其价值的放大。阿里巴巴云效平台,致力于为开发者提供一站式的企业研发与协作服务,并将阿里多年的软件工程实践以一种更加开发的形态反馈技术社区,欢迎更多的技术开发者入驻。目前,Mac用户可以前往下载并体验KT工具作者:郑云龙,阿里巴巴研发效能部高级研发工程师本文作者:云效鼓励师阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 26, 2019 · 1 min · jiezi

开源如何加速NFV转型

作者:Pam Baker迎接即将举行的ONS(开放网络峰会),我们与Red Hat的NFV技术总监Thomas Nadeau讨论了开源在电信服务供应商创新中的角色。Red Hat以开源文化和商业模式而闻名,不仅仅是开发软件的一种方式,而且它的“开源作为创新之路”在很多层面产生共鸣。迎接即将召开的ONS(开放网络峰会),我们与Red Hat技术总监Thomas Nadeau交谈 - 他在去年的活动中发表了主题演讲 - 听取他对开源在电信服务供应商创新中的角色的看法。开源在这个行业得到广泛接受的一个原因是,他说,一些非常成功的项目已经变得太大,任何一家公司都无法管理,或者单枪匹马地将其边界推向其他创新突破。“像Kubernetes这样的项目,现在对任何一家公司来说都太大了。我们作为一个行业需要努力的技术,因为没有一家公司可以单独推动它。“Nadeau说。“展望未来,要解决这些真正难以解决的问题,我们需要开源和开源软件开发模式。”以下是关于开源如何以及在何处对电信公司产生创新影响的更多见解。Linux.com:为什么开源一般来说是电信服务供应商的创新核心?Nadeau:第一个原因是服务供应商可以更好地掌控自己的命运。有些服务供应商比其他服务供应商更积极参与。其次,开源使服务供应商不必长时间等待他们需要开发的功能。第三,开放源代码使服务供应商不必费力地使用和管理单体系统,而他们真正想要的只是一些功能。幸运的是,网络设备供应商正在应对这种过度杀伤问题。它们变得更加灵活、更加模块化,而开源是实现这一目标的最佳方式。Linux.com:在你的ONS主题演讲中,你说开源提供传统运营商在创建数字服务和收入流方面与云规模公司竞争的对等环境。请解释开源如何帮助。Nadeau:这又跟Kubernetes有关。另一个是OpenStack。这些是这些企业真正需要的工具,不仅仅是扩展,而是存在于当今的市场中。如果没有虚拟化领域的开源,你就会陷入专有的单体,无法控制你的未来,并且需要等待很长时间才能获得竞争所需的功能。NFV方程中有两部分:基础设施和应用程序。NFV不仅仅是底层平台,而是平台和使用平台的应用程序之间的持续推动和拉动。NFV实际上是功能的虚拟化。它始于单体虚拟机(VM)。然后是“分解的虚拟机”,由于各种原因,各个功能以更分散的方式运行。这样做意味着将它们分开,这就是SDN进入的地方,控制平面与数据平面分离。这些概念也推动了底层平台的变化,从而大大增加了开销。这反过来又引起了对容器环境的兴趣,作为一种潜在的解决方案,但它仍然是NFV。你可以将其视为具有复合应用程序的SOA的最新版本。Kubernetes是Google使用的那种SOA模型,它消除了对复杂网络和存储的担忧,并且允许用户启动起作用的应用程序。对于企业应用程序模型,这很有用。但不是在NFV的情况下。在NFV案例中,在OpenStack平台的上一次迭代中,每个人都享受一对一的网络性能。但是当我们将它移到OpenShift时,由于他们已经实现了最新的SOA模型,我们又回到了原点,在那里你失去了80%的性能。所以现在进化的底层平台的重要性越来越高,所以钟摆摆动,但它仍然是NFV。开源允许你有效、快速地适应这些变化和影响。因此,创新快速而逻辑地发生,他们的迭代也是如此。Linux.com:告诉我们NFV中的底层Linux,以及为什么这个组合如此强大。Nadeau:Linux是开源的,它始终处于开源的一些最纯粹的意义。另一个原因是它是底层操作系统的主要选择。现实情况是,所有主要网络和所有顶级网络公司都在其所有高性能平台上运行Linux作为基本操作系统。现在它都是非常灵活。你可以将它放在Raspberry Pi上,或者放在价值数百万美元的巨大路由器上。它安全、灵活且可扩展,因此操作员现在可以真正将其用作工具。Linux.com:运营商一直在努力重新定义自己。事实上,许多正在积极寻求方法,摆脱严格防御以对抗破坏者,以及在他们是破坏者时采取进攻。网络功能虚拟化(NFV)如何帮助其中一种策略或两种策略?Nadeau:Telstra和Bell Canada就是很好的例子。他们使用开源代码与他们围绕该代码的合作伙伴生态系统协同工作,这使他们能够以与过去不同的方式做事。今天他们做了两件不同的事情。一个是他们设计自己的网络。他们在很多方面设计自己的东西,相对于以前他们可能需要使用来自供应商的整体解决方案,而这些解决方案跟竞争对手的业务看起来差不多一样。这些电信公司正在采取真正的“深入,卷起袖子”的方法,他们在更深入的层面上知道他们使用了什么,可以与下游的发行商或供应商合作。这可以追溯到生态系统,它类似于我们在Red Hat的合作伙伴计划,是填补空白的胶水,完善给电信公司设想的网络解决方案。在4月3日至5日在圣何塞麦克内里会议中心举行的ONS(Open Networking Summit,开放网络峰会)上了解更多信息。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 26, 2019 · 1 min · jiezi

Kubernetes 1.14:Windows节点的生产级支持、Kubectl更新、持久本地卷GA

作者:1.14发布团队我们很高兴地宣布推出Kubernetes 1.14,这是我们2019年的首次发布!Kubernetes 1.14由31个增强功能组成:10个移动到稳定、12个在测试版、7个新增。此版本的主题是可扩展性,并支持Kubernetes上更多工作负载,其中三个主要功能转向一般可用,以及一个重要的安全功能转向beta。与之前发布的任何Kubernetes相比,此版本有更多功能转向稳定。对用户和运营而言是重要里程碑,设定支持期望。此外,此版本还有值得注意的Pod和RBAC增强功能,将在下面的“其他值得注意的功能”部分中讨论。让我们深入了解此版本的主要功能:Windows节点的生产级支持到目前为止,Kubernetes中的Windows节点支持处于测试阶段,允许许多用户进行实验并查看Kubernetes给Windows容器的价值。Kubernetes现在正式支持将Windows节点添加为工作节点,以及编排Windows容器,从而使庞大的Windows应用程序生态系统能够利用我们平台的强大功能。投资基于Windows的应用程序和基于Linux的应用程序的企业,不必寻找单独的协调器来管理其工作负载,从而提高整个部署的运营效率,无论操作系统如何。在Kubernetes中启用Windows容器的一些主要功能包括:支持Windows Server 2019的工作站节点和容器支持Azure-CNI、OVN-Kubernetes和Flannel的树外网络连接改进了对pod、服务类型、工作负载控制器和指标/配额的支持,以便与Linux容器提供的功能紧密匹配值得注意的Kubectl更新新的Kubectl文档和徽标kubectl的文档已经从头开始重写,重点是使用声明性资源配置来管理资源。该文档已作为独立站点发布,其格式为书籍,从k8s.io文档链接(可从 https://kubectl.docs.kubernet… 获取)。新的kubectl徽标和吉祥物(发音为kubee-cuddle)显示在新的docs站点徽标上。Kustomize Integrationkustomize的声明性Resource Config创建功能现在可以通过-k标志在kubectl中获得(例如,对于apply、get等命令)和kustomize子命令。Kustomize使用Kubernetes原生概念帮助用户创建和重用Resource Config。用户现在可以使用kubectl apply -k dir/将目录内的kustomization.yaml一起应用于集群。用户还可以通过kubectl kustomize dir/,向stdout发出自定义的资源配置,而无应用它们。新功能记录在 https://kubectl.docs.kubernet… 的新文档中。kustomize子命令将继续在Kubernetes拥有的kustomize repo中开发。最新的kustomize功能将以独立的kustomize二进制文件(发布到kustomize repo)以频繁的发布节奏提供,并将在每次Kubernetes发布之前在kubectl中更新。kubectl插件机制转向稳定kubectl插件机制允许开发者以独立二进制文件的形式发布自己的自定义kubectl子命令。这可以用于扩展具有新的更高级功能的kubectl和附加的porcelain(例如,添加set-ns命令)。插件必须具有kubectl-命名前缀并存在于用户的$PATH中。插件机制在GA已经大大简化,并且类似于git插件系统。持久本地卷现在是GA此功转向稳定,使本地连接存储可用作持久卷源。分布式文件系统和数据库,由于性能和成本,是持久性本地存储的主要用例。在云供应商上,本地SSD提供比远程磁盘更好的性能。在裸机上,除了性能之外,本地存储通常更便宜,并且使用它是配置分布式文件系统的必要条件。PID限制转向Beta进程ID(PID)是Linux主机上的基本资源。在不遇到任何其他资源限制的情况下,达到任务限制并导致主机不稳定是会发生的。管理员需要一些机制来确保用户pod不会导致PID耗尽,从而阻止主机守护程序(运行时、kubelet等)运行。此外,确保在pod之间限制PID以确保它们对节点上的其他工作负载的影响有限是很重要的。作为beta功能,管理员可以通过将每个Pod的PID数量设定默认值,以提供pod-to-pod PID隔离。此外,作为alpha功能,管理员可以通过节点可分配的方式,为用户pod保留大量可分配的PID,从而启用节点到pod的PID隔离。该社区希望在下一版本中将此功能转为测试版。其他值得注意的功能Pod优先级和抢占使Kubernetes调度程序能够首先调度更重要的Pod,当集群资源不足时,它会删除不太重要的pod,以便为更重要的Pod创建空间。重要性由优先级指定。Pod Readiness Gates为pod准备就绪提供了外部反馈的扩展点。加强默认RBAC发现clusterrolebindings会从API集中删除发现,默认情况下允许进行未经身份验证的访问,从而提高CRD的隐私性,以及默认群集的默认安全状态。下载安装Kubernetes 1.14可从GitHub下载。开始使用Kubernetes,请查看这些互动式教程。你也可以使用kubeadm轻松安装1.14。功能博客系列如果你有兴趣更深入地探索这些功能,请查看下周我们的5天Kubernetes系列,其中我们将重点介绍以下的详细功能:第1天 - Windows Server容器第2天 - 加强默认的RBAC发现clusterrolebindings第3天 - 在Kubernetes的Pod优先级和抢占第4天 - PID限制第5天 - 持久本地卷发布团队通过数百名提供技术和非技术内容的个人的努力,这一发布成为可能。特别感谢Google高级测试工程师Aaron Crickenberger领导的发布团队。发布团队中的43个人协调了发布的许多方面,从文档到测试,验证和功能完整性。随着Kubernetes社区的发展,我们的发布过程代表了开源软件开发协作的一个惊人演示。Kubernetes继续迅速获得新用户。这种增长创造了一个积极的反馈循环,让更多的贡献者提交代码创建一个更有活力的生态。迄今为止,Kubernetes拥有超过28,000名个人贡献者,以及超过57,000人的活跃社区。项目速度CNCF继续完善DevStats,这是一个雄心勃勃的项目,可视化项目中的无数贡献。K8s DevStats说明了主要公司贡献者的贡献细分,以及一系列令人印象深刻的预配置报告,包括从个人贡献者到拉取请求生命周期时间的所有内容。在过去一年中,平均每月有381家不同的公司和超过2,458名个人为Kubernetes贡献。查看DevStats,了解有关Kubernetes项目和社区整体速度的更多信息。用户亮点全球性组织正在生产环境大规模使用Kubernetes。最近发布的社区用户故事包括:网易移至Kubernetes将其研发效率提高了100%以上,部署效率提高了280%。VSCO发现转向持续集成、容器化和Kubernetes,速度显着提高。从典型服务的代码完成到生产部署的时间从1-2周减少到2-4小时。NAV转向Kubernetes使公司节省了50%的基础设施成本,部署从每天10个增加到每天50个,资源利用率从1%增加到40%。Kubernetes能帮助你的团队吗?与社区分享你的故事。生态系统近况Kubernetes将通过CNCF参加GSoC 2019。在CNCF的GitHub页面上查看2019年项目创意的完整列表。CNCF 2018年度报告回顾了Kubernetes的发展和基础、社区参与、生态系统工具、测试一致性项目、KubeCon等。在KubeCon + CloudNativeCon北美2018年的8,000名与会者中,73%是首次参与的KubeCon-ers,突出了Kubernetes和云原生技术的巨大增长和新兴趣。会议透明度报告。KubeCon + CloudNativeCon世界上最大的Kubernetes聚会,KubeCon + CloudNativeCon将于2019年5月20日至23日来到巴塞罗那以及2019年6月24日至26日来到上海(与开源峰会共同举办)。这些会议将包括技术会议、案例研究、开发者深入了解,沙龙等等!立即注册!网络研讨会太平洋世界4月23日上午10点,加入Kubernetes 1.14发布团队,了解该版本的主要功能。在这里注册。参与其中参与Kubernetes的最简单方法是加入符合你兴趣的众多特殊兴趣小组(SIG)之一。你有什么想要向Kubernetes社区广播的吗?在我们的每周社区会议上,通过以下渠道分享你的声音。感谢你的持续反馈和支持。在Stack Overflow上发布问题(或回答问题)加入有关讨论的社区讨论在Twitter @Kubernetesio上关注我们以获取最新更新加入社区Slack分享你的Kubernetes故事KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 26, 2019 · 1 min · jiezi

京东云Kubernetes集群最佳实践

京东云Kubernetes集群最佳实践容器是Cloud Native的基石,它们之间的关系不言而喻。了解容器对于学习Cloud Native也是十分重要的。近期,京东云Cloud Native的“在线公开课”从理论和实践两个层面为大家分享了Cloud Native相关的技术知识。在本周的周日,我们还将迎来”Cloud Native时代的应用之路与开源创新“专场技术沙龙。因此我们今天的文章将会和大家分享关于京东云Kubernetes集群的部分最佳实践。感兴趣的小伙伴也可以跟着文档自己动手进行创建。京东云Kubernetes集群采用管理节点全托管的方式,为用户提供简单易用、高可靠、功能强大的容器管理服务。该产品完全兼容标准Kubernetes API ,集成京东云网络、存储等插件。Kubernetes集群服务简化了Kubernetes部署、管理,降低了Kubernetes使用门槛,增强应用的可靠性,提升开发的效率,同时,也能更好地帮助用户减少资源投入的成本。最佳实践——部署应用部署持久化存储京东云Kubernetes集群服务集成了京东云云硬盘,您可以在集群中使用京东云云硬盘作为持久化存储;使用京东云云盘定义静态存储1. 创建PVkind: PersistentVolumeapiVersion: v1metadata: name: pv-static labels: type: jdcloud-ebsspec: capacity: storage: 30Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain jdcloudElasticBlockStore: volumeID: vol-ogcbkdjg7x fsType: xfs参数说明:1、如您需要在京东云Kubernetes集群服务中使用京东云云硬盘作为持久化存储,请在PersistentVolume定义时,指定插件jdcloudElasticBlockStore;2、VolumeID:指定同地域下为Kubernetes集群服务提供持久化存储的云硬盘ID;3、Fstype:指定文件系统类型;目前仅支持ext4和xfs两种;4、Capacity:PV 将具有特定的存储容量。这是使用 PV 的容量属性设置的;5、PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。京东云云硬盘目前只支持一种模式ReadWriteOnce——该卷可以被单个节点以读/写模式挂载;访问模式包括:ReadWriteOnce——该卷可以被单个节点以读/写模式挂载在命令行中,访问模式缩写为:RWO - ReadWriteOnce京东云为PersistentVolume提供了插件,插件类型为:jdcloudElasticBlockStore注:由于云硬盘限制一个云硬盘只能同时挂载一个云主机,在使用基于PVC的Pod时,建议使用replicas=1来创建一个部署集。StatefulSet可解决多副本问题。Pod迁移,PVC迁移(卸载旧实例/挂载新实例)默认35秒。通过Deployment部署,删除Deployment之后,可重新挂载原有PVC到新的Pod里面。2. 创建PVC声明可以指定一个标签选择器来进一步过滤该组卷。只有标签与选择器匹配的卷可以绑定到声明。选择器由两个字段组成:所有来自 MatchLabels 和 MatchExpressions 的要求都被“与”在一起——它们必须全部满足才能匹配。本例使用MatchLabels作为过滤条件,将匹配的PersistentVolume绑定到Persistent Volume Claim。MatchLabels:Volume 必须有具有该值的标签matchExpressions:这是一个要求列表,通过指定关键字,值列表以及与关键字和值相关的运算符组成。有效的运算符包括 In、NotIn、Exists 和 DoesNotExist。访问模式包括:ReadWriteOnce——该卷可以被单个节点以读/写模式挂载。在命令行中,访问模式缩写为:RWO - ReadWriteOnce京东云为Persistent Volume提供了插件,插件类型为:jdcloudElasticBlockStore注:副本数只能指定1。apiVersion: v1kind: PersistentVolumeClaimmetadata: name: pv-static-pvcspec: accessModes: - ReadWriteOnce storageClassName: "" resources: requests: storage: 30Gi selector: matchLabels: type: jdcloud-ebs创建Podkind: Pod apiVersion: v1 metadata: name: pod-static spec: volumes: - name: pv-static persistentVolumeClaim: claimName: pv-static-pvc containers: - name: busybox-static image: busybox command: - sleep - “600” imagePullPolicy: Always volumeMounts: - mountPath: “/usr/share/mybusybox/” name: pv-static使用京东云云盘定义动态存储当集群中的静态 PV 都不匹配新建的 Persistent Volume Claim 时,集群可能会尝试动态地为 PVC 创建卷。关于京东云云硬盘规格:创建PVCapiVersion: v1kind: PersistentVolumeClaimmetadata: name: pvc1spec: accessModes: - ReadWriteOnce storageClassName: jdcloud-ssd resources: requests: storage: 20Gi查看集群的PVCkubectl get pvc输出NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEpvc1 Bound pvc-73d8538b-ebd6-11e8-a857-fa163eeab14b 20Gi RWO jdcloud-ssd 18s查看集群的PVkubectl get pv输出NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpvc-73d8538b-ebd6-11e8-a857-fa163eeab14b 20Gi RWO Delete Bound default/pvc1 jdcloud-ssd 2m基于Storage Class jdcloud-ssd,为PVC创建了卷。一旦 PV 和 PVC 绑定后,Persistent Volume Claim 绑定是排他性的,不管它们是如何绑定的。 PVC 跟 PV 绑定是一对一的映射。2 部署ServiceKubernetes ServiceKubernetes Service定义了这样一种抽象:一个 Pod 的逻辑分组,一种可以访问它们的策略-通常称为微服务。这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector(查看下面了解,为什么可能需要没有 Selector 的 Service)实现的。一个 Service 在 Kubernetes 中是一个REST对象,和Pod类似.像所有的 REST 对象一样, Service 定义可以基于 POST 方式,请求 API Server 创建新的实例。京东云Kubernetes集成负载均衡服务,支持创建Load Balance类型的Service,为应用提供安全、可靠的网络。创建的负载均衡会占用本地域的负载均衡配额,需要保证有足够配额。1、创建支持Load Balance类型的Service,命名为myservice.yaml文件定义如下:kind: ServiceapiVersion: v1metadata: name: servicetest labels: run: myappspec: ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 30062 type: LoadBalancer selector: run: myapp2、执行Kubectl创建命令,创建一个Service;其中使用相应的YAML文件名称替换:kubectl create -f myservice.yaml3、创建一组Nginx Pod,mynginx.yaml文件定义如下:apiVersion: apps/v1beta1kind: Deploymentmetadata: name: my-nginxspec: selector: matchLabels: run: myapp replicas: 2 template: metadata: labels: run: myapp spec: containers: - name: my-nginx image: nginx ports: - containerPort: 804、执行Kubectl创建命令,创建一个Deployment;其中使用相应的YAML文件名称替换kubectl create -f mynginx.yaml5、查看已创建成功的Deployment,执行以下命令:kubectl get pods -l run=myapp -o wide返回结果如下:NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEmy-nginx 2 2 2 2 4m6、查看相应的Pod运行状态,kubectl get pods -l run=myapp -o wide返回结果如下:NAME READY STATUS RESTARTS AGE IP NODEmy-nginx-864b5bfdc7-6297s 1/1 Running 0 23m 172.16.0.10 k8s-node-vmtwjb-0vy9nuo0ymmy-nginx-864b5bfdc7-lr7gq 1/1 Running 0 23m 172.16.0.42 k8s-node-vm25q1-0vy9nuo0ym7、查看Service详情:kubectl describe service servicetest可以查看绑定到Service的Endpoints:Name: servicetestNamespace: defaultLabels: run=myappAnnotations: <none>Selector: run=myappType: LoadBalancerIP: 172.16.61.58LoadBalancer Ingress: 114.67.227.25Port: <unset> 80/TCPTargetPort: 80/TCPNodePort: <unset> 30062/TCPEndpoints: 172.16.0.10:80,172.16.0.42:80Session Affinity: NoneExternal Traffic Policy: ClusterEvents: Type Reason Age From Message —- —— —- —- ——- Normal EnsuringLoadBalancer 11m (x9 over 26m) service-controller Ensuring load balancer Normal EnsuredLoadBalancer 10m service-controller Ensured load balancer注:Load Balancer Ingress:114.67.227.25为外部公网IP8、执行如下命令查询绑定到service的enpoints列表:kubectl get ep servicetest返回NAME ENDPOINTS AGEservicetest 172.16.0.10:80,172.16.0.42:80 28m9、在浏览器中输入与Service关联的Load Balance公网IP及端口,看到如下页面,即表明Nginx服务正常。·END· ...

March 25, 2019 · 2 min · jiezi

SAP:开源的最佳秘密之一

作者:Pam BakerSAP已经成立了一个开源计划办公室,以进一步开展开源活动,并扩大与开源社区的合作。SAP几十年来一直致力于开源,现在已经成立了一个开源计划办公室(Open Source Program Office,OSPO),以进一步正式协调开源活动,并扩大其与开源社区的合作。“SAP是首批正式定义开源消费和贡献流程的行业参与者之一。”开源计划办公室主任Peter Giese说。即便如此,许多人还不认为SAP是一家拥抱开源参与和贡献的公司。“在过去,我们可能没有积极地分享我们的开源活动。”Giese说。现在,SAP关注其在开源领域的工作。透明度是新开源任务的重要组成部分,首先要解释公司的最新动态以及开源方式。SAP如何采用开源“1998年,SAP开始将我们市场领先的ERP系统R/3系统移植到Linux上。”Giese说。“这是在企业软件市场建立Linux的一个重要里程碑。”将系统移植到Linux只是第一步,也是成功的一步。行动引发了内部讨论,并探讨了如何以及在何处采用Linux。“我们得出结论,Linux将成为主流。”Giese说。“今天看这是很明显,但当时对每个人来说并不那么明显。那是我们开始致力于开源的时候。”2001年,SAP正式定义,并内部记录了其开源消费流程,该公司并且对内承诺使用开源项目来构建SAP产品。有许多细节需要注意,例如开源许可、安全性和出口控制限制。到2004年,SAP已经获得了与其他公司交换规范的信息,并且是Eclipse Foundation的创始成员之一。从那时起,SAP开发者积极参与了几个Eclipse项目,包括JGit、EGit、Mat、Tycho和Che。但是直到2008年,SAP才开始在全公司范围内积极推动SAP员工的开源贡献。这也是该公司推出其对外开源流程的一年。“我们有一套指导方针和规则,用于SAP团队与开源社区分享他们的工作所必须做的事情。”Giese解释道。2010年,SAP进一步将开源工具集成到其开发流程中。“通过引入系统化的开源代码扫描作为我们标准开发流程的一部分,我们提高了合规水平。”Giese说。“这意味着我们开始系统地扫描开源代码,以了解许可证合规性和安全性问题。”2014年,SAP与开源社区共享了一个名为CLA助手的工具,该工具是为管理开源贡献者许可协议而开发的。尽管这些活动和项目非常成功,对SAP的开源活动越来越需要更多的集中协调。“我们有几个团队负责开源的特定方面,例如安全扫描、许可证扫描和构建我们自己的开源工具。但是,没有专门的职能或角色来对SAP的所有开源负责。“Giese说。“现在已经发生了变化,SAP的首席技术官负责SAP的开源。”SAP和开源的现况新的中央开源计划办公室成立于2018年初。“我们希望在与外部客户和合作伙伴,以及开源基金会和其他开源社区的互动中更加积极和明显。”Giese说。“这就是我们去年加入TODO Group分享经验,共同开发最佳实践,以及共同工具的原因。”Giese指出,该公司对开源的投资和贡献是巨大的,但它们仍然让许多人感到惊讶。“例如,在2018年2月,来自Adobe的Fil Maj,根据在GitHub上积极参与开源项目的员工总数,公布了全球公司排名,SAP排名第七。”Giese说。“当然,有不同的方法来创建这样的统计数据,但它让你了解SAP作为贡献者的角色。也许我们是开源的最佳秘密之一。”SAP不再是一个秘密,而是以更明显的方式加强其开源参与。“我们将参加更多的开源社区会议,例如开源峰会、OSCON、FOSDEM、EclipseCon、KubeCon等等。”Giese说。SAP以更明显的方式参与是其持续致力于开源卓越的标志,该公司旨在形成更多的合作伙伴关系并促进加速创新。最近SAP的创新开源项目的一个例子是Gardener,这是一种针对Kubernetes集群即服务的解决方案,如CNCF云原生景观中所列。它支持管理大量Kubernetes集群,并在其核心架构中重用Kubernetes原生功能。另一个新开源的SAP项目是Kyma,这是一种在云原生世界中,连接和扩展企业应用程序的灵活而简单的方法。SAP积极鼓励公司和其他开发者在Gardener和Kyma等项目上进行代码开发和合作。“对我而言,这种共同创新是整个开源运动最引人注目的方面。”Giese说。SAP的开源办公室是如何运作SAP成立了一个虚拟团队,由来自不同领域的多个团队组成。“我们以scrum模式工作,这是一种软件开发方法。它在推动开源计划办公室方面具有优势。”OSPO首席开发架构师Michael Picht说。“你在scrum的冲刺(sprint)中工作,这意味着你被迫将你的任务分解成更小的部分。”“scrum方法传播跨职能团队,这就是我们的OSPO。我们有来自公司各地的同事。Scrum促进了这种设置的工作。有些人听到我们在scrum模式下工作时听起来很奇怪,但在我们的案例中,它运作得很好。”Picht表示,“将大型工作分成较小的块,并进行为期四周的冲刺,这使得挑战性和长期运行的任务更容易掌握。但是,它确实需要一些培训,以确保所有团队成员对该方法感到合适。”该办公室的使命是培养和支持在SAP内部和外部使用开源方法进行软件开发。因此,对于希望在公司环境之外的业余时间为开源项目做出贡献的员工,SAP大大简化了流程。“我们提供了一些简单的规则,只要你遵守这些规则,你就可以在业余时间直接开始开源项目的工作。”Giese说。该公司还在重新设计企业开源贡献流程,以提高效率。目标是从监管开发者转向通过简单的表单、流程步骤的自动化和团队服务来支持他们。对于开源社区,为了推进开源最佳实践和工具,SAP最近贡献了它的开源漏洞评估工具,该工具支持任何软件开发组织评估其应用程序开发中的开源组件的安全漏洞。SAP的开源计划办公室将继续寻找加速和改进流程的方法,并支持开发者、合作伙伴和开源社区。“这将永远不会结束,永远持续下去,所以我们总是希望找到进一步改进开源流程和工具的新方法。”Picht说。鸣谢我们要感谢SAP开源计划办公室主任Peter Giese和首席开发架构师Michael Picht对本案例研究的贡献。我们还要感谢Pam Baker花时间在开源计划办公室进行访谈。SAP是Linux基金会和LF项目的积极成员,包括Cloud Foundry Foundation、Cloud Native Computing Foundation(CNCF)、Hyperledger、ODPi、OpenAPI Initiative和TODO Group。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 25, 2019 · 1 min · jiezi

Kubernetes准入控制器指南

作者:Malte Isberner(StackRox)Kubernetes极大地提高了当今生产中后端群集的速度和可管理性。由于其灵活性、可扩展性和易用性,Kubernetes已成为容器编排器的事实标准。Kubernetes也提供一系列保护生产工作负载的功能。安全功能的最新引入是一组称为“准入控制器”的插件。必须启用准入控制器才能使用Kubernetes的一些更高级的安全功能,例如,在整个命名空间中强制实施安全配置基线的pod安全政策。以下必须知道的提示和技巧,将帮助你利用准入控制器,在Kubernetes中充分利用这些安全功能。什么是Kubernetes准入控制器?简而言之,Kubernetes准入控制器是管理和强制执行集群使用方式的插件。可以将它们视为拦截(经过身份验证的)API请求的网守,并且可以更改请求对象,或完全拒绝请求。准入控制过程有两个阶段:首先执行改变(mutating)阶段,然后是验证(validating)阶段。因此,准入控制器可以充当改变或验证控制器,或两者的组合。例如,LimitRanger准入控制器可以使用默认资源请求和限制(改变阶段)扩充pod,并验证具有设置资源要求的pod,不超过LimitRange对象中指定的每命名空间限制(验证阶段)。准入控制器阶段值得注意的是,许多用户认为是内置的Kubernetes操作的某些方面,实际上由准入控制器管理。例如,当删除命名空间并随后进入Terminating状态时,NamespaceLifecycle准入控制器将阻止在此命名空间中创建任何新对象。在Kubernetes附带的30多个准入控制器中,有两个因其几乎无限的灵活性而发挥特殊作用 - ValidatingAdmissionWebhooks和MutatingAdmissionWebhooks,两者在Kubernetes 1.13都处于beta状态。我们将仔细研究这两个准入控制器,因为它们本身并没有实现任何政策决策逻辑。相反,相应的操作是从集群内运行的服务的REST端点(webhook)获得的。这种方法将准入控制器逻辑与Kubernetes API服务器分离,从而允许用户在Kubernetes集群中创建、更新或删除资源时实现自定义逻辑。两种准入控制器webhooks之间的差异几乎是不言自明的:改变(mutating)准入webhooks可能会改变对象,而验证(validating)准入webhooks则不会。然而,即使是改变准入webhook也可以拒绝请求,从而以验证的方式行事。验证入场webhooks比改变webhooks有两个主要优点:首先,出于安全原因,可能需要禁用MutatingAdmissionWebhook准入控制器(或对谁可能创建MutatingWebhookConfiguration对象应用更严格的RBAC限制),因为它可能会产生混淆,甚至危险的副作用。其次,如上图所示,验证准入控制器(以及webhooks)在改变控制器之后运行。因此,验证webhook看到的任何请求对象都是将持久保存到etcd的最终版本。通过将标志传递给Kubernetes API服务器来配置启用的准入控制器集。请注意,旧的-admission-control标志在1.10中已弃用,并替换为-enable-admission-plugins。–enable-admission-plugins=ValidatingAdmissionWebhook,MutatingAdmissionWebhookKubernetes建议默认启用以下准入控制器。–enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota,PodSecurityPolicy可以在Kubernetes官方参考中找到完整的准入控制器列表及其说明。本讨论将仅关注基于webhook的准入控制器。为什么我需要准入控制器?安全性:准入控制器可以通过在整个命名空间或集群中,强制使用合理的安全基准来提高安全性。内置的PodSecurityPolicy准入控制器可能是最突出的例子;例如,它可以用于禁止容器以root身份运行,或者确保容器的根文件系统始终以只读方式挂载。可通过基于webhook的自定义准入控制器实现的其他用例包括:允许仅从企业已知的特定仓库中提取镜像,同时拒绝未知的镜像仓库。拒绝不符合安全标准的部署。例如,使用特权(privileged)标志的容器可以规避许多安全检查。基于webhook的准入控制器可以减轻此风险,该准入控制器拒绝此类部署(验证)或覆盖特权(privileged)标志,将其设置为false。治理:准入控制器允许你强制遵守某些做法,例如具有良好的标签、注释、资源限制或其他设置。一些常见的场景包括:对不同对象强制执行标签验证,以确保将正确的标签用于各种对象,例如分配给团队或项目的每个对象,或指定应用程序标签的每个部署。自动向对象添加注释,例如为“dev”部署资源分配正确的成本中心。配置管理:准入控制器允许你验证群集中运行对象的配置,并防止群集中任何明显的错误配置。准入控制器可用于检测和修复没有语义标签的部署镜像,例如:自动添加资源限制或验证资源限制,确保合理的标签被添加到pod,或确保生产部署中使用的镜像引用不使用最新的(latest)标记或带有-dev后缀的标记。通过这种方式,准入控制器和政策管理有助于确保应用程序在不断变化的控制环境中保持合规。示例:编写和部署准入控制器Webhook为了说明如何利用准入控制器webhook来建立自定义安全政策,让我们考虑一个解决Kubernetes缺点之一的例子:它的许多默认值都经过优化,易于使用并减少摩擦,有时以牺牲安全性为代价。其中一个设置是默认允许容器以root身份运行(并且,如果没有进一步的配置,Dockerfile中也没有USER指令,也会这样)。尽管容器在一定程度上与底层主机隔离,但以root身份运行容器确实会增加部署的风险级别 - 作为许多安全性最佳实践之一,这应该避免。例如,最近暴露的runC漏洞(CVE-2019-5736)只有在容器以root身份运行时才能被利用。你可以使用自定义改变准入控制器webhook来应用更安全的默认值:除非明确请求,否则我们的webhook将确保pod作为非root用户运行(如果未进行明确分配,我们将分配用户ID 1234)。请注意,此设置不会阻止你在群集中部署任何工作负载,包括那些合法需要以root身份运行的工作负载。它只要求你在部署配置中,明确启用此风险程序操作模式,而对所有其他工作负载默认为非root模式。完整的代码以及部署说明可以在我们随附的GitHub存储库中找到。在这里,我们将重点介绍webhook如何工作的一些更微妙的方面。改变(Mutating)Webhook配置通过在Kubernetes中创建MutatingWebhookConfiguration对象来定义改变准入控制器webhook。在我们的示例中,我们使用以下配置:apiVersion: admissionregistration.k8s.io/v1beta1kind: MutatingWebhookConfigurationmetadata: name: demo-webhookwebhooks: - name: webhook-server.webhook-demo.svc clientConfig: service: name: webhook-server namespace: webhook-demo path: “/mutate” caBundle: ${CA_PEM_B64} rules: - operations: [ “CREATE” ] apiGroups: [""] apiVersions: [“v1”] resources: [“pods”]此配置定义webhook webhook-server.webhook-demo.svc,并指示Kubernetes API服务器在通过向/mutate URL发出HTTP POST请求创建pod时,在命名空间webhook-demo中查询服务webhook-server。要使此配置生效,必须满足几个先决条件。Webhook REST APIKubernetes API服务器向给定服务和URL路径发出HTTPS POST请求,并在请求正文中使用JSON编码的AdmissionReview(设置了Request字段)。响应应该是JSON编码的AdmissionReview,这次设置了Response字段。我们的演示存储库包含一个处理序列化/反序列化样板代码的函数,并允许你专注于实现在Kubernetes API对象上运行的逻辑。在我们的示例中,实现准入控制器逻辑的函数称为applySecurityDefaults,在/mutate URL下提供此功能的HTTPS服务器可以设置如下:mux := http.NewServeMux()mux.Handle("/mutate", admitFuncHandler(applySecurityDefaults))server := &http.Server{ Addr: “:8443”, Handler: mux,}log.Fatal(server.ListenAndServeTLS(certPath, keyPath))请注意,要使服务器在没有提升权限的情况下运行,我们让HTTP服务器侦听端口8443。Kubernetes不允许在webhook配置中指定端口;它始终采用HTTPS端口443。但是,由于无论如何都需要服务对象,我们可以轻松地将服务的端口443映射到容器上的端口8443:apiVersion: v1kind: Servicemetadata: name: webhook-server namespace: webhook-demospec: selector: app: webhook-server # specified by the deployment/pod ports: - port: 443 targetPort: webhook-api # name of port 8443 of the container对象修改逻辑在改变准入控制器webhook中,通过JSON补丁执行改变。虽然JSON补丁标准包含许多复杂性,远远超出了本讨论的范围,但我们的示例中的Go数据结构,及其用法应该为用户提供有关JSON补丁如何工作的良好初步概述:type patchOperation struct { Op string json:"op" Path string json:"path" Value interface{} json:"value,omitempty"}要将pod的字段.spec.securityContext.runAsNonRoot设置为true,我们构造以下patchOperation对象:patches = append(patches, patchOperation{ Op: “add”, Path: “/spec/securityContext/runAsNonRoot”, Value: true,})TLS证书由于必须通过HTTPS提供webhook,因此我们需要适当的服务器证书。这些证书可以是自签名的(由自签名CA签名),但我们需要Kubernetes在与webhook服务器通信时指示相应的CA证书。此外,证书的公用名(CN)必须与Kubernetes API服务器使用的服务器名称匹配,内部服务的名称是<service-name>.<namespace>.svc,在我们的案例中即webhook-server.webhook-demo.svc。由于自签名TLS证书的生成在Internet上有详细记录,因此我们只需在示例中引用相应的shell脚本。之前显示的webhook配置包含占位符${CA_PEM_B64}。在我们创建此配置之前,我们需要将此部分替换为CA的Base64编码的PEM证书。openssl base64 -A命令可用于此目的。测试Webhook在部署webhook服务器并对其进行配置之后(可以通过从存储库调用./deploy.sh脚本来完成),现在是时候测试并验证webhook是否确实完成它的工作。存储库包含三个示例:未指定安全上下文的pod(pod-with-defaults)。我们希望此pod以非root身份运行,用户ID为1234。一个指定安全上下文的pod,明确允许它以root身份运行(pod-with-override)。具有冲突配置的pod,指定它必须以非root用户身份运行,但用户ID为0(pod-with-conflict)。为了展示拒绝对象创建请求,我们增加了我们的准入控制器逻辑,以拒绝这些明显的错误配置。通过运行kubectl create -f examples/<name>.yaml创建其中一个pod。在前两个示例中,你可以通过检查日志来验证pod运行的用户ID,例如:$ kubectl create -f examples/pod-with-defaults.yaml$ kubectl logs pod-with-defaultsI am running as user 1234在第三个示例中,应该拒绝对象创建并提供适当的错误消息:$ kubectl create -f examples/pod-with-conflict.yamlError from server (InternalError): error when creating “examples/pod-with-conflict.yaml”: Internal error occurred: admission webhook “webhook-server.webhook-demo.svc” denied the request: runAsNonRoot specified, but runAsUser set to 0 (the root user)你也可以使用自己的工作负载进行测试。当然,你还可以通过更改webhook的逻辑,并查看更改如何影响对象创建来进一步实验。有关如何进行此类更改实验的更多信息,请参阅存储库的自述文件。摘要Kubernetes准入控制器为安全性提供了显着优势。深入研究两个功能强大的示例,并附带可用的代码,将帮助你开始利用这些强大的功能。参考文档:https://kubernetes.io/docs/re…https://docs.okd.io/latest/ar...https://kubernetes.io/blog/20...https://medium.com/ibm-cloud/...https://github.com/kubernetes...https://github.com/istio/istiohttps://www.stackrox.com/post...KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 25, 2019 · 1 min · jiezi

CNCF案例研究:Nav

一家初创公司如何通过Kubernetes将其基础设施成本降低50%公司:Nav地点:犹他州盐湖城和加利福尼亚州圣马特奥工业:为企业提供金融服务挑战Nav成立于2012年,为小型企业提供三个主要商业信用局 - Equifax、Experian和Dun&Bradstreet - 的商业信用评分,以及最符合他们需求的融资方案。五年后,该创业公司发展迅速,“我们的云环境变得越来越大,我们对这些环境的使用率极低,例如低于1%。”工程总监Travis Jeppson说。“我们希望我们对云环境的使用与我们实际需要的内容更紧密地结合在一起,因此我们开始关注容器化和编排,以帮助我们能够运行彼此不同,但可以共享类似资源池的工作负载。”解决方法在评估了许多编排解决方案后,Nav团队决定采用在AWS上运行的Kubernetes。Kubernetes周围社区的实力强大,以及Google的出身。此外,“其他解决方案往往相当笨重、非常复杂、非常庞大,而且很难立即管理。”Jeppson说。“Kubernetes为我们提供了一种非常简单的方法,可以作为符合我们当前需求的编排解决方案,而且它的可扩展性使我们能够在未来增长并能够构建更多特性和功能。”影响这个由四人组成的团队在六个月内完成了Kubernetes的启动和运行,Nav的25个微服务的完全迁移在另外六个月内完成。结果令人印象深刻:首先使公司走上了这条道路的资源利用率,从1%增加到40%。推出一项新服务过去需要两个开发者两周;现在只需一个开发者不到10分钟。部署增加了5倍。该公司节省了50%的基础设施成本。“Kubernetes为我们提供了一种非常简单的方法,可以作为符合我们当前需求的编排解决方案,而且它的可扩展性使我们能够在未来增长并能够构建更多特性和功能。” - TRAVIS JEPPSON,工程总监,NAVNav成立于2012年,为小企业提供三个主要商业信用局 - Equifax、Experian和Dun&Bradstreet - 的商业信用评分,以及最适合他们需求的企业财务健康和融资方案的详细信息。工程总监Travis Jeppson表示,其使命归结为,“提高小企业的成功率。”几年前,Nav认识到自己走向成功的障碍。业务发展迅速,“我们的云环境变得越来越大,我们对这些环境的使用率非常低,比如低于1%。”Jeppson说。“大多数问题都与扩展能力有关。我们只是在砸钱。‘让我们启动更多的服务器。让我们做更多的事情来处理增加的负担。‘而我们是一家创业公司,这可能会导致我们的死亡。我们没有钱在那种东西上烧。”此外,每项新服务都必须经过10个不同的人,这需要两周时间才能完成。“所有的补丁管理和服务器管理都是非常手动完成的,因此我们都必须观察,并保持良好状态。”Jeppson补充道。“这只是一个非常麻烦的系统。”“社区绝对至关重要:能够传递各种想法,谈论我们所面临的许多类似挑战,并获得帮助。我喜欢我们能够出于不同的原因解决同样的问题,但在此过程中互相帮助。” - TRAVIS JEPPSON,工程总监,NAVJeppson曾在以前的工作中使用容器,并将该技术推荐给Nav的管理层,作为解决这些问题的方法。他在2017年初获得了绿灯。“我们希望我们对云环境的使用与我们实际需要的更加紧密结合,因此我们开始关注容器化和编排,以帮助我们运行彼此不同的工作负载,但可以分享类似的资源库。”他说。在评估了许多业务流程解决方案后,该公司决定采用在AWS上运行的Kubernetes。Kubernetes周围社区的力量强大,加上起源自谷歌。此外,“其他解决方案往往相当笨重、非常复杂、非常庞大,而且真的难以管理。”Jeppson说。“Kubernetes为我们提供了一种非常简单的方法,可以作为一个符合我们当前需求的编排解决方案,但它的可扩展性也可以让我们随之增长,并在以后构建更多特性和功能。”Jeppson的四人工程服务团队在六个月内完成并运行了Kubernetes(他们决定使用Kubespray来启动集群),Nav的25个微服务和一个主要的单体在另外六个月内完成完全迁移。“我们无法重写一切;我们无法停机。”他说。“我们必须不停运行,我们必须保持可用,我们必须有最少的停机时间。因此,我们对构建管道、度量标准和日志记录非常满意,然后围绕Kubernetes本身:如何启动它、如何升级它、如何为它提供服务。我们一点一点地移动。”“Kubernetes通过允许我们以前从未有过的所有这些新自由为Nav带来了如此多的价值。” - TRAVIS JEPPSON,工程总监,NAV该过程的一个关键部分包括培训Nav的50名工程师,并对新工作流程以及迁移路线图保持透明。Jeppson在整个过程中定期进行演示,并为整个工程师团队提供一周每天四小时的实验室。然后他在GitLab中创建了一个存储库来存放所有信息。“我们展示了所有前端和后端开发者如何进入,使用kubectl自己创建自己的命名空间。”他说。“现在,很多时候,他们只是来找我们说,‘这已经准备就绪。‘我们点击GitLab中的一个小按钮,让它进入生产阶段,就完成了。”自从迁移工作于2018年初完成以来,结果令人印象深刻:首先使公司走上了这条道路的资源利用率,从1%增加到40%。推出一项新服务过去需要两个开发者两周;现在只需一个开发者不到10分钟。部署增加了5倍,从每天10个增加到每天50个。该公司在计算方面节省了50%的基础设施成本。“接下来我们想进入数据库方面,一旦我们这样做,那么我们将继续降低成本。”Jeppson说。Kubernetes还帮助Nav满足其合规需求。之前,“我们必须将一个应用程序映射到一个服务器,主要是由于数据的合规性规定不同。”Jeppson说。“使用Kubernetes API,我们可以添加网络政策,隔离该数据并在需要时对其进行限制。”该公司将其群集隔离到一个不受限制的区域和一个限制区域,该区域有自己的一组节点,用于数据保护。该公司还使用Twistlock工具确保安全性。“这使夜间睡眠变得更加容易。”他补充道。“我们现在处理的流量是四到十倍,而且就像’哦,是的。我们很好。Kubernetes为我们处理这个问题。’” - TRAVIS JEPPSON,工程总监,NAV随着Kubernetes的到位,Nav团队也开始采用Prometheus来改进系统的指标和日志记录。“Prometheus制定了一个关于衡量标准的标准,这对开发者来说非常容易采用。”Jeppson说。“他们可以自由地展示他们想要的东西,做他们需要的东西,并保持他们的代码库清洁,这对我们来说绝对是必须的。”Nav来年接下来的是:查看跟踪、存储和服务网格。他们在KubeCon花了很多时间与其他公司交谈之后,目前正在评估Envoy、OpenTracing和Jaeger。“社区绝对至关重要:能够传递各种想法,谈论我们所面临的许多类似挑战,并获得帮助。我喜欢我们能够出于不同的原因解决同样的问题,但在此过程中互相帮助。”Jeppson说。“还有很多要做的事情,关于可扩展性,围绕能够真正完全采用云原生解决方案。”当然,这一切都始于Kubernetes。凭借这项技术,Jeppson的团队已经建立了一个平台允许Nav扩展,并“通过允许我们以前从未有过的所有这些新自由为Nav带来了如此多的价值。”他说。关于新产品的讨论,过去常常陷入困境,因为他们必须等待六个月才能建立一个隔离环境,然后找出如何处理流量高峰。“但现在对我们来说没什么。”Jeppson说。“我们现在处理的流量是四到十倍,而且就像’哦,是的。我们很好。Kubernetes为我们处理这个问题。’”KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 25, 2019 · 1 min · jiezi

重温2018上海Kubernetes贡献者峰会

作者: Josh Berkus (红帽), Yang Li (The Plant), Puja Abbassi (Giant Swarm), XiangPeng Zhao (中兴通讯)KubeCon 上海站新贡献者峰会与会者,摄影:Jerry Zhang最近,在中国的首次 KubeCon 上,我们完成了在中国的首次新贡献者峰会。看到所有中国和亚洲的开发者(以及来自世界各地的一些人)有兴趣成为贡献者,这令人非常兴奋。在长达一天的课程中,他们了解了如何、为什么以及在何处为 Kubernetes 作出贡献,创建了 PR,参加了贡献者圆桌讨论,并签署了他们的 CLA。这是我们的第二届新贡献者工作坊(NCW),它由前一次贡献者体验 SIG 成员创建和领导的哥本哈根研讨会延伸而来。根据受众情况,本次活动采用了中英文两种语言,充分利用了 CNCF 赞助的一流的同声传译服务。同样,NCW 团队由社区成员组成,既有说英语的,也有说汉语的:Yang Li、XiangPeng Zhao、Puja Abbassi、Noah Abrahams、Tim Pepper、Zach Corleissen、Sen Lu 和 Josh Berkus。除了演讲和帮助学员外,团队的双语成员还将所有幻灯片翻译成了中文。共有五十一名学员参加。Noah Abrahams 讲解 Kubernetes 沟通渠道。摄影:Jerry ZhangNCW 让参与者完成了为 Kubernetes 作出贡献的各个阶段,从决定在哪里作出贡献开始,接着介绍了 SIG 系统和我们的代码仓库结构。我们还有来自文档和测试基础设施领域的「客座讲者」,他们负责讲解有关的贡献。最后,我们在创建 issue、提交并批准 PR 的实践练习后,结束了工作坊。这些实践练习使用一个名为贡献者游乐场的代码仓库,由贡献者体验 SIG 创建,让新贡献者尝试在一个 Kubernetes 仓库中执行各种操作。它修改了 Prow 和 Tide 自动化,使用与真实代码仓库类似的 Owners 文件。这可以让学员了解为我们的仓库做出贡献的有关机制,同时又不妨碍正常的开发流程。Yang Li 讲到如何让你的 PR 通过评审。摄影:Josh Berkus「防火长城」和语言障碍都使得在中国为 Kubernetes 作出贡献变得困难。而且,中国的开源商业模式并不成熟,员工在开源项目上工作的时间有限。中国工程师渴望参与 Kubernetes 的研发,但他们中的许多人不知道从何处开始,因为 Kubernetes 是一个如此庞大的项目。通过本次工作坊,我们希望帮助那些想要参与贡献的人,不论他们希望修复他们遇到的一些错误、改进或本地化文档,或者他们需要在工作中用到 Kubernetes。我们很高兴看到越来越多的中国贡献者在过去几年里加入社区,我们也希望将来可以看到更多。「我已经参与了 Kubernetes 社区大约三年」,XiangPeng Zhao 说,「在社区,我注意到越来越多的中国开发者表现出对 Kubernetes 贡献的兴趣。但是,开始为这样一个项目做贡献并不容易。我尽力帮助那些我在社区遇到的人,但是,我认为可能仍有一些新的贡献者离开社区,因为他们在遇到麻烦时不知道从哪里获得帮助。幸运的是,社区在 KubeCon 哥本哈根站发起了 NCW,并在 KubeCon 上海站举办了第二届。我很高兴受到 Josh Berkus 的邀请,帮助组织这个工作坊。在工作坊期间,我当面见到了社区里的朋友,在练习中指导了与会者,等等。所有这些对我来说都是难忘的经历。作为有着多年贡献者经验的我,也学习到了很多。我希望几年前我开始为 Kubernetes 做贡献时参加过这样的工作坊」。贡献者圆桌讨论。摄影:Jerry Zhang工作坊以现有贡献者圆桌讨论结束,嘉宾包括 Lucas Käldström、Janet Kuo、Da Ma、Pengfei Ni、Zefeng Wang 和 Chao Xu。这场圆桌讨论旨在让新的和现有的贡献者了解一些最活跃的贡献者和维护者的幕后日常工作,不论他们来自中国还是世界各地。嘉宾们讨论了从哪里开始贡献者的旅程,以及如何与评审者和维护者进行互动。他们进一步探讨了在中国参与贡献的主要问题,并向与会者预告了在 Kubernetes 的未来版本中可以期待的令人兴奋的功能。工作坊结束后,XiangPeng Zhao 和一些与会者就他们的经历在微信和 Twitter 上进行了交谈。他们很高兴参加了 NCW,并就改进工作坊提出了一些建议。一位名叫 Mohammad 的与会者说:「我在工作坊上玩得很开心,学习了参与 k8s 贡献的整个过程。」另一位与会者 Jie Jia 说:「工作坊非常精彩。它系统地解释了如何为 Kubernetes 做出贡献。即使参与者之前对此一无所知,他(她)也可以理解这个过程。对于那些已经是贡献者的人,他们也可以学习到新东西。此外,我还可以在工作坊上结识来自国内外的新朋友。真是棒极了!」贡献者体验 SIG 将继续在未来的 KubeCon 上举办新贡献者工作坊,包括西雅图站、巴塞罗那站,然后在 2019 年六月回到上海。如果你今年未能参加,请在未来的 KubeCon 上注册。并且,如果你遇到工作坊的与会者,请务必欢迎他们加入社区。材料链接:中文版幻灯片:PDF英文版幻灯片:PDFKubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 25, 2019 · 1 min · jiezi

KubeEdge,一个Kubernetes原生边缘计算框架

作者:Sanil Kumar D(华为),Jun Du(华为)KubeEdge成为第一个Kubernetes原生边缘计算平台,Edge和云组件现已开源!开源边缘计算正在经历其业界最具活力的发展阶段。如此多的开源平台,如此多的整合以及如此多的标准化举措!这显示了构建更好平台的强大动力,以便将云计算带到边缘以满足不断增长的需求。去年宣布的KubeEdge现在为云原生计算带来了好消息!它提供了基于Kubernetes的完整边缘计算解决方案,具有独立的云和边缘核心模块。目前,云端和边缘模块都是开源的。与可用的某些轻量级kubernetes平台不同,KubeEdge旨在构建扩展云的边缘计算解决方案。控制平面位于云中,可伸缩扩展。同时,边缘可以在离线模式下工作。它也是轻量级和容器化的,并且可以支持边缘的异构硬件。通过优化边缘资源,KubeEdge可以为边缘解决方案节省大量设置和运营成本。这使它成为目前世界上最引人注目的边缘计算平台,基于Kubernetes!Kube(rnetes)Edge! - 为边缘计算开辟一个新的基于Kubernetes的生态系统KubeEdge的主要目标是将Kubernetes生态系统从云端扩展到边缘。从2018年11月在上海KubeCon公布的时候开始,KubeEdge的架构方向与Kubernetes一致,正如它的名字!它从v0.1开始,提供基本的边缘计算功能。现在,凭借其最新版本v0.2,它将云组件连接并完成循环。凭借基于Kubernetes的一致且可扩展的界面,KubeEdge支持边缘集群的编排和管理,类似于Kubernetes在云中的管理方式。这为将云计算功能快速有效地提升到边缘提供了无缝可能性。基于其路线图和架构,KubeEdge尝试支持所有边缘节点、应用程序、设备甚至是与Kubernetes接口一致的集群管理。这将有助于边缘云的行为与云集群完全相同。这可以为基于KubeEdge的边缘云开发部署节省大量时间和成本。KubeEdge提供了一个容器化的边缘计算平台,具有固有的可扩展性。由于它是模块化和优化的,因此它重量轻(66MB足迹和~30MB运行内存),可以部署在资源不多的设备上。类似地,边缘节点可以具有不同的硬件架构并且具有不同的硬件配置。对于设备连接,它可以支持多种协议,并使用基于标准MQTT的通信。这有助于有效地使用新节点和设备扩展边缘集群。你没听错!KubeEdge云核心模块是开源的!通过开放边缘和云模块,KubeEdge带来了一个完整的云供应商中立的轻量级异构边缘计算平台。现在它已准备好支持为边缘计算构建一个完整的Kubernetes生态系统,而且利用大多数现有的云原生项目或软件模块。这可以使边缘的迷你云支持要求苛刻的用例,如数据分析、视频分析机器学习等。KubeEdge架构:构建Kubernetes原生边缘计算!KubeEdge的核心架构原则是构建与Kubernetes一致的接口,无论是在云端还是边缘端。Edged:管理Edge的容器化应用程序。EdgeHub:Edge的通信接口模块。它是一个Web套接字客户端,负责与Cloud Service进行边缘计算交互。CloudHub:云端的通信接口模块。一个Web套接字服务器,负责监视云端的更改、缓存并向EdgeHub发送消息。EdgeController:管理Edge节点。它是一个扩展的Kubernetes控制器,用于管理边缘节点和pod元数据,以便将数据定位到特定的边缘节点。EventBus:使用MQTT处理内部边缘通信。它是与MQTT服务器(mosquitto)交互的MQTT客户端,为其他组件提供发布和订阅功能。DeviceTwin:它是处理设备元数据的设备的软件镜像。此模块有助于处理设备状态并将其同步到云。它还为应用程序提供查询接口,因为它与轻量级数据库(SQLite)接口。MetaManager:它管理边缘节点的元数据。这是edged和edgehub之间的消息处理器。它还负责向轻量级数据库(SQLite)存储/检索元数据。即使你希望基于体系结构优化和改进(例如增强的安全性)添加更多控制平面模块,它也很简单,因为它在这些模块中使用一致的注册和模块化通信。KubeEdge提供可扩展的轻量级Kubernetes原生边缘计算平台,可以在离线模式下工作。它有助于简化边缘应用程序开发和部署。云供应商中立,可以在任何计算节点上运行云核心模块。发布0.1到0.2 - 改变游戏规则!KubeEdge v0.1于2018年12月底发布,具有非常基本的边缘功能,可以管理边缘应用程序以及节点、pod、配置等的Kubernetes API。在大约2个月内,KubeEdge v0.2于2019年3月5日发布。此版本提供了云核心模块,并支持端到端的开源边缘计算解决方案。云核心模块可以署到从任何云供应商或本地部的任何计算节点。现在,可以轻松安装和测试完整的边缘解决方案,包括在笔记本电脑上。随处运行 - 简单而轻盈如上所述,可以轻松部署KubeEdge Edge和Cloud核心组件,并可以运行用户应用程序。边缘核心有66MB的脚印,只需要30MB的内存就可以运行。同样,云核可以在任何云节点上运行。(用户也可以通过在笔记本电脑上运行它来体验)安装很简单,只需几步即可完成:设置先决条件Docker、KubernetesMQTT和openssl克隆并构建KubeEdge云和边缘运行云运行边缘KubeEdge/kubeedge提供每个步骤的详细步骤未来:通过胜任的功能和社区协作起飞KubeEdge由社区成员开发,他们是Kubernetes/CNCF的积极贡献者,并从事边缘计算研究。KubeEdge团队还积极与Kubernetes IOT/EDGE WORKING GROUP合作。在KubeEdge宣布的几个月内,它吸引了来自不同组织的成员,包括京东、浙江大学、SEL实验室、Eclipse、中国移动、ARM、英特尔共同构建平台和生态系统。KubeEdge为其即将于2019年发布的主要版本提供了清晰的路线图。v1.0旨在通过标准的边缘到边缘通信提供完整的边缘集群和设备管理解决方案,而v2.0的目标是拥有边缘的服务网格、功能服务、数据分析等高级功能。此外,对于所有功能,KubeEdge架构将尝试利用现有的CNCF项目/软件。KubeEdge社区需要不同的组织,他们的需求、用例和支持来构建它。请加入制作kubernetes原生边缘计算平台,该平台可将云原生计算范例扩展到边缘云。如何参与?我们欢迎更多合作来构建Kubernetes原生边缘计算生态系统。请加入我们!Twitter:https://twitter.com/kubeedgeSlack:https://kubeedge.slack.com/网站:https://kubeedge.ioGitHub:https://github.com/kubeedge/k…电子邮件:kubeedge@gmail.comKubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 20, 2019 · 1 min · jiezi

Kubernetes Ingress 日志分析与监控的最佳实践

摘要: Ingress主要提供HTTP层(7层)路由功能,是目前K8s中HTTP/HTTPS服务的主流暴露方式。为简化广大用户对于Ingress日志分析与监控的门槛,阿里云容器服务和日志服务将Ingress日志打通,只需要应用一个yaml资源即可完成日志采集、分析、可视化等一整套Ingress日志方案的部署。前言目前Kubernetes(K8s)已经真正地占领了容器编排市场,是默认的云无关计算抽象,越来越多的企业开始将服务构建在K8s集群上。在K8s中,组件通过Service对外暴露服务,常见的包括NodePort、LoadBalancer、Ingress等。其中Ingress主要提供HTTP层(7层)路由功能,相比TCP(4层)的负载均衡具备非常多的优势(路由规则更加灵活、支持金丝雀、蓝绿、A/B Test发布模式、SSL支持、日志、监控、支持自定义扩展等),是目前K8s中HTTP/HTTPS服务的主流暴露方式。Ingress简介K8s中Ingress只是一种API资源的声明,具体的实现需要安装对应的Ingress Controller,由Ingress Controller接管Ingress定义,将流量转发到对应的Service。目前Ingress Controller的实现有非常多种(具体可以参考Ingress Controller官方文档),比较流行的有Nginx、Traefik、Istio、Kong等,在国内接受度最高的是Nginx Ingress Controller。日志与监控日志和监控是所有Ingress Controller都会提供的基础功能,日志一般包括访问日志(Access Log)、控制日志(Controller Log)和错误日志(Error Log),监控主要从日志以及Controller中提取部分Metric信息。这些数据中访问日志的量级最大、信息最多、价值也最高,一般7层的访问日志包括:URL、源IP、UserAgent、状态码、入流量、出流量、响应时间等,对于Ingress Controller这种转发型的日志,还包括转发的Service名、Service响应时间等额外信息。从这些信息中,我们能够分析出非常多的信息,例如:网站访问的PV、UV;访问的地域分布、设备端分布;网站访问的错误比例;后端服务的响应延迟;不同URL访问分布。我们的开发、运维、运营、安全等人员可以基于这些信息完成各自的需求,例如:新老版本发布前后的数据指标对比;网站质量监控、集群状态监控;恶意攻击检测、反作弊;网站访问量统计、广告转化率统计。然而手动搭建、运维一整套的Ingress日志分析与监控系统非常复杂,系统所需要的模块有:部署日志采集Agent并配置采集、解析规则;由于K8s集群中,访问量相对较大,因此需要搭建一个缓冲队列,例如Redis、Kafka等;部署实时数据分析引擎,例如Elastic Search、clickhouse等;部署可视化组件并搭建报表,例如grafana、kibana等;部署告警模块并配置告警规则,例如ElastAlert、alertmanager等。阿里云日志服务Ingress解决方案为简化广大用户对于Ingress日志分析与监控的门槛,阿里云容器服务和日志服务将Ingress日志打通(官方文档),只需要应用一个yaml资源即可完成日志采集、分析、可视化等一整套Ingress日志方案的部署。Ingress可视化分析日志服务默认为Ingress创建5个报表,分别是:Ingress概览、Ingress访问中心、Ingress监控中心、Ingress蓝绿发布监控中心、Ingress异常检测中心。不同角色的人员可根据需求使用不同的报表,同时每个报表均提供筛选框用于筛选特定的Service、URL、状态码等。所有的报表均基于日志服务提供的基础可视化组件实现,可根据公司实际场景进行定制化调整。Ingress概览Ingress概览报表主要展示当前Ingress的整体状态,主要包括以下几类信息:整体架构状态(1天),包括:PV、UV、流量、响应延迟、移动端占比、错误比例等;网站实时状态(1分钟),包括:PV、UV、成功率、5XX比例、平均延迟、P95/P99延迟等;用户请求类信息(1天),包括:1天/7天访问PV对比、访问地域分布、TOP访问省份/城市、移动端占比、Android/IOS占比等;TOPURL统计(1小时),包括:访问TOP10、延迟TOP10、5XX错误TOP10、404错误TOP10。Ingress访问中心Ingress访问中心主要侧重于用于访问请求相关的统计信息,一般用于运营分析,包括:当日UV/PV、UV/PV分布、UV/PV趋势、TOP访问省份/城市、TOP访问浏览器、TOP访问IP、移动端占比、Android/IOS占比等。Ingress监控中心Ingress监控中心主要侧重于网站实时监控数据,一般用于实时监控与告警,包括:请求成功率、错误比例、5XX比例、请求未转发比例、平均延迟、P95/P99/P9999延迟、状态码分布、Ingress压力分布、Service访问TOP10、Service错误TOP10、Service延迟TOP10、Service流量TOP10等。Ingress蓝绿发布监控中心Ingress蓝绿发布监控中心主要用于版本发布时的实时监控与对比(版本前后对比以及蓝绿版本当前对比),以便在服务发布时快速检测异常并进行回滚。在该报表中需要选择进行对比的蓝绿版本(ServiceA和ServiceB),报表将根据选择动态显示蓝绿版本相关指标,包括:PV、5XX比例、成功率、平均延迟、P95/P99/P9999延迟、流量等。Ingress异常检测中心Ingress异常检测中心基于日志服务提供的机器学习算法,通过多种时序分析算法从Ingress的指标中自动检测异常点,提高问题发现的效率。实时监控与告警Ingress作为K8s网站请求的主要入口,实时监控与告警是必不可少的Ops手段之一。在日志服务上,基于上述的报表,只需3个简单的步骤即可完成告警的创建。下述示例为Ingress配置5XX比例的告警,告警每5分钟执行一次,当5XX比例超过1%时触发。除了通用的告警功能外,日志服务还额外支持:多维度数据关联,即通过多组SQL结果交叉判断进行告警,增加告警准确度;除支持短信、语音、通知中心、email外,还支持钉钉机器人通知、自定义WebHook扩展;告警的记录也以日志的形式记录,可以实现对告警失败进行告警的双保险。订阅报告日志服务除支持通过告警方式通知外,还支持报表订阅功能,可使用该功能将报表定期渲染成图片并通过邮件、钉钉群等方式发送。例如每天早上10点向运营群中发送昨日网站访问情况、每周发送报告到邮件组中存档、新版本发布时每5分钟发送一次监控报表…自定义分析如果容器服务Kubernetes版提供的默认报表无法满足你的分析需求,可以直接使用日志服务SQL、仪表盘等功能进行自定义的分析和可视化。尝鲜为了让大家可以体验Kubernetes审计日志功能,我们特别开通了体验中心,大家可以通过 https://promotion.aliyun.com/ntms/act/logdoclist.html 进入,该页面提供了非常多和Kubernetes相关的报表。参考文档阿里云日志服务阿里云容器服务Kubernetes版Ingress日志分析与监控告警配置订阅报表Ingress官方文档Ingress Controller官方文档一站式开发者服务,海量学习资源0元起!阿里热门开源项目、机器学习干货、开发者课程/工具、小微项目、移动研发等海量资源;更有开发者福利Kindle、技术图书幸运抽奖,100%中–》https://www.aliyun.com/acts/product-section-2019/developer?utm_content=g_1000047140本文作者:元乙阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 19, 2019 · 1 min · jiezi

与CNCF一起分享K8s博客文章或案例研究

CNCF和Kubernetes网站不时发布来之全世界的博客文章和案例研究。近期的博客文章有:使用Ansible和Vagrant设置KubernetesKubernetes v1.13对原始块卷支持转移到beta使用OperatorHub.io自动化群集上的操作为Envoy v2构建Kubernetes Edge(Ingress)控制平面Runc和CVE-2019-5736国内案例研究有:CNCF案例研究:网易CNCF案例研究:蚂蚁金服CNCF案例研究:京东CNCF案例研究:PingCAPCNCF案例研究:奇虎360我们邀请你与CNCF一起向全世界同好分享你的K8s博客文章或关于你的案例研究。写博客文章任何人都可以撰写博客文章并提交以供审核。博客文章不应具有商业性质,应包含广泛适用于Kubernetes社区的内容。要提交博客文章,你可以使用Kubernetes博客提交表,也可以按照以下步骤操作。如果尚未签署,请签署CLA。查看网站存储库中现有博客帖子的Markdown格式。在你喜欢的文本编辑器中写下你的博客文章。在步骤2的同一链接上,单击“Create new file”按钮。将你的内容粘贴到编辑器中。将文件命名为与博客文章的建议标题相匹配,但不要将日期放在文件名中。博客评论员将与你一起确定最终文件名和博客发布日期。保存文件时,Github将引导你完成拉取请求过程。博客评审员将审核你的提交内容,并与你一起提供反馈和最终详细信息。博客文章获得批准后,博客将安排发布。提交案例研究案例研究强调组织如何使用Kubernetes解决实际问题。它们与Kubernetes营销团队合作编写,由CNCF处理。看看现有案例研究材料。可以使用Kubernetes案例研究提交表提交你的提案。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 19, 2019 · 1 min · jiezi

论文解读:Design patterns for container-based distributed systems

这是由Kubernetes创始人发表的论文,总结了基于容器的分布式系统的设计模式,让我们来一览究竟吧。论文认为,继OOP(面向对象编程)所引领的软件开发革命之后,如今似乎在分布式系统开发中也发生着一场相似的革命:基于容器化组件构建的微服务架构。容器的一大独特优势在于:良好的边界——恰好适合应用开发的隔离性。作者总结了一些设计模式,并且分为三大类型:Single-container management patterns容器的传统接口有run(), pause(), stop()可以有更丰富的接口“向上看”的视角:metrics, config, logs等,通常用HTTP+JSON来暴露“向下看”的视角:lifecycle(提供生命周期回调钩子), priority(为了空出资源给高优先级任务,甚至能提前关掉低优先级任务),“replicate yourself”(迅速创建一组相同的服务容器来应对突发流量)接下来两类都依赖Pod抽象(Kubernetes有提供),因为都涉及容器编排了,而且已进入Sevice Mesh这门新概念的范围。Single-node, multi-container application patterns多个容器组成一个原子单位Sidecar模式例如:web server + log collector前提是容器间能共享“存储卷”之类的资源顺带一提,为什么要用多容器,而非容器内多进程?资源审计和分配:这点很重要,虽然多进程也勉强能做,但多容器做得更成熟职责划分、解耦重用:如果一个容器包含多种进程,就笨重而难以重用了,小巧的单用途容器更适合重用故障隔离:重启一个容器,比修复容器内的故障进程要容易多了交付隔离:每个容器能独立地升级/降级Ambassador模式类似于OOP的proxy模式例如:memcache + twemproxy,这类模式是单结点的,因此twemproxy要和其中1个memcache部署到同一结点上前提是容器间能共享localhost网络接口Adapter模式例如:统一的metrics接口(JMX,statsd等统一收集到HTTP端点)可以免于修改已有的容器(因为已经以容器作为软件开发的单位了)Multi-node application patternsLeader election模式领导者选举这件事已经有很多库了,但往往对编程语言有所限定容器则对编程语言中立容器只需构建一次就能重用,高度贯彻了抽象和封装的原则Work queue模式传统的工作队列框架对编程语言有所限定实现了run(), mount()接口的容器,可作为“工作”的抽象基于此可打造一种通用的工作队列框架(可能是Kubernetes的未来方向)虽然没给例子,但有些类似Mesos的可插拔调度器架构Scatter/gather模式这样传递请求:client->root->serverroot结点把请求分发给很多servers,再把它们的响应汇总到一起,交给client例如:搜索引擎,分布式查询引擎多个leaf容器+1个merge容器,就能实现通用的scatter/gather框架(可能也是Kubernetes的未来方向)结语总之,论文将容器视为软件开发的一等公民,像OOP的对象一样重要,提倡单用途可组合可重用的容器。这似乎是对UNIX编程艺术的重申。

March 18, 2019 · 1 min · jiezi

使用Ansible和Vagrant设置Kubernetes

作者:Naresh L J(Infosys)目的此博客文章介绍了为开发而设的多节点Kubernetes集群所需的步骤。此设置提供了类似生产环境的群集,可以在本地计算机上进行。为什么需要多节点群集设置?多节点Kubernetes集群提供类似生产的环境,具有各种优势。尽管Minikube提供了很好的入门平台,但它并没有提供使用多节点集群的机会,帮助解决与应用程序设计和体系结构相关的问题或错误。例如,Ops可以在多节点集群环境中重现问题,测试者可以部署多个版本的应用程序来执行测试用例和验证更改。这些优势使团队能够更快地解决问题,从而提高敏捷性。为什么使用Vagrant和Ansible?Vagrant可以让我们轻松创建虚拟环境,消除导致“在我的机器能工作”现象的陷阱。它可以与多个供应程序一起使用,例如Oracle VirtualBox、VMware、Docker等。它允许我们通过使用配置文件来创建一次性环境。Ansible是自动化软件配置管理的基础架构自动化引擎。它是无代理的,允许我们使用SSH密钥连接到远程计算机。Ansible playbooks以yaml编写,以简单的文本文件提供库存管理。先决条件在你的机器上安装Vagrant。可以在此处找到安装二进制文件。Oracle VirtualBox可以作为Vagrant供应程序,也可以使用Vagrant官方文档描述的类似供应程序。Ansible安装在你的机器上。有关特定平台的安装,请参阅Ansible安装指南。设置概述我们将建立一个Kubernetes集群,包含一个主节点和两个工作节点。所有节点将运行Ubuntu Xenial 64位操作系统,配置使用Ansible playbooks。第1步:创建Vagrantfile使用你喜欢的文本编辑器,创建名为Vagrantfile的文件,插入下面的代码。N的值表示集群中存在的节点数,可以相应地进行修改。在下面的示例中,我们将N的值设置为2。IMAGE_NAME = “bento/ubuntu-16.04"N = 2Vagrant.configure(“2”) do |config| config.ssh.insert_key = false config.vm.provider “virtualbox” do |v| v.memory = 1024 v.cpus = 2 end config.vm.define “k8s-master” do |master| master.vm.box = IMAGE_NAME master.vm.network “private_network”, ip: “192.168.50.10” master.vm.hostname = “k8s-master” master.vm.provision “ansible” do |ansible| ansible.playbook = “kubernetes-setup/master-playbook.yml” end end (1..N).each do |i| config.vm.define “node-#{i}” do |node| node.vm.box = IMAGE_NAME node.vm.network “private_network”, ip: “192.168.50.#{i + 10}” node.vm.hostname = “node-#{i}” node.vm.provision “ansible” do |ansible| ansible.playbook = “kubernetes-setup/node-playbook.yml” end end end第2步:为Kubernetes master创建Ansible playbook。在Vagrantfile相同的目录中创建名为kubernetes-setup的目录。在kubernetes-setup目录中创建两个名为master-playbook.yml和node-playbook.yml的文件。在master-playbook.yml文件中,添加以下代码。步骤2.1:安装Docker及其相关组件。我们将安装以下软件包,然后将名为“vagrant”的用户添加到“docker”组。—- hosts: all become: true tasks: - name: Install packages that allow apt to be used over HTTPS apt: name: “{{ packages }}” state: present update_cache: yes vars: packages: - apt-transport-https - ca-certificates - curl - gnupg-agent - software-properties-common - name: Add an apt signing key for Docker apt_key: url: https://download.docker.com/linux/ubuntu/gpg state: present - name: Add apt repository for stable version apt_repository: repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable state: present - name: Install docker and its dependecies apt: name: “{{ packages }}” state: present update_cache: yes vars: packages: - docker-ce - docker-ce-cli - containerd.io notify: - docker status - name: Add vagrant user to docker group user: name: vagrant group: docker步骤2.2:如果系统启用了swap,Kubelet将无法启动,因此我们使用以下代码禁用swap。 - name: Remove swapfile from /etc/fstab mount: name: “{{ item }}” fstype: swap state: absent with_items: - swap - none - name: Disable swap command: swapoff -a when: ansible_swaptotal_mb > 0步骤2.3:使用以下代码安装kubelet、kubeadm和kubectl。 - name: Add an apt signing key for Kubernetes apt_key: url: https://packages.cloud.google.com/apt/doc/apt-key.gpg state: present - name: Adding apt repository for Kubernetes apt_repository: repo: deb https://apt.kubernetes.io/ kubernetes-xenial main state: present filename: kubernetes.list - name: Install Kubernetes binaries apt: name: “{{ packages }}” state: present update_cache: yes vars: packages: - kubelet - kubeadm - kubectl步骤2.3:使用以下代码使用kubeadm初始化Kubernetes集群(仅适用于主节点)。 - name: Initialize the Kubernetes cluster using kubeadm command: kubeadm init –apiserver-advertise-address=“192.168.50.10” –apiserver-cert-extra-sans=“192.168.50.10” –node-name k8s-master –pod-network-cidr=192.168.0.0/16步骤2.4:使用以下代码为vagrant用户设置kube配置文件以访问Kubernetes集群。 - name: Setup kubeconfig for vagrant user command: “{{ item }}” with_items: - mkdir -p /home/vagrant/.kube - cp -i /etc/kubernetes/admin.conf /home/vagrant/.kube/config - chown vagrant:vagrant /home/vagrant/.kube/config步骤2.5:使用以下代码设置容器网络供应商和网络政策引擎。 - name: Install calico pod network become: false command: kubectl create -f https://docs.projectcalico.org/v3.4/getting-started/kubernetes/installation/hosted/calico.yaml步骤2.6:生成kube join命令将节点加入Kubernetes集群,并将该命令存储在名为join-command的文件中。 - name: Generate join command command: kubeadm token create –print-join-command register: join_command - name: Copy join command to local file local_action: copy content=”{{ join_command.stdout_lines[0] }}" dest="./join-command"步骤2.7:使用以下代码设置检查Docker守护程序的处理程序。 handlers: - name: docker status service: name=docker state=started步骤3:为Kubernetes节点创建Ansible playbook。在kubernetes-setup目录中创建名为node-playbook.yml的文件。将以下代码添加到node-playbook.yml中步骤3.1:开始添加步骤2.1到2.3的代码。步骤3.2:使用以下代码将节点加入Kubernetes集群。 - name: Copy the join command to server location copy: src=join-command dest=/tmp/join-command.sh mode=0777 - name: Join the node to cluster command: sh /tmp/join-command.sh步骤3.3:添加步骤2.7中的代码以完成此playbook。第4步:完成Vagrantfile和playbooks后,请按照以下步骤操作。$ cd /path/to/Vagrantfile$ vagrant up完成上述所有步骤后,Kubernetes集群应该已启动并运行。我们可以使用Vagrant登录主节点或工作节点,如下所示:$ ## Accessing master$ vagrant ssh k8s-mastervagrant@k8s-master:~$ kubectl get nodesNAME STATUS ROLES AGE VERSIONk8s-master Ready master 18m v1.13.3node-1 Ready <none> 12m v1.13.3node-2 Ready <none> 6m22s v1.13.3$ ## Accessing nodes$ vagrant ssh node-1$ vagrant ssh node-2KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 18, 2019 · 3 min · jiezi

利用Serverless Kubernetes和Kaniko快速自动化构建容器镜像

摘要: 本文介绍了一种新的面向开发者的简单镜像构建实践,基于阿里云Serverless Kubernetes容器服务,可以自动化而且低成本的构建容器镜像,以便让开发者了解如何使用Serverless运行CI/CD和自动化任务。前言:在云原生时代中,容器镜像是一切应用分发的基础载体,除了dockerhub作为流行的镜像仓库外,各大公有云厂商也都提供了功能丰富镜像仓库服务,如ACR(Aliyun Container Registry), GCR(Goolge Container Registry),构建容器镜像已是所有开发者必须掌握的基础实践能力。无论开发者选择在本地使用docker完成基本的镜像构建,还是使用CI/CD服务(如Jenkins),本质上都是遵循“pull -> build -> push”的过程,完成镜像的构建、分发和同步等操作。本文介绍了一种新的面向开发者的简单镜像构建实践,基于阿里云Serverless Kubernetes容器服务,可以自动化而且低成本的构建容器镜像,以便让开发者了解如何使用Serverless运行CI/CD和自动化任务。why serverless kubernetes?容器镜像的构建是需要计算资源的,开发者在本地使用docker pull/build/push时,其计算资源是本地开发机器,如果开发者在传统kubernetes集群中部署Jenkins或Gitlab-runner服务,其计算资源也是需要持续运行。但是,容器镜像的构建基本属于高度动态的行为,往往是定时或者条件触发引起的操作,所以为了动态的构建操作而维护一个固定的计算资源池对成本是不利的。Serverless Kubernetes不同与传统基于节点的k8s集群,serverless集群中只有pod运行时才会收费,意味着只有在构建镜像时用户才需要付费,当构建结束时,也就停止计费。所以在成本上与传统k8s集群或ecs部署的方式相比显著减少。Kaniko在Serverless Kubernetes集群中,pod没有privileged权限,无法访问主机上的docker daemon,也就无法使用docker in docker方案进行镜像的操作,那么如何在kubernetes集群中不依赖宿主机的Docker情况下构建镜像呢?显然这是一个通用需求,社区也有了推荐的方案:kaniko。kaniko的工作原理与docker build类似,但是不依赖docker daemon,在pod中完成Dockfile各层的解析和build,这使得pod不需要privileged权限也可以完成镜像的pull/build/push。实践示例:定时同步容器镜像下面让我们使用Serverless Kubernetes和Kaniko实现一个简单的镜像build实验:定时同步镜像到国内ACR。步骤1: 创建Serverless Kubernetes集群登陆容器服务控制台, 5s即可完成Serverless集群创建。(如果是国外的源镜像仓库,可以选择美西区域)步骤2: 创建secret,配置ACR的用户名密码,用于推送镜像到ACR可登陆cloudshell操作如下命令。#docker login registry.cn-hangzhou.aliyuncs.com…#kubectl create secret generic regsecret –from-file=/root/.docker/config.json…步骤3: 创建定时任务CronJob在控制台选择模版创建如下定时任务,每小时同步busybox镜像到ACR。apiVersion: v1kind: ConfigMapmetadata: name: dockerfile-cmdata: Dockerfile: | FROM busybox:latest—apiVersion: batch/v1beta1kind: CronJobmetadata: name: kaniko-builderspec: schedule: “*/60 * * * *” jobTemplate: spec: template: spec: containers: - name: builder image: gcr.io/kaniko-project/executor:latest imagePullPolicy: Always args: - “–dockerfile=/configs/Dockerfile” - “–destination=registry.cn-hangzhou.aliyuncs.com/jovizhangwei/busybox:latest” volumeMounts: - name: dockerfile readOnly: true mountPath: “/configs/” - name: secrets readOnly: true mountPath: “/root/.docker/” volumes: - name: dockerfile configMap: name: dockerfile-cm - name: secrets secret: secretName: regsecret restartPolicy: OnFailure待job执行后,可查看ACR镜像仓库,确认镜像已同步。用户可以按照需求定制此模版文件,比如修改需要同步的镜像,添加build步骤等,也可以设置pod的资源限制(vcpu 0.25/0.5/1等), 以最小的计算成本完成同步任务。结束通过上面的示例,我们看到基于Serverless Kubernetes的按需付费特性,可以使用很低的成本运行一些定时和CI/CD任务,而不用维护一个固定的计算资源池,其同样适用于压力测试、数据计算、工作流处理等其他场景。Happy Hacking!更多参考信息Serverless Kubernetes快速部署jenkins环境及执行流水线构建: https://yq.aliyun.com/articles/685219kaniko intro:https://cloud.google.com/blog/products/gcp/introducing-kaniko-build-container-images-in-kubernetes-and-google-container-builder-even-without-root-access本文作者:贤维阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 15, 2019 · 1 min · jiezi

CNCF案例研究:网易

网易如何利用Kubernetes支持全球互联网业务公司:网易地点:中国杭州行业:互联网技术挑战它的游戏业务是世界上最大的游戏业务之一,但这并不是网易为中国消费者提供的唯一服务。该公司还经营电子商务、广告、音乐流媒体、在线教育和电子邮件平台;最后一个通过163.com等网站为近十亿用户提供免费电子邮件服务。2015年,为所有这些系统提供基础设施的网易云团队,意识到他们的研发流程正在减缓开发者的速度。“我们的用户需要自己准备所有基础设施。”网易云和容器服务架构师Feng Changjian说。“我们渴望通过无服务器的容器服务,自动为我们的用户提供基础设施和工具。”解决方法在考虑建立自己的业务流程解决方案后,网易决定将其私有云平台建立在Kubernetes上。这项技术来自Google的事实让团队相信它可以跟上网易的规模。“经过2到3个月的评估,我们相信它可以满足我们的需求。”Changjian说。该团队在2015年开始使用Kubernetes,甚至在1.0之前。今天,网易内部云平台还利用了CNCF项目Prometheus、Envoy、Harbor、gRPC和Helm,在生产集群中运行10,000个节点,并且可以在一个集群中支持多达30,000个节点。基于其内部平台的经验,该公司向外部客户推出了基于Kubernetes的云和面向微服务的PaaS产品,网易轻舟微服务。影响网易团队报告说,Kubernetes使研发效率提高了100%以上。部署效率提高了280%。“在过去,如果我们想进行升级,我们需要与其他团队合作,甚至在其他部门工作。”Changjian说。“我们需要特殊的工作人员来准备一切,所以花了大约半个小时。现在我们可以在5分钟内完成。”新平台还允许使用GPU和CPU资源进行混合部署。“之前,如果我们将所有资源都用于GPU,我们就不会为CPU提供备用资源。但是现在我们通过混合部署得到了改进。”他说。这些改进也提高了资源的利用率。“该系统可以在一个集群中支持30,000个节点。在生产中,我们在单个集群中获得了10,000个节点的数据。整个内部系统正在使用该系统进行开发、测试和生产。” - Zeng Yuxing,网易架构师它的游戏业务是全球第五大,但这并非网易为消费者提供的唯一服务。该公司还在中国经营电子商务、广告、音乐流媒体、在线教育和电子邮件平台;其中最后一个通过163.com和126.com等热门网站为近十亿用户提供免费电子邮件服务。凭借这种规模,网易云团队为所有这些系统提供基础设施,在2015年发现他们的研发流程难以使开发者满足需求。“我们的用户需要自己准备所有基础设施。”网易云和容器服务架构师Feng Changjian说。“我们渴望通过无服务器的容器服务,自动为我们的用户提供基础设施和工具。”在考虑建立自己的业务流程解决方案后,网易决定将其私有云平台建立在Kubernetes上。这项技术来自Google的事实让团队相信它可以跟上网易的规模。“经过2到3个月的评估,我们相信它可以满足我们的需求。”Changjian说。“我们利用Kubernetes的可编程性,以便我们可以构建一个平台来满足内部客户的升级和部署需求。” - Feng Changjian,网易云和容器服务架构师该团队在2015年开始采用Kubernetes,甚至在1.0之前,因为它相对容易使用,并且让公司启用了DevOps。“我们放弃了Kubernetes的一些概念;我们只想使用标准化框架。”Changjian说。“我们利用Kubernetes的可编程性,以便我们可以构建一个平台来满足内部客户的升级和部署需求。”该团队首先专注于构建容器平台,以更好地管理资源,然后通过添加监控等内部系统,将注意力转向改进其对微服务的支持。这意味着整合CNCF项目Prometheus、Envoy、Harbor、gRPC和Helm。“我们努力提供简化和标准化的流程,因此我们的用户和客户可以利用我们的最佳实践。”Changjian说。团队正在继续改进。例如,企业的电子商务部分需要利用混合部署,这在过去需要使用两个独立的平台:基础架构即服务平台和Kubernetes平台。最近,网易创建了一个跨平台的应用程序,可以同时使用单命令部署。“只要公司拥有一支成熟的团队和足够的开发者,我认为Kubernetes是一种非常好的技术,可以帮助他们。” - Li Lanqing,网易Kubernetes开发者今天,网易内部云平台“可以在一个集群中支持30,000个节点。”架构师Zeng Yuxing说。“在生产中,我们在单个集群中获得了10,000个节点的数据。整个内部系统正在使用该系统进行开发、测试和生产。”网易团队报告说,Kubernetes使研发效率提高了100%以上。部署效率提高了280%。“在过去,如果我们想进行升级,我们需要与其他团队合作,甚至在其他部门工作。”Changjian说。“我们需要特殊的工作人员来准备一切,所以花了大约半个小时。现在我们可以在5分钟内完成。”新平台还允许使用GPU和CPU资源进行混合部署。“之前,如果我们将所有资源都用于GPU,我们就不会为CPU提供备用资源。但是现在我们通过混合部署得到了改进。”他说。这些改进也提高了资源的利用率。“通过与这个社区合作,我们可以从中获得一些经验,我们也可以从中受益。我们可以看到社区面临的问题和挑战,并参与其中。” - Li Lanqing,网易Kubernetes开发者基于使用其内部平台的结果和经验,该公司向外部客户推出基于Kubernetes的云和面向微服务的PaaS产品,网易轻舟微服务。“我们的想法是,我们可以找到我们的游戏和电子商务以及云音乐供应商遇到的问题,因此我们可以整合他们的经验,并提供一个平台来满足用户的需求。”Changjian说。无论是否使用网易产品,该团队都鼓励其他公司尝试Kubernetes。“只要公司拥有一支成熟的团队和足够的开发者,我认为Kubernetes是一种非常好的技术,可以帮助他们。”Kubernetes开发者Li Lanqing说。作为最终用户和供应商,网易已经更多地参与社区,向其他公司学习并分享他们所做的事情。该团队一直在为Harbor和Envoy项目做出贡献,并在网易规模测试技术时提供反馈。“我们是一个专注于解决微服务架构挑战的团队。”Changjian说。“通过与这个社区合作,我们可以从中获得一些经验,我们也可以从中受益。我们可以看到社区面临的问题和挑战,并参与其中。”KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 15, 2019 · 1 min · jiezi

在 Ali Kubernetes 系统中,我们这样实践混沌工程

在传统的软件测试中,我们通常通过一个给定的条件来判断系统的反馈,通过断言来判断是否符合预期,测试条件和结果通常比较明确和固定。而混沌工程,是通过注入一些“不确定”因素,象放进了一群淘气的猴子,在系统资源、可用性、安全性、延迟、压力等方面进行捣乱,而此过程中,要求系统可以毫无影响的提供服务,用户无感知。这其实对系统的自愈能力,健壮性都有很高的要求。故障注入一般是指比较受控的一些实验条件,通过注入一些相对极端的异常场景,为系统提供可靠性测试的过程。 整体来说,混沌是一种故障注入规则,强调了一些不确定性、随机性,比较常见的"猴子"有 Netflix 的"猴子军团",可以用来随机关闭系统实例,注入延时,回收资源,检查安全漏洞等等。开源工具介绍除了一般系统的 monkey,基于 Kubernetes 已经有一些"猴子"工具可以测试系统的健壮性。接下来,介绍一下比较常见的三种 Kubernetes monkey:kube-monkeyhttps://github.com/asobti/kube-monkey运行方式:kube-monkey 通过 label 设置受害者 pod,创建了一个单独的 kube-monkey pod 对受害者 pod 施加影响;注入类型:目前支持的故障注入类型仅有杀容器;配置项:可以通过配置文件设置运行周期和频率,在一定时间内随机的杀死打标范围内的 pod。powerfulsealhttps://github.com/bloomberg/powerfulseal注入类型:powerfulseal 的故障注入类型包括杀 pod 和启停 node。运行方式:包括交互模式,自动模式、打标模式和示例模式。交互模式通过界面交互查询node/namespace/pod,启停 node 或杀死 pod 操作;自动模式通过读取配置文件确定注入范围,注入频率;打标模式通过给 pod 打标确定注入的靶向 pod 及注入频率;示例模式可以反映根据使用资源情况进行故障注入的过程。Chaos Toolkit-kubernetes[https://github.com/chaostoolk…;是 chaos 工具包中的一个,通过 chaos run experiment.json 设置 json 文件来指定 namespace,正则匹配名字等等来随机杀一个 pod。以上三种"猴子",主要是基于杀 pod 场景来注入故障,虽然是最有力的场面但是比较有局限性,对于商业化系统面临的复杂场景,是值得参考但是不够的。](https://github.com/chaostoolk…结合 Ali Kubernetes 故障场景分析Ali Kubernetes 作为一个管理大规模集群的商业调度系统,需要应对的不仅包括一些基本的 Kubernetes 中 pod 误删误停的故障现象,也包含一些底层 OS、内核、网络、误配置等灾难场景。同时由于其支撑业务生态的复杂性,全链路综合异常流也需要特殊的验证。为更系统的进行演练,在过程中主要进行了以下几部分工作:FMEA 分析就是失效模式和效果分析,旨在对系统范围内潜在的失效模式加以分析,以便按照严重程度加以分类,或者确定失效对于该系统的影响。从故障场景上,分析得出较为符合 Ali Kubernetes 的三大类场景:通用故障场景:包括网络相关故障(网络 iohang ,断网,网络延迟等),宿主机相关故障(机器重启,机器 load 高等)Ali Kubernetes 业务场景故障:包括 Kubernetes 相关的故障(pod 删除,pod patch等),pod 迁移,混部、etcd 等业务相关场景;chaos 故障:较为随机的故障注入,可以为以上任何故障的组合从影响面上,需要 case by case 确定影响范围为无任何影响,仅影响部分功能,影响核心功能等等;从验证恢复手段上,也可以分为自动恢复、手动恢复,同时需要关注监控情况及恢复时间。在分析过程中,我们发现,已有的开源工具无法完全满足 Ali Kubernetes 的故障场景。下面举 2 个典型故障场景:pod 被误删这个场景并不是简单的 pod 随机删除,而是在 kubelet 连错 apiserver 配置等异常情况下,重启 ali-kubelet 后,al 自行判断了容器在当前集群内不存在,自己做了删除操作。要引入这个故障需要修改 kubelet 组件的配置,重启 kubelet,才算是真正引入了故障,而当前的无论是 kube-monkey 还是 powerfulseal 场景都无法满足。master 组件断网有的人可能会说,直接指定 master 组件的机器引入断网操作,是不是就可以了呢?然鹅现实是比较骨感的,我们也许只知道这个 master 所在集群的 kubeconfig,组件的机器其实也可以随着每次升级变动的。在仅仅已知 kubeconfig 的情况下我们只能先查一下 master 组件的机器信息,再在机器上引入断网的操作,才算是一个整体的故障引入。而目前所有的开源工具也没有此类稍微复杂一些的场景,只是通过指定 pod namespace 来随机的删除一些 pod。所以综上所述,其实我们需要对此进行扩展开发,除了简单的杀 pod,我们亟需一套可以自由开发的小程序,把这个步骤拼接起来,进行更为复杂的故障注入。套件实现为了满足此类复杂的故障注入,我们使用了目前集团内正在开发的一套故障注入系统 monkeyking,并在它的基础上扩展了一些 kubernetes 相关的套件,来达到既可以注入 kubernetes 相关的故障,又可以注入一些通用故障,同时又可以相对自由的扩展故障集合的目的。这个故障注入的演练流程如下图所示:它的每一个步骤都可以是我们自由扩展的一个或者多个小程序,各个小程序之间的执行顺序也可以自由的定义。考虑到 Ali Kubernetes 的场景,我们在其中扩展了四大类小程序套件。通用故障小程序在这一部分主要实现了一些比较通用的 os 故障,网络故障,比如最基本的指定一个宿主机断网,指定宿主机重启这类。Kubernetes 套件小程序这一部分主要实现了一些通用的 Kubernetes 命令,通过指定这些命令和入参,我们可以执行比如 create delete apply patch 这些操作,来间接的达到注入一些 Kubernetes 相关故障的目的。实现原理如下:要点说明如下:下载集群证书的地址及证书的 md5 码都作为小程序的输入,在执行实际的 kubectl 生效命令前进行下载校验;底层 toolkit 中已经加入了 kubectl 命令行工具,无需自己找环境进行配置和下载;目前已经支持了 apply,create,delete,patch,get 操作,支持指定 label,namespace,-o json 的操作举个例子,上文中 master 组件故障的场景中,我们就可以利用以上的两类小程序来完成故障注入的操作:开源工具小程序目前我们和集团安全生产的 MonkeyKing 团队合作,联合在故障注入平台 monkeyking 中集成了开源工具 kube-monkey,实现过程借助了上文的 kubernetes 套件执行,可以通过打标的方式标记受害者,让 kube-monkey 随机的杀受害者 pod。步骤如下:环境准备锁演练环境在当前集群中初始化kube-monkey: 使用kubernetes套件的apply功能提交km-config.yaml文件,部署 kube-monkey deployment给应用标记受害者 label使用 Kubernetes 套件的 patch 功能,标记受害者验证步骤自定义组件校验应用服务是否可用故障恢复使用 Kubernetes 套件的 patch 功能,给受害者去标使用 Kubernetes 套件的 delete 功能,删除 kube-monkey deployment解锁演练环境其他业务相关小程序这一部分比较自由,主要根据 Ali Kubernetes 的业务需求,接入了一些常用的小程序。比如故障演练过程中,环境需要独占,不允许其他测试执行,在这里实现了一个小程序用来对环境进行加解锁操作;比如校验阶段需要验证服务是否可用,这里实现了一个通过 curl 命令校验返回值的方式验证服务是否可用的小程序;比如故障注入过程可能影响vip挂载,这里也实现了一个调用 vip 服务校验 vip 下 ip 数量及是否可用的小程序。总结在 Ali Kubernetes 中,我们将故障以场景化的方式进行沉淀,将底层 os,内核、网络、误配置等故障联合 Kubernetes 相关故障,引入混沌工程的理念进行注入,有效的发现了很多系统稳定性问题,驱动开发人员更多关注系统健壮性。后续我们会在 Ali Kubernetes 演进过程中持续发力,基于架构和业务场景输入更多 Kubernetes 相关的故障场景,为系统的高可用保驾护航。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 14, 2019 · 1 min · jiezi

云原生土壤孕育的开源森林

当今的社会是高速发展的新型科技社会,互联网、物联网、人工智能等一系列新鲜事物如雨后春笋般喷薄而出,并以前所未有的速度迅速成长。在这个风起“云”涌的时代,云原生技术作为孕育这些高科技的土壤,亦是备受世人关注。早在2013年的时候,云原生 (Cloud Native) 这个概念一经提出,就已经广受专家们的关注与推崇。再经历了诸多大企业的部署、实践、应用之后,云原生技术的优势更进一步显现,它不仅带动了新的 IT 技术的大发展,也加速了很多类型企业向云技术化转型的进程。那么,火热的云原生究竟怎么去理解呢?其实,由于它具有可以为企业迅速部署新业务的特性,且在我们的实际应用中,可以清晰的感受到它的高弹性、动态调度、自动伸缩等一些传统IT技术所不具备的能力,在部署过程中除了我们要考量技术上的如 :DevOps、持续交付、微服务、敏捷基础设施等特性,也要考量如何体现其与企业管理、企业文化之间的深度融合,所以,综上考虑,我们可以认为云原生的实质,就是一个关联着管理与技术跨层面交叠的融合式集合。为了便于更好的运用云原生应用为我们服务,2015年,由谷歌牵头成立了 CNCF (Cloud Native Computing Foundation,云原生计算基金会) 。该组织来自社区的技术监督委员会整理了“云原生”的概念并通过了“CNCF 云原生定义 v1.0”:云原生技术有利于各组织在公有云,私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。云原生计算基金会 (CNCF) 致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。之后, CNCF 绘制了 Cloud Native Landscape,并不断更新给出了比较详尽的云原生生态的参考体系。CNCF 也绘制了无服务器 Landscape,从而能够更好的跟踪这一热门领域的发展。以下是CNCF 无服务器 Landscape。为了便于大家理解和运用不同阶段的云原生应用,CNCF 在这片广袤的开源生态中,为不同程度的使用者绘制了不同应用阶段的 Trail map,来提供参考。自2017年的 LC3 大会登陆中国以来,云原生的议题便在中国的 IT 界生根发芽,蓬勃发展,面对这一高速发展的态势,我们甚至可以毫不夸张的说,2017年是云原生在中国发展的开元之年,如:Kubernetes 与华为 IT 系统的 PaaS 演变 – Kevin Wang & Jianlin Wu,华为;阿里巴巴在 Linux 内核中资源管理工作 – 马涛,阿里云;Kubernetes API & 下一代自动化工具 – Ian Lewis,Google Inc.;随着 Kubernetes 不断的融入我们的生产环境,在2018的 LC3 大会中,我们更是聆听了许多热门大咖关于这一热门领域的演讲,如:采用 Kubernetes 进行基因组测序的最佳实践 – Shengjun Tang,华为;基于 JStorm 的网络分析平台 – Biao Lyu,阿里云;DPDK 中的 FPGA 和虚拟化技术加速和扩展云网络 – Tianfei Zhang 和 Rosen Xu,Intel;Bcache 稳定性 – 云基础设施的改进 – Coly (Yong) Li,SUSE;在 KVM / QEMU 上实现更好的实时迁移 – Guangong Xiao,Tencent Cloud;使用开源工具加速 Kubernetes 上的云原生应用程序的 DevOps – Rome Li,Microsoft;在同年举办的首届 KubeCon + CloudNativeCon 中国论坛中,大咖们继续为我们带来了更精彩的演讲,如:CNCF 互动景观 – Dan Kohn,云原生计算基金会 (CNCF) ;中国的云原生生态系统 – Tao Ma,阿里云首席工程师;使用 “KubeEdge” 管理边缘节点 – Yulin Sun, 华为 和 Li Xing, 华为;谁在运行我的 Pod?深入研究 K8s Container Runtime Interface – Phil Estes,IBM;用于腾讯机器学习的深度定制 Kubernetes – Shengbo Song,腾讯。那么,在2019年,有关云原生对开源应用的影响等方面的议题又会有哪些大咖加以完善,并与您分享最新的实战观点呢?请您务必不要错过,2019年,CNCF和LF为您即将呈现的开源技术盛宴 - KubeCon + CloudNativeCon + Open Source Summit (原LC3)。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 14, 2019 · 1 min · jiezi

Rancher全新开源力作Submariner:实现Kubernetes跨集群网络

2019年3月12日,业界领先的容器管理软件提供商Rancher Labs(以下简称Rancher)宣布推出全新开源项目Submariner,支持多个Kubernetes集群之间的跨集群网络连接。Submariner将为部署在需要相互通信的多个Kubernetes集群中的微服务提供网络连接。这一全新的解决方案解决了Kubernetes集群之间的连接障碍,为多集群部署提供了更多实现方式,例如在跨地区的Kubernetes内复制数据库,以及跨集群部署服务网格。越来越多的企业将Kubernetes用作为跨所有公有云和私有云基础设施的基础计算平台,而Submariner让这些企业得以无缝连接、扩展和迁移部署在Kubernetes集群上的工作负载,无论这些Kubernetes集群是部署在何种云上。Submariner:跨集群的网络连接过去,Kubernetes的部署实现了网络虚拟化,让容器可以在同一集群中的多个节点运行并相互通信。然而,在不同的Kubernetes集群中运行的容器想要实现互相通信,则必须通过ingress controller或者节点端口。如今,Submariner创建了必要的隧道和路径,使不同的Kubernetes集群中的容器能够直接连接。Submariner的主要功能包括:与现有集群的兼容性和连接性:用户可以将Submariner部署到已有的Kubernetes集群中,并在位于不同集群的节点之间添加三层网络连接。安全路径:使用IPSec隧道实现加密的网络连接。各种连接机制:虽然IPSec是开箱即用的默认连接机制,但Rancher将在不久的将来启用不同的连接插件。集中式代理:用户可以注册和维护一组健康的网关节点。灵活的服务发现:Submariner提供跨多个Kubernetes集群的服务发现。CNI兼容性:适用于流行的CNI驱动程序,如Flannel和Calico。Submariner的使用场景主要为:地理式分布HA数据库,如Cassandra分布式跟踪跨集群扩展服务网络完全开源,立即体验Submariner如果您对Submariner感兴趣,希望进一步了解、下载、安装和使用这一全新的网络技术解决方案,欢迎访问:https://submariner.io同时,Submariner依旧秉承Rancher 100%开源的理念,您可以在GitHub上了解及下载Submariner: https://github.com/rancher/su…如需协助部署和管理,请邮件联系:info@rancher.comAbout Rancher LabsRancher Labs由硅谷云计算泰斗、CloudStack之父梁胜创建,致力于打造创新的开源软件,帮助企业在生产环境中运行容器与Kubernetes。旗舰产品Rancher是一个开源的企业级Kubernetes平台,是业界首个且唯一可以管理所有云上、所有发行版、所有Kubernetes集群的平台。解决了生产环境中企业用户可能面临的基础设施不同的困境,改善Kubernetes原生UI易用性不佳以及学习曲线陡峭的问题,是企业落地Kubernetes的不二之选。Rancher在全球拥有超过一亿的下载量,超过20000家企业客户。全球知名企业如中国人寿、华为、中国平安、民生银行、兴业银行、上汽集团、海尔、米其林、天合光能、丰田、本田、霍尼韦尔、金风科技、普华永道、海南航空、厦门航空、恒大人寿、中国太平、巴黎银行、美国银行、HSCIS恒生指数、中国水利、暴雪、CCTV等均是Rancher的付费客户。添加微信助手(rancher2),进技术群,了解详情~

March 14, 2019 · 1 min · jiezi

CNCF发布KubeCon + CloudNativeCon欧洲2019节目表

基金会迄今为止最大的欧洲活动将包括蚂蚁金服、AT&T、Dyson、Etsy.com、GO-JEK、NTT Corporation、NVIDIA、Offerup、Spotify、Zalando等的演讲加利福尼亚州旧金山 - 2019年3月13日 - 支持和集成Kubernetes®和Prometheus™等开源技术的CNCF(云原生计算基金会)发布了于2019年5月20日至23日在巴塞罗那举行的KubeCon + CloudNativeCon 欧洲的会议阵容。这次活动的亮点包括专家分享使用Kubernetes和其他云原生技术的真实案例研究,他们来自ADMIRALTY、Booking.com、英国电信、Carnegie Mellon、eBay、Engel & Völkers Technology、ING、领英、LSST & French National Institute of Nuclear and Particle Physics (IN2P3)、Mediakind、McKesson、VTT等机构。继去年12月在西雅图举办,有史以来规模最大的KubeCon会议之后,KubeCon + CloudNativeCon 欧洲将汇集来自全球蓬勃发展的开源社区的10,000多名技术专家,以进一步围绕云原生计算进行协作。 CNCF托管项目的维护者和最终用户 - 包括Kubernetes、Prometheus、Envoy、CoreDNS、containerd、OpenTracing、Fluentd、gRPC、rkt、CNI、Jaeger、Notary、TUF、Vitess、NATS、Rook、Harbour、etcd、Linkerd和Helm - 和其他云原生技术将聚集四天,分享见解并鼓励参与这个快速发展的生态系统。3月20日前注册KubeCon + CloudNativeCon欧洲,最高可节省300美元。“令人惊讶的是,我们有望从去年12月在西雅图的8,000人,有史以来最大的开源开发者大会,到今年5月在巴塞罗那召开规模更多的会议。”CNCF执行总Dan Kohn说。“云原生计算已经跨越了鸿沟,因此来自数百个最终用户组织的开发者渴望与社区其他成员合作。”由会议联合主席VMware的Bryan Liles和Google Cloud的Janet Kuo领导的110名专家组成的计划委员会,审核了1,535份提交,以帮助创建该节目的多样化内容。该议程包括令人印象深刻的主题组合,包括技术会议、深度研究和案例研究,涵盖应用和开发(包括Helm和Telepresence)、CI/CD、定制和扩展Kubernetes、促进社区、机器学习和数据、网络(包括NATS、CoreDNS、CNI和gRPC)、可观察性(包括Jaeger、OpenTracing、Fluentd和Prometheus)、操作、性能+可扩展性、运行时(包括containerd和rkt)、安全性、身份和策略(包括OPA、SPIFFE/SPIRE、Notary和TUF)、无服务器(包括CloudEvents)、存储(包括Vitess和Rook)等。“在审阅巴塞罗那的提交文件时,我们对整个社区广泛采用云原生技术,以及从研究机构到银行的所有垂直行业感到惊讶。我们对这个快速发展的生态系统中构建的新工具和技术印象深刻。”KubeCon + CloudNativeCon联合主席兼Google软件工程师Janet Kuo表示。“我们希望今年的与会者能够从专家和项目维护者那里获得第一手新知识,以及使用这些技术的实践经验。”“能够代表这样一个快速发展的多元化社区,从根本上改变我们构建软件和数字体验的方式,我感到非常荣幸。”VMware高级工程师兼会议联合主席Bryan Liles说。“今年的节目表包含了我们见过的一些最具创新性和信息量的会议,我们期待成员们聚在一起分享他们的知识。”社区策划的节目表将包括来自领先的开源技术专家的会议,包括:“How Spotify accidentally deleted all its Kube clusters, with no user impact” – David Xia, Spotify“Getting Started in the Kubernetes Community” – Lucas Käldström & Nikhita Raghunath, Independent“Reperforming a Nobel Prize Discovery on Kubernetes” – Ricardo Rocha & Lukas Heinrich, CERN“From COBOL to Kubernetes: A 250 Year Old Bank’s Cloud-Native Journey” – Mike Ryan, Epitech BV & Laura Rehorst, ABN AMRO Bank NV“Panel Discussion: GitOps & Best Practices for Cloud Native CI/CD” – Moderated by Laura Tacho, CloudBees“Kubernetes the new Research Platform” – Lindsey Tulloch, Brock University & Bob Killen, University of Michigan“From Snowflake Servers to Snowflake Clusters – The GitOps Journey” – Allison Richardet, Asteris, LLC & Fabio Giannetti, MasterCard“Panel Discussion: Democratizing HPC & AI: Startups Scale up with Cloud Native” – Moderated by Emily Tanaka-Delgado, Oracle“Kubectl Apply 2019: Defense against the Dark Arts” – Phillip Wittrock & Jennifer Buckley, Google“Helm 3: Navigating To Distant Shores” – Bridget Kromhout, Microsoft & Jessica Deen, Microsoft“Sharing is Caring: Your Kubernetes Cluster, Namespaces, and You” – Amy Chen, VMware & Eryn Muetzel, VMware“Panel Discussion: Going Multi-cloud for realz. Stories from media, retail, & infrastructure” – Moderated by Lisa-Marie Namphy, Portworx作为KubeCon + CloudNativeCon的一部分,CNCF还将于5月20日星期一举办以下同地活动 - 如果有兴趣,与会者应在预订航班和酒店时预早计划:KubeSec Enterprise Summit hosted by Aqua SecurityA Linkerd in Production Workshop hosted by BuoyantContinuous Delivery Summit hosted by CDFCephaloconContributor SummitServerless Practitioners Summit hosted by CNCFCNCF End User Partner SummitCloud Native Storage Day hosted by CNS EcosystemKubernetes Operator Framework Workshop hosted by Red HatOpenShift Commons Gathering hosted by Red HatIntro to Containers & Kubernetes hosted by VMware完整的KubeCon + CloudNativeCon欧洲计划,请到日程安排。谢谢赞助商在赞助商的支持下,KubeCon + CloudNativeCon成为可能,钻石赞助商:Cisco、IBM Cloud、Microsoft Azure、Oracle、Red Hat和VMware;白金赞助商:AWS、Ballerina、CloudBees、Google Cloud、Mirantis、Pivotal、Rancher、Sysdig和Ubuntu,以及更多金牌、银牌、初创公司和媒体赞助商。有关赞助的更多信息可在网站获得。注册和住宿在太平洋标准时间3月20日晚上11:59之前注册,以节省300美元的会议通行证。此外,网站的Venue/Travel部分提供酒店房价折扣。请提前预订,因为折扣价格视供应情况而定。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon + Open Source Summit赞助方案KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon + Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区 ...

March 14, 2019 · 2 min · jiezi

如何自建一个k8s ingress

如何自建一个k8s ingressingress 接入方案我们都知道访问k8s 集群的服务需要ingress 接入。据我所知,ingress 接入的方案有4种1.云厂商提供LoadBalance, 比如aliyun SLB.2.官方的实现 ingress controller 3.第三方实现方案4.自建, 比如使用envoy 这里重点记录一下,如何自建一个ingress 的思路。### ingress 接入方案的原理 在讲如何自建一个k8s ingress 之前,这里分别记录一下ingress 的实现原理。 先说官方的实现。 https://github.com/kubernetes… 官方的ingress 接入实现使用ingress controller + nginx 实现的。如上图所示 ingress 接入分为配置控制和数据代理。 ingress controller 是一个控制中心,监控的数据来源 1.k8s 集群的api-server, 比如node 、service、 pod 变化 2.ingress 实例的configMap ingress controller 发现监控的数据有变化,就把监控的数据转换成为nginx.conf 代理所需要配置。 然后reload nginx. 从而实现数据流量接入路由。 当然,如果ingress controller 这一套部署在k8s 集群内的话,肯定是要暴露端口的。我接触到到的aliyun 的SLB 也类似。 SLB 控制中心是一个叫CMI的程序, 数据代理是有LVS + nginx 组成。ingress 接入方案的原理

March 13, 2019 · 1 min · jiezi

Vitess安全审计结果(pdf)

作者:Adrianna Tan我们很高兴地宣布,Vitess最近接受了由CNCF/Linux基金会资助的安全评估。2019年2月,来自Cure53的团队在以下领域进行了测试:系统复杂性云基础设施源代码审计操作系统交互低级协议分析多角度渗透测试此独立安全审核是在本地安装的系统以及基于Kubernetes的群集上执行的。审计员执行:(1)手动代码审计和(2)代码辅助渗透测试。以下是一些亮点。“在Cure53看来,有明确的意图和后续行动提供一个用于扩展MySQL数据库的安全系统。这是通过保持攻击面最小,并选择适合此实现的语言来实现的。审计员设法覆盖了与Vitess软件系统主存储库相关的所有方面的广泛覆盖范围。选择最有可能被攻击的途径并验证其恢复能力。”“这次由CNCF/Linux基金会资助的Cure53评估,结果证明了Vitess数据库缩放器是安全可靠的。通过限制攻击面,适当关注用户提供的输入和安全驱动的最佳实践,以及,在某种程度上,使用Go语言生态系统,可以实现这一非常好的结果。”“虽然这次评估的结果很少,而且可能暗示某种测试限制,但实际上它们证明了Vitess团队能够兑现他们所做出的安全承诺。”审核员给Vitess团队确认了三个改进地方。我们感谢Cure53、CNCF、Linux基金会和所有项目贡献者的帮助。点击下载完整报告的pdf。KubeCon + CloudNativeCon + Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 13, 2019 · 1 min · jiezi

initContainer 使用案例

将glusterfs存储同时挂载到initContainer和container的指定目录上,如:/var/data/在initContainer中拉取资源放到/var/data/,也就推到了分布式存储glusterfs上,如:wget -P /var/data/ http://127.0.0.1:8081/repository/k8s/kubectl/kubectl-v1.10.0-linux-amd64.tar.gz这样当业务容器启动后,就可以在指定目录/var/data下看到initContainer拉取到的资源在initContainer中,最好增加一部检测指定资源是否存在,以防重复拉取,如:if [ ! -f “/var/data/kubectl-v1.10.0-linux-amd64.tar.gz” ]; then wget -P /var/data/ http://127.0.0.1:8081/repository/k8s/kubectl/kubectl-v1.10.0-linux-amd64.tar.gz; fiapiVersion: apps/v1kind: Deploymentmetadata: name: mysqlspec: replicas: 1 selector: matchLabels: name: mysql template: metadata: labels: name: mysql spec: initContainers: - name: getresource image: busybox:v0.1.0 command: [‘sh’, ‘-c’, ‘wget -P /var/data/ http://127.0.0.1:8081/repository/k8s/kubectl/kubectl-v1.10.0-linux-amd64.tar.gz ‘] volumeMounts: - name: mysql-pvc mountPath: /var/data containers: - name: mysql image: percona:5.7.22 imagePullPolicy: Always ports: - containerPort: 3306 resources: limits: memory: “500Mi” cpu: “500m” requests: memory: “500Mi” cpu: “250m” env: - name: MYSQL_ROOT_PASSWORD value: “mysql” volumeMounts: - name: mysql-pvc mountPath: /var/data volumes: - name: mysql-pvc persistentVolumeClaim: claimName: mysql—apiVersion: v1kind: PersistentVolumeClaimmetadata: name: mysqlspec: accessModes: - ReadWriteMany resources: requests: storage: “5Gi” volumeName: storageClassName: glusterfs—kind: ServiceapiVersion: v1metadata: name: mysqlspec: type: ClusterIP ports: - name: mysql port: 3306 targetPort: 3306 protocol: TCP selector: name: mysql ...

March 13, 2019 · 1 min · jiezi

6000个边缘Kubernetes节点驱动城市80万次智能停车,如何成为可能?

城市的街道因为汽车数量的增长越来越繁忙,对于驾车一族而言,在热门区域寻找停车场更是无比头痛的事情。然而与此同时,其实也许很多办公楼、住宅楼、酒店和公共车库中仍有许多付费停车的资源未被充分利用。ParkBee就是这样一家为城市提供智能停车解决方案的公司。ParkBee平台上显示着每位车主定位附近的可使用的停车场,停车价格、停车位的空余情况等都是实时更新。ParkBee“打开”了城市中的所有停车场,解决了停车难题,既节约车主时间,又帮助停车场最大限度创收。ParkBee近期开始尝试在边缘位置进行容器部署。因为ParkBee的整体业务的一个重要部分就是大量的停车场,与ParkBee合作的停车场有6000多家,截至目前我们已服务于80万次停车服务。我们必须确保每一个停车场的容器都能按预期工作,因此部署包含业务逻辑的应用程序至关重要。ParkBee目前使用Kops部署Kubernetes,公有云选择的是AWS。虽然这种方法适用于我们的基于云的服务,但对于我们的边缘部署而言,事情却并不是那么简单。我们的理想目标是:在ParkBee合作的每一个停车场上都有一个Kubernetes集群,集群中包含停车点位置的边缘Kubernetes节点以及AWS中的Kubernetes主节点。半个月前,Rancher Labs发布了K3s——一个被认为是史上最轻量的Kubernetes发行版。K3s的设计初衷就是为了能让像树莓派一样的低资源计算平台更容易安装和维护Kubernetes。本质上讲,K3s有望成为一个轻量级的、易于使用、只使用一个二进制文件的Kubernetes provisioner。K3s的发布公告里写到它的主要功能包括:生产级Kubernetes:K3s是一个符合标准的、已获CNCF官方认证的Kubernetes发行版。一个没有主机依赖的二进制文件:在任何设备上安装Kubernetes所需的一切都包含在这一个40MB的二进制文件当中,不需要像KuberSpray、KubeADM或者RKE这样的外部安装程序。只需要一个命令,用户就可以配置或者升级单节点K3s集群。一条命令,向集群添加节点:若想向集群添加其他节点,管理员只需在新节点上运行一条命令,指向原始服务器,通过安全token传递即可。自动生成证书:集群启动时,在Kubernetes主服务器和节点之间建立TLS所需的所有证书都会被自动创建,还会自动创建服务账号的加密密钥。准备工作在这篇文章中,我将使用K3s的第一个版本v0.1.0。如果你想要按照我的文章来尝试一样的操作,你需要准备:Raspberry Pi 3 B+型号,带有闪存了Raspbian Stretch Lite 的microSD卡。本地网络:为了方便起见,我将在家里使用自己的局域网。在你的笔记本电脑本地安装的Vagrant:也可以使用Docker for Mac,不过本质上来说,K3s二进制文件还是为了Linux、arm64和armhf架构而构建的。Vagrant如果您正在使用Vagrant,则可以在test目录中使用以下内容创建一个Vagrantfile:# -- mode: ruby --# vi: set ft=ruby :VAGRANT_API = 2Vagrant.configure(VAGRANT_API) do |config| config.vm.box = “bento/ubuntu-18.04” config.vm.box_check_update = false config.vm.network “forwarded_port”, guest: 6443, host: 6443, host_ip: “0.0.0.0” config.vm.provider “virtualbox” do |vb| vb.cpus = 1 vb.gui = true vb.memory = “2048” vb.name = “k3s-master” end config.vm.provision :docker config.vm.provision “shell”, inline: <<-SHELL sudo modprobe vxlan curl -sfL https://get.k3s.io | sh - hostnamectl set-hostname k3s-master SHELLend至此,你将安装好了Docker以及K3s二进制文件。安装脚本也可以方便地将kubectl二进制文件符号链接到K3s,因为它是内置的。防火墙小提示:Raspberry Pi需要连接到LAN中的本地计算机。在macOS中,确保转到设置=>安全和隐私=>防火墙,然后单击“关闭 ”按钮。对于Windows,您可以参考Lifewire关于在Windows中关闭防火墙的文章:https://www.lifewire.com/how-…运行K3s主节点我们将先使用Vagrant机器作为K3s主节点; 一旦它开始正常工作,我们将尝试将Raspberry Pi连接到本地LAN上的K3s主节点。与任何Vagrant机器一样,只需运行vagrant up,一切就开始启动了。Vagrant将运行K3s自动安装脚本,打开本地计算机上的6443端口,以便K3s节点加入,并创建稍后所需的连接令牌。首先,验证主节点安装是否成功:root@k3s-master:# kubectl get nodesNAME STATUS ROLES AGE VERSIONk3s-master Ready <none> 4m51s v1.13.3-k3s.6默认情况下,K3s安装脚本不会将k3s-master标记为主节点;但因为我们已经预先安装好了kubectl二进制文件,我们现在可以解决这个问题:root@k3s-master:# kubectl label node k3s-master kubernetes.io/role=masternode/k3s-master labeledroot@k3s-master:# kubectl label node k3s-master node-role.kubernetes.io/master=““node/k3s-master labeledK3s安装也不会污染NoSchedule的主节点。在此次测试中,我们希望确保Raspberry Pi能够接收测试部署,因此使用以下方法污染主节点:root@k3s-master:# kubectl taint nodes k3s-master node-role.kubernetes.io/master=effect:NoSchedulenode/k3s-master tainted接下来,我们需要token,来将K3s节点连接到新主节点。该k3s server命令应该已经为您创建了这个/var/lib/rancher/k3s/server/node-token。运行以下命令:root@k3s-master:# cat /var/lib/rancher/k3s/server/node-token<some-long-node-token>在Raspberry Pi上运行K3s节点首先,我们需要为树莓派准备一些初始步骤。首先,使用以下命令来禁用swap:dphys-swapfile swapoff && \dphys-swapfile uninstall && \update-rc.d dphys-swapfile remove然后,将以下文本附加到/boot/cmdline.txt的第一行:cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory然后,reboot树莓派。返回时,重新登录,然后运行以下命令下载k3s二进制文件。curl -fSL “https://github.com/rancher/k3s/releases/download/v0.1.0/k3s-armhf" \ -o /usr/local/bin/k3s && \chmod +x /usr/local/bin/k3s因为K3s已经不使用containerd了,因此我们无需安装Docker ,但最好还是验证一下是不是所有pod都在正常运行。通过运行以下命令可以快速安装Docker:curl -fsSL https://get.docker.com | sh - && \usermod -aG docker pi获取从主服务器创建的token,并将其导出为环境变量:export NODE_TOKEN="<some-long-node-token>“最后,运行k3s agent命令以启动代理程序,然后加入主节点。在我的这次使用中,192.168.0.10是我网络中本地笔记本电脑上运行的Vagrant机器的地址。记得务必使用适当的地址替换该值。k3s agent --docker --server https://192.168.0.10:6443 --token ${NODE_TOKEN} &gt; /root/logs.txt 2>&1 &与K3s主节点类似,这次安装不会使用正确的节点标签标记Raspberry Pi。在k3s-master上,在Raspberry Pi加入集群后运行以下命令:root@k3s-master:# kubectl label node raspberrypi kubernetes.io/role=nodenode/raspberrypi labeledroot@k3s-master:# kubectl label node raspberrypi node-role.kubernetes.io/node=““node/raspberrypi labeled如果Raspberry Pi成功加入,则在主服务器上运行该命令时应该会看到类似以下内容:root@k3s-master:# kubectl get nodesNAME STATUS ROLES AGE VERSIONraspberrypi Ready node 2m v1.13.3-k3s.6k3s-master Ready master 20m v1.13.3-k3s.6部署一个测试NGINX容器为了确保K3s集群能真正正常工作,我们可以部署一个测试NGINX pod和NodePort服务,以确保Raspberry Pi创建了pod,并成功打开了端口。在K3s主Vagrant机器上,使用以下内容在/root/nginx-test.yaml上创建一个文件:—apiVersion: v1kind: Servicemetadata: name: nginx-unprivileged-test namespace: defaultspec: type: NodePort selector: app: nginx-unprivileged-test ports: - protocol: TCP nodePort: 30123 port: 8080 name: http targetPort: 8080—apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: nginx-unprivileged-test namespace: defaultspec: replicas: 1 template: metadata: labels: app: nginx-unprivileged-test spec: containers: - image: nginxinc/nginx-unprivileged name: nginx-unprivileged-test ports: - containerPort: 8080 name: http livenessProbe: httpGet: path: / port: http initialDelaySeconds: 3 periodSeconds: 3然后最终将其部署到集群:root@k3s-master:~# kubectl apply -f /root/nginx-test.yamlservice/nginx-unprivileged-test createddeployment.extensions/nginx-unprivileged-test created因为这是一项NodePort服务,K3s将在Raspberry Pi上打开一个端口30123。在我的本地网络上,Raspberry Pi位于192.168.0.43。结 语在我使用K3s的过程中注意到了一些事项,在此想要提醒:在部署NGINX测试容器时,我最初使用了Docker Hub中的常规nginx:latest镜像。但是,似乎K3s还不支持低于1024的端口。在默认情况下,nginx镜像会尝试在容器内打开端口80,而这会导致一些问题。本文中提到过,通常Kubernetes发行版中都包含label和taint,但K3s暂时没有完全实现这一点。K3s将极大地促进Kubernetes在边缘计算场景的使用,对这一点我充分相信。 ...

March 13, 2019 · 2 min · jiezi

容器监控实践—Prometheus存储机制

概述Prometheus提供了本地存储,即tsdb时序数据库,本地存储给Prometheus带来了简单高效的使用体验,prometheus2.0以后压缩数据能力也得到了很大的提升。可以在单节点的情况下满足大部分用户的监控需求。但本地存储也限制了Prometheus的可扩展性,带来了数据持久化等一系列的问题。为了解决单节点存储的限制,prometheus没有自己实现集群存储,而是提供了远程读写的接口,让用户自己选择合适的时序数据库来实现prometheus的扩展性。Prometheus 1.x版本的TSDB(V2存储引擎)基于LevelDB,并且使用了和Facebook Gorilla一样的压缩算法,能够将16个字节的数据点压缩到平均1.37个字节。Prometheus 2.x版本引入了全新的V3存储引擎,提供了更高的写入和查询性能以下所有内容均基于prometheus2.7版本本地存储存储原理Prometheus按2小时一个block进行存储,每个block由一个目录组成,该目录里包含:一个或者多个chunk文件(保存timeseries数据)、一个metadata文件、一个index文件(通过metric name和labels查找timeseries数据在chunk文件的位置)。最新写入的数据保存在内存block中,达到2小时后写入磁盘。为了防止程序崩溃导致数据丢失,实现了WAL(write-ahead-log)机制,启动时会以写入日志(WAL)的方式来实现重播,从而恢复数据。删除数据时,删除条目会记录在独立的tombstone文件中,而不是立即从chunk文件删除。通过时间窗口的形式保存所有的样本数据,可以明显提高Prometheus的查询效率,当查询一段时间范围内的所有样本数据时,只需要简单的从落在该范围内的块中查询数据即可。这些2小时的block会在后台压缩成更大的block,数据压缩合并成更高level的block文件后删除低level的block文件。这个和leveldb、rocksdb等LSM树的思路一致。这些设计和Gorilla的设计高度相似,所以Prometheus几乎就是等于一个缓存TSDB。它本地存储的特点决定了它不能用于long-term数据存储,只能用于短期窗口的timeseries数据保存和查询,并且不具有高可用性(宕机会导致历史数据无法读取)。内存中的block数据未写入磁盘时,block目录下面主要保存wal文件:./data/01BKGV7JBM69T2G1BGBGM6KB12./data/01BKGV7JBM69T2G1BGBGM6KB12/meta.json./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000002./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000001持久化的block目录下wal文件被删除,timeseries数据保存在chunk文件里。index用于索引timeseries在wal文件里的位置。./data/01BKGV7JC0RY8A6MACW02A2PJD./data/01BKGV7JC0RY8A6MACW02A2PJD/meta.json./data/01BKGV7JC0RY8A6MACW02A2PJD/index./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks/000001./data/01BKGV7JC0RY8A6MACW02A2PJD/tombstones存储配置对于本地存储,prometheus提供了一些配置项,主要包括:–storage.tsdb.path: 存储数据的目录,默认为data/,如果要挂外部存储,可以指定该目录–storage.tsdb.retention.time: 数据过期清理时间,默认保存15天–storage.tsdb.retention.size: 实验性质,声明数据块的最大值,不包括wal文件,如512MB–storage.tsdb.retention: 已被废弃,改为使用storage.tsdb.retention.timePrometheus将所有当前使用的块保留在内存中。此外,它将最新使用的块保留在内存中,最大内存可以通过storage.local.memory-chunks标志配置。监测当前使用的内存量:prometheus_local_storage_memory_chunksprocess_resident_memory_bytes监测当前使用的存储指标:prometheus_local_storage_memory_series: 时间序列持有的内存当前块数量prometheus_local_storage_memory_chunks: 在内存中持久块的当前数量prometheus_local_storage_chunks_to_persist: 当前仍然需要持久化到磁盘的的内存块数量prometheus_local_storage_persistence_urgency_score: 紧急程度分数prometheus 2.0的存储升级prometheus 2.0于2017-11-08发布,主要是存储引擎进行了优化。性能的整体提高:与 Prometheus 1.8 相比,CPU使用率降低了 20% - 40%与 Prometheus 1.8 相比,磁盘空间使用率降低了 33% - 50%没有太多查询,平均负载的磁盘 I/O<1%在Kubernetes集群这样的动态环境中,prometheus的数据平面通常看起来是这种样式垂直维度表示所有存储的序列水平维度表示样本传播的时间如:requests_total{path="/status", method=“GET”, instance=“10.0.0.1:80”}requests_total{path="/status", method=“POST”, instance=“10.0.0.3:80”}requests_total{path="/", method=“GET”, instance=“10.0.0.2:80”}Prometheus定期为所有系列收集新数据点,这意味着它必须在时间轴的右端执行垂直写入。但是,在查询时,我们可能希望访问平面上任意区域的矩形(各种label条件)因此为了能够在大量数据中有效地查找查询序列,我们需要一个索引。在Prometheus 1.x存储层可以很好地处理垂直写入模式,但是随着规模增大,索引或出现一些问题,因此在2.0版本中重新设计了存储引擎和索引,主要改造是:样本压缩现有存储层的样本压缩功能在Prometheus的早期版本中发挥了重要作用。单个原始数据点占用16个字节的存储空间。但当普罗米修斯每秒收集数十万个数据点时,可以快速填满硬盘。但,同一系列中的样本往往非常相似,我们可以利用这一类样品(同样label)进行有效的压缩。批量压缩一系列的许多样本的块,在内存中,将每个数据点压缩到平均1.37字节的存储。这种压缩方案运行良好,也保留在新版本2存储层的设计中。具体压缩算法可以参考:Facebook的“Gorilla”论文中时间分片我们将新的存储层划分为块(block),每个块在一段时间内保存所有序列。每个块充当独立数据库。这样每次查询,仅检查所请求的时间范围内的块子集,查询执行时间自然会减少。这种布局也使删除旧数据变得非常容易(这在1.x的存储设计中是一个很耗时的操作)。但在2.x中,一旦块的时间范围完全落后于配置的保留边界,它就可以完全丢弃。索引一般prometheus的查询是把metric+label做关键字的,而且是很宽泛,完全用户自定义的字符,因此没办法使用常规的sql数据库,prometheus的存储层使用了全文检索中的倒排索引概念,将每个时间序列视为一个小文档。而metric和label对应的是文档中的单词。例如,requests_total{path="/status", method=“GET”, instance=“10.0.0.1:80”}是包含以下单词的文档:name=“requests_total"path="/status"method=“GET"instance=“10.0.0.1:80"基准测试cpu、内存、查询效率都比1.x版本得到了大幅度的提升具体测试结果参考:https://dzone.com/articles/pr…故障恢复如果您怀疑数据库中的损坏引起的问题,则可以通过使用storage.local.dirtyflag配置,来启动服务器来强制执行崩溃恢复。如果没有帮助,或者如果您只想删除现有的数据库,可以通过删除存储目录的内容轻松地启动:1.停止服务:stop prometheus.2.删除数据目录:rm -r <storage path>/*3.启动服务:start prometheus远程存储Prometheus默认是自己带有存储的,保存的时间为15天。但本地存储也意味着Prometheus无法持久化数据,无法存储大量历史数据,同时也无法灵活扩展。为了保证Prometheus的简单性,Prometheus并没有从自身集群的维度来解决这些问题,而是定义了两种接口,remote_write/remote_read,将数据抛出去,你自己处理。Prometheus的remote_storage 其实是一个adapter,至于在adapter的另一端是什么类型的时序数据库它根本不关心,如果你愿意,你也可以编写自己的adpater。如:存储的方式为:Prometheus —-发送数据—- > remote_storage_adapter —- 存储数据 —-> influxdb。prometheus通过下面两种方式来实现与其他的远端存储系统对接:Prometheus 按照标准的格式将metrics写到远端存储Prometheus 按照标准格式从远端的url来读取metrics远程读在远程读的流程当中,当用户发起查询请求后,Promthues将向remote_read中配置的URL发起查询请求(matchers,ranges),Adaptor根据请求条件从第三方存储服务中获取响应的数据。同时将数据转换为Promthues的原始样本数据返回给Prometheus Server。当获取到样本数据后,Promthues在本地使用PromQL对样本数据进行二次处理。远程写用户可以在Promtheus配置文件中指定Remote Write(远程写)的URL地址,一旦设置了该配置项,Prometheus将样本数据通过HTTP的形式发送给适配器(Adaptor)。而用户则可以在适配器中对接外部任意的服务。外部服务可以是真正的存储系统,公有云的存储服务,也可以是消息队列等任意形式。配置配置非常简单,只需要将对应的地址配置下就行remote_write: - url: “http://localhost:9201/write"remote_read: - url: “http://localhost:9201/read"社区支持现在社区已经实现了以下的远程存储方案AppOptics: writeChronix: writeCortex: read and writeCrateDB: read and writeElasticsearch: writeGnocchi: writeGraphite: writeInfluxDB: read and writeOpenTSDB: writePostgreSQL/TimescaleDB: read and writeSignalFx: write可以使用读写完整的InfluxDB,我们使用了多prometheus server同时远程读+写,验证了速度还是可以的。并且InfluxDB生态完整,自带了很多管理工具。容量规划在一般情况下,Prometheus中存储的每一个样本大概占用1-2字节大小。如果需要对Prometheus Server的本地磁盘空间做容量规划时,可以通过以下公式计算:磁盘大小 = 保留时间 * 每秒获取样本数 * 样本大小保留时间(retention_time_seconds)和样本大小(bytes_per_sample)不变的情况下,如果想减少本地磁盘的容量需求,只能通过减少每秒获取样本数(ingested_samples_per_second)的方式。因此有两种手段,一是减少时间序列的数量,二是增加采集样本的时间间隔。考虑到Prometheus会对时间序列进行压缩,因此减少时间序列的数量效果更明显。其他远程读写解决了Promtheus的数据持久化问题。使其可以进行弹性扩展。另外还支持联邦集群模式,用于解决横向扩展、网络分区的问题(如地域A+B+C的监控数据,统一汇总到D),联邦集群的配置将在后面的Promthues高可用文章中详细说明。附:kubecon2018上讲Prometheus 2.0的帅哥还有一本专门讲Prometheus的书:Prometheus: Up & Running(600多页…)国内没找到卖的,找到了一本英文pdf的,还在翻译理解中,有新的内容会继续同步在这个系列博客。。。又找到一本:https://www.prometheusbook.com/参考资料:https://prometheus.io/docs/pr…https://coreos.com/blog/prome...https://dzone.com/articles/pr...https://www.linuxidc.com/Linu...http://ylzheng.com/2018/03/06...https://www.cnblogs.com/vovli...https://files-cdn.cnblogs.com...https://www.bookstack.cn/read…本文为容器监控实践系列文章,完整内容见:container-monitor-book ...

March 12, 2019 · 1 min · jiezi

容器监控实践—Prometheus数据可视化

一. 概述Prometheus自带了一个web服务,包括一个默认的dashboard,可以使用表达式查询并进行图表可视化,默认服务的地址为:http://prometheus_ip:9090如下图:自带的web展示一般只用于表达式快速输入或者临时调试,因为默认服务没有鉴权,且图表表达能力有限,因此不会作为线上可视化方案,正式的监控数据可视化一般使用Grafana来配套prometheus可视化方案:自带web服务:在验证指标时是非常好用的,grafana虽然是作为可视化展示,但一般是先确认表达式,才去配置到grafana面板grafana可视化Console templates:官方给的一种选择,使用go templete来实现,使用难度较大,不太推荐promviz:开源项目,不算是监控图,可以做集群实时流量的可视化。二. Grafana可视化Grafana 是一个开源的图表可视化系统,简单说图表配置比较方便、生成的图表比较漂亮。并且模板众多,默认支持了prometheus作为数据源,也是prometheus官方推荐方案这里只对grafana做简单介绍,更多详细的内容参考展示-Grafana2.1 部署grafana是很成熟的(商业)项目,可以在官网下载客户端,或者在github主页自己build为镜像。主要的配置文件为conf文件夹下的defaults.ini文件,常用的配置可以配置在文件中,如果是docker运行或者在k8s中运行,可以使用env的方式,传入全局变量,将覆盖原有的defaults.ini配置。使用docker运行:docker run -d –name=grafana -p 3000:3000 grafana/grafana访问:http://127.0.0.1:3000账号:admin密码:admin2.2 配置第一步:配置数据源进入grafana后,第一步需要配置数据源,grafana默认支持prometheus作为数据源,因此Type直接选择PrometheusHttp的url地址为prometheus的服务地址,如果是同一个pod内,可以127.0.0.1:9090,不同pod的话,可以使用svc地址:http://prometheus.kube-system…:9090数据源配置后,点击save&test,可以验证数据源是否可用:第二步:配置面板:点击左侧的加号,可以添加面板(dashboard),并在该面板中添加各种类型的图表。对于面板,可以设置变量,用于下拉框筛选等场景,如设置机器变量:节点信息然后使用该变量,配置查询语句:得到各节点的cpu使用率面板demo配置完成后,可以出现类似图表,可以点击分享按钮,将本面板分享为json文件也可以筛选时间周期,设置自动刷新上图的json文件如下,仅供参考(需要安装node-exporter)json文件:https://raw.githubusercontent…本文为容器监控实践系列文章,完整内容见:container-monitor-book

March 12, 2019 · 1 min · jiezi

华尔街见闻基于istio的服务网格实践

距离2017年的见闻技术架构调整接近2年,随着业务线的发展,见闻技术部的项目数量、项目架构类型、基础设施规模、服务变更频率都在不断地增长,带给SRE的挑战是如何能更快地助力于开发人员更快更稳定地部署服务,保障线上服务的稳定。我们的后端开发团队仍然以Golang为主,不同业务线的技术选型不尽相同,同时存在Python,Java服务,这就需要SRE提供更易接入的微服务基础组件,常见的方案就是为每种语言提供适配的微服务基础组件,但痛点是基础组件更新维护的成本较高。为了解决痛点,我们将目光放到服务网格,它能利用基础设施下沉解决多语言基础库依赖问题,不同的语言不需要再引入各种不同的服务发现、监控等依赖库,只需简单的配置并运行在给定的环境下,就能享有以上功能,同时网络作为最重要的通信组件,可以基于它实现很多复杂的功能,譬如根据不同可用区进行的智能路由、服务熔断降级等。为此,我们调研了一些服务网格方案,包括Istio、Linkerd,基于我们的当前的后端架构特点:服务通信协议主要基于gRPC、HTTP基于Kubernetes的Docker部署拥抱开源,使用了Prometheus、Grafana作为监控,Zipkin作为链路追踪等对比下来,Istio拥有更多活跃的开源贡献者,迭代速度快,以及Istio架构可行性讨论,我们选择Istio作为实践方案。架构这张图介绍了见闻典型的服务网格架构,左半图介绍了一个用户请求是如何处理,右半图介绍运维系统是如何监控服务,若无特殊说明,服务都是部署在腾讯云托管Kubernetes。组件一览Go(1.11) 后端语言。Docker(17.12.1-ce) 容器技术。Kubernetes(1.10.5,托管于腾讯云容器平台) 容器编排工具。Istio(1.0.0) 服务网格开源方案,支持与Kubernetes集成。Ingress, Proxy(Istio 1.0.0)服务流量转发、智能代理,基于Envoy实现,Istio二次开发Proxy。Pilot Discovery(Istio 1.0.5)负责服务发现,通过监听Kubernetes中Service、Pod等资源维护服务映射表。Mixer Policy(Istio 1.0.5)管理服务之间访问权限,提供gRPC形式的Check接口。Mixer Telemetry(Istio 1.0.5)负责接收服务指标数据,提供gRPC形式的Report接口。Citadel负责管理代理证书。Dashboard 基于Kubernetes Dashboard二次开发的Istio Dashboard,负责管理Istio服务发布,配置变更等。Grafana 负责监控数据可视化。Prometheus 时序数据库,常用于监控系统。Jaeger 负责服务链路追踪,组件包括collector、Jaeger UI。Cassandra 分布式NoSQL数据库,用于Jaeger指标数据存储。用户请求分析我们先从用户请求端开始,用户的请求通过Tencent 4层LB转发到基于Envoy的Istio Ingress,Ingress根据配置将请求路由到Service A所在的PodService A所在Pod接收Ingress请求访问Service A的请求会先到达Proxy再由它转发到Service A进程Service A向Service B发出的请求被iptables路由到Proxy(下文会提到iptables的初始化)Proxy进程发起对Service B所在Pod的请求Proxy进程同步请求Mixer Policy服务,检查是否允许访问Service B,检查通过,开始请求Proxy进程记录请求的指标(QPS,Latency,Status Code分布等),异步并批量上报到Mixer Telemetry服务,这里是客户端指标。Service B所在Pod接收请求Service B Proxy接收请求并路由到Service B所在进程Proxy进程记录请求的指标(QPS,Latency,Status Code分布等),异步并批量上报到Mixer Telemetry服务,这里是服务端指标。Service B进程处理完请求并返回数据原路返回到用户端以上的流程可以观察到,服务之间通信完全依靠Proxy进程完成,Proxy进程接管同一个Pod中服务的出入流量,完成请求的路由。架构可行性通过架构图以及以上流程,我们拆分出以下关键组件,观察其性能、可用性、拓展性。Istio Ingress高性能,可拓展Istio Ingress用来处理用户入流量,使用Envoy实现,转发性能高。挂载在负载均衡后,通过增加实例实现可拓展。Istio Proxy随应用部署,轻微性能损耗,可随应用数量拓展Istio Proxy以Sidecar形式随应用一起部署,增加2次流量转发,存在性能损耗。性能: 4核8G服务器,上面运行Proxy服务和API服务,API服务只返回ok字样。(此测试只测试极限QPS)单独测试API服务的QPS在59k+,平均延时在1.68ms,CPU占用4核。通过代理访问的QPS7k+,平均延时14.97ms,代理CPU占用2核,API服务CPU占用2核。CPU消耗以及转发消耗降低了QPS,增加了延时,通过增加机器核数并增加服务部署数量缓解该问题,经过测试环境测试,延时可以接受。可用性:基于Envoy,我们认为Envoy的可用性高于应用。依赖Pilot Discovery进行服务路由,可用性受Pilot Discovery影响。拓展性:Sidecar形式,随应用数拓展Istio Policy服务可拓展,但同步调用存在风险Istio Policy需要在服务调用前访问,是同步请求,会增加服务调用延时,通过拓展服务数量增加处理能力。属于可选服务,见闻生产未使用该组件。性能: 未测试可用性:若开启Policy,必须保证Policy高可用,否则正常服务将不可用拓展性:增加实例数量进行拓展Istio Telemetry监控收集服务性能: 从监控上观察Report 5000qps,使用25核,响应时间p99在72ms。异步调用不影响应用的响应时间。可用性:Telemetry不影响服务可用性拓展性:增加实例数量进行拓展Pilot Discovery性能: 服务发现组件1.0.5版本经过监控观察,300个Service,1000个Pod,服务变更次数1天100次,平均CPU消耗在0.01核,内存占用在1G以内。可用性: 在服务更新时需要保证可用,否则新创建的Pod无法获取最新路由规则,对于已运行Pod由于Proxy存在路由缓存不受Pilot Discovery关闭的影响。拓展性:增加实例数量可以增加处理量。可以看到各个组件的可用性、拓展性都有相应的策略达到保障,我们认为Istio是具有可实施性的。Istio流量控制背后Pilot Discovery: Istio的交通大脑Pilot Discovery负责Istio服务发现,支持在Kubernetes里部署,它读取K8S资源配置,并生成Proxy可用的路由表。以下面的Service A服务为例,介绍Istio如何进行精细路由。Discovery与对应K8S集群的API server相连,拉取全量资源信息,并使用Watch方法对增量变更进行同步。根据Service A的配置,生成对应Service A的路由配置,通过gRPC形式的ADS接口提供给Proxy。Proxy同步到最新配置,热更新后配置生效。要知道如果在Istio访问一个服务,必须得声明K8S Service。Istio通过K8S CRD拓展K8S已有的服务访问能力,我们列举网络相关常用的配置:Gateway控制Istio Ingress的路由转发及TLS证书绑定。VirtualService服务流量控制,实现如A/B测试、错误注入、服务保护等。DestinationRule用于目标服务的版本管理,根据Pod的Label区分目标服务的版本,联合VirtualService进行流量控制。以下举个例子介绍如何利用它们配置同样大小流量到服务的不同版本,# serviceA.yamlkind: ServiceapiVersion: v1metadata: name: serviceA labels: app: serviceAspec: ports: - name: http-8080 protocol: TCP port: 8080 targetPort: 8080 selector: app: serviceA type: ClusterIP # virtualServiceA.yamlapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: serviceAspec: hosts: - serviceA http: - route: - destination: host: serviceA subset: v1 - route: - destination: host: serviceA subset: v2 —# destinationRuleapiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata: name: serviceAspec: host: serviceA subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2以上实现了Istio服务调用serviceA时,会随机地50%概率到serviceA的v1版本,50%概率到serviceA的v2版本。可以看到,VirtualService通过hosts关联serviceA,在http区域有两个route,分别是subset v1, subset v2,v1,v2依赖DestinationRule来定义,同样用host来标注该DestinationRule控制哪个host的访问,以及通过pod label中version来划分不同版本。流量控制方面,Istio有相当丰富的功能支持,同时也带来了相当的复杂度,建议用户根据日常的使用频率在后台实现相应的前端控制台,利用自动化来完成流量控制。Proxy工作机制自动注入在K8S 1.9之后的版本,Istio利用K8S提供的MutatingAdmissionWebhook在K8S创建Pod前回调Istio提供的istio-sidecar-injector动态修改Pod配置,添加以Sidecar形式运行的Proxy。这里开启自动注入有两个维度,一是namespace,namespace需要添加istio-injection : enabled标签,这样实现该namespace下的所有Pod自动注入Proxy;二是deployment可以设置annotation关闭自动注入。如果K8S版本不够,可以利用命令行工具修改Deployment的配置。接管Pod流量Service A所在Pod至少运行Service A应用容器以及用于代理的Envoy容器,创建Pod时proxy-init命令负责获取Pod监听的端口和具体协议,以此初始化网络,利用iptables将容器网络出入流量都转发到Proxy监听的localhost端口。 若Service A的Pod声明servicePort为8080:HTTP,最终Proxy将会接收8080端口的Pod入流量和全部的Pod出流量。服务发现Proxy基于Envoy,与Pilot Discovery连接,动态同步Kubernetes集群中所有的服务信息:服务与Pod IP、端口之间的映射表,通过路由信息实现智能路由,从而使服务发现从业务代码中剥离。链路追踪Proxy支持设置Zipkin URL,异步上报链路追踪数据。服务质量监控Proxy将属性包上报给Telemetry服务,Telemetry根据用户的配置生成指标数据并由Prometheus收集。适配Istio我们目前的服务部署在腾讯云托管Kubernetes,节点使用16核32G的网络增强型机器,所有的后端服务都以Docker部署,K8S集群外部署高可用ETCD支持集群内服务发现,数据库以MySQL、Cassandra、MongoDB为主,消息队列采用Kafka、NSQ。在应用Istio的过程中,我们对基础库进行了修改,删减了Istio已提供的功能并完成了对Istio的适配。前情提要见闻旧后端服务架构,所有Golang服务以打包成Docker镜像,以"gRPC"协议通信。去"框架"见闻Golang后端使用go-micro框架,一个支持多插件的Golang微服务框架,作者将组件分成transport,server,client,registry,codec等,通过组合不同类型的组件非常灵活地配置微服务技术栈。对于有定制需求的微服务架构,是值得推荐的选择。通信协议作为服务互通的基石,Istio对gRPC和HTTP非常友好,根据协议Istio能解析HTTP头中的信息,支持提取指标以供分析。go-micro只是利用HTTP和gRPC作为通信协议,但是协议的解析逻辑是协议无关的,所以可以说它只是用了这些通信协议的外壳,传输的报文内容是"micro方言",这就导致了Golang暴露的服务无法被其它语言其它框架调用。为了将协议能在多语言中完全统一,也为了更好地使用Istio的监控统计功能,这个时候我们开始对go-micro的存留有一些新的思考,我们是否还需要go-micro?经过近2年的生产实践,我们是不是可以更精简我们的框架?经过这些思考过后,我们的决定是去go-micro框架,拥抱更轻量级的基础框架,这个框架只要支持:gRPC纯原生即可Istio支持Istio的基础功能,譬如一些HTTP header转发等改动尽量小我们已经存在上百个Golang项目,避免改动Golang项目代码,将改动放到基础库为佳go-micro通过定义自制protobuf插件的方式在stub代码中集成框架功能,经过对逻辑的梳理,我们决定复写protobuf插件,生成兼容micro的stub代码,通过对micro接口的向后兼容,开发人员不需要修改代码,只需要在CI阶段运行protoc即时生成新版代码。详情可见再见,micro运维流程右半图描述运维人员如何利用运维后台运维Kubernetes集群,Istio的运维必须有自动化的工具来减少人工配置带来的错误,见闻的旧运维后台基于腾讯云容器平台暴露的开放API,在引入Istio后,功能依赖于更细节的label以及CRD(Custom Resource Definition),于是得依托更细粒度的Kubernetes API,新的后台需要能完成基本的Kubernetes运维,而且结合Istio的实际进行日常更新,经过选型,见闻基于Kubernetes Dashboard二次开发了Istio部分的一些功能(APP部署、更新,Istio配置更新等),利用Istio Dashboard实现APP创建、部署接口,并由此重构原有的运维后台。最终,SRE提供两个后台,精细控制的Istio Dashboard;提供给开发人员日常更新使用的简化版后台。服务发布日常最重要、最高频的功能,服务版本变更。服务创建服务创建包括对老服务的改造,一个K8S服务要经过一些配置上的更新才能成为Istio APP。一个Kubernetes服务需要满足以下要求来获得Istio的功能支持:Service资源声明服务监听的端口号以及协议这里的服务端口声明中name字段值需要以协议名为起始值,譬如grpc、http、tcp、udp等,istio识别前缀,用于初始化Proxy,譬如grpc-svc,http-svc,不正确的端口命名会引起Proxy的异常行为,以及监控服务无法捕获该协议下的指标。服务探活接口每个后端服务提供一个HTTP探活接口,这样服务启动时,不至于让其它服务访问到未就绪的状态。对于HTTP探活接口的定义包括Proxy以及APP是否初始化完成,见闻的实践是在基础镜像中打入一个探活程序:检测Proxy是否初始化通过Proxy的配置同步时间与Pilot Discovery的配置更新时间对比,相同时认为其就绪。APP自定义接口APP可以在指定端口提供就绪API。# serviceA.yamlkind: ServiceapiVersion: v1metadata: name: serviceA namespace: default labels: app: serviceAspec: ports: - name: grpc protocol: TCP port: 10088 targetPort: 10088 selector: app: serviceA type: ClusterIPDeployment资源要求有必要的两个label:app和version,明确定义流量控制中的目标服务。可以看例子中deployment的app为serviceA,version为v1。声明对外服务的端口,要求Proxy对指定端口入流量的接管。例子中ports声明了10088端口。# deploymentA.yamlkind: DeploymentapiVersion: extensions/v1beta1metadata: name: serviceA-v1 labels: app: serviceA version: v1spec: replicas: 1 selector: matchLabels: app: serviceA version: v1 template: metadata: labels: app: serviceA version: v1 spec: containers: - name: serviceA image: ‘some-image’ ports: - containerPort: 10088 protocol: TCP resources: requests: cpu: 1000m livenessProbe: httpGet: path: /health port: 54321 scheme: HTTP initialDelaySeconds: 1 timeoutSeconds: 2 periodSeconds: 5 successThreshold: 1 failureThreshold: 3 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: Always securityContext: privileged: false restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst符合以上要求,服务能正确接入Istio系统并获得服务发现和监控的能力。服务更新Istio提供流量控制,给运维带来方便的A/B测试,用于根据指定规则迁移流量。见闻的服务更新依靠Istio流量迁移功能,发布服务的新版本,并将流量通过Istio规则迁移到新版本,实际细节如下:更新流量控制将流量指向已有版本以下实例利用VirtualService将ServiceA的服务流量全部指向已存在的v1版本# virtualServiceapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: serviceAspec: hosts: http: - route: - destination: host: serviceA subset: v1—# destinationRuleapiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata: name: serviceAspec: host: serviceA subsets: - labels: version: v1 name: v1```部署新版本的Deployment查找符合app label的deployment,运维人员基于该deployment创建v2版本的deployment,并向destinationRule中增加v2版本。# destinationRuleapiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata: name: serviceAspec: host: serviceA subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2更新流量控制将流量指向新版本以下实例利用VirtualService将ServiceA的服务流量全部指向v2版本# virtualServiceapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: serviceAspec: hosts: - serviceA http: - route: - destination: host: serviceA subset: v2下线v1版本的deployment,删除DestinationRule中的v1使用Istio Dashboard来实现上述流程Ingress配置为什么使用Istio Ingress作为新的Ingress方案?过去我们使用腾讯云托管的Kubernetes Ingress,为了对Ingress流量控制而引入Istio Ingress。我们之前提到Istio Ingress是基于Envoy,它读取Istio控制的配置进行路由,与其它内部服务一样方便地接入Istio所有功能。除了VirtualService和DestinationRule,Istio定义了Gateway来控制实例支持的Host和证书。具体的流程是:创建Istio Ingress提供的Deployment和Service创建Deployment ingressgateway时,以ConfigMap的形式挂载Ingress需要的证书。配置Gateway配置Ingress接收具体域名(如wallstreetcn.com)的流量,以及对应的TLS证书位置,这里的证书路径已经挂在到Ingress的Deployment上。以下是一个典型的Gateway配置。apiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata: name: wallstreetcn-com namespace: istio-systemspec: selector: istio: ingressgateway servers: - hosts: - wallstreetcn.com port: name: http number: 80 protocol: HTTP - hosts: - wallstreetcn.com port: name: https number: 443 protocol: HTTPS tls: mode: SIMPLE privateKey: /etc/istio/ingressgateway-certs/tls.key serverCertificate: /etc/istio/ingressgateway-certs/tls.crt配置完成后,再配合VirtualService的路由控制,控制Ingress的反向代理到default命名空间下的gateway服务80端口,如下所示:apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: wallstreetcn-com namespace: istio-systemspec: gateways: - wallstreetcn-com hosts: - wallstreetcn.com http: - route: - destination: host: gateway.default.svc.cluster.local port: number: 80监控指标Istio支持Prometheus拉取集群指标,并提供Grafana看板展示。这里建议初期使用Istio自带的Grafana看板配置,并且注意Kubernetes主机的类型划分,Prometheus服务适合放在内存型机器。可以与Dashboard集成,在发布服务过程中即时查看指标。服务质量Istio自带一些默认的Grafana面板,统计所有可以被访问的HTTP/gRPC服务的返回码以及延时情况。对于返回码,认为5xx为错误,并在面板上使用label_join((sum(rate(istio_requests_total{reporter=“destination”, response_code!~“5.”}[1m])) by (destination_workload, destination_workload_namespace) / sum(rate(istio_requests_total{reporter=“destination”}[1m])) by (destination_workload, destination_workload_namespace)), “destination_workload_var”, “.”, “destination_workload”, “destination_workload_namespace”)计算服务错误率。对于延时情况采用histogram_quantile获取多维度p50、p90、p95、p99的延时分布。链路追踪之前提到Proxy由Envoy实现,Envoy支持设置Zipkin上报API,Proxy在收发请求时将链路指标上报到Zipkin,为了实现链路追踪,Proxy在流量转发中解析协议中的HTTP或gRPC请求头,找出其中的追踪头,组装成指标。所以应用端需要在收到调用方请求时解析出请求头,并持续携带该请求头向后传递。由于见闻在Ingress之后映射一个HTTP gateway,请求从Ingress转发到HTTP gateway,再发送到后续的gRPC服务,所以HTTP gateway有段代码生成gRPC请求头。import ( “github.com/labstack/echo” gmeta “google.golang.org/grpc/metadata”)// Create a gRPC context from Echo.func NewContextFromEcho(ec echo.Context) context.Context { md := gmeta.MD{} for _, header := range []string{ “x-request-id”, “x-b3-traceid”, “x-b3-spanid”, “x-b3-parentspanid”, “x-b3-sampled”, “x-b3-flags”, “x-ot-span-context”, } { md.Set(header, ec.Request().Header.Get(header)) } md.Set(“x-b3-parentspanid”, ec.Request().Header.Get(“x-b3-spanid”)) return gmeta.NewOutgoingContext(context.Background(), md)}在后续的gRPC服务调用中使用该Context,至于gRPC服务之间的调用,我们发现会自动将context传递到下一个服务,所以没有做类似处理。这里追踪的数据如果全量捕获将会是非常大的,并且对于监控来说也不必要,所以可以设置抽样率,Istio提供ConfigMap中设置抽样率,一般来说设置成1%即可。实践中的宝贵经验在Istio实践过程中,有哪些需要注意的问题。API server的强依赖,单点故障Istio对Kubernetes的API有很强的依赖,诸如流量控制(Kubernetes资源)、集群监控(Prometheues通过Kubernetes服务发现查找Pod)、服务权限控制(Mixer Policy)。所以需要保障API server的高可用,我们曾遇到Policy组件疯狂请求Kubernetes API server使API server无法服务,从而导致服务发现等服务无法更新配置。 为避免这种请求,建议使用者了解与API server直接通信组件的原理,并尽量减少直接通信的组件数量,增加必要的Rate limit。* 尽量将与API server通信的服务置于可以随时关闭的环境,这是考虑如果部署在同一Kubernetes集群,如果API server挂掉,无法关闭这些有问题的服务,导致死锁(又想恢复API server,又要依靠API server关闭服务)服务配置的自动化服务配置是Istio部署后的重头戏,避免使用手动方式更改配置,使用代码更新配置,将常用的几个配置更新操作做到运维后台,相信手动一定会犯错的事实。关于Pilot DiscoveryPilot Discovery 1.0.0版本有很大的性能问题,1.0.4有很大的性能提升,但引入了一个新bug,所以请使用1.0.5及以上的版本,该版本在见闻的平均CPU负载从10核降到了0.5核,大大降低了Proxy同步配置的延时。关于Mixer Policy 1.0.0这个组件曾导致API server负载过高(很高的list pods请求),所以我们暂时束之高阁,慎用。性能调优在使用Proxy、Telemetry时,默认它们会打印访问日志,我们选择在生产上关闭该日志。时刻观察Istio社区的最新版本,查看新版本各个组件的性能优化以及bug修复情况,将Istio当做高度模块化的系统,单独升级某些组件。上面就提到我们在Istio1.0的基础上使用了1.0.5版本的Policy、Telemetry、Pilot Discovery等组件。服务平滑更新和关闭Istio依靠Proxy来帮助APP进行路由,考虑几种情况会出现意外的状态:* APP启动先于Proxy,并开始调用其它服务,这时Proxy尚未初始化完毕,APP调用失败。* Service B关闭时,调用者Service A的Proxy尚未同步更新Service A关闭的状态,向Service B发送请求,调用失败。第一种情况要求APP有重试机制,能适当重试请求,避免启动时的Proxy初始化与APP初始化的时差。第二种情况,一种是服务更新时,我们使用新建新服务,再切流量;一种是服务异常退出,这种情况是在客户端重试机制。希望使用Istio的开发人员有更好的解决方案。下一步计划见闻Istio化已于去年10月份完成并上线,我们的线上集群中Istio和非Istio的APP混合部署,上千的Pod数量曾对不够健壮的服务发现组件造成巨大的压力,在这期间曾遇到Istio的一些惊喜,并不断总结经验,希望给之后使用Istio的同学一些借鉴。之后的过程中,SRE的目标依然是保障线上服务的健壮性。Istio Dashboard优化APP部署流程,考虑自动部署的功能,通过服务指标自动完成灰度发布和流量迁移。PrometheusPrometheus的高可用、可拓展方案的探索。 ...

March 12, 2019 · 3 min · jiezi

CNCF终端用户合作伙伴峰会(仅限终端用户)

CNCF终端用户合作伙伴峰会(仅限终端用户)活动时间:6月24日星期一, 9:30 – 16:30活动价格:人民币150元(将捐赠于多元化奖学金)CNCF终端用户合作伙伴峰会将云原生用户聚集在一起,来分享最佳实践和经验。峰会日程将从终端用户介绍他们的故事,并分享战胜挑战和在不同行业采用云原生的旅程开始。之后以非会议(unconference)的形式,使参会者与同行会面并学习如何参与和为云原生社区做出贡献。您的机构必须是CNCF终端用户社区(https://www.cncf.io/people/en…)的成员才能参加。终端用户成员最多可购买四张票,终端用户支持者最多可购买两张票。如有任何问题,请联系Cheryl Hung,chung@linuxfoundation.org。如何注册:您可以在您KubeCon + CloudNativeCon + Open Source Summit的注册表中申请此活动,点击此处添加。在您将此申请添加成功后,我们会对您的申请进行审核。如您通过审核,您将会收到一个付款链接,您须在支付成功并收到确认信后才能参加此活动。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!CNCF邀请你加入最终用户社区

March 12, 2019 · 1 min · jiezi

Kubernetes安全三步谈:三种方法保护Kubernetes免受内部威胁

这是关于Kubernetes安全系列三篇文章中的第二篇。在上篇文章中我们分享了如何确保企业的Kubernetes集群免受外部攻击,这篇文章中我们将分享三种保护Kubernetes免受内部威胁的方法,后续我们还想介绍如何处理资源消耗或noisy neighbor问题。本质上讲,Kubernetes集群是多用户的。因此,组织通常希望通过RBAC(基于角色的访问控制)、逻辑隔离和网络策略来确保交叉通信受到保护。像Kubernetes这样的容器编排系统将开发人员和运维人员(DevOps)更紧密地联系在一起,使团队更容易有效地相互协作。诚然,我们相信DevOps团队的大多数成员不会存在什么恶意企图,但是,组织仍然需要确保,如果应用程序之间存在交叉通信,并且如果有人编写了错误代码,我们能够将损失控制在最小。01 基于角色的访问控制减轻对容器的恶意威胁与保护物理服务器,这两者的策略不同。然而,无论系统管理员是在数据中心部署了多个服务器,还是在Kubernetes中部署了虚拟集群,基于角色的访问控制(RBAC)都是一项至关重要的安全举措。Rancher Labs的高级解决方案架构师Adrian Goins说,“在内部,你希望有某种基于角色的访问控制,遵循最低特权的规则。”Rancher Labs为Kubernetes开发了一个完整的容器管理平台Rancher。“你只允许用户和服务账户访问他们需要访问的资源,而且访问权限只适用于他们需要做的任何事情。”这种访问控制向下扩展到无需使用root权限来运行容器进程。Rancher与RBAC的多个后端提供者交互,简化了Kubernetes用户的流程。例如,系统管理员可以部署Rancher并去到authentication选项卡,将其组织的Microsoft Active Directory数据导入到Kubernetes中。Rancher会立即从Activate Directory中提取所有用户和组,这些组现在可以在角色中使用,然后应用于Rancher管理的所有集群。通常情况下,管理员必须手动配置这些角色,并在每个集群中复制它们。对于一个拥有一到两个集群的组织来说,这可能不是什么问题,但是如果一个公司拥有数十个、数百个或更多集群,那么人为错误的可能性非常高。总有一些东西会遗漏,其后果可能是灾难性的。通过Rancher,管理员可以跨集群将角色集中化,drill down以让用户访问只能执行特定任务的特定集群。如果有员工离职了,只需要停用Active Directory中他们的账户就行,一切都非常简单。完成此操作后,被停用的账户会立刻失去访问每个集群的权限。因为Rancher充当了每个集群的身份验证代理,管理员不再需要为部署集群所在的每个提供者提供或管理账户。02 使用命名空间进行逻辑隔离此外,部署到集群的应用应该使用命名空间,将资源进行逻辑隔离后,管理员可以给它们附加安全策略。命名空间可以给集群资源分段,并且包括它们所包含的pod的配额以及默认资源限制。尽管命名空间最初的目的是用于跨多个团队或项目的多用户环境,但现在它已经是公认的集群内的最佳标准实践了。默认情况下,在Kubernetes中,没有任何东西可以阻止拥有容器的两个不同团队进行对话。但是,Kubernetes的RBAC功能就能限制这种通信。“我们可以说,我的命名空间中的容器只能够与同一命名空间内的容器通信,而不允许与其他命名空间中的容器通信。”Goins说,此外,“可以这么说,作为用户,我只允许与我自己的命名空间对话,而你作为用户,你也只允许和自己的命名空间对话。这是工作负载层面以及用户层面的安全性。如果操作正确,用户甚至无法看到另一个工作负载的存在。”这是Kubernetes的功能之一——单个集群中的多租户。但是,Rancher对命名空间功能进行了进一步拓展,整合了“项目”资源,以帮助减轻集群的管理负担。在Rancher中,项目(Projects)允许管理员在单个实体下收集多个命名空间。在Kubernetes的基础版本中,RBAC或集群资源等特性被分配给各个命名空间。在有些Kubernetes集群里,多个命名空间需要相同的访问权限,而手动将这些权限分配给每个命名空间,可以说是一项乏味的任务。即使所有命名空间都需要相同的权限,也无法保证在一个操作中能将这些权限应用于所有命名空间。Goins指出,管理员必须重复地将这些权限分配给每个命名空间。而Rancher的Project概念,让管理员可以在项目层级分配资源和访问权限,从而解决了上述问题。然后项目中的每个命名空间继承这些资源和策略,因此管理员只需将它们分配给项目一次,而不是将它们分配给每个命名空间。通过Project,管理员可以执行很多操作,例如为用户分配访问一组命名空间的权限、为用户分配项目中的特定角色、为项目分配资源、分配pod安全策略等等。03 NetworkPolicy资源NetworkPolicy是一种Kubernetes资源,用于配置pod(具有共享存储和网络资源的一个或多个容器的逻辑组)如何相互通信或如何与其他网络端点通信。默认情况下,pods是非隔离的,这意味着它们会接受来自任何来源的流量。Goins解释说:“NetworkPolicy就像Kubernetes集群上运行的pods之间基于软件的防火墙。管理员可以为命名空间创建‘默认’隔离策略,方法是先创建一个NetworkPolicy,选择所有pods,但不允许向这些pods发送任何传入或传出的流量。”此外,管理员可以配置哪些pods可以彼此连接。这些策略可以再进一步详细描述,让管理员可以指定哪些命名空间可以通信,或者选择端口号来执行每个策略。NetworkPolicy资源需要支持配置的网络后端,如Calico、Canal、Romana或Weave。根据Kubernetes文档,简单地创建资源而没有控制器来实现它是没有效果的。04 防范内部威胁尽管有一些默认工具可以保护Kubernetes安全,但其中许多工具似乎只是为了防止外部威胁到集群。更有甚者,它们甚至很难进行扩展。若企业想要保护集群不受内部威胁(无论是来自实际的恶意内部威胁,还是仅仅是防止错误或错误编码传播)时,防御的手段非常少。不过所幸的是,有一些解决方案已经着眼于保护集群免受未经授权的内部访问。其中一些存在于Kubernetes框架中,比如命名空间,而Rancher的Project则在默认设置之上还有进一步扩展,以便对整个企业环境进行更精确的管理和控制。关键的是,不要在内部资源的网络安全问题上感到放弃或者气馁。遵循本文的三个步骤,您依然可以在严格控制内部访问保护的同时获得使用Kubernetes集群最高效率。下篇文章将是本系列文章的最后一篇,我们将来看看如何处理资源限制的问题,如何防止用户过度消耗Kubernetes资源。

March 12, 2019 · 1 min · jiezi

灵雀云CTO陈恺:从“鸿沟理论”看云原生,哪些技术能够跨越鸿沟?

历史进入2019年,放眼望去,今天的整个技术大环境和生态都发生了很大的变化。在己亥猪年春节刚刚过去的早春时节,我们来梳理和展望一下整个云原生技术趋势的发展,是一件很有意义的事情,这其中有些变化在不可避免地影响着我们身处其中的每一家企业。如果说云原生在2017年还仅仅是冒出了一些苗头,那么2018可以说是普及之年,云原生变成了一个成熟的、被普遍接受的理念。灵雀云作为云原生理念的拥趸,也不断顺应这种趋势,聚焦云原生的核心场景,围绕容器平台、DevOps和微服务黄金三角进行产品的研发和业务场景的落地。早在1991年Jeffery Moore针对高科技行业和高科技企业生命周期的特点,提出了著名的“鸿沟理论”。这个理论基于“创新传播学”,将创新性技术和产品的生命周期分为五个阶段:创新者(Innovator)、早期使用者(Early adopters)、早期大众(Early majority)、晚期大众(Late majority)、落后者(Laggard)。在Early adopters和Early majority之间有个巨大的鸿沟(Chasm),每个新技术都会经历鸿沟,大多数失败的产品也都是在鸿沟里结束了其整个生命周期,能否顺利跨越“鸿沟”,决定了创新性技术的成败。今天我们尝试以鸿沟理论为基础来分析云原生领域颠覆性的创新技术。“Kubernetes is Boring”,边缘创新有亮点Kubernetes在2017年底成为容器编排事实标准,之后以其为核心的生态持续爆发,在传播周期上可以说已经跨过鸿沟了,进入Early majority早期大众阶段,开始占领潜力巨大的主流市场。根据CNCF在2018年8月进行的第六次测量容器管理市场的温度,83%的受访者更喜欢Kubernetes的容器管理工具,58%的受访者在生产中使用Kubernetes,42%的受访者正在进行评估以备将来使用,40%的企业(员工规模在5000 )正在使用Kubernetes。Kubernetes在开发人员中已经变得非常流行。回过头来看,灵雀云从早期全力投入Kubernetes技术栈,是最早进行Kubernetes产品化的厂商。我们并未满足于把Kubernetes当作一个容器编排工具来使用,而是将它定位成构建上层平台的核心框架,通过合理运用Kubernetes本身的扩展机制、架构模式与API规范,构建出一系列“Kubernetes原生”的产品体系。这样做不仅真正发挥出Kubernetes作为云计算核心框架的最大优势,也可以与以Kubernetes为核心的云原生生态无缝集成。进入主流市场的Kubernetes开始变得“Boring”,这很正常,甚至是一个好的现象。核心项目的创新速度会减慢,最新的版本中主要关注点聚焦在稳定性、可扩展性这些方面,尽可能把代码从主库往外推,让它的主库变得干净,其他功能通过一些扩展机制来做,同时开始关注安全性。Kubernetes项目本身已经过了现象级创新爆发的阶段,但由Kubernetes独特的架构属性催生出的周边生态的二次创新仍然在高速发展,例如诸多与Kubernetes集成或者基于Kubernetes框架开发的上层服务与平台。这个话题我们下次讨论,今天还是主要关注与Kubernetes项目关联最紧密的创新亮点:早期容器化workload大多聚焦在无状态服务,跑的最多的是Nginx,而对有状态应用避讳不谈。现在Kubernetes进入主流市场,显然需要对“现实中的应用”,包括有状态服务提供良好的支持。2019年,对于复杂应用的管理以及Kubernetes本身的自动化运维将会更多的表现为Operator。Operator是基于Kubernetes扩展机制,将运维知识编写成“面向应用的Kubernetes原生控制器“,从而将一个应用的整体状态作为API对象通过Kubernetes进行自动化管理。这个应用通常来说是比较复杂的有状态应用,如MySQL数据库、Redis集群、Prometheus等等。现在基本上常见的有状态应用都有自己相对应的Operator,这是一种更为有效的管理分布式应用的方式。其次是应用跨集群部署与管理。早期社区里有Federation联邦集群的方案。我们不少大金融客户都有跨集群部署、管理业务的需求。当时深入研究Federation v1之后,觉得这个方案复杂度高,观点性强,对于我们实际的需求灵活度不足而又不够成熟。所以我们最终选择自研跨集群部署。后来出现的Federation v2在设计方向上有不小改观,是我们持续关注的项目。早期采用容器技术的用户都会尽可能兼容企业原有的IT基础设施,比如底层物理机,保留物理机之上的虚拟层,虚拟机之上再跑容器。当然,面向资源管理的硬件虚拟化和面向应用的容器化本质上没有冲突。随着Kubernetes的普及并且在应用上超越了容器编排的范畴,后Kubernetes时代如何搭建管理基础设施是值得思考的。我们也观察到一些有意思的趋势,比如在Kubernetes上同时管理容器和虚拟机(所谓的“容器原生虚拟化”),或是使用Kubernetes来管理OpenStack。总之,Kubernetes在云计算领域成为既定标准,会越来越多的往下管理所有种类的基础设施,往上管理所有种类的应用。这类标准的形成对于技术社区有很大的益处,会大大降低围绕Kubernetes技术投入的风险。因此,我们会看到越来越多的周边技术向它靠拢,在Kubernetes之上催化出一个庞大的云原生技术生态。DevOps独辟蹊径:开放式DevOps工具链集成与编排DevOps理念、方法论和实践已经走到了Early Majority早期大众阶段,是已被实践证实的高效开发运维方法。做容器的厂商都经历过用容器搞CI/CD,灵雀云也不例外,CI/CD是容易发挥容器优势的显而易见的使用场景。在去年,我们做了重大的产品升级,将原来的CI/CD功能模块扩展为完整的DevOps产品—Alauda DevOps平台,覆盖应用全生命周期。DevOps包含好几层概念,首先是组织文化的转变,然后涉及到一系列最佳实践,最终这些最佳实践需要用工具去落地。我们在帮助很多大型企业客户落地DevOps的过程中发现:在DevOps的整个流程里涉及到很多类别的工具,每一个类别都会有大量的选择;2. 每个客户的工具选型多少会有些不同,并不存在一个固定的、完全标准的工具组合;3. 随着时间的推移工具选择会发生变化,多数客户意识到目前使用中的工具在未来很可能会被替代。基于这些观察,Alauda DevOps的定位并不是要提供一个新的DevOps产品,去取代客户已有的工具选型。相反,我们致力于打造一个开放式的DevOps工具链集成与编排平台。这个平台可以灵活的兼容客户的工具选型,通过集成将各类工具串联起来,形成一套工具链,通过编排让DevOps工具链与容器平台联动,形成一个完整系统。同时,不断结合自身的经验,提炼DevOps落地的最佳实践,平台将这些最佳实践自动化,作为服务进行输出。这个思路在和客户的交流以及实际落地过程中不断获得认可。值得一提的是,我们对于DevOps工具链的编排也是基于Kubernetes来实现的。Kubernetes不仅是出色的容器编排工具,扩展之后也很适合编排DevOps工具。换句话说,我们开发了一套“Kubernetes原生的DevOps平台”。微服务:落地需要一套完整的基础设施提起微服务治理,很多人会条件反射般的联想到某些特定的技术,例如Spring Cloud,或者Service Mesh。我们不妨先退后一步,系统考虑下企业微服务架构改造和落地所需要的完整的基础设施。首先,在微服务应用的底层需要一个应用管理平台,这在今天毋庸置疑是一个基于Kubernetes的容器平台。微服务本质上是分布式应用,在我们获取敏捷性的同时不可避免的增加了运维和管理的难度。微服务对自动化运维,尤其是可观测性的要求很高。支持微服务架构的基础设施必须具备完善的监控、告警、日志、分布式追踪等能力。在微服务应用的前方,通常需要一个API网关,来管理对外暴露的API。API治理策略,包括安全、路由、流控、遥测、集成等对于任何应用平台都重要,但在微服务架构下尤为关键。我们需要通过定义、封装对外API来屏蔽应用内微服务组件结构细节,将客户端与微服务解耦,甚至为不同客户端提供个性化的API。云原生应用的一大准则是应用与状态分离。在微服务架构下,每个微服务组件更是应该完全掌控自己的数据。所以,云原生应用通常依赖外部数据服务(Backing Services),而在微服务架构下,多元化持久性(Polyglot Persistence)是常态,也就是说一个微服务架构的应用会依赖非常多种类的 Backing Services。面向微服务架构的基础设施需要将这些外部服务暴露给微服务应用消费,甚至直接支撑各类Backing Services 的部署和管理。一个团队之所以采用微服务架构,一定有敏捷性的诉求。所以通常微服务团队也会拥抱DevOps理念。一个完善的面向微服务架构的基础设施需要考虑 DevOps 流程以及工具链的自动化。最后,我们回到狭义的微服务治理,这里关注的是微服务组件之间的连接与通讯,例如服务注册发现、东西向路由流控、负载均衡、熔断降级、遥测追踪等。现在有个时髦的术语来描述这类功能,就是大家熟悉的Service Mesh。其实早期 Sping Cloud 之类的框架解决的是类似的问题,但在实现的方式上,尤其是mesh 和业务代码的耦合度上,有本质的区别。当我们考虑一个平台如何支撑微服务架构的时候,需要涵盖上述提及的方方面面,从产品的角度我们会保持一个开放的态度。这其中一部分需要我们自己去做,其他一些可以借助生态合作伙伴的能力去补全完善。此外,微服务架构也进入到了后Kubernetes时代,早期基本上是微服务作为用例推动容器技术的发展。今天已经反过来了,成为标准的Kubernetes其实在驱动和重新定义微服务的最佳实践。容器和Kubernetes为微服务架构的落地提供了绝佳的客观条件。Service Mesh: 下一个亟待爆发的现象级技术创新业界对于Service Mesh的布道已经持续了一段时间,我们今天不再重复基本的概念。当我们把Service Mesh和上一代以Spring Cloud为代表的微服务治理框架以及更早的Service Oriented Architecture (SOA) 作比较的时候,会看到一个有意思的演化。 我们知道,SOA有企业服务总线(ESB)的概念,ESB重且复杂,其实会混杂很多业务逻辑。SOA架构下,ESB最终容易变成架构以及敏捷性的瓶颈。早期推广微服务架构的时候,一个重要的概念就是“Smart Endpoints and Dumb Pipes”,针对的就是SOA下ESB的痛点,从而每个微服务能够独立、自治、松耦合。但是仔细去想的话,就会发现它其实走到了另一个极端:它把一些基础设施提供的能力放到微服务的业务组件里面了,通常每个组件需要加载一些治理框架提供的库,或是调用特定的API,其实就是在业务组件里内置了基础设施的功能。到了Service Mesh其实又把它们分开了,从架构角度这样也比较合理,应用是纯业务的东西,里面没有任何基础设施,而提供微服务治理的基础设施,要么在Mesh里面,要么由底层的Kubernetes平台来提供,对应用是透明的。Istio的出现促使业界对于Service Mesh的架构有了新的共识:控制平面(Control Plane)与数据平面(Data Plane)解耦。通过独立的控制平面可以对Mesh获得全局性的可观测性(Observability)和可控制性(Controllability),让Service Mesh有机会上升到平台的高度。相对于需要在业务代码层面使用的上一代微服务治理框架,这点对于希望提供面向微服务架构基础设施的厂商,或是企业内部需要赋能业务团队的平台部门都具有相当大的吸引力。在Data Plane,Envoy的领导者地位毫无争议。Envoy使用C 开发,在资源使用效率和性能上(尤其是长尾性能差异)相较早期主要竞争对手Linkerd有明显优势。Envoy提供基于filter chain的扩展机制,从Kubernetes的成功当中我们已经学习到,可扩展性对于大规模采用十分关键。Envoy定义了一套“通用数据平面API”(Universal Data Plane API),也就是它的xDS协议。不仅确保了Envoy本身的动态可配置性,更重要的是为Service Mesh中Control Plane和Data Plane解耦提供了一个标准的接口。由于主流Control Plane(例如Istio)对Envoy以及xDS的采纳,xDS成为Service Mesh Data Plane API的事实标准,Envoy也成为无可争议的Data Plane领导者。在Control Plane,Istio是最具光环的明星级项目。它正在引领Service Mesh创造出一个全新的市场,不过从传播周期看现在还没有跨过技术鸿沟,处于Early adopters阶段。过去一年中,Istio项目在技术上的表现并不完全令人满意,主要体现在对其复杂度的诟病,以及稳定性和性能的质疑。1.0版本的推出并没有完全令人信服。不过,这些似乎并不影响Istio在社区获得的巨大成功。在开源领域,并不存在对Istio有实质性威胁的竞品。可能在经历了Kubernetes之后,以及Istio早期迅猛的发展和在社区中巨大的影响力之下,很少有开源项目愿意在Control Plane和Istio正面交锋。长远来讲,Data Plane会慢慢变成commodity,尤其在有了Universal Data Plane API之后。我们有理由相信成熟稳健的Envoy会保持领先,但最终多数用户会越来越少去关心具体的Data Plane技术。这个情境似曾相识,和当初Docker与Kubernetes的关系有点类似。下个阶段Service Mesh的赋能和创新会更多聚焦在Control Plane。AWS在Data Plane选择成熟的Envoy,而自己开发App Mesh的Control Plane,就很容易理解。灵雀云已经在ACE/ACP两条产品线中集成了Istio,提供企业就绪的Service Mesh。云原生为机器学习输出工程化最佳实践云原生的理念与相关技术对于应用开发与交付的巨大价值已经被普遍接受。但云原生不仅仅可以作用在普通的应用开发上。站在容器平台的角度看,机器学习毫无疑问是一类极为重要新兴工作负载。在未来,可能所有的公司都会是AI公司,所有的应用都会是智能应用,使用算法、模型就像今天应用会依赖数据库一样普遍。如果我们分析数据科学家的工作流,会发现和传统应用开发有很多相似的挑战。如何方便的获取实验环境;如何让实验可重复;如何将数据处理、特征提取、模型训练、模型验证、模型发布这些步骤自动化,并且可重复;如何让研究和生产环境保持一致;如何在生产环境做模型变更、AB测试、灰度发布;如何在生产环境运维模型服务;如何将模型服务化,等等。在软件工程领域,云原生的理念、方法论和最佳实践已经为类似问题找到了良好的解决方案。这些方案其实非常适合应用在机器学习场景。换句话说,我们需要“云原生机器学习”。这仍然是一个相对早期的概念,从鸿沟理论的周期来看,云原生机器学习大致还处在Innovators创新者尝鲜的阶段。我们去年发布的Alauda Machine Learning (AML) 就是一个“云原生机器学习平台”,目标是从云平台的角度,用云原生的思路去落地机器学习工程化的最佳实践。 ...

March 11, 2019 · 1 min · jiezi

Nvidia GPU如何在Kubernetes 里工作

Nvidia GPU如何在Kubernetes 里工作本文介绍Nvidia GPU设备如何在Kubernetes中管理调度。 整个工作流程分为以下两个方面:如何在容器中使用GPUKubernetes 如何调度GPU如何在容器中使用GPU想要在容器中的应用可以操作GPU, 需要实两个目标容器中可以查看GPU设备容器中运行的应用,可以通过Nvidia驱动操作GPU显卡详细介绍可见: https://devblogs.nvidia.com/gpu-containers-runtime/Nvidia-dockerGitHub: https://github.com/NVIDIA/nvidia-dockerNvidia提供Nvidia-docker项目,它是通过修改Docker的Runtime为nvidia runtime工作,当我们执行 nvidia-docker create 或者 nvidia-docker run 时,它会默认加上 –runtime=nvidia 参数。将runtime指定为nvidia。当然,为了方便使用,可以直接修改Docker daemon 的启动参数,修改默认的 Runtime为 nvidia-container-runtime cat /etc/docker/daemon.json{ “default-runtime”: “nvidia”, “runtimes”: { “nvidia”: { “path”: “/usr/bin/nvidia-container-runtime”, “runtimeArgs”: [] } }}gpu-containers-runtimeGitHub: https://github.com/NVIDIA/nvidia-container-runtimegpu-containers-runtime 是一个NVIDIA维护的容器 Runtime,它在runc的基础上,维护了一份 Patch, 我们可以看到这个patch的内容非常简单, 唯一做的一件事情就是在容器启动前,注入一个 prestart 的hook 到容器的Spec中(hook的定义可以查看 OCI规范 )。这个hook 的执行时机是在容器启动后(Namespace已创建完成),容器自定义命令(Entrypoint)启动前。nvidia-containers-runtime 定义的 prestart 的命令很简单,只有一句 nvidia-container-runtime-hook prestart gpu-containers-runtime-hookGitHub: https://github.com/NVIDIA/nvidia-container-runtime/tree/master/hook/nvidia-container-runtime-hook gpu-containers-runtime-hook 是一个简单的二进制包,定义在Nvidia container runtime的hook中执行。 目的是将当前容器中的信息收集并处理,转换为参数调用 nvidia-container-cli 。主要处理以下参数:根据环境变量 NVIDIA_VISIBLE_DEVICES 判断是否会分配GPU设备,以及挂载的设备ID。如果是未指定或者是 void ,则认为是非GPU容器,不做任何处理。 否则调用 nvidia-container-cli , GPU设备作为 –devices 参数传入环境环境变量 NVIDIA_DRIVER_CAPABILITIES 判断容器需要被映射的 Nvidia 驱动库。环境变量 NVIDIA_REQUIRE_ 判断GPU的约束条件。 例如 cuda>=9.0 等。 作为 –require= 参数传入传入容器进程的Pidgpu-containers-runtime-hook 做的事情,就是将必要的信息整理为参数,传给 nvidia-container-cli configure 并执行。nvidia-container-clinvidia-container-cli 是一个命令行工具,用于配置Linux容器对GPU 硬件的使用。支持list: 打印 nvidia 驱动库及路径info: 打印所有Nvidia GPU设备configure: 进入给定进程的命名空间,执行必要操作保证容器内可以使用被指定的GPU以及对应能力(指定 Nvidia 驱动库)。 configure是我们使用到的主要命令,它将Nvidia 驱动库的so文件 和 GPU设备信息, 通过文件挂载的方式映射到容器中。代码如下: https://github.com/NVIDIA/libnvidia-container/blob/master/src/cli/configure.c#L272 / Mount the driver and visible devices. */ if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_MOUNT], ecaps_size(NVC_MOUNT)) < 0) { warnx(“permission error: %s”, err.msg); goto fail; } if (nvc_driver_mount(nvc, cnt, drv) < 0) { warnx(“mount error: %s”, nvc_error(nvc)); goto fail; } for (size_t i = 0; i < dev->ngpus; ++i) { if (gpus[i] != NULL && nvc_device_mount(nvc, cnt, gpus[i]) < 0) { warnx(“mount error: %s”, nvc_error(nvc)); goto fail; } }如果对其他模块感兴趣,可以在 https://github.com/NVIDIA/libnvidia-container 阅读代码。以上就是一个nvidia-docker的容器启动的所有步骤。当我们安装了nvidia-docker, 我们可以通过以下方式启动容器docker run –rm -it -e NVIDIA_VISIBLE_DEVICES=all ubuntu:18.04在容器中执行 mount 命令,可以看到名为 libnvidia-xxx.so 和 /proc/driver/nvidia/gpus/xxx 映射到容器中。 以及 nvidia-smi 和 nvidia-debugdump 等nvidia工具。# mount ## …./dev/vda1 on /usr/bin/nvidia-smi type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/bin/nvidia-debugdump type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/bin/nvidia-persistenced type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/bin/nvidia-cuda-mps-control type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/bin/nvidia-cuda-mps-server type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-cfg.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libcuda.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-fatbinaryloader.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)/dev/vda1 on /usr/lib/x86_64-linux-gnu/libnvidia-compiler.so.396.37 type ext4 (ro,nosuid,nodev,relatime,data=ordered)devtmpfs on /dev/nvidiactl type devtmpfs (ro,nosuid,noexec,relatime,size=247574324k,nr_inodes=61893581,mode=755)devtmpfs on /dev/nvidia-uvm type devtmpfs (ro,nosuid,noexec,relatime,size=247574324k,nr_inodes=61893581,mode=755)devtmpfs on /dev/nvidia-uvm-tools type devtmpfs (ro,nosuid,noexec,relatime,size=247574324k,nr_inodes=61893581,mode=755)devtmpfs on /dev/nvidia4 type devtmpfs (ro,nosuid,noexec,relatime,size=247574324k,nr_inodes=61893581,mode=755)proc on /proc/driver/nvidia/gpus/0000:00:0e.0 type proc (ro,nosuid,nodev,noexec,relatime)我们可以执行nvidia-smi查看容器中被映射的GPU卡Kubernetes 如何调度GPU之前我们介绍了如何在容器中使用Nvidia GPU卡。 那么当一个集群中有成百上千个节点以及GPU卡,我们的问题变成了如何管理和调度这些GPU。Device pluginKubernetes 提供了Device Plugin 的机制,用于异构设备的管理场景。原理是会为每个特殊节点上启动一个针对某个设备的DevicePlugin pod, 这个pod需要启动grpc服务, 给kubelet提供一系列接口。type DevicePluginClient interface { // GetDevicePluginOptions returns options to be communicated with Device // Manager GetDevicePluginOptions(ctx context.Context, in *Empty, opts …grpc.CallOption) (*DevicePluginOptions, error) // ListAndWatch returns a stream of List of Devices // Whenever a Device state change or a Device disapears, ListAndWatch // returns the new list ListAndWatch(ctx context.Context, in *Empty, opts …grpc.CallOption) (DevicePlugin_ListAndWatchClient, error) // Allocate is called during container creation so that the Device // Plugin can run device specific operations and instruct Kubelet // of the steps to make the Device available in the container Allocate(ctx context.Context, in *AllocateRequest, opts …grpc.CallOption) (*AllocateResponse, error) // PreStartContainer is called, if indicated by Device Plugin during registeration phase, // before each container start. Device plugin can run device specific operations // such as reseting the device before making devices available to the container PreStartContainer(ctx context.Context, in *PreStartContainerRequest, opts …grpc.CallOption) (*PreStartContainerResponse, error)}DevicePlugin 注册一个 socket 文件到 /var/lib/kubelet/device-plugins/ 目录下,kubelet 通过这个目录下的socket文件向对应的 Device plugin 发送grpc请求。本文不过多介绍Device Plugin 的设计, 感兴趣可以阅读这篇文章: https://yq.aliyun.com/articles/498185Nvidia pluginGithub: https://github.com/NVIDIA/k8s-device-plugin为了能够在Kubernetes中管理和调度GPU, Nvidia提供了Nvidia GPU的Device Plugin。 主要功能如下支持ListAndWatch 接口,上报节点上的GPU数量支持Allocate接口, 支持分配GPU的行为。 Allocate 接口只做了一件事情,就是给容器加上 NVIDIA_VISIBLE_DEVICES 环境变量。 https://github.com/NVIDIA/k8s-device-plugin/blob/v1.11/server.go#L153// Allocate which return list of devices.func (m *NvidiaDevicePlugin) Allocate(ctx context.Context, reqs *pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error) { devs := m.devs responses := pluginapi.AllocateResponse{} for _, req := range reqs.ContainerRequests { response := pluginapi.ContainerAllocateResponse{ Envs: map[string]string{ “NVIDIA_VISIBLE_DEVICES”: strings.Join(req.DevicesIDs, “,”), }, } for _, id := range req.DevicesIDs { if !deviceExists(devs, id) { return nil, fmt.Errorf(“invalid allocation request: unknown device: %s”, id) } } responses.ContainerResponses = append(responses.ContainerResponses, &response) } return &responses, nil}前面我们提到, Nvidia的 gpu-container-runtime 根据容器的 NVIDIA_VISIBLE_DEVICES 环境变量,会决定这个容器是否为GPU容器,并且可以使用哪些GPU设备。 而Nvidia GPU device plugin做的事情,就是根据kubelet 请求中的GPU DeviceId, 转换为 NVIDIA_VISIBLE_DEVICES 环境变量返回给kubelet, kubelet收到返回内容后,会自动将返回的环境变量注入到容器中。当容器中包含环境变量,启动时 gpu-container-runtime 会根据 NVIDIA_VISIBLE_DEVICES 里声明的设备信息,将设备映射到容器中,并将对应的Nvidia Driver Lib 也映射到容器中。总体流程整个Kubernetes调度GPU的过程如下:GPU Device plugin 部署到GPU节点上,通过 ListAndWatch 接口,上报注册节点的GPU信息和对应的DeviceID。 当有声明 nvidia.com/gpu 的GPU Pod创建出现,调度器会综合考虑GPU设备的空闲情况,将Pod调度到有充足GPU设备的节点上。节点上的kubelet 启动Pod时,根据request中的声明调用各个Device plugin 的 allocate接口, 由于容器声明了GPU。 kubelet 根据之前 ListAndWatch 接口收到的Device信息,选取合适的设备,DeviceID 作为参数,调用GPU DevicePlugin的 Allocate 接口GPU DevicePlugin ,接收到调用,将DeviceID 转换为 NVIDIA_VISIBLE_DEVICES 环境变量,返回kubeletkubelet将环境变量注入到Pod, 启动容器容器启动时, gpu-container-runtime 调用 gpu-containers-runtime-hook gpu-containers-runtime-hook 根据容器的 NVIDIA_VISIBLE_DEVICES 环境变量,转换为 –devices 参数,调用 nvidia-container-cli prestart nvidia-container-cli 根据 –devices ,将GPU设备映射到容器中。 并且将宿主机的Nvidia Driver Lib 的so文件也映射到容器中。 此时容器可以通过这些so文件,调用宿主机的Nvidia Driver。本文作者:萧元阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 11, 2019 · 3 min · jiezi

CNCF邀请你加入最终用户社区

最终用户社区CNCF的最终用户社区正在发展,由70多家顶级公司和初创公司组成,致力于加速采用云原生技术并改善部署体验。Intuit的Jeff Brewer是技术监督委员会的最终用户代表。关于最终用户社区CNCF为最终用户提供多种机会来参与社区贡献,并为自己发声。那些在自己公司内部使用云原生计算技术,但不对外出售任何云原生服务公司有资格参加最终用户社区。在这里,你有机会与同行合作确立最佳操作方式,直接接触项目维护者,并且向CNCF提供反馈意见。加入CNCF最终用户社区的权益包括:投票选举一名最终用户社区代表进入技术监督委员会(TOC)。TOC上的席位非常受欢迎,因为他们是云原生社区的领导者,控制进入CNCF的新项目,并帮助协调现有的项目。每月有专门的最终用户电话会议、邮件列表以及Slack通道。每个月,我们为最终用户会员安排一次机会,聆听云原生社区社区领袖,包括项目的维护人员、管委会和技术监督委员会成员、未来的项目负责人的讲话及他们相互的讨论。5张门票参加云原生社区的盛会KubeCon + CloudNativeCon北美、欧洲或中国(公司少于300名员工的提供2张门票)。提供机会促进最终用户会员与CNCF社区交流,包括在网站上显示用户会员的标志,在新闻报导和分析简报中提及用户会员的名称等。(这是可选的;对希望不公开他们参与的最终用户社区成员,我们支持和配合)。参加CNCF最终用户合作伙伴峰会,一个KubeCon+CloudNativeCon的会前活动,只对CNCF的最终用户社区成员开放。加入用户社区的途径用户有两种途径参加最终用户社区和 CNCF:用户会员(适用于白银、黄金、白金级别)会员权益和会费匹配会员级别,也包括参与最终用户社区的机会。这包括CNCF会员的权益, 如参与市场推广委员会,管委会席位和KubeCon + CloudNativeCon赞助折扣。最终用户支持者参与最终用户社区,但没有CNCF会员的权益。(支持者不会自动成为CNCF或LF成员)参加并获得KubeCon + CloudNativeCon门票300名或以上员工,每年$4,500(包括5张门票参加KubeCon + CloudNativeCon北美、欧洲或中国)299名或以下员工,每年$1,800(包括2张门票参加KubeCon + CloudNativeCon北美、欧洲或中国)扫描二维码联系我们,加入CNCF最终用户社区!KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!

March 11, 2019 · 1 min · jiezi

k8s与configmap--安利configmap-reload组件

前言在kubernetes集群内,当ConfigMap以volume形式挂载到pod内时,更新ConfigMap,kubernetes会自动同步被挂载到pod内的文件内容。当然并不是更改立即生效的,大约是需要10S钟后,才会生效。实际生产使用案例中,假如你的应用具备hot reload 功能, 这时可以增加一些监测配置文件变更的脚本,然后reload对应服务。比如prometheus。今天就给大家介绍一个configmap-reload 组件。configmap-reloadconfigmap-reload 采用rust语言实现,作为主业务容器的sidercar,主要用于k8s当中监听configmap的变化,待变化后通过http接口的方式通知主业务。在资源消耗上,更小。具体如下:[root@ip-172-xx-xx-10 src]# kubectl top podsNAME CPU(cores) MEMORY(bytes)configmap-reload-6bbbb8b45b-7zg2x 0m 1Mi输入参数可以通过configmap-reload -h 获取:configmap-reload 0.1.0gaohj <gaohj2015@yeah.net>USAGE: configmap-reload [OPTIONS]FLAGS: -h, –help Prints help information -V, –version Prints version informationOPTIONS: -l, –log_level <LOG_LEVEL> log level: error|warn|info|debug|trace [default: info] -p, –path <VOLUME_PATH> the config map volume directory to watch for updates [default: ] -m, –webhook_method <WEBHOOK_METHOD> the HTTP method url to use to send the webhook: GET|POST [default: POST] -c, –webhook_status_code <WEBHOOK_STATUS_CODE> the HTTP status code indicating successful triggering of reload [default: 200] -u, –webhook_url <WEBHOOK_URL> the HTTP method url to use to send the webhook [default: ] 示例使用:—apiVersion: v1kind: ConfigMapmetadata: labels: app: configmap-reload name: configmap-reload-cmdata: test.ini: |- key: a—kind: DeploymentapiVersion: apps/v1metadata: name: configmap-reload labels: app: configmap-reloadspec: replicas: 1 selector: matchLabels: app: configmap-reload template: metadata: labels: app: configmap-reload spec: volumes: - name: config configMap: name: configmap-reload-cm containers: - name: configmap-reload image: ‘iyacontrol/configmap-reload:v0.1’ command: - configmap-reload args: - -l - debug - -p - /etc/test/ - -c - ‘200’ - -u - https://www.baidu.com volumeMounts: - name: config mountPath: /etc/test/ imagePullPolicy: Always—总结大家直接可以拉取 dockerhub 中的镜像。当然仓库中已经提供了Dockerfile文件,FROM clux/muslrust:stable as builderWORKDIR /configmap-reloadCOPY ./ ./ARG use_mirrorRUN if [ $use_mirror ]; then \ mkdir -p $HOME/.cargo; \ mv -f ./docker/cargo_config $HOME/.cargo/config; \ fiRUN cargo build –release#####################################FROM alpine:latest as prodRUN apk add –no-cache ca-certificates COPY –from=0 /configmap-reload/target/x86_64-unknown-linux-musl/release/configmap-reload /usr/bin/configmap-reloadRUN chmod +x /usr/bin/configmap-reloadENTRYPOINT [“configmap-reload”]大家可以自己打镜像,然后push到自己的仓库中。 ...

March 10, 2019 · 1 min · jiezi

Kubernetes taint & toleration

一、概述前一篇文章讲解了 Kubernetes 亲和性调度, 所涉及的内容都是描述 pod 的属性,来声明此 pod 希望调度到哪类 nodes。而本文介绍的 Taint(污点) 刚好相反,它是node 的一个属性,允许 node 主动排斥 pod 的调度。对应的 k8s 又给 pod 新增了配套属性 toleration(容忍) ,用于表示这些 pod 可以(但不强制要求)被调度到具有相应 taints 的 nodes 上。这两者经常一起搭配,来确保不将 pod 调度到不合适的 nodes。看下 taint & toleration 结构体,下面足点介绍时会涉及相关字段。type Taint struct { Key string Value string Effect TaintEffect // add taint 的时间点 // 只有 Effect = NoExecute, 该值才会被 nodeController 写入 TimeAdded *metav1.Time}type Toleration struct { Key string Operator TolerationOperator Value string Effect TaintEffect // 容忍时间 TolerationSeconds *int64}type TaintEffect stringconst ( TaintEffectNoSchedule TaintEffect = “NoSchedule” TaintEffectPreferNoSchedule TaintEffect = “PreferNoSchedule” TaintEffectNoExecute TaintEffect = “NoExecute”)type TolerationOperator stringconst ( TolerationOpExists TolerationOperator = “Exists” TolerationOpEqual TolerationOperator = “Equal”)二、Taint我们可以对 node 设置多个 taints,当然也可以在 pod 配置相同个数的 tolerations。影响调度和运行的具体行为,我们可以分为以下几类:如果至少有一个 effect == NoSchedule 的 taint 没有被 pod toleration,那么 pod 不会被调度到该节点上。如果所有 effect == NoSchedule 的 taints 都被 pod toleration,但是至少有一个 effect == PreferNoSchedule 没有被 pod toleration,那么 k8s 将努力尝试不把 pod 调度到该节点上。如果至少有一个 effect == NoExecute 的 taint 没有被 pod toleration,那么不仅这个 pod 不会被调度到该节点,甚至这个节点上已经运行但是也没有设置容忍该污点的 pods,都将被驱逐。三、Toleration再看下 PodSpec 配置 Tolerations,其中的 key、value、effect 与 Node Taint 设置需要保持一致,operator 支持两类:Exists: 这个配置下,不需要指定 value。Equal: 需要配置 value 值。(operator 的默认值)有几个特殊情况:key 为空并且 operator 等于 Exists,表示匹配了所有的 keys,values 和 effects。换句话说就是容忍了所有的 taints。tolerations:- operator: “Exists"effect 为空,则表示匹配所有的 effects(NoSchedule、PreferNoSchedule、NoExecute)tolerations:- key: “key” operator: “Exists"还有一个 TolerationSeconds,该值与 effect 为 NoExecute 配套使用。用来指定在 node 添加了 effect = NoExecute 的 taint 后,能容忍该 taint 的 pods 可停留在 node 上的时间。例如:tolerations: - key: “key1” operator: “Equal” value: “value1” effect: “NoExecute” tolerationSeconds: 3600表示如果这个 pod 已经运行在 node 上并且该 node 添加了一个对应的 taint,那么这个 pod 将会在 node 上停留 3600 秒后才会被驱逐。但是如果 taint 在这个时间前被移除,那么这个 pod 也就不会被驱逐了。来个比较形象的图,描述下:该图参考: Taints and tolerations, pod and node affinities demystified · Banzai Cloud四、内置行为kubernetes 1.6 版本,node controller 会跟进系统情况自动设置 node taint 属性。内置 taint key 如下:node.kubernetes.io/not-ready: 节点尚未就绪node.kubernetes.io/unreachable: 节点无法被访问node.kubernetes.io/unschedulable: 节点不可调度node.kubernetes.io/out-of-disk: 节点磁盘不足node.kubernetes.io/memory-pressure: 节点有内存压力node.kubernetes.io/disk-pressure: 节点有磁盘压力node.kubernetes.io/network-unavailable: 节点网络不可用node.kubernetes.io/pid-pressure: 节点有 pid 压力node.cloudprovider.kubernetes.io/uninitialized: 云节点未初始化node.cloudprovider.kubernetes.io/shutdown: 云节点已下线kubernetes 会通过 DefaultTolerationSeconds admission controller 为创建的 pod 添加两个默认的 toleration: node.kubernetes.io/not-ready 和 node.kubernetes.io/unreachable,并且设置 tolerationSeconds = 300。当然这个默认配置,用户可以自行覆盖。这些自动添加的默认配置,确保 node 出现问题后,pod 可以继续在 node 上停留 5 分钟。DefaultTolerationSeconds admission controller 设置的 tolerationSeconds 值,也可以由用户指定。具体参考: https://github.com/kubernetes…还有一个默认行为,就是 DaemonSet。所有 DaemonSet 创建的 pod 都会添加两个 toleration: node.alpha.kubernetes.io/unreachable 和 node.alpha.kubernetes.io/notReady。设置 effect = NoExecute,并且不指定 tolerationSeconds。目的是确保在 node 出现 unreachable 或 notReady 的问题时,DaemonSet Pods 永远不会被驱逐。示例专用节点如果你希望将一组节点专用于特定的用户,那可以将这些节点设置 taints: kubectl taint nodes nodename dedicated=groupName:NoSchedule, 然后为 pods 设置对应的 tolerations。如果你希望节点被专用并且确保服务仅使用这批节点,那么你还应该向这批节点设置 labels (dedicated=groupName),并且为对应的 pods 设置 NodeAffinity,以控制 pods 只能跑到这批节点上。具有特殊硬件的节点有部分带有特殊硬件的节点,比如 GPU、FPGA 等,要确保不将不需要专用硬件的 pods 调度到这些节点。也可以和 专有节点 一样的方式设置 taints:kubectl taint nodes nodename special=true:NoSchedule 或 kubectl taint nodes nodename special=true:PreferNoSchedule。建议还可以通过 Extended Resources 和 ExtendedResourceToleration admission controller 来更方便的调度依赖特殊硬件的 pods,而不需要手动添加容器的 toleration基于 taint 的驱逐前面也提到了,可以通过 NoExecute taint 来驱逐节点上已经运行的 pods。五、参考资料community/taint-toleration-dedicated.md at master · kubernetes/community · GitHubcommunity/taint-node-by-condition.md at master · kubernetes/community · GitHubTaints and TolerationsTaints and tolerations, pod and node affinities demystified · Banzai Cloud ...

March 9, 2019 · 2 min · jiezi

Kubernetes 调度器浅析

一、概述Kubernetes 是 Google 开源的容器集群管理系统(谷歌内部:Borg),而今天要介绍的 kube-scheduler 是 k8s 系统的核心组件之一,其主要职责就是通过自身的调度算法,为新创建的 Pod 寻找一个最合适的 Node。主要包含如下几个步骤:通过一组叫做谓词 predicates 的过滤算法,先挑出满足条件的 Node;通过一组叫做优先级 priorities 的打分算法,来给上一步符合条件的每个 Node 进行打分排名;最终选择得分最高的节点,当然如果得分一样就随机一个节点,填回 Pod 的 spec.nodeName 字段。官方流程图如下:For given pod: +———————————————+ | Schedulable nodes: | | | | +——–+ +——–+ +——–+ | | | node 1 | | node 2 | | node 3 | | | +——–+ +——–+ +——–+ | | | +——————-+————————-+ | | v +——————-+————————-+ Pred. filters: node 3 doesn’t have enough resource +——————-+————————-+ | | v +——————-+————————-+ | remaining nodes: | | +——–+ +——–+ | | | node 1 | | node 2 | | | +——–+ +——–+ | | | +——————-+————————-+ | | v +——————-+————————-+ Priority function: node 1: p=2 node 2: p=5 +——————-+————————-+ | | v select max{node priority} = node 2scheduler 的工作看似很简单,但其实不然。考虑的问题非常多,比如要保证每个节点被公平调度,提高资源利用率,提高 pod 调度效率,提升调度器扩展能力等等。可涉及的内容非常多,接下来会围绕两个核心步骤对 k8s 的 默认调度策略 深入了解。参考 Kubernetes 版本: v1.12二、PredicatesPredicates 在调度过程中的作用就是先进行过滤,过滤掉所有不符合条件的节点后,剩下的所有节点就都是可以运行带调度 Pod。Predicates 的可以分为如下四类:GeneralPredicates:负责最基础的调度策略,比如 PodFitsResources 计算宿主机资源是否够用。与 Volume 相关的过滤规则:负责与容器持久化 Volume 相关的调度策略。与宿主机相关的过滤规则:负责考察待调度 Pod 是否满足 Node 本身的一些条件。与已运行 Pod 相关的过滤规则:负责检查待调度 Pod 与 Node 上已有 Pod 之间的亲和性关系。具体的 Predicates 默认策略,可以参考: 默认调度策略当开始调度一个 Pod 的时候,调度器会同时开启多个协程并发的进行 Node Predicates 过滤,最后返回一个可以运行 Pod 的节点列表。每个协程都是按照固定的顺序进行计算过滤的。接下来,我们看下四大类具体运行的调度策略内容。1. GeneralPredicates看字面意思就知道 GeneralPredicates 负责的是最基础的调度策略,其包含的具体策略如下:PodFitsResources: 计算宿主机的 CPU、内存、扩展资源(如 GPU)等是否够用。PodFitsHost: 检查宿主机的名字是否跟 Pod 的 spec.nodeName 匹配。PodFitsHostPorts: 检查 Pod 申请的宿主机端口有没有冲突。PodMatchNodeSelector: 检查节点是否能匹配 Pod 的 nodeSelector 和 nodeAffinity。因为 GeneralPredicates 是最基础的调度策略,所以该接口也会被别的组件直接调用,比如 kubelet、daemonSet controller。kubelet 在启动 pod 之前,还会再执行一遍 GeneralPredicates,用于二次确认。2. 与 Volume 相关的过滤规则不废话就直接列举具体的策略了:NoDiskConflict:检查该节点上所有的 Pods 是否与待调度的 Pod 的 Volume 有冲突,比如 AWS、GCE 的 Volume 是不允许被两个 Pod 同时使用的。VolumeZonePredicate:检查 Pod Volume 的 zone 标签是否与节点的 zone 标签匹配。如果 Node 没有 zone 标签则认定为匹配。MaxPDVolumeCountPredicate:检查节点上某种类型的 Volume 是否已经超过指定数目。CSIMaxVolumeLimitPredicate:检查 csi volume 相关的限制VolumeBindingPredicate:检查 Pod 对应的 Local PV 的 nodeAffinity 字段,是否跟某个节点的标签相匹配。如果该 Pod PVC 还没有绑定 PV 的话,则调度器还要负责检查所有待绑定的 PV,且该 PV 的 nodeAffinity 是否与节点标签匹配。3. 与宿主机相关的过滤规则这些规则主要考察待调度的 Pod 是否满足 Node 本身的一些条件。具体的策略如下:NodeConditionPredicate:检查 Node 是否还未准备好或者处于NodeOutOfDisk、NodeNetworkUnavailable 状态,又或者 Node spec.Unschedulable 设置为 true,那该节点都将无法被调度。PodToleratesNodeTaints:检查 Node 的 taint(污点)机制。只有当 Pod 的 Toleration 与 Node 的 Taint 匹配时,Pod 才能调度到该节点上。NodeMemoryPressurePredicate:检查当前节点的内存是否已经不够使用。NodeDiskPressurePredicate:检查当前节点的磁盘是否已经不够使用。NodePIDPressurePredicate:检查当前节点的 PID 是否已经不够使用。4. 与已运行 Pod 相关的过滤规则该规则主要就是 PodAffinityPredicate,用于检查待调度 Pod 与 Node 上已有的 Pod 之间的亲和性和反亲和性关系。具体的亲和性相关的调度,后面会单独拿一篇文章进行介绍。三、Priorities完成了前一个阶段的节点 “过滤” 之后,便需要通过 Priorities 为这些节点打分,选择得分最高的节点,作为调度对象。打分函数很多,总得分可以参考:总分 = (权重1 * 打分函数1) + (权重2 * 打分函数2) + … + (权重n * 打分函数n)。每一次打分的范围是 0 — 10 分。10 表示非常合适,0 表示非常不合适。并且每个打分函数都可以配置对应的权重值,下面介绍 调度器策略配置 时,也会涉及权重值的配置。默认权重值是 1,如果觉得某个打分函数特别重要,便可以加大该权重值。具体的 Priorities 默认策略可以参考: defaultPriorities 。Priorities 最常用到的一个打分规则是 LeastRequestedPriority, 该算法用于选出空闲资源(cpu & memory)最多的宿主机。还有一个常见的是 BalancedResourceAllocation,该规则主要目的是资源平衡。在所有节点里选择各种资源分配最均衡的节点,避免出现某些节点 CPU 被大量分配,但是 Memory 大量剩余的情况。此外,还有 InterPodAffinityPriority、NodeAffinityPriority、TaintTolerationPriority,与亲和性与污点调度有关,后面会有单独的文章进行介绍。这里表示节点满足的规则越多,那得分就越高。在 K8S v1.12 版本还引入了一个调度策略,即 ImageLocalityPriority。该策略主要目的是优先选择那些已经存有 Pod 所需 image 的节点,可以避免实际运行 Pod 时,再去下载 image。注意: pod 运行时是否会下载 image,还跟 Pod ImagePullPolicy 配置有关。可以看到 k8s scheduler 完成一次调度所需的信息非常之多。所以在实际的调度过程中,大量的信息都事先已经缓存,提高了 Pod 的调度效率。四、调度策略配置Kubernetes 调度器有默认的调度策略,具体可以参考 default 。当然用户也可以修改调度策略,可以通过命令行参数 policy-config-file 指定一个 JSON 文件来描述哪些 predicates 和 priorities 在启动 k8s 时被使用, 通过这个参数调度就能使用管理者定义的策略了。示例如下:{“kind” : “Policy”,“apiVersion” : “v1”,“predicates” : [ {“name” : “PodFitsHostPorts”}, {“name” : “PodFitsResources”}, {“name” : “NoDiskConflict”}, {“name” : “NoVolumeZoneConflict”}, {“name” : “MatchNodeSelector”}, {“name” : “HostName”} ],“priorities” : [ {“name” : “LeastRequestedPriority”, “weight” : 1}, {“name” : “BalancedResourceAllocation”, “weight” : 1}, {“name” : “ServiceSpreadingPriority”, “weight” : 1}, {“name” : “EqualPriority”, “weight” : 1} ],“hardPodAffinitySymmetricWeight” : 10,“alwaysCheckAllPredicates” : false}五、自定义调度器前面提到了调度器的扩展能力,除了使用 k8s 自带的调度器,你也可以编写自己的调度器。通过修改 Pod 的 spec.schedulername 参数来指定调度器的名字。参考资料The Kubernetes SchedulerScheduler Algorithm in Kubernetes ...

March 9, 2019 · 2 min · jiezi

Kubernetes 亲和性调度

一、概述前一篇文章 Kubernetes 调度器浅析,大致讲述了调度器的工作原理及相关调度策略。这一章会继续深入调度器,介绍下“亲和性调度”。Kubernetes 支持限制 Pod 在指定的 Node 上运行,或者指定更倾向于在某些特定 Node 上运行。有几种方式可以实现这个功能:NodeName: 最简单的节点选择方式,直接指定节点,跳过调度器。NodeSelector: 早期的简单控制方式,直接通过键—值对将 Pod 调度到具有特定 label 的 Node 上。NodeAffinity: NodeSelector 的升级版,支持更丰富的配置规则,使用更灵活。(NodeSelector 将被淘汰.)PodAffinity: 根据已在节点上运行的 Pod 标签来约束 Pod 可以调度到哪些节点,而不是根据 node label。二、NodeNamenodeName 是 PodSpec 的一个字段,用于直接指定调度节点,并运行该 pod。调度器在工作时,实际选择的是 nodeName 为空的 pod 并进行调度然后再回填该 nodeName,所以直接指定 nodeName 实际是直接跳过了调度器。换句话说,指定 nodeName 的方式是优于其他节点选择方法。方法很简单,直接来个官方示例:apiVersion: v1kind: Podmetadata: name: nginxspec: containers: - name: nginx image: nginx nodeName: kube-01当然如果选择的节点不存在,或者资源不足,那该 pod 必然就会运行失败。三、NodeSelectornodeSelector 也是 PodSpec 中的一个字段,指定键—值对的映射。如果想要将 pod 运行到对应的 node 上,需要先给这些 node 打上 label,然后在 podSpec.NodeSelector 指定对应 node labels 即可。步骤如下:设置标签到 node 上:kubectl label nodes kubernetes-node type=gpupod 配置添加 nodeSelector 字段:apiVersion: v1kind: Podmetadata: name: nginxspec: containers: - name: nginx image: nginx nodeSelector: type: gpu内置 Node 标签Kubernetes 内置了一些节点标签:kubernetes.io/hostnamebeta.kubernetes.io/instance-typebeta.kubernetes.io/osbeta.kubernetes.io/archfailure-domain.beta.kubernetes.io/zonefailure-domain.beta.kubernetes.io/region有些标签是对云提供商使用。还有些表示 node role 的 labels(可以指定 master、lb 等):kubernetes.io/rolenode-role.kubernetes.io四、NodeAffinitynodeSelector 通过 k-v 的方式非常简单的支持了 pod 调度限制到具有特定标签的节点上。而 nodeAffinity 根据亲和力 & 反亲和力极大地扩展了能够表达的约束信息。nodeAffinity 特性的设计初衷就是为了替代 nodeSelector。nodeAffinity 当前支持的匹配符号包括:In、NotIn、Exists、DoesNotExists、Gt、Lt 。nodeAffinity 当前支持两种调度模式:requiredDuringSchedulingIgnoredDuringExecution: 一定要满足的条件,如果没有找到满足条件的节点,则 Pod 创建失败。所有也称为hard 模式。preferredDuringSchedulingIgnoredDuringExecution: 优先选择满足条件的节点,如果没有找到满足条件的节点,则在其他节点中择优创建 Pod。所有也称为 soft 模式。两种模式的名字特长,这是 k8s 的命名风格。其中IgnoredDuringExecution的意义就跟 nodeSelector 的实现一样,即使 node label 发生变更,也不会影响之前已经部署且又不满足 affinity rules 的 pods,这些 pods 还会继续在该 node 上运行。换句话说,亲和性选择节点仅在调度 Pod 时起作用。k8s 社区正在计划提供 requiredDuringSchedulingRequiredDuringExecution 模式,便于驱逐 node 上不满足 affinity rules 的 pods。来个官方示例,看下怎么玩:apiVersion: v1kind: Podmetadata: name: with-node-affinityspec: affinity: nodeAffinity: # 必须选择 node label key 为 kubernetes.io/e2e-az-name, # value 为 e2e-az1 或 e2e-az2. requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 # 过滤掉上面的必选项后,再优先选择 node label key 为 another-node-label-key # value 为 another-node-label-value. preferredDuringSchedulingIgnoredDuringExecution: # 如果满足节点亲和,积分加权重(优选算法,会对 nodes 打分) # weight: 0 - 100 - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: k8s.gcr.io/pause:2.0简单看下 NodeAffinity 的结构体,下面介绍注意事项时会涉及:type NodeAffinity struct { RequiredDuringSchedulingIgnoredDuringExecution *NodeSelector PreferredDuringSchedulingIgnoredDuringExecution []PreferredSchedulingTerm}type NodeSelector struct { NodeSelectorTerms []NodeSelectorTerm}type NodeSelectorTerm struct { MatchExpressions []NodeSelectorRequirement MatchFields []NodeSelectorRequirement}配置相关的注意点:如果 nodeSelector 和 nodeAffinity 两者都指定,那 node 需要两个条件都满足,pod 才能调度。如果指定了多个 NodeSelectorTerms,那 node 只要满足其中一个条件,pod 就可以进行调度。如果指定了多个 MatchExpressions,那必须要满足所有条件,才能将 pod 调度到该 node。五、PodAffinitynodeSelector & nodeAffinity 都是基于 node label 进行调度。而有时候我们希望调度的时候能考虑 pod 之间的关系,而不只是 pod 和 node 的关系。举个例子,会有需求希望服务 A 和 B 部署在同一个机房、机架或机器上,因为这些服务可能会对网路延迟比较敏感,需要低延时;再比如,希望服务 C 和 D 又希望尽量分开部署,即使一台主机甚至一个机房出了问题,也不会导致两个服务一起挂而影响服务可用性,提升故障容灾的能力。podAffinity 会基于节点上已经运行的 pod label 来约束新 pod 的调度。其规则就是“如果 X 已经运行了一个或者多个符合规则 Y 的 Pod,那么这个 Pod 应该(如果是反亲和性,则是不应该)调度到 X 上”。这里的 Y 是关联 namespace 的 labelSelector,当然 namespace 也可以是 all。和 node 不同,pod 是隶属于 namespace 下的资源,所以基于 pod labelSelector 必须指定具体的 namespace;而 X 则可以理解为一个拓扑域,类似于 node、rack、zone、cloud region 等等,就是前面提到的 内置 Node 标签 ,当然也可以自定义。看下 pod affinity 涉及的结构体,便于进行功能介绍:type Affinity struct { // NodeAffinity 前面介绍了 NodeAffinity *NodeAffinity // pod 亲和性 PodAffinity *PodAffinity // pod 反亲和性 PodAntiAffinity *PodAntiAffinity}type PodAffinity struct { // hard 模式, 必选项 RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm // soft 模式, 进行 node 优先 PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm}type PodAffinityTerm struct { LabelSelector *metav1.LabelSelector Namespaces []string TopologyKey string}type WeightedPodAffinityTerm struct { Weight int32 PodAffinityTerm PodAffinityTerm}podAffinity 和 nodeAffinity 有相似的地方,使用了 labelSelector 进行匹配,支持的匹配符号包括:In、NotIn、Exists、DoesNotExists;也支持两种调度模式 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution, 功能和 nodeAffinity 一样,这里就不在累述。podAffinity 和 nodeAffinity 也有较大的差异,前面讲了 pod 是 namespace 资源,所以必然会需要配置 namespaces,支持配置多个 namespace。如果省略的话,默认为待调度 pod 所属的 namespace;如果定义了但是值为空,则表示使用 “all” namespaces。还有一个较大的差别 TopologyKey, 便于理解进行单独介绍。TopologyKeyTopologyKey 用于定义 in the same place,前面也介绍了是拓扑域的概念。看下面的图,这两个 pod 到底该如何算在一个拓扑域?如果我们使用k8s.io/hostname,in the same place 则意味着在同一个 node,那下图的 pods 就不在一个 place:如果我们使用failure-domain.k8s.io/zone 来表示一个 place,那下图的 pods 就表示在一个 zone:当然我们也可以自定义 node labels 作为 TopologyKey。比如我们可以给一组 node 打上 rack 标签,那下图的 pods 表示在同一个 place:原则上,topologyKey 可以是任何合法的 label key。但是出于性能和安全考虑,topologyKey 存在一些限制:对于亲和性和反亲和性的 requiredDuringSchedulingIgnoredDuringExecution 模式,topologyKey 不能为空pod 反亲和性 requiredDuringSchedulingIgnoredDuringExecution 模式下,LimitPodHardAntiAffinityTopology 权限控制器会限制 topologyKey 只能设置为 kubernetes.io/hostname。当然如果你想要使用自定义 topology,那可以简单禁用即可。pod 反亲和性 preferredDuringSchedulingIgnoredDuringExecution 模式下,topologyKey 为空则表示所有的拓扑域。截止 v1.12 版本,所有的拓扑域还只能是 kubernetes.io/hostname, failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合。除此之外,topologyKey 可以是任何合法的 label key。示例来个官方示例,有三节点集群,需要分别部署 3 份 web 和 redis 服务。希望 web 与 redis 服务共存,但需要保证各个服务的副本分散部署。先创建 redis 集群:apiVersion: apps/v1kind: Deploymentmetadata: name: redis-cachespec: selector: matchLabels: app: store replicas: 3 template: metadata: labels: app: store spec: affinity: // pod 反亲和性, 打散 redis 各个副本 podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: “kubernetes.io/hostname” containers: - name: redis-server image: redis:3.2-alpine再部署 web 服务,需要打散并且与 redis 服务共存,配置如下:apiVersion: apps/v1kind: Deploymentmetadata: name: web-serverspec: selector: matchLabels: app: web-store replicas: 3 template: metadata: labels: app: web-store spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web-store topologyKey: “kubernetes.io/hostname” podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: “kubernetes.io/hostname” containers: - name: web-app image: nginx:1.12-alpine注意1: pod affinity 需要进行大量处理,所以会明显减慢大型集群的调度时间,不建议在大于几百个节点的集群中使用该功能。注意2: pod antiAffinity 要求对节点进行一致标志,即集群中的所有节点都必须具有适当的标签用于配置给 topologyKey,如果节点缺少指定的 topologyKey 指定的标签,则可能会导致意外行为。六、参考资料官方Assigning Pods to Nodes - Kubernetesnode affinitypod affinity性能优化: Improve performance of affinity/anti-affinity predicate by 20x in large clusters by bsalamatblogK8S 的调度 (一) 抽象优雅的 AffinityScheduling in Kubernetes, Part 2: Pod Affinity – Koki – Medium ...

March 9, 2019 · 3 min · jiezi

通过阿里云K8S Ingress Controller实现路由配置的动态更新

摘要: 本文主要描述了阿里云Kubernetes集群Ingress Controller如何通过动态更新的方式来极大地缓解转发平面Nginx频繁Reload带来的影响。简介在Kubernetes集群中,Ingress作为集群内服务对外暴露的访问接入点,其几乎承载着集群内服务访问的所有流量。我们知道,Nginx Ingress Controller是Kubernetes社区很重要的一个子项目,其内部主要依托于高性能的负载均衡软件Nginx,将Kubernetes Ingress资源对象实时地自动化转换为Nginx配置规则来对外提供期望的授权访问入口。现实问题当随着Kubernetes集群中部署的微服务越来越多,对外暴露的路由规则越来越复杂,服务后端Endpoint变化的越来越频繁,那么对应地都会引起Nginx Ingress Controller组件内Nginx配置文件的变化越来越频繁;而我们知道,任何一行Nginx配置的变化,都需要Reload Nginx才能生效,这在变化频率较低的场景下索性还能接受,但在高频率变化的场景下就会引起Nginx的频繁Reload。而Nginx频繁Reload带来的问题,这已是一个老生常谈的话题了,其问题本质主要还是源于Nginx本身最初的架构设计模型:一般在Linux服务器中,我们会配置使用Nginx的EPOLL多进程模式;当我们修改了Nginx配置文件后,需要通过nginx -s reload命令来重新热加载新的Nginx配置规则;当Nginx Master进程接收到reload signal后,其会从指定路径重新加载新的Nginx配置文件内容,并校验配置规则的有效性,若检验为有效的配置文件,则会依据新的配置文件中的worker_processes值fork出指定数量的新的Nginx Worker进程,此时新fork出来的子进程完全继承了父进程的内存数据ngx_cycle(其包含了新的解析后的Nginx配置规则),同时将配置中的每一个Listen Socket FD注册到内核的EPOLL事件监听中,此时这些新的Nginx Worker进程可以接收处理来自客户端的请求;同时Nginx Master进程会发送QUIT signal通知老的Nginx Worker进程平滑退出,当老的Nginx Worker进程接收到QTUI信号后,将其之前注册到EPOLL中的监听Event移除,至此不再接收处理新的客户端请求,并依据老配置文件中设置的worker_shutdown_timeout值来设置定时器,然后继续处理完已接收的客户端请求;若在worker_shutdown_timeout之前处理完已有的客户端请求,则自动退出,若未处理完,则被强制Kill退出,此时就会导致该客户端请求响应异常。因此,对于在高频率变化的场景下,Nginx频繁Reload会带来较明显的请求访问问题:造成一定的QPS抖动和访问失败情况对于长连接服务会被频繁断掉造成大量的处于shutting down的Nginx Worker进程,进而引起内存膨胀动态更新为缓解Nginx频繁Reload带来的影响,我们需要通过动态更新的方式来加载Nginx配置规则,即在不Fork新Nginx Worker进程的情况下来实时更新已加载到内存中的Nginx配置规则。首先我们看下Nginx的配置文件样式,主要包含下面几部分配置章节:# 1. main configurationdaemon off;worker_processes 4;events { # 2. event configuration multi_accept on; worker_connections 1024; use epoll;}http { # 3. http main configuration access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; upstream { # 4. upstream configuration server 0.0.0.1; } server { # 5. server configuration server_name _ ; listen 80 default_server; location / { # 6. location configuration proxy_pass http://upstream_balancer; }}而在Kubernetes集群中,一个Ingress资源对象主要被解析映射到Nginx的HTTP Main Block、Server Block、Upstream Block和Location Block等章节的配置规则上,因此我们可以将这几部分频繁变化的配置内容以Shared Memory的方式统一维持在内存中,同时在Ingress Controller内部暴露出管控端口,通过API的方式来实时管理Nginx路由规则配置:当K8S Ingress Controller监控到集群内Ingress及相关联的资源发生变化时,均可通过Internal API将最新的Nginx配置规则推送到统一的共享内存配置中,而不用再通过Reload Nginx的方式来使新配置生效,至此当Nginx处理任何新接收的客户端请求时,都可以基于最新的共享内存中的配置进行规则匹配和路由转发;配置说明1、目前阿里云容器服务Kubernetes集群中最新版本的Nginx Ingress Controller组件默认已开启Upstream的动态更新,同时支持应用服务的灰度发布和蓝绿发布功能,具体配置说明可参考这里;我们可以通过如下命令来查看当前共享内存中的Nginx Upstream的配置列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/backends2、同时也支持HTTPS证书的动态更新,可通过修改nginx-ingress-controller deployment的如下参数配置来开启Nginx Ingress Controller的证书动态更新:- args: - /nginx-ingress-controller - –configmap=$(POD_NAMESPACE)/nginx-configuration - –tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - –udp-services-configmap=$(POD_NAMESPACE)/udp-services - –annotations-prefix=nginx.ingress.kubernetes.io - –publish-service=$(POD_NAMESPACE)/nginx-ingress-lb - –enable-dynamic-certificates=true ### 添加该配置 - –v=2当开启HTTPS证书的动态更新后,Ingress的TLS证书都统一维护在Nginx的共享内存中,我们可通过如下命令来查看当前共享内存中配置的证书列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/certs3、进一步地我们也支持Nginx Server和Location配置的动态更新,可通过修改nginx-ingress-controller deployment的如下参数配置来开启Nginx Ingress Controller的Server和Location的动态更新:- args: - /nginx-ingress-controller - –configmap=$(POD_NAMESPACE)/nginx-configuration - –tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - –udp-services-configmap=$(POD_NAMESPACE)/udp-services - –annotations-prefix=nginx.ingress.kubernetes.io - –publish-service=$(POD_NAMESPACE)/nginx-ingress-lb - –enable-dynamic-certificates=true ### 添加该配置 - –enable-dynamic-servers=true ### 添加该配置,同时也要enable-dynamic-certificates - –v=2同样地,当我们开启了Nginx Ingress Controller的Server动态更新后,所有Nginx Server和Location的配置都统一维护在共享内存中,我们同样可以通过如下命令来查看当前共享内存中的Server配置列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/servers注意说明:当开启Server的动态更新特性后,部分Ingress Annotation配置暂不支持,正在逐步优化支持中,相应地您可直接通过ConfigMap方式来进行配置;本文作者:chenqz阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 8, 2019 · 1 min · jiezi

K8S新安全漏洞的应对之策:API Server拒绝服务漏洞

Kubernetes爆出中等严重性安全漏洞——Kubernetes API Server拒绝服务漏洞CVE-2019-1002100。本文将进行漏洞解读和情景再现,并分享漏洞修复方案,Rancher用户来看应对之策了!CVE-2019-1002100漏洞美国当地时间2019年3月2日,Kubernetes社区发布了Kubernetes API server拒绝服务的漏洞(CVE-2019-1002100),即有API写入权限的用户在写入资源时会导致Kubernetes API server过度消耗资源,此漏洞被评级为【中等严重性】。此漏洞表现为用户在向Kubernetes API server发送 json-patch规则的补丁包来更新资源对象时(例如kubectl patch xxx –type json 或者“Content-Type: application/json-patch+json”),Kubernetes API server会消耗极大的资源,最终导致API server拒绝连接。https://github.com/kubernetes…情景再现一个json-patch的例子:kubectl patch deployment test –type=‘json’ -p ‘[{“op”: “add”, “path”: “/metadata/labels/test”, “value”: “test”},{“op”: “add”, “path”: “/metadata/labels/app”, “value”: “test”} ,{…} ]‘当我们向Kubernetes频繁地发送多个json-patch请求来更新资源对象时,可以发现Kubernetes API server会消耗很多资源来处理我们的请求。此时会有一部分资源的patch请求失败,无法得到Kubernetes API server的响应。受此漏洞影响的Kubernetes API server的版本包括:v1.0.0 – 1.10.xv1.11.0 – 1.11.7v1.12.0 – 1.12.5v1.13.0 – 1.13.3Kubernetes官方建议用户在升级至修复版本之前,可针对此漏洞的采取的缓解措施为:对不受信任用户移除patch权限漏洞修复Kubernetes社区很快地修复了此漏洞,增加了对用户json-patch操作数量的限制。当用户对某一资源对象修改的 json-patch 内容超过10000个操作时,Kubernetes API server会返回413(RequestEntityTooLarge)的错误。错误信息如下:Request entity too large: The allowed maximum operations in a JSON patch is 10000, got 10004修复的Kubernetes版本包括:v1.11.8v1.12.6v1.13.4Rancher已发布最新版本应对此次漏洞此次也一如既往,在Kubernetes自身爆出漏洞之后,Rancher Labs团队都第一时间响应,保障使用Rancher平台管理Kubernetes集群的用户的安全。如果你是使用Rancher平台管理Kubernetes集群,不用担心,Rancher已于今日发布了最新版本,支持包含漏洞修复的Kubernetes版本,保障所有Rancher用户的Kubernetes集群不受此次漏洞困扰。最新发布的Rancher版本为:v2.1.7(提供Kubernetes v1.11.8, v1.12.6, v1.13.4支持)v2.0.12(提供Kubernetes v1.11.8支持)对于Rancher 1.6.x的用户,可以在Rancher v1.6.26的Catalog中使用Kubernetes发布的修复版本 v1.11.8和v1.12.6此次漏洞会影响的Kubernetes版本范围较广,建议中招的用户尽快升级哟!为用户的Docker & K8S之旅护航Rancher Kubernetes平台拥有着超过一亿次下载量,我们深知安全问题对于用户而言的重要性,更遑论那些通过Rancher平台在生产环境中运行Docker及Kubernetes的数千万用户。2018年年底Kubernetes被爆出的首个严重安全漏洞CVE-2018-1002105,就是由Rancher Labs联合创始人及首席架构师Darren Shepherd发现的。2019年1月Kubernetes被爆出仪表盘和外部IP代理安全漏洞CVE-2018-18264时,Rancher Labs也是第一时间向用户响应,确保所有Rancher 2.x和1.6.x的用户都完全不被漏洞影响。2019年2月爆出的严重的runc容器逃逸漏洞CVE-2019-5736,影响到大多数Docker与Kubernetes用户,Rancher Kubernetes管理平台和RancherOS操作系统均在不到一天时间内紧急更新,是业界第一个紧急发布新版本支持Docker补丁版本的平台,还帮忙将修复程序反向移植到所有版本的Docker并提供给用户,且提供了连Docker官方都不支持的针对Linux 3.x内核的修复方案。负责、可靠、快速响应、以用户为中心,是Rancher始终不变的初心;在每一次业界出现问题时,严谨踏实为用户提供相应的应对之策,也是Rancher一如既往的行事之道。未来,Rancher也将一如既往支持与守护在用户的K8S之路左右,确保大家安全、稳妥、无虞地继续前进❤️ ...

March 8, 2019 · 1 min · jiezi

Kubernetes v1.13对原始块卷支持转移到beta

作者:Ben Swartzlander(NetApp),Saad Ali(谷歌)Kubernetes v1.13将原始块卷(raw block volume)支持转移到beta。此功能允许持久卷(persistent volume)作为块设备(block device),而不是作为已安装的文件系统在容器内部公开。什么是块设备?块设备允许随机访问固定大小的块中的数据。硬盘驱动器、SSD和CD-ROM驱动器都是块设备的示例。持久存储通常以分层方式实现,在块设备(如旋转磁盘或SSD)之上使用文件系统(如ext4)。然后,应用程序读取和写入文件,而不是在块上操作。操作系统负责使用指定的文件系统,将文件作为块读取和写入底层设备。值得注意的是,整个磁盘都是块设备,磁盘分区也是,存储区域网络(SAN)设备的LUN也是。为什么要将原始块卷添加到kubernetes?有些专门的应用程序需要直接访问块设备,例如,文件系统层会引入不必要的开销。最常见的情况是数据库,它们更喜欢直接在底层存储上组织数据。原始块设备也常用于任何本身实现某种存储服务的软件(软件定义的存储系统)。从程序员的角度来看,块设备是一个非常大的字节数组,通常具有一些最小的读写粒度,通常为512字节,但更常见为4K或更大。随着在Kubernetes内部运行数据库软件和存储基础架构软件变得越来越普遍,Kubernetes中对原始块设备支持的需求变得更加重要。哪个卷插件支持原始块?在发布此博客时,以下树内(in-tree)卷类型支持原始块:AWS EBSAzure DiskCinderFibre ChannelGCE PDiSCSILocal volumesRBD (Ceph)Vsphere树外(Out-of-tree)CSI卷驱动程序也可以支持原始块卷。 Kubernetes CSI对原始块卷的支持目前是alpha。请参阅此处的文档。Kubernetes原始块卷API原始块与普通卷有很多共同点。两者都是通过创建绑定到PersistentVolume对象的PersistentVolumeClaim对象来请求的,并通过将它们包含在PodSpec的volumes数组中而附加到Kubernetes中的Pod。但是有两个重要的区别。首先,要请求原始块PersistentVolumeClaim,必须在PersistentVolumeClaimSpec中设置volumeMode =“Block”。将volumeMode留空与指定volumeMode =“Filesystem”相同,这会导致传统行为。PersistentVolumes在其PersistentVolumeSpec中也有一个volumeMode字段,而“Block”类型的PVC只能绑定到“Block”类型的PV,而“Filesystem”PVC只能绑定到“Filesystem”PV。其次,在Pods中使用原始块卷时,必须在PodSpec的Container部分而不是VolumeMount中指定VolumeDevice。VolumeDevices具有devicePaths而不是mountPaths,并且在容器内部,应用程序将在该路径中看到设备而不是已安装的文件系统。应用程序打开、读取和写入容器内的设备节点,就像它们将与非容器化或虚拟化环境中的系统上的任何块设备进行交互一样。创建新的原始块PVC首先,确保你选择的存储类关联的配置程序是支持原始块的配置程序。然后创建PVC。apiVersion: v1kind: PersistentVolumeClaimmetadata: name: my-pvcspec: accessModes: - ReadWriteMany volumeMode: Block storageClassName: my-sc resources: requests: storage: 1Gi使用原始块PVC在pod定义中使用PVC时,可以选择块设备的设备路径,而不是文件系统的安装路径。apiVersion: v1kind: Podmetadata: name: my-podspec: containers: - name: my-container image: busybox command: - sleep - “3600” volumeDevices: - devicePath: /dev/block name: my-volume imagePullPolicy: IfNotPresent volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc作为存储供应商,如何在我的CSI插件中添加对原始块设备的支持?CSI插件对原始块支持仍然是alpha,但今天可以添加支持。CSI规范详细说明了如何处理具有BlockVolume功能而不是MountVolume功能的卷请求。CSI插件可以支持这两种卷。有关更多详细信息,请参阅此处。问题/陷阱因为块设备实际上是设备,所以可以从容器内部对它们执行低级操作,这是文件系统卷无法实现的。例如,实际上是SCSI磁盘的块设备支持使用Linux ioctls向设备发送SCSI命令。默认情况下,Linux不允许容器将SCSI命令从容器内部发送到磁盘。为此,你必须将SYS_RAWIO功能授予容器安全上下文(context)以允许此操作。请参阅此处的文档。此外,虽然Kubernetes保证向容器提供块设备,但不能保证它实际上是SCSI磁盘或任何其他类型的磁盘。用户必须确保所需的磁盘类型与其pod一起使用,或者仅部署可处理各种块设备类型的应用程序。怎样能了解更多?在此处查看有关快照功能的其他文档。我如何参与?加入Kubernetes存储SIG和CSI社区,帮助我们添加更多优秀功能,并改进现有功能如原始块存储!鸣谢特别感谢帮助Kubernetes增加块卷支持的所有贡献者,包括:Ben Swartzlander(https://github.com/bswartz)Brad Childs(https://github.com/childsb)Erin Boyd(https://github.com/erinboyd)Masaki Kimura(https://github.com/mkimuram)Matthew Wong(https://github.com/wongma7)Michelle Au(https://github.com/msau42)Mitsuhiro Tanino(https://github.com/mtanino)Saad Ali(https://github.com/saad-ali)KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 8, 2019 · 1 min · jiezi

容错性好、易于管理和便于观察:浅谈如何利用K8s全面拥抱微服务架构

KubeCon + CloudNativeCon 论坛,作为 CNCF 的旗舰会议,自2016年以来已经在北美和欧洲两地的旧金山、伦敦、硅丘(奥斯汀)、哥本哈根等知名城市举办。2018年11月15日,KubeCon + CloudNativeCon 论坛首次来到中国,在上海跨国采购会展中心召开并获得了圆满成功。在去年的论坛上,CNCF不仅邀请到了Liz Rice、Janet Kuo等开源技术大牛到场为KubeCon + CloudNativeCon 在中国举行的首秀呐喊助威,更吸引到了包括美国、日本、印度在内的五大洲48个国家的开源精英前来参与。期间,有954家公司派代表到场展示自己的理念或者聆听精彩的技术分享。据统计,2018年盛会的参会者超过2500人,CNCF 为参会者提供了13场次的主题演讲、97场次的分组会议、55场次的维护者会议和15场次的快闪演讲。华为云、阿里云、腾讯云、微软、GitLab、Lyft等众多知名企业纷纷登台为大家分享相关的产品和技术架构,并为在场观众解答了相关问题。在上届论坛上,大家询问最多的,就是在 K8s(Kubernetes)架构上的使用精髓,而其中,比较有代表性的问题,则是企业如何利用 K8s 作为微服务架构,并且如何通过这样的部署来提升企业的自身价值。那么,什么是微服务架构呢?其实,微服务架构是与当前常用的单体架构相比较而言的。单体架构虽然方便管理,易于规划,但是灵活性和稳定性还是有所欠缺的,甚至一旦局部架构受损则可能面临全盘崩溃的危险;而且单体架构的迭代操作,比较复杂,部署速度慢不说,还会出现阻塞持续集成的现象,这对于要求时效性且相对复杂的生产环境来说,是不言而喻的灾难。基于此,便出现了小的模块化的自治服务架构,即我们常说的微服务架构。因为它所有的节点都被连接到了API网关,所以API网关的用户都会自动连接到这个完整的系统来调用或者聚合所需资源,来完成整个工作。所以,微服务架构在目前来看,基本解决了单体架构的弊端,这如同使用并联的灯泡组,即使一个灯泡损坏,亦不会影响全局的稳定和整体的生产进度,更不会出现整个局部系统的损坏而导致整体系统全面崩塌的灾难性后果。众所周知的是,任何一种架构的运用都会面临一些问题,我们采用的微服务架构也不例外。虽然微服务架构本身具有稳定、轻量、高速的特性,但是在现实的企业生产环境部署过程中,也会出现诸如调度、负载均衡、集群管理、有状态数据的管理等问题。而作为一切以服务为中心的K8s,则为我们提供了解决上述问题的最佳方式。K8s拥抱微服务就成为大势所趋。作为上届大会的焦点 - K8s如何更好的拥抱微服务?主题演讲有这些分享:Zhenqin (Alan) Liao(华为云 PaaS 服务产品部部长)的“垂直扩展,Kubernetes 如何加速各行业的云原生移动”Vicki Cheung(Lyft 工程经理)的“Kubernetes 是架构的基础层”Brendan Burns(杰出工程师及Microsoft K8s 联合创始人)的“Kubernetes 无服务器架构的现在和未来”专题演讲也分享了不少:Tony Erwin和Jonathan Schweikhart(IBM)的“将企业微服务从Cloud Foundry迁移到Kubernetes”Xiang Li(阿里巴巴)的“日新月异的 Sigma:在阿里巴巴使用 Kubernetes”Dan Romlein和Spencer Sugarman(Google)的“用户介面:利用 Kubernetes Dashboard 并决定其未来”Peter Zhao和Yuan Ji(ZTE)的“Kubernetes:使用、贡献并享受它!“Land Lu和Zhang Lei Mao(Canonical)的“利用 MicroK8s 和 Kubeflow 达成的 Kubernetes CICD 小技巧”Hui Chi(PetroChina)和Kai Chen(Alauda)的“石油巨头与Kubernetes, Microservice & DevOps共舞”Shikha Srivastava和Erica Brown(IBM)的“通过 Kubernetes 实现从容器化应用到安全和缩放”YIN SUN(小米)的“从 Mesos 到 Kubernetes”那么,在2019年,这些议题又会有哪些大咖加以完善,并与您分享更新的实战观点呢?敬请关注,今年2019年,CNCF和LF为您即将呈现的开源技术盛宴 - KubeCon + CloudNativeCon 和 Open SourceSummit(原LC3)。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 7, 2019 · 1 min · jiezi

Kubernetes概念与术语

综述学习Kubernetes时,发现它的概念和术语还是比较多的,光靠啃官方文档比较晦涩。所以边学习边整理,对主要的概念和术语做一下分类及简要说明。感觉把重要概念都理解了,对Kubernetes的设计思想,整体框架也就有了初步的认识。从功能上来说,我把Kubernetes的概念或术语大概分为以下三类:组件:指实际在集群中运行的Kubernetes程序集,分为Master组件、Node组件及附加组件。对象:对象是一个抽象的概念实体,Kubernetes把应用、运行场景、功能、集群状态等都抽象成一个个对象,并通过API对这些对象进行管理,从而管理整个集群的状态。标识:对组件和对象的各种表示方式,例如命名、标签、注释等。标识是KubernetesAPI与操作对象间的纽带。组件Master组件Master组件提供了k8s管理集群的核心功能,k8s通过Master组件实现整个集群的调度管理,它就像集群的大脑,会根据集群当前的状态,不断进行调整,使集群一直保持在期望的状态。Master组件包括以下几个进程:kube-apiserverapiserver进程对外暴露REST API接口给外部客户端及内部组件调用,它封装了对各个对象的增、删、改、查操作,可以说是整个集群管理的总入口。kube-schedulerkube-scheduler做的事情说来简单–监控新pod的创建,并把pod分配到合适的node来运行。但实际上,选择“合适的Node”是一个很复杂的过程,需要考虑的因素包括单node及整个集群的资源需求、软硬件资源的限制策略、数据存储、工作负载间的干扰等等。kube-controllers-managercontrollers-manager进程从字面上理解,是用来做控制器管理的。controllers-manager其实是一组守护进程,通过监控集群各组件的状态,并不断调整集群实际状态,使的集群向期望状态调整,它由一组子进程构成:replication controllerendpoints controllernamespace controllerserviceaccounts controllerEtcdEtcd是Kubernetes集群的基础组件,用于保存集群所有的元数据信息、配置信息、对象状态等。Node组件运行Node组件的节点称为Node节点,是k8s集群实际的工作负载节点。Node节点可以是物理机、虚拟机或任何可以运行Node组件的设备。所有的业务应用都运行在Node节点中。Node组件包括以下几个部分:Kubeletkubelet负责实际的容器管理,Kubernetes通过apiserver给kubelet发送Pod管理请求,同时把Pod及Node的运行状态汇报给apiserver。kube-proxykube-proxy负责集群内部的请求转发及负载均衡工作。它通过Service对象的配置信息,为Pod创建代理服务,实现请求从Service到Pod的路由转发。容器运行时实际的容器运行引擎。Kubernetes其实支持其他的容器技术比如rkt,但是Docker相比与它们处于绝对的优势地位。所以,Kubernetes生态中的容器也基本特指指Docker容器。对象Kubernetes中,所谓对象指的就是API对象。Kubernetes集群为每个对象维护三类信息:对象元数据(ObjectMeta)、期望状态(Desired State)与实际状态(Autual State),元数据指对象的基本信息,比如命名、标签、注释等等,用于识别对象;期望状态一般由用户配置spec来描述的;实际状态是由集群各个组件上报的集群实际的运行情况。Kubernetes努力使每个对象的实际状态与期望状态相匹配,从而使整个集群的状态与用户配置的期望状态一致。Kubernetes对象一般用yaml文件来描述,有几个个字段是必须的:apiVersion: 创建该对象所使用的 Kubernetes API 的版本kind: 想要创建的对象的类型metadata: 帮助识别对象唯一性的数据,包括一个 name 字符串、UID 和可选的 namespacespec: 对象期望状态的描述用户通过命令行工具kubectl来操作这些对象,Kubectl吧yaml转换成JSON格式来执行API请求。下面是一个POD对象的描述文件示例及注释:apiVersion: v1kind: Pod # 对象名称metadata: # 对象的基本信息 name: pod-example # 对象唯一标示spec: # 期望状态 containers: # 指定pod中运行的容器镜像及运行参数(类似Dockerfile) - name: ubuntu image: ubuntu:trusty command: [“echo”] args: [“Hello World”]其中,kind字段描述对象类型"Pod",spec之前是对象的ObjectMeta,spec开始,就是对象期望状态的描述。根据官方API对象参考文档的分类,下面我们把对象分为几大类来分别简要说明。计划以后的文章,会结合实际操作,对各个重要对象做更深入的说明。Workloads 资源对象- workloads类的对象用于管理运行容器实例Pod: Pod是Kubernetes里最重要的对象,也是Kubernetes集群中运行部署应用或服务的最小单位。Pod对象描述一个Pod由哪些容器镜像构成,以及这些容器应该怎么运行。类比传统的业务架构,Pod更接近于虚拟机的角色而不是应用进程的角色。ReplicaSet: ReplicaSet对象是对Pod的更高一层抽象,它用来管理一组相同POD副本,并确保这组相同Pod的数量始终与用户期望一致,并实现Pod的高可用。即如果有容器异常退出,ReplicaSet会自动创建新的Pod来替代,保证Pod数量永远与用户配置一致。Deployment: Deployment对象是Kubernetes中最常用的对象之一,用于部署无状态服务。它在ReplicaSet对象的基础上,又做了一层抽象。通过管理多组ReplicaSet对象,来实现POD的滚动升级、回滚、扩容缩容等。StatefulSet: 不同于Deployment,StatefulSet对象顾名思义是对有状态服务的一种抽象。所以,StatefulSet对象在定义时,相比与Deployment多了一些与状态相关的内容,比如持久化存储、服务对外的不变的唯一标示、部署、扩容、滚动升级时确保有序等等。DaemonSet: DaemonSet对象是Kubernetes对守护进程的抽象。当我们需要集群中的每个Node都跑一些如日志收集、监控等守护进程时,就可以把这类型进程包装成Pod,并用调用DaemonSet来部署了。DaemonSet做的事情其实和Deployment差不多,只不过Deployment对象部署的Pod,会根据集群情况,在不同Node间自动调度。而DaemonSet会指定的NODE上(默认是集群所有Node),都部署定义Pod,确保这些NODE都有跑着守护进程Pod。Job、CronJob: 除了上面几个对象所抽象描述的应用工作场景外,实际业务场景中,还有一类应用或服务并不需要一直运行,比如一些一次性任务,或需要定时执行的任务。这种不需要长时间运行的任务,完成了就可以退出的服务,就可以用Job对象来定义。CronJob和Job对象的关系,和Deployment与ReplicaSet的关系很像,可以类比来理解。首先,Job也是直接用于管理Pod的,同时可以定义这个一次性任务Pod的执行时间、超时时间、错误处理(重启还是生成新Pod)等任务属性。而CronJob管理是用来管理Job,类似crobtab,它可以通过yaml文件中的schedule字段配置具体时间,来控制指定Job定时执行,从而实现定时执行特定的一次性任务。Discovery & LB 资源对象- 该类对象用于服务发现和负载均衡的对象Service:上面提到的对象都是用于管理POD及容器实例的。但是,业务系统光有POD实例还不够,还必须对外提供服务。这里就会衍生出两个问题:Pod的IP地址并不是固定,而是随着编排不断变化的,外面的请求怎么找到对应的POD,这个也就是大多数分布式业务都会遇到的服务发现问题多个相同Pod一起提供服务的时候,它们的负载均衡怎么实现而Service对象就是用来解决这两个问题的。它用固定的VIP或DNS名称和指定标识的一组Pod对应起来,不管Pod IP怎么变,Service对外的VIP都不会变化,并且,自动的将请求在这组Pod中负载均衡。Config & Storage 资源对象- 该类对象用于初始化容器配置及持久化容器存储的对象Volume:前面说到,Pod里的不同容器可以共享存储,这个共享存储就靠Volume来配置的。要注意的是,这里Volume与Docker中的定义不用,Kubernetes中Volume跟Pod生命周期一致,Pod终止了,该Pod挂载的Volume就失效了(根据挂载volume的类型不同,数据可能丢失也可能不丢失)。PV,PVC:Volume可以支持多种类型的存储,除了直接在Volume字段中去声明所有存储细节,K8S还抽象出了PV和PVC对象。简单来说PV是对具体存储资源的描述,比如存储类型、地址、访问账户等;而PVC,是对怎么使用资源的方法的描述,比如只读只写,需要的空间等;而Pod通过Volume字段挂载具体要使用的PVC。PV和PVC是独立于Pod单独定义的,这样,就把共享存储的配置、分割、挂载等操作都解耦了。比如,一个NFS迁移后ip地址变了,存储管理员只需要修改PV中的配置,而不用关心具体哪个业务POD在使用这个NFS。ConfigMap,SecuretK8S中除了常见的存储,还有一类特殊的Volume,不是为了Pod存放数据,而是为了给Pod提供数据的。ConfigMap和Secret对象就是用来定义这类型的Volume。简单来说,可以将它们理解为一份Key:Value格式的数据,Pod可以通过Volume挂载它们,将这份数据保存成文件随时调用。唯一的区别是,ConfigMap对象保存的数据是明文,一般作为应用配置文件;而Secret对象保存的对象要求是经过Base64转码的,用于提供数据库密码等对安全要求比较高的配置。不过这些配置,直接在做容器镜像时就配置不就好了,为啥要多此一举呢?原因和上面PV和PVC一样,都是为了尽可能解耦业务核心与经常可能变化的依赖配置。比如数据库更换了账号,只需要修改Secret对象,不用重新去构建容器镜像。Cluster resources objects- 该类对象定义整个K8S集群运行方式的对象NamespaceKubernetes作为一个集群管理平台,为不同用户划分不同权限管理,例如多租户等,是必备的功能。而不同用户作用域的隔离,就是靠Namespace对象实现的。Namespace是Kubernetes项目中的一个逻辑管理单位,不同Namespace的API对象,在调用API进行操作是,是相互隔离开的。通过不同用户角色与Namespace关联,从而实现权限管理。Metadata resources- 除了上述分类外的其他对象都归为这一类,一般用来管理集群的特殊功能比如弹性伸缩等Horizontal Pod Autoscaling容器作为一个轻量级的承载应用的技术,快速启动和快速部署是它的优点之一。自然的,根据业务负载自动扩缩容等需求,在容器集群的可行性和效率就可以变得很高。而Kubernetes中 Horizontal Pod Autoscaling对象,就是用于进行POD自动水平缩放的,这也是Kubernetes最能体现运维优势的特性之一。Horizontal Pod Autoscaling具体的操作对象是Deployment和ReplicaSet,通过不同循环获取每个Pod的资源情况,比如CPU利用率,并根据设定的目标利率来计算目前需要的Pod副本缩放的比例,然后通过访问相应的Deployment或ReplicaSet对象,来对Pod数量进行自动缩放,从而提高了集群资源整体利用率。标识标识是Kubernetes中最重要的概念,因为它是所有API的操作与操作对象间的纽带。Kubernetes中的标识主要有以下几种:LabelLabel可以说是Kubernetes中最最重要的核心概念,一个Lable是一个KEY=Value的键值对。任何对象资源都可以有一个或多个Label,而同个Label,也可以配置在多个对象上。然后重点来了,大多数API对象的yaml字段中,都有Label Selector字段,可以实现对Label中的key或value的多维度选择,例如in、not in、and、or等等。这样,Kubernetes对API作用对象就能进行多维度,细粒度的选择,从而实现比较精细化的容器编排调度工作,比如,对所有"ENV:release"执行扩容操作,或者把部分请求灰度到有"ver:v1.14.0"的pod上等等。Label把资源对象和应用、基础设施都解耦了,你不用关心这个Pod具体在那个Node上运行,也不用关心具体是什么应用用了哪个容器镜像,只要Label符合Label Selector,就可以通过API调用统一进行操作。Names除了Label,所有资源对象肯定还必须有一个全局唯一的标识,即Names字段。AnnotationAnnotation很好理解,与通常意义的注释一样,用于描述作者、版本、配置说明等等任何需要的信息,需要说明的是,Annotation也必须是Key:Value格式的。总结通过上面对Kubernetes重要概念的说明,我们可以大致梳理出Kubernetes的一些设计理念:Kubernetes对容器应用进行了抽象,例如把一个容器或强关联的一组容器抽象为Pod,把各类存储都抽象成Volume,把一组Pod抽象成Service等等基础对象。在基础对象的层面上,Kubernetes又对应用使用场景,做了一层抽象。极客时间的Kubernetes课程有一张图画的很好:可以看到,Kubernetes中各个对象实际就是对生产业务场景的各类需求的抽象。抽象出各类型对象以后,用户可以通过yaml文件(或直接命令行调用API)来描述这些对象的期望状态,确认了各对象些期望状态的集合,也就确认了整个集群的期望状态。这些所有的操作,都是声明式的,而不是命令集群要怎么做Kubernetes通过控制器循环不断将各组件收集来的集群实际状态与各对象的期望状态对比,并自动化的将集群实际状态向期望状态转移,这个过程,也就是Kubernetes最核心的概念:编排。本文对Kubernetes中的重要概念做了分类和简要,后面的文章会结合集群的实际操作,对每个概念做更详细的说明。 ...

March 6, 2019 · 1 min · jiezi

实战生产环境:1.13.3最新版k8s集群部署Heapster插件

本篇文章,所使用的任何镜像和yaml我都会发一个网盘链接,供大家下载学习!链接:https://pan.baidu.com/s/1inmW… 密码:92uagithub:https://github.com/heyangguang有任何问题可以直接联系我的Email:heyangev@cn.ibm.comHeapster是一个收集者,将每个Node上的cAdvisor的数据进行汇总,然后导到第三方工具(如InfluxDB)。Heapster介绍架构图:Heapster首先从K8S Master获取集群中所有Node的信息,然后通过这些Node上的kubelet获取有用数据,而kubelet本身的数据则是从cAdvisor得到。所有获取到的数据都被推到Heapster配置的后端存储中,并还支持数据的可视化。现在后端存储 + 可视化的方法,如InfluxDB + grafana。部署实施:下载heapster镜像,上传heapster.yaml、heapster-mod.yaml文件apply就可以了。k8smaster:[root@k8smaster ~]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/heapster-amd64:v1.5.4Trying to pull repository registry.cn-hangzhou.aliyuncs.com/google_containers/heapster-amd64 …v1.5.4: Pulling from registry.cn-hangzhou.aliyuncs.com/google_containers/heapster-amd6491380601464e: Pull completef351486260ed: Pull completeDigest: sha256:c4a8d9c0007abb73a1b9e4f9c8bfb044e475aae2b4e6276ab2f8b13959cf6949Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/google_containers/heapster-amd64:v1.5.4[root@k8smaster ~]# lsanaconda-ks.cfg heapster-mod.yaml heapster.yaml images.tar kube-flannel.yml[root@k8smaster ~]# kubectl apply -f heapster.yamlserviceaccount/heapster createdclusterrolebinding.rbac.authorization.k8s.io/heapster createddeployment.apps/heapster createdservice/heapster created[root@k8smaster ~]# kubectl apply -f heapster-mod.yamlWarning: kubectl apply should be used on resource created by either kubectl create –save-config or kubectl applyclusterrole.rbac.authorization.k8s.io/system:heapster configured查看状态:[root@k8smaster ~]# kubectl get pods -n kube-systemNAME READY STATUS RESTARTS AGEcoredns-86c58d9df4-kmfct 1/1 Running 0 23mcoredns-86c58d9df4-qn2k2 1/1 Running 0 23metcd-k8smaster 1/1 Running 0 23mheapster-569b679494-rktzf 1/1 Running 0 18skube-apiserver-k8smaster 1/1 Running 1 22mkube-controller-manager-k8smaster 1/1 Running 0 22mkube-flannel-ds-amd64-9rmfz 1/1 Running 0 19mkube-flannel-ds-amd64-vnwtf 1/1 Running 0 15mkube-flannel-ds-amd64-x7q4s 1/1 Running 0 15mkube-proxy-7zl9n 1/1 Running 0 22mkube-proxy-t2sx9 1/1 Running 0 23mkube-proxy-txsfr 1/1 Running 0 22mkube-scheduler-k8smaster 1/1 Running 0 23m稍等一会,使用kubectl top node查看集群状态即可:[root@k8smaster ~]# kubectl top nodeNAME CPU(cores) CPU% MEMORY(bytes) MEMORY%k8smaster 122m 3% 2848Mi 8%k8snode-1 27m 0% 603Mi 1%k8snode-2 26m 0% 582Mi 1%到这里heapster收集集群数据教程就完成了!希望大家可以给我指出问题,我们一起前进!谢谢大家! ...

March 6, 2019 · 1 min · jiezi

详细教程丨如何在Kubernetes上部署Redis集群

介 绍Redis(REmote DIctionary Server的意思)是一个开源的内存数据存储,通常用作数据库、缓存以及消息代理。它可以存储和操作高级的数据结构类型,比如lists、maps、sets以及排序sets。Redis接受多种格式的键,因此可以在服务器上执行操作,减少客户端的工作负载。它将数据库完全地保存在内存中,只使用磁盘进行持久化存储。Redis是一种流行的数据存储解决方案,受到了Github、Pinterest、Snapchat、Twitter、StackOverflow、Flickr等科技巨头的青睐。为什么要用Redis?它非常快,它由ANSI C编写,可以在Linux、Mac OS X和Solaris等POSIX系统上运行。Reis经常被评为最流行的键值数据库以及在容器上使用最流行的NoSQL数据库。它的缓存解决方案减少了对云数据库后端的调用。应用程序可以通过客户端API库访问它。所有流行的编程语言都支持Redis。它开源且非常稳定的。Redis的应用案例Facebook的一些在线游戏中,游戏分数更新频率非常高。当使用Redis排序set时,即使每分钟有数百万用户和数百万个新分数,执行这些操作都非常简单。Twitter在Redis集群中存储了所有用户的时间线。Pinterest将用户关注者图存储在Redis集群中,其中的数据分布在数百个实例中。Github使用Redis作为队列什么是Redis集群?Redis集群是一个多Redis实例的集合,用于通过对数据库分区来扩展数据库,使其更具有弹性。集群中的每个成员,无论是主副本还是次级副本,都管理哈希槽的一个子集。如果一个主服务器出现不能访问的故障,那么它的从属服务器会提升为主服务器。在由三个主节点组成的最小的Redis集群中,每个主节点都有一个从属节点(为了至少能保证最低程度的故障转移),每个主节点分配一个范围在0至16383之间的哈希槽。节点A包含哈希槽范围为从0到5000,节点B为5001到10000,节点C从10001到18383。集群内部的通信则通过内部总线进行,使用gossip协议来传播关于集群的信息或者发现新节点。在Kubernetes上部署Redis集群在Kubernetes中部署Redis集群很有挑战,因为每个Redis实例都依赖于一个配置文件,该文件跟踪其他集群实例及其角色。为此,我们需要结合使用Kubernetes状态集(StatefulSets)和持久卷(PersistentVolumes)。前期准备要完成此次的demo,我们需要有下列准备:RancherGoogle云平台或者其他云提供商账号。下面的展示中使用了GKE,不过使用任何云提供商都是可以的,且操作方法大致相同。启动Rancher实例如果你没有Rancher的实例,可以参考这里的Quick Start文档简单快速地启动一个:https://rancher.com/quick-start/用Rancher部署GKE集群用Rancher启动并配置你的Kubernetes集群,具体步骤可以参考文档:https://rancher.com/docs/ranc…当集群准备就绪,我们可以通过kubectl指令检查当前状态部署Redis接着部署Redis集群,我们既可以通过kubectl来应用YAML文件,也可以将它们导入到Rancher UI中。下面列出了我们所有需要的YAML文件。YAML内容如下:redis-sts.yamlredis-svc.yaml验证部署检查Redis节点是否启动并运行:下面的6个卷是我们创建的$ kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpvc-ae61ad5c-f0a5-11e8-a6e0-42010aa40039 1Gi RWO Delete Bound default/data-redis-cluster-0 standard 7mpvc-b74b6ef1-f0a5-11e8-a6e0-42010aa40039 1Gi RWO Delete Bound default/data-redis-cluster-1 standard 7mpvc-c4f9b982-f0a5-11e8-a6e0-42010aa40039 1Gi RWO Delete Bound default/data-redis-cluster-2 standard 6mpvc-cd7af12d-f0a5-11e8-a6e0-42010aa40039 1Gi RWO Delete Bound default/data-redis-cluster-3 standard 6mpvc-d5bd0ad3-f0a5-11e8-a6e0-42010aa40039 1Gi RWO Delete Bound default/data-redis-cluster-4 standard 6m我们可以检查任何一个pod,看看它添加的卷:$ kubectl describe pods redis-cluster-0 | grep pvc Normal SuccessfulAttachVolume 29m attachdetach-controller AttachVolume.Attach succeeded for volume “pvc-ae61ad5c-f0a5-11e8-a6e0-42010aa40039” 同样的数据还可以在Rancher UI上看到部署Redis集群下一步就是创建Redis集群了。为此,我们需要运行以下命令,输入yes接受配置。前三个节点成为主节点,最后三个节点设置为从属节点。$ kubectl exec -it redis-cluster-0 – redis-cli –cluster create –cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath=’{range.items[*]}{.status.podIP}:6379 ‘)以下是完整的输出命令:>>> Performing hash slots allocation on 6 nodes…Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 10.60.1.13:6379 to 10.60.2.12:6379Adding replica 10.60.2.14:6379 to 10.60.1.12:6379Adding replica 10.60.1.14:6379 to 10.60.2.13:6379M: 2847de6f6e7c8aaa8b0d2f204cf3ff6e8562a75b 10.60.2.12:6379slots:[0-5460] (5461 slots) masterM: 3f119dcdd4a33aab0107409524a633e0d22bac1a 10.60.1.12:6379slots:[5461-10922] (5462 slots) masterM: 754823247cf28af9a2a82f61a8caaa63702275a0 10.60.2.13:6379slots:[10923-16383] (5461 slots) masterS: 47efe749c97073822cbef9a212a7971a0df8aecd 10.60.1.13:6379replicates 2847de6f6e7c8aaa8b0d2f204cf3ff6e8562a75bS: e40ae789995dc6b0dbb5bb18bd243722451d2e95 10.60.2.14:6379replicates 3f119dcdd4a33aab0107409524a633e0d22bac1aS: 8d627e43d8a7a2142f9f16c2d66b1010fb472079 10.60.1.14:6379replicates 754823247cf28af9a2a82f61a8caaa63702275a0Can I set the above configuration? (type ‘yes’ to accept): yes>>> Nodes configuration updated>>> Assign a different config epoch to each node>>> Sending CLUSTER MEET messages to join the clusterWaiting for the cluster to join….>>> Performing Cluster Check (using node 10.60.2.12:6379)M: 2847de6f6e7c8aaa8b0d2f204cf3ff6e8562a75b 10.60.2.12:6379slots:[0-5460] (5461 slots) master1 additional replica(s)S: 47efe749c97073822cbef9a212a7971a0df8aecd 10.60.1.13:6379slots: (0 slots) slavereplicates 2847de6f6e7c8aaa8b0d2f204cf3ff6e8562a75bM: 754823247cf28af9a2a82f61a8caaa63702275a0 10.60.2.13:6379slots:[10923-16383] (5461 slots) master1 additional replica(s)M: 3f119dcdd4a33aab0107409524a633e0d22bac1a 10.60.1.12:6379slots:[5461-10922] (5462 slots) master1 additional replica(s)S: e40ae789995dc6b0dbb5bb18bd243722451d2e95 10.60.2.14:6379slots: (0 slots) slavereplicates 3f119dcdd4a33aab0107409524a633e0d22bac1aS: 8d627e43d8a7a2142f9f16c2d66b1010fb472079 10.60.1.14:6379slots: (0 slots) slavereplicates 754823247cf28af9a2a82f61a8caaa63702275a0[OK] All nodes agree about slots configuration.>>> Check for open slots…>>> Check slots coverage… [OK] All 16384 slots covered.验证集群部署检查集群细节以及每个成员的角色测试Redis集群我们希望使用集群并且模拟节点故障。对于前一个任务,我们将部署一个简单的python应用程序,而后一个任务,我们将删除一个节点来观察集群行为。部署Hit Counter应用我们将在集群中部署一个简单的应用程序,并在其之前放置一个负载均衡器。该应用程序的目的是在将计数器的值作为HTTP响应返回值返回之前,增加计数器的值,并将值存到Redis集群上。使用kubectl或者Rancher UI部署:YAML内容如下:app-deployment-service.yamlRancher展示了我们创建的资源:一个包含python应用的pod,以及LoadBalancer类型的服务。该服务的详细信息内,将显示其公共IP地址:到了这一步,我们可以用浏览器访问IP,生成hit counter的值:模拟节点故障我们可以通过删除pod(使用kubectl或Rancher UI)来模拟集群成员的故障。当我们删除原先是master的redis-cluster-0时,我们看到Kubernetes将redis-cluster-3提升为master,而当redis-cluster-0重新回来时,redis-cluster-3会重新恢复从属身份。之 前之 后我们可以看到redis-cluster-0的IP发生了变化,那么集群是如何恢复的呢?在创建集群时,我们创建了ConfigMap,该ConfigMap又在/conf/update-node.sh处创建了一个脚本,容器在启动时调用该脚本。该脚本使用本地节点的新IP地址更新Redis配置。有了confic中的新IP,集群就可以在新的pod中以不同的IP地址启动并恢复。在这个过程中,如果我们继续加载页面,计数器仍会继续增加,在集群收敛之后,我们会看到没有丢失任何数据。结 论Redis是一个强大的数据存储和缓存工具。因为Redis存储数据的方式,Redis集群更是能通过提供分片、相关性能优势、线性扩展和高可用性,来进一步扩展其功能。数据在多个节点之间自动分割,即使节点的子集出现故障或者不能和集群其他部分通信,操作仍然能够继续。有关Redis集群的更多信息,请访问教程(https://redis.io/topics/clust…)或者文档(https://redis.io/topics/clust…)。有关Rancher的更多信息,请访问我们的主页(https://www.cnrancher.com)或者部署文档(https://www.cnrancher.com/doc…)。 ...

March 6, 2019 · 2 min · jiezi

CNCF参与Google Summer of Code 2019!感兴趣的学生现在是加入的最佳时机

Google Summer of Code(GSoC)是面向开源开发领域新贡献者的最知名和最受欢迎的计划之一,我们很高兴地宣布CNCF(Cloud Native Computing Foundation,云原生计算基金会)参与GSoC 2019!CNCF是过去几年(包括2017年和2018年)GSoC中最活跃的参与者之一,我们将在2019年继续这项工作,有近50个项目构想涉及13个CNCF项目。如果你是学生,计划参加GSoC 2019,现在是审查项目构想,并与导师开始讨论的最佳时机。这里分享一篇去年浙江大学研究生,在谐云实习的Jian Liu,有关“GSoC 18:Kata Containers对containerd的支持”的经验。Kubernetes项目构想Integrate kube-batch with pytorch-operator/mxnet-operatorImplement volume snapshotting support into the external Manila provisionerEnable full e2e tests for external Azure cloud providerCSI driver for AzureDiskCSI driver for AzureFileCSI driver for BlobfuseStreamline and simplify SASS for the Kubernetes websiteFully automate API and reference doc generationAdd support for Custom Resource Definitions to the DashboardAdd plugin mechanism to the DashboardPrometheus项目构想Benchmarks for TSDBContinue the work on PrombenchPersist Retroactive Rule ReevaluationsOptimize queries using regex matchers for set lookupsPackage for bulk importsOpen Policy Agent (OPA)项目构想IntelliJ plugin to experiment with and visualize policy evaluationInteractive website detailing OPA integrationsIntegration with IPTablesCoreDNS项目构想Support source-IP based query block/allowSupport Google Cloud DNS backendSupport Azure DNS backendTiKV项目构想Migrate to tower-grpcIntroduce other storage enginesBuild TiKV clients in different languagesAuto-tune RocksDBRook项目构想Upgrade Rook to a more advanced operator/controller frameworkStorage provider features and enhancementsEnable multiple network interfaces for Rook storage providersEnhance and extend the Rook framework for storage solutionsExpand coverage and scope of Rook’s continuous integration (CI) systemDynamic provisioning for portable workloadsLinkerd and Envoy项目构想Benchmarks for Linkerd and EnvoyVirtual Kubelet项目构想Conformance testing for Virtual KubeletLinkerd项目构想Cross-cloud integration testingAuto-UpdateConformance ValidationAlertmanager IntegrationKafka Introspectionrkt项目构想Add support for the OCI runtime spec by implementing a runc stage2Add native OCI image supportcontainerd项目构想Snapshotter implementation for block devicesp2p or remote blob store implementationFalco项目构想Improved Falco OutputsAdditional Event SourcesLayer 7 Inspection and DetectionFalco integration with AI/ML platformsPrometheus Metrics ExporterPerformance Analysis and OptimizationFalco rules profiles for applications and security benchmarksCortex项目构想Improve Ingester HandoverCentralized Rate LimitingUse etcd in Cortex请在CNCF的GitHub页面上查看2019年项目构想的完整列表,包括描述、推荐技巧和导师资料等。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 6, 2019 · 2 min · jiezi

实战生产环境:kubeadmin安装1.13.3最新版k8s集群教程

2019年3月6日:出版安装kubeadmin部署k8s集群教程本次安装采用kubeadmin !安装的k8s版本为1.13.3版,是当前最新版本!本篇文章,所使用的任何镜像和yaml都会在我的github上找到!github:https://github.com/heyangguang有任何问题可以直接联系我的Email:heyangev@cn.ibm.com主机列表:系统采用的是Centos7.5主机名IP地址角色k8smaster9.186.137.114masterk8snode-19.186.137.115nodek8snode-29.186.137.116Node基础环境准备:关闭防火墙、关闭selinux,关闭swap,关闭网卡管理器。k8smaster:[root@k8smaster ~]# systemctl stop firewalld[root@k8smaster ~]# systemctl disable firewalld[root@k8smaster ~]# systemctl stop NetworkManager ; systemctl disable NetworkManager[root@k8smaster ~]# vim /etc/selinux/config[root@k8smaster ~]# scp /etc/selinux/config root@k8snode-1:/etc/selinux/configconfig 100% 546 1.1MB/s 00:00[root@k8smaster ~]# scp /etc/selinux/config root@k8snode-2:/etc/selinux/configconfig 100% 546 1.3MB/s 00:00[root@k8smaster ~]# swapoff -a[root@k8smaster ~]# vim /etc/fstab[root@k8smaster ~]# cat /etc/fstab## /etc/fstab# Created by anaconda on Mon Mar 4 17:23:04 2019## Accessible filesystems, by reference, are maintained under ‘/dev/disk’# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info#/dev/mapper/centos-root / xfs defaults 0 0UUID=3dd5660e-0905-4f1e-9fa3-9ce664d6eb94 /boot xfs defaults 0 0/dev/mapper/centos-home /home xfs defaults 0 0#/dev/mapper/centos-swap swap swap defaults 0 0k8snode-1:[root@k8snode-1 ~]# systemctl stop firewalld[root@k8snode-1 ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.[root@k8snode-1 ~]# systemctl stop NetworkManager ; systemctl disable NetworkManager[root@k8snode-1 ~]# swapoff -a[root@k8snode-1 ~]# vim /etc/fstabk8snode-2:[root@k8snode-2 ~]# systemctl stop firewalld[root@k8snode-2 ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.[root@k8snode-2 ~]# swapoff -a[root@k8snode-2 ~]# systemctl stop NetworkManager ; systemctl disable NetworkManager[root@k8snode-2 ~]# vim /etc/fstabyum源配置:需要k8snode-1和k8snode-2先操作,在把yum源copy过去。k8smaster:[root@k8smaster yum.repos.d]# rm -rf [root@k8smaster yum.repos.d]# ll总用量 12-rw-r–r– 1 root root 2206 3月 5 18:50 CentOS-Base.repo-rw-r–r– 1 root root 923 3月 5 18:50 epel.repo-rw-r–r– 1 root root 276 3月 5 18:50 k8s.repo[root@k8smaster yum.repos.d]# scp * k8snode-1:/etc/yum.scp: /etc/yum.: No such file or directory[root@k8smaster yum.repos.d]# scp * k8snode-1:/etc/yum.repos.d/CentOS-Base.repo 100% 2206 352.0KB/s 00:00epel.repo 100% 923 160.8KB/s 00:00k8s.repo 100% 276 48.2KB/s 00:00[root@k8smaster yum.repos.d]# scp * k8snode-2:/etc/yum.repos.d/CentOS-Base.repo 100% 2206 216.3KB/s 00:00epel.repo 100% 923 157.1KB/s 00:00k8s.repo 100% 276 47.5KB/s 00:00k8snode-1:[root@k8snode-1 ~]# cd /etc/yum.repos.d/[root@k8snode-1 yum.repos.d]# rm -rf k8snode-2:[root@k8snode-2 ~]# rm -rf /etc/yum.repos.d/安装Docker引擎:k8smaster:[root@k8smaster yum.repos.d]# yum -y install docker[root@k8smaster yum.repos.d]# systemctl start docker ; systemctl enable dockerCreated symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.k8snode-1:[root@k8snode-1 yum.repos.d]# yum -y install docker[root@k8snode-1 yum.repos.d]# systemctl start docker ; systemctl enable dockerCreated symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.k8snode-2:[root@k8snode-2 ~]# yum -y install docker[root@k8snode-2 ~]# systemctl start docker ; systemctl enable dockerCreated symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.设置k8s相关系统内核参数:k8smaster:[root@k8smaster ~]# cat << EOF > /etc/sysctl.d/k8s.conf> net.bridge.bridege-nf-call-iptables = 1> net.bridge.bridege-nf-call-ip6tables = 1> EOF[root@k8smaster ~]# sysctl -pk8snode-1:[root@k8snode-1 ~]# cat << EOF > /etc/sysctl.d/k8s.conf> net.bridge.bridege-nf-call-iptables = 1> net.bridge.bridege-nf-call-ip6tables = 1> EOF[root@k8snode-1 ~]# sysctl -pk8snode-2:[root@k8snode-2 ~]# cat << EOF > /etc/sysctl.d/k8s.conf> net.bridge.bridege-nf-call-iptables = 1> net.bridge.bridege-nf-call-ip6tables = 1> EOF[root@k8snode-2 ~]# sysctl -p安装kubernetes相关组件:k8smaster:[root@k8smaster ~]# yum install -y kubelet-1.13.3 kubeadm-1.11.1 kubectl-1.13.3 –disableexcludes=kubernetes[root@k8smaster ~]# systemctl start kubelet ; systemctl enable kubeletCreated symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.k8snode-1:[root@k8snode-1 ~]# yum install -y kubelet-1.13.3 kubeadm-1.11.1 kubectl-1.13.3 –disableexcludes=kubernetes[root@k8snode-1 ~]# systemctl start kubelet ; systemctl enable kubeletCreated symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.k8snode-2:[root@k8snode-2 ~]# yum install -y kubelet-1.13.3 kubeadm-1.11.1 kubectl-1.13.3 –disableexcludes=kubernetes[root@k8snode-2 ~]# systemctl start kubelet ; systemctl enable kubeletCreated symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.导入所需要的镜像:为什么要导入镜像呢?因为kubeadmin会去谷歌的镜像源上面下载,大家都懂得!所以我下载下来,使用的时候直接导入就好了。所需要的镜像:k8s.gcr.io/kube-apiserver:v1.13.3k8s.gcr.io/kube-controller-manager:v1.13.3k8s.gcr.io/kube-scheduler:v1.13.3k8s.gcr.io/kube-proxy:v1.13.3k8s.gcr.io/etcd:3.2.24k8s.gcr.io/coredns:1.2.6k8s.gcr.io/pause:3.1这里所用到的镜像,我会全部打包到我的github上,需要的可以去下载。导入方式相同,只需要全部导入即可!k8smaster:[root@k8smaster ~]# lsanaconda-ks.cfg images.tar[root@k8smaster ~]# ll总用量 1834184-rw——-. 1 root root 1245 3月 4 17:27 anaconda-ks.cfg-rw-r–r–. 1 root root 1878197248 3月 5 18:31 images.tar[root@k8smaster ~]# docker load < images.tark8snode-1:[root@k8snode-1 ~]# lsanaconda-ks.cfg images.tar[root@k8snode-1 ~]# docker load < images.tark8snode-2:[root@k8snode-2 ~]# lsanaconda-ks.cfg images.tar[root@k8snode-2 ~]# docker load < images.tarmaster上初始化kubeadmin生成node token:使用kubeadm init 初始化环境,–kubernetes-version指定版本,-pod-network-cidr指定虚拟网络的网段,可以随便指定任何网段![root@k8smaster ~]# kubeadm init –kubernetes-version=v1.13.3 –pod-network-cidr=10.244.0.0/16[init] using Kubernetes version: v1.13.3[preflight] running pre-flight checks [WARNING KubernetesVersion]: kubernetes version is greater than kubeadm version. Please consider to upgrade kubeadm. kubernetes version: 1.13.3. Kubeadm version: 1.11.xI0305 19:49:27.250624 5373 kernel_validator.go:81] Validating kernel versionI0305 19:49:27.250718 5373 kernel_validator.go:96] Validating kernel config[preflight/images] Pulling images required for setting up a Kubernetes cluster[preflight/images] This might take a minute or two, depending on the speed of your internet connection[preflight/images] You can also perform this action in beforehand using ‘kubeadm config images pull’[kubelet] Writing kubelet environment file with flags to file “/var/lib/kubelet/kubeadm-flags.env”[kubelet] Writing kubelet configuration to file “/var/lib/kubelet/config.yaml”[preflight] Activating the kubelet service[certificates] Generated ca certificate and key.[certificates] Generated apiserver certificate and key.[certificates] apiserver serving cert is signed for DNS names [k8smaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 9.186.137.114][certificates] Generated apiserver-kubelet-client certificate and key.[certificates] Generated sa key and public key.[certificates] Generated front-proxy-ca certificate and key.[certificates] Generated front-proxy-client certificate and key.[certificates] Generated etcd/ca certificate and key.[certificates] Generated etcd/server certificate and key.[certificates] etcd/server serving cert is signed for DNS names [k8smaster localhost] and IPs [127.0.0.1 ::1][certificates] Generated etcd/peer certificate and key.[certificates] etcd/peer serving cert is signed for DNS names [k8smaster localhost] and IPs [9.186.137.114 127.0.0.1 ::1][certificates] Generated etcd/healthcheck-client certificate and key.[certificates] Generated apiserver-etcd-client certificate and key.[certificates] valid certificates and keys now exist in “/etc/kubernetes/pki”[kubeconfig] Wrote KubeConfig file to disk: “/etc/kubernetes/admin.conf”[kubeconfig] Wrote KubeConfig file to disk: “/etc/kubernetes/kubelet.conf”[kubeconfig] Wrote KubeConfig file to disk: “/etc/kubernetes/controller-manager.conf”[kubeconfig] Wrote KubeConfig file to disk: “/etc/kubernetes/scheduler.conf”[controlplane] wrote Static Pod manifest for component kube-apiserver to “/etc/kubernetes/manifests/kube-apiserver.yaml”[controlplane] wrote Static Pod manifest for component kube-controller-manager to “/etc/kubernetes/manifests/kube-controller-manager.yaml”[controlplane] wrote Static Pod manifest for component kube-scheduler to “/etc/kubernetes/manifests/kube-scheduler.yaml”[etcd] Wrote Static Pod manifest for a local etcd instance to “/etc/kubernetes/manifests/etcd.yaml”[init] waiting for the kubelet to boot up the control plane as Static Pods from directory “/etc/kubernetes/manifests”[init] this might take a minute or longer if the control plane images have to be pulled[apiclient] All control plane components are healthy after 19.502118 seconds[uploadconfig] storing the configuration used in ConfigMap “kubeadm-config” in the “kube-system” Namespace[kubelet] Creating a ConfigMap “kubelet-config-1.13” in namespace kube-system with the configuration for the kubelets in the cluster[markmaster] Marking the node k8smaster as master by adding the label “node-role.kubernetes.io/master=’’"[markmaster] Marking the node k8smaster as master by adding the taints [node-role.kubernetes.io/master:NoSchedule][patchnode] Uploading the CRI Socket information “/var/run/dockershim.sock” to the Node API object “k8smaster” as an annotation[bootstraptoken] using token: xjzf96.nv0qhqwj9j47r1tv[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster[bootstraptoken] creating the “cluster-info” ConfigMap in the “kube-public” namespace[addons] Applied essential addon: CoreDNS[addons] Applied essential addon: kube-proxyYour Kubernetes master has initialized successfully!To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configYou should now deploy a pod network to the cluster.Run “kubectl apply -f [podnetwork].yaml” with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/You can now join any number of machines by running the following on each nodeas root: kubeadm join 9.186.137.114:6443 –token xjzf96.nv0qhqwj9j47r1tv –discovery-token-ca-cert-hash sha256:e386175a5cae597dec6bfeb7c92d01bc5fe052313b50dc48e419057c8c3f824c [root@k8smaster ~]# mkdir -p $HOME/.kube[root@k8smaster ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config[root@k8smaster ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/confignode节点执行kubeadm join加入集群:注意!一定要时间同步,否则就会出问题!报这个错误:[discovery] Failed to request cluster info, will try again: [Get https://9.186.137.114:6443/api/v1/namespaces/kube-public/configmaps/cluster-info: x509: certificate has expired or is not yet valid]k8snode-1:[root@k8snode-1 ~]# kubeadm join 9.186.137.114:6443 –token xjzf96.nv0qhqwj9j47r1tv –discovery-token-ca-cert-hash sha256:e386175a5cae597dec6bfeb7c92d01bc5fe052313b50dc48e419057c8c3f824c[preflight] running pre-flight checks [WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]you can solve this problem with following methods: 1. Run ‘modprobe – ’ to load missing kernel modules;2. Provide the missing builtin kernel ipvs supportI0305 20:02:24.453910 5983 kernel_validator.go:81] Validating kernel versionI0305 20:02:24.454026 5983 kernel_validator.go:96] Validating kernel config[discovery] Trying to connect to API Server “9.186.137.114:6443”[discovery] Created cluster-info discovery client, requesting info from “https://9.186.137.114:6443”[discovery] Requesting info from “https://9.186.137.114:6443” again to validate TLS against the pinned public key[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server “9.186.137.114:6443”[discovery] Successfully established connection with API Server “9.186.137.114:6443”[kubelet] Downloading configuration for the kubelet from the “kubelet-config-1.13” ConfigMap in the kube-system namespace[kubelet] Writing kubelet configuration to file “/var/lib/kubelet/config.yaml”[kubelet] Writing kubelet environment file with flags to file “/var/lib/kubelet/kubeadm-flags.env”[preflight] Activating the kubelet service[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap…[patchnode] Uploading the CRI Socket information “/var/run/dockershim.sock” to the Node API object “k8snode-1” as an annotationThis node has joined the cluster: Certificate signing request was sent to master and a response was received. The Kubelet was informed of the new secure connection details.Run ‘kubectl get nodes’ on the master to see this node join the cluster.k8snode-2:[root@k8snode-2 ~]# kubeadm join 9.186.137.114:6443 –token xjzf96.nv0qhqwj9j47r1tv –discovery-token-ca-cert-hash sha256:e386175a5cae597dec6bfeb7c92d01bc5fe052313b50dc48e419057c8c3f824c[preflight] running pre-flight checks [WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs_rr ip_vs_wrr ip_vs_sh ip_vs] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]you can solve this problem with following methods: 1. Run ‘modprobe – ’ to load missing kernel modules;2. Provide the missing builtin kernel ipvs supportI0305 19:51:39.452856 5036 kernel_validator.go:81] Validating kernel versionI0305 19:51:39.452954 5036 kernel_validator.go:96] Validating kernel config[discovery] Trying to connect to API Server “9.186.137.114:6443”[discovery] Created cluster-info discovery client, requesting info from “https://9.186.137.114:6443”[discovery] Requesting info from “https://9.186.137.114:6443” again to validate TLS against the pinned public key[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server “9.186.137.114:6443”[discovery] Successfully established connection with API Server “9.186.137.114:6443”[kubelet] Downloading configuration for the kubelet from the “kubelet-config-1.13” ConfigMap in the kube-system namespace[kubelet] Writing kubelet configuration to file “/var/lib/kubelet/config.yaml”[kubelet] Writing kubelet environment file with flags to file “/var/lib/kubelet/kubeadm-flags.env”[preflight] Activating the kubelet service[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap…[patchnode] Uploading the CRI Socket information “/var/run/dockershim.sock” to the Node API object “k8snode-2” as an annotationThis node has joined the cluster: Certificate signing request was sent to master and a response was received.* The Kubelet was informed of the new secure connection details.Run ‘kubectl get nodes’ on the master to see this node join the cluster.安装Flannel网络:k8smaster:[root@k8smaster ~]# kubectl apply -f kube-flannel.ymlclusterrole.rbac.authorization.k8s.io/flannel createdclusterrolebinding.rbac.authorization.k8s.io/flannel createdserviceaccount/flannel createdconfigmap/kube-flannel-cfg createddaemonset.extensions/kube-flannel-ds-amd64 createddaemonset.extensions/kube-flannel-ds-arm64 createddaemonset.extensions/kube-flannel-ds-arm createddaemonset.extensions/kube-flannel-ds-ppc64le createddaemonset.extensions/kube-flannel-ds-s390x created查看K8S集群状态:k8smaster:[root@k8smaster ~]# kubectl get pods -n kube-systemNAME READY STATUS RESTARTS AGEcoredns-86c58d9df4-kmfct 1/1 Running 0 8m26scoredns-86c58d9df4-qn2k2 1/1 Running 0 8m26setcd-k8smaster 1/1 Running 0 8m35skube-apiserver-k8smaster 1/1 Running 1 8m10skube-controller-manager-k8smaster 1/1 Running 0 7m43skube-flannel-ds-amd64-9rmfz 1/1 Running 0 5m9skube-flannel-ds-amd64-vnwtf 1/1 Running 0 12skube-flannel-ds-amd64-x7q4s 1/1 Running 0 51skube-proxy-7zl9n 1/1 Running 0 7m31skube-proxy-t2sx9 1/1 Running 0 8m27skube-proxy-txsfr 1/1 Running 0 7m27skube-scheduler-k8smaster 1/1 Running 0 8m56s到这里kubeadmin就部署完毕k8s集群了!希望大家可以给我指出问题,我们一起前进!谢谢大家! ...

March 6, 2019 · 8 min · jiezi

通过vim-plug安装UltiSnips,vim添加k8s自动补全功能

安装plug (https://github.com/junegunn/v...curl -fLo /.vim/autoload/plug.vim –create-dirs \https://raw.githubusercontent…编辑/.vimrc文件(不存在,则创建)" Specify a directory for plugins" - For Neovim: /.local/share/nvim/plugged" - Avoid using standard Vim directory names like ‘plugin’call plug#begin(’/.vim/plugged’)" Multiple Plug commands can be written in a single line using | separatorsPlug ‘SirVer/ultisnips’ | Plug ‘honza/vim-snippets’" Initialize plugin systemcall plug#end()打开vim,输入:PlugInstall加载插件vim 需要开启对 python 的支持,通过以下两个方式来验证你的 vim 是否支持 python 接口,支持一种即可:echo has(“python”) " 如果你用的是 python 2.7:echo has(“python3”) " 如果你用的是 python 3.3 或者 3.4当我们打开 vim 的时候, UltiSnips 会搜寻 $VIM 路径下的所有名字为 UltiSnips 的文件夹,然后根据文档类型来寻找对应的 snips。配置$VIMexport VIM=~/.vim验证vim a.cpp,输入main。按tab键,自动补全则成功int main(int argc, char *argv[]){ return 0;}添加k8s相关snippet (https://github.com/andrewstua…,将里面UltiSnips目录下的yaml.snippets文件移动到.vim目录下的UltiSnips文件下,就可以使用了,如vim a.yamlapiVersion: v1kind: Servicemetadata: name: frontend namespace: default labels: app: someApp tier: frontendspec: ports: - port: 80 selector: app: someApp tier: frontend ...

March 5, 2019 · 1 min · jiezi

CNCF多元化奖学金系列:一次学习和成长的机会

CNCF为开发者和学生提供多元化奖学金,以参加KubeCon + CloudNativeCon North America 2018。在这篇文章中,Surbhi Aggarwal分享了她作为KubeCon第一次参加者的经历以及她从活动中获得的巨大技术优势。任何有兴趣申请CNCF多元化奖学金,以参加于5月20日至23日在巴塞罗那的KubeCon + CloudNativeCon Europe 2019的人士,可在此提交申请,申请截止日期为3月11日;任何有兴趣参加于6月24-26日在上海的KubeCon + CloudNativeCon China 2019的人士,可在此提交申请,申请截止日期为4月15日。作者:Cvent的统计分析师Surbhi Aggarwal最近,我有机会参加2018年12月11日至13日,在华盛顿州西雅图华盛顿州会议中心举办的KubeCon + CloudNativeCon北美2018。该活动由CNCF组织,这是一个致力于推动云原生计算发展的非营利机构。我非常感谢Linux基金会,Wendi West为我提供了参与此次活动的机会,并感谢PranavJain向我介绍了KubeCon,这次经历极大地促进了我的知识、成长和观点。它让我有机会向专家学习,并体验Kubernetes的大量使用案例。KubeCon是我的第一次云原生会议,也是在7021英里外的国外。也就是说,我充满渴望和热情,最大限度地获益。经过25个多小时的旅行后,我到达了西雅图,在西雅图机场第一眼就看到了KubeCon的海报,它让我感到KubeCon的规模并留下印象。在第一天,我参加了Liz Rice、Michelle Noorali、Aparna Sinha和来自云原生世界的一些知名人士的主题演讲。看到大多数主题演讲由女性提供是非常令人惊讶和激励。大厅里满是大约8000人,感觉华盛顿州会议中心是当时世界上最具知识性的游乐场。在此之前,我不知道云原生社区有多强大和Kubernetes的增长速度如此之快。当Liz Rice分享数字突显KubeCon在互联网上的趋势,甚至超过了Seahawk和曼联时,我对成为整个活动的一部分充满了狂喜。从很多讲者那里了解Kubernetes的力量,使我非常积极地学习,并在我的日常工作中开始使用它。在主题演讲之后,我参加了一些有关机器学习主题的有趣且内容丰富的分论坛。我感兴趣的是在ML驱动应用程序中Kubernetes的用法,以及在初学者级别部署ML模型时它如何有用。这就是为什么我参加的大多数论坛围绕着ML和AI的主题,并且属于初级/中级水平。我参加的每次演讲都向我介绍了一种使用Kubernetes的新技术,这种技术可以与我围绕ML的工作联系起来。我参加来自IBM的AnimeshSingh和Tommy Li的“使用KNative构建机器学习模型服务和管道”,他们解释了Knative,这是Google、Pivotal和其他公司的开源项目。他们解释了Knative如何帮助构建自动化和事件驱动的AI管道,从而在流程的每个阶段启用触发器。这一天行程紧密,有更多的会议、演讲、网络和我正在接触的新话题。Google aronchick的“机器学习即代码:Kubernetes与Kubeflow”是我最爱的。我过去曾使用过TensorFlow,但本身并不了解KubeFlow,这次演讲帮助我了解Kubeflow的可用性,以及它如何让每个人都轻松地在Kubernetes上开发、部署和管理便携式分布式ML。演讲之后,我对Kubeflow非常感兴趣,我已经开始从Katacoda学习。事先就确信Kubernetes获得广泛采用,但在Red Hat的SophieWatson的“数据科学家为什么爱Kubernetes”的演讲中,我更详细地了解了它的用例。在第一天结束前,我去了主题演讲和mesosphere的IceCubeCon音乐会,这是有史以来最好的会议派对。我非常仔细地看IceCube,得到了一些非常酷的小礼物,而且不要忘记“没有像KubeCon派对的派对因为KubeCon派对不会停止”。第二天,我参加了Liz Rice、Jason McGee的主题演讲。在主题演讲之后,我参加了一些分论坛,在那里我了解了“贝莱德如何自动化研究工作流程”。Mathew Magaldi和VaibhavPage谈到他们如何使用Kubernetes和Jupyter Notebook API来自动化研究环境,并在贝莱德扩展数据科学工作流程。我非常喜欢的另一个话题是ChrisDutra的“使用Prometheus和ML作预测性应用程序扩展”,他是Schireson数据科学咨询和工程公司的站点可靠性工程总监。他的演讲使我明白他是如何开发出一种将数据科学流程转移到生产的方法。我有机会在多元午餐会上遇到一些不可思议的人,我喜欢Heptio的KrisNova的活力,她的想法非常简洁,她的一切都启发着我,我喜欢她在传达她的想法的同时,所拥有的细节水平和清晰度。在午餐桌上,我们有7位不同背景的女性。我们讨论过许多热门话题。我们围绕各种主题对话,包括工作空间的挑战、与薪酬相关的最佳谈判实践。我们进一步讨论了我们首次参与技术、Kubernetes背后的动机以及我们对会议的主要关注。对我来说,体验每个人是否愿意以任何可能的方式互相帮助是如此迷人。我在桌子上结识了很多朋友,RiaBhatia、CatherineShen、MaryaryStyles。最后,我参加了在Space Needle and Chihuly Gardens举办的所有与会者派对,这是当天的亮点。感谢KubeCon举办的盛大派对,这对我来说是一次超现实的体验,我好像在硅谷电视系列中扮演一个角色,在这个城市最好的景点举办派对。我有机会参观太空针的顶部,我的眼睛仍然可以看到令人惊叹的景色。我可以告诉你,KubeCon不仅每年都会变得更大,而且每天都会变得更大。在主题演讲结束后的会议的最后一天,我大部分时间都在赞助商摊位上。我没有看到这个级别的活动,有近200个赞助商。摊位不亚于一个小孩的糖果店。我见到了来自不同公司的很多人,并了解他们如何利用Kubernetes。从Datadog、Influxdata、New Relic、Iguazio团队等学习关于他们涉及Kubernetes和CNCF其他项目是非常有趣的。此外,令人惊讶的是,赞助商中出现了Nordstrom、WeWork等公司。这些公司对我来说是完全不同的业务,对我而言与技术无关。在与他们交谈之后,我意识到这些公司在技术方面有多大,以及他们如何使用Kubernetes。这清楚地给出了Kubernetes巨大的例子。了解不同的公司让我增长见识,我也非常喜欢收集一些非常酷的小礼物。感谢所有赞助商,即使是小礼物也是如此创新。我也在抽奖嘉年华上试过我的运气,几乎每个赞助商摊位上都有引人注目的赠品,但那天运气似乎太好。在会议到达其最后的主题演讲时,它令人舍不得,但我的每一次体验,在很大程度上让我充满了希望和积极。最后,我在Pike啤酒厂AWS举办的派对上向KubeCon North American 2018干杯告别。总的来说,KubeCon对我来说是一次非常棒的体验。在此次会议之前,我无法自信地谈论Kubernetes或其他云原生项目。在这里,我发现了几个可能对我的工作有帮助的新软件项目。回到印度,在与朋友、工作网络和不同社区成员分享我的经验的同时,我可以看到人们对学习云原生项目真正感兴趣。KubeCon让我接触到无限的机会,导致我的个人和职业发展。整体体验是一个很好的启发,我很高兴将这些想法付诸实践。我期待着KubeCon Barcelona'19。谢谢2018年KubeCon + CloudNativeCon北美!KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 5, 2019 · 1 min · jiezi

Project EVE促进针对边缘计算的云原生方法

作者:Eric BrownProject EVE是新成立的LF Edge的一部分,它提供了一个基于云原生的虚拟化引擎,用于为工业边缘计算机开发和部署容器。上周由Linux基金会宣布的用于开源边缘计算的LF Edge伞式组织包括两个新项目:Samsung Home Edge和Project EVE。我们对三星的家庭自动化项目了解不多,但我们发现了更多关于基于Zededa边缘虚拟化技术的Project EVE。上周,我们与Zededa联合创始人Roman Shaposhnik就Project EVE交谈,该项目提供了一个基于云原生的虚拟化引擎,用于开发和部署工业边缘计算机的容器(见下文)。LF Edge旨在建立“开放、可互操作的边缘计算框架,独立于硬件、芯片、云或操作系统”。它围绕Linux基金会的电信导向Akraino边缘堆栈以及EdgeX Foundry构建。EdgeX Foundry是一个工业级物联网中间件项目。与谷歌(谷歌云物联网边缘)、亚马逊(AWS IoT)、微软(Azure Sphere)以及最近的百度(开放边缘)等新兴的云端到边缘平台一样,LF Edge设想了一个世界,物联网网关和边缘设备上运行的软件,是从云端向下发展,而不是从传统的嵌入式平台开始。Linux基金会亦支持许多“基础”嵌入式项目,如Yocto项目和Iotivity,但是对于LF Edge,它已经朝着以云为中心的范例迈出了实质性的一步。云原生方法给嵌入式系统的优势包括更简单的软件开发,特别是在需要多个应用程序时,以及通过虚拟化,定期更新的容器应用程序提高安全性。云原生边缘计算还应该能够在边缘更有效地部署基于云的分析,同时减少昂贵、高延迟的云通信。上面列出的四大云运营商(除了百度)目前都不是LF Edge的成员,这对该组织构成了挑战。然而,已经有很多公司上市,包括Arm、AT&T、百度、戴尔EMC、爱立信、HPE、华为、IBM、英特尔、诺基亚解决方案、高通、Radisys、红帽、三星、Seagate和WindRiver(参阅LF Edge公布完整名单)。随着开发者从自上而下,和自下而上的角度处理边缘计算问题,通常对相反领域的知识有限,第一步是就术语达成一致。早在六月,Linux基金会就推出了Open Glossary of Edge Computing ,一个开放式边缘计算词汇表项目来解决这个问题。现在,作为LF Edge的一部分,Open Glossary的努力“旨在提供与边缘计算领域相关的简明术语集合。”在LF Edge项目的公告中没有提到Linux,所有这些都提出了边缘计算的开源、操作系统中立的方法。然而,毫无疑问,Linux将成为这里的推动力。Project EVE旨在成为边缘计算的AndroidProject EVE正在开发一种“开放、中立和标准化的架构,统一了在整个企业边缘开发和编排云原生应用程序的方法。”Linux基金会表示。Project EVE基于Santa Clara创业公司Zededa的专有Edge Virtualization X(EVx)引擎的开源EVE(边缘虚拟化引擎)版本构建,旨在使用Docker容器和其他开源云原生软件,如Kubernetes,重新构建嵌入式系统。云原生边缘计算的“简单、标准化的编排”将使开发者能够“安全地将云应用程序扩展到边缘设备,而无需专门的工程绑定到特定的硬件平台。”该项目说。今年早些时候,Zededa加入了EdgeX Foundry项目,其技术同样针对工业领域。但是,Project EVE主要涉及更高的应用程序级别而不是中间件。该项目的边缘软件的云原生方法也将它连接到另一个LF项目:CNCF(云原生计算基金会)。除了轻量级虚拟化引擎外,Project EVE还提供零信任安全框架。在与Linux.com的对话中,Zededa联合创始人Roman Shaposhnik建议将“嵌入式”一词交给较低级别的基于MCU的简单IoT设备,这些设备无法运行Linux。“To learn embedded you have to go back in time, which is no longer cutting it.”Shaposhnik说。“我们有数百万可以驱动边缘计算的云原生软件开发者。如果你熟悉云原生,那么在开发边缘原生应用程序时应该没有问题。”如果Shaposhnik对传统的、基于嵌入式开发持批评态度,由于其复杂性和缺乏安全性,他也对专有的云端到边缘解决方案不屑一顾。“很明显,构建孤岛式端到端集成云应用程序并不是真正的方向。”他说,并提到供应商锁定的危险以及缺乏互操作性和隐私。Shaposhnik表示,为了实现边缘计算的目标,我们需要的是一种可以与任何云一起使用的标准化开源边缘虚拟化方法。他说,Project EVE可以实现这一目标,它是与Android相当的边缘计算。Shaposhnik表示,“今天的边缘市场是移动设备在21世纪初期所处的位置”,指的是Palm、BlackBerry和Windows Mobile等早期移动操作系统创造了专有孤岛的时代。iPhone通过应用程序和其他高级功能改变了这种模式,但更为开放的Android确实让移动世界陷入了超速状态。Shaposhnik表示,“Project EVE在边缘在做Android在移动设备方面做的事。”他补充说。该项目的标准化边缘虚拟化技术相当于Android软件包管理和Dalvik VM for Java的合并。“作为移动开发者,你不会考虑使用什么驱动程序。同样,我们的技术可以保护开发者免受硬件复杂性的影响。”Project EVE基于Zededa的EVx边缘虚拟化引擎,该引擎目前运行在Advantech、Lanner、SuperMicro和Scalys等合作伙伴的边缘硬件上。Zededa的客户大多是需要及时分析的大型工业或能源公司,这些公司越来越需要多种应用。“我们有客户希望优化他们的风力涡轮机,并需要预测性维护和振动分析。”Shaposhnik说。“有六家机器学习和人工智能公司可以提供帮助,但他们提供产品的唯一方法就是给他们一个新盒子,这会增加成本和复杂性。”典型的边缘计算机可能只需要少数几个不同的应用程序,而不是典型智能手机上的数百个应用程序。然而,如果没有虚拟化容器等应用程序管理解决方案,就没有简单的方法来托管它们。使用嵌入式容器技术提供应用程序的其他开源云端到边缘解决方案,包括Balena(以前的Resin.io)的Balena IoT车队管理解决方案,以及Canonical的容器式Ubuntu Core发行版。目前,重点是将EVx的开源版本推向市场。Project EVE计划在第二季度发布1.0版本的EVE以及用于开发EVE边缘容器的SDK。应用程序商店平台将在今年晚些时候推出。更多信息可以在这篇Zededa博客文章中找到。了解有关LF Edge的更多信息:https://www.lfedge.org/KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 4, 2019 · 1 min · jiezi

电信业已走向开源

LF Networking通过创建一个伞形项目,成为电信行业的催化剂,各种参与者可以通过该项目贡献,并丰富所涉及的技术。电信业是第四次工业革命的核心。无论是连接的物联网设备,还是移动娱乐,现代经济都在互联网上运行。但是,网络的支柱一直在传统技术上运行。一些电信公司已有数百年的历史,它们拥有庞大的基础设施,需要进行现代化改造。好消息是,这个行业已经处于新兴技术的前沿。AT&T、Verizon、中国移动、DTK等公司已采用开源技术,以便更快地进入未来。LF Networking是这次转型的核心。“2018年是非常棒的一年。”Linux基金会Networking总经理Arpit Joshipura在去年秋天在温哥华举行的开源峰会上发言。“我们已经看到一家拥有140年历史的电信行业,从专有和传统技术转向使用LF Networking的开源技术。”现在LF Networking拥有超过100名成员,占这些电信运营商全球用户的约70%。这些成员积极参与LF Networking的软件开发。他们在现有项目上合作,将自己的内部代码贡献给基金会,并将其作为开源发布。例如,AT&T将自己的虚拟网络以ONAP项目贡献给了Linux基金会。该项目现在被其他公司用于生产,AT&T作为回报,受益于竞争对手为改进代码库所做的工作。“在开源社区中,已经创造了价值超过5亿美元的软件创新。”Joshipura说。“我们现在可以有把握地说,电信行业将使用基于Linux Foundation的开源来构建他们的下一代网络。电信转型对于电信行业的这种转变而言,令人难以置信的是,与开发者推动变革的其他行业不同,这里的最高领导层一直主张改变。LF Networking成为一个催化剂,通过创建一个伞形项目来帮助该行业。在该项目下,各种参与者可以收集、贡献和丰富所涉及的技术。LF Networking目前的主要焦点是在生产环境中看到越来越多的这些技术。“但我们的下一个目标是了解网络如何实现我们所谓的跨项目协作、跨行业协作、跨社群协作。区块链如何影响电信公司,电信公司如何能够与Kubernetes一起使用云计算等等。”Joshipura说。网络社区最有前途的领域之一是边缘计算,正如最近创建的新LF Edge伞式项目所示。这个领域有很多创新 - 5G、自动驾驶等等。“我们的重点是弄清楚这些项目是如何结合在一起并进行协作的,这样我们的最终用户成员才能获得更多价值。”他说。Linux Foundation拥有广泛的项目,其中许多项目都是单独构建代码。Joshipura希望这些项目能够密切合作。“我们有VNF(虚拟网络功能)的概念。我们如何让他们成为云原生的?我们创建了一个名为CNF(云原生网络功能)的项目,但我们需要与ONAP社区、网络社区和Kubernetes社区合作,以解决网络社区面临的一些问题。”他说。凭借目前的发展势头和社区支持,LF Networking有望引领潮流。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!

March 4, 2019 · 1 min · jiezi

Kubernetes安全公告:发布v1.11.8、1.12.6、1.13.4以解决中等严重性CVE-2019-1002100

Kubernetes社区你好,在kube-apiserver中发现了拒绝服务漏洞,其中具有API写入权限的授权用户可以在处理写入请求时导致API服务器消耗过多的资源。问题是中等严重性,可以通过将kube-apiserver升级到v1.11.8、v1.12.6或v1.13.4来解决。我使用的版本是脆弱吗?以下版本的kube-apiserver易受攻击:v1.0.0-1.10.xv1.11.0-1.11.7v1.12.0-1.12.5v1.13.0-1.13.3如何在升级之前缓解漏洞?对不受信任的用户删除“patch”权限。漏洞详细信息有权向Kubernetes API服务器发出补丁(patch)请求的用户可以发送特制的“json-patch”补丁(例如kubectl patch –type json或“Content-Type: application/json-patch+json”)处理时消耗过多资源,导致API服务器上的拒绝服务。没有与此漏洞相关的信息泄露或权限升级。这漏洞提交为CVE-2019-1002100。我们将其评为CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H(6.5,中等)。请参阅GitHub问题#74534了解更多详情。谢谢感谢Carl Henrik Lunde报告此问题。请注意,如果您在Kubernetes中发现安全漏洞,请按照安全公开流程进行报告。感谢Chao Xu和Jordan Liggitt开发修复程序,感谢修补程序发布经理Aleksandra Malinowska、Timothy Pepper、Pengfei Ni和Anirudh Ramanathan协调发布。-CJ Cullen代表Kubernetes产品安全团队KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!

March 4, 2019 · 1 min · jiezi

使用OperatorHub.io自动化群集上的操作

作者:Diane Mueller,红帽云平台社区发展总监开发者和Kubernetes管理员面临的重要挑战之一,是缺乏快速查找在Kubernetes提供运营就绪的公共服务的能力。通常情况下,存在特定服务的Operator - 这种模式在2016年推出并获得了动力 - 对于Kubernetes服务的运营就绪是一个很好的信号。但是,迄今为止还没有Operator注册表来简化发现此类服务。为了帮助应对这一挑战,今天Red Hat与AWS、Google Cloud和Microsoft合作推出OperatorHub.io。OperatorHub.io使开发者和Kubernetes管理员能够查找和安装策划好的、Operator支持的服务,其中包括基础文档、社区或供应商的主动维护、基本测试以及Kubernetes优化生命周期管理的打包。目前在OperatorHub.io中的Operator只是开始。我们邀请Kubernetes社区加入我们,通过在OperatorHub.io上开发、打包和发布Operator,为Operator建立一个充满活力的社区。OperatorHub.io提供什么?OperatorHub.io旨在满足Kubernetes开发者和用户的需求。对于前者,它提供了通用的注册表,他们可以在其中发布他们的Operator以及描述、相关的详细信息,如版本、镜像、代码仓库,并打包准备方便安装。他们也可以对已发布的Operator发布更新版本。用户可以在一个中心位置发现和下载Operator,该Operator的内容已根据前面提到的标准进行筛选并扫描已知漏洞。此外,开发者可以使用他们引入的CustomResources的说明性示例,指导其Operator的用户,与应用程序进行交互。Operator是什么?Operator最初由CoreOS于2016年推出,并已被Red Hat和Kubernetes社区用作打包、部署和管理Kubernetes原生应用程序的方法。Kubernetes原生应用程序是一个部署在Kubernetes上的应用程序,使用Kubernetes API和众所周知的工具进行管理,如kubectl。Operator实现为自定义控制器,用于监视某些Kubernetes资源的显示、修改或删除。这些通常是Operator“拥有”的CustomResourceDefinition。在这些对象的spec属性中,用户声明应用程序或操作的所需状态。Operator的协调循环将选择这些,并执行所需的操作以实现所需的状态。例如,可以通过创建EtcdCluster类型的新资源,来表达创建高可用性etcd集群的意图:apiVersion: “etcd.database.coreos.com/v1beta2"kind: “EtcdCluster"metadata: name: “my-etcd-cluster"spec: size: 3 version: “3.3.12"这样,EtcdOperator将负责创建运行版本v3.3.12的3节点etcd集群。类似地,可以定义类型为EtcdBackup的对象,以表示创建etcd数据库一致备份到S3存储桶的意图。如何创建和运行Operator?一种入门方法是使用Operator框架,这是一个开源工具包,提供SDK、生命周期管理、计量和监视功能。它使开发者能够构建、测试和打包Operator。Operator可以用几种编程和自动化语言实现,包括Go、Helm和Ansible,这三种语言都直接由SDK支持。如果你有兴趣创建自己的Operator,我们建议你查看Operator框架以开始使用。Operator的功能范围各不相同,从基本功能到应用程序的特定操作逻辑,以及备份、恢复或调整等高级方案的自动化。除了基本安装之外,高级Operator可以更加无缝地处理升级并自动应对故障。目前,OperatorHub.io上的Operator来自不同成熟度范围,但我们预计它们会随着时间而持续成熟。虽然不需要使用SDK实现OperatorHub.io上的Operator,但它们是打包给通过Operator Lifecycle Manager(OLM)进行部署。格式主要由称为ClusterServiceVersion的YAML清单组成。它提供有关Operator拥有或要求的CustomResourceDefinitions的信息、所需的RBAC定义、存储图像的位置等。此文件通常附带定义Operator自己的CRD的其他YAML文件。OLM在用户请求安装Operator以提供依赖性解析和自动化时处理此信息。OperatorHub.io上的Operator列表是什么意思?要列出,Operator必须成功显示群集生命周期功能,打包为CSV并通过OLM维护,以及为其预期用户提供可接受的文档。目前在OperatorHub.io上列出的Operator的一些示例包括:Amazon Web Services Operator、Couchbase Autonomous Operator、CrunchyData’s PostgreSQL、etcd Operator、Jaeger Operator for Kubernetes、Kubernetes Federation Operator、MongoDB Enterprise Operator、Percona MySQL Operator、PlanetScale’s Vitess Operator、Prometheus Operator和Redis Operator。想要将你的Operator添加到OperatorHub.io?跟着这些步骤如果你有现有的Operator,请遵循贡献指南使用社区Operator仓库的分支。每个贡献包含CSV、所有CustomResourceDefinitions、访问控制规则以及安装和运行Operator所需的容器映像的资料,其功能描述和支持的Kubernetes版本等其他信息。EtcdOperator可以作为完整的示例,包括Operator的多个版本。在你自己的集群上测试Operator之后,将PR提交到社区存储库,其中包含此目录结构的所有YAML文件。可以以相同的方式发布Operator的后续版本。刚开始这将是手动审查,但往后会自动化。由维护者合并之后,它将显示在OperatorHub.io上,以及其文档和方便的安装方法。想了解更多?参加即将举行的Kubernetes Operator框架实践研讨会:3月7日在Pasadena的ScaleX举行,以及3月11日在Santa Clara的OpenShift Commons Gathering on Operating举行听听Daniel Messer和Diane Mueller关于“Operator现况”的OpenShift Commons简报加入社区Kubernetes-Operator Slack Channel和Operator框架Google Group的在线对话最后,阅读如何将你的Operator添加到OperatorHub.io:https://operatorhub.io/contri…KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 4, 2019 · 1 min · jiezi

容器监控实践—Prometheus的配置与服务发现

本文将分析Prometheus的常见配置与服务发现,分为概述、配置详解、服务发现、常见场景四个部分进行讲解。一. 概述Prometheus的配置可以用命令行参数、或者配置文件,如果是在k8s集群内,一般配置在configmap中(以下均为prometheus2.7版本)查看可用的命令行参数,可以执行 ./prometheus -h也可以指定对应的配置文件,参数:–config.file 一般为prometheus.yml如果配置有修改,如增添采集job,Prometheus可以重新加载它的配置。只需要向其进程发送SIGHUP或向/-/reload端点发送HTTP POST请求。如:curl -X POST http://localhost:9090/-/reload二. 配置详解2.1 命令行参数执行./prometheus -h 可以看到各个参数的含义,例如:–web.listen-address=“0.0.0.0:9090” 监听端口默认为9090,可以修改只允许本机访问,或者为了安全起见,可以改变其端口号(默认的web服务没有鉴权)–web.max-connections=512 默认最大连接数:512–storage.tsdb.path=“data/” 默认的存储路径:data目录下–storage.tsdb.retention.time=15d 默认的数据保留时间:15天。原有的storage.tsdb.retention配置已经被废弃–alertmanager.timeout=10s 把报警发送给alertmanager的超时限制 10s–query.timeout=2m 查询超时时间限制默认为2min,超过自动被kill掉。可以结合grafana的限时配置如60s–query.max-concurrency=20 并发查询数 prometheus的默认采集指标中有一项prometheus_engine_queries_concurrent_max可以拿到最大查询并发数及查询情况–log.level=info 日志打印等级一共四种:[debug, info, warn, error],如果调试属性可以先改为debug等级…..在prometheus的页面上,status的Command-Line Flags中,可以看到当前配置,如promethues-operator的配置是:2.2 prometheus.yml从官方的download页下载的promethues二进制文件,会自带一份默认配置prometheus.yml-rw-r–r–@ LICENSE-rw-r–r–@ NOTICEdrwxr-xr-x@ console_librariesdrwxr-xr-x@ consoles-rwxr-xr-x@ prometheus-rw-r–r–@ prometheus.yml-rwxr-xr-x@ promtoolprometheus.yml配置了很多属性,包括远程存储、报警配置等很多内容,下面将对主要属性进行解释:# 默认的全局配置global: scrape_interval: 15s # 采集间隔15s,默认为1min一次 evaluation_interval: 15s # 计算规则的间隔15s默认为1min一次 scrape_timeout: 10s # 采集超时时间,默认为10s external_labels: # 当和其他外部系统交互时的标签,如远程存储、联邦集群时 prometheus: monitoring/k8s # 如:prometheus-operator的配置 prometheus_replica: prometheus-k8s-1# Alertmanager的配置alerting: alertmanagers: - static_configs: - targets: - 127.0.0.1:9093 # alertmanager的服务地址,如127.0.0.1:9093 alert_relabel_configs: # 在抓取之前对任何目标及其标签进行修改。 - separator: ; regex: prometheus_replica replacement: $1 action: labeldrop # 一旦加载了报警规则文件,将按照evaluation_interval即15s一次进行计算,rule文件可以有多个rule_files: # - “first_rules.yml” # - “second_rules.yml”# scrape_configs为采集配置,包含至少一个jobscrape_configs: # Prometheus的自身监控 将在采集到的时间序列数据上打上标签job=xx - job_name: ‘prometheus’ # 采集指标的默认路径为:/metrics,如 localhost:9090/metric # 协议默认为http static_configs: - targets: [’localhost:9090’]# 远程读,可选配置,如将监控数据远程读写到influxdb的地址,默认为本地读写remote_write: 127.0.0.1:8090# 远程写remote_read: 127.0.0.1:8090 2.3 scrape_configs配置prometheus的配置中,最常用的就是scrape_configs配置,比如添加新的监控项,修改原有监控项的地址频率等。最简单配置为:scrape_configs:- job_name: prometheus metrics_path: /metrics scheme: http static_configs: - targets: - localhost:9090完整配置为(附prometheus-operator的推荐配置):# job 将以标签形式出现在指标数据中,如node-exporter采集的数据,job=node-exporterjob_name: node-exporter# 采集频率:30sscrape_interval: 30s# 采集超时:10sscrape_timeout: 10s# 采集对象的path路径metrics_path: /metrics# 采集协议:http或者httpsscheme: https# 可选的采集url的参数params: name: demo# 当自定义label和采集到的自带label冲突时的处理方式,默认冲突时会重名为exported_xxhonor_labels: false# 当采集对象需要鉴权才能获取时,配置账号密码等信息basic_auth: username: admin password: admin password_file: /etc/pwd# bearer_token或者文件位置(OAuth 2.0鉴权)bearer_token: kferkhjktdgjwkgkrwgbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token# https的配置,如跳过认证,或配置证书文件tls_config: # insecure_skip_verify: true ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt server_name: kubernetes insecure_skip_verify: false# 代理地址proxy_url: 127.9.9.0:9999# Azure的服务发现配置azure_sd_configs:# Consul的服务发现配置consul_sd_configs: # DNS的服务发现配置dns_sd_configs:# EC2的服务发现配置ec2_sd_configs:# OpenStack的服务发现配置openstack_sd_configs:# file的服务发现配置file_sd_configs:# GCE的服务发现配置gce_sd_configs:# Marathon的服务发现配置marathon_sd_configs:# AirBnB的服务发现配置nerve_sd_configs:# Zookeeper的服务发现配置serverset_sd_configs:# Triton的服务发现配置triton_sd_configs:# Kubernetes的服务发现配置kubernetes_sd_configs: - role: endpoints namespaces: names: - monitoring# 对采集对象进行一些静态配置,如打特定的标签static_configs: - targets: [’localhost:9090’, ’localhost:9191’] labels: my: label your: label # 在Prometheus采集数据之前,通过Target实例的Metadata信息,动态重新写入Label的值。如将原始的__meta_kubernetes_namespace直接写成namespace,简洁明了relabel_configs: - source_labels: [__meta_kubernetes_namespace] separator: ; regex: (.) target_label: namespace replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.) target_label: service replacement: $1 action: replace - source_labels: [_meta_kubernetes_pod_name] separator: ; regex: (.) target_label: pod replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.) target_label: job replacement: ${1} action: replace - separator: ; regex: (.*) target_label: endpoint replacement: web action: replace# 指标relabel的配置,如丢掉某些无用的指标metric_relabel_configs: - source_labels: [name] separator: ; regex: etcd(debugging|disk|request|server).* replacement: $1 action: drop # 限制最大采集样本数,超过了采集将会失败,默认为0不限制sample_limit: 0三. 服务发现上边的配置文件中,有很多*sd_configs的配置,如kubernetes_sd_configs,就是用于服务发现的采集配置。支持的服务发现类型:// prometheus/discovery/config/config.gotype ServiceDiscoveryConfig struct { StaticConfigs []*targetgroup.Group yaml:"static_configs,omitempty" DNSSDConfigs []*dns.SDConfig yaml:"dns_sd_configs,omitempty" FileSDConfigs []*file.SDConfig yaml:"file_sd_configs,omitempty" ConsulSDConfigs []*consul.SDConfig yaml:"consul_sd_configs,omitempty" ServersetSDConfigs []*zookeeper.ServersetSDConfig yaml:"serverset_sd_configs,omitempty" NerveSDConfigs []*zookeeper.NerveSDConfig yaml:"nerve_sd_configs,omitempty" MarathonSDConfigs []*marathon.SDConfig yaml:"marathon_sd_configs,omitempty" KubernetesSDConfigs []kubernetes.SDConfig yaml:"kubernetes_sd_configs,omitempty" GCESDConfigs []gce.SDConfig yaml:"gce_sd_configs,omitempty" EC2SDConfigs []ec2.SDConfig yaml:"ec2_sd_configs,omitempty" OpenstackSDConfigs []openstack.SDConfig yaml:"openstack_sd_configs,omitempty" AzureSDConfigs []azure.SDConfig yaml:"azure_sd_configs,omitempty" TritonSDConfigs []triton.SDConfig yaml:"triton_sd_configs,omitempty"}因为prometheus采用的是pull方式来拉取监控数据,这种方式需要由server侧决定采集的目标有哪些,即配置在scrape_configs中的各种job,pull方式的主要缺点就是无法动态感知新服务的加入,因此大多数监控都默认支持服务发现机制,自动发现集群中的新端点,并加入到配置中。Prometheus支持多种服务发现机制:文件,DNS,Consul,Kubernetes,OpenStack,EC2等等。基于服务发现的过程并不复杂,通过第三方提供的接口,Prometheus查询到需要监控的Target列表,然后轮询这些Target获取监控数据。对于kubernetes而言,Promethues通过与Kubernetes API交互,然后轮询资源端点。目前主要支持5种服务发现模式,分别是:Node、Service、Pod、Endpoints、Ingress。对应配置文件中的role: node/role:service如:动态获取所有节点node的信息,可以添加如下配置:- job_name: kubernetes-nodes scrape_interval: 1m scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: null role: node namespaces: names: [] bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true relabel_configs: - separator: ; regex: _meta_kubernetes_node_label(.+) replacement: $1 action: labelmap - separator: ; regex: (.) target_label: address replacement: kubernetes.default.svc:443 action: replace - source_labels: [__meta_kubernetes_node_name] separator: ; regex: (.+) target_label: metrics_path replacement: /api/v1/nodes/${1}/proxy/metrics action: replace就可以在target中看到具体内容对应的service、pod也是同样的方式。需要注意的是,为了能够让Prometheus能够访问收到Kubernetes API,我们要对Prometheus进行访问授权,即serviceaccount。否则就算配置了,也没有权限获取。prometheus的权限配置是一组ClusterRole+ClusterRoleBinding+ServiceAccount,然后在deployment或statefulset中指定serviceaccount。ClusterRole.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: namespace: kube-system name: prometheusrules:- apiGroups: [""] resources: - configmaps - secrets - nodes - pods - nodes/proxy - services - resourcequotas - replicationcontrollers - limitranges - persistentvolumeclaims - persistentvolumes - namespaces - endpoints verbs: [“get”, “list”, “watch”]- apiGroups: [“extensions”] resources: - daemonsets - deployments - replicasets - ingresses verbs: [“get”, “list”, “watch”]- apiGroups: [“apps”] resources: - daemonsets - deployments - replicasets - statefulsets verbs: [“get”, “list”, “watch”]- apiGroups: [“batch”] resources: - cronjobs - jobs verbs: [“get”, “list”, “watch”]- apiGroups: [“autoscaling”] resources: - horizontalpodautoscalers verbs: [“get”, “list”, “watch”]- apiGroups: [“policy”] resources: - poddisruptionbudgets verbs: [“get”, list", “watch”]- nonResourceURLs: ["/metrics"] verbs: [“get”]ClusterRoleBinding.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: namespace: kube-system name: prometheusroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheussubjects:- kind: ServiceAccount name: prometheus namespace: kube-systemServiceAccount.yamlapiVersion: v1kind: ServiceAccountmetadata: namespace: kube-system name: prometheusprometheus.yaml….spec: serviceAccountName: prometheus….完整的kubernete的配置如下:- job_name: kubernetes-apiservers scrape_interval: 1m scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: null role: endpoints namespaces: names: [] bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] separator: ; regex: default;kubernetes;https replacement: $1 action: keep- job_name: kubernetes-nodes scrape_interval: 1m scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: null role: node namespaces: names: [] bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true relabel_configs: - separator: ; regex: _meta_kubernetes_node_label(.+) replacement: $1 action: labelmap - separator: ; regex: (.) target_label: address replacement: kubernetes.default.svc:443 action: replace - source_labels: [__meta_kubernetes_node_name] separator: ; regex: (.+) target_label: metrics_path replacement: /api/v1/nodes/${1}/proxy/metrics action: replace- job_name: kubernetes-cadvisor scrape_interval: 1m scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: null role: node namespaces: names: [] bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: false relabel_configs: - separator: ; regex: _meta_kubernetes_node_label(.+) replacement: $1 action: labelmap - separator: ; regex: (.) target_label: address replacement: kubernetes.default.svc:443 action: replace - source_labels: [__meta_kubernetes_node_name] separator: ; regex: (.+) target_label: metrics_path replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor action: replace- job_name: kubernetes-service-endpoints scrape_interval: 1m scrape_timeout: 10s metrics_path: /metrics scheme: http kubernetes_sd_configs: - api_server: null role: endpoints namespaces: names: [] relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] separator: ; regex: “true” replacement: $1 action: keep - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] separator: ; regex: (https?) target_label: scheme replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] separator: ; regex: (.+) target_label: metrics_path replacement: $1 action: replace - source_labels: [address, __meta_kubernetes_service_annotation_prometheus_io_port] separator: ; regex: ([^:]+)(?::\d+)?;(\d+) target_label: address replacement: $1:$2 action: replace - separator: ; regex: _meta_kubernetes_service_label(.+) replacement: $1 action: labelmap - source_labels: [__meta_kubernetes_namespace] separator: ; regex: (.) target_label: kubernetes_namespace replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.) target_label: kubernetes_name replacement: $1 action: replace配置成功后,对应的target是:四. 常见场景1.获取集群中各节点信息,并按可用区或地域分类如使用k8s的role:node采集集群中node的数据,可以通过"meta_domain_beta_kubernetes_io_zone"标签来获取到该节点的地域,该label为集群创建时为node打上的标记,kubectl decribe node可以看到。然后可以通过relabel_configs定义新的值relabel_configs:- source_labels: [“meta_domain_beta_kubernetes_io_zone”] regex: “(.)” replacement: $1 action: replace target_label: “zone"后面可以直接通过node{zone=“XX”}来进行地域筛选2.过滤信息,或者按照职能(RD、运维)进行监控管理对于不同职能(开发、测试、运维)的人员可能只关心其中一部分的监控数据,他们可能各自部署的自己的Prometheus Server用于监控自己关心的指标数据,不必要的数据需要过滤掉,以免浪费资源,可以最类似配置;metric_relabel_configs: - source_labels: [name] separator: ; regex: etcd(debugging|disk|request|server).* replacement: $1 action: dropaction: drop代表丢弃掉符合条件的指标,不进行采集。3.搭建prometheus联邦集群,管理各IDC(地域)监控实例如果存在多个地域,每个地域又有很多节点或者集群,可以采用默认的联邦集群部署,每个地域部署自己的prometheus server实例,采集自己地域的数据。然后由统一的server采集所有地域数据,进行统一展示,并按照地域归类配置:scrape_configs: - job_name: ‘federate’ scrape_interval: 15s honor_labels: true metrics_path: ‘/federate’ params: ‘match[]’: - ‘{job=“prometheus”}’ - ‘{name=“job:.*”}’ - ‘{name=“node.*”}’ static_configs: - targets: - ‘192.168.77.11:9090’ - ‘192.168.77.12:9090’本文为容器监控实践系列文章,完整内容见:container-monitor-book ...

March 4, 2019 · 4 min · jiezi

容器监控实践—PromQL查询解析

一. 概述Prometheus除了存储数据外,还提供了一种强大的功能表达式语言 PromQL,允许用户实时选择和汇聚时间序列数据。表达式的结果可以在浏览器中显示为图形,也可以显示为表格数据,或者由外部系统通过 HTTP API 调用。通过PromQL用户可以非常方便地查询监控数据,或者利用表达式进行告警配置如:k8s中的node在线率:sum(kube_node_status_condition{condition=“Ready”, status=“true”}) / sum(kube_node_info) 100 Metric类型关于时间序列存储,可以参考:https://www.infoq.cn/article/…Prometheus会将所有采集到的样本数据以时间序列(time-series)的方式保存在内存数据库TSDB中,并且定时保存到硬盘上。time-series是按照时间戳和值的序列顺序存放的,我们称之为向量(vector)。每条time-series通过指标名称(metrics name)和一组标签集(labelset)命名。在time-series中的每一个点称为一个样本(sample),样本由以下三部分组成:指标(metric):metric name和描述当前样本特征的labelsets;时间戳(timestamp):一个精确到毫秒的时间戳;样本值(value): 一个folat64的浮点型数据表示当前样本的值。如某一时刻的node_cpu指标为459.71node_cpu{app=“node-exporter”,cpu=“cpu0”,instance=“192.168.0.4:9100”,job=“kubernetes-service-endpoints”,kubernetes_name=“node-exporter”,kubernetes_namespace=“kube-system”,mode=“guest”} 459.71Prometheus定义了4中不同的指标类型(metric type):Counter 计数器计数器,只增不减,如http_requests_total请求总数例如,通过rate()函数获取HTTP请求量的增长率:rate(http_requests_total[5m])Gauge 仪表盘当前状态,可增可减。如kube_pod_status_ready当前pod可用数可以获取样本在一段时间返回内的变化情况,如:delta(kube_pod_status_ready[2h])Histogram 直方图Histogram 由 <basename>_bucket{le="<upper inclusive bound>"},<basename>_bucket{le="+Inf"}, <basename>_sum,<basename>_count 组成,主要用于表示一段时间范围内对数据进行采样(通常是请求持续时间或响应大小),并能够对其指定区间以及总数进行统计,通常它采集的数据展示为直方图。例如 Prometheus server 中 prometheus_local_storage_series_chunks_persisted, 表示 Prometheus 中每个时序需要存储的 chunks 数量,我们可以用它计算待持久化的数据的分位数。Summary 摘要Summary 和 Histogram 类似,由 <basename>{quantile="<>"},<basename>_sum,<basename>_count 组成,主要用于表示一段时间内数据采样结果(通常是请求持续时间或响应大小),它直接存储了 quantile 数据,而不是根据统计区间计算出来的。例如 Prometheus server 中 prometheus_target_interval_length_seconds。Histogram 需要通过 <basename>_bucket 计算 quantile, 而 Summary 直接存储了 quantile 的值。基础查询PromQL是Prometheus内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。如http_requests_total指标你可以通过附加一组标签,并用{}括起来,来进一步筛选这些时间序列。下面这个例子只选择有http_requests_total名称的、有prometheus工作标签的、有canary组标签的时间序列:http_requests_total{job=“prometheus”,group=“canary”}如果条件为空,可以写为:http_requests_total{}另外,也可以也可以将标签值反向匹配,或者对正则表达式匹配标签值。如操作符: =:选择正好相等的字符串标签 !=:选择不相等的字符串标签 =~:选择匹配正则表达式的标签(或子标签) !=:选择不匹配正则表达式的标签(或子标签) 范围查询类似http_requests_total{job=“prometheus”,group=“canary”}的方式,得到的是瞬时值,如果想得到一定范围内的值,可以使用范围查询时间范围通过时间范围选择器[]进行定义。例如,通过以下表达式可以选择最近5分钟内的所有样本数据,如:http_request_total{}[5m]除了分钟,支持的单位有:s - 秒m - 分钟h - 小时d - 天w - 周y - 年偏移查询如:查询http_requests_total在当前时刻的一周的速率:rate(http_requests_total{} offset 1w)偏移修饰符允许更改查询中单个即时向量和范围向量的时间偏移量,例如,以下表达式返回相对于当前查询时间5分钟前的http_requests_total值:http_requests_total offset 5m等价于http_requests_total{job=“prometheus”}[5m]请注意,偏移量修饰符始终需要跟随选择器,即以下是正确的:sum(http_requests_total{method=“GET”} offset 5m) // GOOD.下面是错误的:sum(http_requests_total{method=“GET”}) offset 5m // INVALID.操作符Prometheus 的查询语言支持基本的逻辑运算和算术运算二元算术运算:加法减法乘法/ 除法% 模^ 幂等运算中用到的基础数据类型:瞬时向量(Instant vector) - 一组时间序列,每个时间序列包含单个样本,它们共享相同的时间戳。也就是说,表达式的返回值中只会包含该时间序列中的最新的一个样本值。而相应的这样的表达式称之为瞬时向量表达式。区间向量(Range vector) - 一组时间序列,每个时间序列包含一段时间范围内的样本数据。标量(Scalar) - 一个浮点型的数据值。字符串(String) - 一个简单的字符串值。二元运算操作符支持 scalar/scalar(标量/标量)、vector/scalar(向量/标量)、和 vector/vector(向量/向量) 之间的操作。在两个标量之间进行数学运算,得到的结果也是标量。例如,如果我们想根据 node_disk_bytes_written 和 node_disk_bytes_read 获取主机磁盘IO的总量,可以使用如下表达式:node_disk_bytes_written + node_disk_bytes_read或者node的内存数GBnode_memory_free_bytes_total / (1024 * 1024)布尔运算== (相等)!= (不相等)(大于)< (小于)= (大于等于)<= (小于等于)如:获取http_requests_total请求总数是否超过10000,返回0和1,1则报警http_requests_total > 10000 # 结果为 true 或 falsehttp_requests_total > bool 10000 # 结果为 1 或 0集合运算and (并且)or (或者)unless (排除)优先级四则运算有优先级,promql的复杂运算也有优先级例如,查询主机的CPU使用率,可以使用表达式:100 * (1 - avg (irate(node_cpu{mode=‘idle’}[5m])) by(job) )其中irate是PromQL中的内置函数,用于计算区间向量中时间序列每秒的即时增长率在PromQL操作符中优先级由高到低依次为:^, /, %+, -==, !=, <=, <, >=, >and, unlessor匹配模式(联合查询)与数据库中的join类似,promsql有两种典型的匹配查询:一对一(one-to-one)多对一(many-to-one)或一对多(one-to-many)例如当存在样本:method_code:http_errors:rate5m{method=“get”, code=“500”} 24method_code:http_errors:rate5m{method=“get”, code=“404”} 30method_code:http_errors:rate5m{method=“put”, code=“501”} 3method_code:http_errors:rate5m{method=“post”, code=“500”} 6method_code:http_errors:rate5m{method=“post”, code=“404”} 21method:http_requests:rate5m{method=“get”} 600method:http_requests:rate5m{method=“del”} 34method:http_requests:rate5m{method=“post”} 120使用 PromQL 表达式:method_code:http_errors:rate5m{code=“500”} / ignoring(code) method:http_requests:rate5m该表达式会返回在过去 5 分钟内,HTTP 请求状态码为 500 的在所有请求中的比例。如果没有使用 ignoring(code),操作符两边表达式返回的瞬时向量中将找不到任何一个标签完全相同的匹配项。因此结果如下:{method=“get”} 0.04 // 24 / 600{method=“post”} 0.05 // 6 / 120同时由于 method 为 put 和 del 的样本找不到匹配项,因此不会出现在结果当中。多对一模式例如,使用表达式:method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m该表达式中,左向量 method_code:http_errors:rate5m 包含两个标签 method 和 code。而右向量 method:http_requests:rate5m 中只包含一个标签 method,因此匹配时需要使用 ignoring 限定匹配的标签为 code。 在限定匹配标签后,右向量中的元素可能匹配到多个左向量中的元素 因此该表达式的匹配模式为多对一,需要使用 group 修饰符 group_left 指定左向量具有更好的基数。最终的运算结果如下:{method=“get”, code=“500”} 0.04 // 24 / 600{method=“get”, code=“404”} 0.05 // 30 / 600{method=“post”, code=“500”} 0.05 // 6 / 120{method=“post”, code=“404”} 0.175 // 21 / 120提醒:group 修饰符只能在比较和数学运算符中使用。在逻辑运算 and,unless 和 or 操作中默认与右向量中的所有元素进行匹配。聚合操作Prometheus 还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个具有较少样本值的新的时间序列。sum (求和)min (最小值)max (最大值)avg (平均值)stddev (标准差)stdvar (标准差异)count (计数)count_values (对 value 进行计数)bottomk (样本值最小的 k 个元素)topk (样本值最大的k个元素)quantile (分布统计)这些操作符被用于聚合所有标签维度,或者通过 without 或者 by 子语句来保留不同的维度。without 用于从计算结果中移除列举的标签,而保留其它标签。by 则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过 without 和 by 可以按照样本的问题对数据进行聚合。例如:如果指标 http_requests_total 的时间序列的标签集为 application, instance, 和 group,我们可以通过以下方式计算所有 instance 中每个 application 和 group 的请求总量:sum(http_requests_total) without (instance)等价于 sum(http_requests_total) by (application, group)如果只需要计算整个应用的 HTTP 请求总量,可以直接使用表达式:sum(http_requests_total)count_values 用于时间序列中每一个样本值出现的次数。count_values 会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签。这个标签的名字由聚合参数指定,同时这个标签值是唯一的样本值。例如要计算运行每个构建版本的二进制文件的数量:count_values(“version”, build_version)返回结果如下:{count=“641”} 1{count=“3226”} 2{count=“644”} 4topk 和 bottomk 则用于对样本值进行排序,返回当前样本值前 n 位,或者后 n 位的时间序列。获取 HTTP 请求数前 5 位的时序样本数据,可以使用表达式:topk(5, http_requests_total)quantile 用于计算当前样本数据值的分布情况 quantile(, express) ,其中 0 ≤ ≤ 1例如,当 为 0.5 时,即表示找到当前样本数据中的中位数:quantile(0.5, http_requests_total)返回结果如下:{} 656内置函数Prometheus 提供了其它大量的内置函数,可以对时序数据进行丰富的处理。如上文提到的irate100 * (1 - avg (irate(node_cpu{mode=‘idle’}[5m])) by(job) )常用的有:两分钟内的平均CPU使用率: rate(node_cpu[2m])和irate(node_cpu[2m])需要注意的是使用rate或者increase函数去计算样本的平均增长速率,容易陷入“长尾问题”当中,其无法反应在时间窗口内样本数据的突发变化。 例如,对于主机而言在2分钟的时间窗口内,可能在某一个由于访问量或者其它问题导致CPU占用100%的情况,但是通过计算在时间窗口内的平均增长率却无法反应出该问题。为了解决该问题,PromQL提供了另外一个灵敏度更高的函数irate(v range-vector)。irate同样用于计算区间向量的计算率,但是其反应出的是瞬时增长率。irate函数是通过区间向量中最后两个两本数据来计算区间向量的增长速率。这种方式可以避免在时间窗口范围内的“长尾问题”,并且体现出更好的灵敏度,通过irate函数绘制的图标能够更好的反应样本数据的瞬时变化状态。irate函数相比于rate函数提供了更高的灵敏度,不过当需要分析长期趋势或者在告警规则中,irate的这种灵敏度反而容易造成干扰。因此在长期趋势分析或者告警中更推荐使用rate函数。完整的函数列表为:abs()absent()ceil()changes()clamp_max()clamp_min()day_of_month()day_of_week()days_in_month()delta()deriv()exp()floor()histogram_quantile()holt_winters()hour()idelta()increase()irate()label_join()label_replace()ln()log2()log10()minute()month()predict_linear()rate()resets()round()scalar()sort()sort_desc()sqrt()time()timestamp()vector()year()<aggregation>_over_time()API访问Prometheus当前稳定的HTTP API可以通过/api/v1访问错误状态码:404 Bad Request:当参数错误或者缺失时。422 Unprocessable Entity 当表达式无法执行时。503 Service Unavailiable 当请求超时或者被中断时。所有的API请求均使用以下的JSON格式:{ “status”: “success” | “error”, “data”: <data>, // 为error时,有如下报错信息 “errorType”: “<string>”, “error”: “<string>"}通过HTTP API我们可以分别通过/api/v1/query和/api/v1/query_range查询PromQL表达式当前或者一定时间范围内的计算结果。瞬时数据查询URL请求参数:query=:PromQL表达式。time=:用于指定用于计算PromQL的时间戳。可选参数,默认情况下使用当前系统时间。timeout=:超时设置。可选参数,默认情况下使用-query,timeout的全局设置。$ curl ‘http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z’返回:{ “status” : “success”, “data” : { “resultType” : “vector”, “result” : [ { “metric” : { “name” : “up”, “job” : “prometheus”, “instance” : “localhost:9090” }, “value”: [ 1435781451.781, “1” ] }, { “metric” : { “name” : “up”, “job” : “node”, “instance” : “localhost:9100” }, “value” : [ 1435781451.781, “0” ] } ] }}区间查询URL请求参数:query=: PromQL表达式。start=: 起始时间。end=: 结束时间。step=: 查询步长。timeout=: 超时设置。可选参数,默认情况下使用-query,timeout的全局设置。$ curl ‘http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s’返回:{ “status” : “success”, “data” : { “resultType” : “matrix”, “result” : [ { “metric” : { “name” : “up”, “job” : “prometheus”, “instance” : “localhost:9090” }, “values” : [ [ 1435781430.781, “1” ], [ 1435781445.781, “1” ], [ 1435781460.781, “1” ] ] }, { “metric” : { “name” : “up”, “job” : “node”, “instance” : “localhost:9091” }, “values” : [ [ 1435781430.781, “0” ], [ 1435781445.781, “0” ], [ 1435781460.781, “1” ] ] } ] }}本文为容器监控实践系列文章,完整内容见:container-monitor-book ...

March 4, 2019 · 3 min · jiezi

容器监控实践—Prometheus基本架构

系统架构图1.x版本的Prometheus的架构图为:目前Prometheus版本为2.7,架构图为:Prometheus从exporter拉取数据,或者间接地通过网关gateway拉取数据(如果在k8s内部署,可以使用服务发现的方式),它默认本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中,采集到的数据有两个去向,一个是报警,另一个是可视化。PromQL和其他API可视化地展示收集的数据,并通过Alertmanager提供报警能力。组件内容Prometheus Server负责从 Exporter 拉取和存储监控数据,并提供一套灵活的查询语言(PromQL)Retrieval: 采样模块TSDB: 存储模块默认本地存储为tsdbHTTP Server: 提供http接口查询和面板,默认端口为9090Exporters/Jobs负责收集目标对象(host, container…)的性能数据,并通过 HTTP 接口供 Prometheus Server 获取。支持数据库、硬件、消息中间件、存储系统、http服务器、jmx等。只要符合接口格式,就可以被采集。Short-lived jobs瞬时任务的场景,无法通过pull方式拉取,需要使用push方式,与PushGateway搭配使用PushGateway可选组件,主要用于短期的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。为此,这次 jobs 可以直接向 Prometheus server 端推送它们的 metrics。这种方式主要用于服务层面的 metrics,对于机器层面的 metrices,需要使用 node exporter。客户端sdk官方提供的客户端类库有go、java、scala、python、ruby,其他还有很多第三方开发的类库,支持nodejs、php、erlang等PromDash使用rails开发的dashboard,用于可视化指标数据,已废弃Alertmanager从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等。Service Discovery服务发现,Prometheus支持多种服务发现机制:文件,DNS,Consul,Kubernetes,OpenStack,EC2等等。基于服务发现的过程并不复杂,通过第三方提供的接口,Prometheus查询到需要监控的Target列表,然后轮训这些Target获取监控数据。其大概的工作流程是:Prometheus server 定期从配置好的 jobs 或者 exporters 中拉 metrics,或者接收来自 Pushgateway 发过来的 metrics,或者从其他的 Prometheus server 中拉 metrics。Prometheus server 在本地存储收集到的 metrics,并运行已定义好的 alert.rules,记录新的时间序列或者向 Alertmanager 推送警报。Alertmanager 根据配置文件,对接收到的警报进行处理,发出告警。在图形界面中,可视化采集数据。关于Push与PullPrometheus采集数据是用的pull也就是拉模型,通过HTTP协议去采集指标,只要应用系统能够提供HTTP接口就可以接入监控系统,相比于私有协议或二进制协议来说开发、简单。优点主要是:开发任何新功能,你甚至可以在电脑上查看你的监控如果目标实例挂掉,你可以很快知道你可以手动指定目标实例,并且在浏览器中查看他的健康状态总体来说,Pull模式比Push模式更好一些,在监控系统中这也不是一个很重要的点。如果要使用push的方式,可以使用Pushgateway的方式,如定时任务的采集。对于定时任务这种短周期的指标采集,如果采用pull模式,可能造成任务结束了,Prometheus还没有来得及采集,这个时候可以使用加一个中转层,客户端推数据到Push Gateway缓存一下,由Prometheus从push gateway pull指标过来。(需要额外搭建Push Gateway,同时需要新增job去从gateway采数据)推的代表有 ElasticSearch,InfluxDB,OpenTSDB 等,需要你从程序中将指标使用 TCP,UDP 等方式推送至相关监控应用,只是使用 TCP 的话,一旦监控应用挂掉或存在瓶颈,容易对应用本身产生影响,而使用 UDP 的话,虽然不用担心监控应用,但是容易丢数据。拉的代表,主要代表就是 Prometheus,让我们不用担心监控应用本身的状态。而且,可以利用 DNS-SRV 或者 Consul 等服务发现功能就可以自动添加监控。当然,InfluxDB 加上 collector,或者 ES 加上 metricbeat 也可以变为 『拉』,而 Prometheus 加上 Push Gateway 也可以变为 『推』。更多区别可以参考下图:存储机制Prometheus有着非常高效的时间序列数据存储方法,每个采样数据仅仅占用3.5byte左右空间,上百万条时间序列,30秒间隔,保留60天,大概花了200多G(引用官方PPT)。Prometheus内部主要分为三大块,Retrieval是负责定时去暴露的目标页面上去抓取采样指标数据,Storage是负责将采样数据写磁盘,PromQL是Prometheus提供的查询语言模块。Prometheus内置了一个基于本地存储的时间序列数据库。在Prometheus设计上,使用本地存储可以降低Prometheus部署和管理的复杂度同时减少高可用(HA)带来的复杂性。 在默认情况下,用户只需要部署多套Prometheus,采集相同的Targets即可实现基本的HA。同时由于Promethus高效的数据处理能力,单个Prometheus Server基本上能够应对大部分用户监控规模的需求。同时为了适应数据持久化的问题,Prometheus提供了remote_write和remote_read的特性,支持将数据存储到远端和从远端读取数据。通过将监控与数据分离,Prometheus能够更好地进行弹性扩展。关于存储用量规划:https://www.jianshu.com/p/934…更多:Prometheus存储机制详解https://yunlzheng.gitbook.io/…https://www.cnblogs.com/vovli...https://www.linuxidc.com/Linu...https://segmentfault.com/a/11...https://www.infoq.cn/article/…关于日志处理不建议将日志监控放在Prometheus中,这不是他的专长,还是使用ELK或EFK的方式处理日志信息竞品对比参考: https://toutiao.io/posts/fsjq…未来规划服务端度量指标元数据支持在度量指标类型和其他元数据仅仅在客户库和展示格式中使用,并不会在Prometheus服务中持久保留或者利用。将来我们计划充分利用这些元数据。第一步是在Prometheus服务的内存中聚合这些数据,并开放一些实验性的API来提供服务支持OpenMetricsOpenMetrics组开放了一个新的监控指标暴露标准,我们将支持这种标准:https://openmetrics.io/回溯时间序列允许将过去一段时间的数据发送到其他的监控系统HTTP服务支持TLS安全认证当前的Prometheus, Alertmanager和一些官方exporter,暴露服务时,都不支持tls认证,有很大的安全风险,现在的实现都是基于反向代理,之后将内置到组件中支持子查询当前的Promq不支持子查询,如max_over_time() of a rate()),后续将会支持支持生态建设Prometheus有很多的client库和exporter,我们将会对其进行规范和生态建设。在K8S中使用在之前的版本中,k8s默认以及推荐的监控体系是它自己的一套东西:Heapster + cAdvisor + Influxdb + Grafana,1.8后Heaspter由Metric-server替代。如果你部署了Dashboard,就能看到监控数据(来自heapster)k8s 自身的 HPA (Horizontal Pod Autoscaler),默认从 Heapster 中获取数据进行自动伸缩1.8版本以后,K8S希望将核心监控指标收拢到metric api的形式,而自定义监控指标,由prometheus来实现,prometheus正式成为k8s推荐的监控实现方案。参考文档:https://www.ibm.com/developer…https://prometheus.io/docs/in...https://www.kancloud.cn/cdh08...https://yunlzheng.gitbook.io/…本文为容器监控实践系列文章,完整内容见:container-monitor-book ...

March 4, 2019 · 1 min · jiezi

容器监控实践—Prometheus部署方案

一.单独部署二进制安装各版本下载地址:https://prometheus.io/download/Docker运行运行命令:docker run –name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus暴露服务: http://localhost:9090/二.在K8S中部署如果在Kubernetes中部署Prometheus,可以使用prometheus in kubernetes,含exporter、grafana等组件。安装方式:kubectl apply \ –filename https://raw.githubusercontent.com/giantswarm/kubernetes-prometheus/master/manifests-all.yaml卸载方式:kubectl delete namespace monitoring该方式为大多数用户和云厂商使用的方式,可以基于Prometheus的服务发现:在annotation中设置prometheus.io/scrape为true,就可以把K8S的所有服务都加入到监控中,但在使用的过程中会有一些问题:1.如果增加了新的exporter,如nginx-exporter,需要修改prometheus配置并重启2.服务本身和监控配置没有分离3.监控集群多实例的状态不好管理4.报警配置也包含在prometheus的配置中,监控与报警没有分离,添加规则麻烦以上问题一般的处理方式为:在prometheus上加一个控制台,来动态配置target、报警规则,并向后端server发起修改、重启操作。同时有权限控制、日志审计、整体配置过期时间等功能。但如果使用了Prometheus Operator,就可以将以上大多数操作抽象为k8s中的资源提交、修改,减少上层封装的工作量。三.Prometheus Operator部署Prometheus-Operator是一套为了方便整合prometheus和kubernetes的开源方案,使用Prometheus-Operator可以非常简单的在kubernetes集群中部署Prometheus服务,用户能够使用简单的声明性配置来配置和管理Prometheus实例,这些配置将响应、创建、配置和管理Prometheus监控实例。官方地址:https://github.com/coreos/pro…目前状态:beta状态,还不够完整,但向后兼容。将成为趋势前置条件:要求k8s的版本>=1.8.0(应该是因为metric api和CRD支持的限制)Operator的核心思想是将Prometheus的部署与它监控的对象的配置分离,做到部署与监控对象的配置分离之后,就可以轻松实现动态配置。使用Operator部署了Prometheus之后就可以不用再管Prometheus Server了,以后如果要添加监控对象或者添加告警规则,只需要编写对应的ServiceMonitor和Prometheus资源就可以,不用再重启Prometheus服务,Operator会动态的观察配置的改动,并将其生成为对应的prometheus配置文件其中Operator可以部署、管理Prometheus Service四种CRD作用如下:Prometheus: 由 Operator 依据一个自定义资源kind: Prometheus类型中,所描述的内容而部署的 Prometheus Server 集群,可以将这个自定义资源看作是一种特别用来管理Prometheus Server的StatefulSets资源。ServiceMonitor: 一个Kubernetes自定义资源(和kind: Prometheus一样是CRD),该资源描述了Prometheus Server的Target列表,Operator 会监听这个资源的变化来动态的更新Prometheus Server的Scrape targets并让prometheus server去reload配置(prometheus有对应reload的http接口/-/reload)。而该资源主要通过Selector来依据 Labels 选取对应的Service的endpoints,并让 Prometheus Server 通过 Service 进行拉取(拉)指标资料(也就是metrics信息),metrics信息要在http的url输出符合metrics格式的信息,ServiceMonitor也可以定义目标的metrics的url。Alertmanager:Prometheus Operator 不只是提供 Prometheus Server 管理与部署,也包含了 AlertManager,并且一样通过一个 kind: Alertmanager 自定义资源来描述信息,再由 Operator 依据描述内容部署 Alertmanager 集群。PrometheusRule:对于Prometheus而言,在原生的管理方式上,我们需要手动创建Prometheus的告警文件,并且通过在Prometheus配置中声明式的加载。而在Prometheus Operator模式中,告警规则也编程一个通过Kubernetes API 声明式创建的一个资源.告警规则创建成功后,通过在Prometheus中使用想servicemonitor那样用ruleSelector通过label匹配选择需要关联的PrometheusRule即可。安装方式:创建命名空间:monitoring执行yaml文件:https://github.com/coreos/pro…prometheus的target列表: grafana的自带监控图列表:常见问题:因为要operator中要支持聚合api,在某些版本的集群上可能需要一些配置,如下:安装cfssl证书生成工具:http://www.cnblogs.com/xuling…生成证书cfssl gencert -ca=/etc/kubernetes/pki/ca.pem -ca-key=/etc/kubernetes/pki/ca-key.pem -config=/etc/kubernetes/pki/ca-config.json -profile=jpaas metrics-server-csr.json | cfssljson -bare metrics-server{ “CN”: “aggregator”, “host”: [], “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “C”: “CN”, “ST”: “BeiJing”, “L”: “BeiJing”, “O”: “k8s”, “OU”: “cloudnative” } ]}配置master组件参数,以支持metric-servervim /etc/systemd/system/kube-apiserver.service–requestheader-client-ca-file=/etc/kubernetes/pki/ca.pem --requestheader-allowed-names=“aggregator” --requestheader-extra-headers-prefix=“X-Remote-Extra-” --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --proxy-client-cert-file=/etc/kubernetes/pki/metrics-server.pem --proxy-client-key-file=/etc/kubernetes/pki/metrics-server-key.pem --runtime-config=api/all=true --enable-aggregator-routing=true \systemctl daemon-reloadsystemctl restart kube-apiserver.servicesystemctl status kube-apiserver.servicevim /etc/systemd/system/kube-controller.service–horizontal-pod-autoscaler-use-rest-clients=truesystemctl daemon-reloadsystemctl restart kube-controller.servicesystemctl status kube-controller.service启动成功后,prometheus的target中,kubelet没有值,401报错vim /etc/systemd/system/kubelet.service–authentication-token-webhook=true–authorization-mode=Webhooksystemctl daemon-reloadsystemctl restart kubelet.service参考文档:https://github.com/coreos/pro…https://www.yinjk.cn/2018/09/...http://www.servicemesher.com/…本文为容器监控实践系列文章,完整内容见:container-monitor-book ...

March 4, 2019 · 1 min · jiezi

K3s初探:Rancher架构师带你尝鲜史上最轻量Kubernetes发行版

发布不到两天,GitHub上Star数已近3000,这个业界大热的、史上最轻量的开源Kubernetes发行版,你试过了没?Rancher资深架构师来教你走出尝鲜第一步!使用教程在此!前 言昨天,Rancher Labs正式发布了一款史上最轻量的开源Kubernetes发行版——K3s。K3s大小只有40M,极简,轻便,易于使用。K3s专为在资源有限的环境中运行Kubernetes的研发和运维人员设计,尤其适用于边缘计算、IoT、ARM和CI等新兴使用场景。同时,K3s支持x86_64、ARM64和ARMv7架构,可以更加灵活地跨任何边缘基础架构工作。K3s发布不到两天时间,就得到了来自业界的大量积极反馈,大家的热情让我们感受到容器领域的创新依然还在路上。K3s顺利地成为了CNCF认证的Kubernetes发行版,K3s的GitHub star数短短一天时间内就逼近3000,国内外新闻及技术媒体高度关注,容器技术圈广受尊重的大师Kelsey Hightower也发出推文表示赞赏。而Rancher所做的一切就是我们始终没有忘记初心,我们始终要做一家云基础设施厂商,并坚持创新,Rancher/RKE/RancherOS/Longhorn/Rio/K3s这些产品不断的在扩展我们的技术版图。那么K3s到底是什么?主要创新点在哪里?让我们上手一试。上手一试我们在AWS 启动两个虚拟机,系统为RancherOS v1.5.1,当然你也可以换成你熟悉的OS。不过目前K3s项目还处在发展阶段,有些OS的适配还没有完成,Ubuntu会是另一个不错的选择。RancherOS是极致精简专为容器定制的Linux,在这里使用RancherOS可以让我们更充分体会到K3s对OS的依赖几乎很少。K3s已经使用了containerd替换Docker来做runtime, 所以我们可以在RancherOS停止Docker。containerd本身就是Docker的一部分,完全兼容我们所熟悉的Docker image。默认server本身会自带agent,可以使用 –disable-agent 参数让其只提供server功能。获取node token添加额外的agent,node_token使用上面步骤返回的内容替换。同样我们已经不需要docker,依然在RancherOS中停止Docker。由于K3s移除了k8s中很多Legacy/alpha/non-default features,所以不要用一个特别复杂的yaml文件来尝试。基本常用的deployment是支持的,所以我们可以部署一个deployment。当然我们也可以将K3s添加到Rancher中,目前支持导入方式,虽然还不是很完善,不过我们会持续不断更新提升体验。你需要下载Rancher import集群时所需的yaml文件,与原生的K8s不同,这里K3s导入需要使用 K3s kubectl。等待一段时间后,你可以看到K3s集群导入成功,由于K3s精简了很多k8s的组件,etcd默认是不启用的(默认使用sqlite3),所以有些报错暂时可以忽略。我们还可以用Rancher UI来创建简单的workload。K3s,推动Kubernetes在边缘计算场景“K3s”的名称含义是指“5 Less Than K8s”,它的大小、对资源的需求、复杂度、使用难度等等都【不到Kubernetes的一半】,极其的轻量和易于使用。对于制造业、零售、金融、电信、公共事业等行业,或是任何认可Kubernetes是管理边缘基础设施的理想平台、但难以在边缘设备中投入大量资源来运行一个成熟的Kubernetes平台的用户而言,K3s都是具有巨大进步意义的创造性新产品。K3s被打包为一个没有主机依赖的单个二进制文件,大小只有40M,却包含运行Kubernetes所需的一切,包括容器运行时和任何重要的主机实用程序,如iptables、socat和du等。只需要一条命令,您就可以配置或者升级单节点K3s集群,或是向集群添加节点。极低的资源消耗,操作简单,易于上手,删繁就简的理念,加上最重要的、创造性地满足边缘计算的场景需求,让K3s甫一推出就受到了全球范围内企业客户、开源用户、业界大牛、媒体、技术社区等的关注及肯定。发布不到两天时间,GitHub上的Star数已经逼近3000:K3s发布当天,各种相关新闻直接登顶谷歌Kubernetes关键词搜索结果:Hacker News上的讨论热度居高不下:K3s通过了CNCF认证,成为官方认证Kubernetes发行版,CNCF执行总裁Dan Kohn亦亲自祝贺:来自巨量社区用户的支持:技术圈广受尊敬的大牛Kelsey Hightower对K3s高度推崇:一些思考Rancher在近些年越来越感受到outside datacenter的管理需求,不仅仅来自有工业物联网背景的制造业,甚至还有美国的快餐连锁行业,这些边缘计算的真实诉求推动着我们来创新。将容器技术移植到边缘计算场景是个非常好的选择,容器拥有很好的生态系统,并且能够天然屏蔽硬件差异,带来部署管理上的极大便捷。容器技术尤其是Kubernetes在数据中心层面愈发成熟,但是完全移植到边缘计算场景还是存在诸多问题,比如K8s对计算资源的消耗是边缘设备无法承受的, 同时很多K8s发行版无法支持ARM,而边缘设备目前是以ARM居多。这些其实就是Rancher创建K3s项目要解决的真实问题,K3s不仅仅是Rancher的产品, 我们还会推动它成为Kubernetes在边缘计算领域的标准。未来Rancher容器管理平台会成为既可以管理datacenter k8s又可以管理outside k3s的产品,用户可以选择极致精简的容器操作系统RancherOS,和专为容器而生的存储系统Longhorn来满足云内部和云之间的存储需求。在即将发布Rancher 2.2版本中,Rancher完成了对ARM的支持,这样Rancher的纳管版图又扩大了很多,对边缘计算的支持将会更大。K3s官网主页现已上线,您可以访问https://k3s.io了解K3s项目的更…。同时,欢迎通过GitHub页面https://github.com/rancher/k3…。下周我们会面向Rancher付费订阅客户进行K3s的首次产品最佳实践及架构培训。需要协助部署和管理k3s的企业可邮件联系yiyi@rancher.com,或添加微信助手(rancher2)为好友进行咨询。

March 1, 2019 · 1 min · jiezi

CNCF宣布containerd毕业

阿里云、AWS、Cloud Foundry、Docker、Google、IBM、Rancher Labs以及更多支持促进生态系统最广泛采用的容器运行引擎加利福尼亚州旧金山,2018年2月28日 - 支持Kubernetes®和Prometheus™等开源技术的CNCF®(云原生计算基金会Cloud Native Computing Foundation®)今天宣布,在Kubernetes、Prometheus、Envoy和CoreDNS之后,containerd是第五个毕业项目。要从孵化的成熟水平到毕业,项目必须表现出蓬勃的采用、多样性、正式的治理过程,以及对社区永续性和包容性的坚定承诺。“在差不多两年前被CNCF接纳后,containerd继续看到显着的发展势头,展示了对基础容器技术的需求。”CNCF首席技术官Chris Aniszczyk说。“项目社区投放了大量的工作和协作,以稳定核心容器运行引擎的开发和测试,社区也努力扩大其维护者和采用基础,同时通过外部安全审计,所以我很激动看到项目毕业。”在2014年出生于Docker,containerd最初是Docker引擎的低层运行管理器。继2017年3月被CNCF接受之后,containerd已经成为行业标准的容器运行引擎,专注于简单、健壮和可移植,其最广泛的用途和采用是作为Docker引擎和OCI runc执行器的中间层。 “当Docker向社区贡献containerd的时候,我们的目标是分享一个强大且可扩展的运行引擎,这个引擎作为Docker Engine的一部分已经是数百万用户和成千上万的组织的标准。”containerd维护者和Docker工程师Michael Crosby说。“随着我们扩大范围以满足Docker平台和Kubernetes生态系统等现代化容器平台的需求,看到containerd在过去一年的采用和进一步的创新得到了回报。随着containerd的采用不断增长,我们期待整个生态系统继续合作推动我们的行业发展。”“IBM Cloud Kubernetes Service(IKS)致力于为我们的客户提供卓越的托管Kubernetes体验。为实现这一目标,我们一直在努力简化IKS的架构和运营状况。”IBM Cloud Kubernetes Service杰出工程师Dan Berg说。“迁移到containerd有助于简化我们替客户配置和管理的Kubernetes架构。通过采用containerd作为我们的容器引擎,我们减少了架构中的附加层,从而为我们的客户改善了运营,并提高了服务性能。”containerd自成立以来就拥有各种维护者和审阅者,目前有来自阿里巴巴、Cruise Automation、Docker、Facebook、Google、华为、IBM、微软、NTT、特斯拉等公司的14位提交者,4,406份提交和166位贡献者。可以在DevStats上找到containerd项目统计信息、贡献者统计信息等。“自成立以来,阿里巴巴一直使用containerd,我们很高兴看到该项目达到了这一里程碑。containerd作为容器运营引擎的开放、可靠和通用基础发挥着关键作用。在阿里云,我们的阿里云Kubernetes服务和无服务器Kubernetes利用了containerd的简单、稳健和可扩展性。”阿里云高级工程师Li Yi说。“阿里巴巴团队将继续致力于社区以推动创新。”为了正式从孵化状态毕业,该项目采用了CNCF行为准则,执行了独立的安全审计,并确定了自己的治理结构以发展社区。此外,containerd还必须获得(并维护)核心基础设施倡议(Core Infrastructure Initiative,CII)最佳实践徽章。CII徽章于2018年9月1日完成,显示了对代码质量和安全最佳实践的持续承诺。containerd背景containerd是行业标准的容器运行引擎,强调简单、健壮和可移植性。containerd可用作Linux和Windows的守护程序。containerd管理其主机系统的完整容器生命周期,从镜像传输和存储,到容器执行和监督,到低级存储,到网络附件等。有关下载、文档以及如何参与,请到https://github.com/containerd…。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!

March 1, 2019 · 1 min · jiezi

Rancher发布K3s!史上最轻量K8s发行版,赋能边缘计算

史上最轻量的开源Kubernetes发行版——K3s来了!满足Kubernetes在边缘计算和IoT设备上的新兴使用场景。2019年2月26日,业界领先的容器管理软件提供商Rancher Labs(以下简称Rancher)宣布推出轻量级Kubernetes发行版K3s,这款产品专为在资源有限的环境中运行Kubernetes的研发和运维人员设计。Rancher此次发布的K3s项目,将满足在边缘计算环境中运行在x86、ARM64和ARMv7处理器上的小型、易于管理的Kubernetes集群日益增长的需求。“现有的Kubernetes发行版通常是内存密集型的,在边缘计算环境中显得过于复杂。”Rancher联合创始人及CEO梁胜表示:“在过去的一年间,和Rancher达成合作的企业客户中有数十个都向我们表达过,他们认为Kubernetes是管理边缘基础设施的理想平台,但他们不愿意在他们的边缘设备中投入大量资源来运行一个成熟的Kubernetes平台。通过K3s,我们可以为这些团队提供一个小于512MB RAM的Kubernetes发行版,非常适用于边缘计算的用例。零售、金融、电信、公共事业和制造业的企业将对K3s有非常大的需求。”K3s如何减少Kubernetes的大小为了减少运行Kubernetes所需内存,Rancher K3s开发团队主要专注于以下四个方面的主要变化:删除旧的、非必须的代码:K3s不包括任何默认禁用的Alpha功能或者过时的功能,原有的API组件目前仍运行于标准部署当中。除此之外,Rancher还删除了所有非默认许可控制器,in- tree云提供商和存储驱动程序,但允许用户添加任何他们需要的驱动程序。整合正在运行的打包进程:为了节省RAM,Rancher将通常在Kubernetes管理服务器上运行的多流程合并为单个流程。Rancher还将在工作节点上运行的kubelet、kubeproxy和flannel代理进程组合成一个进程。使用containerd代替Docker作为运行时的容器引擎:通过用containderd替换Docker,Rancher能够显著减少运行时占用空间,删除libnetwork、swarm、Docker存储驱动程序和其他插件等功能。除了 etcd 之外,引入 SQLite 作为可选的数据存储:Rancher在k3s中添加了SQLite作为可选的数据存储,从而为etcd提供了一个轻量级的替代方案。该方案不仅占用了较少的内存,而且大幅简化了操作。推动Kubernetes在边缘计算场景落地随着Kubernetes的部署开始有边缘部署的发展趋势,企业需要运维管理的Kubernetes集群数量正在迅速增加。在许多最有趣的边缘计算用例当中,组织将运行成千上万的只有一个、两个或者三个节点的Kubernetes集群,运维人员需要负责管理如此大规模的基础架构,而K3s正是为此而生,旨在最大限度地简化用户的安装和操作体验。K3s主要功能包括:生产级Kubernetes:K3s是一个符合标准的、已获CNCF官方认证的Kubernetes发行版。一个没有主机依赖的二进制文件:在任何设备上安装Kubernetes所需的一切都包含在这一个40MB的二进制文件当中,不需要像KuberSpray、KubeADM或者RKE这样的外部安装程序。只需要一个命令,用户就可以配置或者升级单节点K3s集群。一条命令,向集群添加节点:若想向集群添加其他节点,管理员只需在新节点上运行一条命令,指向原始服务器,通过安全token传递即可。自动生成证书:集群启动时,在Kubernetes主服务器和节点之间建立TLS所需的所有证书都会被自动创建,还会自动创建服务账号的加密密钥。Rancher同时发布了支持x86_64、ARM64和ARMv7架构的K3s,使K3s得以更加灵活地跨任何边缘基础架构工作。除了边缘计算的使用场景,K3s还非常适合那些寻求简单方法来部署Kubernetes轻量级发行版的用户。在早期技术预览期间,许多用户反馈说K3s对于CI/CD环境、嵌入式系统和本地Kubernetes部署特别有帮助。K3s的四大使用场景为:边缘计算与应用程序绑定使用嵌入式设备CI环境“我们有着超过30,000个风力发电机在投产使用中,K3s的出现让我们无比兴奋与期待,因为它意味着我们将可以在成千上万个边缘计算的位置部署Kubernetes集群。”世界第二大风力发电机制造商金风慧能技术副总经理张伟表示。K3s,业界所需Arm一直在致力于构建下一代云端到边缘基础设施,同时也与合作伙伴紧密合作以实现进一步创新。我们与Kubernetes创新领导者Rancher的持续合作,充分证明了云原生容器生态在支持基于Arm Neoverse™平台的云端数据中心和边缘使用案例方面取得的进展。 ——Arm基础业务设施软件生态系统拓展高级主管Kevin RyanKubernetes不仅是最流行的集中式云工作负载的控制平台,它也越来越多地集中管理着广泛多样的环境当中的众多应用程序。Rancher的K3s项目解决了一个巨大的挑战,通过减少资源足迹将Kubernetes的优势进一步扩展到边缘计算领域,同时提供相同的生产级体验。向Rancher团队致敬!他们领导了云原生‘无处不在’的冲锋 ——Packer CEO Zac Smith我们早已察觉到,越来越多企业有这一需求——希望将Kubernetes的分布式应用部署到边缘。这一次,支持Hivecell硬件的Rancher K3s的发布,将使生产级别的工作负载在无人参与、资源受限的远程物联网环境中成为可能。Ricker Lyman Robotic的团队很高兴能与Rancher合作! ——Ricker Lyman Robotic CEO Jeffrey Ricker一切开源,欢迎使用K3s官网主页现已上线,您可以访问 https://k3s.io 了解K3s项目的更多信息。同时,欢迎通过GitHub https://github.com/rancher/k3s 下载K3s并安装与使用。需要协助部署和管理k3s的企业请邮件联系 info@rancher.com。About Rancher LabsRancher Labs由硅谷云计算泰斗、CloudStack之父梁胜创建,致力于打造创新的开源软件,帮助企业在生产环境中运行容器与Kubernetes。旗舰产品Rancher是一个开源的企业级Kubernetes平台,是业界首个且唯一可以管理所有云上、所有发行版、所有Kubernetes集群的平台。解决了生产环境中企业用户可能面临的基础设施不同的困境,改善Kubernetes原生UI易用性不佳以及学习曲线陡峭的问题,是企业落地Kubernetes的不二之选。Rancher在全球拥有超过一亿的下载量,超过20000家企业客户。全球知名企业如中国人寿、华为、中国平安、民生银行、兴业银行、上汽集团、海尔、米其林、天合光能、丰田、本田、霍尼韦尔、金风科技、普华永道、海南航空、厦门航空、恒大人寿、中国太平、巴黎银行、美国银行、HSCIS恒生指数、中国水利、暴雪、CCTV等均是Rancher的付费客户。

February 28, 2019 · 1 min · jiezi

k8s与监控--k8s部署grafana6.0

前言本文主要介绍最新版本grafana6.0的一些新特性和如何部署到k8s当中。grafana6.0简介Grafana的这一更新引入了一种新的查询展示数据的方式,支持日志数据和大量其他功能。主要亮点是:Explore - 一个新的查询工作流,用于临时数据探索和故障排除。Grafana Loki - 与Grafana Labs的新开源日志聚合系统集成。Gauge Panel - 种用于gauges的新型独立面板。New Panel Editor UX 改进了面板编辑,并可在不同的可视化之间轻松切换。Google Stackdriver Datasource 已经过测试版并正式发布。Azure Monitor 插件从作为外部插件移植到核心数据源。React Plugin 支持可以更轻松地构建插件。Named Colors 包含在我们新的改良颜色选择器中。Removal of user session storage 使Grafana更易于部署并提高安全性。其实可以看出,Explore和Grafana Loki是专为用于grafana增强自己在日志展示方面而推出的future。不过 loki这个受prometheus启发而创建的日志存储和检索框架至今没有release,而且官方也不建议生产环境使用。但是loki是值得大家关注的一个技术,深度和k8s结合,可以用于专门处理k8s当中的日志。下面是一张使用Explore处理日志的截图:grafana6.0 部署我们主要提供将grafana6.0 部署到k8s中的方法。由于我们的环境是aws托管的k8s,所以需要注意pvc和svc这两个地方,需要大家移植的时候稍微做一下修改。下面是configmap,主要包含了ldap.toml 和 grafana.ini 两个配置文件。由于企业实际环境中,需要对接单位的ldap,所以包含了ldap.tomlapiVersion: v1kind: ConfigMapmetadata: labels: app: hawkeye-grafana name: hawkeye-grafana-cm namespace: sgtdata: ldap.toml: |- # To troubleshoot and get more log info enable ldap debug logging in grafana.ini # [log] # filters = ldap:debug [[servers]] # Ldap server host (specify multiple hosts space separated) host = “ldap.xxx.org” # Default port is 389 or 636 if use_ssl = true port = 389 # Set to true if ldap server supports TLS use_ssl = false # Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS) start_tls = false # set to true if you want to skip ssl cert validation ssl_skip_verify = false # set to the path to your root CA certificate or leave unset to use system defaults # root_ca_cert = “/path/to/certificate.crt” # Authentication against LDAP servers requiring client certificates # client_cert = “/path/to/client.crt” # client_key = “/path/to/client.key” # Search user bind dn bind_dn = “cn=Manager,dc=xxx,dc=com” # Search user bind password # If the password contains # or ; you have to wrap it with triple quotes. Ex “”"#password;""" bind_password = ‘xxxxx’ # User search filter, for example “(cn=%s)” or “(sAMAccountName=%s)” or “(uid=%s)” search_filter = “(cn=%s)” # An array of base dns to search through search_base_dns = [“ou=tech,cn=hawkeye,dc=xxxx,dc=com”] ## For Posix or LDAP setups that does not support member_of attribute you can define the below settings ## Please check grafana LDAP docs for examples # group_search_filter = “(&(objectClass=posixGroup)(memberUid=%s))” # group_search_base_dns = [“ou=groups,dc=grafana,dc=org”] # group_search_filter_user_attribute = “uid” # Specify names of the ldap attributes your ldap uses [servers.attributes] name = “givenName” surname = “sn” username = “cn” member_of = “memberOf” email = “email” # Map ldap groups to grafana org roles [[servers.group_mappings]] group_dn = “cn=admins,dc=grafana,dc=org” org_role = “Admin” # To make user an instance admin (Grafana Admin) uncomment line below # grafana_admin = true # The Grafana organization database id, optional, if left out the default org (id 1) will be used # org_id = 1 [[servers.group_mappings]] group_dn = “cn=users,dc=grafana,dc=org” org_role = “Editor” [[servers.group_mappings]] # If you want to match all (or no ldap groups) then you can use wildcard group_dn = “*” org_role = “Viewer” grafana.ini: |- ##################### Grafana Configuration Example ##################### # # Everything has defaults so you only need to uncomment things you want to # change # possible values : production, development ;app_mode = production # instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty ;instance_name = ${HOSTNAME} #################################### Paths #################################### [paths] # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) ;data = /var/lib/grafana # Temporary files in data directory older than given duration will be removed ;temp_data_lifetime = 24h # Directory where grafana can store logs ;logs = /var/log/grafana # Directory where grafana will automatically scan and look for plugins ;plugins = /var/lib/grafana/plugins # folder that contains provisioning config files that grafana will apply on startup and while running. ;provisioning = conf/provisioning #################################### Server #################################### [server] # Protocol (http, https, socket) ;protocol = http # The ip address to bind to, empty will bind to all interfaces ;http_addr = # The http port to use http_port = 3000 # The public facing domain name used to access grafana from a browser ;domain = localhost # Redirect to correct domain if host header does not match domain # Prevents DNS rebinding attacks ;enforce_domain = false # The full public facing url you use in browser, used for redirects and emails # If you use reverse proxy and sub path specify full url (with sub path) ;root_url = http://localhost:3000 # Log web requests ;router_logging = false # the path relative working path ;static_root_path = public # enable gzip ;enable_gzip = false # https certs & key file ;cert_file = ;cert_key = # Unix socket path ;socket = #################################### Database #################################### [database] # You can configure the database connection by specifying type, host, name, user and password # as separate properties or as on string using the url properties. # Either “mysql”, “postgres” or “sqlite3”, it’s your choice ;type = sqlite3 ;host = 127.0.0.1:3306 ;name = grafana ;user = root # If the password contains # or ; you have to wrap it with triple quotes. Ex “”"#password;""" ;password = # Use either URL or the previous fields to configure the database # Example: mysql://user:secret@host:port/database ;url = # For “postgres” only, either “disable”, “require” or “verify-full” ;ssl_mode = disable # For “sqlite3” only, path relative to data_path setting ;path = grafana.db # Max idle conn setting default is 2 ;max_idle_conn = 2 # Max conn setting default is 0 (mean not set) ;max_open_conn = # Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) ;conn_max_lifetime = 14400 # Set to true to log the sql calls and execution times. log_queries = #################################### Session #################################### [session] # Either “memory”, “file”, “redis”, “mysql”, “postgres”, default is “file” ;provider = file # Provider config options # memory: not have any config yet # file: session dir path, is relative to grafana data_path # redis: config like redis server e.g. addr=127.0.0.1:6379,pool_size=100,db=grafana # mysql: go-sql-driver/mysql dsn config string, e.g. user:password@tcp(127.0.0.1:3306)/database_name # postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable ;provider_config = sessions # Session cookie name ;cookie_name = grafana_sess # If you use session in https only, default is false ;cookie_secure = false # Session life time, default is 86400 ;session_life_time = 86400 #################################### Data proxy ########################### [dataproxy] # This enables data proxy logging, default is false ;logging = false #################################### Analytics #################################### [analytics] # Server reporting, sends usage counters to stats.grafana.org every 24 hours. # No ip addresses are being tracked, only simple counters to track # running instances, dashboard and error counts. It is very helpful to us. # Change this option to false to disable reporting. ;reporting_enabled = true # Set to false to disable all checks to https://grafana.net # for new vesions (grafana itself and plugins), check is used # in some UI views to notify that grafana or plugin update exists # This option does not cause any auto updates, nor send any information # only a GET request to http://grafana.com to get latest versions ;check_for_updates = true # Google Analytics universal tracking code, only enabled if you specify an id here ;google_analytics_ua_id = #################################### Security #################################### [security] # default admin user, created on startup ;admin_user = admin # default admin password, can be changed before first start of grafana, or in profile settings ;admin_password = admin # used for signing ;secret_key = xxxxx # Auto-login remember days ;login_remember_days = 7 ;cookie_username = grafana_user ;cookie_remember_name = grafana_remember # disable gravatar profile images ;disable_gravatar = false # data source proxy whitelist (ip_or_domain:port separated by spaces) ;data_source_proxy_whitelist = # disable protection against brute force login attempts ;disable_brute_force_login_protection = false #################################### Snapshots ########################### [snapshots] # snapshot sharing options ;external_enabled = true ;external_snapshot_url = https://snapshots-origin.raintank.io ;external_snapshot_name = Publish to snapshot.raintank.io # remove expired snapshot ;snapshot_remove_expired = true #################################### Dashboards History ################## [dashboards] # Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1 ;versions_to_keep = 20 #################################### Users ############################### [users] # disable user signup / registration ;allow_sign_up = true # Allow non admin users to create organizations ;allow_org_create = true # Set to true to automatically assign new users to the default organization (id 1) ;auto_assign_org = true # Default role new users will be automatically assigned (if disabled above is set to true) ;auto_assign_org_role = Viewer # Background text for the user field on the login page ;login_hint = email or username # Default UI theme (“dark” or “light”) ;default_theme = dark # External user management, these options affect the organization users view ;external_manage_link_url = ;external_manage_link_name = ;external_manage_info = # Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard. ;viewers_can_edit = false [auth] # Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false ;disable_login_form = false # Set to true to disable the signout link in the side menu. useful if you use auth.proxy, defaults to false ;disable_signout_menu = false # URL to redirect the user to after sign out ;signout_redirect_url = #################################### Anonymous Auth ########################## [auth.anonymous] # enable anonymous access ;enabled = false # specify organization name that should be used for unauthenticated users ;org_name = Main Org. # specify role for unauthenticated users ;org_role = Viewer #################################### Github Auth ########################## [auth.github] ;enabled = false ;allow_sign_up = true ;client_id = some_id ;client_secret = some_secret ;scopes = user:email,read:org ;auth_url = https://github.com/login/oauth/authorize ;token_url = https://github.com/login/oauth/access_token ;api_url = https://api.github.com/user ;team_ids = ;allowed_organizations = #################################### Google Auth ########################## [auth.google] ;enabled = false ;allow_sign_up = true ;client_id = some_client_id ;client_secret = some_client_secret ;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email ;auth_url = https://accounts.google.com/o/oauth2/auth ;token_url = https://accounts.google.com/o/oauth2/token ;api_url = https://www.googleapis.com/oauth2/v1/userinfo ;allowed_domains = #################################### Generic OAuth ########################## [auth.generic_oauth] ;enabled = false ;name = OAuth ;allow_sign_up = true ;client_id = some_id ;client_secret = some_secret ;scopes = user:email,read:org ;auth_url = https://foo.bar/login/oauth/authorize ;token_url = https://foo.bar/login/oauth/access_token ;api_url = https://foo.bar/user ;team_ids = ;allowed_organizations = ;tls_skip_verify_insecure = false ;tls_client_cert = ;tls_client_key = ;tls_client_ca = #################################### Grafana.com Auth #################### [auth.grafana_com] ;enabled = false ;allow_sign_up = true ;client_id = some_id ;client_secret = some_secret ;scopes = user:email ;allowed_organizations = #################################### Auth Proxy ########################## [auth.proxy] ;enabled = false ;header_name = X-WEBAUTH-USER ;header_property = username ;auto_sign_up = true ;ldap_sync_ttl = 60 ;whitelist = 192.168.1.1, 192.168.2.1 ;headers = Email:X-User-Email, Name:X-User-Name #################################### Basic Auth ########################## [auth.basic] ;enabled = true #################################### Auth LDAP ########################## [auth.ldap] enabled = true ;config_file = /etc/grafana/ldap.toml ;allow_sign_up = true #################################### SMTP / Emailing ########################## [smtp] enabled = true host = smtp.exmail.qq.com:465 user = noreply@xxx.com # If the password contains # or ; you have to wrap it with trippel quotes. Ex “”"#password;""" password = AFxxxxxxYoQ2G from_address = noreply@xxxx.com from_name = Hawkeye ;cert_file = ;key_file = ;skip_verify = false ;from_address = admin@grafana.localhost ;from_name = Grafana # EHLO identity in SMTP dialog (defaults to instance_name) ;ehlo_identity = dashboard.example.com [emails] ;welcome_email_on_sign_up = false #################################### Logging ########################## [log] # Either “console”, “file”, “syslog”. Default is console and file # Use space to separate multiple modes, e.g. “console file” ;mode = console file # Either “debug”, “info”, “warn”, “error”, “critical”, default is “info” ;level = info # optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug ;filters = # For “console” mode only [log.console] ;level = # log line format, valid options are text, console and json ;format = console # For “file” mode only [log.file] ;level = # log line format, valid options are text, console and json ;format = text # This enables automated log rotate(switch of following options), default is true ;log_rotate = true # Max line number of single file, default is 1000000 ;max_lines = 1000000 # Max size shift of single file, default is 28 means 1 << 28, 256MB ;max_size_shift = 28 # Segment log daily, default is true ;daily_rotate = true # Expired days of log file(delete after max days), default is 7 ;max_days = 7 [log.syslog] ;level = # log line format, valid options are text, console and json ;format = text # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used. ;network = ;address = # Syslog facility. user, daemon and local0 through local7 are valid. ;facility = # Syslog tag. By default, the process’ argv[0] is used. ;tag = #################################### Alerting ############################ [alerting] # Disable alerting engine & UI features ;enabled = true # Makes it possible to turn off alert rule execution but alerting UI is visible ;execute_alerts = true # Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state) ;error_or_timeout = alerting # Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok) ;nodata_or_nullvalues = no_data # Alert notifications can include images, but rendering many images at the same time can overload the server # This limit will protect the server from render overloading and make sure notifications are sent out quickly ;concurrent_render_limit = 5 #################################### Explore ############################# [explore] # Enable the Explore section ;enabled = false #################################### Internal Grafana Metrics ########################## # Metrics available at HTTP API Url /metrics [metrics] # Disable / Enable internal metrics ;enabled = true # Publish interval ;interval_seconds = 10 # Send internal metrics to Graphite [metrics.graphite] # Enable by setting the address setting (ex localhost:2003) ;address = ;prefix = prod.grafana.%(instance_name)s. #################################### Distributed tracing ############ [tracing.jaeger] # Enable by setting the address sending traces to jaeger (ex localhost:6831) ;address = localhost:6831 # Tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2) ;always_included_tag = tag1:value1 # Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote ;sampler_type = const # jaeger samplerconfig param # for “const” sampler, 0 or 1 for always false/true respectively # for “probabilistic” sampler, a probability between 0 and 1 # for “rateLimiting” sampler, the number of spans per second # for “remote” sampler, param is the same as for “probabilistic” # and indicates the initial sampling rate before the actual one # is received from the mothership ;sampler_param = 1 #################################### Grafana.com integration ########################## # Url used to import dashboards directly from Grafana.com [grafana_com] ;url = https://grafana.com #################################### External image storage ########################## [external_image_storage] # Used for uploading images to public servers so they can be included in slack/email messages. # you can choose between (s3, webdav, gcs, azure_blob, local) ;provider = [external_image_storage.s3] ;bucket = ;region = ;path = ;access_key = ;secret_key = [external_image_storage.webdav] ;url = ;public_url = ;username = ;password = [external_image_storage.gcs] ;key_file = ;bucket = ;path = [external_image_storage.azure_blob] ;account_name = ;account_key = ;container_name = [external_image_storage.local] # does not require any configuration [rendering] # Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer ;server_url = ;callback_url =—以上凡是我打 xxx都是经过修改的,隐藏了本司的一些重要信息。大家需要根据实际情况,自行配置修改。。如果你不需要ldap 认证,这可以删除configmap当中的 ldap.toml 并且在grafana.ini 当中 将true改为false。#################################### Auth LDAP ########################## [auth.ldap] enabled = true ;config_file = /etc/grafana/ldap.toml ;allow_sign_up = true deployment.yaml 如下:apiVersion: apps/v1kind: Deploymentmetadata: name: hawkeye-grafana namespace: sgt labels: app: hawkeye-grafanaspec: replicas: 1 selector: matchLabels: app: hawkeye-grafana template: metadata: labels: app: hawkeye-grafana spec: containers: - image: grafana/grafana:6.0.0 name: grafana imagePullPolicy: IfNotPresent # env: env: - name: GF_PATHS_PROVISIONING value: /var/lib/grafana/provisioning resources: # keep request = limit to keep this container in guaranteed class limits: cpu: 100m memory: 100Mi requests: cpu: 100m memory: 100Mi readinessProbe: httpGet: path: /login port: 3000 # initialDelaySeconds: 30 # timeoutSeconds: 1 volumeMounts: - name: grafana-persistent-storage mountPath: /var/lib/grafana/ - name: config mountPath: /etc/grafana/ initContainers: - name: “init-chown-data” image: “busybox:latest” imagePullPolicy: “IfNotPresent” command: [“chown”, “-R”, “472:472”, “/var/lib/grafana/”] volumeMounts: - name: grafana-persistent-storage mountPath: /var/lib/grafana/ subPath: "" volumes: - name: config configMap: name: hawkeye-grafana-cm - name: grafana-persistent-storage persistentVolumeClaim: claimName: hawkeye-grafana-claim—注意增加了initContainers,主要是解决挂载的写权限的问题。service.yaml 如下:apiVersion: v1kind: Servicemetadata: annotations: service.beta.kubernetes.io/aws-load-balancer-type: nlb labels: app: hawkeye-grafana name: hawkeye-grafana namespace: sgtspec: type: LoadBalancer ports: - name: http port: 80 protocol: TCP targetPort: 3000 selector: app: hawkeye-grafana—pvc.yaml 如下:kind: PersistentVolumeClaimapiVersion: v1metadata: name: hawkeye-grafana-claim namespace: sgtspec: accessModes: - ReadWriteOnce resources: requests: storage: 30Gi执行成功以后,访问成功,通过admin/admin 登录。可以看出,左侧新增了Explore图标。总结grafana 首先会从/usr/share/grafana/conf/defaults.ini读取配置文件,然后再读取/etc/grafana/grafana.ini读取,同一参数的配置,那么/etc/grafana/grafana.ini 会覆盖/usr/share/grafana/conf/defaults.ini中配置。而命令行配置的参数会覆盖/etc/grafana/grafana.ini中的同一参数,最后环境变量中同一配置,又会覆盖命令行中的。下面是默认的一些环境变量:GF_PATHS_CONFIG /etc/grafana/grafana.iniGF_PATHS_DATA /var/lib/grafanaGF_PATHS_HOME /usr/share/grafanaGF_PATHS_LOGS /var/log/grafanaGF_PATHS_PLUGINS /var/lib/grafana/pluginsGF_PATHS_PROVISIONING /etc/grafana/provisioning ...

February 28, 2019 · 12 min · jiezi

今年的LC3大会没了?

2019年6月24-26日,由Linux基金会在2017和2018年主办的LinuxCon + ContainerCon + CloudOpen大会(简称LC3)将正式更名为Open Source Summit(简称OSS),并与CNCF主办的KubeCon + CloudNativeCon大会合体,在上海世博中心盛大召开。2018年6月27日,由Linux基金会主办的LC3大会又一次在北京国家会议中心完美收官。本次盛会聚集了来自36个国家382个组织的2024名与会者。其中,86%的与会者来自中国各地的公司和组织,包括开发人员、工程师、架构师、技术管理人员在内的技术类参会者更是占到了62%的高席。在历时三天(2018年6月25-27日)的时间里,100多家国内外开源技术领先企业的300多位技术大咖齐聚一堂,通过主题演讲、全方位互动、展览展示等多种形式,与全球的开发人员、运营专家、企业合规人员、法律界相关人士等不同行业、不同层级的观众,再次分享了一场开源盛宴。有150场精心策划的分享,内容涵盖云原生应用程序、云基础设施、Linux系统、区块链、AI、物联网和M2M、开源领导力和社区、人工智能和深度学习、区块链和网络等不同领域,让与会者深入了解了开源领域的最新趋势和主题。此外,本届盛会与2017年相比,提交提案的人数增加了37%;大会盛况被中外50多家媒体争相报道,550余篇次的文章曾与读者见面;更有91%的受访者认为本届会议内容既有信息性又有实用性…其实,早在2017年6月的时候,也是在北京国家会议中心,LC3在中国的首秀就已经相当成功了。当时,有数据表明,首秀中国的LC3大会,到现场参观的观众就已经达到二千人之多。2017年的LC3大会,不仅汇聚了开源界的世界级顶尖专家莅临现场为参会观众解惑,更是邀请到了Linux之父 - Linus Torvalds先生,以及Linux基金会执行董事 - Jim Zemlin先生,到现场为LC3在中国的首秀助威。在大会上,中国开源软件推进联盟主席 - 陆首群教授,获得了由Jim Zemlin先生亲自为其授予的“终身成就奖”。众多国内外知名企业,如华为、阿里巴巴、Intel、腾讯、微软、思科等也悉数亮相会场,并将开源成果对企业运用的意义做了深度分享。在本次大会上,当Jim Zemlin先生郑重的宣布Linux基金会培训认证项目在中国落地的消息的时候,现场响起了热烈的掌声,这不仅是Linux基金会对中国开源界的重视,对于广大中国技术人员来说,更是切实的福利,这也意味着我国的技术人员将有更多的机会接受到更多更专业的国际技术培训。在2018年北京的LC3大会期间,Linux基金会公布了2019年LinuxCon+ ContainerCon + CloudOpen大会将正式升级为Open Source Summit,加入Linux基金会在北美、欧洲和日本举办的具有行业领导意义的开源峰会序列,并与CNCF主办的KubeCon + CloudNativeCon大会合体,把两场盛会融合成一款更加精品的活动,为观众带来全方位的技术分享与开源盛宴。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票!

February 28, 2019 · 1 min · jiezi

我们如何在Linkerd 2.2里设计重试

作者:Alex Leong重试是处理分布式系统中的部分或瞬态故障的基本机制。但重试也可能是危险的,如果做得不好,他们可以迅速将一个小错误升级为系统范围的中断。在这篇文章中,我们描述了我们如何在Linkerd 2.2里设计重试,使Linkerd能够在最小化风险的同时,自动提高系统可靠性。将路由标记为可重试在Linkerd 2.2里,我们引入了重试,就是Linkerd能够自动重试失败的请求。这使Linkerd能够自动处理服务中的部分或瞬态故障,而无需应用程序知道:如果请求失败,Linkerd可以再次尝试!结合Linkerd的请求级负载平衡,这允许Linkerd处理各个pod的故障。在Linkerd里,您将重试指定为服务配置文件的一部分(在之前的博客文章中介绍)。将路由标记为可重试就像添加isRetryable一样简单:设定true到相应的服务配置文件条目:- name: HEAD /authors/{id}.json condition: method: HEAD pathRegex: /authors/[^/]\.json isRetryable: true当然,在向路由添加重试行为之前,应该确保路由是幂等的(idempotent)。换句话说,对具有相同参数的相同路由的多次调用将没有不良影响。这很重要,因为重试(根据定义!)可能导致将同一请求的多个副本发送到服务。如果请求做了非幂等的(non-idempotent)事情,例如从您的银行帐户中减去一美元,您可能不希望它自动重试。启用后,重试有两个重要参数:预算(budget)和超时(timeout)。让我们依次考虑这两个方面。使用重试预算将路由标记为可重试后,Linkerd允许您为服务配置重试预算。Linkerd附带了合理的默认值,但如果您想自定义预算,可以在服务配置文件中进行设置:retryBudget: # The retryRatio is the maximum ratio of retries requests to original # requests. A retryRatio of 0.2 means that retries may add at most an # additional 20% to the request load. retryRatio: 0.2 # This is an allowance of retries per second in addition to those allowed # by the retryRatio. This allows retries to be performed, when the request # rate is very low. minRetriesPerSecond: 10 # This duration indicates for how long requests should be considered for the # purposes of calculating the retryRatio. A higher value considers a larger # window and therefore allows burstier retries. ttl: 10sLinkerd使用重试预算,较使用最大重试次数配置重试的常规做法,是更好替代方法。我们花一点时间来理解为什么。为什么预算而不是最大重试次数?首先,一些背景。配置重试的最常用方法,是指定在放弃之前执行的最大重试次数。对于使用网络浏览器的任何人来说,这是一个熟悉的想法:您尝试加载网页,如果没有加载,则再试一次。如果仍然无法加载,则第三次尝试。最后您放弃了。不幸的是,以这种方式配置重试至少有两个问题:选择最大重试次数是猜谜游戏。您需要选择一个足够高的数字,以便在出现某种故障时发挥作用,但不要太高,以至于当系统真正失败时会在系统上产生额外负载。在实践中,您通常会从帽子中选择最大重试次数(例如3),并希望获得最佳效果。以这种方式配置的系统易受重试风暴的影响。当一个服务开始出现大于正常的故障率时,重试风暴开始。这会导致其客户端重试这些失败的请求。重试带来的额外负载,会导致服务进一步减速,并使更多请求失败,从而触发更多重试。如果每个客户端配置为最多重试3次,则可以将发送的请求数量翻两番!更糟糕的是,如果任何客户端的客户端配置了重试,则重试次数会成倍增加,并且可以将少量错误转化为自我造成的拒绝服务攻击。为了避免这些问题,Linkerd使用重试预算。Linkerd不是为每个请求指定固定的最大重试次数,而是跟踪常规请求和重试之间的比率,并将此数字保持在限制之下。例如,您可以指定要重试最多添加20%的请求。然后,Linkerd将尽可能多地重试,同时保持该比率。因此,使用重试预算可以明确在提高成功率和额外负载之间进行权衡。您的重试预算正是您的系统愿意从重试中接受的额外负载。(最后,Linkerd的重试预算还包括允许的最小重试次数,这将是唯一允许的,与比率无关。这使得Linkerd可以在非常低的流量系统中重试。)设置每个请求的超时除了预算之外,重试还按每个请求的超时参数。超时可确保始终失败的请求最终会返回响应,即使该响应失败也是如此。超时时,Linkerd将取消请求并返回HTTP 504响应。与重试预算类似,重试超时具有可在服务配置文件中覆盖的合理默认值:- name: HEAD /authors/{id}.json condition: method: HEAD pathRegex: /authors/[^/]\.json timeout: 50ms谁管有重试行为?客户端还是服务器?您可能已经注意到上面的配置片段中的有趣内容。在“传统”重试系统(例如Web浏览器)中,是在客户端上配置重试行为,毕竟,这是重试实际发生的地方。但是在上面的服务配置文件中,我们将在服务器端指定重试政策。能够将政策附加到服务器端,但客户端必须遵守该政策,这是Linkerd服务配置文件方法的基本优势之一。重试配置在逻辑上属于服务级别(“这是您应该和我说话的方式”)。由于Linkerd控制客户端和服务器行为,我们可以正确的方式执行此操作:服务配置文件允许服务准确发布“这是我希望您与我交谈的方式”,通过Linkerd的所有流量,无论来源如何,会尊重这种行为。太酷了!把它们放在一起我们已经展示了如何通过组合超时、预算和可重试性来配置Linkerd的重试行为。现在让我们将它们放在一起进行简短的演示。如果您有一个终端窗口和一个Kubernetes集群,您可以在家里跟随。我们首先安装Linkerd和我们的样本书应用程序:$ linkerd install | kubectl apply -f -$ curl https://run.linkerd.io/bookapp.yml | linkerd inject - | kubectl apply -f -$ linkerd check关于这个应用程序,我们可以注意到的一件事是,从书籍服务到作者服务的请求的成功率非常低:$ linkerd routes deploy/books –to svc/authorsROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99[DEFAULT] authors 54.24% 3.9rps 5ms 14ms 19ms为了更好地了解这里发生了什么,让我们为作者服务添加一个服务配置文件,从Swagger定义生成:$ curl https://run.linkerd.io/booksapp/authors.swagger | linkerd profile –open-api - authors | kubectl apply -f -$ linkerd routes deploy/books –to svc/authorsROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99DELETE /authors/{id}.json authors 0.00% 0.0rps 0ms 0ms 0msGET /authors.json authors 0.00% 0.0rps 0ms 0ms 0msGET /authors/{id}.json authors 0.00% 0.0rps 0ms 0ms 0msHEAD /authors/{id}.json authors 50.85% 3.9rps 5ms 10ms 17msPOST /authors.json authors 0.00% 0.0rps 0ms 0ms 0ms[DEFAULT] authors 0.00% 0.0rps 0ms 0ms 0ms有一件事是清楚的,从书籍到作者的所有请求都是针对HEAD /authors/{id}.json路线,这些请求在大约50%的时间内失败。为了纠正这个问题,让我们编辑作者服务配置文件,并使这些请求可以重试:$ kubectl edit sp/authors.default.svc.cluster.local[…] - condition: method: HEAD pathRegex: /authors/[^/]\.json name: HEAD /authors/{id}.json isRetryable: true ### ADD THIS LINE ###在编辑服务配置文件后,我们看到成功率几乎立即有所改善:$ linkerd routes deploy/books –to svc/authors -o wideROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99DELETE /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msGET /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msGET /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msHEAD /authors/{id}.json authors 100.00% 2.8rps 58.45% 4.7rps 7ms 25ms 37msPOST /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms[DEFAULT] authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms成功率看起来很好,但p95和p99延迟有所增加。这是可以预料到的,因为重试需要时间。但是,我们可以通过设置超时,Linkerd 2.x的另一个新功能,在我们愿意等待的最长持续时间来限制此操作。出于本演示的目的,我将设置25ms的超时。您的结果将根据系统的特性而有所不同。$ kubectl edit sp/authors.default.svc.cluster.local[…] - condition: method: HEAD pathRegex: /authors/[^/]\.json isRetryable: true name: HEAD /authors/{id}.json timeout: 25ms ### ADD THIS LINE ###我们现在看到成功率略有下降,因为有些请求超时,但尾部延迟已大大减少:$ linkerd routes deploy/books –to svc/authors -o wideROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99DELETE /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msGET /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msGET /authors/{id}.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0msHEAD /authors/{id}.json authors 97.73% 2.9rps 49.71% 5.8rps 9ms 25ms 29msPOST /authors.json authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms[DEFAULT] authors 0.00% 0.0rps 0.00% 0.0rps 0ms 0ms 0ms请注意,由于直方图分段工件,p99延迟似乎大于我们的25ms超时。总结在这篇文章中,我们描述了Linkerd如何以最小化系统风险的方式自动重试请求。我们描述了为什么在服务器,而不是客户端级别,指定了重试行为,我们向您介绍了如何在演示应用程序中部署服务的重试和超时功能。重试是Linkerd可靠性路线图中的一大进步。服务配置文件、重试和诊断的交集是Linkerd特别令人兴奋的领域,您可以期待未来版本中更酷的功能。敬请期待!喜欢这篇文章?Linkerd是一个社区项目,由CNCF托管。如果您有功能请求、问题或评论,我们很乐意让您加入我们快速发展的社区!Linkerd的仓库在GitHub上,我们在Slack、Twitter和邮件列表上拥有一个蓬勃发展的社区。快来加入吧!KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国 ...

February 27, 2019 · 3 min · jiezi

Kubernetes安全三步谈:如何通过RBAC和强身份验证确保外部安全

毋庸置疑,K8s已经成为云容器编排系统的标准,但是,如果缺乏K8s环境相关的安全问题认识的话,会致使各种组件暴露在网络集群内外的攻击之下。本文将介绍通过强身份验证如何确保企业的K8s集群免受外部攻击。这是关于Kubernetes安全性的三篇系列文章中的第一篇,在本系列文章中,我们将依次介绍如何确保企业的Kubernetes集群免受外部攻击、内部攻击,以及如何处理资源消耗或noisy neighbors问题。毋庸置疑,Kubernetes已经成为云容器编排系统的标准,据Cloud Native Computing Foundation(CNCF)的定义,它提供了一个“自动化部署、扩展以及跨主机集群操作应用程序容器的平台”。但是,如果缺乏Kubernetes环境相关的安全问题认识的话,会致使各种组件暴露在网络集群内外的攻击之下。锁定API服务器,KubeletsKubernetes环境中有多种可由外部访问的组件,包括应用程序编程接口(API)服务器、kubelet以及数据存储。如果没有正确锁定和保护它们的话,这些组件有可能会造成数据泄漏和系统损害。Kubernetes为开发、运维和安全团队提供了一个API结构,可用于和应用程序和Kubernetes平台交互。Kubelet是一个在节点上运行并且读取容器清单的服务,它确保定义了的容器已经启动并运行。Kubernetes利用etcd分布式键值存储来保存和复制Kubernetes在整个集群中使用的数据。基本上,最经常受到攻击的Kubernetes系统是那些根本没有设置访问控制的系统。Goins指出,Kubernetes易于部署,在默认情况下并没有内置太多确保安全性的东西。例如,直到2017年年中,容器编排系统才开始具有RBAC(基于角色的访问控制)功能。Kubernetes 1.8版本的亮点之一是RBAC(基于角色的访问控制),这是一种用于管理Kubernetes资源周围权限的授权机制。RBAC允许配置灵活的授权策略,可以在不需要重启集群的情况下进行更新。“在很多Kubernetes部署中,一旦出现compromise,用户可以使用root权限安装和运行他们想要的软件。”Goins说,“黑客和网络犯罪分子希望进入一个系统,升级他们的权限,接着转向其他系统,开始收集信用卡和个人身份识别数据等信息。”2018年12月在Kubernetes爆出的首个安全漏洞——特权升级漏洞(CVE-2018-1002105),当时是由Rancher Labs联合创始人及首席架构师Darren Shepherd发现的。该漏洞演示了用户如何通过Kubernetes API服务器建立和后端服务器的连接。建立连接之后,攻击者可以通过网络连接直接向后端集群服务(如kubelets)发送任意的请求。该漏洞让任何用户在任何计算节点上都拥有完整的管理员权限。后来发布了专门修复受支持的Kubernetes版本的补丁,在1.10.11,1.11.5和1.12.3中都提供了这样的补丁。企业该如何保护K8s集群免受外部攻击Goins建议,Kubernetes用户需要做的第一件事是完全关闭外部API访问,或者将该功能封装在某种强身份验证中设置保护。为了减轻外部攻击的威胁,信息技术/安全管理员必须确保只有必要的Kubernetes服务能对外暴露。此外,他们必须设置身份验证并且给所有公开的服务配置正确的网络安全策略。Handy Tecchnologies的Alexander Uricoli在一篇博客中写道:“除非你在kubelet上指定了一些标志(flags),否则它在默认操作模式下,是会接受未经身份验证的API请求的。”在这篇博客中Uricoli分析了黑客是如何入侵同时个人服务器上的Kubernetes集群的:https://medium.com/handy-tech…Uricoli说:“看来有人找到了一种方法,可以在一个正在运行的容器上放置一些加密挖掘软件,然后执行这个过程。”Kubernetes API服务器虽然面向internet公开,但是受到证书身份验证的保护。结果,同事的服务器公开了kubelet端口(tcp 10250和tcp 10255)。Uricoli指出,尽管问题已显而易见,这样的入侵仍然应该引起大家对Kubernetes的部署的一些问题的关注。如果你的用户可以通过网络节点来访问你的节点,那么kubelet API就是一个通往集群的API后门,它功能齐全且未经身份验证。如果用户已经花了很多心思在webhook、RBAC或其他方法启用身份验证和授权上,那么他们也同样应该将kubelet好好地锁定上。互联网安全中心(CIS)建议用户为kubelet连接部署HTTPS。CIS在关于为Kubernetes 1.11建立安全配置的指南中写道,“从API服务器到kubelets的连接可能带有机密和密钥等敏感数据。因此,在API服务器和kubeletes之间的任何通信中使用在途加密(in-transit)是非常重要的。”Kubernetes用户应该禁用对API服务器的匿名请求。启用时,没有被其他配置好的身份验证方法拒绝的请求将被视为匿名请求,然后API服务器会处理这些请求。根据CIS的说法,Kubernetes的用户应该依靠身份验证来授权访问,并切拒绝匿名请求,而组织应该根据需要实现可控制的访问。Goins指出,加强内部集群用户防御的安全控制——RBAC、隔离以及权限限制——对于保护Kubernetes免受外部攻击同等重要。他说:“如果有人使用任何内部用户的账户从外部访问集群,他们会立刻获得完全访问权限。”所以,这并不是说你需要内部控制来抵御外部的攻击。而是说如果你没有这些措施,当受到攻击的时候你就遭大殃了。结 语Rancher Kubernetes平台拥有着超过一亿次下载量,我们深知安全问题对于用户而言的重要性,更遑论那些通过Rancher平台在生产环境中运行Docker及Kubernetes的数千万用户。2018年年底Kubernetes被爆出的首个严重安全漏洞CVE-2018-1002105,就是由Rancher Labs联合创始人及首席架构师Darren Shepherd发现的。2019年1月Kubernetes被爆出仪表盘和外部IP代理安全漏洞时,Rancher Labs也是业界第一时间向用户响应,确保了所有Rancher 2.x和1.6.x的用户都完全不被漏洞影响。未来Rancher将会向用户分享更多容器及Kubernetes安全技巧。在下一篇博客中,我们将分享三种保护Kubernetes不受内部攻击的方法:基于角色的访问、Kubernetes特性(如逻辑隔离,即命名空间)和Rancher资源(如Project)。记得保持关注~

February 27, 2019 · 1 min · jiezi

使用Logtail采集Kubernetes上挂载的NAS日志

采集k8s挂载Nas后的日志该文档主要介绍使用logtail以两种不同的方式进行k8s挂载Nas后的日志采集。两种采集方式的实现原理是一样的,都是通过将Logtail和业务容器挂载到相同的NAS上,使Logtail和业务容器的日志数据共享,以此实现日志采集。下面是两种采集方式的各自特点:1. SideCar模式。比较灵活、适合水平扩容,适用于数据量较大的场景;2. 单独部署Logtail的Deployment。资源消耗比较低、但灵活性以及伸缩性不强,适用于整体集群数据量较少的场景(建议整体日志量不超过每秒10M)。1. Sidecar NAS采集方式通过 链接 使用PV&PVC的方式配置挂载Nas的nas-pvc步骤一 创建pv步骤二 创建pvc步骤三 根据下面的yaml模板创建含有logtail的Pod,进行单个Pod的内部采集sideCar模式实验yaml内容:apiVersion: batch/v1kind: Jobmetadata: name: nginx-log-sidecar1-demospec: template: metadata: name: nginx-log-sidecar-demo spec: # volumes配置 volumes: - name: nginx-log persistentVolumeClaim: claimName: nas-pvc containers: # 主容器配置 - name: nginx-log-demo image: registry.cn-hangzhou.aliyuncs.com/log-service/docker-log-test:latest command: ["/bin/mock_log"] args: ["–log-type=nginx", “–stdout=false”, “–stderr=true”, “–path=/var/log/nginx/access.log”, “–total-count=1000000000”, “–logs-per-sec=100”] volumeMounts: - name: nginx-log mountPath: /var/log/nginx # Logtail的Sidecar容器配置 - name: logtail image: registry.cn-hangzhou.aliyuncs.com/log-service/logtail:latest env: # user id - name: “ALIYUN_LOGTAIL_USER_ID” value: “${your_aliyun_user_id}” # user defined id - name: “ALIYUN_LOGTAIL_USER_DEFINED_ID” value: “${your_machine_group_user_defined_id}” # config file path in logtail’s container - name: “ALIYUN_LOGTAIL_CONFIG” value: “/etc/ilogtail/conf/${your_region_config}/ilogtail_config.json” # env tags config - name: “ALIYUN_LOG_ENV_TAGS” value: “pod_name|pod_ip|namespace|node_name|node_ip” - name: “pod_name” valueFrom: fieldRef: fieldPath: metadata.name - name: “pod_ip” valueFrom: fieldRef: fieldPath: status.podIP - name: “namespace” valueFrom: fieldRef: fieldPath: metadata.namespace - name: “node_name” valueFrom: fieldRef: fieldPath: spec.nodeName - name: “node_ip” valueFrom: fieldRef: fieldPath: status.hostIP # 和主容器共享volume volumeMounts: - name: nginx-log mountPath: /var/log/nginx # 健康检查 livenessProbe: exec: command: - /etc/init.d/ilogtaild - status initialDelaySeconds: 30 periodSeconds: 30 restartPolicy: “Never"SLS控制台采集配置设置如下图:日志路径与被采集容器的日志所在路径一致注意:由于NAS路径已经挂载到了Logtail容器上,所以不需要打开docker文件的按钮采集上来的系统默认字段含义:source: pod容器内部IP__tag__:hostname: pod名称__tag__:path: 日志路径__tag__:receive_time: 采集时间__tag__:user_defined_id: 用户自定义标识__tag__:namespace: pod所属namaspace__tag__:node_ip: pod所在Node的IP地址__tag__:node_name: pod所属Node的name__tag__:pod_ip: pod容器内部IP__tag__:pod_name: pod名称用户参数:2. 一个Logtail采集所有POD的NAS数据注意项:副本数spec.replicas只能为1,不能更多,多了会重复采集。首先,创建一个logtail的deployment,以下是本次使用的模板:apiVersion: apps/v1kind: Deploymentmetadata: name: logtail-deployment namespace: kube-system labels: k8s-app: nas-logtail-collecterspec: replicas: 1 selector: matchLabels: k8s-app : nas-logtail-collecter template: metadata: name: logtail-deployment labels: k8s-app : nas-logtail-collecter spec: containers: # Logtail的配置 - name: logtail image: registry.cn-hangzhou.aliyuncs.com/log-service/logtail:latest env: # aliuid - name: “ALIYUN_LOGTAIL_USER_ID” value: “${your_aliyun_user_id}” # user defined id - name: “ALIYUN_LOGTAIL_USER_DEFINED_ID” value: “${your_machine_group_user_defined_id}” # config file path in logtail’s container - name: “ALIYUN_LOGTAIL_CONFIG” value: “/etc/ilogtail/conf/${your_region_config}/ilogtail_config.json” volumeMounts: - name: nginx-log mountPath: /var/log/nginx # volumes配置 volumes: - name: nginx-log persistentVolumeClaim: claimName: pvc-test-nginx__注意:__这里的 claimName: pvc-test-nginx 以及mountPath: /var/log/nginx 是将logtail的/var/log/nginx挂载了Nas下的/nginx文件夹相关参数设置请参考方案1中的表格说明logtail运行成功之后,可以在SLS控制台根据模板中的ALIYUN_LOGTAIL_USER_DEFINED_ID创建对应的机器组,请参考方案1中的表格说明。这里新建2个Pod来测试采集是否成功,其中一个POD的模板为:apiVersion: v1kind: Podmetadata: name: “test-nginx-2"spec: containers: - name: “nginx-log-demo” image: “registry.cn-hangzhou.aliyuncs.com/log-service/docker-log-test:latest” command: ["/bin/mock_log”] args: [”–log-type=nginx", “–stdout=false”, “–stderr=true”, “–path=/var/log/nginx/access.log”, “–total-count=1000000000”, “–logs-per-sec=100”] volumeMounts: - name: “nas2” mountPath: “/var/log/nginx” volumes: - name: “nas2” flexVolume: driver: “alicloud/nas” options: server: “Nas挂载地址” path: “/nginx/test2” vers: “4.0"另一个Pod将 /var/log/nginx 挂载在了 /nginx/test1 目录下;结合logtail的挂载情况,现在两个Pod分别挂载在 /nginx/test1 和 /nginx/test2,而logtail挂载在了 /nginx 下。最后配置logtail的采集配置因为logtail也挂载了相同的Nas,所以logtail只需要采集自身文件夹下的日志就可以了,这里的是否为docker文件选项关闭。注意:由于NAS路径已经挂载到了Logtail容器上,所以不需要打开docker文件的按钮本文作者:元乙阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 27, 2019 · 2 min · jiezi

Spark in action on Kubernetes - Playground搭建与架构浅析

前言Spark是非常流行的大数据处理引擎,数据科学家们使用Spark以及相关生态的大数据套件完成了大量又丰富场景的数据分析与挖掘。Spark目前已经逐渐成为了业界在数据处理领域的行业标准。但是Spark本身的设计更偏向使用静态的资源管理,虽然Spark也支持了类似Yarn等动态的资源管理器,但是这些资源管理并不是面向动态的云基础设施而设计的,在速度、成本、效率等领域缺乏解决方案。随着Kubernetes的快速发展,数据科学家们开始考虑是否可以用Kubernetes的弹性与面向云原生等特点与Spark进行结合。在Spark 2.3中,Resource Manager中添加了Kubernetes原生的支持,而本系列我们会给大家介绍如何用更Kubernetes的方式在集群中使用Spark进行数据分析。本系列不需要开发者有丰富的Spark使用经验,对着系列的逐渐深入,会穿插讲解使用到的Spark特性。搭建Playground很多的开发者在接触Hadoop的时候,被安装流程的复杂度打消了很多的积极性。为了降低学习的门槛,本系列会通过spark-on-k8s-operator作为Playground,简化大家的安装流程。spark-on-k8s-operator顾名思义是为了简化Spark操作而开发的operator,如果对operator不是很了解的开发者,可以先自行搜索了解下,理解operator能做什么可以快速帮你掌握spark-on-k8s-operator的要领。在讲解内部原理前,我们先将环境搭建起来,通过一个简单的demo,跑通整个的运行时环境。1. 安装spark-on-k8s-operator官方的文档是通过Helm Chart进行安装的,由于很多开发者的环境无法连通google的repo,因此此处我们通过标准的yaml进行安装。## 下载repogit clone git@github.com:AliyunContainerService/spark-on-k8s-operator.git## 安装crdkubectl apply -f manifest/spark-operator-crds.yaml ## 安装operator的服务账号与授权策略kubectl apply -f manifest/spark-operator-rbac.yaml ## 安装spark任务的服务账号与授权策略kubectl apply -f manifest/spark-rbac.yaml ## 安装spark-on-k8s-operator kubectl apply -f manifest/spark-operator.yaml 验证安装结果此时在spark-operator的命名空间下的无状态应用下,可以看到一个运行中的sparkoperator,表名此时组件已经安装成功,接下来我们运行一个demo应用来验证组件是否可以正常工作。2. Demo验证学习Spark的时候,我们运行的第一个任务是官方文档中介绍的圆周率运行的例子。今天我们换一种方式,通过Kubernetes的方式再运行一次。## 下发spark-pi任务kubectl apply -f examples/spark-pi.yaml 任务下发成功后,可以通过命令行观察任务的状态。## 查询任务kubectl describe sparkapplication spark-pi## 任务结果 Name: spark-piNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:“sparkoperator.k8s.io/v1alpha1”,“kind”:“SparkApplication”,“metadata”:{“annotations”:{},“name”:“spark-pi”,“namespace”:“defaul…API Version: sparkoperator.k8s.io/v1alpha1Kind: SparkApplicationMetadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7bSpec: Deps: Driver: Core Limit: 200m Cores: 0.1 Labels: Version: 2.4.0 Memory: 512m Service Account: spark Volume Mounts: Mount Path: /tmp Name: test-volume Executor: Cores: 1 Instances: 1 Labels: Version: 2.4.0 Memory: 512m Volume Mounts: Mount Path: /tmp Name: test-volume Image: gcr.io/spark-operator/spark:v2.4.0 Image Pull Policy: Always Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar Main Class: org.apache.spark.examples.SparkPi Mode: cluster Restart Policy: Type: Never Type: Scala Volumes: Host Path: Path: /tmp Type: Directory Name: test-volumeStatus: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: Spark - Pi - 1547981232122 - Exec - 1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56ZEvents: Type Reason Age From Message —- —— —- —- ——- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed此时我们发现任务已经执行成功,查看这个Pod的日志,我们可以到计算最终的结果为Pi is roughly 3.1470557352786765。至此,在Kubernetes上,已经跑通了第一个Job,接下来我们要来详解一下刚才这一波操作到底都做了些什么。Spark Operator的基础架构浅析这张图是Spark Operator的流程图,在上面的操作中,第一个步骤里面,实际上是将图中的中心位置蓝色的Spark Operator安装到集群中,Spark Opeartor本身即是是一个CRD的Controller也是一个Mutating Admission Webhook的Controller。当我们下发spark-pi模板的时候,会转换为一个名叫SparkApplication的CRD对象,然后Spark Operator会监听Apiserver,并将SparkApplication对象进行解析,变成spark-submit的命令并进行提交,提交后会生成Driver Pod,用简单的方式理解,Driver Pod就是一个封装了Spark Jar的镜像。如果是本地任务,就直接在Driver Pod中执行;如果是集群任务,就会通过Driver Pod再生成Exector Pod进行执行。当任务结束后,可以通过Driver Pod进行运行日志的查看。此外在任务的执行中,Spark Operator还会动态attach一个Spark UI到Driver Pod上,希望查看任务状态的开发者,可以通过这个UI页面进行任务状态的查看。最后在本文中,我们讨论了Spark Operator的设计初衷,如何快速搭建一个Spark Operator的Playground以及Spark Operator的基本架构与流程。在下一篇文章中,我们会深入到Spark Operator的内部,为大家讲解其内部的实现原理以及如何与Spark更无缝的集成。本文作者:莫源 阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 26, 2019 · 2 min · jiezi

CNCF推出云原生网络功能(CNF)Testbed

开源计划验证了在Kubernetes上运行ONAP网络功能对电信运营商的好处巴塞罗那,2019年2月25日 - 移动世界大会 - 支持Kubernetes®和Prometheus™等开源技术的的CNCF®(云原生计算基金会®)今天宣布与LF Networking(LFN)合作的开源云原生网络功能(CNF)Testbed。在巴塞罗那举行的移动世界大会上,CNCF正在演示相同的网络代码,在OpenStack上以虚拟网络功能(VNF)方式运行,以及在Kubernetes上以CNF方式运行,通过避免虚拟化开销来展示性能改进。“CNF正在成为未来的网络架构,其原因与容器和Kubernetes成为企业计算的标准平台的原因相同。”CNCF执行总监Dan Kohn说。“我们很高兴继续与LF Networking合作,为电信公司及其供应商提供一种在VNF和CNF之间进行可复制比较的方法。”CNF Testbed使组织能够可靠地测试ONAP或其自己的网络代码的网络功能,以VNF和CNF的方式,在相同底层硬件上比较运行在Kubernetes和OpenStack之间的性能和容错性。随着电信架构从VNF演变为CNF,其优势包括通过改进的打包节省成本,提高开发速度,以及单个CNF、机器甚至数据中心的故障恢复能力。ONAP作为LF Networking的一部分,为实时、政策驱动的物理和虚拟网络功能的编排和自动化提供了全面的平台。在去年宣布了ONAP现在是cncf.ci项目涵盖的一部分,CNCF运行该项目以在裸机上运行的K8集成、测试和部署CNCF和LF项目。CNF Testbed使用ONAP虚拟客户端设备(vCPE)用例中的几个开源VNF,并将代码重新打包为CNF容器。“很高兴看到ONAP和Kubernetes这两个增长最快的Linux基金会项目的协作,作为支持下一代架构的网络和云平台。”Linux基金会网络、边缘和物联网总经理Arpit Joshipura表示。“我们很高兴能够协助CNF Testbed展示行业从VNF转向CNF的道路。”CNF Testbed利用社区基础设施实验室(Community Infrastructure Lab),该实验室利用裸机托管公司Packet慷慨提供的信用额度。Testbed继续关注持续集成(CI)和可复制性,这些都是Kubernetes发展的标志。Kubernetes项目每个工作日运行超过10,000个CI工作,这是通过去年从Google向CNCF捐赠的900万美元谷歌云平台信用额度来实现。不需要信任CNF Testbed的初始结果,任何人都可以使用开源CNF Testbed存储库的副本和用于访问Packet的API密钥来复制结果。有兴趣了解更多关于CNF的组织,可以参与每月两次的BoF会议。详细信息在CNF Testbed仓库可以找到。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国

February 26, 2019 · 1 min · jiezi

CNCF案例研究:VSCO

VSCO:移动应用如何通过云原生节省70%的EC2账单公司:VSCO地点:加州奥克兰行业:照片移动应用程序挑战在2015年从Rackspace迁移到AWS之后,除了运行PHP单体应用外,VSCO开始构建Node.js和Go微服务。该团队使用Docker将微服务容器化,但“它们都是在每个服务专用的EC2实例的独立组中。”机器学习团队工程经理Melinda Lu说。社区团队高级软件工程师Naveen Gattu补充:“这产生了大量浪费的资源。我们开始寻找一种在AWS EC2实例中整合,并提高效率的方法。”解决方法团队开始探索编排系统,并在决定采用Kubernetes之前查看了包括Mesos和Swarm在内的几种解决方案。VSCO也在他们的云原生堆栈中使用gRPC和Envoy。影响在之前,部署需要“大量的手动调整,我们编写的内部脚本,以及由于我们不同的EC2实例,操作必须从始至终照顾整个事情。”高级软件工程师Brendan Ryan说。“我们并没有真正有条理进行测试的故事,可重复使用的容器或以标准化的方式构建。”现在有更快的上线流程。之前,首次部署的时间是两天的动手设置,现在是两个小时。通过持续集成、容器化和Kubernetes,速度显着提高。典型服务从代码完成到生产部署到基础设施的时间从一到两周减少到两到四个小时。Gattu补充:“在工时来说,这是一个人比较起在同时需要开发者和DevOps。”在生产中单个部署的时间减少了80%,部署的数量也增加了,从每年1200到每年3200。实际上也节省了成本:凭借Kubernetes,VSCO的EC2效率提高了2倍至20倍,具体取决于服务,使公司的EC2账单总体节省约70%。Ryan指出,该公司能够从管理一个大型单体应用程序到50多个微服务,使用“或多或少同等规模的开发团队。我们之所以能够做到这一点,是因为我们对工具的信任度更高和灵活性更高,因此我们不需要聘请DevOps工程师来调整每项服务。”随着Kubernetes、gRPC和Envoy到位,VSCO的中断时间减少了88%,这主要是由于消除了JSON模式错误和特定于服务的基础设施配置错误,以及加快修复停机的速度。“看到我们的工程师通过结合大量的Kubernetes基元来提出创造性的解决方案,让我一直留下了非常深刻的印象。将Kubernetes构造作为服务暴露给我们的工程师,而不是暴露高阶构造对我们来说效果很好。它可以让你熟悉这项技术,并用它做更多有趣的事情。” - Melinda Lu,VSCO机器学习团队工程经理作为移动摄影应用程序,VSCO于2011年诞生于云端。最初,“我们使用Rackspace并使用PHP单体应用程序与MySQL数据库通信,使用FTP部署,没有容器化,没有编排。”软件工程师Brendan Ryan说,“当时足够了。” 在VSCO于2015年迁至AWS并且其用户群超过3000万大关之后,该团队很快意识到现有设置将不够用。开发者开始构建一些Node和Go微服务,团队尝试用Docker进行容器化。但是“它们都是在每个服务专用的EC2实例的不同组中。”机器学习团队工程经理Melinda Lu说。社区团队高级软件工程师Naveen Gattu补充说:“这产生了大量浪费的资源。我们开始寻找一种在EC2实例中整合并提高效率的方法。”通过一个包括易用性和实现、支持级别以及是否是开源的清单,团队在决定使用Kubernetes之前评估了一些调度解决方案,包括Mesos和Swarm。“Kubernetes似乎拥有最强大的开源社区。”Lu说。此外,“我们已经开始标准化大量的Google堆栈,Go作为编写语言,gRPC用于我们在数据中心内部服务之间的几乎所有通信。所以我们似乎很自然地选择了Kubernetes。”“Kubernetes似乎拥有最强大的开源社区,而且,我们已经开始标准化很多Google堆栈,Go作为编写语言,gRPC用于我们在数据中心内部服务之间的几乎所有通信。所以我们似乎很自然地选择了Kubernetes。” - Melinda Lu,VSCO机器学习团队工程经理当时,生态系统中很少有托管的Kubernetes产品和较少的工具,因此团队建立了自己的集群,并为其特定的部署需求构建了一些自定义组件,例如自动入口控制器和灰度部署的政策构造。“我们已经开始拆除单体了,所以我们一个接一个地搬东西,从相当小的低风险服务开始。”Lu说。“每一项新服务都部署在那里。”第一项服务于2016年底迁移,一年后,整个堆栈的80%在Kubernetes上跑,包括其余的单体。带来的影响很大。在过去,部署需要“大量的手动调整,我们编写的内部脚本,以及由于我们不同的EC2实例,操作必须从始至终照顾整个事情。”Ryan说。“我们并没有真正有条理进行测试的故事,可重复使用的容器或以标准化的方式构建。”现在有更快的上线流程。之前,首次部署的时间是两天的动手设置时间,现在是两个小时。通过持续集成、容器化和Kubernetes,速度显着提高。典型服务从代码完成到生产部署到基础设施的时间从一到两周减少到两到四个小时。另外,Gattu说,“在工时来说,这是一个人比较起在同时需要开发者和DevOps。”在生产中单个部署的时间减少了80%,部署的数量也增加了,从每年1200到每年3200。“看到我们的工程师通过结合大量的Kubernetes基元来提出创造性的解决方案,让我一直留下了非常深刻的印象。将Kubernetes构造作为服务暴露给我们的工程师,而不是暴露高阶构造对我们来说效果很好。它可以让你熟悉这项技术,并用它做更多有趣的事情。” - Melinda Lu,VSCO机器学习团队工程经理实际上也节省了成本:凭借Kubernetes,VSCO的EC2效率提高了2倍至20倍,具体取决于服务,使公司的EC2账单总体节省约70%。Ryan指出,该公司能够从管理一个大型单体应用程序到50多个微服务,使用“或多或少同等规模的开发团队。我们之所以能够做到这一点,是因为我们能够增加对工具的信任,并且当系统存在压力点时更加灵活。你可以增加服务的CPU内存需求,而无需启动和拆除实例,阅读AWS页面只是为了熟悉许多行话,这对于我们规模的公司而言并不适合。”Envoy和gRPC也对VSCO产生了积极影响。“我们从开箱即用的gRPC中获得了许多好处:跨多种语言输入安全性、使用gRPC IDL轻松定义服务、内置架构如拦截器,以及通过HTTP/1.1和JSON的性能改进。”Lu说。VSCO是Envoy的首批用户之一,在它开源五天后将其投入生产。“我们希望通过我们的边缘负载平衡器直接向移动客户端提供gRPC和HTTP/2,而Envoy是我们唯一合理的解决方案。”Lu说。“在所有服务中默认发送一致且详细的统计数据的能力,使得仪表板的可观察性和标准化变得更加容易。”Envoy内置的指标也“极大地帮助了调试”,DevOps工程师Ryan Nguyen说。“因为现在有一个支持Kubernetes的组织,这会增强信心吗?答案是响亮的。” - Naveen Gattu,VSCO社区团队高级软件工程师随着Kubernetes、gRPC和Envoy的到位,VSCO的中断时间减少了88%,这主要是由于消除了JSON模式错误和特定于服务的基础架构配置错误,以及加快修复停机的速度。鉴于其使用CNCF项目的成功,VSCO开始尝试其,包括CNI和Prometheus。“拥有一个大型组织支持这些技术,我们更有信心尝试这个软件并部署到生产中。”Nguyen说。该团队为gRPC和Envoy做出了贡献,并希望在CNCF社区中更加活跃。“看到我们的工程师通过结合大量的Kubernetes基元来提出创造性的解决方案,让我一直留下了非常深刻的印象。”Lu说。“将Kubernetes构造作为服务暴露给我们的工程师,而不是暴露高阶构造对我们来说效果很好。它可以让你熟悉这项技术,并用它做更多有趣的事情。”KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国

February 25, 2019 · 1 min · jiezi

多集群应用如何帮助企业级Kubernetes获益

扩大Kubernetes集群规模运维人员有两个选择:Scale Up和Scale Out。如果想将工作量以及成本维持在较低水平,那么多集群应用程序将是一个重要功能。本文将介绍这两种选择,并阐述为何多集群应用程序如此重要。Kubernetes有许多受用户喜爱的功能。它提供了一种在大型资源池上部署和运行应用程序的最佳方式。凭借其易于使用的UI和开箱即用的RBAC、监控、审计、日志等功能,Rancher可以轻松地管理企业级Kubernetes。使用Rancher,IT运维人员可以连接他们的云提供商(AWS、GCP、Azure等)或者数据中心,只需简单点击几下就可以创建集群。随着企业对Kubernetes需求的增长,IT运维人员可以有两种选择:Scale Up:团队在相关项目上一起工作,不需要通过添加更多节点来扩大现有集群的规模。Scale Out:由于安全问题、资源回收或其他原因,团队需要高度隔离,可以通过添加更多集群来scale out Kubernetes环境。Rancher均支持这两种选择。要如何做到无论选择scale up还是scale out,都能够确保企业级Kubernetes管理的工作量和成本都控制在一个比较低的水平呢?支持多集群应用程序就是实现这一目标的其中一步。尽管名称上仿佛表示该功能仅适用于多个集群,但其实它也适用于同一集群中的多个项目。Scale up场景随着对高可靠性、高可用性或更大规模集群的需求增长,集群管理员可能会向现有集群添加更多节点。为了实现某种程度的隔离,管理员可以为每个团队提供他们自己的项目。Rancher中的项目是比命名空间更高级别的抽象,可以使用RBAC进行限制。使用相同集群的团队仍然可以在自己的项目中工作,而不需要查看其他项目。出于公司的需求或者不同的团队可能使用相同的应用程序,因此必须将该应用程序的副本push到多个项目中。例如,由内部开发人员组成的项目团队可能必须与外包团队协作。因为他们必须在相同的应用程序上工作,而需要有自己的独立实例,因此两个项目中都应该有应用程序的副本。Scale out场景随着Kubernetes在企业中的应用越来越多,我们经常发现客户会构建多个集群,以在不同的团队之间获得最高级别的隔离。在这种情况下,企业需求(例如需要在每个集群中部署安全工具)要求集群管理员将相同应用程序的副本push到每个集群。在客户可能拥有数百(甚至数千)个集群的边缘计算场景中,这种问题的复杂度是指数级的。为何多集群应用程序如此重要在这两种情况下,将应用程序副本部署到多个目标的场景都算是较小的问题。如果没有复杂的脚本和高度熟练的支持团队,想要升级和维护这些应用程序的同步几乎是不可能的。这就是对于多集群应用程序的支持变得如此重要的原因。想象一下在同一(或多)集群上的多个项目内针对应用程序的Helm charts,我们需要提供配置的值,覆盖项目/集群具体的设置,然后单击一个按钮部署应用程序。不久前的如何部署和管理多Kubernetes集群一文就详细介绍了这种功能。为这些应用程序选择升级策略(滚动或同步更新)的能力,进一步简化了应用程序保持最新版本的方式。可以说,无论是那些支持具有多个集群的企业级Kubernetes用户,还是那些职场时具有多个项目、单个集群的用户,多集群应用程序都拥有着强大的能力。总 结百闻不如一见,试着用用它吧。你可能会发现,采用Kubernetes作为你的企业策略并不会像有些人说的那样复杂!如果要在实验室或者开发环境中测试这些特性,请安装最新的alpha版本:https://rancher.com/docs/ranc…如果有任何需要反馈的内容,请进入Github中的issue,或者直接加入我们的论坛或者添加小助手微信(rancher2)进技术群,与同道中人一起交流。Github:https://github.com/rancher/ra…论坛链接:https://forums.cnrancher.com/

February 25, 2019 · 1 min · jiezi

Etcd超全解:原理阐释及部署设置的最佳实践

本文将带你充分了解Etcd的工作原理,演示如何用Kubernetes建立并运行etcd集群,如何与Etcd交互,如何在Etcd中设置和检索值,如何配置高可用等等。介 绍Etcd是一个开源的分布式键值存储,它由CoreOS团队开发,现在由Cloud Native Computing Foundation负责管理。这个词的发音是“et-cee-dee”,表示在多台机器上分发Unix系统的“/etc”目录,其中包含了大量的全局配置文件。它是许多分布式系统的主干,为跨服务器集群存储数据提供可靠的方式。它适用于各种操作系统,包括Linux、BSD和OS X。Etcd具有下面这些属性:完全复制:集群中的每个节点都可以使用完整的存档高可用性:Etcd可用于避免硬件的单点故障或网络问题一致性:每次读取都会返回跨多主机的最新写入简单:包括一个定义良好、面向用户的API(gRPC)安全:实现了带有可选的客户端证书身份验证的自动化TLS快速:每秒10000次写入的基准速度可靠:使用Raft算法实现了存储的合理分布Etcd的工作原理在理解Etcd的工作机制之前,我们先定义三个关键概念:leaders、elections以及terms。在一个基于Raft的系统中,集群使用election为给定的term选择leader。Leader处理所有需要集群一致协商的客户端请求。不需要一致协商的请求(如读取)可以由任何集群成员处理。Leader负责接受新的更改,将信息复制到follower节点,并在follower验证接受后提交更改。每个集群在任何给定的时间内只能有一个leader。如果leader挂了或者不再响应了,那么其他节点将在预定的时间超时之后开启一个新的term来创建新election。每个节点维护一个随机的election计时器,该计时器表示节点在调用新的election以及选择自己作为候选之前需要等待的时间。如果节点在超时发生之前没有收到leader的消息,则该节点将通过启动新的term、将自己标记为候选,并要求其他节点投票来开始新的election。每个节点投票给请求其投票的第一个候选。如果候选从集群中的大多数节点处获得了选票,那么它就成为了新的leader。但是,如果存在多个候选且获得了相同数量的选票,那么现有的election term将在没有leader的情况下结束,而新的term将以新的随机选举计时器开始。如上所述,任何更改都必须连接到leader节点。Etcd没有立即接受和提交更改,而是使用Raft算法确保大多数节点都同意更改。Leader将提议的新值发送到集群中的每个节点。然后,节点发送一条消息确认收到了新值。如果大多数节点确认接收,那么leader提交新值,并向每个节点发送将该值提交到日志的消息。这意味着每次更改都需要得到集群节点的仲裁才能提交。Kubernetes中的Etcd自从2014年成为Kubernetes的一部分以来,Etcd社区呈现指数级的增长。CoreOS、谷歌、Redhat、IBM、思科、华为等等均是Etcd的贡献成员。其中AWS、谷歌云平台和Azure等大型云提供商成功在生产环境中使用了Etcd。Etcd在Kubernetes中的工作是为分布式系统安全存储关键数据。它最著名的是Kubernetes的主数据存储,用于存储配置数据、状态和元数据。由于Kubernetes通常运行在几台机器的集群上,因此它是一个分布式系统,需要Etcd这样的分布式数据存储。Etcd使得跨集群存储数据和监控更改变得更加容易,它允许来自Kubernetes集群的任何节点读取和写入数据。Kubernetes使用Etcd的watch功能来监控系统实际(actual)状态或期望(desired)状态的变化。如果这两个状态不同,Kubernetes会做出一些改变来调和这两个状态。kubectl命令的每次读取都从Etcd存储的数据中检索,所做的任何更改(kubectl apply)都会在Etcd中创建或更新条目,每次崩溃都会触发etcd中值的修改。部署以及硬件建议出于测试或开发目的,Etcd可以在笔记本电脑或轻量云上运行。然而,在生产环境中运行Etcd集群时,我们应该考虑Etcd官方文档提供的指导。它为良好稳定的生产部署提供了一个良好的起点。需要留意的是:Etcd会将数据写入磁盘,因此强烈推荐使用SSD始终使用奇数个集群数量,因为需要通过仲裁来更新集群的状态出于性能考虑,集群通常不超过7个节点让我们回顾一下在Kubernetes中部署Etcd集群所需的步骤。之后,我们将演示一些基本的CLI命令以及API调用。我们将结合Kubernetes的概念(如StatefulSets和PersistentVolume)进行部署。预先准备在继续demo之前,我们需要准备:一个谷歌云平台的账号:免费的tier应该足够了。你也可以选择大多数其他云提供商,只需进行少量修改即可。一个运行Rancher的服务器启动Rancher实例在你控制的服务器上启动Rancher实例。这里有一个非常简单直观的入门指南:https://rancher.com/quick-start/使用Rancher部署GKE集群参照本指南使用Rancher在GCP账户中设置和配置Kubernetes集群:https://rancher.com/docs/ranc…在运行Rancher实例的同一服务器上安装Google Cloud SDK以及kubelet命令。按照上面提供的链接安装SDK,并通过Rancher UI安装kubelet。使用gcloud init和gcloud auth login,确保gcloud命令能够访问你的GCP账户。集群部署后,输入下面的命令检查基本的kubectl功能:在部署Etcd集群(通过kubectl或在Rancher的UI中导入YAML文件)之前,我们需要配置一些项。在GCE中,默认的持久化磁盘是pd-standard。我们将为Etcd部署配置pd-ssd。这不是强制性的,不过根据Etcd的建议,SSD是非常好的选择。查看此链接可以了解其他云提供商的存储类:https://kubernetes.io/docs/co…让我们检查一下GCE提供的可用存储类。正如预期的那样,我们看到了一个默认的结果,叫做standard:应用下面这个YAML文件,更新zone的值来匹配你的首选项,这样我们就可以使用SSD存储了:我们再一次检查,可以看到,除了默认standard类之外,ssd也可以使用了:现在我们可以继续部署Etcd集群了。我们将创建一个带有3个副本的StatefulSet,每个副本都有一个ssd storageClass的专用卷。我们还需要部署两个服务,一个用于内部集群通信,一个用于通过API从外部访问集群。在搭建集群时,我们需要将一些参数传递给Etcd二进制文件再到数据存储中。Listen-client-urls和listen-peer-urls选项指定Etcd服务器用于接受传入连接的本地地址。指定0.0.0.0作为IP地址意味着Etcd将监听所有可用接口上的连接。Advertise-client-urls和initial-advertise-peer-urls参数指定了在Etcd客户端或者其他Etcd成员联系etcd服务器时应该使用的地址。下面的YAML文件定义了我们的两个服务以及Etcd StatefulSe图:# etcd-sts.yaml---apiVersion: v1kind: Servicemetadata: name: etcd-clientspec: type: LoadBalancer ports:name: etcd-client port: 2379 protocol: TCP targetPort: 2379selector:app: etcdapiVersion: v1kind: Servicemetadata: name: etcdspec: clusterIP: None ports:port: 2379 name: clientport: 2380 name: peerselector:app: etcdapiVersion: apps/v1beta1kind: StatefulSetmetadata: name: etcd labels:app: etcdspec: serviceName: etcd replicas: 3 template:metadata: name: etcd labels: app: etcdspec: containers: - name: etcd image: quay.io/coreos/etcd:latest ports: - containerPort: 2379 name: client - containerPort: 2380 name: peer volumeMounts: - name: data mountPath: /var/run/etcd command: - /bin/sh - -c - | PEERS="etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" exec etcd --name ${HOSTNAME} \ --listen-peer-urls http://0.0.0.0:2380 \ --listen-client-urls http://0.0.0.0:2379 \ --advertise-client-urls http://${HOSTNAME}.etcd:2379 \ --initial-advertise-peer-urls http://${HOSTNAME}:2380 \ --initial-cluster-token etcd-cluster-1 \ --initial-cluster ${PEERS} \ --initial-cluster-state new \ --data-dir /var/run/etcd/default.etcdvolumeClaimTemplates:metadata:name: dataspec:storageClassName: ssdaccessModes: [ "ReadWriteOnce" ]resources: requests: storage: 1Gi 输入下列命令应用YAML:在应用YAML文件后,我们可以在Rancher提供的不同选项卡中定义资源:与Etcd交互与Etcd交互的方式主要有两种:使用etcdctl命令或者直接通过RESTful API。我们将简要介绍这两种方法,不过你还可以通过访问这里和这里的完整文档找到更加深入的信息和示例。Etcdctl是一个和Etcd服务器交互的命令行接口。它可以用于执行各种操作,如设置、更新或者删除键、验证集群健康情况、添加或删除Etcd节点以及生成数据库快照。默认情况下,etcdctl使用v2 API与Etcd服务器通信来获得向后兼容性。如果希望etcdctl使用v3 API和Etcd通信,则必须通过ETCDCTL_API环境变量将版本设置为3。对于API,发送到Etcd服务器的每一个请求都是一个gRPC远程过程调用。这个gRPC网关提供一个RESTful代理,能够将HTTP/JSON请求转换为gRPC消息。让我们来找到API调用所需的外部IP:我们应该还能找到3个pods的名称,这样我们就可以使用etcdctl命令:我们检查Etcd版本。为此我们可以使用API或CLI(v2和v3).根据你选择的方法, 输出的结果将略有不同。使用此命令可直接与API联系:检查API版本为v2的etcdctl客户端,输入:检查API版本为v3的etcdctl客户端,则输入:接下来,列出集群成员,就像我们上面做的那样:{“members”:[{“id”:“2e80f96756a54ca9”,“name”:“etcd-0”,“peerURLs”:[“http://etcd-0.etcd:2380”],“clientURLs”:[“http://etcd-0.etcd:2379”]},{“id”:“7fd61f3f79d97779”,“name”:“etcd-1”,“peerURLs”:[“http://etcd-1.etcd:2380”],“clientURLs”:[“http://etcd-1.etcd:2379”]},{“id”:“b429c86e3cd4e077”,“name”:“etcd-2”,“peerURLs”:[“http://etcd-2.etcd:2380”],“clientURLs”:[“http://etcd-2.etcd:2379”]}]}V2版本的etcdctl:V3版本的etcdctl:在Etcd中设置和检索值下面我们将介绍的最后一个示例是在Etcd集群中全部3个pods上创建一个键并检查其值。然后我们会杀掉leader,在我们的场景中是etcd-0,然后来看看新的leader是如何选出来的。最后,在集群恢复之后,我们将在所有成员上验证之前创建的键的值。我们会看到,没有数据丢失的情况发生,集群只是换了一个leader而已。我们可以通过输入下面的命令来验证集群最初是健康的:接下来,验证当前leader。最后一个字段表明etcd-0是我们集群中的leader:使用该API,我们将创建一个名为message的键并给它分配一个值,请记住在下面的命令中把IP地址替换为你在集群中通过下面命令获取到的地址:无论查询哪个成员,键都具有相同的值。这帮助我们验证值是否已经复制到其他节点并提交到日志。演示高可用性和恢复接下来,我们可以杀掉Etcd集群leader。这样我们可以看到新的leader是如何选出的,以及集群如何从degraded状态中恢复过来。删除与上面发现的Etcd leader相关的pod:下面我们检查一下集群的健康情况:failed to check the health of member 2e80f96756a54ca9 on http://etcd-0.etcd:2379: Get http://etcd-0.etcd:2379/health: dial tcp: lookup etcd-0.etcd on 10.15.240.10:53: no such host member 2e80f96756a54ca9 is unreachable: [http://etcd-0.etcd:2379] are all unreachable member 7fd61f3f79d97779 is healthy: got healthy result from http://etcd-1.etcd:2379 member b429c86e3cd4e077 is healthy: got healthy result from http://etcd-2.etcd:2379cluster is degraded command terminated with exit code 5上面的信息表明,由于失去了leader节点,集群出于degrade状态。一旦Kubernetes通过启动新实例来响应删除的pod,Etcd集群应该就恢复过来了:输入下面指令,我们可以看到新的leader已经选出来了:在我们的例子中,etcd-1节点被选为leader如果我们再一次检查message键的值,会发现没有出现数据的损失:结 论Etcd是一种非常强大、高可用以及可靠的分布式键值存储,专门为特定用例设计。常见的例子包括存储数据哭连接细节、缓存设置、特性标记等等。它被设计成顺序一致的,因此在整个集群中每个事件都是以相同的顺序存储。我们了解了如何在Rancher的帮助下用Kubernetes建立并运行etcd集群。之后,我们能够使用一些基本的Etcd命令进行操作。为了更好的了解这个项目,键是如何组织的,如何为键设置TTLs,或者如何备份所有数据,参考官方的Etcd repo会是个不错的选择:https://github.com/etcd-io/et… ...

February 22, 2019 · 1 min · jiezi

Kublet PLEG不健康问题排障

环境:Rancher管控的K8S集群。现象:某个Node频繁出现“PLEG is not healthy: pleg was last seen active 3m46.752815514s ago; threshold is 3m0s”错误,频率在5-10分钟就会出现一次。排查:kubectl get pods –all-namespaces 发现有一个istio-ingressgateway-6bbdd58f8c-nlgnd一直处于Terminating状态,也就是说杀不死。到Node上docker logs –tail 100 kubelet也看到这个Pod的状态异常:I0218 01:21:17.383650 10311 kubelet.go:1775] skipping pod synchronization - [PLEG is not healthy: pleg was last seen active 3m46.752815514s ago; threshold is 3m0s]…E0218 01:21:30.654433 10311 generic.go:271] PLEG: pod istio-ingressgateway-6bbdd58f8c-nlgnd/istio-system failed reinspection: rpc error: code = DeadlineExceeded desc = context deadline exceeded用kubelet delete pod尝试删除,命令挂住。用kubectl delete pod –force –grace-period=0,强制删除Pod。再到Node上检查这个容器是否真的被停止,docker ps -a| grep ingressgateway-6bbdd58f8c-nlgnd,看到容器处于Exited状态。观察Node状态,问题依旧。把Pod关联的Deployment删除,把一只处于Terminating的Pod用kubectl delete pod –force –grace-period=0的方式删除。重新部署Deployment。问题解决。相关issue ...

February 22, 2019 · 1 min · jiezi

全网最简单的k8s User JWT token管理器

kubernetes集群三步安装概述kubernetes server account的token很容易获取,但是User的token非常麻烦,本文给出一个极简的User token生成方式,让用户可以一个http请求就能获取到。token主要用来干啥官方dashboard登录时需要。 如果通过使用kubeconfig文件登录而文件中又没有token的话会失败,现在大部分文章都介绍使用service account的token来登录dashboard,能通,不过有问题:第一:绑定角色时要指定类型是service account:apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: kubernetes-dashboard labels: k8s-app: kubernetes-dashboardroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-adminsubjects:- kind: ServiceAccount # 这里不是User类型 name: kubernetes-dashboard namespace: kube-system第二:要理解kubeconfig里是解析证书把CN作为用户名的,这时service account即便与CN一样那还是两个账户,绑定角色时还需要绑定两次,有点像把service account给"人"用, 所以把service account的token扔给某个开发人员去用往往不合适,service account token更多时候是给程序用的。想直接调用https的,没有token就会:[root@iZj6cegflzze2l7fpcqoerZ ssl]# curl https://172.31.12.61:6443/api/v1/namespaces/default/pods –insecure{ “kind”: “Status”, “apiVersion”: “v1”, “metadata”: { }, “status”: “Failure”, “message”: “pods is forbidden: User "system:anonymous" cannot list resource "pods" in API group "" in the namespace "default"”, “reason”: “Forbidden”, “details”: { “kind”: “pods” }, “code”: 403}因为没有任何认证信息,所以匿名(anonymous)用户没有任何权限加了token是这样的:[root@iZj6cegflzze2l7fpcqoerZ ssl]# curl -H “Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkNnYzRPVEV5TlRVM0VnWm5hWFJvZFdJIn0.eyJpc3MiOiJodHRwczovL2RleC5leGFtcGxlLmNvbTo4MDgwIiwic3ViIjoiQ2djNE9URXlOVFUzRWdabmFYUm9kV0kiLCJhdWQiOiJleGFtcGxlLWFwcCIsImV4cCI6MTU1MTA5NzkwNiwiaWF0IjoxNTUwNzM3OTA2LCJlbWFpbCI6ImZodGpvYkBob3RtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiZGV2Il0sIm5hbWUiOiJmYW51eCJ9.ZqKn461UW0aGtyjyqu2Dc5tiUzC-6eYLag542d3AvklUdZuw8i9XwyaUg_f1OAj0ZsEcOybOe9_PeGMaUYzU0OvlKPY-q2zbQVC-m6u6sQw6ZXx8pi0W8k4wQSJnMaOLddCfurlYufmr8kScDBQlnKapSR0F9mJzvpKkHD-XNshQKWhX3n03g7OfFgb4RuhLjKDNQnoGn7DfBNntibHlF9sPo0jC5JjqTZaGvoGmiRE4PAXwxA-RJifsWDNf_jW8lrDiY4NSO_3O081cia4N1GKht51q9W3eaNMvFDD9hje7abDdZoz9KPi2vc3zvgH7cNv0ExVHKaA0-dwAZgTx4g” -k https://172.31.12.61:6443/api/v1/namespaces/default/pods{ “kind”: “Status”, “apiVersion”: “v1”, “metadata”: { }, “status”: “Failure”, “message”: “pods is forbidden: User "https://dex.example.com:8080#fanux" cannot list resource "pods" in API group "" in the namespace "default"”, “reason”: “Forbidden”, “details”: { “kind”: “pods” }, “code”: 403}看,虽然还是403 但是已经有了用户信息,只要给该用户授权就可正常访问了,如何授权下文介绍token种类介绍token的生成方式有很多,主要分成三种:service account token 这个创建service account就有,存在secret里 获取比较简单,但是要区分好 User 和 service account区别普通的token,这种token就是个普通的字符串,一般是自己写一个认证的web hook, k8s认证时调用这个hook 查询token是否有效,比较low基于openid的jwt(josn web token) 这种token,认证中心把用户信息放在json里,用私钥加密,k8s拿到token后用公钥解密,只要解密成功token就是合法的而且能拿到用户信息,不需要再像认证中心请求基于openid的jwt是本文介绍的重点。社区用的比较多的就是dex,是一个比较完整的实现,但是对于不熟悉该技术的朋友来说还是有点门槛的,容易绕进去。 而且还存在一些使用不方便的问题。如依赖复杂,首先得需要一个真正的用户管理程序,如ldap 或者一个auth2服务端,这还可以接受,关键是认证时可能需要依赖浏览器进行跳转授权,这在十分多的场景里就变的十分尴尬,就比如我们的场景压根没有界面,这样生成token就成了一个大问题。 其次集成到别的系统中时往往用户已经登录过了,所以需要一个二次授权的过程才能拿到token,依赖过重导致系统难以设计。然而如果不是集成到别的系统中,比如从0开发一个完成的PaaS平台那使用dex还是一个完美的方案。所以我们实现了一个简单粗暴的方案,完全解放了这个过程, 只care最核心的东西。sealyun fist介绍我们想要啥?input:{ “User”: “fanux”, “Group”: [“sealyun”, “develop”]}output:eyJhbGciOiJSUzI1NiIsImtpZCI6IkNnYzRPVEV5TlRVM0VnWm5hWFJvZFdJIn0.eyJpc3MiOiJodHRwczovL2RleC5leGFtcGxlLmNvbTo4MDgwIiwic3ViIjoiQ2djNE9URXlOVFUzRWdabmFYUm9kV0kiLCJhdWQiOiJleGFtcGxlLWFwcCIsImV4cCI6MTU1MTA5NzkwNiwiaWF0IjoxNTUwNzM3OTA2LCJlbWFpbCI6ImZodGpvYkBob3RtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiZGV2Il0sIm5hbWUiOiJmYW51eCJ9.ZqKn461UW0aGtyjyqu2Dc5tiUzC-6eYLag542d3AvklUdZuw8i9XwyaUg_f1OAj0ZsEcOybOe9_PeGMaUYzU0OvlKPY-q2zbQVC-m6u6sQw6ZXx8pi0W8k4wQSJnMaOLddCfurlYufmr8kScDBQlnKapSR0F9mJzvpKkHD-XNshQKWhX3n03g7OfFgb4RuhLjKDNQnoGn7DfBNntibHlF9sPo0jC5JjqTZaGvoGmiRE4PAXwxA-RJifsWDNf_jW8lrDiY4NSO_3O081cia4N1GKht51q9W3eaNMvFDD9hje7abDdZoz9KPi2vc3zvgH7cNv0ExVHKaA0-dwAZgTx4g结束,多简单,别整那么多没用的。所以为了实现上面的功能,我们开发了 fist, fist的auth模块把dex里最核心的token生成功能以及jwt功能实现了。sealyun fist/auth 使用教程安装部署生成证书# mkdir /etc/kubernetes/pki/fist# cd /etc/kubernetes/pki/fist# sh gencert.sh # 脚本内容内代码启动fist auth模块kubectl create -f deploy/fist-auth.yaml修改k8s apiserver启动参数vim /etc/kubernetes/manifests/kube-apiserver.yaml - command: - kube-apiserver - –oidc-issuer-url=https://fist.sealyun.svc.cluster.local:8080 - –oidc-client-id=example-app - –oidc-ca-file=/etc/kubernetes/pki/fist/ca.pem - –oidc-username-claim=name - –oidc-groups-claim=groups获取及使用 token获取tokencurl https://fist.sealyun.svc.cluster.local:8080/token?user=fanux&group=sealyun,develop –cacert ca.pem使用token直接curl加bare token 见上文加入到kubeconfig中:kubectl config set-credentials –token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkNnYzRPVEV5TlRVM0VnWm5hWFJvZFdJIn0.eyJpc3MiOiJodHRwczovL2RleC5leGFtcGxlLmNvbTo4MDgwIiwic3ViIjoiQ2djNE9URXlOVFUzRWdabmFYUm9kV0kiLCJhdWQiOiJleGFtcGxlLWFwcCIsImV4cCI6MTU1MTEwMDI5MywiaWF0IjoxNTUwNzQwMjkzLCJlbWFpbCI6ImZodGpvYkBob3RtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiZGV2Il0sIm5hbWUiOiJmYW51eCJ9.OAK4oIYqJszm1EACYW2neXTo738RW9kXFOIN5bOT4Z2CeKAvYqyOVKCWZf04xX45jwT78mATR3uas2YvRooDXlvxaD3K43ls4KBSG-Ofp-ynqlcVTpD3sUDqyux2iieNv4N6IyCv11smrU0lIlkrQC6oyxzTGae1FrJVGc5rHNsIRZHp2WrQvw83uLn_elHgUfSlsOq0cPtVONaAQWMAMi2DX-y5GCNpn1CDvudGJihqsTciPx7bj0AOXyiOznWhV186Ybk-Rgqn8h0eBaQhFMyNpwVt6oIP5pvJQs0uoODeRv6P3I3-AjKyuCllh9KDtlCVvSP4WtMUTfHQN4BigQ kubernetes-admin然后.kube/config 文件里的 user.client-certifacate-data 和 client-key-data就可以删了,再执行kubectl会:[root@iZj6cegflzze2l7fpcqoerZ ~]# kubectl get podError from server (Forbidden): pods is forbidden: User “https://dex.example.com:8080#fanux" cannot list resource “pods” in API group "” in the namespace “default"说明新用户成功了授权[root@iZj6cegflzze2l7fpcqoerZ ~]# cat rolebind.yamlkind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: read-secrets-globalsubjects:- kind: User name: “https://dex.example.com:8080#fanux" # Name is case sensitive apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole name: cluster-admin # 超级用户给他 apiGroup: rbac.authorization.k8s.io创建个role binding即可:[root@iZj6cegflzze2l7fpcqoerZ ~]# kubectl –kubeconfig /etc/kubernetes/admin.conf create -f rolebind.yaml # 用管理员的kubeconfigclusterrolebinding.rbac.authorization.k8s.io/read-secrets-global created[root@iZj6cegflzze2l7fpcqoerZ ~]# kubectl get pod # 有权限访问pod了No resources found.原理介绍jwt原理 https://fist.sealyun.cluster.local:8080k8s jwt server | /.well-known/openid-configuration | |————————————————>| k8s通过此url发现一些信息,最重要的就是用于校验token公钥的地址 | discover info | |<————————————————| | /keys | |————————————————>| 上一步拿到地址,这一步获取到公钥 | public keys | |<————————————————| | |discoer info 是个json:{“issuer”: “https://accounts.google.com”,“authorization_endpoint”: “https://accounts.google.com/o/oauth2/v2/auth","token_endpoint": “https://oauth2.googleapis.com/token","userinfo_endpoint": “https://openidconnect.googleapis.com/v1/userinfo","revocation_endpoint": “https://oauth2.googleapis.com/revoke","jwks_uri": “https://www.googleapis.com/oauth2/v3/certs","response_types_supported": [“code”,“token”,“id_token”,“code token”,“code id_token”,“token id_token”,“code token id_token”,“none”],…public keys也是个json 类似:{“keys”: [{“e”: “AQAB”,“kty”: “RSA”,“alg”: “RS256”,“n”: “3MdFK4pXPvehMipDL_COfqn6o9soHgSaq_V1o8U_5gTZ-j9DxO9PV7BVncXBgHFctnp3JQ1QTDF7txeHeuLOS4KziRw5r4ohaj2WoOTqXh7lqVMR2YDAcBK46asS177NpkQ1CqHIsy3kNfqhXLwTaKfdlwdA_XUfRbKORWbq0kDxV35egx35nHl5qJ6aP6fcpsnnPvHf7KWO0zkdvwuR-IX79HjqUAEg5UERd5FK4y06PRbxuXHjAgVhHu_sk4reNXNp1HRuTYtQ26DFbVaIjsWb8-nQC8-7FkTjlw9FteAwLVGOm9sTLFp73jAf0pWLh7sJ02pBxZKjsxLO1Lvg7w”,“use”: “sig”,“kid”: “7c309e3a1c1999cb0404ab7125ee40b7cdbcaf7d”},{“alg”: “RS256”,“n”: “2K7epoJWl_B68lRUi1txaa0kEuIK4WHiHpi1yC4kPyu48d046yLlrwuvbQMbog2YTOZdVoG1D4zlWKHuVY00O80U1ocFmBl3fKVrUMakvHru0C0mAcEUQo7ItyEX7rpOVYtxlrVk6G8PY4EK61EB-Xe35P0zb2AMZn7Tvm9-tLcccqYlrYBO4SWOwd5uBSqc_WcNJXgnQ-9sYEZ0JUMhKZelEMrpX72hslmduiz-LMsXCnbS7jDGcUuSjHXVLM9tb1SQynx5Xz9xyGeN4rQLnFIKvgwpiqnvLpbMo6grhJwrz67d1X6MwpKtAcqZ2V2v4rQsjbblNH7GzF8ZsfOaqw”,“use”: “sig”,“kid”: “7d680d8c70d44e947133cbd499ebc1a61c3d5abc”,“e”: “AQAB”,“kty”: “RSA”}]}所以fist只需要实现这两个url 和 用私钥匙加密用户信息生成token即可。创建密钥对: key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatalf(“gen rsa key: %v”, err) } priv = jose.JSONWebKey{ Key: key, KeyID: “Cgc4OTEyNTU3EgZnaXRodWI”, Algorithm: “RS256”, Use: “sig”, } pub = jose.JSONWebKey{ Key: key.Public(), KeyID: “Cgc4OTEyNTU3EgZnaXRodWI”, Algorithm: “RS256”, Use: “sig”, }私钥加密: tok := idTokenClaims{ Issuer: “https://dex.example.com:8080”, Subject: “Cgc4OTEyNTU3EgZnaXRodWI”, Audience: “example-app”, Expiry: time.Now().Add(time.Hour * 100).Unix(), IssuedAt: time.Now().Unix(), Email: “fhtjob@hotmail.com”, EmailVerified: &ev, Groups: []string{“dev”}, Name: “fanux”, } payload, err := json.Marshal(&tok) if err != nil { return } var idToken string if idToken, err = signPayload(&Priv, signingAlg, payload); err != nil { return总结fist核心代码已经可用,不过为了更方便使用还需要进一步梳理,敬请期待。 鉴权仅是其其中一个功能,fist定位是一个极简的k8s管理平台。探讨可加QQ群:98488045公众号: ...

February 21, 2019 · 2 min · jiezi

基于 Kubernetes 实践弹性的 CI/CD 系统

大家好,我是来自阿里云容器服务团队的华相。首先简单解释一下何为 Kubernetes 来帮助大家理解。Kuberentes 是一个生产可用的容器编排系统。Kuberentes 一方面在集群中把所有 Node 资源做一个资源池,然后它调度的单元是 Pod,当然 Pod 里面可以有多个容器。 就像一个人左手抓着 ECS 资源或计算资源,右手抓容器,然后把它们两个匹配起来,这样它就可以作为一个容器的编排系统。而 Cloudnative 这个概念现在会经常被大家提起,很多人迷惑 Cloudnative 又与 Kuberentes 有什么关联?我们又该如何判断一个应用是 Cloudnative 呢?我认为有以下三个判断标准:第一,它能够给资源做池化;第二,应用可以快速接入池的网络。在 Kuberentes 里面有一层自己的独立网络,然后只需要知道我要去访问哪个服务名就可以,就是各种服务发现的一些功能,它可以通过 service mesh 去做一个快速地访问;第三是有故障转移功能,如果一个池子里面有一台主机,或者某一个节点 down 掉了,然后整个应用就不可用了,这肯定不算是 Cloudnative 的应用。比较这三点就可以发现 Kuberentes 做的非常好。首先我们看一个资源池的概念,Kuberentes 一个大的集群就是一个资源池,我们再也不用去关心说我这个应用要跑在哪台主机上了,我只要把我们部署的 yaml 文件往 Kuberentes 上发布就可以了,它会自动做这些调度,并且它可以快速地接入我们整个应用的网络,然后故障转移也是自动。接下来我就来分享如何基于 Kuberentes 实现一个弹性的 CI/CD 系统。CI/CD 的现状首先了解一下 CI/CD 的现状。CI/CD 这个概念实际上已经提出很多年了,但是随着技术地演进和新工具地不断推出,它在整个流程和实现方式上逐渐丰富。而我们通常最早接触 CI/CD 就是代码提交,随之触发一个事件,然后在某个 CI/CD 系统上做自动构建。下图可以反映目前 CI/CD 的现状:另外还有 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 开始引入 pipeline as code 特性,pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins 建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是由运维人员来管理 Jenkins 系统,开发人员编写代码,但是这个代码怎么去构建,发布到哪里,开发人员完全不知道。这就造成了开发和运维地割裂。但 pipeline as code 方式出现了之后,jenkins file 与代码源码可以放在同样的仓库里面。首先它有一个非常大的好处是发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Docker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Docker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Docker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Docker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD 工具的选择接下来,我们看一下 CI/CD 这些工具的选择和他们的发展。首先最老牌的肯定是 Jenkins。实际上在容器技术兴起之前,CI/CD 简直约等于 Jenkins。但是在出现容器技术之后,很多新生 CI/CD 的工具也应运而生,比如说图中 Drone 工具,它是一个完全基于容器来实现的 CI/CD 工具。它与容器地结合地非常好,并且它的构建过程是完全在容器中实现的。第三个是 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 时开始引入 pipeline as code 特性,什么叫 pipeline as code?pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins,然后建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是运维人员来管理 Jenkins 这个系统。开发人员编写代码,但是这个代码怎么去构建,发布到哪里,他是完全不知道的,是运维人员在Jenkins 里面配的。这个就造成了开发和运维地割裂。但 pipeline as code 这种方式出现了之后,我们可以把 jenkins file 跟代码源码放在同样的仓库里面。首先它有一个非常大的好处就是我们发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Doker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Doker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Doker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Doker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD的系统业务场景然后我们看一下 CI/CD 它的系统的业务场景,它有一个比较典型的场景与特点,首先它面向开发人员,这是比较少见的,因为开发人员一般都比较挑剔一点。所以你要是这个系统做的不够稳健了,或者说响应时间比较长一点的话,会被经常吐槽。然后就是有时效性要求,因为我们代码写完之后,往上提交,我们都不希望在这个代码的构建中一直排队,我们希望马上就开始进行构建,并且资源足够丰富。另外一个就是它的资源占用的波峰波谷是非常明显的。就因为开发人员不可能时时刻刻都在提交代码,有的人可能一天提交几次,有的人会提交很多次。因为我之前看过有一个分享,有一个人画了一条反映自家公司构建任务的曲线。他们公司大概是每天下午三、四点的时候代码提交量最高,其他时间都比较平缓。这说明他们公司三、四点的时候,程序员提交代码开始划水了。然后随着 CI/CD 资源地需求越来越高,构建集群是一个必须要做的一件事情。就是提高负载能力,缩短任务的排队时间。当然真正的集群有一个让人觉得很不太好的地方,就是它的 Master 实际上只有一个,当然这个也可以通过插件来做改进。容器可以给我们 CI/CD 系统来注入新的能力,就是环境隔离的能力。我们可以通过 Kubernetes 来为 CI/CD 系统注入更多的能力,然后矛盾点就出现了。开发人员总是希望 CI/CD 系统能够快速地响应代码提交的一个事件,但是每个公司资源都不可能是无限的。因为就像上面提到的,如果每天下午三、四点的时候是一个代码提交的高峰,这个时候可能需要 30 或 40 台机器才能满足构建的任务。但是我不可能每天就开着 30 或 40 台机器在这里,就为了每天下午三、四点,可能会构建一、两个小时。Kubernetes 可以为 jenkins 注入新的能力,让 CI/CD 系统实现弹性的能力。我们期望的目标是什么呢?有构建任务的时候,可以自动为我们资源增加新的机器也好,或增加新的运计算能力也好,反正就是当我需要的时候,可以帮我自动地做一个资源扩张,但是同时也在我不需要的时候,可以自动把这些资源释放掉。我们期望的目标就是这样,Kuberentes 就可以为 Jenkins 来做这样的能力。Kuberentes 作为一个容器编排的系统,它所能提供的能力,它可以快速地弹出一些新的实例,并且把它们自动调度到空闲的机器上,做一个资源池,在资源池里面做一个调度,并且他执行完任务之后,它可以做一个回收。而且如果把这 Jenkins Master 也部署在 Kuberentes 之上,它可以对 Master 做一个故障转移,就是说如果我们系统可以容忍的话,Master 就算挂了,我可以快速把它调到另外一台机器上,这个响应时间不会很长。Kuberentes-plugin这里面也是用一个插件来实现,这个插件名字比较直接叫 Kuberentes-plugin,它这个插件所能提供的能力就是说,他直接管理一个 Kuberentes 集群,它在 Jenkins 里面安装之后,它可以监听 Jenkins 的构建任务。有构建任务,在等待资源的时候,它就可以向 Kuberenetes 去申请一个新的资源,申请一个新的 Pod 去做自动地构建完之后,它就会自动的清理。先简单介绍一下它的能力,因为这个插件安装完之后,它对 pipeline 的语法也有一个改造,一会我们来看一下实例。但是就算到了这一步,还是不行的。首先,Kuberentes 的集群规划还是一个问题。比说我有个集群有 30 个节点,真正的 master 部署在这上面,然后装了那些插件,做了一个管理之后,我们可以发现来了一个新的任务,它就起一个新的 Pod,把这个构建任务给执行制定完。执行完之后,这 Pod 自动销毁不占集群的资源。 平时我们可以在这集群上做一些别的任务,但这个终究还是有一点不好,就是我们这个集群到底规划多大,并且这个集群我们平时不做构建任务的时候,可以在上面做一些别的任务。但是如果正在做任务,突然来了一些构建任务,它可能会出现资源的冲突问题。Kubernetes Autoscaler总的来说,还是有一些不完美的地方,那么我们可以利用 Kuberentes 一些比较没那么常见的特性,来解决我们刚才说的这个问题。这两个东西一个是叫 Autoscaler,一个叫 Virtual node。我们先看一下 Autoscaler,Autoscaler 是一个 Kubernetes 官方的一个组件。在 Kuberentes 的 group 下面支持三种能力:Cluster Autoscaler,可以对集群节点做自动伸缩;Vertical Pod Autoscaler,对集群的 Pod 竖直方向的资源伸缩。因为 Kuberentes 本身里面就带着 HPA 可以做水平方向的 Pod 伸缩、节点数量的伸缩;这个特性还不是生产可用的特性;Addone Resizer,是 Kuberentes 上那些 addone 比如说 Ingress Controler、 DNS 可以根据 Node 的数量来对资源的分配做调整。Cluster autoscaler我要讲的是 Cluster autoscaler,是对集群 node 节点数量做一个扩缩容。 首先我们看一下,这个是在阿里云我们容器服务上所实现的 Autoscaler 的一个方式。我们看一下这个图,这个是 HPA 和 Autoscler 做结合使用的一个场景。HPA 监听监控的事件时发现资源使用率上升到一定程度了之后,HPA 会自动通知 workload,来弹出一个新的 Pod,弹出一个新的 Pod,可能这时候集群资源就已经不够了,所以这个 Pod 可能就会 pending 在这里。它就会触发 Autoscaler 的事件,Autoscaler 就会根据我们之前配置好的 ESS 这个模板来去弹出来一台新的 Node,然后自动地把 Node 加入到我们集群里面。 它是利用了 ESS 定制的模板功能,并且它可以支持多种的 Node 实例的类型,可以支持普通实例,支持 gpu,还有抢占式实例。Virtual node然后第二种是 Virtual node,Virtual node 实现方式是基于微软开源的 Virtual Kubelet 这个项目。它做了一个虚拟的 Kubelet,然后向 Kubernetes 集群里面去注册上面。但如果不太好理解的话,可以想象一下 MySQL proxy ,然后他把自己伪装成一个MySQL server,然后后端可能管理着非常多的 MySQL server,并且它可以帮你自动的做一些 SQL 查询的路由或者拼接。Virtual kubelet 做的也是类似的工作,就是说它本身向着 Kubernetes 注册说我是一个节点,但实际上它后端管理的可能是整个公有云上的非常多的资源,他可能对接公有云的一些 ECI 或者说对接的这些 VPC,这是一个它的大体的示意图。在阿里云上他们对接的是阿里云的 ECI 做一个弹性的容器实例,它响应时间就非常快,因为它不需要把 Node 去加入到集群里面,它是大概能够到一分钟一百个 Pod 左右这种性能。而且我们可以在 Pod 上声明这种资源的使用情况,这是一个非常快的响应速度时间。然后刚才说我们利用这两种方式,就可以对我们 CI/CD 弹性的系统做出新的改造,我们不用非常早规划好我们集群的规模,我们可以让集群规模在需要的时候自动的做一些伸缩的动作。但是你做了这些动作之后,我们做了这些把真正的放在容器里面的这些动作之后,引入了一些新的门槛:docker-outside-of-docker 和 docker in docker。我们在 Docker 中运行 Jenkins 时,通常有两种方式,一个是把宿主机的 docker.sock 挂载到容器里面,让 Jenkins 通过这个文件来和本机的 docker daemon 做一个通信,然后它在这里面做 docker build 构建镜像,或者把这些镜像 push 到远程的仓库里面,所以它中间产生的所有镜像都会堆积在本机上,这是一个问题。在一些 serverless 的那些场景上使用,它就会有一些限制,因为 serverless 本身就不允许把 socket 文件给挂在进去。另外一个就是 docker in docker 这种方式,它的优点就在于在容器里面它启动一个新的 Docker daemon,它所有的中间产物、构建产物随着容器都一起销毁,但是它有问题,它就是需要 privilege 的权限。很多时候我们是尽量不要用它。另外一个就是说你做 docker build 的时候能在宿主机上做的时候,它如果有已经有镜像了,它会直接就使用这个镜像,但是你用 docker in docker 这种方式来使用的,它每次都会重新拉进项,拉镜像也是需要一定时间,这个取决于我们各个使用场景来判断。新的构建工具——Kaniko这时又引入了一个谷歌开源的新工具——Kaniko。它做的东西是 docker in docker 的方式。它有一个非常大的好处就是不依赖 Docker,而且所以它不需要 privilege 权限就可以在容器里面用用户态的模式,来完全构建 docker image。用户态执行 Dockerfile 的命令,它把这个镜像完全构建出来。这算是一个比较期望的弹性的 CI/CD 系统。然后这个时候就是说从真正的节点到底层的计算资源全部是弹性扩缩的,而且满足交付的需求,可以非常精细化地管理我们的资源。Demo 演示然后我们可以看一下 Demo 演示:https://github.com/hymian/webdemo 这里是我准备好的一个例子,重点在这个 Jenkinsfile 文件,里面定义了agent 的 pod template,包含两个容器,一个用来做 golang 的 build,一个用来做 image 的 build。然后我们现在构建它。开始构建了,刚开始的,因为是现在我们在这环境里面只有一个,只有一个 master,所以他就是没有不会有构建节点。大家可以看到,它现在新启动了一个 Pod,这个 Pod 是作为节点加进来的,但是因为我在这个 Pod 模板里面定义了一个 label,所以它没有这个节点,所以它 Pod 状态是 pending 的。所以我们在构建日志里面显示的这个是 agent 节点是离线的。 但是我们在这个集群里面定义了一个弹性伸缩的一个东西,当没有节点的时候,它会自动做一个新节点分配加入,可以看到有一个节点正在加入,这个我就可以稍等一下。就是说这段时间可能会有个一分钟两分钟的时间。这个是异常,是因为这个节点正在向集群加入,所以它显示是异常,这是我们从命令行看一下,好,已经是四个节点了,加了一个节点,这时候我们看 Pod,这时候在 agent 正在创建,这时候大家可能有一个小的细节,大家可以看一下,就是 0/3 是显示 Pod,它有三个容器,但是我刚才在这个里面定义的,它实际上是 Pod 里面只有两个容器,这就是我们刚才 PPT 上写的一个地方。 JNLP 那个容器,是 plugin 自动注入的一个容器,它通过这个容器实时的向 master 汇报构建的一个中间的状态,我把它的日志给发送出去。这个是 agent 的节点在初始化的一个过程一个事情这时候 slave节点已经在运行了。我这边已经输出完了,构建完成。我的分享内容就这些,谢谢大家。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 20, 2019 · 3 min · jiezi

如何在Kubernetes集群动态使用 NAS 持久卷

介绍:本文介绍的动态生成NAS存储卷的方案:在一个已有文件系统上,自动生成一个目录,这个目录定义为目标存储卷;镜像地址:registry.cn-hangzhou.aliyuncs.com/acs/alicloud-nas-controller:v1.11.5.4-433631d-aliyun默认生成资源:生成的PV名字为:pvc-${pvc-uid}生成目录的名字:namespace-pvcname-pvname可以再pvc的annotations中如下声明,自定义名字:生成的pv、目录名字为下面定义的名字。 annotations: pv-name-created: replace-user-id2. 部署NAS Controller创建alicloud-nas-controller,实现动态provider nas pv;创建alicloud-nas storageclass,为nas pv provision 提供模板;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nasprovisioner: alicloud/nasreclaimPolicy: Deleteparameters: drivertype: flexvolume nfsversion: “4.0” options: “”—kind: DeploymentapiVersion: extensions/v1beta1metadata: name: alicloud-nas-controller namespace: kube-systemspec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: alicloud-nas-controller spec: tolerations: - effect: NoSchedule operator: Exists key: node-role.kubernetes.io/master - effect: NoSchedule operator: Exists key: node.cloudprovider.kubernetes.io/uninitialized serviceAccount: admin containers: - name: alicloud-nas-controller image: registry.cn-hangzhou.aliyuncs.com/acs/alicloud-nas-controller:v1.11.5.4-433631d-aliyun imagePullPolicy: Always volumeMounts: - mountPath: /persistentvolumes name: nfs-client-root env: - name: NFS_SERVER value: 154154b095-.cn-beijing.nas.aliyuncs.com - name: NFS_PATH value: / volumes: - name: nfs-client-root flexVolume: driver: alicloud/nas options: path: / server: 154154b095-.cn-beijing.nas.aliyuncs.com vers: “4.0"StorageClass使用说明:drivertype: 用来表示生成pv存储类型,可选nfs, flexvolume. nfs: 默认选项,表示使用k8s原生NFS驱动挂载; flexvolume: 表示使用阿里云提供的Flexvolume NAS驱动挂载;nfsversion: 挂载nfs使用的版本,支持3,4.0.默认为4.0; drivertype为flexvolume的时候在这里配置; 为nfs的时候通过mountOptions 配置;options:为挂载nfs的可选项配置; drivertype为flexvolume的时候在这里配置; 为nfs的时候通过mountOptions 配置;StorageClass举例:## 使用kubernetes提供的NFS驱动,并配置mountOptions,reclaimPolicy为Delete;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nas-nfsmountOptions:- vers=4.0- noresvportprovisioner: alicloud/nasreclaimPolicy: Delete## 使用阿里云提供的Flexvolume NAS驱动,配置nfs版本、options;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nas-flexprovisioner: alicloud/nasreclaimPolicy: Deleteparameters: drivertype: flexvolume nfsversion: “3” options: “noresvport"3. 创建应用-Deployment:kind: PersistentVolumeClaimapiVersion: v1metadata: name: replace-user-id annotations: pv-name-created: replace-user-idspec: storageClassName: alicloud-nas accessModes: - ReadWriteMany resources: requests: storage: 5Gi—apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: “deploy-nas"spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: deploy-nas spec: containers: - name: “nginx” image: “nginx” volumeMounts: - name: pvc-nas mountPath: “/data” volumes: - name: pvc-nas persistentVolumeClaim: claimName: replace-user-id执行:# userID=“hello-123”# cat deploy.yaml | sed “s/replace-user-id/"$userID"/g” | kubectl create -f -# kubectl get pod | grep deploy-nasdeploy-nas-85696b6bfc-t5dmh 1/1 Running 0 28m# kubectl get pvc | grep hellhello-123 Bound hello-123 5Gi RWX alicloud-nas-flex 28m# kubectl get pv | grep hellhello-123 5Gi RWX Delete Bound default/hello-123 alicloud-nas-flex 28m# Nas目录下查看生成目录:# ls -l | grep hellodrwxrwxrwx 2 root root 4096 2月 19 09:58 hello-1234. 创建应用-StatefulSet:使用volumeTemplateClaim不支持使用pv-name-created配置pv名字;apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx—apiVersion: apps/v1beta1kind: StatefulSetmetadata: name: webspec: replicas: 2 serviceName: “nginx” template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine volumeMounts: - mountPath: “/data” name: pvc-sts volumeClaimTemplates: - metadata: name: pvc-sts spec: accessModes: - ReadWriteOnce storageClassName: alicloud-nas-flex resources: requests: storage: 2Gi 创建后查看:# kubectl get pod | grep webweb-0 1/1 Running 0 7sweb-1 1/1 Running 0 4s# kubectl get pvc | grep webpvc-sts-web-0 Bound pvc-65ab251a-33ec-11e9-a151-00163e066784 2Gi RWO alicloud-nas-flex 13mpvc-sts-web-1 Bound pvc-8437c50e-33ed-11e9-a151-00163e066784 2Gi RWO alicloud-nas-flex 5m# kubectl get pv | grep webpvc-65ab251a-33ec-11e9-a151-00163e066784 2Gi RWO Delete Bound default/pvc-sts-web-0 alicloud-nas-flex 13mpvc-8437c50e-33ed-11e9-a151-00163e066784 2Gi RWO Delete Bound default/pvc-sts-web-1 alicloud-nas-flex 5m# Nas目录下查看生成目录:# ls -l | grep stsdrwxrwxrwx 2 root root 4096 2月 19 10:16 default-pvc-sts-web-0-pvc-65ab251a-33ec-11e9-a151-00163e066784drwxrwxrwx 2 root root 4096 2月 19 10:24 default-pvc-sts-web-1-pvc-8437c50e-33ed-11e9-a151-00163e0667845. 创建应用-Pod:kind: PersistentVolumeClaimapiVersion: v1metadata: name: replace-user-id annotations: pv-name-created: replace-user-idspec: storageClassName: alicloud-nas-flex accessModes: - ReadWriteMany resources: requests: storage: 5Gi—apiVersion: v1kind: Podmetadata: name: “nas-pod"spec: containers: - name: “nginx” image: “nginx” volumeMounts: - name: pvc-nas mountPath: “/data” volumes: - name: pvc-nas persistentVolumeClaim: claimName: replace-user-id # userID=“pod-123”# cat pod.yaml | sed “s/replace-user-id/"$userID"/g” | kubectl create -f -# kubectl get pod | grep podnas-pod 1/1 Running 0 32s# kubectl get pvc | grep podpod-123 Bound pod-123 5Gi RWX alicloud-nas-flex 44s# kubectl get pv | grep podpod-123 5Gi RWX Delete Bound default/pod-123 alicloud-nas-flex 48s# ls -l | grep poddrwxrwxrwx 2 root root 4096 2月 19 10:54 pod-123本文作者:kanjunbao阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 20, 2019 · 3 min · jiezi

Kubernetes的共享GPU集群调度

问题背景全球主要的容器集群服务厂商的Kubernetes服务都提供了Nvidia GPU容器调度能力,但是通常都是将一个GPU卡分配给一个容器。这可以实现比较好的隔离性,确保使用GPU的应用不会被其他应用影响;对于深度学习模型训练的场景非常适合,但是如果对于模型开发和模型预测的场景就会比较浪费。 大家的诉求是能够让更多的预测服务共享同一个GPU卡上,进而提高集群中Nvidia GPU的利用率。而这就需要提供GPU资源的划分,而这里GPU资源划分的维度指的就是GPU显存和Cuda Kernel线程的划分。通常在集群级别谈支持共享GPU,通常是两件事情:1.调度 2.隔离,我们这里主要讨论的是调度,隔离的方案未来会基于Nvidia的MPS来实现。而对于细粒度的GPU卡调度,目前Kubernetes社区并没有很好的方案,这是由于Kubernetes对于GPU这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用Pod A占用半张GPU卡,这在目前Kubernetes的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡GPU共享是实际矢量资源问题,而Extened Resource是标量资源的描述。针对此问题,我们设计了一个outoftree的共享GPU调度方案,该方案依赖于Kubernetes的现有工作机制:Extended Resource定义Scheduler Extender机制Device Plugin机制用户场景作为集群管理员,我想提高集群的GPU使用率;在开发过程中,多个用户共享模型开发环境作为应用开发人员,我希望能够同时在Volta GPU上运行多个推理任务目标能够让使用者通过API描述对于一个可共享资源的申请, 并能实现该种资源的调度非目标不支持该共享资源的隔离不支持超卖设计原则明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个GPU上,他们可以接受从应用级别控制显存的大小,利用类似gpu_options.per_process_gpu_memory_fraction控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。不做侵入式修改本设计中不会修改Kubernetes核心的Extended Resource的设计, Scheduler的实现,Device Plugin的机制以及Kubelet的相关设计。重用Extended Resource描述共享资源的申请API。这样的好处在于提供一个可以移植的方案,用户可以在原生Kubernetes上使用这个方案。按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。详细设计前提:依旧延用Kubernetes Extended Resource定义,但是衡量维度最小单位从1个GPU卡变为GPU显存的MiB。如果所节点使用的GPU为单卡16GiB显存,它对应的资源就是16276MiB由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡而我们的工作首先是定义了两个新的Extended Resource: 第一个是gpu-mem, 对应的是GPU显存;第二个是gpu-count,对应的是GPU卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享GPU的工作机制。下面是基本的架构图:核心功能模块:GPU Share Scheduler Extender: 利用Kubernetes的调度器扩展机制,负责在全局调度器Filter和Bind的时候判断节点上单个GPU卡是否能够提供足够的GPU Mem,并且在Bind的时刻将GPU的分配结果通过annotation记录到Pod Spec以供后续Filter检查分配结果。GPU Share Device Plugin: 利用Device Plugin机制,在节点上被Kubelet调用负责GPU卡的分配,依赖scheduler Extender分配结果执行。具体流程:1. 资源上报GPU Share Device Plugin利用nvml库查询到GPU卡的数量和每张GPU卡的显存, 通过ListAndWatch()将节点的GPU总显存(数量 显存)作为另外Extended Resource汇报给Kubelet; Kubelet进一步汇报给Kubernetes API Server。 举例说明,如果节点含有两块GPU卡,并且每块卡包含16276MiB,从用户的角度来看:该节点的GPU资源为16276 2 = 32552; 同时也会将节点上的GPU卡数量2作为另外一个Extended Resource上报。2. 扩展调度GPU Share Scheduler Extender可以在分配gpu-mem给Pod的同时将分配信息以annotation的形式保留在Pod spec中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的gpu-mem分配。2.1 Kubernetes默认调度器在进行完所有过滤(filter)行为后会通过http方式调用GPU Share Scheduler Extender的filter方法, 这是由于默认调度器计算Extended Resource时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由GPU Share Scheduler Extender检查单张卡上是否含有可用资源。以下图为例, 在由3个包含两块GPU卡的节点组成的Kubernetes集群中,当用户申请gpu-mem=8138时,默认调度器会扫描所有节点,发现N1所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1节点被过滤掉。 而N2和N3节点所剩资源都为8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托GPU Share Scheduler Extender进行二次过滤,在二次过滤中,GPU Share Scheduler Extender需要判断单张卡是否满足调度需求,在查看N2节点时发现该节点虽然有8138MiB可用资源,但是落到每张卡上看,GPU0和分别GPU1只有4069MiB的可用资源,无法满足单卡8138MiB的诉求。而N3节点虽然也是总共有8138MiB可用资源,但是这些可用资源都属于GPU0,满足单卡可调度的需求。由此,通过GPU Share Scheduler Extender的筛选就可以实现精准的条件筛选。2.2 当调度器找到满足条件的节点,就会委托GPU Share Scheduler Extender的bind方法进行节点和Pod的绑定,这里Extender需要做的是两件事情以binpack的规则找到节点中最优选择的GPU卡id,此处的最优含义是对于同一个节点不同的GPU卡,以binpack的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的GPU卡,并且将其作为ALIYUN_COM_GPU_MEM_IDX保存到Pod的annotation中;同时也保存该Pod申请的GPU Memory作为ALIYUN_COM_GPU_MEM_POD和ALIYUN_COM_GPU_MEM_ASSUME_TIME保存至Pod的annotation中,并且在此时进行Pod和所选节点的绑定。注意:这时还会保存ALIYUN_COM_GPU_MEM_ASSIGNED的Pod annotation,它被初始化为“false”。它表示该Pod在调度时刻被指定到了某块GPU卡,但是并没有真正在节点上创建该Pod。ALIYUN_COM_GPU_MEM_ASSUME_TIME代表了指定时间。如果此时发现分配节点上没有GPU资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在assume超时后重新调度。调用Kubernetes API执行节点和Pod的绑定以下图为例,当GPU Share Scheduler Extender要把gpu-mem:8138的Pod和经过筛选出来的节点N1绑定,首先会比较不同GPU的可用资源,分别为GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中GPU2所剩资源不满足需求,被舍弃掉;而另外三个满足条件的GPU中, GPU1恰恰是符合空闲资源满足条件但同时又是所剩资源最少的GPU卡,因此GPU1被选出。3. 节点上运行当Pod和节点绑定的事件被Kubelet接收到后,Kubelet就会在节点上创建真正的Pod实体,在这个过程中, Kubelet会调用GPU Share Device Plugin的Allocate方法, Allocate方法的参数是Pod申请的gpu-mem。而在Allocate方法中,会根据GPU Share Scheduler Extender的调度决策运行对应的Pod3.1 会列出该节点中所有状态为Pending并且ALIYUN_COM_GPU_MEM_ASSIGNED为false的GPU Share Pod3.2 选择出其中Pod Annotation的ALIYUN_COM_GPU_MEM_POD的数量与Allocate申请数量一致的Pod。如果有多个符合这种条件的Pod,就会选择其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的Pod。3.3 将该Pod的annotation ALIYUN_COM_GPU_MEM_ASSIGNED设置为true,并且将Pod annotation中的GPU信息转化为环境变量返回给Kubelet用以真正的创建Pod。相关项目目前项目已经开源到github.com上gpushare-scheduler-extendergpushare-device-plugin部署请参照部署文档测试样例1. 首先创建一个使用aliyun.com/gpu-mem的应用apiVersion: apps/v1kind: Deploymentmetadata: name: binpack-1 labels: app: binpack-1spec: replicas: 1 selector: # define how the deployment finds the pods it manages matchLabels: app: binpack-1 template: # define the pods specifications metadata: labels: app: binpack-1 spec: containers: - name: binpack-1 image: cheyang/gpu-player:v2 resources: limits: # MiB aliyun.com/gpu-mem: 1024使用请参照使用文档构建请参照如何构建视频DemoDemo 1: 部署多个GPU Share的Pod,发现他们以binpack的方式被放置到同一个GPU卡上视频地址:http://cloud.video.taobao.com…Demo 2:避免错误调度申请资源超过单个GPU可用资源的Pod视频地址:http://cloud.video.taobao.com…Roadmap利用nvidia MPS实现隔离支持该方案可以在由kubeadm初始化的Kubernetes集群自动化部署Scheduler Extener的高可用性为GPU, RDMA 和弹性网卡提供通用方案本文作者:必嘫阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 19, 2019 · 1 min · jiezi

超长干货 | Kubernetes命名空间详解

K8s使用命名空间的概念帮助解决集群中在管理对象时的复杂性问题。在本文中,会讨论命名空间的工作原理,介绍常用实例,并分享如何使用命名空间来管理K8s对象。最后,介绍名为projects的Rancher特性是如何构建并扩展命名空间的概念的。本文中,我们将探索Kubernetes命名空间,它是集群中组织和管理对象的一种方式。介 绍Kubernetes集群可以同时管理大量互不相关的工作负载,而组织通常会选择将不同团队创建的项目部署到共享集群上。随着数量的增加,部署对象常常很快就会变得难以管理,拖慢操作响应速度,并且会增加危险错误出现的概率。Kubernetes使用命名空间的概念帮助解决集群中在管理对象时的复杂性问题。命名空间允许将对象分组到一起,便于将它们作为一个单元进行筛选和控制。无论是应用自定义的访问控制策略,还是为了测试环境而分离所有组件,命名空间都是一个按照组来处理对象、强大且灵活的概念。在本文中,我们会讨论命名空间的工作原理,介绍一些常用实例,并分享如何使用命名空间来管理Kubernetes对象。最后,我们还会介绍一个叫做projects(项目)的Rancher特性,看它是如何构建并扩展命名空间的概念的。什么是命名空间,为什么它很重要?命名空间(namespace)是Kubernetes提供的组织机制,用于给集群中的任何对象组进行分类、筛选和管理。每一个添加到Kubernetes集群的工作负载必须放在一个命名空间中。命名空间为集群中的对象名称赋予作用域。虽然在命名空间中名称必须是唯一的,但是相同的名称可以在不同的命名空间中使用。这对于某些场景来说可能帮助很大。例如,如果使用命名空间来划分应用程序生命周期环境(如开发、staging、生产),则可以在每个环境中维护利用同样的名称维护相同对象的副本。命名空间还可以让用户轻松地将策略应用到集群的具体部分。你可以通过定义ResourceQuota对象来控制资源的使用,该对象在每个命名空间的基础上设置了使用资源的限制。类似地,当在集群上使用支持网络策略的CNI(容器网络接口)时,比如Calico或Canal(calico用于策略,flannel用于网络)。你可以将NetworkPolicy应用到命名空间,其中的规则定义了pod之间如何彼此通信。不同的命名空间可以有不同的策略。使用命名空间最大的好处之一是能够利用Kubernetes RBAC(基于角色的访问控制)。RBAC允许您在单个名称下开发角色,这样将权限或功能列表分组。ClusterRole对象用于定义集群规模的使用模式,而角色对象类型(Role object type)应用于具体的命名空间,从而提供更好的控制和粒度。在角色创建后,RoleBinding可以将定义的功能授予单个命名空间上下文中的具体具体用户或用户组。通过这种方式,命名空间可以使得集群操作者能够将相同的策略映射到组织好的资源集合。常见的命名空间使用模式命名空间是一种非常灵活的特性,它不强制使用特定的结构或组织模式。不过尽管如此,还是有许多在团队内常使用的模式。将命名空间映射到团队或项目上在设置命名空间时有一个惯例是,为每个单独的项目或者团队创建一个命名空间。这和我们前面提到的许多命名空间的特性很好的结合在了一起。通过给团队提供专门的命名空间,你可以用RBAC策略委托某些功能来实现自我管理和自动化。比如从命名空间的RoleBinding对象中添加或删除成员就是对团队资源访问的一种简单方法。除此之外,给团队和项目设置资源配额也非常有用。有了这种方式,你可以根据组织的业务需求和优先级合理地访问资源。使用命名空间对生命周期环境进行分区命名空间非常适合在集群中划分开发、staging以及生产环境。通常情况下我们会被建议将生产工作负载部署到一个完全独立的集群中,来确保最大程度的隔离。不过对于较小的团队和项目来说,命名空间会是一个可行的解决方案。和前面的用例一样,网络策略、RBAC策略以及配额是实现用例的重要因素。在管理环境时,通过将网络隔离来控制和组件之间的通信能力是很有必要的。同样,命名空间范围的RBAC策略允许运维人员为生产环节设置严格的权限。配额能够确保对最敏感环境的重要资源的访问。重新使用对象名称的能力在这里很有帮助。在测试和发布对象时,可以把它们放到新环境中,同时保留其命名空间。这样可以避免因为环境中出现相似的对象而产生的混淆,并且减少认知开销。使用命名空间隔离不同的使用者另一个命名空间可以解决的用例是根据使用者对工作负载进行分段。比如,如果你的集群为多个客户提供基础设施,那么按命名空间进行分段就能够实现管理每个客户,同时跟踪账单的去向。另外,命名空间的特性可以让你控制网络和访问策略,为你的使用者定义不同的配额。在通用的情况下,命名空间允许你为每个用户开发和部署相同模板化环境的不同实例。这种一致性可以大大简化管理和故障诊断的过程。理解预配置的Kubernetes命名空间在我们进行创建命名空间之前,先讨论一下Kubernetes是如何自动设置它的。在默认情况下,新的集群上有三个命名空间:default:向集群中添加对象而不提供命名空间,这样它会被放入默认的命名空间中。在创建替代的命名空间之前,该命名空间会充当用户新添加资源的主要目的地,无法删除。kube-public:kube-public命名空间的目的是让所有具有或不具有身份验证的用户都能全局可读。这对于公开bootstrap组件所需的集群信息非常有用。它主要是由Kubernetes自己管理。kube-system:kube-system命名空间用于Kubernetes管理的Kubernetes组件,一般规则是,避免向该命名空间添加普通的工作负载。它一般由系统直接管理,因此具有相对宽松的策略。虽然这些命名空间有效地将用户工作负载与系统管理的工作负载隔离,但它们并不强制使用任何额外的结构对应用程序进行分类和管理。比较友好的是,创建和使用额外的命名空间非常简单使用命名空间使用kubectl管理命名空间及其包含的资源相当简单。在这一节中,我们将演示一些最常见的命名空间操作,便于你开始有效地分割资源。查看现有的命名空间要显示集群中可用的所有命名空间,使用kubectl get namespaces命令:该命令显示了所有可用的命名空间,无论它们是否是活跃的。此外还有资源的时长(age)。如果想获得更详细的信息,使用kubectl describe命令:Name: default Labels: field.cattle.io/projectId=p-cmn9g Annotations: cattle.io/status={“Conditions”:[{“Type”:“ResourceQuotaInit”,“Status”:“True”,“Message”:"",“LastUpdateTime”:“2018-12-17T23:17:48Z”},{“Type”:“InitialRolesPopulated”,“Status”:“True”,“Message”:"",“LastUpda… field.cattle.io/projectId=c-7tf7d:p-cmn9g lifecycle.cattle.io/create.namespace-auth=trueStatus: ActiveNo resource quota.No resource limits.该命令用于显示与命名空间关联的标签和注释,以及已经应用了的所有配额或资源限制。创建命名空间我们使用kubectl create namespace命令来创建命名空间。用命名空间的名称作为该命令的参数。你还可以通过文件,使用manifest来创建命名空间。例如,下面的文件定义了我们和上面一模一样的命名空间。假设上面的规范保存在demo-namespace.yml文件中。你可以输入指令来使用它:无论我们采用哪种方法创建命名空间,在我们再次检查可用命名空间时,应该能列出新的命名空间(我们使用ns——命名空间的缩写,第二次进行查询):我们新创建的命名空间已经变为可使用。根据命名空间筛选和执行操作如果我们将一个工作负载对象部署到集群而不指定命名空间,它将被添加到默认命名空间:我们可以使用kubectl来验证部署是否创建在默认的命名空间:如果我们尝试再次使用相同的名称创建部署,会得到命名空间冲突的错误。要将操作应用于不同的命名空间,我们必须在命令中包含—namespace=这一选项。下面我们在demo-namespace命名空间上创建具有相同名称的部署:这次部署成功了,尽管我们仍然使用的是相同的部署名称。命名空间为资源名称提供了不同的作用域,避免了前面所经历的命名冲突。如果想查看新部署的详细信息,我们再次使用—namespace=选项指定命名空间:这说明我们已经在demo-namespace命名空间创建了另一个名为demo-nginx的部署。通过设置Context选择命名空间如果希望避免为每个命令提供同样的命名空间,可以通过配置kubectl的context来改变命令作用的默认命名空间。这会修改操作在context活跃时应用到的命名空间。列出context配置的细节,输入:上图说明我们使用了一个名为Default的context,context没有指定命名空间,因此使用了默认命名空间。想要将该context使用的命名空间修改成demo-context,我们输入:我们可以在此查看context配置来验证当前是否选择了demo-namespace:验证我们的kubectl describe命令现在默认使用demo-namespace,它会请求我们的demo-nginx部署而不需要指定命名空间:删除命名空间并清理如果不需要命名空间了,我们可以删除它。删除命名空间这一功能非常强大,因为它不仅删除命名空间,还会清理其中部署了的所有资源。这一功能非常方便,但是同时如果你一不小心,也会非常危险。在删除之前,最好列出和命名空间相关的资源,确定想要删除的对象:一旦确定了要操作的范围,可以输入下面的命令删除demo-namespace命名空间和其中的所有资源:命名空间及其资源将从集群中删除如果你之前在kubectl上下文中更改了所选的命名空间,那么输入下面的命令清除所选的命名空间:在清理demo资源时,请记住删除我们最初提供给默认命名空间的原始demo-nginx部署:现在你的集群应该处于一开始的状态了。使用Rancher的Project扩展命名空间如果你使用Rancher来管理Kubernetes集群,那么你就可以使用projects特性提供的扩展功能。Rancher里的Project是一个额外的组织层,用于将多个命名空间绑定在一起。Rancher的project在命名空间上覆盖了一个控制结构,允许你将命名空间分组成逻辑单元并对其应用相应的策略。Project在大多数情况下反映了命名空间,但它是作为命名空间的容器而不是单独的工作负载资源。Rancher中的每个命名空间只存在于一个project中,命名空间继承应用于该项目的所有策略。在默认情况下,Rancher集群定义了两个project:Default:该project包含了默认命名空间System:该project包含所有其他预配置的命名空间,包括kube-public、kube-system和系统提供的所有命名空间在选择了集群之后,你可以通过访问Projects/Namespaces选项卡来查看集群中可用的项目:在这里,单击Add Project按钮来添加project。在新建project时,你可以配置project成员及其访问权限,还可以配置安全策略和资源配额。你还可以点击project的Add Namespace按钮向现有的项目添加命名空间。如果要将命名空间移动到不同的project上,请先选择命名空间,单击Move按钮。将命名空间移动到新project中的开关会立即修改应用于该命名空间的权限和策略。Rancher的project没有引入新的组织模型,而是简单地将相同的抽象应用到了命名空间上,而命名空间作用于工作负载对象。如果你喜欢使用命名空间,但是又需要额外的控制层的话,那么它们就能够填补这一使用上的空白。总 结在本文中,我们介绍了Kubernetes命名空间的概念以及它们是如何帮助管理集群资源的。我们讨论了集群中命名空间是如何为资源名称分段和分作用域的,以及在命名空间层面应用的策略如何影响用户权限和资源分配。之后,我们介绍了团队用命名空间将集群分段成逻辑块的一些常用模式,描述了Kubernetes预配置的命名空间及其用途。然后,我们还了解了如何在集群中创建和使用命名空间。最后,我们还介绍了Rancher项目以及它们是如何通过对命名空间本身进行分组来扩展命名空间的。命名空间是一个非常简单又重要的概念,可以帮助团队管理集群资源并且降低复杂性。花一些时间熟悉它们的优点和特性可以帮助你有效地配置集群,避免将来遇到麻烦。

February 19, 2019 · 1 min · jiezi

如何在Rancher 2.2 Preview2上部署和管理多K8s集群应用

Rancher 2.2 Preview2于近日全面发布,这一版本包含了许多K8S集群操作的强大特性。本文将详细介绍多集群应用这一特性,让您可以在短时间内更新集群,大大提升工作效率。近日,全球领先的容器管理软件供应商Rancher Labs宣布,其旗舰产品Rancher——开源的企业级Kubernetes管理平台——最新版本Rancher 2.2 Preview 2全面发布,这一版本包含了许多在K8S集群操作的强大特性。您可以通过访问发布页面(https://rancher.com/products/…) 和发布说明(https://github.com/rancher/ra…) 来了解所发布的新功能。本文将介绍其中一个特性:多集群应用(multi-cluster applications),下面将为您介绍,该特性将如何显著减少您的工作量,并提高多集群操作的可靠性。概 览假如您有用过k8s,并且有两个及以上的集群运维经验,那么您遇到下面的情况:当跨多个可用区部署(AZs)时,应用需要具有更高的容错性;在具有数百个集群的边缘计算场景中,同一个应用需要在多个集群上运行。在高可靠性的情况下,运维操作人员通常通过将节点从多个可用区纳入到一个集群内来降低单个可用区不可用风险。但是这个方案的问题在于,虽然抵抗了可用区故障,但是防不住集群本身故障,集群故障的可能性高于可用区故障,而且一旦集群出故障后,可能会影响集群中在运行的程序。另外一种方法是,每个可用区中运行单独的集群,病症每个集群上运行应用程序的副本。相当于每个可用区都有一套k8s集群,但是每个集群手动维护应用程序成本高,又易错。边缘计算场景跟多可用区集群相同的问题:应用程序手动维护,既耗时,又容易出错,即使运维团队给力,创建了复杂的脚本来部署和升级,但是又多了一个故障点,而且这些脚本也需要升级和维护,并且要求负责的运维人员不仅要编写流程(升级发版流程),还要在脚本失败时能够转成人肉运维。从Rancher 2.2 Preview 2 (https://github.com/rancher/ra… ) 开始,Rancher支持在任意数量的k8s集群中同时部署和升级同一应用程序的副本。同时也扩展了基于Helm软件包管理器的应用商店(Application Catalogs),在此之前,应用商店仅适用于单个集群,我们在全局级别增加了一个附加功能,权限允许的情况下,可以将应用程序部署到Rancher管理的任意集群上。有关Rancher 2.2 Preview2的功能的完整演示,请保持关注,我们将在3月推出全新一季的在线培训,届时将提供新功能的演示,并在Q&A环节进行答疑。下面将演示,在Rancher中如何便捷的管理多集群应用。功能快速入门登陆Rancher后,将看到纳管的所有集群的列表,同时在菜单栏新增了一个【多集群应用(Multi-Cluster Apps)】 的按钮单击 多集群应用 按钮后,将看到两个按钮,【管理Catalogs】和【启动】。【管理Catalogs】将跳到【应用商店(Catalogs) 】的管理页,您开源在其中启用主要Helm repo或者添加其他第三方Helm repo。单击【启动】按钮以启动新应用程序。从显示的可以部署的应用中,选择Grafana(用于演示)。按照要求配置详细信息,使用表单或者直接用提供YAML进行配置。注意,在此处的设置将应用到部署此应用程序的集群中。在【配置选项】下,在【Target(目标) 】下拉框中选择目标集群的指定项目。选择升级策略。此处为了演示,我们将选择【滚动更新】并提供每批1个,间隔20秒。此设置可以确保以后升级应用时,一次只更新一个集群,并且每个集群升级操作的间隔为20秒。如果要调整集群间的差异,可以在【Answer Overrides】部分进行设置。一切准备妥当,点击底部【启动】,然后将跳到结果页,显示刚刚已安装的多集群应用(此处是演示用的Grafana)。每个应用将显示当前状态和目标集群以及项目列表。当应用程序可以升级时,应用状态将显示【Upgrade Available】。要启动升级,请单击应用上的菜单按钮(三个点的菜单),然后选择升级。验证是否已选择【滚动更新】选项。更改一些设置,然后点击底部的【升级】按钮。打开目标集群的【工作负载】选项卡,将看到其中一个状态更改为更新 ,此集群中的应用将被更新,然后Rancher将暂停20s(刚刚设置的间隔时间),然后继续更新下一个集群的应用。总 结多集群应用程序将减少运维团队的工作量,并使跨集群快速可靠的部署和升级应用成为可能。要在实验室或者开发环境中测试这些功能,请安装最新的Alpha版本(https://rancher.com/docs/ranc… ) ,如果有任何反馈意见,请在Github上提交Issues 或者加入论坛(https://forums.rancher.com/)...://slack.rancher.io/) 。

February 18, 2019 · 1 min · jiezi

Why Kubernetes ,我所理解的docker与k8s

去年换工作后,开始真正在生产环境中接触容器与Kubernetes。边恶补相关知识的同时,也想把学到的内容和自己的理解整理出来。学习的途径包括k8s官方文档、书籍、极客时间专栏及网上各种博文。所涉及一些摘抄或描述,大多用自己的理解来组织语言,也就不一一注明出处了。Kubernetes(简称K8S)与容器技术,可以说是近几年最火热的技术之一。提起K8S,大家都知道是google开源的容器编排工具。今天想先谈谈,我理解的容器、K8S是什么,以及为什么它们能火起来。Why Docker既然说K8S是一个容器编排的工具,那么要搞清楚K8S是什么,首先得搞清楚,容器是什么,以及为什么要用容器技术。形象的来说,一个linux容器,实际就是一个进程,还是个被系统欺骗的进程。为什么这么说呢?一个运行在容器里的进程,主要有以下特点:它被宿主机操作系统隔离了,它看不到宿主机上的其他进程,以为自己就是pid为1的进程它被宿主机操作系统限制了硬件资源,它能使用的cpu、内存等硬件资源只是宿主机的一部分在被宿主机操作系统限制了存储空间,让这个进程认为宿主机的某个目录就是系统根目录这几个欺骗进程的技术,就是是容器技术的三板斧,用于资源隔离的namespace,用于资源限制的cgroup,以及用于伪装进程根目录的rootfs。这三种技术,都是是早已存在于linux中的,只是docker公司比较创新的把这三种技术整合在一起,并且,提出了容器镜像及镜像仓库等概念,把这个进程及相关的依赖环境都一起打包成可分发及重复使用的镜像文件,方便容器能在不同机器之间移植。这样,在任何地方,只要能运行docker,就能把容器镜像跑成一个包含这应用进程及相关依赖环境的容器实例。这里用利用K8S官方文档的图,简单说下生产中的场景,看看容器技术能解决什么问题。左图是传统的物理机部署应用方式的方式,可以看到除了一个应用的运行,除了程序本身,离不开应用配置、库、等等依赖环境。通常情况下,一个应用的上线,要经历开发环境、pre环境、beta环境、灰度测试、生产环境等等不同的基础环境。开发的同学在开发环境跑通了代码,到其他环境运行时,由于各环境依赖、配置、安全需求不同,可能会出现各种问题。运维的同学忙着在不同的环境中统一依赖。不同应用各种语言,各种应用的特殊依赖需求,也造成了CI/CD逻辑复杂,难以统一。右图是用了容器技术之后的场景。一个容器镜像的实质就是程序进程加所有运行时环境及配置、依赖的集合。只要各个环境的底层能兼容docker,就能实现所有环境部署的一致性。开发同学不用关心生产环境和开发环境的差异可能会导致应用运行问题,运维同学部署一个应用,只要确保容器镜像能正常运行就好。CI/CD的自动化也相对容易实现很多。从而极大增加开发效率、应用迭代效率及节省了运维工作量。说到这里,不得不说下容器与传统意义的虚拟机间的对比。其实二者都可以理解为虚拟化,它们最本质的区别是,容器是操作系统层级的虚拟化,而虚拟机是硬件层级的虚拟化。参看下图。由于虚拟机多了一层Guest OS,需要宿主机额外的性能开销进行硬件虚拟化,同时因为是完整的操作系统,虚拟机镜像一般动辄大几G,很难在各环境间快速传播,hypervisor层相对Docker Engine也比较重。再看docker容器,实质就是宿主机上跑的一个进程,只不过通过docker与其他进程隔离开来。简单的说,敏捷和高效,是容器相比虚拟机最大的优势,当然也有劣势,由于容器只是操作系统级别的隔离,不同容器间隔离的不够彻底。Why Kubernetes简单说完了docker的理解,那么Kubernetes又是什么,它解决了哪些问题呢,为啥现在提容器技术必提k8s呢。这里再谈谈我理解的Why K8S。回到实际的场景来,假如你已经开始用docker镜像来打包应用,可以方便的进行分发和部署,不用去考虑不同环境的差异。但是不是还感觉还少了点什么?因为正常的实际业务系统,不是应用能部署,能运行起来就完事了,还要考虑应用容器的访问、水平伸缩、监控、安全、备份、容灾等等因素。而对于一个完整的业务系统来说,也不是单个应用就能搞定的,还要考虑的是各应用间的关系,及应用运行的形态。比如一个web业务,可能需要web服务器、缓存系统、数据库等多个应用。容器化部署后,它们可能部署在不同宿主机的不同容器中,相互间的访问要怎么实现,这就涉及到容器间访问关系的处理。再比如,有个优化缓存的应用也跑在容器里,只需要定期运行容器实例执行优化任务,执行完毕就终止容器,这就需要处理不同容器应用的运行形态问题。类似上述这些对容器应用及容器间关系进行管理,就是所谓的容器编排及调度。而Kubernetes,就是目前的容器编排的平台的事实标准了。那么,具体来说,K8S到底能做哪些事呢。在官方文档中,对K8S功能的描述如下Kubernetes 满足了生产中运行应用程序的许多常见的需求,例如:Pod提供了一种复合的应用容器模型,挂载外部存储,Secret管理,应用健康检查,副本应用实例,横向自动扩缩容,服务发现,负载均衡,滚动更新,资源监测,日志采集和存储,支持自检和调试,认证和鉴权.从这些功能介绍可以看出,K8S已很类似一个云平台了,可以完全能满足生产级别的容器应用管理需求。下面是一张最简单的K8S系统示意图:K8S集群由一个主节点(master节点)及多个工作节点(node节点)构成,开发者提交应用容器镜像,并将镜像运行的数量、方法等通过描述文件提交给K8S master节点,K8S master节点或根据集群整体情况,将应用按照需求部署在工作节点中。对于开发者来说,利用K8S可以方便的部署程序,不用关心基础设施,而对于运维人员来说,工作重心从维护具体应用,转变为维护K8S集群。而且,不管是开发者还是运维人员,都不用关心应用具体部署在哪个节点,K8S会自动判断搞定一切。相比于传统的应用部署方式,有没有觉得K8S很棒棒?在容器编排这个概念出现的时候,Kubernetes并不是唯一的一个容器编排工具,主流的工具还有Docker公司原生的swarm和Apache基金会的mesos,为什么K8S能笑到最后,成为容器编排的事实标准呢?我理解K8S对比它们有两个最大不同点:(这里不对swarm和mesos做详细介绍了,实际也确实没怎么玩过)K8S对容器又做了一层抽象,也就是POD。不同于与其他两个工具,K8S管理的原子对象,其实并不是容器,而是POD。按照官方文档的定义,一个POD,是由一个或多个共享存储及网络的容器,以及描述怎么运行这些容器的集合,所以,POD实际是一个抽象的概念。k8s对容器的所有操作,比如动态伸缩、监控等,实际上都是对pod的管理。那这层抽象的好处是什么呢?上面有提到过,容器实质就是被特殊处理的进程。想像一个web业务,web应用进程输出的日志需要被大数据agent进程处理。这个业务如果想容器化,通常有两个做法。一是分别起来两个容器,挂载宿主机同一个目录来存放日志。另一种是起一个操作系统级别的容器或supervisord容器作为enterpoint,来管理web服务和agent进程。前一种方式,这个两个容器就被框在这台宿主机上了,要实现业务实例横向扩缩容,要考虑两个容器的运行情况和存储挂载,逻辑比较复杂。后一种方式,你要为每个容器再额外开一个supervisord进程,更重要的是,由于entrypoint是supervisord进程,web应用和大数据agent对docker来说,都是不可见的。即使nginx出错频繁重启,只要supervisord还活着,Docker就认为这个容器是正常的。我们再来看看,使用了pod这个概念以后,有什么变化。一个pod里面同时起了web服务进程和大数据agent两个容器实例,首先,pod里的容器实例是共享存储和网络namespace的,也就是说,这两进程的存储数据是直接共享的,不需要额外的挂载动作。其次,这个pod是作为一个整体被k8s管理着的,k8s会监控pod里每个容器的状态,并根据策略在有问题时进行自动干预。从这个意义上说,pod才更类似传统的虚拟机。声明式API第二点也是比较重要的方面,是K8S的声明式api(貌似swarm的新版也支持了,同样没玩过就不细说了)。什么是声明式API呢,可以参考上面系统图中的描述文件。比如要我需要集群中跑10个web服务容器,传统的命令式API是一步步调用命令构建出容器。而使用声明式api,只要告诉K8S我要10个web容器,K8S就会自动将web集群实例数维持在10个,并且,在某个pod出问题退出时,K8S会自动重新拉起新pod,使集群始终保持10个pod实例在跑。这就使得管理集群变得很简单,只要通过配置文件描述出希望的集群状态,而不用去关注中间的实现过程。最后,总结一下:Why Dokcer: 用容器技术跑应用,相比原来的物理机及虚拟机更高效、轻量、省资源,同时大大方便了不同环境下的应用部署及分发。Why Kubernetes:生产集群光跑容器还不够,还要对容器应用作为一个业务系统集群进行编排及管理,而K8S的一些优势使得它成为目前容器集群编排管理工具的事实标准。最后的最后再多提一点,实际上,容器技术不止Docker公司一家在做,Kubernetes也不是只能管理Docker容器。只是,无论从市场份额、应用性还是开发社区的热度来说,它们都是目前容器技术最主流的解决方案,就生产环境来说,目前基本没有必要去考虑其他的容器技术了。

February 18, 2019 · 1 min · jiezi

SAP云平台对Kubernetes的支持

截至本文发稿(2019-2-10, 农历大年初六)时为止,访问SAP云平台的官方网站:https://cloudplatform.sap.com…能看到下面的网页:SAP云平台上的Kubernetes环境,Coming Soon(即将推出)Build powerful container-native applications and deploy them on a cloud or infrastructure of your choice without worrying about the creation and management of the underlying container clusters.我来翻译一下:SAP云平台的Kubernetes编程环境能让编程人员开发功能强大的容器原生应用并顺利部署在云上,而不用担心底层容器集群的创建和管理。为什么SAP云平台要选择支持Kubernetes?Containers are rapidly becoming a popular development paradigm for cloud-native applications in the industry – with Kubernetes as the dominant container orchestrations technology. The SAP Cloud Platform Kubernetes environment reduces pain points associated with the creation and management of Kubernetes clusters by offering an easy to use, secure and open standards-based Cluster-as-a-Service running on top of a variety of underlying infrastructure choices, deployment options of cloud vs. on-premise, etc. SAP is making this innovation accessible to the entire developer community via an open-source project called Gardener.SAP给出的答案是:基于Kubernetes的容器编排技术近年来已经成为行业里最流行的云原生应用开发范式之一。SAP云平台的Kubernetes编程环境提供了一种简易,安全,基于业界标准的方式提供了对Kubernetes集群的创建和管理,这种方式基于Cluster-as-a-Service(集群即服务)的方式运作,能运行在多种底层云技术设施上,解决了开发人员需要花大量时间学习Kubernetes底层细节的痛点。这种Cluster-as-a-Service的服务,SAP通过开源项目Gardener提供访问:https://gardener.cloud/更多Gardener的使用方式和截图,请参考我的文章:站在巨人肩膀上的牛顿:Kubernetes和SAP Kymahttps://www.jianshu.com/p/c85…使用SAP云平台的Kubernetes编程环境能享受哪些收益Customers can rely upon the SAP Cloud Platform to create, manage, secure and maintain the container clusters for them.客户可以直接使用SAP云平台创建和管理容器集群Leverage the Gardener open-source project to easily access a variety of community innovations.借助Gardener这个开源项目享受到开源社区的种种创新Use container-native development to build and operate complex, stateful cloud applications that require greater freedom over underlying infrastructure.通常情况下开发复杂的云原生应用和有状态的云应用,需要对底层云的基础设施具有很高的自由度。而SAP云平台通过Gardener提供的Cluster-as-a-Service, 给使用者提供了这种自由度。要获取更多Jerry的原创文章,请关注公众号"汪子熙": ...

February 14, 2019 · 1 min · jiezi

为Envoy v2构建Kubernetes Edge(Ingress)控制平面

作者:Daniel Bryant,Datawire产品架构师;Flynn,Datawire Ambassador首席开发者;Richard Li,Datawire首席执行官兼联合创始人Kubernetes已经成为基于容器的微服务应用程序的事实上的运行引擎,但是这个编排框架本身并不提供运行分布式系统所需的所有基础结构。微服务通常通过第7层协议,如HTTP、gRPC或WebSockets,进行通信,因此能够制定路由决策,操作协议元数据,以及在此层进行观察至关重要。然而,传统的负载平衡器和边缘代理主要关注L3/4流量。这就是Envoy Proxy发挥作用的地方。Envoy代理由Lyft工程团队从头开始设计为通用数据平面,用于当今分布式,以L7为中心的世界,广泛支持L7协议,用于管理其配置的实时API,一流的可观察性,在小内存空间内实现高性能。然而,Envoy庞大的功能集和操作灵活性也使其配置非常复杂 - 从查看其丰富但冗长的控制平面语法可以看出这一点。通过开源Ambassador API网关,我们想要解决创建新控制平面的挑战,该控制平面侧重于在Kubernetes集群中部署Envoy作为前向边缘代理的用例,采用Kubernetes operator惯用的方式。在本文中,我们将介绍Ambassador设计的两个主要迭代,以及我们如何将Ambassador与Kubernetes相结合。2019年之前的Ambassador:Envoy v1 API、Jinja模板文件和热重启Ambassador本身作为Kubernetes服务部署在容器中,使用添加到Kubernetes Services的注释作为其核心配置模型。此方法使应用程序开发者能够将路由作为Kubernetes服务定义的一部分进行管理。由于当前Ingress API规范的限制,我们明确决定采用这种方式,我们也喜欢扩展Kubernetes服务的简单性,而不是引入另一种自定义资源类型。这里可以看到Ambassador注释的一个例子:kind: ServiceapiVersion: v1metadata: name: my-service annotations: getambassador.io/config: | — apiVersion: ambassador/v0 kind: Mapping name: my_service_mapping prefix: /my-service/ service: my-servicespec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376将这个简单的Ambassador注释配置转换为有效的Envoy v1配置并不是一项简单的任务。按照设计,Ambassador的配置不是基于与Envoy配置相同的概念模型 - 我们故意想要聚合和简化操作和配置。因此,将一组概念转换为另一组概念涉及Ambassador内部的相当多的逻辑。在Ambassador的第一次迭代中,我们创建了一个基于Python的服务,该服务监视Kubernetes API以更改Service对象。当检测到新的或更新的Ambassador注释时,这些注释从Ambassador语法转换为中间表示(intermediate representation,IR),其体现了我们的核心配置模型和概念。接下来,Ambassador将此IR转换为Envoy配置,该配置在运行的Ambassador k8s服务相关联的pod中被保存为文件。Ambassador然后“热重启”在Ambassador pod内运行的Envoy进程,这引发了新配置的加载。这个初始实现有很多好处。所涉及的机制基本上很简单,将Ambassador配置转换为Envoy配置是可靠的,Envoy基于文件的热重启集成是可靠的。但是,这一版本的Ambassador也面临着显着的挑战。首先,虽然热启动对我们大多数客户的用例有效,但速度并不快,一些客户(特别是那些具有大量应用程序部署的客户)发现它限制了更改配置的频率。热重启也可以丢弃连接,尤其是长期连接,如WebSockets或gRPC流。但更重要的是,IR的第一次实施允许快速原型设计,但有点原始,事实证明很难做出实质性的改变。虽然从一开始就是一个痛点,但当Envoy转向Envoy v2 API时,它成了一个关键问题。显然,v2 API将为Ambassador提供许多好处 - 正如Matt Klein在他的博客文章中概述的“通用数据平面API” - 包括访问新功能和上述连接丢弃问题的解决方案,但同时明确表示现有的IR实施无法实现跨越式发展。Ambassador >= v0.50:Envoy v2 API(ADS)、使用KAT测试和Golang在与Ambassador社区协商后,Datawire团队在2018年对Ambassador内部进行了重新设计。这是由两个关键目标驱动的。首先,我们希望集成Envoy的v2配置格式,这将支持SNI、速率限制和gRPC身份验证API等功能。其次,我们还希望对Envoy配置进行更强大的语义验证,因为它的复杂性越来越高(特别是在大规模应用程序部署时)。初始阶段我们首先通过多通道编译器对Ambassador内部进行重组。类层次结构是为了更密切地反映Ambassador配置资源、IR和Envoy配置资源之间的关注点分离(separation of concerns)。Ambassador的核心部分也进行了重新设计,以促进Datawire以外社区的贡献。我们决定采用这种方法有几个原因。首先,Envoy Proxy是一个非常快速发展的项目,我们意识到我们需要一种方法,即看似微小的Envoy配置变更不会导致Ambassador内部的重新设计。此外,我们希望能够提供配置的语义验证。当我们开始与Envoy v2更紧密地合作时,很快就发现了测试挑战。随着Ambassador支持越来越多的功能,Ambassador处理不太常见但完全有效的功能组合时出现了越来越多的漏洞。这促使创建一个新的测试要求,这意味着Ambassador的测试套件需要重新设计,以自动管理许多功能组合,而不是依靠人手单独编写每个测试。此外,我们希望测试套件快速,以最大限度地提高工程效率。因此,作为Ambassador重构的一部分,我们引入了Kubernetes验收测试(KAT)框架。KAT是一个可扩展的测试框架:将一堆服务(与Ambassador一起)部署到Kubernetes集群针对启动的API运行一系列验证查询对这些查询结果执行一堆认定KAT专为性能而设计 - 它预先批量测试设置,然后在步骤3中与高性能客户端异步运行所有查询。KAT中的流量驱动程序使用Telepresence在本地运行,这使得调试问题变得更加容易。将Golang引入Ambassador堆栈随着KAT测试框架到位,我们很快遇到了Envoy v2配置和热重启的一些问题,这提供了切换到使用Envoy的聚合发现服务(ADS)API而不是热重启的机会。这完全消除了重新配置更改的要求,我们发现这可能导致在高负载或长期连接下断开连接。然而,当我们考虑转向ADS时,我们遇到了一个有趣的问题。ADS并不像人们想象的那么简单:在向Envoy发送更新时存在明确的排序依赖性。Envoy项目具有排序逻辑的参考实现,但仅限于Go和Java,而Ambassador主要使用Python。我们挣扎了一点,决定最简单的方法是接受我们世界的多语言性质,并使用Go来实施我们的ADS。我们还发现,在KAT的情况下,我们的测试已经达到了Python在许多网络连接中的性能受到限制的程度,因此我们在这里利用Go,主要使用Go编写KAT的查询和后端服务。毕竟,当你已经投入采取了Golang,另一个依赖是什么?通过新的测试框架、新的IR生成有效的Envoy v2配置和ADS,我们认为我们完成了0.50Ambassador的主要体系结构更改。唉,我们又遇到了一个问题。在Azure Kubernetes服务上,不再检测到Ambassador注释更改。与高度响应的AKS工程团队合作,我们能够确定问题 - 在AKS中的Kubernetes API服务器通过一系列代理公开,要求客户端更新,以了解如何使用API的FQDN连接服务器,这是通过AKS中的变异webhook提供。不幸的是,官方Kubernetes Python客户端没有对此功能的支持,所以这是我们选择切换到Go而不是Python的第三个原因。这提出了一个有趣的问题,“为什么不放弃所有的Python代码,只是完全用Go重写Ambassador?”这是一个有效的问题。重写的主要问题是Ambassador和Envoy在不同的概念层面上运作,而不是简单地用不同的语法表达相同的概念。确信我们已经用新语言表达了概念桥梁并不是一个微不足道的挑战,如果没有真正优秀的测试覆盖范围就无法实行。在这一点上,我们使用Go覆盖非常具体、包含良好的函数,可以更容易地验证它们的正确性,以便我们可以验证完整的Golang重写。在将来,谁知道?但是对于0.50.0,这个功能分坼让我们既利用Golang的优势,又让我们对已经在0.50的所有变化保持更多信心。得到的教训我们在建立Ambassador 0.50的过程中学到了很多东西。我们的一些关键要点:Kubernetes和Envoy是非常强大的框架,但它们也是极其快速移动的目标 - 有时候无法替代阅读源代码并与维护者交谈(幸运的是,所有人都非常容易访问!)Kubernetes/Envoy生态系统中最受支持的库是用Go编写的。虽然我们喜欢Python,但我们不得不采用Go,这样我们就不会被迫自己维护太多的组件。有时需要重新设计测试工具来推动软件的发展。重新设计测试工具的实际成本通常是将旧测试移植到新的线束实现中。为边缘代理用例设计(和实现)一个有效的控制平台一直是一个挑战,来自Kubernetes、Envoy和Ambassador的开源社区的反馈非常有用。将Ambassador迁移到Envoy v2配置和ADS API是一个漫长而艰难的过程,需要大量的架构和设计讨论,以及大量编码,但结果的早期反馈是积极的。Ambassador 0.50现已发布,因此你可以使用参加测试,并在我们的Slack频道或Twitter上与社区分享你的反馈。KubeCon + CloudNativeCon中国论坛提案征集(CFP)2月22日截止KubeCon + CloudNativeCon 论坛让用户、开发人员、从业人员汇聚一堂,面对面进行交流合作。与会人员有 Kubernetes、Prometheus 及其他云原生计算基金会 (CNCF) 主办项目的领导,和我们一同探讨云原生生态系统发展方向。Open Source Summit中国提案征集(CFP)2月22日截止在Open Source Summit中国,与会者将共同合作及共享信息,了解最新和最有趣的开源技术,包括Linux、IoT、区块链、AI、网络等;并获得如何在开源社区中导向和引领的信息。大会日期:提案征集截止日期:太平洋标准时间 2 月 22 日,星期五,晚上 11:59提案征集通知日期:2019 年 4 月 8 日会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日提醒:这是一场社区会议。因此,让我们尽量避开公然推销产品和/或供应商销售宣传。KubeCon + CloudNativeCon和Open Source Summit赞助方案出炉KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国 ...

February 14, 2019 · 1 min · jiezi

CNCF案例研究:蚂蚁金服

蚂蚁金服利用Kubernetes的高速增长策略公司:蚂蚁金服地点:中国杭州行业:金融服务挑战蚂蚁金服于2014年10月正式成立,源自2004年推出的全球最大的在线支付平台支付宝。该公司还利用技术创新提供众多其他服务。随着支付宝处理其全球9亿多用户(通过其本地和全球合作伙伴)的交易量 - 在2017年双十一的高峰期每秒256,000笔交易,以及2018年双十一的总商品价值310亿美元 - 更不用说其他服务,蚂蚁金服面临着“全新的数据处理挑战”,负责存储和计算产品管理的Haojie Hang说。“我们看到了在这种规模下运营的三个主要问题:如何提供实时计算、存储和处理能力,例如为欺诈检测提供实时建议;如何在这些数据之上提供智能,因为数据太多,我们没有获得足够的洞察力;以及如何在应用程序级别,中间件级别,系统级别甚至芯片级别提供安全性。”为了向其客户提供可靠和一致的服务,蚂蚁金服在2014年初拥抱了容器,很快就需要为数据中心的数万个节点集群提供一个编排解决方案。解决方法在调查了几项技术后,该团队选择了Kubernetes作容器编排,以及其他一些CNCF项目,包括Prometheus、OpenTracing、etcd和CoreDNS。“2016年底,我们认为Kubernetes将成为事实上的标准,”Haojie说。“回顾过去,我们在合适的技术上做出了正确的选择。但是,我们需要将生产工作量从遗留基础设施转移到最新的Kubernetes平台,这需要一些时间,因为我们在可靠性和一致性方面非常谨慎。”所有核心财务系统都在2017年11月容器化,正在迁移到Kubernetes。影响“我们已经看到使用云原生技术在运营方面至少提高了十倍,这意味着你的产出可以增加十倍,”Haojie说。蚂蚁也为全球的业务合作伙伴提供完全集成的金融云平台,希望通过在服务创新和技术专业知识方面的丰富经验为下一代数字银行提供支持。Haojie表示,该团队还没有开始关注优化Kubernetes平台:“因为我们还处于超高速增长阶段,我们还没有采用节约成本的模式。”“2016年底,我们认为Kubernetes将成为事实上的标准。回顾过去,我们在合适的技术上做出了正确的选择。” - Haojie Hang,产品管理,蚂蚁金服作为跨国集团阿里巴巴的分拆公司,蚂蚁金服拥有1500亿美元的估值以及相匹配的规模。该金融科技创业公司于2014年成立,由全球最大的在线支付平台支付宝以及利用技术创新的众多其他服务组成。 支付宝为全球超过9亿用户(通过其本地和全球合作伙伴)处理的交易量惊人:2017年双11高峰期每秒256,000次,2018年双11总商品价值310亿美元。蚂蚁金服以“为世界带来更多平等的机会”为使命,致力于通过技术创新创建开放、共享的信用体系和金融服务平台。再加上其他业务的运营 - 如花呗在线信贷系统、借呗贷款服务以及3.5亿用户的蚂蚁森林绿色能源移动应用程序 - 蚂蚁金服面临着“全新的数据处理挑战”,负责存储和计算产品管理的Haojie Hang说。“我们看到了在这种规模下运营的三个主要问题:如何提供实时计算、存储和处理能力,例如为欺诈检测提供实时建议;如何在这些数据之上提供智能,因为数据太多,我们没有获得足够的洞察力;以及如何在应用程序级别,中间件级别,系统级别甚至芯片级别提供安全性。”为了应对这些挑战,为其客户提供可靠和一致的服务,蚂蚁金服在2014年采用了Docker容器化。但他们很快意识到需要为公司数据中心的数万个节点集群提供编排解决方案。“在今年的双11上,我们有很多节点运行Kubernetes,但与基础设施的整体规模相比,这仍然在进行中。” - Ranger Yu,全球技术合作伙伴关系与发展,蚂蚁金服该团队研究了几种技术,包括Docker Swarm和Mesos。“我们做了很多POC,但我们在生产系统方面非常谨慎,因为我们希望确保不会丢失任何数据。”Haojie说。“你不能让服务停工一分钟,甚至一秒钟也会产生非常非常大的影响。我们每天都在为中国和全球的消费者和企业提供可靠、一致的服务的前提下运营。”最终,Haojie说蚂蚁选择了Kubernetes,因为它满足了所有需求方框:一个强大的社区、“将在未来三到五年内是相关的技术”,以及与公司工程人才的良好匹配。“2016年底,我们认为Kubernetes将成为事实上的标准。”Haojie说。“回顾过去,我们在合适的技术上做出了正确的选择。但是,我们需要将生产工作量从遗留基础设施转移到最新的Kubernetes平台。我们花了很多时间学习,然后培训我们的员工在Kubernetes上很好地构建应用程序。”所有核心财务系统都在2017年11月进行了容器化,正在迁移到Kubernetes。蚂蚁的平台还利用了许多其他CNCF项目,包括Prometheus、OpenTracing、etcd和CoreDNS。“在今年的双11,我们有很多节点运行Kubernetes,但与基础设施的整体规模相比,这仍然在进行中。”全球技术合作伙伴关系与发展的Ranger Yu说。“我们非常感谢CNCF和这项令人惊叹的技术,这是我们在全球不断扩展所需要的。我们肯定会在未来更拥抱社区和开源。” - Haojie Hang,产品管理,蚂蚁金服这已经产生了影响。“云原生技术使我们在效率方面受益匪浅。”Haojie说。“总的来说,我们希望确保我们的基础设施敏捷和灵活,足以应对明天可能发生的工作。这就是目标。借助云原生技术,我们已经看到运营改进至少十倍,这意味着您可以将产出提高十倍。假设您正在一个人操作10个节点。使用云原生,明天你可以有100个节点。”蚂蚁也为世界各地的合作伙伴提供其金融云平台,希望通过在服务创新和技术专业知识方面的丰富经验为下一代数字银行提供支持。Haojie说团队还没有开始专注于优化Kubernetes平台,“因为我们还处于超高速增长阶段,我们还没有采用节约成本的模式。”在蚂蚁金服迁移到云原生期间,CNCF社区也是一项宝贵的资产。“如果你正在应用一项新技术,那么有一个社区与其他用户讨论技术问题是非常好的。”Haojie说。“我们非常感谢CNCF和这项令人惊叹的技术,这是我们在全球不断扩展所需要的。我们肯定会在未来更拥抱社区和开源。”“在中国,我们是金融和其他相关服务创新方面的北极星。我们肯定希望通过我们对技术的投资,确保在未来5到10年内保持领先地位。” - Haojie Hang,产品管理,蚂蚁金服事实上,该公司已经开始开源一些云原生中间件。“我们将非常积极主动,”Ranger说。“CNCF提供了一个平台,让每个人都可以加入或贡献组件。这是非常好的开源治理。”展望未来,蚂蚁团队将继续评估许多其他CNCF项目。该团队在中国建立了服务网络社区,汇集了许多中国公司和开发者,共同探讨该技术的潜力。“对于中国开发者和最终用户来说,服务网络非常吸引,因为我们现在有很多遗留系统在运行,它是一个理想的中间层,可以将所有内容粘合在一起,包括新旧系统。”Haojie说。“对于新技术,我们会密切关注它们是否会持久。”在蚂蚁,Kubernetes以优异的成绩通过了测试,团队希望其他公司也会效仿。“在中国,我们是金融和其他相关服务创新方面的北极星。”Haojie说。“我们肯定希望通过我们对技术的投资,确保在未来5到10年内保持领先地位。”KubeCon + CloudNativeCon中国论坛提案征集(CFP)2月22日截止KubeCon + CloudNativeCon 论坛让用户、开发人员、从业人员汇聚一堂,面对面进行交流合作。与会人员有 Kubernetes、Prometheus 及其他云原生计算基金会 (CNCF) 主办项目的领导,和我们一同探讨云原生生态系统发展方向。Open Source Summit中国提案征集(CFP)2月22日截止在Open Source Summit中国,与会者将共同合作及共享信息,了解最新和最有趣的开源技术,包括Linux、IoT、区块链、AI、网络等;并获得如何在开源社区中导向和引领的信息。大会日期:提案征集截止日期:太平洋标准时间 2 月 22 日,星期五,晚上 11:59提案征集通知日期:2019 年 4 月 8 日会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日提醒:这是一场社区会议。因此,让我们尽量避开公然推销产品和/或供应商销售宣传。KubeCon + CloudNativeCon和Open Source Summit赞助方案出炉KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国 ...

February 14, 2019 · 1 min · jiezi

革命性新特性 | 单一应用跨多Kubernetes集群的部署与管理

近日,全球领先的容器管理软件供应商Rancher Labs宣布,其旗舰产品Rancher——开源的企业级Kubernetes管理平台——全面发布的最新版本Rancher 2.2 Preview 2中,正式支持多集群应用程序。Rancher 至此成为业界首个支持多集群应用程序的平台,为用户提供了业界领先的多集群和边缘计算环境的可靠性、安全性和可用性。“Rancher 使Kubernetes 的部署和管理变得轻松。多年来,我们不断增加新的功能,比如 RBAC、Project和开箱即用的监控等等,使Rancher越来越简单易用,”Rancher联合创始人及工程副总裁 Will Chan表示:“随着组织内用户和集群数量的增长,比如在边缘计算场景中,跨集群的应用和服务的部署、管理、升级变得异常困难。用户希望既能满足企业日益增长的需求,又能降低使用Kubernetes的复杂性。现在,Rancher对多集群应用程序的支持,正是用户所急需的。”传统做法一般云基础设施有多个可用区,可用区之间保证高可用。想要让一个应用完全高可用,就需要让应用部署在不同的可用区上,这样一来,一个可用区失败,另一个可用区可以顶替使用。对于那些有高可用需求的应用程序而言,想要确保可靠性,它们必须被部署到多个不同的集群。过去的实现方法,便是将节点从其他可用区拉入同一集群。但是,如果集群失败了,应用程序将变得不可用。在多个集群中同时部署、管理和升级应用程序Rancher 对多集群应用程序的支持,通过允许用户选择应用程序和目标集群、提供特定的集群数据、随后启动对这些集群的部署,而创造性地解决了上述问题。这对业界而言,是向前迈出的重要一步。“我们的 AI 解决方案 B-Yond INFINITY运行在电信环境中的 Kubernetes 上。出于可用性原因,必须支持多集群部署。”B-yond 首席产品官 Rikard Kjellberg说:“应用程序的多集群部署,大大有利于生命周期管理,并满足我们在5G边缘云中发现的新兴的边缘部署的趋势与需求。”使用 Rancher 2.2,我们现在可以将IT流程完全自动化,并将其与我们的生命周期管理过程集成,减少耗时,降低风险,同时保持符合电信级要求。——B-yond 首席产品官 Rikard Kjellberg多集群的 Kubernetes 应用程序支持扩展了 Kubernetes包管理器Helm 的强大功能集。用户只需从 Rancher Catalog 中选择应用程序,添加目标集群,提供关于每个集群的信息,然后进行部署即可。多集群应用程序使用运行在Rancher管理平台上的 Kubernetes controller来获取Helm chart,并会将应用程序部署到每个目标集群。通过Helm chart,Rancher 将可以实现应用程序的升级、回滚和版本控制等功能。产品更新Rancher 2.2.0-alpha6及以后的版本中都将包含多集群应用程序功能,以下载相应版本体验与使用:https://github.com/rancher/ra…在将于本季度晚些时候正式发布的Rancher 2.2中,多集群应用程序功能将GA。您可以提交GitHub issue或扫描本文下方二维码加入Rancher微信技术讨论群,为我们提供更多的意见与反馈❤️后续我们会发布更多多集群应用程序相关的技术教程文章,敬请保持关注哟~

February 14, 2019 · 1 min · jiezi

k8s与HPA--通过 Prometheus adaptor 来自定义监控指标

k8s与HPA–通过 Prometheus adaptor 来自定义监控指标自动扩展是一种根据资源使用情况自动扩展或缩小工作负载的方法。 Kubernetes中的自动缩放有两个维度:Cluster Autoscaler处理节点扩展操作,Horizontal Pod Autoscaler自动扩展部署或副本集中的pod数量。 Cluster Autoscaling与Horizontal Pod Autoscaler一起用于动态调整计算能力以及系统满足SLA所需的并行度。虽然Cluster Autoscaler高度依赖托管您的集群的云提供商的基础功能,但HPA可以独立于您的IaaS / PaaS提供商运营。Horizontal Pod Autoscaler功能最初是在Kubernetes v1.1中引入的,并且从那时起已经发展了很多。 HPA缩放容器的版本1基于观察到的CPU利用率,后来基于内存使用情况。在Kubernetes 1.6中,引入了一个新的API Custom Metrics API,使HPA能够访问任意指标。 Kubernetes 1.7引入了聚合层,允许第三方应用程序通过将自己注册为API附加组件来扩展Kubernetes API。 Custom Metrics API和聚合层使Prometheus等监控系统可以向HPA控制器公开特定于应用程序的指标。Horizontal Pod Autoscaler实现为一个控制循环,定期查询Resource Metrics API以获取CPU /内存等核心指标和针对特定应用程序指标的Custom Metrics API。以下是为Kubernetes 1.9或更高版本配置HPA v2的分步指南。您将安装提供核心指标的Metrics Server附加组件,然后您将使用演示应用程序根据CPU和内存使用情况展示pod自动扩展。在本指南的第二部分中,您将部署Prometheus和自定义API服务器。您将使用聚合器层注册自定义API服务器,然后使用演示应用程序提供的自定义指标配置HPA。在开始之前,您需要安装Go 1.8或更高版本并在GOPATH中克隆k8s-prom-hpa repo。cd $GOPATHgit clone https://github.com/stefanprodan/k8s-prom-hpa部署 Metrics Serverkubernetes Metrics Server是资源使用数据的集群范围聚合器,是Heapster的后继者。度量服务器通过汇集来自kubernetes.summary_api的数据来收集节点和pod的CPU和内存使用情况。摘要API是一种内存高效的API,用于将数据从Kubelet / cAdvisor传递到度量服务器。在HPA的第一个版本中,您需要Heapster来提供CPU和内存指标,在HPA v2和Kubernetes 1.8中,只有在启用horizontal-pod-autoscaler-use-rest-clients时才需要指标服务器。默认情况下,Kubernetes 1.9中启用了HPA rest客户端。 GKE 1.9附带预安装的Metrics Server。在kube-system命名空间中部署Metrics Server:kubectl create -f ./metrics-server一分钟后,度量服务器开始报告节点和pod的CPU和内存使用情况。查看nodes metrics:kubectl get –raw “/apis/metrics.k8s.io/v1beta1/nodes” | jq .结果如下:{ “kind”: “NodeMetricsList”, “apiVersion”: “metrics.k8s.io/v1beta1”, “metadata”: { “selfLink”: “/apis/metrics.k8s.io/v1beta1/nodes” }, “items”: [ { “metadata”: { “name”: “ip-10-1-50-61.ec2.internal”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/nodes/ip-10-1-50-61.ec2.internal”, “creationTimestamp”: “2019-02-13T08:34:05Z” }, “timestamp”: “2019-02-13T08:33:38Z”, “window”: “30s”, “usage”: { “cpu”: “78322168n”, “memory”: “563180Ki” } }, { “metadata”: { “name”: “ip-10-1-57-40.ec2.internal”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/nodes/ip-10-1-57-40.ec2.internal”, “creationTimestamp”: “2019-02-13T08:34:05Z” }, “timestamp”: “2019-02-13T08:33:42Z”, “window”: “30s”, “usage”: { “cpu”: “48926263n”, “memory”: “554472Ki” } }, { “metadata”: { “name”: “ip-10-1-62-29.ec2.internal”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/nodes/ip-10-1-62-29.ec2.internal”, “creationTimestamp”: “2019-02-13T08:34:05Z” }, “timestamp”: “2019-02-13T08:33:36Z”, “window”: “30s”, “usage”: { “cpu”: “36700681n”, “memory”: “326088Ki” } } ]}查看pods metrics:kubectl get –raw “/apis/metrics.k8s.io/v1beta1/pods” | jq .结果如下:{ “kind”: “PodMetricsList”, “apiVersion”: “metrics.k8s.io/v1beta1”, “metadata”: { “selfLink”: “/apis/metrics.k8s.io/v1beta1/pods” }, “items”: [ { “metadata”: { “name”: “kube-proxy-77nt2”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube-proxy-77nt2”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:00Z”, “window”: “30s”, “containers”: [ { “name”: “kube-proxy”, “usage”: { “cpu”: “2370555n”, “memory”: “13184Ki” } } ] }, { “metadata”: { “name”: “cluster-autoscaler-n2xsl”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/cluster-autoscaler-n2xsl”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:12Z”, “window”: “30s”, “containers”: [ { “name”: “cluster-autoscaler”, “usage”: { “cpu”: “1477997n”, “memory”: “54584Ki” } } ] }, { “metadata”: { “name”: “core-dns-autoscaler-b4785d4d7-j64xd”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/core-dns-autoscaler-b4785d4d7-j64xd”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:08Z”, “window”: “30s”, “containers”: [ { “name”: “autoscaler”, “usage”: { “cpu”: “191293n”, “memory”: “7956Ki” } } ] }, { “metadata”: { “name”: “spot-interrupt-handler-8t2xk”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/spot-interrupt-handler-8t2xk”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:04Z”, “window”: “30s”, “containers”: [ { “name”: “spot-interrupt-handler”, “usage”: { “cpu”: “844907n”, “memory”: “4608Ki” } } ] }, { “metadata”: { “name”: “kube-proxy-t5kqm”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube-proxy-t5kqm”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:08Z”, “window”: “30s”, “containers”: [ { “name”: “kube-proxy”, “usage”: { “cpu”: “1194766n”, “memory”: “12204Ki” } } ] }, { “metadata”: { “name”: “kube-proxy-zxmqb”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube-proxy-zxmqb”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:06Z”, “window”: “30s”, “containers”: [ { “name”: “kube-proxy”, “usage”: { “cpu”: “3021117n”, “memory”: “13628Ki” } } ] }, { “metadata”: { “name”: “aws-node-rcz5c”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/aws-node-rcz5c”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:15Z”, “window”: “30s”, “containers”: [ { “name”: “aws-node”, “usage”: { “cpu”: “1217989n”, “memory”: “24976Ki” } } ] }, { “metadata”: { “name”: “aws-node-z2qxs”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/aws-node-z2qxs”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:15Z”, “window”: “30s”, “containers”: [ { “name”: “aws-node”, “usage”: { “cpu”: “1025780n”, “memory”: “46424Ki” } } ] }, { “metadata”: { “name”: “php-apache-899d75b96-8ppk4”, “namespace”: “default”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/php-apache-899d75b96-8ppk4”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:08Z”, “window”: “30s”, “containers”: [ { “name”: “php-apache”, “usage”: { “cpu”: “24612n”, “memory”: “27556Ki” } } ] }, { “metadata”: { “name”: “load-generator-779c5f458c-9sglg”, “namespace”: “default”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/load-generator-779c5f458c-9sglg”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:34:56Z”, “window”: “30s”, “containers”: [ { “name”: “load-generator”, “usage”: { “cpu”: “0”, “memory”: “336Ki” } } ] }, { “metadata”: { “name”: “aws-node-v9jxs”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/aws-node-v9jxs”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:00Z”, “window”: “30s”, “containers”: [ { “name”: “aws-node”, “usage”: { “cpu”: “1303458n”, “memory”: “28020Ki” } } ] }, { “metadata”: { “name”: “kube2iam-m2ktt”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube2iam-m2ktt”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:11Z”, “window”: “30s”, “containers”: [ { “name”: “kube2iam”, “usage”: { “cpu”: “1328864n”, “memory”: “9724Ki” } } ] }, { “metadata”: { “name”: “kube2iam-w9cqf”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube2iam-w9cqf”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:03Z”, “window”: “30s”, “containers”: [ { “name”: “kube2iam”, “usage”: { “cpu”: “1294379n”, “memory”: “8812Ki” } } ] }, { “metadata”: { “name”: “custom-metrics-apiserver-657644489c-pk8rb”, “namespace”: “monitoring”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/monitoring/pods/custom-metrics-apiserver-657644489c-pk8rb”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:04Z”, “window”: “30s”, “containers”: [ { “name”: “custom-metrics-apiserver”, “usage”: { “cpu”: “22409370n”, “memory”: “42468Ki” } } ] }, { “metadata”: { “name”: “kube2iam-qghgt”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube2iam-qghgt”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:11Z”, “window”: “30s”, “containers”: [ { “name”: “kube2iam”, “usage”: { “cpu”: “2078992n”, “memory”: “16356Ki” } } ] }, { “metadata”: { “name”: “spot-interrupt-handler-ps745”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/spot-interrupt-handler-ps745”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:10Z”, “window”: “30s”, “containers”: [ { “name”: “spot-interrupt-handler”, “usage”: { “cpu”: “611566n”, “memory”: “4336Ki” } } ] }, { “metadata”: { “name”: “coredns-68fb7946fb-2xnpp”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/coredns-68fb7946fb-2xnpp”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:12Z”, “window”: “30s”, “containers”: [ { “name”: “coredns”, “usage”: { “cpu”: “1610381n”, “memory”: “10480Ki” } } ] }, { “metadata”: { “name”: “coredns-68fb7946fb-9ctjf”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/coredns-68fb7946fb-9ctjf”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:13Z”, “window”: “30s”, “containers”: [ { “name”: “coredns”, “usage”: { “cpu”: “1418850n”, “memory”: “9852Ki” } } ] }, { “metadata”: { “name”: “prometheus-7d4f6d4454-v4fnd”, “namespace”: “monitoring”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/monitoring/pods/prometheus-7d4f6d4454-v4fnd”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:00Z”, “window”: “30s”, “containers”: [ { “name”: “prometheus”, “usage”: { “cpu”: “17951807n”, “memory”: “202316Ki” } } ] }, { “metadata”: { “name”: “metrics-server-7cdd54ccb4-k2x7m”, “namespace”: “kube-system”, “selfLink”: “/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/metrics-server-7cdd54ccb4-k2x7m”, “creationTimestamp”: “2019-02-13T08:35:19Z” }, “timestamp”: “2019-02-13T08:35:04Z”, “window”: “30s”, “containers”: [ { “name”: “metrics-server-nanny”, “usage”: { “cpu”: “144656n”, “memory”: “5716Ki” } }, { “name”: “metrics-server”, “usage”: { “cpu”: “568327n”, “memory”: “16268Ki” } } ] } ]}基于CPU和内存使用情况的Auto Scaling您将使用基于Golang的小型Web应用程序来测试Horizontal Pod Autoscaler(HPA)。将podinfo部署到默认命名空间:kubectl create -f ./podinfo/podinfo-svc.yaml,./podinfo/podinfo-dep.yaml使用NodePort服务访问podinfo,地址为http:// <K8S_PUBLIC_IP>:31198。接下来定义一个至少维护两个副本的HPA,如果CPU平均值超过80%或内存超过200Mi,则最多可扩展到10个:apiVersion: autoscaling/v2beta1kind: HorizontalPodAutoscalermetadata: name: podinfospec: scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: podinfo minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu targetAverageUtilization: 80 - type: Resource resource: name: memory targetAverageValue: 200Mi创建这个hpa:kubectl create -f ./podinfo/podinfo-hpa.yaml几秒钟后,HPA控制器联系度量服务器,然后获取CPU和内存使用情况:kubectl get hpaNAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEpodinfo Deployment/podinfo 2826240 / 200Mi, 15% / 80% 2 10 2 5m为了增加CPU使用率,请使用rakyll / hey运行负载测试:#install heygo get -u github.com/rakyll/hey#do 10K requestshey -n 10000 -q 10 -c 5 http://<K8S_PUBLIC_IP>:31198/您可以使用以下方式监控HPA事件:$ kubectl describe hpaEvents: Type Reason Age From Message —- —— —- —- ——- Normal SuccessfulRescale 7m horizontal-pod-autoscaler New size: 4; reason: cpu resource utilization (percentage of request) above target Normal SuccessfulRescale 3m horizontal-pod-autoscaler New size: 8; reason: cpu resource utilization (percentage of request) above target 暂时删除podinfo。稍后将在本教程中再次部署它:kubectl delete -f ./podinfo/podinfo-hpa.yaml,./podinfo/podinfo-dep.yaml,./podinfo/podinfo-svc.yaml部署 Custom Metrics Server要根据自定义指标进行扩展,您需要拥有两个组件。一个组件,用于从应用程序收集指标并将其存储在Prometheus时间序列数据库中。第二个组件使用collect(k8s-prometheus-adapter)提供的指标扩展了Kubernetes自定义指标API。您将在专用命名空间中部署Prometheus和适配器。创建monitoring命名空间:kubectl create -f ./namespaces.yaml在monitoring命名空间中部署Prometheus v2:kubectl create -f ./prometheus生成Prometheus适配器所需的TLS证书:make certs生成以下几个文件:# ls outputapiserver.csr apiserver-key.pem apiserver.pem部署Prometheus自定义指标API适配器:kubectl create -f ./custom-metrics-api列出Prometheus提供的自定义指标:kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta1” | jq .获取monitoring命名空间中所有pod的FS使用情况:kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods//fs_usage_bytes” | jq .查询结果如下:{ “kind”: “MetricValueList”, “apiVersion”: “custom.metrics.k8s.io/v1beta1”, “metadata”: { “selfLink”: “/apis/custom.metrics.k8s.io/v1beta1/namespaces/monitoring/pods/%2A/fs_usage_bytes” }, “items”: [ { “describedObject”: { “kind”: “Pod”, “namespace”: “monitoring”, “name”: “custom-metrics-apiserver-657644489c-pk8rb”, “apiVersion”: “/v1” }, “metricName”: “fs_usage_bytes”, “timestamp”: “2019-02-13T08:52:30Z”, “value”: “94253056” }, { “describedObject”: { “kind”: “Pod”, “namespace”: “monitoring”, “name”: “prometheus-7d4f6d4454-v4fnd”, “apiVersion”: “/v1” }, “metricName”: “fs_usage_bytes”, “timestamp”: “2019-02-13T08:52:30Z”, “value”: “24576” } ]}基于custom metrics 自动伸缩在默认命名空间中创建podinfo NodePort服务和部署:kubectl create -f ./podinfo/podinfo-svc.yaml,./podinfo/podinfo-dep.yamlpodinfo应用程序公开名为http_requests_total的自定义指标。 Prometheus适配器删除_total后缀并将度量标记为计数器度量标准。从自定义指标API获取每秒的总请求数:kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods//http_requests” | jq .{ “kind”: “MetricValueList”, “apiVersion”: “custom.metrics.k8s.io/v1beta1”, “metadata”: { “selfLink”: “/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/http_requests” }, “items”: [ { “describedObject”: { “kind”: “Pod”, “namespace”: “default”, “name”: “podinfo-6b86c8ccc9-kv5g9”, “apiVersion”: “/__internal” }, “metricName”: “http_requests”, “timestamp”: “2018-01-10T16:49:07Z”, “value”: “901m” }, { “describedObject”: { “kind”: “Pod”, “namespace”: “default”, “name”: “podinfo-6b86c8ccc9-nm7bl”, “apiVersion”: “/__internal” }, “metricName”: “http_requests”, “timestamp”: “2018-01-10T16:49:07Z”, “value”: “898m” } ]}建一个HPA,如果请求数超过每秒10个,将扩展podinfo部署:apiVersion: autoscaling/v2beta1kind: HorizontalPodAutoscalermetadata: name: podinfospec: scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: podinfo minReplicas: 2 maxReplicas: 10 metrics: - type: Pods pods: metricName: http_requests targetAverageValue: 10 在默认命名空间中部署podinfo HPA:kubectl create -f ./podinfo/podinfo-hpa-custom.yaml几秒钟后,HPA从指标API获取http_requests值:kubectl get hpaNAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEpodinfo Deployment/podinfo 899m / 10 2 10 2 1m在podinfo服务上应用一些负载,每秒25个请求:#install heygo get -u github.com/rakyll/hey#do 10K requests rate limited at 25 QPShey -n 10000 -q 5 -c 5 http://<K8S-IP>:31198/healthz几分钟后,HPA开始扩展部署:kubectl describe hpaName: podinfoNamespace: defaultReference: Deployment/podinfoMetrics: ( current / target ) “http_requests” on pods: 9059m / 10Min replicas: 2Max replicas: 10Events: Type Reason Age From Message —- —— —- —- ——- Normal SuccessfulRescale 2m horizontal-pod-autoscaler New size: 3; reason: pods metric http_requests above target按照当前的每秒请求速率,部署永远不会达到10个pod的最大值。三个复制品足以使每个吊舱的RPS保持在10以下。负载测试完成后,HPA会将部署缩到其初始副本:Events: Type Reason Age From Message —- —— —- —- ——- Normal SuccessfulRescale 5m horizontal-pod-autoscaler New size: 3; reason: pods metric http_requests above target Normal SuccessfulRescale 21s horizontal-pod-autoscaler New size: 2; reason: All metrics below target您可能已经注意到自动缩放器不会立即对使用峰值做出反应。默认情况下,度量标准同步每30秒发生一次,只有在最后3-5分钟内没有重新缩放时才能进行扩展/缩小。通过这种方式,HPA可以防止快速执行冲突的决策,并为Cluster Autoscaler提供时间。结论并非所有系统都可以通过单独依赖CPU /内存使用指标来满足其SLA,大多数Web和移动后端需要基于每秒请求进行自动扩展以处理任何流量突发。对于ETL应用程序,可以通过作业队列长度超过某个阈值等来触发自动缩放。通过使用Prometheus检测应用程序并公开正确的自动缩放指标,您可以对应用程序进行微调,以更好地处理突发并确保高可用性。 ...

February 13, 2019 · 6 min · jiezi

CNCF案例研究:PingCAP

PingCAP将其TiDB数据库平台押注在云原生上公司:PingCAP地点:中国北京和加利福尼亚州圣马特奥行业:软件挑战流行的开源NewSQL数据库TiDB是由PingCAP公司领先开发。TiDB与MySQL兼容,可以处理混合事务和分析处理(HTAP)工作负载,并具有云原生架构设计。“拥有混合多云产品是我们全球市场战略的重要组成部分,”全球战略与运营总经理Kevin Xu说。为了实现这一目标,团队必须解决两个挑战:“如何在容器化的世界中部署、运行和管理分布式有状态应用程序,例如像TiDB这样的分布式数据库,”Kevin说,“如何交付给我们的客户,在云中使用TiDB,在任何云,无论是云供应商还是不同云环境的组合,都能为我们的客户提供易于使用,一致且可靠的体验。”了解使用分布式系统并非易事,他们开始寻找合适的编排层,以帮助减少最终用户的一些复杂性。解决方法该团队很早就开始关注Kubernetes的编排功能。“我们知道Kubernetes有希望帮助我们解决问题,”Kevin说。“我们只是在等待它成熟。”在2018年初,PingCAP开始将Kubernetes整合到其内部开发以及TiDB产品中。此时,该团队已经拥有使用其他云原生技术的经验,之前已将Prometheus和gRPC集成为TiDB平台的一部分。影响Kevin说,到目前为止,PingCAP客户对Kubernetes作为部署和管理TiDB的工具做出了非常积极的回应。客户部署TiDB时,默认情况下会安装带有Grafana作为仪表板的Prometheus,这样他们就可以在生产中部署TiDB之前和之后监控性能,并进行任何调整以达到目标。Kevin表示,监控层“使评估过程和沟通更加顺畅”。通过该公司基于Kubernetes的Operator实施(开源),客户现在能够在云中部署、运行、管理、升级和维护他们的TiDB集群,无需停机,减少了工作量、负担和开销。在内部,Kevin说,“我们已经完全转向Kubernetes进行自己的开发和测试,包括我们的数据中心基础设施和用于TiDB的自动化测试平台Schrodinger。使用Kubernetes,我们的资源使用率大大提高。我们的开发者可以自己分配和部署集群,部署过程从几小时降到几分钟,因此我们可以投入更少的人来管理IDC资源。生产率提高了大约15%,随着我们在Kubernetes的调试和诊断方面获得更多知识,生产率应提高到20%以上。”“我们知道Kubernetes有望帮助我们解决问题。我们只是在等待它成熟,使我们可以把它带到我们自己的开发和产品路线图。” - PingCAP全球战略和运营总经理Kevin Xu自2015年推出以来,开源的NewSQL数据库TiDB因其与MySQL的兼容性,处理混合事务和分析处理(HTAP)工作负载的能力及其云原生架构设计而获得了追随者。全球战略与运营总经理Kevin Xu表示,TiDB背后的公司PingCAP从第一天开始就包括云计算平台在设计中,“拥有混合多云产品是我们全球市场战略的重要组成部分。”为了实现这一目标,团队必须解决两个挑战:“如何在容器化的世界中部署、运行和管理分布式有状态应用程序,例如像TiDB这样的分布式数据库,”Kevin说,“如何交付给我们的客户,在云中使用TiDB,在任何云,无论是云供应商还是不同云环境的组合,都能为我们的客户提供易于使用,一致且可靠的体验。”知道使用分布式系统并不容易,PingCAP团队开始寻找合适的编排层,以帮助减少最终用户的一些复杂性。他们关注Kubernetes已经有很长一段时间了。“我们知道Kubernetes有望帮助我们解决问题,”Kevin说。“我们只是在等待它成熟。”“由于治理过程如此开放,不难发现技术和社区的最新发展是什么,或者如果我们遇到问题或问题,找出应该与谁联系。” - PingCAP全球战略和运营总经理Kevin Xu那段时间是在2018年初,当时PingCAP开始将Kubernetes整合到其内部开发以及TiDB产品中。“让Kubernetes成为CNCF的一部分,而不是只有一家公司的支持,于对技术的使用寿命带来信心,是有价值的,”Kevin说。此外,“由于治理流程如此开放,不难发现技术和社区的最新发展是什么,或者如果我们遇到问题或问题,找出可以与谁联系。”TiDB的云原生架构由无状态SQL层(也称为TiDB)和支持分布式事务的持久键值存储层(TiKV,现在是CNCF的沙箱项目)组成,它们松散耦合。“你可以根据你的计算和存储需求来伸缩扩展,这两个扩展过程可以相互独立地进行,”Kevin说。PingCAP团队还构建了基于Kubernetes的TiDB Operator,可以帮助在任何云环境中引导TiDB集群,并简化和自动化部署、扩展、调度、升级和维护。该公司最近还预览了其完全托管的TiDB云产品。“云原生基础设施不仅可以为你节省资金,让你可以更好地控制所消耗的基础架构资源,还可以为你的用户提供新产品创新、新体验和新业务可能性。它既能降低成本又能赚钱。” - PingCAP全球战略和运营总经理Kevin Xu整个TiDB平台利用Kubernetes和其他云原生技术,包括用于监控的Prometheus和用于服务间通信的gRPC。到目前为止,客户对支持Kubernetes的平台的反应非常积极。默认情况下,当客户部署TiDB时,Prometheus(以Grafana为仪表板)安装,以便他们在生产中部署TiDB之前可以监控,并进行任何调整以达到其性能的要求。Kevin表示,监控层“使评估过程和沟通更加顺畅”。通过该公司基于Kubernetes的Operator实施,客户现在能够在云中部署、运行、管理、升级和维护他们的TiDB集群,无需停机,减少工作量、负担和开销。这些技术在内部也产生了影响。“我们已经完全转向Kubernetes进行自己的开发和测试,包括我们的数据中心基础设施和用于TiDB的自动化测试平台Schrodinger,”Kevin说。“使用Kubernetes,我们的资源使用率大大提高。我们的开发者可以自己分配和部署集群,部署过程所需的时间更少,因此我们可以投入更少的人来管理IDC资源。”“整个云原生社区,无论是Kubernetes,CNCF,还是像我们这样的云原生供应商,都获得了足够的经验,并且有实战伤痕来证明,随时准备帮助你取得成功。” - PingCAP全球战略和运营总经理Kevin Xu生产率提高了大约15%,随着我们在Kubernetes的调试和诊断方面获得更多知识,生产率应提高到20%以上。“Kubernetes现在是PingCAP产品路线图的重要组成部分。对于其他任何考虑上云原生的人来说,Kevin有这样的建议:“没有比这更好的时机了,”他说。“整个云原生社区,无论是Kubernetes,CNCF,还是像我们这样的云原生供应商,都获得了足够的经验,并且有实战伤痕来证明,随时准备帮助你取得成功。”实际上,PingCAP团队已经看到越来越多的客户转向云原生方法,并且有充分的理由。“IT基础设施正在迅速从成本中心和事后的想法,发展到任何公司的核心能力和竞争力,”Kevin说。“云原生基础设施不仅可以为你节省资金,让你可以更好地控制所消耗的基础架构资源,还可以为你的用户提供新产品创新、新体验和新业务可能性。它既能降低成本又能赚钱。”TiDB Operator:KubeCon + CloudNativeCon中国论坛提案征集(CFP)2月22日截止KubeCon + CloudNativeCon 论坛让用户、开发人员、从业人员汇聚一堂,面对面进行交流合作。与会人员有 Kubernetes、Prometheus 及其他云原生计算基金会 (CNCF) 主办项目的领导,和我们一同探讨云原生生态系统发展方向。中国开源峰会提案征集(CFP)2月22日截止在中国开源峰会上,与会者将共同合作及共享信息,了解最新和最有趣的开源技术,包括Linux、IoT、区块链、AI、网络等;并获得如何在开源社区中导向和引领的信息。大会日期:提案征集截止日期:太平洋标准时间 2 月 22 日,星期五,晚上 11:59提案征集通知日期:2019 年 4 月 8 日会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日提醒:这是一场社区会议。因此,让我们尽量避开公然推销产品和/或供应商销售宣传。KubeCon + CloudNativeCon + Open Source Summit赞助方案出炉KubeCon + CloudNativeCon + Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon + Open Source Summit即将首次合体落地中国

February 13, 2019 · 1 min · jiezi