今天给大家介绍下如何快速部署应用到阿里云Kubernetes(托管版),以下简称k8s

k8s是个复杂的产品我相信大部分企业在应用的时候并不会关系太深层次的问题,所以我个人比较推荐的k8s使用方式是直接部署各大云平台的托管版(Azure云平台只提供了托管版)。托管版有如下优势:

  1. 部署简单,因为云平台解决了master节点管理,所以我们只需一键部署node节点
  2. 运维简单,因为只管理node节点,所以我们并不需要担心集群可靠性问题。并且云平台一般会在安装的k8s版本中嵌入云平台自己的网络和存储解决方案。网络方面可能体会不太明显,但至少我们可以直接在k8s中管理云磁盘Disk
  3. 成本低,大部分中小公司如果要运作k8s是需要招聘独立的运维人员的,如果使用托管版我相信一般的运维人员或开发人员是可以替代的,因为运维并不需要花太多功夫

所以今天的主题中k8s托管版是我们强调的其中一个因素。 另一个因素就是Coderun,它是一个CI/CD平台,你可以将它与JenkinsdroneTravisCodefresh等进行比较,他们是类似的平台,其实准确说CoderunCodefresh是比较类似的,与其他平台的差异是集成了镜像仓库Helm Charts,以及集成了一些相关的云平台资源,所以它是另一个的因素。

阿里云Kubernetes

阿里云k8s部署这里不进行介绍,详见:阿里云ACK

  1. 自部署,阿里云仅提供一键部署但不提供管理和后续维护.要求用户水平较高
  2. 托管模式,阿里云提供一键部署,并负责管理Master节点.这种模式用户仅需要管理Node节点,基本不需要担心节点挂了,并且可以自行确定Node节点要求的性能.后续升级也可以交给阿里云负责
  3. serverless,终极模式,啥都不需要管理,只需要把镜像提交上去,并确定资源需求即可.不需要维护任何服务器.

如上所述我比较推荐托管版

获取KubeConfig

不管哪种集群创建后都可以在控制台获取到KubeConfig配置,在阿里云控制台点击某个集群后可以看到下图KubeConfig

我们需要三个信息:

  1. server,集群地址,阿里云为每个Kubernetes集群都分配了一个外部地址(如果是自部署模式好像需要自己配置)
  2. client-certificate-data,集群的访问证书
  3. client-key-data,相当于证书的秘钥

如果你为k8s开启了RBAC模式,那么我们需要创建Service Account并绑定Role后参考Token模式配置:K8s Token

Coderun

Coderun的地址是:https://g.coderun.top/,我们需要先进行注册,当然它的注册很方便,直接使用GithubGitlabGiteeCoding账号都可以直接登录(注册并登录),所以如果你的代码仓库是使用云平台那最好直接使用可以访问你代码仓库的账号进行登录,这样就可以直接使用相关的代码仓库。

下面演示的例子: coderun-demo,因为我是直接使用Github账号登录,所以默认会自动添加了Github的配置,如果你要构建的仓库不在你的当前账号下需要自己再配置Git账号,参考官方文档:Git配置

配置Kubernetes集群

现在我们需要将k8s的集群连接配置到Coderun中,在控制台的整合->Kubernetes,点击右边的添加按钮选择证书模式(如果你使用Token请选择Token模式),如图:

  • 其中上图中的名称是你可以自行定义的名称,这个名称可以方便后续在Pipeline中使用,所以最好取一个好记的名称(这里使用myk8s).
  • 证书:填写KubeConfig中的client-certificate-data的内容
  • Key:填写KubeConfig中的client-key-data的内容

完毕后保存,对于Pipeline就有一个可用的myk8s的集群,这个集群连接到我们在阿里云上的k8s集群,后续的所有部署只需要部署到myk8s即可。

配置Pipeline

添加仓库

Coderun控制台的Repo|仓库,点击添加仓库.在右侧选择代码仓库,(如果不是当前用户的Git仓库,参见Git配置),如下图:

