Jimmy Song's Blog

使用Jenkins进行持续构建与发布应用到kubernetes集群中

(题图:正午@东直门 Jun 27,2017) 本文已归档到kubernetes-handbook中的【最佳实践—使用Jenkins进行持续构建与发布】章节中,一切内容以kubernetes-handbook中稳准。 我们基于Jenkins的CI/CD流程如下所示。 流程说明 应用构建和发布流程说明。 用户向Gitlab提交代码,代码中必须包含Dockerfile; 将代码提交到远程仓库; 用户在发布应用时需要填写git仓库地址和分支、服务类型、服务名称、资源数量、实例个数等,确定后触发Jenkins自动构建; Jenkins的CI流水线自动编译代码并打包成docker镜像推送到Harbor镜像仓库; Jenkins的CI流水线中包括了自定义脚本,根据我们已准备好的kubernetes的YAML模板,将其中的变量替换成用户输入的选项; 生成应用的kubernetes YAML配置文件; 更新Ingress的配置,根据新部署的应用的名称,在ingress的配置文件中增加一条路由信息 更新PowerDNS,向其中插入一条DNS记录,IP地址是边缘节点的IP地址。关于边缘节点,请查看kubernetes-handbook中的【最佳实践——边缘节点配置】章节; Jenkins调用kubernetes的API,部署应用到kubernetes集群中。 关于应用的更新、滚动升级、灰度发布请留意博客中的后续文章或关注kubernetes-handbook的更新。

云原生微服务治理框架Linkerd简介

(题图:青岛 May 26,2017) 前言 Linkerd是一个用于云原生应用的开源、可扩展的service mesh(一般翻译成服务网格,还有一种说法叫”服务啮合层“,见Istio:用于微服务的服务啮合层)。同时,Linkerd也是CNCF(云原生计算基金会)中的组件之一。 P.S 本文已归档到kubernetes-handbook中的【领域应用—微服务架构】章节中。 Linkerd是什么 Linkerd的出现是为了解决像twitter、google这类超大规模生产系统的复杂性问题。Linkerd不是通过控制服务之间的通信机制来解决这个问题,而是通过在服务实例之上添加一个抽象层来解决的。 Linkerd负责跨服务通信中最困难、易出错的部分,包括延迟感知、负载均衡、连接池、TLS、仪表盘、请求路由等——这些都会影响应用程序伸缩性、性能和弹性。 如何运行 Linkerd作为独立代理运行,无需特定的语言和库支持。应用程序通常会在已知位置运行linkerd实例,然后通过这些实例代理服务调用——即不是直接连接到目标服务,服务连接到它们对应的linkerd实例,并将它们视为目标服务。 在该层上,linkerd应用路由规则,与现有服务发现机制通信,对目标实例做负载均衡——与此同时调整通信并报告指标。 通过延迟调用linkerd的机制,应用程序代码与以下内容解耦: 生产拓扑 服务发现机制 负载均衡和连接管理逻辑 应用程序也将从一致的全局流量控制系统中受益。这对于多语言应用程序尤其重要,因为通过库来实现这种一致性是非常困难的。 Linkerd实例可以作为sidecar(既为每个应用实体或每个主机部署一个实例)来运行。 由于linkerd实例是无状态和独立的,因此它们可以轻松适应现有的部署拓扑。它们可以与各种配置的应用程序代码一起部署,并且基本不需要去协调它们。 参考 Buoyant发布服务网格Linkerd的1.0版本 Linkerd documentation Istio:用于微服务的服务啮合层

Kubernetes Pod Cheat Sheet——Pod数据结构参考图

昨天晚上构思,今天花了一上午的时间翻阅了下kubernetes api reference,画了一个Kubernetes Pod Cheat Sheet。 从Pod的数据结构和API入手,管中窥豹,可见一斑。通过该图基本可以对kubernetes中这个最基本的object——Pod的功能和配置有一个感性的认识了,也许具体的某个组件的实现你不了解,但是从high level的视角来看待Pod整体有助于今后深入研究某个feature。 该图是根据kubernetes 1.6版本的Pod v1 core API绘制。 图片归档在kubernetes-handbook,请以GitHub中的图片为准。 注:在移动设备上打开该链接后会提示图片太大无法查看请选择Desktop version方可查看原图。 今后我将陆续推出其他object的cheat sheet,敬请关注。

