CCE最佳实践之Guestbook搭建

本文将介绍在百度智能云云容器引擎服务里,如何构建一个最简单的web应用

流程概览

容器引擎为百度智能云基于Kubernetes+Docker构建的弹性高可用的容器集群服务,您可以轻松地在采购的集群上部署所需的业务应用,本文将以经典的前端应用GuestBook为例,为您展示集群搭建、部署应用的全流程。

Guestbook搭建步骤

  1. 百度智能云账号注册与实名制
  2. 创建容器集群
  3. 创建镜像仓库
  4. 配置Kubectl命令行工具
  5. (可选)配置KuKubernetes Dashboard
  6. 通过kubernetes kubectl创建GuestBook
  7. 绑定域名,提供服务

百度智能云账号注册与实名认证

注册百度智能云账号,请参考注册百度账号,完成注册操作。

请根据自身情况,进行“企业认证”或者“个人认证”,具体请参考认证流程

如果您在创建 CCE 集群的时候仍未完成实名认证,你可以点击页面上的认证提示按钮到实名认证页面完成相关操作。

创建容器集群

容器集群为一组由服务器构成的资源集合,同时包含了Kubernetes的集群能力,您可以在集群之上构建高可用的业务应用,具体容器集群创建流程如下所示:

  1. 登录百度智能云官网

  2. 登录成功后,选择“产品服务>云容器引擎CCE”,进入“集群列表”页面。

  3. (可选)“集群列表”页面会显示所有已创建的CCE集群名称/ID、状态、地域等信息,并且用户可以通过集群名称进行搜索集群的操作。

  4. (可选)选择区域,请根据实际需求进行选择切换。

    • 集群为全局操作,用户可以根据需要选择不同的地区,如果您需要在多区域创建集群,请参考区域选择说明

    • 在不同区域创建的集群相互独立。

  5. 点击“创建集群”,进入“创建集群”界面。

  6. 创建集群名称,然后根据需要填写相关配置信息。

集群配置

配置说明:

  • 单一区域下配额为5个集群,每个集群配额为20个节点。
  • 集群名称暂不支持修改,请谨慎输入。用户可以自定义集群名称,自定义名称需遵守“字母、数字以及-_ /.等特殊字符,字母开头,长度1-64”的规则。
  • 集群配置中,用户只有勾选了某个可用区域后,后面会显示该可用区内的节点子网选择框,必须填写,且节点子网从属于节点网络,不同可用区的节点子网不可以冲突。
  • 容器网络为独立的地址空间,须与节点网络、节点子网、其他集群的容器网络相互独立。

节点配置

节点是构成集群的单一服务器资源,支持CPU、GPU多种类型可供选择,后续您创建的业务应用所需要的容器将会分步到各个节点上,构建高可用环境。

用户根据自身业务需求,选择不同的云服务器类型,如选择普通型,配置详情如下图所示:

如选择GPU实例,详细配置如下如所示:

配置说明:
操作系统支持由百度智能云配置过的集成GPU驱动版系统,如果用户在自己的BCC中创建了GPU自定义镜像的话,镜像是支持GPU自定义镜像,用户如果使用自定义镜像需要手动设置集成GPU驱动
GPU提供固定大小的本地磁盘且暂不支持自主选择,具体信息如下表所示:

GPU卡型号 GPU数量(块) GPU(核) 内存(GB) 磁盘(GB)
NVIDIA Tesla K40 1 6 40 200
NVIDIA Tesla K40 2 12 80 400
NVIDIA Tesla K40 4 24 160 800
NVIDIA 深度学习开发卡 1 6 40 200
NVIDIA 深度学习开发卡 2 12 80 400
NVIDIA 深度学习开发卡 4 24 160 800

存储

配置说明:

  • 用户可以选择创建直接CDS盘或从快照创建CDS盘。如何选择 SSD云磁盘 / 高性能云磁盘 / 普通云磁盘,请查看详细说明
  • 目前支持对创建的CDS云磁盘进行自动格式化并挂载云磁盘至目录/data、同时将容器存储目标指定为/data/docker(该功能仅支持首块CDS云磁盘)。

弹性资源

配置说明:

  • 购买弹性公网IP:用户根据需要可以选择是否购买弹性公网IP。如不购买弹性公网IP,用户将不能使用百度智能云命令行工具和Kubernetes Dashboard来管理集群。
  • 如果勾选“购买弹性公网IP”,则需要进行EIP的配置,具体请参考EIP实例
  • 公网带宽中可以选择按使用流量计费或按使用带宽计费中任意一种作为计费标准。

