最近使用兩天使用吃奶的力氣在處理 舊版(CentOS-5) / 新版(Ubuntu-1604/CentOS7) 在 log forwarder 的相容性,前陣子有提到 elastic 現代化的 ELK/EFK Log 架構大補帖 在 Node 上可以用 filebeat / logstash 來收

問題來了 … 用來當中介 filter 的 logstash input (6.x) 如果和 Node 的版本 output (1.x) 差太多的話會有不相容的狀況發生 (NoMethodError),如果要和 6.x 的 logstash 相容至少要上到 5.x later … 索性先放棄 logstash 當 log forwarder。
在 elastic 的支援清單看到 filebeat 全面不支援 CentOS 5 瞬間想哭,後來有高手同事建議可以用 rpmbuild 來嘗試在 CentOS 來 build 看看,結果真的可以動!!
這篇就是要講怎麼用 rpmbuild 來 build 出可用的 rpm,範本當然就是 filebeat!!
話先講在前面,如果很懶得 build 也提供給各位 rpm 下載:MEGA
CentOS 5 用 rpmbuild filebeat 6.x
環境:
- OS:CentOS 5.x x86_64
這個方案 x86_64 / i686 都適用,只是 x86_64 build 出來的只能給 x86_64 的機器裝,不能混用。
Step.1 yum 安裝 rpmbuild
$ sudo yum install rpm-build redhat-rpm-config -y
Step.2 建立 build 資料夾結構
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ cat <<EOF >~/.rpmmacros
%_topdir %(echo $HOME)/rpmbuild
%_tmppath %{_topdir}/tmp
EOF
- BUILD:RPM 安裝內容自動建立的位置
- RPMS:Build 出來的 RPM Package
- SOURCES:包好的 source code (example.tar.gz)
- SPECS:RPM 建立的規格檔 (build spec)
- SRPMS:Source RPM
.rpmmacros 則是定義在使用 rpmbuild 時預設的路徑。
Step.3 下載最新版的 filebeat (6.2.4)。
$ curl -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.2.4-linux-x86_64.tar.gz $ tar zxvf filebeat-6.2.4-linux-x86_64.tar.gz && mv filebeat-6.2.4-linux-x86_64 filebeat-6.2.4_x86_64_el5-acme
Step.4 filebeat 裡面的 source code 沒有 init 啟動服務的 script,所以把這部份加進去
$ mkdir filebeat-6.2.4_x86_64_el5-acme/init.d
$ tee filebeat-6.2.4_x86_64_el5-acme/init.d/filebeat <<EOF
#!/bin/bash
PATH=/usr/bin:/sbin:/bin:/usr/sbin
export PATH
[ -f /etc/sysconfig/filebeat ] && . /etc/sysconfig/filebeat
pidfile=${PIDFILE-/var/run/filebeat.pid}
agent=${BEATS_AGENT-/usr/share/filebeat/bin/filebeat}
args="-c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat"
RETVAL=0
# Source function library.
. /etc/rc.d/init.d/functions
if status | grep -q -- '-p' 2>/dev/null; then
daemonopts="--pidfile $pidfile"
pidopts="-p $pidfile"
fi
test() {
$agent test config -c /etc/filebeat/filebeat.yml > /dev/null
}
start() {
echo -n $"Starting filebeat: "
test
if [ $? -ne 0 ]; then
echo
exit 1
fi
if ps a | pgrep -f $agent > /dev/null; then
failure
echo;
exit 1
fi
$agent $args &
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
success
echo $! > $pidfile
fi
echo
return $RETVAL
}
stop() {
echo -n $"Stopping filebeat: "
killproc $agent
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f ${pidfile}
}
restart() {
test
if [ $? -ne 0 ]; then
return 1
fi
stop
start
}
rh_status() {
status $pidopts $agent
RETVAL=$?
return $RETVAL
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
status)
rh_status
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
esac
exit $RETVAL
EOF
啟動 script 有土炮一些作法,因為原本 filebeat 是用 filebeat-god 來管理服務,但是 source code 沒有,也懶得再 build filebeat-god ….
Step.5 打包丟到 rpmbuild/SOURCES
$ tar zcvf filebeat-6.2.4_x86_64_el5-acme.tar.gz filebeat-6.2.4_x86_64_el5-acme $ mv filebeat-6.2.4_x86_64_el5-acme.tar.gz rpmbuild/SOURCES/
Step.6 再來是寫 spec 定義怎麼 build 和安裝
$ tee rpmbuild/SPECS/filebeat-6.2.4_x86_64_el5-acme.spec <<EOF
# Don't try fancy stuff like debuginfo, which is useless on binary-only
# packages. Don't strip binary too
# Be sure buildpolicy set to do nothing
%define __spec_install_post %{nil}
%define debug_package %{nil}
%define __os_install_post %{_dbpath}/brp-compress
Summary: Custom Filebeat log transfer system service
Name: filebeat
Version: 6.2.4_x86_64_el5
Release: acme
License: Apache-2.0
Group: System/Monitoring
Source: %{name}-%{version}-%{release}.tar.gz
Url: https://www.elastic.co/products/beats/filebeat
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
Requires: logrotate
%description
%{summary}
%prep
%setup -q -n %{name}-%{version}-%{release}
%build
# Empty section.
%install
## Add Filebeat binary to /usr/bin
%{__install} -d -m 755 %{buildroot}%{_bindir}
%{__install} -m 755 filebeat %{buildroot}%{_bindir}/%{name}
## Add Filebeat binary to /usr/share
%{__install} -d -m 755 %{buildroot}/usr/share/%{name}/
%{__install} -d -m 755 %{buildroot}/usr/share/%{name}/bin
%{__install} -m 755 filebeat %{buildroot}/usr/share/%{name}/bin/
## Add Filebeat modules
cp -rp module %{buildroot}/usr/share/%{name}/
## etc
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/%{name}/
%{__install} -m 644 *.yml %{buildroot}%{_sysconfdir}/%{name}/
cp -rp modules.d %{buildroot}%{_sysconfdir}/%{name}/
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/%{name}/conf.d
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/init.d
%{__install} -m 755 init.d/filebeat %{buildroot}%{_sysconfdir}/init.d/
## var
%{__install} -d -m 755 %{buildroot}/var/lib/%{name}/
%files
%defattr(-,root,root)
/*
%exclude %dir /etc/init.d
%changelog
* Sat Jun 3 2018 Scott Liao <scott.liao@104.com.tw> 6.2.4_x86_64_el5-acme
- build x86_64 for CentOS 5.
EOF
先定義 Summary, Name, Version 必要資訊
直接跳過看 %install 的部份,其實就是把需要的檔案搬到 %buildroot 這邊去,按照想要安裝的目錄結構放在以 %buildroot 為起始的位置
舉例這段 %{__install} -m 755 init.d/filebeat %{buildroot}%{_sysconfdir}/init.d/
其實就是把 init.d/filebeat 丟到 rpmbuild/tmp/etc/init.d/filebeat,而實際 rpm 安裝後會放在 /etc/init.d/filebeat 這邊。
%files 這段就是在打包檔案,%defattr 用來定義權限,%exclude 可以排除要打包的位置,( 如果不排除 /etc/init.d 安裝 rpm 時會跟 chkconfig 打架,exclude 後還是會把啟動 script 丟過去 /etc/init.d/filebeat )
最後就是 %changelog,這麼辛苦弄好,做個記錄吧!
Step.7 用 rpmbuild 打包成 rpm
$ rpmbuild -ba ~/rpmbuild/SPECS/filebeat-6.2.4_x86_64_el5-acme.spec
成功後可以在 ~rpmbuild/RPMS/x86_64 找到打包好的 filebeat-6.2.4_x86_64_el5-acme.x86_64.rpm
試試把 rpm 拿來安裝吧 !!
$ sudo rpm -ivh filebeat-6.2.4_x86_64_el5-acme.x86_64.rpm
Reference:
使用 RPM Build ,在Linux 打包 Package
Creating RPM package of Elastic Filebeat
