在单个节点上最快速度安装Mesos

Tags mesos centos marathon etcd flannel


2016-07-28 23:16:25


背景

在写Mesos应用的时候会用到这个Case

网络安装脚本

本地安装脚本

注意安装文件本地化的位置。在脚本里面了请提前下载

配置

HostIP='192.168.56.112'
IFACE='enp0s3'

配置本机IP地址以及对外访问的Interface名字,可能的都有ethX,emX,enpXsX等。

安装组件:

1. Mesos
2. Marathon
3. Flannel
4. ETCD

注意Docker需要自行安装

总结

速度很快,成功率很高。适合自己在单点的时候开发应用。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

近期的工作失误

Tags etcd


2016-06-23 07:04:36


背景

做配置同步,机器数量非常非常多。错误波及范围在几百台,一方面我是数据流设计的太过负载没有做好功能上的取舍,造成了服务发现端与agent端双写的状态。以及由于错误的操作计划导致,不正确的异常处理造成的综合错误。

服务异常处理设计错误

  1. 在服务配置解析的异常处理中直接使用了暴力的进程Fatal进行处理,导致进程在初始化结束之后还在做类似的处理。每隔一段事件应该检查一下类似的问题。不然会造成明显的系统崩溃
  2. 历史原因: 在之前的开发中由于配置的初始化处于初始化的位置,后来因为设计修改。变成了配置重新载入时候的代码引入了此bug。
  3. 在抛出错误之后,并没有对系统状态,或者当前的业务逻辑进行错误处理,只处理了错误数据。比如说该逻辑应该break 或者 continue 或者 return 这部分容易落下。

当前最高时间性价比错误避免的方法:

  1. 基于上面的错误发生应该反复核对设计图纸,对于服务器比较多的场景,更应该对设计图纸的重视程度反复核对有没有设计上的逻辑错误。
  2. 使用测试的方法来防止细节上的错误。
  3. 在开发中逻辑最清晰的时候在工作日志中标记出测试Case

之前模块设计的错误

由于模块设计的读写职责不够情绪,想要的功能太多,想在ETCD里面备份要同步,要故障恢复等等的功能。 导致多个进程之间可读可写,逻辑越来越复杂,BUG非常多。维护起来很麻烦。

事故小记:

  1. 部署计划中写的很清楚如果自动化服务发现进程在线上表现不佳,那么就可以手动删除所有配置,让线上服务器自动回复上一次配置。 1.1 因为我知道ETCD如果全挂了都没有事情。因为Agent还可以用上一次正确的配置 1.2 我测试过了任何ETCD情况下Agent是否能启动。所以不会影响线上监控。

事故过程,HBS删除数据后触发所有Agent重新读取配置,结果为空。到时json.Unmarshal Panic进程崩溃后Supervisor 或者 Systemd重启进程。 并且使用上一次正确的配置,停止当前所有监控周期,导致所有Agent监控周期同步,由于大家的周期普遍在10-30秒的范围内。进一步的 同时执行了数据库写操作,然后InfluxDB集群整个全部挂掉,才500台服务器就搞成这个样子。

之后Agent全部停掉,分批重启解决问题。

技术全局性不足,无法解决模块解耦问题,工作流读写职责问题。

  1. 我是知道我现在要做什么功能,应该做什么功能了。
  2. 我知道重要级,先做重要且紧急的事情。
  3. 但是模块逻辑安排在模块比较多的时候我多应该考虑考虑。这些功能加在这些模块里面是否合适。
  4. 应该再多思考一遍。该谁做,用何种方式做,工程成本,维护成本应该给出大概工期评估。
  5. 而且我没分清人和自动化之间的关系。

关于自动化

  1. 日常重复操作过多。
  2. 数据库种类过多。
  3. 机房有点多,每个机房的CMDB数据触发的BUG基本不同。
  4. 自动化来解决重复劳动的问题。以及排除由于调试时候的操作失误问题。
  5. 自动化解决资源调度问题,数据多,数据库多。
  6. 可怕!光资源调度就要搞好久。

git小习惯:

  1. 我的确有一个不良的习惯按照时间提交git感觉差不多了commit一次。
  2. 我应该做到的是,我做完一个小的事情我就要提交一次做一次备份,但是不一定push上去。