系统信息

配置说明:

  • 实例名称:可随机生成或用户自定义。自定义名称需遵守“字母、数字以及-_ /.等特殊字符,字母开头,长度1-64”的规则。
  • 管理员密码:可随机生成或用户自定义。自定义需遵守“8-16位字符,英文,数字和符号必须同时存在,符号仅限!@#$%^*()”的规则。
  • 安全组:默认安全组/自定义安全组,创建实例后也可以更改相关访问规则,具体可以参考管理安全组

填写购买信息

配置说明:

  • 购买时长:1-9个月或1-3年选择配置。时长周期为实例创建日起的单位周期。如2015年5月20日购买BCC服务一个月,则使用周期为2015年5月20日-2015年6月20日(默认单位月份时间为30天)。
  • 后付费子节点暂不支持备案。

7.用户确认选择的配置信息和配置费用后,点击“去支付”,进入支付环节。

说明:如果您有百度智能云代金券,可以使用代金券结算抵扣费用,如果代金卷金额不足,则可以使用银行卡完成支付操作。

8.点击“确认付款”,完成支付。支付成功后,系统在后台进行集群的创建。

9.点击链接“管理控制台”,进入“集群列表”界面,查看创建集群的状态,创建成功后该集群状态显示为“运行中”。

创建镜像仓库

镜像仓库为用户专有的Docker镜像存储空间,为容器运行的模板服务,支持使用用户自构建镜像、DockerHub、百度智能云镜像,来创建业务应用。

开通镜像仓库

首次进入镜像仓库,会弹出下图所示页面,按照要求填写用户名并设置密码。

注意:

用户名:镜像仓库用户名命名规则是:用户名由4-30个英文小写字母与数字组成。
密 码:是用户登录到docker镜像仓库的凭证。

创建命名空间

  1. 在镜像仓库分类下选择命名空间,然后在命名空间列表中点击新建命名空间。
  2. 填写新建空间名称并选择空间类型后点击确定完成命名空间的创建。

注意:

命名空间的命名规则为:小写字母、数字及. _ - 构成,开头与结尾必须为小写字母与数字,长度:1-65。

(可选)新建镜像

1.点击镜像列表页中新建按钮。

2.选择命名空间、填写镜像名称和版本号然后点击确定。

注意:

1.镜像名称和版本号的命名需遵守“小写字母、数字及. _ - 构成,开头与结尾必须为小写字母与数字,长度:1-65”的规则,且不支持中文。命名空间、镜像名称和版本号三者的名称加起来不能重复。
2.如果用户不选择新建镜像,在完成镜像推送到相应命名空间后,也会自动生成以上基本信息。

推送镜像到镜像仓库

登录百度智能云镜像仓库

>$ sudo docker login --username=[username] hub.baidubce.com

username:镜像仓库名称,即是开通镜像仓库服务时填写的用户名。输入密码后完成登录。

上传镜像

$ sudo docker tag [ImageId] hub.baidubce.com/[namespace]/[ImageName]:[镜像版本号]
    $ sudo docker push hub.baidubce.com/[namespace]/[ImageName]:[镜像版本号]
  • ImageId和镜像版本号根据镜像信息补充
  • namespace是开通镜像仓库时填写的命名空间
  • ImageName是在控制台创建的镜像名称

配置Kubectl命令行工具

Kubernetes是谷歌开源的容器集群管理系统,是Google多年大规模容器管理技术Borg的开源版本,也是CNCF最重要的项目之一,主要功能包括:

  • 基于容器的应用部署、维护和滚动升级
  • 负载均衡和服务发现
  • 跨机器和跨地区的集群调度
  • 自动伸缩
  • 无状态服务和有状态服务
  • 广泛的Volume支持
  • 插件机制保证扩展性

目前百度智能云容器服务基于kubernetes v1.8.6,如果用户需要从本地个人计算机连接到百度智能云的 Kubernetes 集群,需要使用 Kubernetes 命令行客户端kubectl,kubectl的安装步骤如下所示

Kubernetes 版本下载页面下载对应的 kubectl 客户端,关于kubectl 的其他信息,可以参见kubernetes官方安装和设置 kubectl文档

注意:
下载kubectl之前,用户需要先登录自己的服务器使用指令kubectl version查看自己创建的集群的版本号,然后选择对应的kubectl版本进行下载。例如:用户的集群版本号为1.8,则需要下载的kubectl为1.8版。

