在上文中,我介绍了如何使用Azure DevOps为ASP.NET Core应用程序案例:tasklist搭建持续集成环境。在持续集成的过程中,Azure DevOps的Build Pipeline会下载tasklist的源代码,使用Docker容器环境进行项目构建,将构建的容器镜像推送到Docker Hub,并将源代码库中的yml文件复制到构建生成目录(Build Artifacts),以备持续部署时使用。今天,我打算介绍一下基于Azure Kubernetes Service和Azure DevOps的部署过程,本章节结束后,你可以看到我们的tasklist已在Kubernetes集群中运行。 强烈建议在阅读本文前,先对上两篇文章做一个大致的了解,然后阅读 tasklist源码库,因为tasklist源码库展示的是一个完整的案例。
Kubernetes与Azure Kubernetes Service
好吧,既然介绍Kubernetes部署,就离不开这两个概念:Kubernetes与Azure Kubernetes Service。Kubernetes(k8s)是Google开源的容器编排集群系统,可以让一个或一组容器运行在集群环境,从而使基于容器的应用程序获得可伸缩与高可用的特性。Kubernetes使用Go语言实现,它有一个实验性的版本,叫Minikube。Minikube是一个只包含一个节点的Kubernetes集群,可以在Windows、Linux等多平台中部署Minikube,部署过程也相对简单,因此,如果是用于学习或者一些简单的实验,可以选择Minikube。在Kubernetes集群运行起来后,就可以使用Kubectl命令行客户端对集群进行管理。 如果是自己部署生产级别的Kubernetes集群的话,配置过程会相对比较复杂,此外,由于Kubernetes是Google的项目,有很多配置部署的脚本以及二进制文件都是使用Google的CDN进行分发,国内是无法访问这些资源的,所以,我还是建议大家使用托管的Kubernetes服务,比如Azure的Azure Kubernetes Service(AKS),这样可以省去繁杂的配置过程,而且还可以根据自己的需要来决定Kubernetes集群的体量,非常方便。 Azure Container Service为容器化的应用程序的运行提供了容器集群环境,它支持三种不同的容器编排器(container orchestrator):Docker Swarm、基于DC/OS的Marathon服务,以及大家熟知的Kubernetes,也就是今天我打算介绍的Azure Kubernetes Service。大家如果有兴趣的话,也不妨了解一下Docker Swarm和DC/OS Marathon。
在Azure上创建托管的Kubernetes(AKS)集群
据我所知,目前Azure中国区版没有官方的AKS服务,网上也有一些资料,帮助读者在Azure中国区版中部署Kubernetes集群,但是过程也相对比较繁杂。在这里,我会使用Azure国际版进行介绍。 首先,登录Azure国际版,点击Create a resource按钮,在新建资源的列表中输入Kubernetes进行搜索,在搜索结果中点击Kubernetes Service选项:
在Create Kubernetes Cluster页面中,进入Basics标签页,然后填写以下信息:
- Subscription:选择你的Azure订阅
- Resource Group:为Kubernetes集群选择一个Azure的资源组(Resource Group),之后为Kubernetes创建的所有资源都会被划入该资源组中,便于管理。你也可以点击Create new按钮新建一个资源组
- Kubernetes cluster name:新创建的Kubernetes集群的名称
- Region:创建资源所属的Region
- Kubernetes version:Kubernetes的版本,选择默认的即可
- DNS name prefix:所创建集群的DNS名称前缀
- Node size:集群中每个节点的虚拟机配置,可以根据自己的实际情况进行选择,当然,配置越高费用也越高。这里我只选择Standard B2s,一个月40美金的样子
- Node count:集群中的节点个数,为了演示,我选择2个节点,于是,Node size * Node count,费用大概一个月80美金的样子
为了演示tasklist项目的K8S部署,我选择了如下的配置:
在这个页面中还可以选择针对认证、网络、监控等方面的高级设置,我就不一一介绍了,官方网站的文档中都有详细说明。现在直接点击Review + create按钮,在Azure完成了对配置信息的校验之后,就可以点击Create按钮创建集群了。
创建成功后,就可以在Azure的站点中找到刚刚创建好的Kubernetes集群了。在集群的管理页面上,点击View Kubernetes dashboard链接,此时会打开一个边窗,列出连接Kubernetes集群的操作步骤。接下来,按照步骤一步步地安装kubectl命令行,并通过Azure的命令行打开Kubernetes的仪表盘。
- 首先确保已经安装Azure命令行工具(Azure CLI)2.0.27或以上版本,有关Azure CLI的安装,可以参考:https://docs.microsoft.com/zh-cn/cli/azure/install-azure-cli?view=azure-cli-latest
- 使用以下命令安装kubectl命令行工具:
az aks install-cli
- Kubectl工具安装完成之后,可以将kubectl的路径添加到PATH环境变量中,方便今后使用。然后,执行下面的命令,以下载集群的登录连接凭证:
az aks get-credentials --resource-group --name
此处表示在创建Kubernetes集群时指定的资源组名称,则是创建集群时指定的Kubernetes集群名称
- 执行以下命令,即可打开Kubernetes集群的仪表盘(Dashboard),其中参数如上所述:
az aks browse --resource-group --name
在完成上述步骤之后,可以看到Dashboard被正常打开:
目前除了kubernetes服务之外,没有部署任何其它的组件。除了使用Dashboard,我们也可以使用kubectl命令行工具,比如,通过以下命令查看已经部署的服务:
接下来,让我们一起看看如何将由Azure DevOps构建好的tasklist应用程序容器部署到这个Kubernetes集群中。
tasklist容器的部署
在前一篇文章中,我们已经将构建生成的容器镜像推送到Docker Hub中,并将用于部署的yml文件复制到了构建输出目录。简便起见,我已经将yml文件保存到了代码库中,在tasklist的代码库中,目前有三个yml文件:docker-compose.pki.yml,docker-compose.yml以及k8s.deployment.yml。前两个文件都是用于构建或者运行容器的(docker-compose.pki.yml文件是我私人使用的,这里可以忽略),只有k8s.deployment.yml才是真正用来实现部署的。接下来,我们将使用这个k8s.deployment.yml,将tasklist容器部署到Kubernetes集群中。
Compose?Kompose?
在Kubernetes上部署容器应用,需要使用YAML格式的配置文件,然后使用kubectl apply命令实现部署。通过阅读官方网站的文档,你会发现其实编写这些YAML文件还是有一定工作量的。对于tasklist案例,我使用Google官方的 Kompose命令行工具,它可以很方便地将Docker Compose文件转为Kubernetes的部署文件。官方的解释就是:Kubernetes + Compose = Kompose。不过可惜的是,Kompose的网站在国内是打不开的,不过可以通过 Kompose的代码库来了解这个工具。tasklist所使用的k8s.deployment.yml文件,正是通过Kompose生成的,不过我也基于自己的需要进行了一些简单的定制。
在Azure Pipeline中创建部署任务
打开Azure DevOps管理界面,选择我们在上一讲中创建的tasklist-demo项目,然后,在Pipelines下选择Releases,然后点击New pipeline按钮,新建一个Release Pipeline。
然后,在Select a template页面,选择Deploy to a Kubernetes cluster模板,点击Apply按钮使用该模板:
在Stage的配置中,填入Stage的名称:
回到All pipelines的配置界面,首先为我们的部署任务起个名字,然后,点击Add an artifact选项,将之前持续集成的输出结果文件,也就是用于k8s部署的YAML文件作为Release Pipeline的输入,添加到Artifacts中。在Add an artifact界面中,我们选择Build类型,表示要使用构建的输出结果,然后,Source选择Build Pipeline的名称,也就是tasklist-demo,其它选项可以默认。当然,你也可以根据自己项目的需求对这些默认的设置进行更改,不过,在此也就不多介绍了。一切设置好之后,点击Add按钮,将Artifact加入Release Pipeline。
之后,点击创建好的K8S Deployment stage,在Agent job列表中,选择kubectl apply,表示我们需要更改一个Kubernetes的集群,然后,在右边的Deploy to Kubernetes界面中,进行如下设置:
- Display name:当前任务的名称,随便起一个有意义的名字就行了
- Kubernetes service connection:选择所需部署的k8s集群的连接信息。目前我们没有可用的连接,所以需要创建一个。点击New按钮即可创建:
- 在Add a Kubernetes service connection对话框中,可以选择两种认证模式:Kubeconfig和Service account。前者需要使用由Azure k8s集群提供的认证配置文件;后者则是直接通过Azure的服务账号来创建连接。这里,我们选用Kubeconfig
- 在Connection name中,输入名称
- 打开Azure Portal,进入tasklist-demo Kubernetes集群的主页,找到API server address项,将内容复制到剪贴板:
- 回到Add a Kubernetes service connection对话框,将复制的内容粘贴到Service URL中,注意前面加上https://的前缀
- 打开Azure Portal,进入tasklist-demo Kubernetes集群的主页,点击View Kubernetes dashboard连接,在Windows命令行中执行获取credential的命令,这个内容在上文也已经介绍过了,这里就贴个截图示意一下:
- 在操作系统中,打开当前用户目录(比如,Windows下为C:\Users\daxnet,Linux下为/home/daxnet),找到.kube文件夹,然后用文本编辑器打开config文件
- 复制config文件的所有内容,然后回到Add a Kubernetes service connection对话框,将内容粘贴到KubeConfig项
- 目前我们暂时不涉及证书的问题,所以勾选Accept untrusted certificates复选框
- 点击Verify connection链接,确保连接Kubernetes集群成功:
- 回到Deploy to Kubernetes页面,此时Kubernetes service connection会自动选中刚刚所创建的Kubernetes连接
- 勾选Use Configuration file复选框,在Configuration file文本框右边点击省略号按钮:
- 在Select a file or folder对话框中,选择k8s.deployment.yml。还记得上面我们选择Build作为Artifact的类型吗?这个k8s.deployment.yml就是从那边复制过来的:
- 对于其它的配置选项,我们暂且使用默认值,然后点击Save按钮,保存我们的Release Pipeline设置
触发部署事件
在成功创建了Azure Kubernetes集群,并在Azure DevOps Pipeline中创建了Release Pipeline之后,就可以尝试将我们的tasklist应用部署到AKS了。回到Pipelines\Releases界面,选择刚刚新建的Pipeline,然后点击Release下拉菜单,选择Create a release选项:
在Create a new release页面中,指定所需部署的编译版本,然后填入一些描述信息后,点击Create按钮,即可手工触发部署。
成功部署之后,会在Release Pipeline的K8S Deployment stage上显示出状态:
点击Logs按钮,可以查看详细的部署信息。事实上,通过编辑K8S Deployment stage的设置,还可以选择部署执行的触发条件,比如,是仅通过手工触发,还是在每次release之后触发,还可以设置触发时间以及通过Pull Request创建触发等,限于文章篇幅,这里就不多介绍了。对这部分有需求的读者请根据自己的实际情况自行设置。
使用部署在Azure Kubernetes集群中的应用程序
现在回到命令行,通过kubectl get po命令,可以看到,我们的容器已经正常运行:
通过kubectl get svc命令,可以看到我们已经部署在Kubernetes集群中的服务:
在上面的服务列表中可以看到,tasklist-web服务的类型是LoadBalancer,也就是这个服务会有一个公网可访问的IP地址。这个IP地址就是104.211.50.78。现在打开浏览器,直接访问这个IP地址,可以看到,我们的tasklist已经成功运行在Azure Kubernetes集群中:
还可以使用下面的命令对tasklist的ASP.NET Core应用程序(也就是后端)进行伸缩:
然后看看执行后有多少个Pods在运行:
总结
本文是有关ASP.NET Core应用程序容器化以及Azure DevOps持续集成、持续部署和Azure Kubernetes Service部署相关内容介绍的最后一篇文章。在这个系列中,我们首先介绍了ASP.NET Core应用程序容器化所需注意的要点,然后介绍了基于容器开发与部署的CI/CD流程,之后包含了有关在Azure DevOps中创建持续集成和持续部署任务的内容,然后是在Azure Kubernetes集群中部署我们的应用程序。相关内容还是比较多的,因此,也无法在这个系列文章中一一介绍完。对于这方面技术感兴趣的读者,我仍然推荐阅读tasklist的源代码库,因为它是一个完整的案例,它涵盖了一个ASP.NET Core应用程序容器化之路的各个方面。在今后的文章中,我还会对DevOps以及代码库分支策略等内容进行介绍,欢迎广大读者阅读讨论。