Elasticsearch (二)

logstash

logstash基本语法组成

logstash主要由三部分组成:input、filter、output。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//输入插件
input{

//文件类型
file{
#path属性接受的参数是一个数组,其含义是标明需要读取的文件位置
path => [‘pathA’,‘pathB’]

#表示多就去path路径下查看是够有新的文件产生。默认是15秒检查一次。
discover_interval => 15

#排除那些文件,也就是不去读取那些文件
exclude => [‘fileName1’,‘fileNmae2’]

#被监听的文件多久没更新后断开连接不在监听,默认是一个小时。
close_older => 3600

#在每次检查文件列 表的时候, 如果一个文件的最后 修改时间 超过这个值, 就忽略这个文件。 默认一天。
ignore_older => 86400

#logstash 每隔多 久检查一次被监听文件状态( 是否有更新) , 默认是 1 秒。
stat_interval => 1

#sincedb记录数据上一次的读取位置的一个index
sincedb_path => ’$HOME/. sincedb‘

#logstash 从什么 位置开始读取文件数据, 默认是结束位置 也可以设置为:beginning 从头开始
start_position => ‘beginning’

#注意:这里需要提醒大家的是,如果你需要每次都从同开始读取文件的话,关设置start_position => beginning是没有用的,你可以选择sincedb_path 定义为 /dev/null
}

//数据库类型
jdbc{
#jdbc sql server 驱动,各个数据库都有对应的驱动,需自己下载
jdbc_driver_library => "/etc/logstash/driver.d/sqljdbc_2.0/enu/sqljdbc4.jar"

#jdbc class 不同数据库有不同的 class 配置
jdbc_driver_class => "com.microsoft.sqlserver.jdbc.SQLServerDriver"

#配置数据库连接 ip 和端口,以及数据库
jdbc_connection_string => "jdbc:sqlserver://200.200.0.18:1433;databaseName=test_db"

#配置数据库用户名
jdbc_user =>

#配置数据库密码
jdbc_password =>

#上面这些都不重要,要是这些都看不懂的话,你的老板估计要考虑换人了。重要的是接下来的内容。
# 定时器 多久执行一次SQL,默认是一分钟
# schedule => 分 时 天 月 年
# schedule => * 22 * * * 表示每天22点执行一次
schedule => "* * * * *"

#是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
clean_run => false

#是否需要记录某个column 的值,如果 record_last_run 为真,可以自定义我们需要表的字段名称,
#此时该参数就要为 true. 否则默认 track 的是 timestamp 的值.
use_column_value => true

#如果 use_column_value 为真,需配置此参数. 这个参数就是数据库给出的一个字段名称。当然该字段必须是递增的,可以是 数据库的数据时间这类的
tracking_column => create_time

#是否记录上次执行结果, 如果为真,将会把上次执行到的 tracking_column 字段的值记录下来,保存到 last_run_metadata_path 指定的文件中
record_last_run => true

#们只需要在 SQL 语句中 WHERE MY_ID > :last_sql_value 即可. 其中 :last_sql_value 取得就是该文件中的值
last_run_metadata_path => "/etc/logstash/run_metadata.d/my_info"

#是否将字段名称转小写。
#这里有个小的提示,如果你这前就处理过一次数据,并且在Kibana中有对应的搜索需求的话,还是改为true,
#因为默认是true,并且Kibana是大小写区分的。准确的说应该是ES大小写区分
lowercase_column_names => false

#你的SQL的位置,当然,你的SQL也可以直接写在这里。
#statement => SELECT * FROM tabeName t WHERE t.creat_time > :last_sql_value
statement_filepath => "/etc/logstash/statement_file.d/my_info.sql"

#数据类型,标明你属于那一方势力。单了ES哪里好给你安排不同的山头。
type => "my_info"
}
#注意:外载的SQL文件就是一个文本文件就可以了,还有需要注意的是,一个jdbc{}插件就只能处理一个SQL语句,
#如果你有多个SQL需要处理的话,只能在重新建立一个jdbc{}插件。

//redis
redis {
codec => #可选项,默认是plain,可设置其他编码方式。

discover_interval => #可选项,logstash多久检查一下path下有新文件,默认15s。

exclude => #可选项,排除path下不想监听的文件。

sincedb_path => #可选项,记录文件以及文件读取信息位置的数据文件。~/.sincedb_xxxx

sincedb_write_interval => #可选项,logstash多久写一次sincedb文件,默认15s.

stat_interval => #可选项,logstash多久检查一次被监听文件的变化,默认1s。

start_position => #可选项,logstash从哪个位置读取文件数据,默认从尾部,值为:end。初次导入,设置为:beginning。

path => #必选项,配置文件路径,可定义多个。

tags => #可选项,在数据处理过程中,由具体的插件来添加或者删除的标记。

type => #可选项,自定义处理时间类型。比如nginxlog。
}
}

filter{
过滤器插件
过滤器提供的并不单单是过滤的功能,还可以对进入过滤器的原始数据进行复杂的逻辑处理,甚至添加独特的新事件到后续流程中
}

outer{

  输出插件
elasticsearch {
id => "log"
hosts => ["elasticsearch:9200"]
index => "logstash-%{type}-%{+YYYY.MM.dd}"
}
}

protoful 集中记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
生成GO 
protoc -I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOPATH/src/protobuf/src/ \
-I$GOPATH/src/datacenter/proto \
--go_out=plugins=grpc:. \
adverse_event.proto

生成envoy 翻译器 descriptor.pb
protoc -I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOPATH/src/protobuf/src/ \
-I$GOPATH/src/datacenter/proto \
--include_imports \
--include_source_info \
--descriptor_set_out=../build/envoy/descriptor.pb \
*.proto

生成grpc-webJS
protoc -I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOPATH/src/protobuf/src/ \
-I$GOPATH/src/datacenter/proto \
--js_out=import_style=commonjs:. \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:. *.proto


生成protoc-gen-swagger
protoc -I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOPATH/src/protobuf/src/ \
-I$GOPATH/src/proto-doc/proto \
--swagger_out=logtostderr=true:. \
adverse_event.proto


交叉编译
set GOARCH=amd64

set GOOS=linux

go build xx.go

GO mod的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
打开
GO111MODULE=on

Usage:

go mod <command> [arguments]

The commands are:

download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.

GO111MODULE=on go mod init
GO111MODULE=on go mod tidy

内网穿透工具

https://dashboard.ngrok.com/get-started

1
ngrok http 80

基于jaeger和tracing实现 grpc调用链跟踪模块

#基于jaeger和tracing实现 grpc调用链跟踪模块

#####Jaeger

参考 Jaeger部署

Jaeger是Uber推出的一款调用链追踪系统,类似于Zipkin和Dapper。 其主要用于多个服务调用过程追踪分析,图形化服务调用轨迹,便于快速准确定位问题。
Jaeger组成

  • 前端界面展示UI
  • 数据存储Cassandra
  • 数据查询Query
  • 数据收集处理Collector
  • 客户端代理Agent
  • 客户端库jaeger-client-*
1
2
3
4
5
6
7
8
9
10
11
12
13
    
仅为测试,该方式数据会存入内存,不能用于生产

docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 9411:9411 \
jaegertracing/all-in-one:1.9

#####grpc-jaeger源依赖

google.golang.org/grpc
github.com/opentracing/opentracing-go
github.com/uber/jaeger-client-go
github.com/pkg/errors

请参阅 案例分享

记录一些GO的常见问题

###空struct{} 的使用

空结构体 struct{} 可以用来节省内存
  • 空结构体的特点:1、不占用内存;2、地址不变

  • 如果使用的是map,而且map又很长,通常会节省不少资源

  • 空struct{}也在向别人表明,这里并不需要一个值

比较

