腾讯云容器微服务API设计

Posted 技术不入流

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了腾讯云容器微服务API设计相关的知识,希望对你有一定的参考价值。



关键字:  腾讯云,容器,CCS, ELK , CVM, CDB, API Gteway,RestAPI, mysql ,GO, BeeGO


本文会在腾讯云容器服务上面搭建ELK集群,实现利用Logstash 采集nginx日志,收纳及利用kibana展示的功能,同时利用Beego开发Rest API,定义ELK Service类,实现ELK Service GET/POST/DELETE/PUT的功能,用户可以通过访问API Gateway实现对API的调用,获取目前CCS上面ELK服务的整体功能状态等信息。ELK 服务的所有信息存在于MySQL数据库中,当服务发生变化,状态信息会更新数据库,提供实时信息给用户。 




腾讯云容器微服务API设计(一)

文会包括下面的主要信息:


  1. 安装测试ELK容器集群,在腾讯云上分别构建nginx-basiauth, elasticsearch, logstash, kibana 容器。

  2. 在CVM安装测试BeeGO,golong, 调试确认ELKServiceAPI可以工作正常

  3. 制作Dockerfile以及ENTRYPOINT,将ELKServiceAPI commit到GitHub,从github构建ELKServiceAPI容器镜像

  4. **构建ServiceDiscovery镜像,此容器会监控ELKService状态,并写入ElkserviceAPI的MySQL数据库

  5. 附录参考资料,代码相关部分可以访问 https://github.com/littleking1/elkserviceapi 


首先,安装测试ELK容器集群


     我们总共需要安装下面四个容器: 


   a. ElasticSearch服务:该服务提供日志集中存储和查询

   b. Kibana服务:以web的形式提供日志的可视化展现和查询界面

   c.  Kibana登录鉴权服务:Kibana如果直接放到公网上,因为kibana本身没有        鉴权机制,如果被端口扫描工具扫出来,很容易出现他人查看操作日志的          行为,为避免该 情况,在kibana前面加个nginx服务,利用nginx的basic认          证来做鉴权。

  d. nginx应用服务:创建该服务的目的是为了验证是否可以将应用日志采集到        ElasticSearch里。该服务用nginx的访问日志做日志源,浏览器每访问一次        nginx服务,就会生成一条access日志,和该服务在一起的logstash容器会          将新产生的日志发到ElasticSearch里。


    首先在容器CCS上创建集群,此集群包括两个集群节点,后面用来运行多个服务及容器。由于ElasticSearch需要至少2GB内存,我们选择两个节点都配置为2核4GB。  


腾讯云容器微服务API设计(一)

选择机型及主机配置:


腾讯云容器微服务API设计(一)

在两台主机上分别跑下面的命令:【1】

sysctl -w vm.max_map_count=262144 --  增大虚拟内存

echo 3 > /proc/sys/vm/drop_caches   -- 内存不够,释放部分内存


接下来创建各个服务,我们选择从DockerHub拉取官方镜像: 


  1. 创建 elasticseach服务,该服务包含一个ES容器,ES容器配置硬件:


    配置项名称

    配置值

    服务名称

    elasticsearch

    CPU限制

    1核

    内存限制

    3072M

    镜像

    elasticsearch

    镜像版本

    5.4

    实例个数

    1

    运行命令

    /docker-entrypoint.sh

    运行参数

    -Etransport.host=0.0.0.0 -Ediscovery.zen.minimum_master_nodes=1

    网络参数

    网络方式选仅在集群内访问,协议选TCP,容器端口9200,服务端口9200

    数据卷

    选择本地磁盘,选择一个主机目录,取名为esdata

    挂载点

    选择数据卷esdata,映射到容器目录为/usr/share/elasticsearch/data

  2. 创建kibana服务,该服务包含一个kibana容器,kibana和Elasticsearch 之间以服务的方式连接。


    配置项名称

    配置值

    服务名称

    kibana

    核数

    1核

    内存

    512M

    实例个数

    1

    镜像

    kibana

    镜像版本

    5.4

    网络方式

    提供集群内访问方式,不在公网上直接暴露5601的端口

  3. 搭建kibana的鉴权服务,该服务使用nginx容器,放在kibana前面,避免kibaban在公网上被随机登录使用。


    配置项名称

    配置值


    服务名称

    nginx-basicauth


    镜像

    nginx


    数据卷1

    使用本地硬盘,volume名称用nginxconf,对应的主机目录 /home/ubuntu/conf/nginx.conf


    数据卷2

    使用本地磁盘,volume名称用passwd,对应的主机目录/home/ubuntu/conf/.htpasswd


    网络方式

    提供公网访问,容器端口用80,服务端口用9098


    挂载点1

    使用volume nginxconf,容器内目录/etc/nginx/nginx.conf,放nginx的配置文件


    挂载点2

    使用volume passwd,容器内目录/conf/.htpasswd,放basic auth的用户密码文件


  4. 创建nginx应用服务,该服务包括两个容器,一个nginx还有一个是logstash,logstash和nginx容器之间共享数据目录/var/log/nginx,logstash采集nginx的访问日志文件并将新生成的日志发给ElasticSearch。


    配置项名称

    配置值

    实例个数

    1

    镜像

    logstash

    镜像版本

    5.4

    核数

    1

    内存

    1650M

    运行命令

    /docker-entrypoint.sh

    运行参数

    -f /conf/logstash.conf,注意在界面上填的时候,-f 和/conf/logstash.conf要放两行,如下所示:

    -f

    /conf/logstatsh.conf

    挂载点1

    挂载卷 log,容器目录/var/log/nginx,存放nginx生成的日志文件

    挂载点2

    挂载卷conf,容器目录/conf,存放logstash的配置文件