使用API blueprint创建API文档

在进行微服务开发的过程中,为了保证最终开发的系统跟最初的设计保持一致,约定RESTful接口之间的调用方法,我们需要将API设计文档化,因此我们引入了API Blueprint。 API Blueprint 是什么 API Blueprint 用来编写API文档的一种标记语言,类似于Markdown,因为是纯文本的,所以方便共享编辑,具体的语法规则可以在 API Blueprint documentation 查看,配合一些开源的工具可以把接口文档渲染成 html 再搭配一个静态服务器,方便于分享。 另外,配合一些工具,可以直接生成一个 mock data 数据,这样只要和后端的同学约定好接口格式,那么前端再开发的时候可以使用 mock data 数据来做测试,等到后端写好接口之后再做联调就可以了。 我们以Cloud Native Go书中的gogo-service示例里的apiary.apib文件为例。 该文件实际上是一个Markdown格式的文件,Github中原生支持该文件,使用Typora打开后是这样子。 在Visual Studio Code中有个API Element extension对于API Blueprint文件的支持也比较好。 生成静态页面和进行冒烟测试 我们分别使用开源的aglio和drakov来生成静态页面和进行冒烟测试。 aglio 是一个可以根据 api-blueprint 的文档生成静态 HTML 页面的工具。 其生成的工具不是简单的 markdown 到 html 的转换, 而是可以生成类似 rdoc 这样的拥有特定格式风格的查询文档。 在本地安装有node环境的情况下,使用下面的命令安装和使用aglio。 $ npm install -g aglio $ aglio -i apiary.apib -o api.html 打开api.html文件后,如图: 安装和使用drakov。 $ npm install -g drakov $ drakov -f apiary.

使用Wercker进行持续构建与发布