####结构体的比较

  • 如果结构体的所有成员变量都是可比较的,那么结构体就可比较

  • 如果结构体中存在不可比较的成员变量,那么结构体就不能比较

####struct可以作为map的key么?

  • struct必须是可比较的,才能作为key,否则编译时报错

####interface的比较

  • 接口值可以用 == 和 != 相比较。两个接口值相等,仅当他们都是nil,或者他们动态类型相同,并且动态的值也根据这个动态类型的==相等。

Golang不可以比较类型:

  • slice(切片)、map(key-value集合)、func(函数),当接口的原始类型是这三个的时候,比较会报panic。

TCP和UDP的区别及应用场景

  • tcp有流量控制,udp没有
  • tcp的头部比20bytes,udp8byres
面向连接VS无连接
  • TCP建立一个连接需要3次握手IP数据包,断开连接需要4次握手。另外断开连接时发起方可能进入TIME_WAIT状态长达数分钟(视系统设置,windows一般为120秒),在此状态下连接(端口)无法被释放。
  • UDP不需要建立连接,可以直接发起。
可靠VS不可靠

TCP利用握手、ACK和重传机制,udp没有。

  • 校验和(校验数据是否损坏);
  • 定时器(分组丢失则重传);
  • 序列号(用于检测丢失的分组和重复的分组);
  • 确认应答ACK(接收方告知发送方正确接收分组以及期望的下一个分组);
  • 否定确认(接收方通知发送方未被正确接收的分组);
  • 窗口和流水线(用于增加信道的吞吐量)。(窗口大小:无需等待确认应答而可以继续发送数据的最大值)

有序性

  • TCP利用seq序列号对包进行排序,udp没有。

面向字节流vs面向报文

  • 面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。(一个upd的最大报文长度2^16-1-20-8,20是ip报文头,8是udp报文头)

  • 面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

应用场景

  • TCP:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。

  • UDP:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。

select是随机的还是顺序的?

select会随机选择一个可用通道做收发操作

Go语言局部变量分配在栈还是堆?

Go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析,当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。

GO-grpc-Gateway 的安装与编译(WIN环境)

#grpc-gateway

grpc-gateway是protoc的一个插件。它读取gRPC服务定义,并生成一个反向代理服务器,将RESTful JSON API转换为gRPC。此服务器是根据gRPC定义中的自定义选项生成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger

进入 github.com/grpc-ecosystem/grpc-gateway/rotoc-gen-grpc-gateway
执行go build 然后安装 go install
进入 github.com/grpc-ecosystem/grpc-gateway/pprotoc-gen-swagger
执行go build 然后安装 go install

**
需要额外下载
go get github.com/ghodss/yaml
go get google/api/annotations.proto (被墙使用:github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis)
git clone https://github.com/protocolbuffers/protobuf
**

#####grpc-gateway-proto文件例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//需要在编译的时候 指定包的路径,并且该包依赖 https://github.com/protocolbuffers/protobuf
import "google/api/annotations.proto";

service Menu {
rpc Save (MenuModel) returns (Res) {
option (google.api.http) = {
post: "/api/menu"
body: "*"
};
}

rpc View (RepMenuView) returns (Res) {
option (google.api.http) = {
get: "/api/menu"
};
}
}

#####编译

1
2
3
4
5
6
7
8
9
10
//生成服务端
protoc --go_out=plugins=grpc:. role_manage.proto

//生成网关使用使用部分
protoc -I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOPATH/src/protobuf/src/ \
-I$GOPATH/src/vsiapi/proto \
--grpc-gateway_out=logtostderr=true:. \
role_manage_gw.proto

####调用
$ curl -d ‘{“ID”:1}’ -X GET ‘http://localhost:3344/api/menu'

请参阅 案例分享

GO-grpc 的安装与编译(WIN环境)

grpc win 安装流程

google.golang.org: grpc相关组件默认获取package的路径

1、安装Protobuf

https://github.com/google/protobuf/releases

下载 protoc-3.5.1-win32.zip

把解压后的 protoc.exe 放入到 GOPATH\BIN 中