总结几个不争的事实。

  1. 只要我一上手动服务器,一定会出错,每次升级线上的东西都会发生这种事。而且一错就是一个机房。
  2. 基础太薄弱。可怕!我得好好研究研究大神怎么做到的,才能知道我现在应该做什么。就跟想完好LOL比较省力玩好的方法就是看大神的视频。
  3. 我们的确需要一个服务器注册与发现了。跟CMDB无关。

本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

RancherOS iPXE 启动以及ISO重新打包的方法

Tags rancher docker linux iPXE PXE syslinux virtualbox


2016-06-11 22:32:57


VER: 1

意义

最近一直在尝试自己写一服务器平台方便自己和别人开发的,能把流程做进去最好了。 但是万事开头难,在尝试了CoreOS iPXE 启动方法之后发现Image太大大概要200mb+的样子。 Boot2Docker始终没找到正确的看文档的方式,这种方法我个人预估也只能是Docker ToolBox使用比较靠谱了。 然后开始尝试RancherOS的IPXE启动操作系统但是但是很不稳定,有的时候Cloud-init下载不了。 大概2次就有一次无法启动不能忍,但是不用cloud-init还好,但是也是去了在我这里使用的意义。 这种只适合大规模的集群部署。不得不说他们的工作真的很赞。

那么要满足我的需求:

  1. Image 要小
  2. 开机迅速,可定制。各种系统配置。
  3. 稳定不容易出错。
  4. 自动持久化。
  5. 可以持续集成打包。

那么就只有一个路线syslinux使用mkisofs这个工具重新打包RancherOS最后我自己打包的结果30mb 比官方的还小1mb还可以对docker 进行自动持久化。方便在不同系统种分发Docker daemon

iPXE 启动的方法:

VirtualBox参考启动:

VBoxManage createvm --name "service" --register
VBoxManage modifyvm "service" --memory 512 --acpi on --boot1 dvd
VBoxManage modifyvm "service" --nic1 hostonly --hostonlyadapter1 vboxnet0 --nicpromisc1 allow-all
VBoxManage modifyvm "service" --nic2 nat  --natnet2 "192.168/16" --natpf2 "guestssh,tcp,,2222,,22" --nicpromisc2 allow-all
VBoxManage modifyvm "service" --ostype Linux

VBoxManage createhd --filename /mnt/vdis/io.vdi --size 10000
VBoxManage storagectl "service" --name "IDE Controller" --add ide
VBoxManage storageattach "service" --storagectl "IDE Controller"  \
    --port 0 --device 0 --type hdd --medium /mnt/vdis/io.vdi
VBoxManage storageattach "service" --storagectl "IDE Controller" \
    --port 1 --device 0 --type dvddrive --medium /mnt/git/ipxe/src/bin/ipxe.iso

因为总是需要重新启动调试所以这里把所有的VBOX操作都自动化。提升调试速度。

ipxe.iso 重新打包

因为要针对我们的using case使用,我们需要自动化boot一个固定的操作系统 所以这里要针对我们的脚本重新打包。

iso重新打包命令如下

git clone git://git.ipxe.org/ipxe.git
cd ipxe/src
make bin/ipxe.iso EMBED=bootscript

打包依赖:

gcc (version 3 or later)
binutils (version 2.18 or later)
make
perl
syslinux (for isolinux, only needed for building .iso images)
liblzma or xz header files

bootscript 的内容:

#!ipxe

dhcp
chain http://192.168.56.1:8089/boot.html

注意: boot的时候请求的整个地址返回的内容为启动脚本。

启动脚本内容:

#!ipxe
# Boot a persistent RancherOS to RAM

# Location of Kernel/Initrd images
set base-url http://192.168.56.1:8089

kernel ${base-url}/vmlinuz044 rancher.state.formatzero=true rancher.state.autoformat=[/dev/sda] rancher.cloud_init.datasources=['url:http://192.168.56.1:8089/rancheros.yml']
initrd ${base-url}/initrd044
boot

然后就可以启动RancherOS了。

启动流程说明: 虚拟机启动->启动ipxe DVD->Chain load 请求 boot.html -> iPXE 根据boot.html下载 vmlinuz initrd -> 带入参数启动Linux(其实PE之类的也都好使)

参考文档:

重新打包RancherOS 系统image

虽然官方提供了Release下载但是这里面的iso对于我的使用场景来说还远远不够。 首先默认密码不能是固定的rancher,另外Docker 自动持久化的部分并没有做,另外就是Docker启动参数我不想用默认的我需要有一定的调整。这些原因通过iPXE.iso重新打包的方法学习之后促成了这一想法虽然简单,但是kernel参数的调整的确花费了我至少2-3小时的时间。为了避免自己再次踩坑来写一些说明。