本文介绍了wercker和它的基本用法,并用我GitHub上的magpie应用作为示例,讲解如何给GitHub项目增加wercker构建流程,并将生成的镜像自动上传到Docker Hub上。 注:本文参考了Cloud Native Go书中的”持续交付“章节。 CI工具 开源项目的构建离不开CI工具,你可能经常会在很多GitHub的开源项目首页上看到这样的东西: 这些图标都是CI工具提供的,可以直观的看到当前的构建状态,例如wercker中可以在Application-magpie-options中看到: 将文本框中的代码复制到你的项目的README文件中,就可以在项目主页上看到这样的标志了。 现在市面上有很多流行的CI/CD工具和DevOps工具有很多,这些工具提高了软件开发的效率,增加了开发人员的幸福感。这些工具有: 适用于GitHub上的开源项目,可以直接使用GitHub账户登陆,对于公开项目可以直接使用:Travis-ci、CircleCI、Wercker。从目前GitHub上开源项目的使用情况来看,Travis-ci的使用率更高一些。 适用于企业级的:Jenkins 不仅包括CI/CD功能的DevOps平台:JFrog、Spinnaker、Fabric8 Wercker简介 Wercker是一家为现代云服务提供容器化应用及微服务的快速开发、部署工具的初创企业,成立于2012年,总部位于荷兰阿姆斯特丹。其以容器为中心的平台可以对微服务和应用的开发进行自动化。开发者通过利用其命令行工具能够生成容器到桌面,然后自动生成应用并部署到各种云平台上面。其支持的平台包括Heroku、AWS以及Rackspace等。 Wercker于2016年获得450万美元A轮融资,此轮融资由Inkef Capital领投,Notion Capital跟投,融资所得将用于商业版产品的开发。此轮融资过后其总融资额为750万美元。 Wercker于2017年4月被Oracle甲骨文于收购。 为什么使用Wercker 所有的CI工具都可以在市面上获取,但为何要建议使用Wercker呢?依据云之道的准则评估了所有工具,发现Wercker正是我们需要的。 首先,无须在工作站中安装Wecker,仅安装一个命令行客户端即可,构建过程全部在云端进行。 其次,不用通过信用卡就可使用Wercker。当我们迫切希望简化流程时,这是一件令人赞叹的事。付款承诺这一条件大大增加了开发者的压力,这通常是不必要的。 最后,Wercker使用起来非常简单。它非常容易配置,不需要经过高级培训或拥有持续集成的博士学位,也不用制定专门的流程。 通过Wercker搭建CI环境只需经过三个基本步骤。 1.在Wercker网站中创建一个应用程序。 2.将wercker.yml添加到应用程序的代码库中。 3.选择打包和部署构建的位置。 如何使用 可以使用GitHub帐号直接登录Wercker,整个创建应用CI的流程一共3步。 一旦拥有了账户,那么只需简单地点击位于顶部的应用程序菜单,然后选择创建选项即可。如果系统提示是否要创建组织或应用程序,请选择应用程序。Wercker组织允许多个Wercker用户之间进行协作,而无须提供信用卡。下图为设置新应用程序的向导页面。 选择了GitHub中的repo之后,第二步配置访问权限,最后一步Wercker会尝试生成一个wercker.yml文件(后面会讨论)。不过至少对于Go应用程序来说,这个配置很少会满足要求,所以我们总是需要创建自己的Wercker配置文件。 安装Wercker命令行程序 这一步是可选的,如果你希望在本地进行wercker构建的话才需要在本地安装命令行程序。本地构建和云端构建都依赖于Docker的使用。基本上,代码会被置于所选择的docker镜像中(在wercker.yml中定义),然后再选择执行的内容和方法。 要在本地运行Wercker构建,需要使用Wercker CLI。有关如何安装和测试CLI的内容,请查看http://devcenter.wercker.com/docs/cli。Wercker更新文档的频率要比本书更高,所以请在本书中做个标记,然后根据Wercker网站的文档安装Wercker CLI。 如果已经正确安装了CLI,应该可以查询到CLI的版本,代码如下所示。 Version: 1.0.882 Compiled at: 2017-06-02 06:49:39 +0800 CST Git commit: da8bc056ed99e27b4b7a1b608078ddaf025a9dc4 No new version available 本地构建只要在项目的根目录下输入wercker build命令即可,wercker会自动下载依赖的docker镜像在本地运行所有构建流程。 创建Wercker配置文件wercker.yml Wercker配置文件是一个YAML文件,该文件必须在GitHub repo的最顶层目录,该文件主要包含三个部分,对应可用的三个主要管道。 — Dev:定义了开发管道的步骤列表。与所有管道一样,可以选定一个box用于构建,也可以全局指定一个box应用于所有管道。box可以是Wercker内置的预制Docker镜像之一,也可以是Docker Hub托管的任何Docker镜像。 — Build:定义了在Wercker构建期间要执行的步骤和脚本的列表。与许多其他服务(如Jenkins和TeamCity)不同,构建步骤位于代码库的配置文件中,而不是隐藏在服务配置里。 — Deploy:在这里可以定义构建的部署方式和位置。 Wercker中还有工作流的概念,通过使用分支、条件构建、多个部署目标和其他高级功能扩展了管道的功能,这些高级功能读着可以自己在wercker的网站中探索。 示例 我们以我用Go语言开发的管理yarn on docker集群的命令行工具magpie为例,讲解如何使用wercker自动构建,并产生docker镜像发布到Docker Hub中。

kubernetes client-go包使用示例

(题图:青岛栈桥 May 26,2017) 前言 本文将归档到kubernetes-handbook的【开发指南—client-go示例】章节中,最终版本以kubernetes-handbook中为准。 本文中的代码见:https://github.com/rootsongjc/kubernetes-client-go-sample client-go示例 访问kubernetes集群有几下几种方式: 方式 特点 支持者 Kubernetes dashboard 直接通过Web UI进行操作,简单直接,可定制化程度低 官方支持 kubectl 命令行操作,功能最全,但是比较复杂,适合对其进行进一步的分装,定制功能,版本适配最好 官方支持 client-go 从kubernetes的代码中抽离出来的客户端包,简单易用,但需要小心区分kubernetes的API版本 官方支持 client-python python客户端,kubernetes-incubator 官方支持 Java client fabric8中的一部分,kubernetes的java客户端 redhat 下面,我们基于client-go,对Deployment升级镜像的步骤进行了定制,通过命令行传递一个Deployment的名字、应用容器名和新image名字的方式来升级。代码和使用方式见 https://github.com/rootsongjc/kubernetes-client-go-sample 。 kubernetes-client-go-sample 代码如下: package main import ( "flag" "fmt" "os" "path/filepath" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" ) func main() { var kubeconfig *string if home := homeDir(); home !