Windows环境下的操作步骤

  1. 创建集群之后,下载windows版本的kubectl工具,例如64位的工具如下:

    注意:
    下载kubectl之前,用户需要先登录自己的服务器使用指令kubectl version查看自己创建的集群的版本号,然后选择对应的kubectl版本进行下载。例如:用户的集群版本号为1.8,则需要下载的kubectl为1.8版。下载链接为https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md?spm=5176.app53755.3.2.2uYdIN&file=CHANGELOG.md#client-binaries-17,用户根据自己集群版本号,下载相应版本的工具。

  2. 下载之后,将其解压到任意目录,例如放在D盘下

  3. 在 目录C:\users\下进入用户的文件夹,例如用户名为foo,则文件夹应该为C:\users\foo,同时进入此目录,创建文件夹.kube

  4. 在集群列表页面,下载集群配置文件,放在上一步创建的.kube文件夹中,并且重命名为config

  5. 打开windows命令行提示符

  6. 进入kubectl文件存放的目录,运行kubectl.exe get node可以查看集群的节点。

Linux环境下的操作步骤

1.解压下载后的文件,为kubectl添加执行权限,并放在PATH下

chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl

2.配置kubectl,下载集群凭证。在集群界面下载集群配置文件,放在kubectl的默认配置路径

mv kubectl.conf  ~/.kube/config

3.配置完成后,您即可以使用 kubectl 从本地计算机访问 Kubernetes 集群

kubectl get node

(可选)配置Kubernetes Dashboard

Kubernetes Dashboard是基于Web页面的图形化用户界面,支持用户部署业务、监控、管理业务应用。

前提条件

在本地使用 Kubernetes Dashboard 前,用户需要先配置好kubectl,能通过kubectl连接百度智能云的 Kubernetes 集群。

在本地通过kubectl工具,可以在kubernetes集群里创建一个Dashboard应用,操作步骤如下所示。

Windows环境下创建Dashboard服务。

  1. 首先在存放解压的kubectl.exe的同一个目录下,创建dashboard.yaml文件,例如可以用记事本创建:

对应的`dashboard.yaml`文件为:
apiVersion: extensions/v1beta1
        kind: Deployment
        metadata:
          labels:
            app: kubernetes-dashboard
          name: kubernetes-dashboard
          namespace: kube-system
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: kubernetes-dashboard
          template:
            metadata:
              labels:
                app: kubernetes-dashboard
            spec:
              containers:
              - name: kubernetes-dashboard
                image: hub.baidubce.com/public/dashboard:v1.5.0-caas
                imagePullPolicy: Always
                ports:
                - containerPort: 9090
                  protocol: TCP
                volumeMounts:
                - name: "kubeconfig"
                  mountPath: "/etc/kubernetes/"
                  readOnly: true
                args:
                  - --kubeconfig=/etc/kubernetes/config
                livenessProbe:
                  httpGet:
                    path: /
                    port: 9090
                  initialDelaySeconds: 30
                  timeoutSeconds: 30
              volumes:
              - name: "kubeconfig"
                hostPath:
                  path: "/root/.kube/"
        ---
        kind: Service
        apiVersion: v1
        metadata:
          labels:
            app: kubernetes-dashboard
          name: kubernetes-dashboard
          namespace: kube-system
        spec:
          type: NodePort
          ports:
          - port: 80
            targetPort: 9090
          selector:
            app: kubernetes-dashboard
  1. 然后输入kubectl.exe create -f dashboard.yaml创建dashboard

  2. 通过kubectl.exe get pod --all-namespaces命令可以查看是否创建成功

  3. 输入kubectl.exe proxy可以打开proxy,然后在浏览器中访问127.0.0.1:8001/ui 即可以访问dashboard

Linux环境下创建Dashboard服务

输入以下指令完成Dashboard服务的创建

$ kubectl create -f dashboard.yaml
deployment "kubernetes-dashboard" created
service "kubernetes-dashboard" created

对应的dashboard.yaml文件为:

apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      labels:
        app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: kubernetes-dashboard
      template:
        metadata:
          labels:
            app: kubernetes-dashboard
        spec:
          containers:
          - name: kubernetes-dashboard
            image: hub.baidubce.com/public/dashboard:v1.5.0-caas
            imagePullPolicy: Always
            ports:
            - containerPort: 9090
              protocol: TCP
            volumeMounts:
            - name: "kubeconfig"
              mountPath: "/etc/kubernetes/"
              readOnly: true
            args:
              - --kubeconfig=/etc/kubernetes/config
            livenessProbe:
              httpGet:
                path: /
                port: 9090
              initialDelaySeconds: 30
              timeoutSeconds: 30
          volumes:
          - name: "kubeconfig"
            hostPath:
              path: "/root/.kube/"
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    spec:
      type: NodePort
      ports:
      - port: 80
        targetPort: 9090
      selector:
        app: kubernetes-dashboard

在创建好dashboard之后,使用kubectl proxy命令开启一个代理,连接到Kubernetes API Server。

kubectl proxy

成功开启代理后,可以在本地浏览器中访问http://localhost:8001/ui,连接到Dashboard。

注意:

localhost 是指的用户使用的本地机器,而不是虚拟机,且对应的IP地址为:127.0.0.1

通过kubernetes kubectl创建GuestBook

本实践中的GuestBook应用由两部分组成:

  • Web前端服务。
  • Redis存储系统,包含redis master节点和redis slave节点。

创建Redis Master Pod

redis-master:用于前端web应用进行“写”留言操作的Redis服务。

*注意:
本操作中所有的yaml文件,都和kubectl在同一目录下保存。

在Master节点执行以下命令,将redis-master-deployment.yaml文件发布到Kubernetes集群中,完成redis-master的创建。

kubectl apply -f redis-master-deployment.yaml

对应的redis-master-deployment.yaml文件为:

apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: redis-master
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: redis
            role: master
            tier: backend
        spec:
          containers:
          - name: master
            image: hub.baidubce.com/public/guestbook-redis-master:e2e  # or just image: redis
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379

创建好后,使用以下指令,验证Pod是否正在运行:

kubectl get pods

答复应类似如下:

NAME                            READY     STATUS    RESTARTS   AGE
redis-master-1068406935-3lswp   1/1       Running   0          28s

当STATUS的状态为:Running表示 pod 正常运行。

创建Redis Master Service

服务为一组配置相同的容器以及如何访问他们的规则,即微服务架构中的部署单元,即是用户业务应用的最小运行单元。

输入以下指令,创建一个于redis-master Pod关联的Service。

kubectl apply -f redis-master-service.yaml

对应的redis-master-service.yaml文件为:

apiVersion: v1
    kind: Service
    metadata:
      name: redis-master
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      ports:
      - port: 6379
        targetPort: 6379
      selector:
        app: redis
        role: master
        tier: backend

注意:
tarPort属性,指定Pod内容器应用监听的端口号。

完成之后通过一下指令验证Redis Master Service是否正在运行:

kubectl get service

答复应该类似于:

NAME           CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.0.0.1     <none>        443/TCP    1m
redis-master   10.0.0.151   <none>        6379/TCP   8s

创建Redis Slave Pod

redis-slave:用于前端Web应用进行“读”留言操作的Redis服务,并与Redis-Master的数据保持同步。

redis-slave-deployment.yaml文件发布到Kubernetes集群中,完成redis-slave的创建。

kubectl apply -f redis-slave-deployment.yaml

对应的redis-slave-deployment.yaml文件为:

apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: redis-slave
    spec:
      selector:
        matchLabels:
          app: redis
          role: slave
          tier: backend
      replicas: 2
      template:
        metadata:
          labels:
            app: redis
            role: slave
            tier: backend
        spec:
          containers:
          - name: slave
            image: hub.baidubce.com/public/guestbook-redis-slave:v1
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            env:
            - name: GET_HOSTS_FROM
              value: dns
              # Using `GET_HOSTS_FROM=dns` requires your cluster to
              # provide a dns service. As of Kubernetes 1.3, DNS is a built-in
              # service launched automatically. However, if the cluster you are using
              # does not have a built-in DNS service, you can instead
              # instead access an environment variable to find the master
              # service's host. To do so, comment out the 'value: dns' line above, and
              # uncomment the line below:
              # value: env
            ports:
            - containerPort: 6379

完成上述操作后,执行一下代码查询Pods列表以验证Redis Slave Pods是否正在运行:

kubectl get pods

答复应该类似于:

NAME                            READY     STATUS              RESTARTS   AGE
redis-master-1068406935-3lswp   1/1       Running             0          1m
redis-slave-2005841000-fpvqc    1/1       Running             0          6s
redis-slave-2005841000-phfv9    1/1       Running             0          6s