VBOX 调试脚本

VBoxManage createvm --name "service" --register
VBoxManage modifyvm "service" --memory 512 --acpi on --boot1 dvd
VBoxManage modifyvm "service" --nic1 hostonly --hostonlyadapter1 vboxnet0 --nicpromisc1 allow-all
VBoxManage modifyvm "service" --nic2 nat  --natnet2 "192.168/16" --natpf2 "guestssh,tcp,,2222,,22" --nicpromisc2 allow-all
VBoxManage modifyvm "service" --ostype Linux

VBoxManage createhd --filename /mnt/vdis/io.vdi --size 10000
VBoxManage storagectl "service" --name "IDE Controller" --add ide
VBoxManage storageattach "service" --storagectl "IDE Controller"  \
    --port 0 --device 0 --type hdd --medium /mnt/vdis/io.vdi
VBoxManage storageattach "service" --storagectl "IDE Controller" \
    --port 1 --device 0 --type dvddrive --medium /mnt/git/rancheros.iso

打包命令(build.sh):

mkisofs -o ros.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table rosiso/

打包后结果

├── build.sh
├── rosiso
│   ├── initrd
│   ├── isolinux
│   │   └── isolinux.bin
│   ├── isolinux.cfg
│   └── vmlinuz
└── ros.iso

文件来源:

  • initrd 以及vmlinuz 从rancheros release 页面获取
  • isolinux.bin 如果是ubuntu文件的位置在: /usr/lib/syslinux/isolinux.bin
  • boot.cat 是自动生成的
  • ros.iso 生成的系统镜像

isolinux.cfg 启动参数定制

default rancheros
label rancheros
    kernel /vmlinuz
    initrd /initrd
    append quiet rancher.password=rancher rancher.state.autoformat=[/dev/sda] rancher.state.formatzero=true 

参数解释:(从quiet之后开始)

  • rancher.password 设置默认账户密码。
  • rancher.state.autoformat 自动格式化磁盘。
  • Starts with 1 megabyte of zeros and rancher.state.formatzero is true.
  • 参数顺序会影响系统稳定性。
  • 所有参数查看需要等启动之后sudo ros c export -f > cfg.yml 几乎所有参数都可以调整,另外单独一个参数里面不能有空格kernel的参数检查比cloud-init模块本身严格多了。
  • 上面这种方式为cmdline操作系统源码 在GetDatasources 函数这里。

参考文档:

Windows 启动参考

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" createvm --name "service" --register
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "service" --memory 512 --acpi on --boot1 dvd
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "service" --nic1 hostonly --hostonlyadapter1 "VirtualBox Host-Only Ethernet Adapter" --nicpromisc1 allow-all
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "service" --nic2 nat  --natnet2 "192.168/16" --natpf2 "guestssh,tcp,,2222,,22" --nicpromisc2 allow-all
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "service" --ostype Linux

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" createhd --filename D:\io.vdi --size 10000
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" storagectl "service" --name "IDE Controller" --add ide
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" storageattach "service" --storagectl "IDE Controller"  --port 0 --device 0 --type hdd --medium D:\io.vdi
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" storageattach "service" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium D:\ros.iso

注意: hostonly 网卡名字

vboxmanage 踩坑

查看所有hostonly网卡:

VBoxManage list hostonlyifs

创建网卡并配置DHCP

VBoxManage hostonlyif create
VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.56.1
VBoxManage dhcpserver add --ifname vboxnet0 --ip 192.168.56.1 --netmask 255.255.255.0 --lowerip 192.168.56.254 --upperip 192.168.56.200
VBoxManage dhcpserver modify --ifname vboxnet0 --enable

注意上面如果是windows注意换网卡名字

总结

  • 新打包好的系统大小30MB
  • 启动时间10s左右(机械硬盘)
  • 强制关机,重新启动10次以上无错误。每次测试都有不同的小操作。

本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

Docker 私有镜像最基本调试

Tags nginx docker registry


2016-04-21 23:28:09


VERSION:1

背景

Registry 作为Docker的重要基本组件,无论是在自己的内网搭建,或者是公网私有带宽搭建都是托管私有Image的好方法。

Step1 Docker Image准备