kubernetes管理的容器命名规则解析

本文将归档到kubernetes-handbook的【运维管理-监控】章节中,最终版本以kubernetes-handbook中为准。 当我们通过cAdvisor获取到了容器的信息后,例如访问${NODE_IP}:4194/api/v1.3/docker获取的json结果中的某个容器包含如下字段: "labels": { "annotation.io.kubernetes.container.hash": "f47f0602", "annotation.io.kubernetes.container.ports": "[{\"containerPort\":80,\"protocol\":\"TCP\"}]", "annotation.io.kubernetes.container.restartCount": "0", "annotation.io.kubernetes.container.terminationMessagePath": "/dev/termination-log", "annotation.io.kubernetes.container.terminationMessagePolicy": "File", "annotation.io.kubernetes.pod.terminationGracePeriod": "30", "io.kubernetes.container.logpath": "/var/log/pods/d8a2e995-3617-11e7-a4b0-ecf4bbe5d414/php-redis_0.log", "io.kubernetes.container.name": "php-redis", "io.kubernetes.docker.type": "container", "io.kubernetes.pod.name": "frontend-2337258262-771lz", "io.kubernetes.pod.namespace": "default", "io.kubernetes.pod.uid": "d8a2e995-3617-11e7-a4b0-ecf4bbe5d414", "io.kubernetes.sandbox.id": "843a0f018c0cef2a5451434713ea3f409f0debc2101d2264227e814ca0745677" }, 这些信息其实都是kubernetes创建容器时给docker container打的Labels。 你是否想过这些label跟容器的名字有什么关系?当你在node节点上执行docker ps看到的容器名字又对应哪个应用的Pod呢? 在kubernetes代码中pkg/kubelet/dockertools/docker.go中的BuildDockerName方法定义了容器的名称规范。 这段容器名称定义代码如下: // Creates a name which can be reversed to identify both full pod name and container name. // This function returns stable name, unique name and a unique id. // Although rand.Uint32() is not really unique, but it's enough for us because error will // only occur when instances of the same container in the same pod have the same UID.

Kubernetes配置最佳实践

(题图:青岛 May 26,2017) 前言 本文档旨在汇总和强调用户指南、快速开始文档和示例中的最佳实践。该文档会很很活跃并持续更新中。如果你觉得很有用的最佳实践但是本文档中没有包含,欢迎给我们提Pull Request。 本文已上传到kubernetes-handbook中的第四章最佳实践章节,本文仅作归档,更新以kubernetes-handbook为准。 通用配置建议 定义配置文件的时候,指定最新的稳定API版本(目前是V1)。 在配置文件push到集群之前应该保存在版本控制系统中。这样当需要的时候能够快速回滚,必要的时候也可以快速的创建集群。 使用YAML格式而不是JSON格式的配置文件。在大多数场景下它们都可以作为数据交换格式,但是YAML格式比起JSON更易读和配置。 尽量将相关的对象放在同一个配置文件里。这样比分成多个文件更容易管理。参考guestbook-all-in-one.yaml文件中的配置(注意,尽管你可以在使用kubectl命令时指定配置文件目录,你也可以在配置文件目录下执行kubectl create——查看下面的详细信息)。 为了简化和最小化配置,也为了防止错误发生,不要指定不必要的默认配置。例如,省略掉ReplicationController的selector和label,如果你希望它们跟podTemplate中的label一样的话,因为那些配置默认是podTemplate的label产生的。更多信息请查看 guestbook app 的yaml文件和 examples 。 将资源对象的描述放在一个annotation中可以更好的内省。 裸奔的Pods vs Replication Controllers和 Jobs 如果有其他方式替代“裸奔的pod”(如没有绑定到replication controller 上的pod),那么就使用其他选择。在node节点出现故障时,裸奔的pod不会被重新调度。Replication Controller总是会重新创建pod,除了明确指定了restartPolicy: Never 的场景。Job 也许是比较合适的选择。 Services 通常最好在创建相关的replication controllers之前先创建service(没有这个必要吧?)你也可以在创建Replication Controller的时候不指定replica数量(默认是1),创建service后,在通过Replication Controller来扩容。这样可以在扩容很多个replica之前先确认pod是正常的。 除非时分必要的情况下(如运行一个node daemon),不要使用hostPort(用来指定暴露在主机上的端口号)。当你给Pod绑定了一个hostPort,该pod可被调度到的主机的受限了,因为端口冲突。如果是为了调试目的来通过端口访问的话,你可以使用 kubectl proxy and apiserver proxy 或者 kubectl port-forward。你可使用 Service 来对外暴露服务。如果你确实需要将pod的端口暴露到主机上,考虑使用 NodePort service。 跟hostPort一样的原因,避免使用 hostNetwork。 如果你不需要kube-proxy的负载均衡的话,可以考虑使用使用headless services。 使用Label 定义 labels 来指定应用或Deployment的 semantic attributes 。例如,不是将label附加到一组pod来显式表示某些服务(例如,service:myservice),或者显式地表示管理pod的replication controller(例如,controller:mycontroller),附加label应该是标示语义属性的标签, 例如{app:myapp,tier:frontend,phase:test,deployment:v3}。 这将允许您选择适合上下文的对象组——例如,所有的”tier:frontend“pod的服务或app是“myapp”的所有“测试”阶段组件。 有关此方法的示例,请参阅guestbook应用程序。 可以通过简单地从其service的选择器中省略特定于发行版本的标签,而不是更新服务的选择器来完全匹配replication controller的选择器,来实现跨越多个部署的服务,例如滚动更新。