添加nginx容器:


配置项名称

配置值

实例个数

1

镜像

nginx

内存

128M

核数

0.2

挂载点1

挂载卷 log,容器目录/var/log/nginx,存放nginx生成的日志文件

当容器服务建立完成后,访问nginx 服务80端口



腾讯云容器微服务API设计(一)


此时会在nginx上更新产生的日志信息,然后打开kibana,确认更新的日志信息会完全呈现: 


腾讯云容器微服务API设计(一)


接下来, 在CVM安装测试Beego,测试基本功能. beego提供了使用go语言进行Restapi开发的能力,同时很好的支持MVC模型建立和开发,实现ORMapping。


    2.1   Ubuntu 16.04 CVM安装Golong


        添加apt-get源并刷新

        $ sudo add-apt-repository ppa:gophers/archive 

        $ sudo apt-get update          

 

安装Go 1.8

$ sudo apt-get install golang-1.8


设置环境变量

等安装完毕后,Go会被安装到/usr/lib/go-1.8目录。我们要执行go命令和建         立自己项目的话,需要增加一些环境变量。


我们以后代码要放在当前用户下的Go目录下,需要先创建2个目录:


$ mkdir -p ~/go/bin 

$ mkdir -p ~/go/src

然后设置当前用户的环境变量:


vi ~/.profile

在结尾增加以下内容:


export GOROOT=/usr/lib/go-1.8 

export PATH="$PATH:$GOROOT/bin" 

export GOPATH=$HOME/go 

export PATH="$PATH:$GOPATH/bin"


保存后,重新刷新环境变量


source ~/.profile


接下来我们验证一下我们的Go版本,输入go version ,确认已经安装成功


腾讯云容器微服务API设计(一)

下载需要的go项目,在后面建立ORMapping的时候需要使用:


$ go get -u github.com/astaxie/beego

$ go get -u github.com/beego/bee

$ go get github.com/go-sql-driver/mysql

        

        安装MYsql server, mysqlclient ,配置好密码及用户。 

        登录mysql, mysql -u root -p XXXX, 创建elkservice table

         

CREATE TABLE `elkservice` (

  `Id` int(11) NOT NULL,

  `Name` varchar(10),

  `Status` varchar(10) ,

  `Running` tinyint(1) ,

  `FailedCount` int(11),

  PRIMARY KEY (`Id`)

)


定义ELKService结构如下:


       type Elkservice struct {

       Id int

       Name string

       Status string

       Running bool

       FailedCount int  }


2.2  开发ELKServiceAPI

       

创建API项目模板 ELKTestAPI

 bee api ELKTestAPI 

         

修改项目文件 go/src/ELKTestAPI/models/ELKTestAPI.go, 增加下面的GET/POST/PUT/DELETE 函数:


func GetAllElkservices() []*Elkservice {

       o := orm.NewOrm()

       o.Using("Elkservice")

       var Elkservices []*Elkservice

       q:= o.QueryTable("Elkservice")

       q.All(&Elkservices)

       return Elkservices


}

func GetElkserviceById(id int) Elkservice{

       u:=Elkservice{Id:id}

       o := orm.NewOrm()

       o.Using("Elkservice")

       err := o.Read(&u)

       if err == orm.ErrNoRows {

              fmt.Println("not found")

       } else if err == orm.ErrMissPK {

              fmt.Println("no primary key")

       }

       return u

}

func AddElkservice(Elkservice *Elkservice) int{

       o := orm.NewOrm()

       o.Using("Elkservice")

       o.Insert(Elkservice)

       return Elkservice.Id

}

func UpdateElkservice(Elkservice *Elkservice) {

       o := orm.NewOrm()

       o.Using("Elkservice")

       o.Update(Elkservice)

}


