腾讯云容器微服务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数据库中,当服务发生变化,状态信息会更新数据库,提供实时信息给用户。
文会包括下面的主要信息:
安装测试ELK容器集群,在腾讯云上分别构建nginx-basiauth, elasticsearch, logstash, kibana 容器。
在CVM安装测试BeeGO,golong, 调试确认ELKServiceAPI可以工作正常
制作Dockerfile以及ENTRYPOINT,将ELKServiceAPI commit到GitHub,从github构建ELKServiceAPI容器镜像
**构建ServiceDiscovery镜像,此容器会监控ELKService状态,并写入ElkserviceAPI的MySQL数据库
附录参考资料,代码相关部分可以访问 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。
选择机型及主机配置:
在两台主机上分别跑下面的命令:【1】
sysctl -w vm.max_map_count=262144 -- 增大虚拟内存
echo 3 > /proc/sys/vm/drop_caches -- 内存不够,释放部分内存
接下来创建各个服务,我们选择从DockerHub拉取官方镜像:
创建 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
创建kibana服务,该服务包含一个kibana容器,kibana和Elasticsearch 之间以服务的方式连接。
配置项名称
配置值
服务名称
kibana
核数
1核
内存
512M
实例个数
1
镜像
kibana
镜像版本
5.4
网络方式
提供集群内访问方式,不在公网上直接暴露5601的端口
搭建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的用户密码文件
创建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端口
此时会在nginx上更新产生的日志信息,然后打开kibana,确认更新的日志信息会完全呈现:
接下来, 在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 ,确认已经安装成功
下载需要的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
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:
在腾讯云容器CCS中新建镜像仓库 -- elkapitest
建立镜像构建配置:
Dockerfile文件在根目录,所以不需要添加路径,如果不在根目录,需要格外添加修改,例如你的项目名称为test,Dockerfile在目录123/456下面,那么Dockerfile路径应该填写为 123/456/Dockerfile.
配置完成后,点击立即构建镜像,大概需要5~10分钟构建:
镜像构建完成后,在CCS上创建服务。如果定义了触发条件,每次源码发生变化,就可以触发服务更新,使用最新的容器镜像:
查看容器中正在运行的进程,确认项目已经在运行:
查询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设计的主要内容,如果未能解决你的问题,请参考以下文章
微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计
基于容器微服务的PaaS云平台设计 实现容器微服务和持续集成