创建Redis Slave Service

输入以下指令启动redis-slave的两个副本,每个副本上的Redis进行都与redis-master进行数据同步,与redis-master共同构成一个具有读写能力的Redis集群。

kubectl apply -f redis-slave-service.yaml

对应的redis-slave-service.yaml文件为:

apiVersion: v1
    kind: Service
    metadata:
      name: redis-slave
      labels:
        app: redis
        role: slave
        tier: backend
    spec:
      ports:
      - port: 6379
      selector:
        app: redis
        role: slave
        tier: backend

完成上述操作后,通过以下指令查询服务列表以验证Redis Slave Service是否正在运行:

kubectl get services

答复应该类似于:

NAME           CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.0.0.1     <none>        443/TCP    2m
redis-master   10.0.0.151   <none>        6379/TCP   1m
redis-slave    10.0.0.223   <none>        6379/TCP   6s

创建Frontend Pod

frontend-deployment.yaml文件发布到Kubernetes集群中,完成redis-slave的创建。

kubectl apply -f frontend-deployment.yaml

对应的frontend-deployment.yaml文件为:

apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      name: frontend
    spec:
      selector:
        matchLabels:
          app: guestbook
          tier: frontend
      replicas: 3
      template:
        metadata:
          labels:
            app: guestbook
            tier: frontend
        spec:
          containers:
          - name: php-redis
            image: hub.baidubce.com/public/guestbook-frontend:v4
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            env:
            - name: GET_HOSTS_FROM
              value: dns
              # Using `GET_HOSTS_FROM=dns` requires your cluster to
              # provide a dns service. As of Kubernetes 1.3, DNS is a built-in
              # service launched automatically. However, if the cluster you are using
              # does not have a built-in DNS service, you can instead
              # instead access an environment variable to find the master
              # service's host. To do so, comment out the 'value: dns' line above, and
              # uncomment the line below:
              # value: env
            ports:
            - containerPort: 80

完成上述操作后,通过以下指令查询Pods列表以验证三个前端副本是否正在运行:

kubectl get pods -l app=guestbook -l tier=frontend

答复应该类似于:

NAME                        READY     STATUS    RESTARTS   AGE
frontend-3823415956-dsvc5   1/1       Running   0          54s
frontend-3823415956-k22zn   1/1       Running   0          54s
frontend-3823415956-w9gbt   1/1       Running   0          54s

创建Frontend Service

创建Frontend Service的目的是使用Service的NodePort给Kubernetes集群中的redis-master和redis-slave Service映射一个外网可以访问的端口。

注意:
如果您使用百度智能云提供的负载均衡器,请注释type: NodePort,并取消注释type: LoadBalancer。

输入以下指令完成Frontend Service的创建

kubectl apply -f frontend-service.yaml

对应的frontend-service.yaml文件为:

apiVersion: v1
    kind: Service
    metadata:
      name: frontend
      labels:
        app: guestbook
        tier: frontend
    spec:
      # comment or delete the following line if you want to use a LoadBalancer
      type: LoadBalancer 
      # if your cluster supports it, uncomment the following to automatically create
      # an external load-balanced IP for the frontend service.
      ports:
      - port: 80
      selector:
        app: guestbook
        tier: frontend

完成上述操作后,通过以下代码查询服务列表以验证前端服务是否正在运行:

kubectl get services

答复应该类似于:

NAME           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    frontend       10.0.0.112   <nodes>       80:32372/TCP   6s
    kubernetes     10.0.0.1     <none>        443/TCP        4m
    redis-master   10.0.0.151   <none>        6379/TCP       2m
    redis-slave    10.0.0.223   <none>        6379/TCP       1m

查看Frontend Service LoadBalancer

运行以下命令获取Frontend ServiceIP地址。

kubectl get service frontend

答复应该类似于:

NAME       CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
    frontend   10.0.0.112      180.76.174.157     80:32372/TCP   1m

复制外部IP地址,并在浏览器中加载页面以查看您的Guestbook。

绑定域名,提供服务

域名购买

如果用户已经有注册过的域名,则可以直接进行下一步绑定域名,如果没有域名,则可以参考域名购买

绑定域名

  1. 登录管理控制台,进入域名管理
  2. 选择需要绑定frontend service的外网IP的域名,点击操作栏中的解析

  3. 在弹出的添加解析菜单栏中,记录类型选择A记录类,记录值填写frontend service的外网IP。

  4. 用域名访问服务,结果如下图所示: