ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(三)

By | 2018年10月26日

在上文中,我介绍了如何使用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选项:

image

在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部署,我选择了如下的配置:

image

在这个页面中还可以选择针对认证、网络、监控等方面的高级设置,我就不一一介绍了,官方网站的文档中都有详细说明。现在直接点击Review + create按钮,在Azure完成了对配置信息的校验之后,就可以点击Create按钮创建集群了。

image

创建成功后,就可以在Azure的站点中找到刚刚创建好的Kubernetes集群了。在集群的管理页面上,点击View Kubernetes dashboard链接,此时会打开一个边窗,列出连接Kubernetes集群的操作步骤。接下来,按照步骤一步步地安装kubectl命令行,并通过Azure的命令行打开Kubernetes的仪表盘。

image

  1. 首先确保已经安装Azure命令行工具(Azure CLI)2.0.27或以上版本,有关Azure CLI的安装,可以参考:https://docs.microsoft.com/zh-cn/cli/azure/install-azure-cli?view=azure-cli-latest
  2. 使用以下命令安装kubectl命令行工具:
    az aks install-cli
  3. Kubectl工具安装完成之后,可以将kubectl的路径添加到PATH环境变量中,方便今后使用。然后,执行下面的命令,以下载集群的登录连接凭证:
    az aks get-credentials --resource-group <resource_group> --name <k8s_cluster_name>

    此处<resource_group>表示在创建Kubernetes集群时指定的资源组名称,<k8s_cluster_name>则是创建集群时指定的Kubernetes集群名称

  4. 执行以下命令,即可打开Kubernetes集群的仪表盘(Dashboard),其中参数如上所述:
    az aks browse --resource-group<resource_group> --name <k8s_cluster_name>

 

在完成上述步骤之后,可以看到Dashboard被正常打开:

image
目前除了kubernetes服务之外,没有部署任何其它的组件。除了使用Dashboard,我们也可以使用kubectl命令行工具,比如,通过以下命令查看已经部署的服务:

image

接下来,让我们一起看看如何将由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。

image

然后,在Select a template页面,选择Deploy to a Kubernetes cluster模板,点击Apply按钮使用该模板:

image

在Stage的配置中,填入Stage的名称:

image

回到All pipelines的配置界面,首先为我们的部署任务起个名字,然后,点击Add an artifact选项,将之前持续集成的输出结果文件,也就是用于k8s部署的YAML文件作为Release Pipeline的输入,添加到Artifacts中。在Add an artifact界面中,我们选择Build类型,表示要使用构建的输出结果,然后,Source选择Build Pipeline的名称,也就是tasklist-demo,其它选项可以默认。当然,你也可以根据自己项目的需求对这些默认的设置进行更改,不过,在此也就不多介绍了。一切设置好之后,点击Add按钮,将Artifact加入Release Pipeline。

image

之后,点击创建好的K8S Deployment stage,在Agent job列表中,选择kubectl apply,表示我们需要更改一个Kubernetes的集群,然后,在右边的Deploy to Kubernetes界面中,进行如下设置:

  1. Display name:当前任务的名称,随便起一个有意义的名字就行了
  2. 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项,将内容复制到剪贴板:image
    • 回到Add a Kubernetes service connection对话框,将复制的内容粘贴到Service URL中,注意前面加上https://的前缀
    • 打开Azure Portal,进入tasklist-demo Kubernetes集群的主页,点击View Kubernetes dashboard连接,在Windows命令行中执行获取credential的命令,这个内容在上文也已经介绍过了,这里就贴个截图示意一下:image
    • 在操作系统中,打开当前用户目录(比如,Windows下为C:\Users\daxnet,Linux下为/home/daxnet),找到.kube文件夹,然后用文本编辑器打开config文件
    • 复制config文件的所有内容,然后回到Add a Kubernetes service connection对话框,将内容粘贴到KubeConfig项
    • 目前我们暂时不涉及证书的问题,所以勾选Accept untrusted certificates复选框
    • 点击Verify connection链接,确保连接Kubernetes集群成功:
      image
  3. 回到Deploy to Kubernetes页面,此时Kubernetes service connection会自动选中刚刚所创建的Kubernetes连接
  4. 勾选Use Configuration file复选框,在Configuration file文本框右边点击省略号按钮:image
  5. 在Select a file or folder对话框中,选择k8s.deployment.yml。还记得上面我们选择Build作为Artifact的类型吗?这个k8s.deployment.yml就是从那边复制过来的:image
  6. 对于其它的配置选项,我们暂且使用默认值,然后点击Save按钮,保存我们的Release Pipeline设置

触发部署事件

在成功创建了Azure Kubernetes集群,并在Azure DevOps Pipeline中创建了Release Pipeline之后,就可以尝试将我们的tasklist应用部署到AKS了。回到Pipelines\Releases界面,选择刚刚新建的Pipeline,然后点击Release下拉菜单,选择Create a release选项:

image

在Create a new release页面中,指定所需部署的编译版本,然后填入一些描述信息后,点击Create按钮,即可手工触发部署。

image

成功部署之后,会在Release Pipeline的K8S Deployment stage上显示出状态:

image

点击Logs按钮,可以查看详细的部署信息。事实上,通过编辑K8S Deployment stage的设置,还可以选择部署执行的触发条件,比如,是仅通过手工触发,还是在每次release之后触发,还可以设置触发时间以及通过Pull Request创建触发等,限于文章篇幅,这里就不多介绍了。对这部分有需求的读者请根据自己的实际情况自行设置。

image

使用部署在Azure Kubernetes集群中的应用程序

现在回到命令行,通过kubectl get po命令,可以看到,我们的容器已经正常运行:

image

通过kubectl get svc命令,可以看到我们已经部署在Kubernetes集群中的服务:

image

在上面的服务列表中可以看到,tasklist-web服务的类型是LoadBalancer,也就是这个服务会有一个公网可访问的IP地址。这个IP地址就是104.211.50.78。现在打开浏览器,直接访问这个IP地址,可以看到,我们的tasklist已经成功运行在Azure Kubernetes集群中:

image

还可以使用下面的命令对tasklist的ASP.NET Core应用程序(也就是后端)进行伸缩:

image

然后看看执行后有多少个Pods在运行:

image

总结

本文是有关ASP.NET Core应用程序容器化以及Azure DevOps持续集成、持续部署和Azure Kubernetes Service部署相关内容介绍的最后一篇文章。在这个系列中,我们首先介绍了ASP.NET Core应用程序容器化所需注意的要点,然后介绍了基于容器开发与部署的CI/CD流程,之后包含了有关在Azure DevOps中创建持续集成和持续部署任务的内容,然后是在Azure Kubernetes集群中部署我们的应用程序。相关内容还是比较多的,因此,也无法在这个系列文章中一一介绍完。对于这方面技术感兴趣的读者,我仍然推荐阅读tasklist的源代码库,因为它是一个完整的案例,它涵盖了一个ASP.NET Core应用程序容器化之路的各个方面。在今后的文章中,我还会对DevOps以及代码库分支策略等内容进行介绍,欢迎广大读者阅读讨论。

(总访问量:1,357;当日访问量:4)

7 thoughts on “ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(三)

  1. siegrain

    最近花了两天时间跑通了这一套,因为 Azure DevOps 更新有两个跟教程不一样的地方建议注意一下:
    1. 在登录 Azure DevOps 后在右上角的 Preview features 中关闭 New YAML pipeline creation experience 以便跟进教程,不然只能用 YAML 来管理 pipeline
    2. 在本篇的 Add a Kubernetes service connection 一步中直接粘贴配置不需要填写Server URL。

    非常感谢博主希望能看到更多关于DevOps的实践~

    Reply
  2. ChuanGoing

    目前卡在了最后一步了,Azure DevOps自动部署成功,但是在aks 管理页面提示错误信息是Error: ImagePullBackOff。
    按照这个错误提示,我做了两个测试:
    1.怀疑是dockerhub私有仓储权限的问题,改为public情况依旧
    2.命令行运行docker pull 镜像 提示需要登录,输入账号密码后拉取镜像又提示:image operating system “linux” cannot be used on this platform
    (因为我本机安装的是docker for windows)
    所以,现在应该是需要在ask的配置里面增加dockerhub的登陆授权,这块要需要怎么配置呢?

    Reply
      1. ChuanGoing

        昨天又重新试了下,dockerhub仓储改为public就好了,出现上面的原因可能是我两台电脑来回调试的时候没有注意配置需要重新设置导致。另外用你的tasklist跑了一遍,除了上面那位仁兄指出的两处,还有两点需要注意:
        1.新建build pilelines 第一步创建代码连接的配置页的时候需要注意切换到经典模式(Use the classic editor to create a pipeline without YAML)
        2.代码推送到dockerhub时,第一次运行pipeline可能会出现denied: requested access to the resource is denied,但是登录仓储看到镜像是推送成功的,不知道是不是我网络的原因,后面把仓储调整为public再次run pipeline没有出现次问题
        非常感谢这个系列的介绍,让我对CI/CD的流程大概有个脉络,后面将从官方文档入手,仔细理清配置的使用

        Reply
        1. daxnet Post author

          感谢将问题的原因贴在这里供更多朋友参考。这个系列文章发布有一段时间了,Azure DevOps在这段时间也有一定的调整和功能的改进,因此,有些地方可能会有出入,敬请谅解。

          Reply

回复 siegrain 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据