Kubernetes Cookbook 编程指南 中文版教程
创建时间:2018-12-07  访问量:3668  7  0

Kubernetes Cookbook 编程指南 中文版教程

与Jenkins集成

在软件工程中,持续集成(CI)(https://en.wikipedia.org/wiki/Continuous_integration )与持续交付(CD)(https://en.wikipedia.org/wiki/Continuous_delivery ),简写为CI/CD,有使用连续测试机制来简化传统开发过程的思想,以减少严重冲突带来的恐慌,也就是说,一旦发现小的错误就立即解决它。此外,通过自动化工具,一个运行在CI/CD中的产品在Bug修复和新产品的发布上达到更好的效果。Jenkins就是有名的CI/CD应用程序之一。Jenkins中的工程从代码基础服务器中拉取代码并测试或部署。在本节,我们将向你展示Kubernetes系统如何与Jenkins服务器一起组成CI/CD工作组。

开始

在开始本节之前,如果你没有自己的Docker Registry,那就准备一个Docker Hub帐户(https://hub.docker.com );我们将Jenkins构建的镜像放在这里。它也是Kubernetes拉取镜像的地方。下一步,保证Kubernetes服务器和你的Jenkins服务器就是没有问题的。你可以通过Docker镜像设置你自己的独立的Jenkins服务器。这里有详细的说明。

安装可以构建一个Docker程序的Jenkins服务器

首先,你需要一个安装了Docker的机器。然后,你就可以使用下面的命令创建一个Jenkins服务器:

// Pull the Jenkins image from Docker Hub
$ docker run -p 8080:8080 -v /your/jenkins_home/:/var/jenkins_home -v $(which docker):/bin/docker jenkins

8080端口是网站的入口。它建议为挂载Jenkins主目录分配一个本地目录。因此,你可以在容器关闭时保持数据。 我们也将Docker的二进制文件挂载到我们的Jenkins容器中,因为这个Jenkins官方镜像没有安装docker命令。执行此命令后,安装日志就会显示在终端控制台上。一旦你看到了这个信息,INFO:Jenkins is fully up and running,你就可以使用DOCKER_MACHINE_IP_ADDRESS:8080来验证Jenkins的Web终端了:

在这之后,你需要为Jenkins安装Git和Docker插件。安装插件是自定义你的Jenkins服务器的方法。这里,这两个插件可以让你实现从你手提电脑中的代码到Kubernetes系统容器中的工作流。你可以参考以下步骤:

  1. 在左侧菜单中点击Manage Jenkins

  2. 选择Manage Plugins

  3. 选择Available标签

  4. 输入Git插件并验证;与CloudBees Docker Build and Publish Plugin中一样

  5. 开始安装并重启

如何去做...

我们创建使用Kubernetes作为运行测试容器或部署容器的官方工作站。目前,Kubernetes系统中的开发Pod没有Jenkins插件。因此,我们将调用Kubernetes API来使用。为了运行一个程序测试,我们可以使用第3章玩转容器,保证容器的灵活使用这一节提到的Kubernetes作业(Job),它将创建一个job-like的Pod并在完成之后终止。它适合测试和验证。另一方面,我们可以为官方部署直接创建一个副本控制器和服务。

创建Jenkins项目

作为一个程序构建,我们将为每个程序创建一个单独的Jenkins项目。现在,你可以单击左侧菜单中的New Item。在本节,选择Freestyle project;对于接下来构建示例已经足够了。为项目命名并点击OK:

然后,你将在配置页面看到下面所示的一些类别:

  • Advanced Project Options(高级项目选项)

  • Source Code Management(源代码管理)

  • Build Triggers(构建触发器)

  • Build(构建)

  • Post-build Actions(后构建行为)

这些设置可以使用项目更灵活并且更能接近你的需求。然而,我们将仅仅把焦点放在Source Code Management和Build的部分来满足我们的需求。Source Code Management是我们定义基础代码位置的地方。在后面的章节,我们将选择Git并放到相应的仓库:

在Build类别中,有几个步骤,如Docker Build and Publish和Execute shell,将帮助我们构建Docker镜像,将镜像放到Docker Registry中,并触发Kubernetes系统运行程序:

下面两种情形将展示了如何为在Kubernetes系统中运行你的应用程序设置配置。

运行一个程序测试

Kubernetes的作业用来处理具有终端条件的程序,如单元测试。这里,我们有一个简短的Docker化的程序,非常适合这种情况。在GitHub(https://github.com/kubernetes-cookbook/sleeper )上查看。正如Dockerfile中指明的,这个微小的程序不会做任何事情并在运行10秒后终止。下面的步骤将指导你设置项目的配置:

  1. 在Source Code Management中,选择Git,将你的GitHub仓库地址的HTTPS URL放到Repository URL中。例如,https://github.com/kubernetescookbook/sleeper.git 。就将会发现对于公共仓库有一个WARNING消息;或者你需要添加一个凭证。

  2. 在Build类中,我们需要以下两个构建步骤:

    1. 首先添加Docker Build and Publish来将你的程序构建为一个镜像。仓库名称是必填项。在这种情况下,我们需要使用Docker Hub作为Registry;请将仓库的名称写为DOCKERHUB_ACCOUNT: YOUR_CUSTOMIZED_NAME这个形式。例如,nosus:sleeper。添加一个标签,如v$BUILD_NUMBER,可以使用Jenkins构建编号来标记你的Docker镜像。如果你的Jenkins服务器已经安装了Docker软件包,那就让Docker Host URI和Server credentials保持为空。但是,如果你遵循前一页的说明来安装Jenkins服务器并作为一个容器,对于这两个选择的详细设置请检查以下提示。使Docker registry URL为空,因为我们使用Docker Hub作为Docker registry。然后,为你的Docker Hub访问权限设置一个新的凭证。

    2. 接下来,为调用Kubernetes API添加一个Execute Shell块。我们需要两个API来达到我们的目的:一个是使用JSON模板创建一个Kubernetes作业,另一个是查询作业是否成功完成:

#run a k8s job
curl -XPOST -d'{"apiVersion":"extensions/
v1beta1","kind": "Job","metadata":{"name":"sleeper
"}, "spec": {"selector": {"matchLabels": {"image":
"ubuntu","test": "jenkins"}},"template": {"metadata":
{"labels": {"image": "ubuntu","test": "jenkins"}},"spec":
{"containers": [{"name": "sleeper","image": "nosus/
sleeper"}],"restartPolicy": "Never"}}}}' http://YOUR_
KUBERNETES_MASTER_ENDPOINT/apis/extensions/v1beta1/
namespaces/default/jobs
#check status
count=1
returnValue=-1
while [ $count -lt 60 ]; do
	curl -XGET http://YOUR_KUBERNETES_MASTER_ENDPOINT/apis/
extensions/v1beta1/namespaces/default/jobs/sleeper | grep
"\"succeeded\": 1" && returnValue=0 && break
	sleep 3
count=$(($count+1))
done
return $returnValue

我们对3分钟的超时限制添加一个while循环。周期检查作业和状态是知道作业是否完成的简单方法。如果你得不到successed:1这条消息,就可以断定作业失败了。

为容器化的Jenkins服务器设置Docker Host URI和Server Credential

如果使用docker-machine来构建你的Docker环境(例如,一个OSX用户),在终端中输入这个命令:

$ docker-machine env
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/YOUR_ACCOUNT/.
docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"

运行这个命令来配置你的Shell:

# eval $(docker-machine env)

黙认情况下,你将获得前面的信息。请将$DOCKER_HOST粘贴到Docker Host URI中。然后,检查$DOCKER_CERT_PATH这个目录:

$ ls /Users/carol/.docker/machine/machines/default
boot2docker.iso cert.pem default id_
rsa key.pem server.pem
ca.pem config.json disk.vmdk id_
rsa.pub server-key.pem

这里列出的某些文件可以让您获得许可。请点击Registry credentials旁边的Add按钮并将内容作为文件一部分粘贴到前面文件中,如下截图所示:

在完成项目配置之后,你可以点击Save然后点击Build Now来验证结果。你可能发现你的镜像也会推送到Docker Hub中:

部署一个程序

通过Jenkins服务器部署一个Docker化的程序配置与项目设置的相似。我们将准备一个简单的Nginx程序来尝试!为新的设置打开一个新的Jenkins项目,如下所示:

  1. 在Source Code Management中,选择Git;设置Repository URI的值为https://github.com/kubernetes-cookbook/nginx-demo.git

  2. 在Build中,我们也将需要两个构建步骤。它们如下所示:

    1. 首先添加一个Docker Build and Publish;我们将使用nosus:nginx-demo作为仓库的名称。为Docker Host URI和Server credentials指定适当的值。

    2. 我们需要一个Execute shell块来调用Kubernetes API。有两个API调用:第一个是创建一个Pod,另一个是创建一个服务来暴露Pod:

#create a pod
curl -XPOST -d'{"apiVersion": "v1","kind":
"Pod","metadata": {"labels":{"app": "nginx"},"name":
"nginx-demo"},"spec": {"containers": [{"image": "nosus/
nginx-demo","imagePullPolicy": "Always","name":
"nginx-demo","ports": [{"containerPort": 80,"name":
"http"}]}],"restartPolicy": "Always"}}' http:// YOUR_
KUBERNETES_MASTER_ENDPOINT/api/v1/namespaces/default/pods

#create a service
curl -XPOST -d'{"apiVersion": "v1","kind":
"Service","metadata": {"name": "nginx-demo"},"spec":
{"ports": [{"port": 8081,"protocol": "TCP","targetPort":
80}],"selector": {"app": "nginx"},"type": "NodePort"}}'
http://YOUR_KUBERNETES_MASTER_ENDPOINT /api/v1/namespaces/
default/services

它是如何工作的...

Jenkins服务器与Kubernetes系统是通过RESTful API通讯的。你也可以通过这个URL(http://YOUR_KUBERNETES_MASTER_ENDPOINT:KUBE_API_PORT/swagger_ui )查看一下更多的功能。嗨!API列表只保存在您的服务器中!

另一方面,你也可以安装一个叫HTTP Request Plugin(https://wiki.jenkins-ci.org/display/JENKINS/HTTP+Request+Plugin )的插件来实现Kubernetes API调用。我们将不对这个进行解释,因为,当前版本的POST功能不能使用JSON格式负载。你仍然可以使用这个插件尝试其它类型的API调用。

目前,没有插件能够协助部署Kubernetes任务。这就是构建对于长的curl命令来说是个头疼的问题。您还可以通过RESTful API将其他系统或服务与Kubernetes系统组合在一起,这也是一种鼓励。

不止这些

你可能发现在部署一个程序这一节中,如果我们再次构建一个相同的项目,Kubernetes API调用将返回一个错误的响应,回复说,Pod和Service已经存在。在这种情况下,Kubernetes没有任何一个滚动更新的API来实时更新我们的程序。

尽管如此,在基础设施方面,有两个关于Kubernetes集成的想法:

  • 一个叫作Kubernetes Plugin(https://wiki.jenkins-ci.org/display/JENKINS/Kubernetes+Plugin )的插件帮助动态构建Jenkins从服务。

  • 你可以尝试使你的Kubernetes Master作为一个Jenkins从服务!结果,不使用复杂的API调用来创建Pod是很好的。使用一个滚动更新是没有问题的!

Kubernetes在1.2版本中,有一个新的资源类型部署来控制Pod和副本集,它应该是管理Pod的一个新的解决方案。部署有以下特征:

  • 期望状态和可用状态标明了Pod的使用是否准备就绪

  • 为Pod的任何修改滚动更新

  • 部署回滚到前一版本是可能的

资源部署是在扩展的API版本/v1beta1中。Kubernetes为更新和回滚支持它的API调用。请参考以下API调用:

// Create a deployment
curl -XPOST -d "{\"metadata\":{\"name\":\"nginx-123\"},\"spec\":{\"repl
icas\":2,\"template\":{\"metadata\":{\"labels\":{\"app\":\nginx\"}},\"sp
ec\":{\"containers\":[{\"name\":\"nginx-deployment\",\"image\":\"nosus/
nginx-demo:v$BUILD_NUMBER\",\"ports\":[{\"containerPort\": 80}]}]}}}}"
YOUR_KUBERNETES_MASTER_ENDPOINT /v1beta1/namespaces/default/deployments

一个补丁API的调用用来更新部署。这里,我们将改变镜像的版本。关于补丁操作的一些详细信息可以在这里查到https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md

// Update a deployment
curl -H "Content-Type: application/strategic-merge-patch+json" -XPATCH
-d '{"spec":{"template":{"spec":{"containers":[{"name":"nginxdeployment","image":"nosus/nginx-demo:v1"}]}}}}' YOUR_KUBERNETES_MASTER_
ENDPOINT /apis/extensions/v1beta1/namespaces/default/deployments/nginxdeployment
// Rollback the deployment

在最后的API调用中,我们将部署回滚到最初版本,标明版本为0。尝试自已管理新的资源类型部署!

还可参考

关于更多的CI/CD概念,请继续阅读下一节。当你将你的程序放到Kubernetes系统中时,它将清楚的帮助你。也可以参考下面的章节:

  • 设置持续交付管线

  • 第7章高级集群管理,RESTful API的使用和授权认证这两节