点击下一步后,选择Build类型

三种类型分别是:

  1. coderun.yml,使用代码仓库中的coderun.yml文件进行构建
  2. Dockerfile,使用代码仓库中的Dockerfile作为镜像的构建
  3. 模板,和上述的Dockerfile类似,只是使用Coderun内置的各语言Dockerfile模板

因为我们在代码仓库中已经有Dockerfile,所以直接使用Dockerfile创建,我们可以看到添加好的仓库:

Pipeline配置

点击添加好的仓库hellwen/coderun-demo,我们可以看到Pipeline页面,如图:

Pipeline配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
steps:
  docker:
    image: crun/docker
    registry_name: coderun
    repo_name: hellwen/coderun-demo
    dockerfile_content: |
      FROM node:8

      WORKDIR /www
      COPY index.html /www

      RUN npm install http-server -g

      EXPOSE 8080
      CMD ["http-server"]

    context: .
    tags: latest

默认coderun会将Dockerfile解析出来,这样的好处是在Coderun上可以随意修改Pipeline并重新部署而无需重新提交代码仓库,因为我更想使用代码仓库中的Dockerfile所以更简洁的配置:

1
2
3
4
5
6
steps:
  docker:
    image: crun/docker
    registry_name: coderun
    repo_name: hellwen/coderun-demo
    tags: latest

上述配置会默认使用当前代码仓库下的Dockerfile文件,注意:如果是使用代码仓库中的文件是和Build的代码分支有关(使用对应分支下的Dockerfile)

几个比较重要的配置:

  • docker: 这个关键字可以任意定义,用于给每个step取一个名称,后面会显示在Build日志中
  • image: 指定了用于step的基础镜像,这里默认使用官方的docker镜像处理Dockerfile
  • registry_name: 这个参数是指定代码仓库的配置,相关的配置在整合中,每个用户coderun会自动创建一个同名的镜像仓库,所以这里可以直接使用
  • repo_name: 镜像名称,默认为代码仓库名称,可以执行修改但要注意不要和其他仓库镜像同名
  • tags: 指定build后镜像的tag分支名称

详细的配置说明详见文档:crun/docker

如果你想使用脚本自己构建Dockerfile,可以把crun/docker替换成docker

配置好我们就可以进行下测试了,选择分支页面,如图:

点击Build后可以看到当前的Build进度,第一次Build一般会因为上传镜像所以稍微有点慢

Build完成后如下右上角有绿色确定图标指示成功:

crun/docker会自动上传镜像到对应的仓库中,所以观察日志可以看到上传后的镜像地址是:r.crun.top/hellwen/hellwen/coderun-demo:latest,其中hellwen/hellwen并不是Bug第一个hellwenCoderun账号,第二个hellwenGithub账号(我们添加的仓库的前缀)

我们到镜像页面可以看到我们刚刚上传的镜像:

Kubernetes部署

前面步骤我们只是完成了镜像的构建,有了镜像后我们就可以进行部署。

配置镜像仓库到k8s

如果要让k8s访问你的Coderun私有镜像仓库需要配置Secret,操作如下:

Coderun不支持账号密码,因此我们需要一个Token,可通过整合->Token获取:

点击生成Token,任何输入一个名称,点击生成,如下:

复制上图的Token备用:bj8pikhk57kg00fn9vd0

(要使用kubectl访问k8s集群请自行配置KubeConfig,参考:阿里云上的进群KubeConfig页面)

1
$ kubectl create secret docker-registry coderun --docker-server=r.crun.top --docker-username=hellwen --docker-password=bj8pikhk57kg00fn9vd0

其中docker-password为上面生成的Tokendocker-username修改成你自己的账号

1
2
3
$ kubectl get secrets coderun
NAME      TYPE                             DATA   AGE
coderun   kubernetes.io/dockerconfigjson   1      1m

Pipeline增加deploy

在原有Pipeline配置上增加一个step: deploy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
steps:
  docker:
    image: crun/docker
    registry_name: coderun
    repo_name: hellwen/coderun-demo
    tags: latest

  deploy:
    image: crun/kube
    settings:
      cluster_name: myk8s
      namespace: default
      template: deployment.yml
  • 其中crun/kube是官方提供的插件,用于部署到k8s,它可以执行任何k8s对象
  • cluster_name这里指定的是前面步骤配置的k8s集群,我们命名为:myk8s
  • namespace指定k8s集群的默认命名空间
  • template指定k8s能有效识别的yaml配置(可以包含:servicedeployment等)

详细的配置说明详见文档:crun/kube

其中deployment.yml如下(内容有点多,不好意思,如果你不了解k8s请自行学习):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: {{CR_IMAGE}}
        ports:
          - name: http
            containerPort: 8080
---
kind: Service
apiVersion: v1
metadata:
  name: demo
  labels:
    app: demo
spec:
  selector:
    app: demo
  ports:
    - port: 80
      targetPort: http
      name: http
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
spec:
  rules:
    - host:
      http:
        paths:
          - backend:
              serviceName: demo
              servicePort: 80
            path: /

重要参数:

  • image中我们使用了一个变量{{CR_IMAGE}}这个变量会自动从crun/docker获取到build后的完整镜像地址
  • Ingress中的host配置为空是为了让集群的根目录可以访问到

其中ingress需要nginx-ingress控制器的支持(如果没有安装你没法访问到部署后的页面,但部署依然正常的)。

helm的安装这里不介绍了,自行Google,如果要安装ingress控制器可以使用下列命令:

1
$ helm install stable/nginx-ingress --name nginx-ingress --namespace kube-system

在执行一次Build,如下:

上图的左边列表我们可以看到多了一个deploy,右边的日志显示我们部署了DeploymentServiceIngress

部署效果

部署后的k8s状态(要使用kubectl访问k8s集群请自行配置KubeConfig):

1
2
3
4
5
6
7
8
9
$ kubectl get svc,deployment,ingress demo
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/demo   ClusterIP   172.21.10.89   <none>        80/TCP    14m

NAME                         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/demo   1         1         1            1           14m

NAME                      HOSTS   ADDRESS         PORTS   AGE
ingress.extensions/demo   *       47.110.164.15   80      9m
1
2
$ kubectl get deployment demo -o go-template='{{range .spec.template.spec.containers}}{{.image}}{{end}}'
r.crun.top/hellwen/hellwen/coderun-demo:latest

上面的镜像地址我们可以看到使用{{CR_IMAGE}}会自动被替换成r.crun.top/hellwen/hellwen/coderun-demo:latest,也就是crun/docker上传的地址,是不是特别方便了:)

访问应用

如果有ingress控制器,直接使用ingress的地址47.110.164.15进行访问:

下次你如果往代码仓库中提交代码,Coderun就会自动触发并自动部署,完全自动哦。

总结

到这里我们的部署就完成了.比起自己搭建Jenkins是不是方便不少

Jenkins应该是用得做广泛的CI/CD工具了,但是Jenkins并不诞生在DockerKubernetes的年代,所以难免有些设计比较落后。最明显的问题就是配置的雪花问题,现在的运维架构很讲究IaC,从Iac的角度来讲雪花会带来后续大量运维和管理难点。

目前新的CI/CD一般都采用一个一代码仓库统一进行管理的配置文件方式来进行部署,这样就可以避免雪花问题。Coderun更是如此,相较于其他产品我觉得Coderun的好处有几点:

  1. 国内的平台,速度和服务有保障
  2. coderun.yml解决雪花问题,支持嵌入式和文件方式配置
  3. 整合常见的Git平台:GithubGiteeCodingGitlab(其中GiteeCoding国内有不少用户,国外产品不太会支持这两个代码仓库)
  4. 自带镜像仓库和Helm Charts仓库,更方便维护和Pipeline的使用
  5. 基于docker镜像作为step,用户可以自定义自己的镜像,进行无限扩容