Rootop 服务器运维与web架构

2019-08-29
发表者 Venus
nginx 四层代理已关闭评论

nginx 四层代理

官方文档:http://nginx.org/en/docs/stream/ngx_stream_core_module.html
nginx四层代理需要ngx_stream_core_module模块支持,这个模块需要在nginx1.9版本之后。
默认这个模块不会编译,需要加编译参数–with-stream

[root@localhost nginx-1.17.3]# ./configure --prefix=/usr/local/nginx --with-stream

# 主配置文件通过include指令引入其他目录下的配置文件,便于管理。

[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events
{
	worker_connections  1024;
}

http {
	include       mime.types;
	default_type  application/octet-stream;
	sendfile        on;
	keepalive_timeout  65;
	server
	{
		listen       80;
		server_name  localhost;
		location /
		{
			root   html;
			index  index.html index.htm;
		}
	}
}
# 注意这个include是在http{}配置段外层,也就是说stream和http段是平级的。
include vhost/*.conf;

# 四层代理配置

[root@localhost conf]# cat vhost/a.conf 
stream {

	upstream ssh
	{
		server 192.168.10.74:22;
	}

	server
	{
		listen 8888;
		proxy_pass ssh;
	}
}

这样ssh登陆本机8888端口时,就会连接74这台机器的22端口。
upstream中可以写多个server,也支持会话保持。
会话保持参考官方文档:http://nginx.org/en/docs/stream/ngx_stream_upstream_module.html#hash

2019-08-28
发表者 Venus
fluentd接收docker日志转存到kafka (elasticsearch+fluentd+kafka+logstash+kibana)已关闭评论

fluentd接收docker日志转存到kafka (elasticsearch+fluentd+kafka+logstash+kibana)

系统版本:centos7
IP:192.168.10.74

组件版本:
logstash 6.6.2
elasticsearch 6.5.4
kibana 6.5.4
fluentd 1.3.2
kafka 2.12-2.3.0
都安装在本机。

目的:
docker容器(应用日志输出为json格式)日志通过log-driver直接输出到fluentd。
fluentd将接收的日志生产转存到kafka消息队列。
logstash从kafka中消费日志,经过处理后输出到elasticsearch中用于检索。
kibana展示。

# kafka消息队列
配置参考:https://www.rootop.org/pages/4508.html
此处略过

# 启动一个fluentd

[root@localhost]# docker pull fluentd
[root@localhost]# docker run -dit --name fluentd -p 24224:24224 -p 24224:24224/udp docker.io/fluent/fluentd

# 进入fluentd容器,配置转存kafka
fluentd docker版安装kafka插件 官网文档:https://docs.fluentd.org/output/kafka
1、安装插件

# fluent-gem install fluent-plugin-kafka

2、编辑配置文件

# vi /fluentd/etc/fluent.conf

<source>
  @type  forward
  @id    input1
  @label @mainstream
  port  24224
</source>

<filter **>
  @type stdout
</filter>

<label @mainstream>
  <match docker.**>
    @type file
    @id   output_docker1
    path         /fluentd/log/docker.*.log
    symlink_path /fluentd/log/docker.log
    append       true
    time_slice_format %Y%m%d
    time_slice_wait   1m
    time_format       %Y%m%dT%H%M%S%z
  </match>

  <match **>
    @type kafka2

    # list of seed brokers,这个地方可以通过逗号写多个地址比如 host1:9092,host2:9092
    brokers 192.168.10.74:9092
    use_event_time true

    # buffer settings
    <buffer topic>
	@type file
	# 下面的path可能需要手动创建目录,并给写入权限,我直接给了777
	path /var/log/td-agent/buffer/td
	flush_interval 3s
    </buffer>

    # data type settings
    <format>
	@type json
    </format>

    # kafka中创建的topic
    topic_key test
	# 默认topic
    default_topic test
    get_kafka_client_log true
    # producer settings
    required_acks -1
    compression_codec gzip
  </match>
</label>

保存退出,重启容器。

# docker容器通过log-driver输出到fluentd

[root@localhost]# docker run -dit --name name-api-2 -v /home/dockermount/api:/mnt --publish-all --log-driver=fluentd --log-opt fluentd-address=192.168.10.74:24224 --log-opt fluentd-async-connect java8t

docker fluentd官方资料:https://docs.docker.com/config/containers/logging/fluentd/
fluentd-async-connect # 此参数可以防止连不上fluentd导致容器退出。
Docker connects to Fluentd in the background. Messages are buffered until the connection is established. Defaults to false.
If container cannot connect to the Fluentd daemon, the container stops immediately unless the fluentd-async-connect option is used.
目前为止,容器日志已经可以写入kafka了。

# 安装es、kibana

[root@localhost log]# docker run -dit --name es -p 9200:9200 -p 9200:9200/udp elasticsearch:6.5.4
[root@localhost log]# docker run -dit --name kibana -e ELASTICSEARCH_HOST=http://192.168.10.74:9200 -e ELASTICSEARCH_URL=http://192.168.10.74:9200 -p 5601:5601 kibana:6.5.4

# 配置logstash配置文件,直接rpm安装,过程略。

[root@localhost ~]# cd /usr/share/logstash/
[root@localhost logstash]# cat kafka.conf 
input {

	kafka {
		bootstrap_servers => ["192.168.10.74:9092"]
		client_id => "test1"
		group_id => "test1"
		auto_offset_reset => "latest"
		consumer_threads => 1
		decorate_events => false
		topics => ["test"]
		type => "fromk"
	}
}

filter {
	
    json {
		# 将message字段的key及value(json格式)导入到es,在根部生成新字段。
        source => "message"
		# 添加新列,便于下面再执行source
		add_field => { "@javalog" => "%{log}" }
    }

	# 将json中的json字段、值导入到es中(json嵌套json)
	# {"xxx":"xxx","log":{"time":"xxx","path":"xxx"}}
	# 即导入json中的log


	# 第二次解析json串
    json {
		source => "@javalog"
		# 移除没用的字段
		remove_field => [ "log","@javalog" ]
    }
}

output
{

	elasticsearch {
		hosts => "192.168.10.74"
		index => "jar-log-%{+YYYY.MM.dd}"
	}

	stdout {
		codec => rubydebug
	}

}

# 启动logstash

[root@localhost logstash]# logstash -f kafka.conf

# 容器中java应用日志输出格式为:

{"@timestamp":"2019-08-22T15:09:26.801+08:00","@version":"1","message":"运行时报错:","logger_name":"com.sailei.modules.test.controller.TestController","threa"level":"INFO","level_value":20000}

# docker fluentd日志输出会将应用产生的日志再加入4个元数据发给fluentd(仍然是json格式):
container_id #The full 64-character container ID.
container_name #The container name at the time it was started. If you use docker rename to rename a container, the new name is not reflected in the journal entries.
source #stdout or stderr
log #The container log 应用日志会在log字段中做为value

所以要在logstash中处理json嵌套,获取log字段中数据(提取到根部,便于检索)。
(本来想用filebeat处理json问题,结果因为log字段和filebeat内部一个方法关键词冲突,导致log字段中的数据无法加到根部,才换的logstash)

2019-08-27
发表者 Venus
通过HSTS实现浏览器自动跳转https(非服务器响应跳转)已关闭评论

通过HSTS实现浏览器自动跳转https(非服务器响应跳转)

nginx中关于hsts资料:https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/

全称 HTTP Strict Transport Security

HSTS目的是让浏览器在访问网站的时候浏览器内部自动实现https协议访问(不需要服务器告诉浏览器跳转https)。
在没有hsts功能时,需要自己在nginx里配置http跳转https。
但是这样每个请求(可能)都需要nginx告诉浏览器你访问的地址需要跳转到https,这样就浪费了时间。

hsts需要在第一次访问https时,服务器返回一个指定的响应头,用于告诉浏览器你可以用hsts功能。
然后后续的访问都会自动走https,而不需要跳转了(浏览器内部自己跳转,下面会说)。

nginx配置:

# 首先配置 http跳转https
if ($scheme = http) {
	return 301 https://$host$request_uri;
}

# 添加hsts响应头,可以在server{}段,或者location中。

add_header Strict-Transport-Security "max-age=86400; includeSubdomains; preload";

# 参数解释
max-age # 必选参数,告诉浏览器在多少秒内一直用https (关闭浏览器不会失效、刷新页面会延长失效时间)
includeSubdomains # 可选参数,包括子域名
preload # 可选参数,使用HSTS预加载列表,在nginx文档有说明

这里就不演示我自己的站了(HK的机器https不稳定)。
我们来看百度的首页

第一次访问http协议的百度首页,百度响应头里回应了需要跳转到https。

第二次访问https,响应头里有Strict-Transport-Security参数,生命周期是172800秒,也就是48小时。也就是在放着当前页面不动的情况下,48小时内刷新页面,或者关掉浏览器重新访问百度,都会自动访问https。

关掉浏览器,重新打开百度

第一次发起http协议访问,看到状态码是 307 internal redirect ,307内部跳转,这就是浏览器内部自己实现的,没有通过服务器来返回location头跳转。

第二个请求就直接https协议访问服务器了。

chrome浏览器里可以通过访问: chrome://net-internals/#hsts 搜索支持的域名。

2019-08-26
发表者 Venus
logstash过滤器-json插件解析多层json嵌套已关闭评论

logstash过滤器-json插件解析多层json嵌套

版本:logstash 6.6.2
方法:用logstash过滤器中的json插件配置选项实现

首先介绍用到的参数
参数:add_field
作用:添加字段

参数:%{field}
作用:调用事件中的指定字段

参数:remove_field
作用:删除字段

官方插件资料:https://www.elastic.co/guide/en/logstash/6.6/plugins-filters-json.html
通过文档描述,json插件可以将事件中的json格式日志提取到事件的根中,根中的字段传递到elasticsearch后,可以做过滤条件,而且展示起来比较直观。

比如json日志格式为:

{
    "name":"root",
    "info":{
        "from":"host1",
        "path":"var/log/log.log"
    }
}

info字段的值还是一个json,现在需要将info中的数据提取到事件的根中,也就是变为如下格式。

{
    "name":"root",
    "from":"host1",
    "path":"var/log/log.log"
}

# logstash配置文件

[root@localhost logstash]# cat kafka.conf 
input {

	kafka {
		bootstrap_servers => ["192.168.10.74:9092"]
		client_id => "test1"
		group_id => "test1"
		auto_offset_reset => "latest"
		consumer_threads => 1
		decorate_events => false
		topics => ["test"]
		type => "fromk"
	}
 
}

# 将message字段的数据(json格式) "导入"
filter {
	json {
		# 输入的日志,都会进入message字段,使用source解析json。
		source => "message"
		# 添加列,便于下面再执行source
		add_field => { "javalog" => "%{info}" }
	}

	# 第二次解析json串
	json {
		source => "javalog"
		# 移除列,info字段和javalog字段不需转存到elasticsearch。
		remove_field => [ "info","javalog" ]
	}
}


output {

	elasticsearch {
		hosts => "192.168.10.74"
		index => "jar-log-%{+YYYY.MM.dd}"
	}

	stdout {
		codec => rubydebug
	}
}

效果:

kibana中展示效果

2019-08-21
发表者 Venus
kafka单机版配置已关闭评论

kafka单机版配置

官方这个kafka版本集成了zookeeper,不需要单独安装。

[root@localhost ~]# wget -c http://mirror.bit.edu.cn/apache/kafka/2.3.0/kafka_2.12-2.3.0.tgz
[root@localhost ~]# mv kafka_2.12-2.3.0.tgz /usr/local
[root@localhost ~]# cd /usr/local/
[root@localhost local]# tar zxvf kafka_2.12-2.3.0.tgz
[root@localhost local]# ln -s kafka_2.12-2.3.0 kafka
[root@localhost local]# cd kafka/bin/

# 启动zookeeper,默认端口2181

[root@localhost bin]# ./zookeeper-server-start.sh -daemon ../config/zookeeper.properties

# kafka配置文件需要注意 listeners 参数,直接写服务器ip

[root@localhost config]# cat server.properties | grep -vE "^#|^$"
broker.id=0
# listeners 这个值会返给客户端(因为这里卡了2天没解决),具体信息看配置文件里的解释。
listeners=PLAINTEXT://192.168.10.74:9092
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
# 指定zookeeper地址,因为在本机,直接默认localhost
zookeeper.connect=localhost:2181
zookeeper.connection.timeout.ms=6000
group.initial.rebalance.delay.ms=0

# 启动kafka

[root@localhost bin]# ./kafka-server-start.sh -daemon ../config/server.properties 

# 创建topic,类似创建一个数据库。

[root@localhost ~]# /usr/local/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

# 查看已创建的topic

[root@localhost ~]# /usr/local/kafka/bin/kafka-topics.sh --list --zookeeper localhost:2181

# 查看指定的topic信息

[root@localhost ~]# /usr/local/kafka/bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test

# 启动一个生产者

[root@localhost ~]# /usr/local/kafka/bin/kafka-console-producer.sh --broker-list 192.168.10.74:9092 --topic test

# 启动一个消费者

[root@localhost ~]# /usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic test

在生产者里输入内容并回车,在消费者里就可以显示出生产者输入的内容。