func DeleteElkservice(id int){

       o := orm.NewOrm()

       o.Using("Elkservice")

       o.Delete(&Elkservice{Id:id} 

}  


3.  修改go/src/ELKTestAPI/controllers/Elkservicecontroller.go

      

func (u *ElkserviceController) GetAll() {

       ss := models.GetAllElkservices()

       u.Data["json"] = ss

       u.ServeJSON()

}

func (u *ElkserviceController) GetById() {

       id ,_:= u.GetInt(":id")

       s := models.GetElkserviceById(id)

       u.Data["json"] = s

       u.ServeJSON()

}

func (u *ElkserviceController) Post() {

       var s models.Elkservice

       json.Unmarshal(u.Ctx.Input.RequestBody, &s)

       uid := models.AddElkservice(&s)

       u.Data["json"] = uid

       u.ServeJSON()

}

func (u *ElkserviceController) Update() {

       var s models.Elkservice

       json.Unmarshal(u.Ctx.Input.RequestBody, &s)

       models.UpdateElkservice(&s)

       u.Data["json"] = s

       u.ServeJSON()

}

4.  测试程序可以成功运行:

     bee run -gendoc=true -downdoc=true 

     

腾讯云容器微服务API设计(一)

5. 编写Dockerfile,将ELKService做成镜像,上传到腾讯云容器中,可以参考我的Github上面的Dockerfile进行制作https://github.com/littleking1/elkserviceapi  


FROM ubuntu:16.04

# Set the working directory to /app

WORKDIR /root/go


# Copy the current directory contents into the container at /app

#ADD . /root/go


# Install any needed packages specified 

RUN apt-get update && apt-get install  -y --no-install-recommends  software-properties-common python-software-properties \

&& add-apt-repository ppa:gophers/archive && apt-get update \

&& apt-get install -y --no-install-recommends golang-1.8 \

&& apt-get install -y --no-install-recommends vim git \

&& mkdir -p $HOME/go/bin && mkdir -p $HOME/go/src \

&& echo 'export GOROOT=/usr/lib/go-1.8'>>~/.profile \

&& echo 'export PATH="$PATH:$GOROOT/bin"'>>~/.profile \

&& echo 'export GOPATH="/root/go"'>>~/.profile \

&& echo 'export PATH="$PATH:$GOPATH/bin"'>>~/.profile \ 

&& . ~/.profile \

&& go get -u github.com/astaxie/beego \

&& go get -u github.com/beego/bee \

&& go get github.com/go-sql-driver/mysql


# Define environment variable

ENV GOROOT="/usr/lib/go-1.8"

ENV PATH="$GOROOT/bin:${PATH}"

ENV GOPATH="/root/go"

ENV PATH="$GOPATH/bin:${PATH}"


# Make port 80 available to the world outside this container

EXPOSE 8080


COPY docker-entrypoint.sh /usr/local/bin/

RUN chmod 777 /usr/local/bin/docker-entrypoint.sh


# Run when the container launches

ENTRYPOINT docker-entrypoint.sh

CMD ["top","-b"]


Dockerfile中使用下面的ENTRYPOINT ,在容器开始启动RestAPI运行: 

#!/bin/bash

bee api testuserapi

cd /root/go/src/ELKTestAPI

bee run -gendoc=true -downdoc=true


上传程序源文件到Github:


腾讯云容器微服务API设计(一)

在腾讯云容器CCS中新建镜像仓库 -- elkapitest


腾讯云容器微服务API设计(一)

建立镜像构建配置:


腾讯云容器微服务API设计(一)


Dockerfile文件在根目录,所以不需要添加路径,如果不在根目录,需要格外添加修改,例如你的项目名称为test,Dockerfile在目录123/456下面,那么Dockerfile路径应该填写为 123/456/Dockerfile. 


腾讯云容器微服务API设计(一)

配置完成后,点击立即构建镜像,大概需要5~10分钟构建: 


腾讯云容器微服务API设计(一)


镜像构建完成后,在CCS上创建服务。如果定义了触发条件,每次源码发生变化,就可以触发服务更新,使用最新的容器镜像:


腾讯云容器微服务API设计(一)

查看容器中正在运行的进程,确认项目已经在运行:


腾讯云容器微服务API设计(一)



查询ELKService的状态,收到回复如下所示:


 

构建ServiceDiscovery容器, 以及调用API Gateway防护ELKServiceAPI ,等不同服务在容器中的调用,我们会在系列(二)中详述,希望大家持续关注。 


【附录】

 [1] https://cloud.tencent.com/developer/article/1005427 

 [2] https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/05.5.md 

 [3] https://docs.docker.com/engine/reference/builder/#entrypoint

 [4] http://www.linuxidc.com/Linux/2018-01/150348.htm

 [5] https://www.gfzj.us/2015/07/07/dockerfile_set_PATH.html

 [6] https://yeasy.gitbooks.io/docker_practice/content/basic_concept/image.html

 [7] https://cloud.tencent.com/document/product/457/9115

 [8] https://cloud.tencent.com/document/product/583/9734 

以上是关于腾讯云容器微服务API设计的主要内容,如果未能解决你的问题,请参考以下文章

部署微服务于容器云平台,API网关应如何选择?

在容器云平台部署微服务,API网关应如何选择?

微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计

基于容器微服务的PaaS云平台设计 实现容器微服务和持续集成

微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)

微服务与K8S容器云平台架构