2、安装grpc

git clone https://github.com/grpc/grpc-go
将grpc-go更名为grpc放入到google.golang.org中

3、安装Genproto

git clone  https://github.com/google/go-genproto
将clone下来的文件夹更名为genproto,放到google.golang.org下  

4、下载text包

为了使包的导入方式不变,需要在src目录下面构造目录结构
mkdir -p $GOPATH/src/golang.org/x/
cd $GOPATH/src/golang.org/x/
git clone https://github.com/golang/text.git    

5、下载net包

为了使包的导入方式不变,需要在src目录下面构造目录结构
mkdir -p $GOPATH/src/golang.org/x/
cd $GOPATH/src/golang.org/x/

git clone https://github.com/golang/net.git net
go install net
执行go install之后没有提示,就说明安装好了。    

6、安装proto

go get -u github.com/golang/protobuf/proto

7、安装protoc-gen-go

go get -u github.com/golang/protobuf/protoc-gen-go  

将proto文件编译为go文件

  • proto文件语法详解参阅:https://blog.csdn.net/u014308482/article/details/52958148

    // protoc --go_out=plugins=grpc:{输出目录}  {proto文件}
    protoc --go_out=plugins=grpc:./test/ ./test.proto
    
    //在shell下可以批量编译。但是在win cmd下会报错,无法识别通配符
    protoc --go_out=plugins=grpc:. *.proto
    

注意:原则上不要修改编译出来的.bp.go文件的代码,因为双方接口基于同一个proto文件编译成自己的语言源码,此文件只作为接口数据处理,业务具体实现不在.bp.go中。

grpc+ProtoBuf所需的一些资源

请参阅 案例分享

GO-interceptor

引用 带入gRPC:Unary and Stream interceptor.

interceptor (拦截器)

在 grpc 中进行通信前 与 后的逻辑处理

在 gRPC 中,大类可分为两种 RPC 方法,与拦截器的对应关系是:

  • 普通方法:一元拦截器(grpc.UnaryInterceptor)

  • 流方法:流拦截器(grpc.StreamInterceptor)

常规实现方式:

1
2
3
4
5
6
7
8
9
10
11
var opts []grpc.ServerOption
// 注册interceptor
var interceptor grpc.UnaryServerInterceptor
interceptor = func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {

/*
一些中间逻辑代码
*/
return handler(ctx, req)
}
opts = append(opts, grpc.UnaryInterceptor(interceptor))

grpc 本身只能设置一个拦截器,为了避免所有逻辑都写在可以 可以使用(go-grpc-middleware)来处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

import "github.com/grpc-ecosystem/go-grpc-middleware"

//RPC 方法的入参出参的日志输出
func LoggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
log.Printf("gRPC method: %s, %v", info.FullMethod, req)
resp, err := handler(ctx, req)
log.Printf("gRPC method: %s, %v", info.FullMethod, resp)
return resp, err
}

//RPC 方法的异常保护和日志输出
func RecoveryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
defer func() {
if e := recover(); e != nil {
debug.PrintStack()
err = status.Errorf(codes.Internal, "Panic err: %v", e)
}
}()

return handler(ctx, req)
}


myServer := grpc.NewServer(
grpc.Creds(c), //安全通信,处理证书认证相关
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
...
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
...
)),
)

or

opts := []grpc.ServerOption{
grpc.Creds(c),
grpc_middleware.WithUnaryServerChain(
RecoveryInterceptor,
LoggingInterceptor,
),
}

请参阅 案例分享

##JWT - GO

现成的库,不是官方,但是星高!有很多方法可以使用

github.com/dgrijalva/jwt-go

1
2
3
4
5
6
/*
测试Token
*/
Token,_ := jwt.GenerateToken("felix","123456")
fmt.Println(Token)
jwt.ParseToken(Token.Token)

请参阅 JWT中间件

同一主机下的Docker 部署

##同一主机下的Docker 部署