docker pull index.alauda.cn/library/registry:2.3
docker pull index.alauda.cn/library/nginx
docker tag index.alauda.cn/library/registry:2.3 registry:2.3
docker tag index.alauda.cn/library/nginx:latest nginx:latest

Step2 Nginx 配置文件准备

docker run -it --rm -v /root/:/data/ nginx cp -rf /etc/nginx /data/ngreg
cat > /root/ngreg/conf.d/reg.conf << EOF
server {
    listen       443;
    server_name XXX.XXX.XXX;

    ssl on;
    ssl_certificate /etc/nginx/XXX.XXX.XXX/fullchain1.pem;
    ssl_certificate_key /etc/nginx/XXX.XXX.XXX/privkey1.pem;
    add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
    client_max_body_size 0;
    chunked_transfer_encoding on;

    location / {

        if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
          return 404;
        }

        proxy_pass                          http://reg.prod:5000;
        proxy_set_header  Host              $http_host;   # required for docker client's sake
        proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;
        proxy_read_timeout                  900;
  }
}
EOF

在上面的脚本重需要修改的是: 1. XXX.XXX.XXX 需要修改成您自己的域名 2. 如果需要申请证书请参考:http://www.philo.top/2016/04/06/letsencryptSSLApply/

配置解释: 1. 默认使用HTTPS协议。 2. header添加指定registry版本。 3. 设置body长度为0无限制长度。 4. 拒绝低于docker1.6版本的访问。 5. 反向代理到docker registry 容器。 6. 其他Headers都是参考文档得到的。

Step3 简单账号配置:

配置修改

        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/htpasswd;

上面这两段,放到location下面就可以了。

账号密码文件生成工具

Step4 开始服务

docker network create prod
docker run -it -d --name ngreg --net=prod -v /root/ngreg/:/etc/nginx -p 0.0.0.0:443:443 nginx
docker run -it -d --name reg --net=prod -v /data:/regdata registry:2.3

总结

  1. 需要根据自己的需要来进行配置文件的修改。
  2. 次文档为最低成本限度的registry部署。

之后要面临的挑战

  1. 使用registry2.4进行GC
  2. auth上微服务。
  3. 存储管理。(OSS,UFile,等等这些产品。)
  4. Public Private 控制。

本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

letsencrypt HTTPS SSL 证书在不影响生产的情况下申请

Tags letsencrypt docker nginx


2016-04-06 16:22:14


VERSION: 1

TODO:

自动续期

背景

在线上运行的nginx web service 需要持续不间断的做生产服务,这时候证书需要更新,LE又需要独立占用一个端口这里使用webroot的方式实现证书申请。 同时为了不占用线上服务器的端口,并且发挥docker的优势不需要装太多的软件。因此做了这个法案。

部署结构

           反向代理             文件共享
线上Nginx ----------> LE nginx ---------> LE container

准备nginx配置文件

docker run -it --rm -v /root/:/data/ nginx cp -rf /etc/nginx /data/le
mkdir /root/le/static
echo a >> /root/le/statuc/index.html

LE nginx

配置文件

server {
    listen       80;
    server_name  localhost;

    location / {
        root   /etc/nginx/static/;
        index  index.html index.htm;
    }
}

运行方法

docker run -it -d --name lenginx -p 8989:80 -v /root/le/:/etc/nginx/ --net=aaa nginx

测试

# curl http://127.0.0.1:8989/
a

如果测试结果有返回自己输入的hml内容即为成功。

域名配置

开始配置目标域名A 记录到服务器

线上服务Nginx 配置调整:

在 server 配置中加入如下location配置

location /.well-known {
    proxy_pass http://lenginx.aaa;
}

以容易的方式运行LetsEncrypt

docker run -it -d --name le -v /root/le/static/:/webroot index.tenxcloud.com/philo/le:0 /bin/bash

在LE容器中申请证书

letsencrypt-auto certonly -a webroot --webroot-path=/webroot -d example.com -d www.example.com

总结

当使用LE申请证书的时候,LE的服务器(我抓到的IP地址 66.133.109.36)会请求你的域名到类似这种地址位置:/.well-known/acme-challenge/j3r4u4GEXbYIqjbGotSqbBRNp_3sohuzZw_G5Aw1lcI 所以这里在线上服务器使用反向代理到LE共享磁盘位置的nginx中,是的LE服务器访问我们的服务器授权正常。就ok了。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

使用aglio自动化管理API文档