Cloud Native Go - 基于Go和React的web云服务构建指南

(题图:北京植物园桃花 Mar 26,2016) Kevin Hoffman和Dan Nemeth著的《Cloud Native Go - 基于Go和React的web云原生应用构建指南》将由电子工业出版社出版。 简介 Cloud Native Go向开发人员展示如何构建大规模云应用程序,在满足当今客户的强大需求的同时还可以动态扩展来处理几乎任何规模的数据量、流量或用户。 Kevin Hoffman和Dan Nemeth详细描述了现代云原生应用程序,阐明了与快速、可靠的云原生开发相关的因素、规则和习惯。他们还介绍了Go这种“简单优雅”的高性能语言,它特别适合于云开发。 在本书中你将使用Go语言创建微服务,使用ReactJS和Flux添加前端Web组件,并掌握基于Go的高级云原生技术。Hoffman和Nemeth展示了如何使用Wercker、Docker和Dockerhub等工具构建持续交付管道; 自动推送应用程序到平台上; 并系统地监控生产中的应用程序性能。 学习“云之道”:为什么开发好的云软件基本上是关于心态和规则 了解为什么使用Go语言是云本地微服务开发的理想选择 规划支持持续交付和部署的云应用程序 设计服务生态系统,然后以test-first的方式构建它们 将正在进行的工作推送到云 使用事件源和CQRS模式来响应大规模和高吞吐量 安全的基于云的Web应用程序:做与不做的选择 使用第三方消息传递供应商创建响应式云应用程序 使用React和Flux构建大规模,云友好的GUI 监控云中的动态扩展,故障转移和容错 章节简介如下图。 关于作者 Kevin Hoffman通过现代化和以多种不同语言构建云原生服务的方式帮助企业将其应用程序引入云端。他10岁时开始编程,在重新组装的CommodoreVIC-20上自习BASIC。从那时起,他已经沉迷于构建软件,并花了很多时间学习语言、框架和模式。他已经构建了从遥控摄影无人机、仿生性安全系统、超低延迟金融应用程序到移动应用程序等一系列软件。他在构建需要与Pivotal Cloud Foundry配合使用的自定义组件时爱上了Go语言。 Kevin 是流行的幻想书系列(*The Sigilord Chronicles*,http://amzn.to/ 2fc8iES)的作者,他热切地期待着最终能够将自己对构建软件的热爱与对构建幻想世界的热爱结合起来。 Dan Nemeth目前在Pivotal担任咨询解决方案架构师,负责支持Pivotal Cloud Foundry。他从Commodore 64开始就一直在开发软件,从1995年起开始专业编码,使用ANSIC编写了用于本地ISP的CGI脚本。从那时起,他职业生涯的大部分时间里是作为独立顾问为从金融到制药行业提供解决方案,并使用当时流行的各种语言和框架。Dan最近接受了Go作为自己的归宿,并热情地将它用于所有的项目。 如果你发现Dan没在电脑前,他很可能就是在靠近安纳波利斯的水域玩帆船或飞钓。 下面先罗列下目录,以飨读者。 目录 云之道.. 1 云之道的优点.. 2 遵循简单.. 2 测试优先,测试一切.. 3 尽早发布,频繁发布.. 5 自动化一切.. 6

微服务管理框架Istio简介

(题图:威海朱口 May 29,2017) 前言 本文已上传到kubernetes-handbook中的第五章微服务章节,本文仅作归档,更新以kubernetes-handbook为准。 Istio是由Google、IBM和Lyft开源的微服务管理、保护和监控框架。Istio为希腊语,意思是”起航“。 简介 使用istio可以很简单的创建具有负载均衡、服务间认证、监控等功能的服务网络,而不需要对服务的代码进行任何修改。你只需要在部署环境中,例如Kubernetes的pod里注入一个特别的sidecar proxy来增加对istio的支持,用来截获微服务之间的网络流量。 目前版本的istio只支持kubernetes,未来计划支持其他其他环境。 特性 使用istio的进行微服务管理有如下特性: 流量管理:控制服务间的流量和API调用流,使调用更可靠,增强不同环境下的网络鲁棒性。 可观测性:了解服务之间的依赖关系和它们之间的性质和流量,提供快速识别定位问题的能力。 策略实施:通过配置mesh而不是以改变代码的方式来控制服务之间的访问策略。 服务识别和安全:提供在mesh里的服务可识别性和安全性保护。 未来将支持多种平台,不论是kubernetes、Mesos、还是云。同时可以集成已有的ACL、日志、监控、配额、审计等。 架构 Istio架构分为控制层和数据层。 数据层:由一组智能代理(Envoy)作为sidecar部署,协调和控制所有microservices之间的网络通信。 控制层:负责管理和配置代理路由流量,以及在运行时执行的政策。 Envoy Istio使用Envoy代理的扩展版本,该代理是以C++开发的高性能代理,用于调解service mesh中所有服务的所有入站和出站流量。 Istio利用了Envoy的许多内置功能,例如动态服务发现,负载平衡,TLS终止,HTTP/2&gRPC代理,断路器,运行状况检查,基于百分比的流量拆分分阶段上线,故障注入和丰富指标。 Envoy在kubernetes中作为pod的sidecar来部署。 这允许Istio将大量关于流量行为的信号作为属性提取出来,这些属性又可以在Mixer中用于执行策略决策,并发送给监控系统以提供有关整个mesh的行为的信息。 Sidecar代理模型还允许你将Istio功能添加到现有部署中,无需重新构建或重写代码。 更多信息参见设计目标。 Mixer Mixer负责在service mesh上执行访问控制和使用策略,并收集Envoy代理和其他服务的遥测数据。代理提取请求级属性,发送到mixer进行评估。有关此属性提取和策略评估的更多信息,请参见Mixer配置。 混音器包括一个灵活的插件模型,使其能够与各种主机环境和基础架构后端进行接口,从这些细节中抽象出Envoy代理和Istio管理的服务。 Istio Manager Istio-Manager用作用户和Istio之间的接口,收集和验证配置,并将其传播到各种Istio组件。它从Mixer和Envoy中抽取环境特定的实现细节,为他们提供独立于底层平台的用户服务的抽象表示。 此外,流量管理规则(即通用4层规则和七层HTTP/gRPC路由规则)可以在运行时通过Istio-Manager进行编程。 Istio-auth Istio-Auth提供强大的服务间和最终用户认证,使用相互TLS,内置身份和凭据管理。它可用于升级service mesh中的未加密流量,并为运营商提供基于服务身份而不是网络控制的策略的能力。 Istio的未来版本将增加细粒度的访问控制和审计,以使用各种访问控制机制(包括属性和基于角色的访问控制以及授权hook)来控制和监控访问你服务、API或资源的人员。 参考 Istio开源平台发布,Google、IBM和Lyft分别承担什么角色? Istio:用于微服务的服务啮合层 Istio Overview