1
2
3
生成docker 镜像 ./docker
docker build -t go-gw .
docker build -t go_server .
  • 首先,对于Gateway指定的 server要改成 “container_name:port” 模式

    因为docker下 容器间无法直接通信。需要指定物理IP,或者指定容器网络。通常选择容器名称,因为微服务下容器IP 会随时变

  • 其次docker 部署需要指定 –network 这里我推荐两种方式

    • Docker DNS Server:

      • docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。方法很简单,只要在启动时用 –name 为容器命名就可以了

      • 使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的。

      1
      2
      3
      4
      5
      6
      7
      案例:(代码中使用了此方式demo)
      先创建网络
      docker network create d4_ghost

      docker run -it --name=felixgw --net=d4_ghost -p 3344:3344 -d go-gw

      docker run -it --name=felixserver --net=d4_ghost -p 50051:50051 -d go_server
    • joined 容器 :

      • joined 容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。

      • joined 容器非常适合以下场景

        • 不同容器中的程序希望通过 loopback 高效快速地通信,比如 web server 与 app server。

        • 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。

          1
          2
          3
          4
          docker run -it --name=felixserver  -p 50051:50051 -d go_server

          ##指定 jointed 容器为 felixserver
          docker run -it --name=felixgw --network=container:felixserver -p 3344:3344 -d go-gw

#切记给代码文件加可执行权限!

GO-casbin 随手记

#casbin 随手记

相关路由设定 请参阅 go-study

casbin 配置文件的规范 请参阅 supported-models

  • 配置文件使用 PERM 元模型。PERM 表示策略(Policy)、效果(Effect)、请求(Request)和匹配器(Matchers)。

    其中定义了请求和策略来表示主体,客体和动作。
    在本例中,主体表示用户角色,客体表示访问路径,action 表示请求方法(例:GET, POST 等)。
    匹配器定义了策略是如何匹配的,可以通过直接定义主体,或者使用像 keyMatch 这样的帮助方法,它也可以匹配通配符。
    casbin 实际比这个简单的例子要强大得多,你可以用声明的方式定义各种自定义功能来达到轻松切换和维护鉴权配置的效果。
    


PERM 元模型配置文件 auth_model.conf

[request_definition]

r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers] #核心权限验证部分,可以根据自己需要进行设定
m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == “*”)

  • 策略文件就是一个简单的 csv 文件,描述了哪些角色可以访问哪些路径等(也可以使用数据库来管理)

    p, admin, /,
    p, anonymous, /login,
    p, anonymous, /index,

    p, member,/logout,
    p, member, /home/
    ,
    p, member, /home,

权限判断代码
authEnforcer, err := casbin.NewEnforcerSafe(“./src/casbin-examples/roles/auth_model.conf”, “./src/casbin-examples/roles/policy.csv”)
sub := “member”
obj := “/home”
act := “GET”

if authEnforcer.Enforce(sub, obj, act) == true {
fmt.Println(“路由成功?”)
} else {
fmt.Println(“路由失败?”)
}

Kubernetes 学习笔记 (基础)

概况

集群采用 Master/Node的结构,Master(主节点)控制整个集群,Node(从节点)为集群提供计算能力。

Master

Master是Kubernetes集群的大脑,负责公开集群的API,调度部署和管理整个集群。集群至少有一个Master节点,如果在生产环境中要达到高可用,还需要配置Master集群。Master主要包含API Server、Scheduler、Controller三个组件,需要etcd组件来保存整个集群的状态。

  • etcd:一个高可用、强一致性的服务发现存储仓库,为Kubernetes集群提供存储服务,类似于zookeper。

  • API Server: kubernetes最重要的核心组件之一,提供资源操作的唯一入口(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd),并提供认证、授权、访问控制、API注册和发现等机制。

  • Scheduler:负责资源的调度,按照预定的调度策略将Pod(k8s中调度的基本单位)调度到相应的Node上。

  • Controller:通过API Server来监控整个集群的状态,并确保集群处于预期的工作状态,比如故障检测、自动扩展、滚动更新等。