Tags npm nodejs aglio docker shell git nginx


2016-04-05 22:25:28


VERSION: 1

背景

前后端需要良好的沟通交流环境无法离开实时更新的文档,我没无法离开实时更新的API接口文档。使用Github hooks在服务器上实现文档自动更新是一个不错的选择。

注意本文中hook代码中删掉了所有安全验证的内容

托管容器

文档的托管容器只管所有的关键其他的所有东西都没有。 既: 环境与业务分离,以任务执行的不同来分割容器。

FROM node
RUN apt-get update && apt-get install -y git build-essential curl vim && apt-get clean
RUN npm install aglio -g
CMD bash /e.sh

注意:容器构建时由于包本身需要构建的原因,使用内存会达到2gb。

自动运行脚本 e.sh

echo "build time" $(date)
cd /root/
rm -rf XXX-doc
git clone --depth=1 git@github.com:XXX/XXX-doc.git
cd XXX-doc
nohup aglio -i android.md -h 0.0.0.0 -p 3001 -s >> /tmp/log 2>&1 &
nohup aglio -i admin.md -h 0.0.0.0 -p 3002 -s >> /tmp/log 2>&1 &
tail -F /tmp/log

首先给出自动化build时间,紧接着在容器中下载代码,进入后直接使用命令运行。最后不要忘记输出日志。

钩子容器

package main

import (
    "bytes"
    "io"
    "net/http"
    "os"
    "os/exec"

    "github.com/wothing/log"
)

// hello 文档管理的首页,提供强制更新容器的方法。
func hello(w http.ResponseWriter, r *http.Request) {
    resp := `<h1>CURRENT STATUS <a href="/afejid">force update</a></h1><pre>`
    o, e := CMD("docker logs --tail=100 docs_running_container")
    resp = resp + o
    resp = resp + e
    resp = resp + "</pre>"
    io.WriteString(w, resp)
}

// afejid 重启容器触发,容器重启之后会从新clone代码以及重新生成文档。
func afejid(w http.ResponseWriter, r *http.Request) {
    // !!! 这里不要忘了安全验证。
    io.WriteString(w, "updateing already started")
    go CMD("docker restart docs_running_container")
}

func main() {
    http.HandleFunc("/", hello)
    http.HandleFunc("/afejid", afejid)
    http.ListenAndServe(":8000", nil)
}

// CMD 调用系统命令。
func CMD(order string) (string, string) {
    log.Tinfof("", "RUN: %s", order)
    cmd := exec.Command("/usr/bin/script", "-e", "-q", "-c", order)
    var out bytes.Buffer
    var stderr bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = &stderr
    err := cmd.Run()
    if err != nil {
        log.Terrorf("", "%s --> %s \n order return none zero code STDERR: \n %s", order, err.Error(), stderr.String())
        os.Exit(1)
    }
    return out.String(), stderr.String()
}

ngxin 配合

这里主要涉及的问题是一个端口给两个端口的应用使用。 我们这里使用路由分开。在本文中给出了两个例子,一个是安卓的API另外一个是管理端的API

使用技术内容: nginx rewrite + proxy_pass

这里我们给出访问安卓的方法 doc.XXX.XXX/android

nginx 配置参考

    location ^~/android {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/htpasswd;
        rewrite /android(.*) /$1  break;
        proxy_pass http://docs_running_container.aaa:3001/;
    }

注意:location 内第一行第二行的内容为账号密码验证。

总结

在此次实践中想了非常多的东西对依赖的分析执行的计划思考,以及更新hook调度的范围,以及真个项目的复用都进行了成本考量。还是花了不少时间。在这了做了一些简单的小终结。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

GitHook自动检查版本冲突问题

Tags git


2016-04-05 14:14:07


VERSION: 1

背景

为了解决团队代码同步的痛点,每次commit之前都需要检查一次当前主仓库的情况。及时了解其他人的PR动向。

Fork主仓库的情况

从主仓库Fork到自己的github账号下的工作模式。

echo BEFORE COMMIT
ex=$(git remote -v  | awk '{printf "%s\n",$1}' | grep wothing | wc -l)
if [[ $ex == 0 ]];then
    git remote add wothing https://github.com/XXXXX/XXXX.git
fi
git fetch wothing
echo -e "UR \033[32m ahead $(git rev-list  --left-only develop...wothing/develop | wc -l)  \033[0m commits before" 
echo -e "UR \033[31m behind $(git rev-list  --right-only develop...wothing/develop | wc -l) \033[0m commits after"

添加此文件到.git/hooks/pre-commit 即可 提示在您Commit之前落后主仓库多少版本。

上面的脚本注意修改主仓库的地址。

缺点

  1. fetch远程仓库比较费时间尤其是github上

Feature Branch 方法

git fetch 
echo -e "UR \033[32m ahead $(git rev-list  --left-only master...develop | wc -l)  \033[0m commits before" 
echo -e "UR \033[31m behind $(git rev-list  --right-only master...develop | wc -l) \033[0m commits after"

文件同上一种方法一致。

总结

Github的速度真的是非常慢,所以还是建议在GOGS上面做比较好。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。

ELK安装与调试

Tags elk elasticsearch kibina logstash docker


2016-03-30 11:06:19


VERSION:1.1

更新

2016年04月16日17:30:24

  1. ubuntu镜像更新
  2. 添加百度网盘下载
  3. 修正logstash 检查config的bug添加一个注意事项
  4. 修改配置文件中的明显问题

环境Version

java 8u77
elasticsearch 2.2.1
logstash 2.2.2
kibana 4.4.2

快速下载通道:

http://pan.baidu.com/s/1qYCFvvY

背景:

随着业务量的增长对于日志的处理显得越来越重要。主要需求来源于各种数据的统计,数据的分析。以及对于可以用户的查询,系统故障的排查与监控。

本文为入门比较浅显讲述ELK的安装,不涉及到生产方面的内容,在未来还会更新更佳深入的实践或者线上实战的内容。

我当时学习的参考文档:

elastic

在文档上官方详细程度足够,ELK文档质量好评,结合本文进行实践相信您一定会非常顺利的使用ELK。

方法论

通过脚本自动化构建docker容器。通过固定的脚本减少重复工作带来的辛苦。专注于技术研究。

环境依赖包下载

wget https://www.reucon.com/cdn/java/jdk-8u77-linux-x64.tar.gz
wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.2.1/elasticsearch-2.2.1.tar.gz
wget https://download.elastic.co/logstash/logstash/packages/debian/logstash_2.2.2-1_all.deb
wget https://download.elastic.co/kibana/kibana/kibana-4.4.2-linux-x64.tar.gz
tar xf elasticsearch-2.2.1.tar.gz
tar xf jdk-8u77-linux-x64.tar.gz
tar xf kibana-4.4.2-linux-x64.tar.gz
mkdir -p el ki lo
mv kibana-4.4.2-linux-x64 kibana
mv elasticsearch-2.2.1 elasticsearch
mv jdk1.8.0_77 jdk
mv elasticsearch el
cp -rf jdk el
mv jdk lo
mv kibana ki
mv logstash_2.2.2-1_all.deb lo

执行内容:

  1. 下载安装包
  2. 解压安装包
  3. 整理ELK到固定的文件夹,用名字开头两个字母来区分
  4. 吧解压好的安装包改了名字放到固定的位置上去。

其中:

  1. kibana是不需要java环境的。
  2. 我的java环境下载是通过CDN下载的效果还不错。
  3. 被墙的很厉害。建议到国外的VPS上实践,我用的Vultr (连接有小尾巴,谢谢支持。)
  4. 注意内存一定要大于1gb ELK启动后空载的内存使用为900mb左右。

准备好之后检查所有包的位置是否正确

root@elk:~# ls el
elasticsearch  jdk
root@elk:~# ls ki
kibana
root@elk:~# ls lo
jdk  logstash_2.2.2-1_all.deb

Dockerfile

Docker 可以让环境的构建的问题可以复现,构建好的环境可以分发。用来研究问题非常方便。

注意: 在本环境中所有的配置文件没有做成环境变量与气动脚本,因此变量都是固定的,尤其要注意网卡的创建elastic避免不必要的时间浪费。 在未来的研究中笔者将会构建生产中使用的ELK容器,会考虑扩展性与灵活性。在本例中只考虑安装特性研究配合看查看官方文档学习。

Elasticsearch

cat >> /root/el/Dockerfile << EOF
FROM ubuntu:14.04.4
ADD jdk /usr/local/jdk
ADD elasticsearch /usr/local/elasticsearch
ENV JAVA_HOME /usr/local/jdk
ENV PATH $PATH:/usr/local/jdk/bin:/usr/local/elasticsearch/bin/
RUN useradd -d /home/elasticsearch -m elasticsearch
RUN mkdir -p /data && echo "path.data: /data" >> /usr/local/elasticsearch/config/elasticsearch.yml && echo "network.host: 0.0.0.0" >> /usr/local/elasticsearch/config/elasticsearch.yml &&chown -R elasticsearch /usr/local/elasticsearch && chown -R elasticsearch /data
USER elasticsearch
CMD elasticsearch
EOF

请注意,由于Elasticsearch不可以使用root用户运行。因此需要针对data文件夹的挂载创建系统所需运行账户。 在本例中,使用如下命令创建用户。useradd -d /home/elasticsearch -G root -s /bin/bash elasticsearch

kibana

cat >> /root/ki/Dockerfile << EOF
FROM ubuntu:14.04.4
ADD kibana /usr/local/kibana
RUN echo "port: 5601" >> /usr/local/kibana/config/kibana.yml && echo "host: 0.0.0.0" >> /usr/local/kibana/config/kibana.yml && echo "elasticsearch_url: http://elasticsearch.elastic:9200" >> /usr/local/kibana/config/kibana.yml
ENV PATH $PATH:/usr/local/kibana/bin/
CMD kibana
EOF

Logstash

cat >> /root/lo/Dockerfile << EOF
FROM ubuntu:14.04.4
ADD jdk /usr/local/jdk
ADD logstash_2.2.2-1_all.deb /logstash_2.2.2-1_all.deb
ENV JAVA_HOME /usr/local/jdk
RUN dpkg -i /logstash_2.2.2-1_all.deb
ENV PATH $PATH:/opt/logstash/bin:/usr/local/jdk/bin
CMD logstash agent -f /conf
EOF

构建

docker build -t el:0 /root/el/
docker build -t ki:0 /root/ki/
docker build -t lo:0 /root/lo/

构建之后查看容器结果

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
lo                  0                   6592f152333d        3 minutes ago       763.8 MB
ki                  0                   fd93c06a3d4e        4 minutes ago       312.3 MB
el                  0                   4395211af2d0        4 minutes ago       619.5 MB
ubuntu              14.04.3             3876b81b5a81        9 weeks ago         187.9 MB

logstash 测试用配置文件


input {
    file {
        path => "/syslog"
        start_position => beginning
        ignore_older => 0
    }

}

output {
    elasticsearch {
        hosts => "elasticsearch.elastic"
    }
    file {
        path => "/data/%{+YYYY-MM-dd}/%{host}.log.gz"
        gzip => true
    }
}

注意文件的后缀名为 .conf

在本例配置文件中,入口方式为监控syslog输出为elasticsearch 以及按照天与容器到压缩包。 方便备份。 配合上面的dockerfile请将上面的配置文件放到/root/conf/

logstash 配置文件的检查。

由于配置文件格式复杂,并且运行之后不能轻易修改(技术不到位)因此在运行之前一定要做好检查工作。

docker run -it --rm -v /root/conf/:/conf -v /root/logstash/:/data/ --net=elastic lo:0 logstash -t -f /conf

注意检查中会检查文件夹权限,如果错误是不会通过的。所以需要先运行下面的elastic 和kibana 运行脚本

运行ELK

useradd -d /home/elasticsearch -s /bin/bash elasticsearch
mkdir -p /root/data
chown -R elasticsearch /root/data
docker network create elastic
docker run -it -d --name elasticsearch -v /root/data:/data --net=elastic el:0
docker run -it -d --name kibana -p 5601:5601 --net=elastic ki:0
docker run -it -d --name logstash -v /root/conf/:/conf -p 12201:12201/udp -v /root/logstash/:/data/ -v /var/log/syslog:/syslog --net=elastic lo:0
  1. 创建用户
  2. 创建Elasticsearch所需的文件夹
  3. 修改文件夹权限
  4. 创建docker网卡
  5. 运行Elasticsearch
  6. 运行 kibana
  7. 运行logstash

最后输出结果,elasticsearch 文件会输出到/root/data 中,logstash的日志压缩备份会放到/root/logstash

总结

由于时间有限,有一些问题没有能够及时补充发现,很抱歉。在实践中的确遇到了很多坑,尤其是对java虚拟机的不熟悉造成的一些问题。 占用了我不少时间,虽然查看文档需要占用很多时间,但是从中等时间的角度考虑是占优的十分推荐官方文档的阅读。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。