Node

Node是Kubernetes集群的工作节点,可以是物理机也可以是虚拟机。Node需要包含容器、kubelet、kube-proxy等组件。。

  • kubelet:维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理。每个节点上都会运行一个kubelet服务进程,接收并执行Master发来的指令,管理Pod及Pod中的容器。每个kubelet进程会在API Server上注册节点自身信息,定期向Master节点汇报节点的资源使用情况,并通过cAdvisor监控节点和容器的资源。

  • kube-proxy: 为 Service 提供集群内部的服务发现和负载均衡,监听 API Server 中 service和endpoint的变化情况,并通过iptables等方式来为服务配置负载均衡。

  • Docker: 每台Node上需要安装Docker来运行镜像,但是Docker不是唯一选择,Kubernetes支持多种容器,比如CoreOS公司的Rkt容器(之前称为Rocket,现更名为Rkt)。

Pod

在创建新部署时,Kubernetes会建立一个Pod来寄存你的应用实例。Pod是一个抽象的概念,它包含一个或多个容器组成的容器组,还有这些容器共享的资源,Pod就像是豌豆荚一样,它可以由一个或者多个容器组成,这些容器共享存储、网络和配置项。这些资源包括:

  • 共享的存储,例如Volume

  • 网络,比如使用唯一的集群IP地址

  • 如何运行容器的配置信息,比如镜像版本和容器端口

Pod模型上类似于一个具有特定应用的逻辑主机,它可以包含相对紧密耦合的不同应用容器。例如,一个Pod可能既包含Node.js Web服务容器,又包含给它提供数据库服务的容器。同一个Pod里的容器共享一个IP地址和端口段,协同工作和调度,并且在同一节点上的共享环境中运行。

Pod是Kuberlnetes平台中的原子单位。在部署创建时,部署并不直接创建容器,而是创建包含了容器的Pod。Pod被分配绑定在指定的Node上,除非被停止或者删除它会一直在该Node上工作。万一出现Node宕机的情况,集群中另外一个可用的Node会马上启动运行一个完全一样的Pod

Pod控制器

目前Kubernetes中的业务类型可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application)这四种类型,而这四种类型的业务又可以由不同类型的Pod控制器来完成,分别为:Deployment、Job、DaemonSet和StatefulSet。

  • Deployment: 复制控制器(Replication Controller,RC)是集群中最早的保证Pod高可用的API对象,副本集(Replica Set,RS)是它的升级,能支持更多种类的匹配模式。部署(Deployment)又是比RS应用模式更广的API对象,以Kubernetes的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理。

  • Service: Deployment保证了Pod的数量,但是没有解决如何访问Pod的问题,一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力,Service可以稳定为用户提供服务。

  • Job: 用来控制批处理型任务,Job管理的Pod根据用户的设置把任务成功完成就自动退出了。

  • DaemonSet: 后台支撑型服务的核心关注点在集群中的Node,要保证每个Node上都有一个此类Pod运行。比如用来收集日志的Pod。

  • StatefulSet: 不同于RC和RS,StatefulSet主要提供有状态的服务,StatefulSet中Pod的名字都是事先确定的,不能更改,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。比如数据库服务MySQL,我们不希望一个Pod故障后,MySQL中的数据即丢失。

API

 API对象是Kubernetes集群中的管理操作单元。集群中的众多技术概念分别对应着API对象,每个API对象都有3大类属性:

metadata(元数据):用来标识API对象,包含namespace、name、uid等。

spec (规范):描述用户期望达到的理想状态,所有的操作都是声明式(Declarative)的而不是命令式(Imperative),在分布式系统中的好处是稳定,不怕丢操作或运行多次。比如设置期望3个运行Nginx的pod,运行多次也还是一个结果,而给副本数加1的操作就不是声明式的,运行多次结果就错了。

status(状态):描述系统当前实际达到的状态,比如期望3个pod,现在实际创建好了2个。