Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

基于Calico的CNI

12
Feb
2018

基于Calico的CNI

By Alex
/ in Network,PaaS
/ tags CNI, K8S
2 Comments
什么是Calico

Calico为容器或虚拟机提供安全的网络连接,它创建一个扁平化的第3层网络,为每个节点分配一个可路由的IP地址。网络中的节点不需要NAT或IP隧道就可以相互通信,因此性能很好,接近于物理网络,不使用网络策略的情况下,可能引入0.01毫秒级别的延迟,带宽影响不明显)。 在需要Overlay的应用场景下,Calico可以支持IP-in-IP隧道,也可以与其它Overlay网络(例如Flannel)配合,IP-in-IP隧道会带来较小的性能下降。

Calico支持动态的网络安全策略(NetPolicy),你可以细粒度的控制容器、虚拟机、物理机端点之间的网络通信。

Calico在每个节点运行一个虚拟路由器(vRouter),vRouter利用Linux内核自带的IP转发功能,工作负载依赖于此路由器和外部通信。节点上的代理组件Felix负责根据分配到节点上的工作负载的IP地址信息为vRouter提供L3转发规则。vRouter基于BIRD实现了边界网关协议(BGP)。通过vRouter,工作负载直接基于物理网络进行通信,甚至可以被分配外网IP并直接暴露到互联网上。

BGP术语
术语 说明
BGP

边界网关协议(Border Gateway Protocol)是互联网上一个核心的去中心化自治路由协议,它通过维护IP路由表或前缀表来实现自治系统(AS)之间的可达性

大多数ISP使用BGP来与其他ISP创建路由连接,特大型的私有IP网络也可以使用BGP

BGP的通信对端(对等实体,Peer)通过TCP(端口179)会话交换数据,BGP路由器会周期地发送19字节的保活消息来维护连接。在路由协议中,只有BGP使用TCP作为传输层协议

IBGP

内部边界网关协议。同一个AS内部的两个或多个对等实体之间运行的BGP被称为IBGP

IGP

内部网关协议。同一AS内部的对等实体(路由器)之间使用的协议,它存在可扩容性问题:

  1. 一个IGP内部应该仅有数十(最多小几百)个对等实体
  2. 对于端点数,也存在限制,一般在数百(最多上千)个Endpoint级别

IBGP和IGP都是处理AS内部路由的,仍然需要IGP的原因是:

  1. IBGP之间是TCP连接,也就意味着IBGP邻居采用的是逻辑连接的方式,两个IBGP连接不一定存在实际的物理链路。所以需要有IGP来提供路由,以完成BGP路由的递归查找
  2. BGP协议本身实际上并不发现路由,BGP将路由发现的工作全部移交给了IGP协议,它本身着重于路由的控制
EBGP

外部边界网关协议。归属不同的AS的对等实体之间运行的BGP称为EBGP

Border Router

边界路由器,在AS边界上与其他AS交换信息的路由器

AS 

自治系统(Autonomous system),一个组织(例如ISP)管辖下的所有IP网络和路由器的整体

参与BGP路由的每个AS都被分配一个唯一的自治系统编号(ASN)。对BGP来说ASN是区别整个相互连接的网络中的各个网络的唯一标识。64512到65535之间的ASN编号保留给专用网络使用

Route Reflector

同一AS内如果有多个路由器参与BGP路由,则它们之间必须配置成全连通的网状结构——任意两个路由器之间都必须配置成对等实体。由于所需要TCP连接数是路由器数量的平方,这就导致了巨大的TCP连接数

为了缓解这种问题,BGP支持两种方案:Route Reflector、Confederations

路由反射器(Route Reflector)是AS内的一台路由器,其它所有路由器都和RR直接连接,作为RR的客户机。RR和客户机之间建立BGP连接,而客户机之间则不需要相互通信

RR的工作步骤如下:

  1. 从非客户机IBGP对等实体学到的路由,发布给此RR的所有客户机
  2. 从客户机学到的路由,发布给此RR的所有非客户机和客户机
  3. 从EBGP对等实体学到的路由,发布给所有的非客户机和客户机

RR的一个优势是配置方便,因为只需要在反射器上配置

工作负载 Workload,即运行在Calico节点上的虚机或容器
全互联 全互联网络(Full node-to-node Mesh)是指任何两个Calico节点都进行配对的L3连接模式
集成K8S
安装Calico

关于如何快速启用基于Calico的CNI网络连接,参考Kubernetes学习笔记。

网络策略

Calico支持K8S的NetworkPolicy,下面是一个示例。

准备

首先创建一个名字空间:

Shell
1
2
3
kubectl create ns dev
# 为新名字空间的默认账户添加imagePullSecrets
kubectl --namespace=dev edit serviceaccount default

然后创建一个5实例的部署:

Shell
1
2
kubectl --namespace=dev run media-api --replicas=5 --image=docker.gmem.cc/media-api:1.1
kubectl --namespace=dev get pod

将上述部署暴露为服务:

Shell
1
2
kubectl --namespace=dev expose deployment media-api --port=8800,7700
kubectl --namespace=dev get service

执行类似下面的命令,确认服务能够正常响应HTTP请求:

Shell
1
curl http://media-api.dev.svc.k8s.gmem.cc:8800/media/newpub/2017-01-01
隔离访问

下面将上述名字空间dev隔离掉,Calico会阻止访问此名字空间中各的Pod:

Shell
1
2
3
4
5
6
7
8
9
10
11
kubectl create -f - <<EOF
kind: NetworkPolicy
apiVersion: extensions/v1beta1
metadata:
  name: default-deny
  namespace: dev
spec:
  podSelector:
    # 默认拒绝任何访问
    matchLabels: {}
EOF

这是再次执行curl命令,你无法得到响应。

准许访问

下面我们再创建一个网络策略, 允许API网关层访问上面的服务:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kubectl create -f - <<EOF
kind: NetworkPolicy
apiVersion: extensions/v1beta1
metadata:
  name: allow-ingress-nginx
  namespace: dev
spec:
  podSelector:
    matchLabels:
      # 下面的标签是自动添加的
      run: media-api
  # 允许来自apigateway层的入站连接
  ingress:
    - from:
      - podSelector:
          matchLabels:
            tier: apigateway
EOF
删除策略

要删除网络策略,执行:

Shell
1
kubectl --namespace=dev delete networkpolicy default-deny
网络策略列表
策略 说明
禁止所有入站连接
YAML
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: advanced-policy-demo
spec:
  # 下面的选择器匹配所有Pod
  podSelector:
    matchLabels: {}
  # 策略类型:入站
  policyTypes:
  - Ingress
禁止对特定Pod的入站连接
YAML
1
2
3
4
5
6
7
8
9
spec:
  podSelector:
    # 允许对Nginx的入站访问
    matchLabels:
      run: nginx
  ingress:
    - from:
      - podSelector:
          matchLabels: {}
禁止所有出站连接
YAML
1
2
3
4
5
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
允许进行DNS查询的出站连接
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
  # 允许针对kube-system名字空间中的Pod的53端口进行UDP访问
  egress:
  - to:
    # 名字空间选择器
    - namespaceSelector:
        matchLabels:
          name: kube-system
    # 53端口
    ports:
    - protocol: UDP
      port: 53
允许对Nginx的出站访问
YAML
1
2
3
4
5
6
7
8
9
10
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          run: nginx
静态IP

通常你应该使用Service(具有集群静态IP)而不是尝试为Pod指定静态IP。

如果非要这么做,Calico为Pod提供了一些注解:

YAML
1
2
3
4
5
6
7
8
9
# 分配给当前Pod的IP地址列表,请求的地址必须位于Calico的IPAM的地址池中
annotations:
    "cni.projectcalico.org/ipAddrs": "[\"192.168.0.1\"]"
 
# 分配给当前Pod的IP地址列表,绕过IPAM
# 你可以分配任何地址给Pod,但是仅仅当地址位于Calico的地址空间中时,Calico才负责分配路由
# 注意IP冲突问题
annotations:
    "cni.projectcalico.org/ipAddrsNoIpam": "[\"10.0.0.1\"]"
高可用

Calico依赖于Etcd来存放配置信息,缺省情况下它会容器化安装单实例的Etcd。你可以修改其Configmap,指定使用外部的、高可用的Etcd:

YAML
1
2
3
4
5
6
7
8
kind: ConfigMap
apiVersion: v1
metadata:
  name: calico-config
  namespace: kube-system
data:
  # 可以和K8S共享Etcd集群
  etcd_endpoints: "http://10.0.1.1:2379,http://10.0.2.1:2379,http://10.0.3.1:2379" 
外部连接
出站连接

所谓出站外部连接,是指从Calico端点到位于Calico集群外部的目的主机的连接。

最简单的实现外部出站连接的方式是为Calico池开启NAT:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看默认IP池的配置
# calicoctl get ipPool default-ipv4-ippool -o yaml
# 输出:
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: 2018-02-12T11:33:04Z
  name: default-ipv4-ippool
  resourceVersion: "5"
  uid: 7d7a9461-0fe8-11e8-a715-deadbeef00a0
spec:
  cidr: 192.168.0.0/16
  ipipMode: Always
  # 已经启用出站NAT
  natOutgoing: true  

你可以针对某个IP池进行NAT设置。

入站连接

所谓入站外部连接,是指从Calico集群外部主机发起的,针对Calico端点的连接。实现入站外部连接的方式主要由两种。

BGP Peering

利用BGP配对,将外部网络的基础设施配对到Calico集群中的某些节点。这需要外部网络中包含支持BGP协议的交换机或者路由器,该路由器作为访问Calico集群内部端点的网关。

如果网络规模较小,你可以让外部路由器和所有Calico节点之间建立BGP会话;如果网络规模较大,可能需要利用RR来创建一个第三层拓扑。 

下面是一个基于BIRD(支持BGP协议的软路由)的示例:Calico集群使用AS号65000,外部网络使用AS号65001,Calico集群内部节点10.0.0.100配对到外部路由器(BIRD)10.0.0.1,Calico内部使用节点全互联模式:

  1. Calico BGP Peer配置文件:
    Shell
    1
    2
    3
    4
    5
    6
    7
    8
    apiVersion: projectcalico.org/v3
    kind: BGPPeer
    metadata:
      name: bgppeer-xenial-100-zircon
    spec:
      peerIP: 10.0.0.1
      node: xenial-100
      asNumber: 65001 
  2. BIRD配置文件:
    Shell
    1
    2
    3
    4
    5
    6
    7
    8
    9
    protocol bgp xenial100 {
        description "10.0.0.100";
        local as 65001;
        neighbor 10.0.0.100 as 65000;
        source address 10.0.0.1;
        graceful restart;
        import all;
        export all;
    }

按照上面方式配置后,可以在BIRD上看到学习到的路由:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# sudo birdc show route
172.27.154.192/26  via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
172.27.187.192/26  via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
172.27.97.64/26    via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
172.27.121.64/26   via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
172.27.41.128/26   via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
172.27.61.64/26    via 10.0.0.100 on virbr0 [xenial100 14:59:05] * (100) [AS65000i]
 
# 同步的内核路由表
# route
172.27.41.128   xenial-100      255.255.255.192 UG    0      0        0 virbr0
172.27.61.64    xenial-100      255.255.255.192 UG    0      0        0 virbr0
172.27.97.64    xenial-100      255.255.255.192 UG    0      0        0 virbr0
172.27.121.64   xenial-100      255.255.255.192 UG    0      0        0 virbr0
172.27.154.192  xenial-100      255.255.255.192 UG    0      0        0 virbr0
172.27.187.192  xenial-100      255.255.255.192 UG    0      0        0 virbr0 

此外,下一章的RR示例也可以支持入站外部链接。

编排器特定方式

Calico支持多种容器编排器(Orchestrator)特有的入站连接方式,例如Kubernetes的Service IP。

外部访问K8S服务IP

本节内容和Calico无直接关系,Calico仅仅为K8S提供容器连接性,它不知道K8S的服务(Service)是何物。

K8S中Service IP仅仅在集群内部可以访问,集群内节点或者Pod依赖Kube Proxy来访问Service IP。外部访问Service的规范化方式是,使用NodePort(可以配合LoadBalancer),向外部暴露服务。

但是,要直接暴露Service的IP地址到集群外部也是可以实现的。你只需要配置适当的路由规则,将Service IP子网的网关设置为K8S集群的任意节点即可:

Shell
1
2
3
4
# K8S 服务网段为10.96.0.0/12,10.0.0.100为集群中一个节点
route add -net 10.96.0.0 netmask 255.240.0.0 gw 10.0.0.100
 
# 设置完路由后,尝试连接集群的DNS服务:telnet 10.96.0.10 53,不要ping,不支持
使用RR

较大规模的网络拓扑中,启用节点全互联需要大量的TCP连接,可以考虑引入Router Refactor并禁用全互联。实践中“较大规模”网络拓扑包含50+节点,但是也有超过100节点的正常运作的全互联网络。

BIRD是一个BGP实现,支持完全的动态路由,本章以BIRD软路由器作为RR。

安装BIRD
Shell
1
2
3
sudo add-apt-repository ppa:cz.nic-labs/bird
sudo apt-get update
sudo apt-get install bird
配置BIRD
IPv4
/etc/bird/bird.conf
Shell
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
# 日志配置
log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
log stderr all;
 
# 当前路由器(RR)全局唯一标识,通常设置为路由器的IP地址
router id 10.0.0.1;
 
filter import_kernel {
    if ( net != 0.0.0.0/0 ) then {
        accept;
    }
    reject;
}
 
# 所有协议的全局性调试开关
debug protocols all;
 
# 伪协议,不是和网络中其它路由器通信,而是每60秒将BIRD的路由表同步到OS内核
protocol kernel {
    scan time 60;
    import none;  # 从内核路由表导入路由条目
    export all;   # 将BIRD的路由同步给内核
}
# 伪协议,每2秒监控网络接口的信息
protocol device {
    scan time 2;
}
 
 
# 为拓扑中每个节点(每个连接到此RR的Peer)添加以下内容
protocol bgp xenial100 {
    # 可选的描述
    description "10.0.0.100";
 
    # 声明本路由器所属的AS
    #       IP地址 如果不使用179 AS号
    # local [ip] [port number] [as number]
    local as 65000;
 
    # BGP实例,指定当前路由器与自通信的邻居路由器的信息
    #                                            如果和当前路由器AS一样则自动切换为IBGP
    #                                                        可以不指定AS号而指定internal
    #                指定网络前缀而非精确的IP,则启用动态BGP行为,当前路由器会在BGP端口监听,当匹配
    #                前缀的BGP连接到来后,spawn一个BGP实例处理它。普通BGP实例/动态BGP实例可混合使用
    # neighbor [ip | range prefix] [port number] [as number] [internal|external]
    # neighbor range 10.0.3.0/24 as 65000;
    neighbor 10.0.0.100 as 65000;
    # 提示此邻居和本路由器(的某个接口)是直接相连的
    direct;
    # 本路由器作为路由反射器,邻居作为RR客户端
    rr client;
    # 当一个BGP speaker重启/崩溃后,邻居会丢弃从它接收到的所有路径。即使该speaker的转发平面仍然
    # 继续工作,也会出现封包转发被干扰的情况。该选项用于缓和这个问题
    graceful restart;
    import all;
    export all;
}
protocol bgp xenial101 {
    description "10.0.0.101";
    local as 65000;
    neighbor 10.0.0.101 as 65000;
    direct;
    rr client;
    graceful restart;
    import all;
    export all;
}
protocol bgp xenial102 {
    description "10.0.0.102";
    local as 65000;
    neighbor 10.0.0.102 as 65000;
    direct;
    rr client;
    graceful restart;
    import all;
    export all;
}
protocol bgp xenial103 {
    description "10.0.0.103";
    local as 65000;
    neighbor 10.0.0.103 as 65000;
    direct;
    rr client;
    graceful restart;
    import all;
    export all;
}
protocol bgp xenial104 {
    description "10.0.0.104";
    local as 65000;
    neighbor 10.0.0.104 as 65000;
    direct;
    rr client;
    graceful restart;
    import all;
    export all;
}
protocol bgp xenial105 {
    description "10.0.0.105";
    local as 65000;
    neighbor 10.0.0.105 as 65000;
    direct;
    rr client;
    graceful restart;
    import all;
    export all;
}

配置完毕后,重启BIRD: sudo service bird restart

很快,你就可以看到RR从Calico节点同步了路由信息过来:

Shell
1
2
3
4
5
6
7
8
9
10
11
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         localhost       0.0.0.0         UG    0      0        0 wlan1
10.0.0.0        *               255.255.0.0     U     0      0        0 virbr0
172.17.0.0      *               255.255.0.0     U     0      0        0 docker0
172.18.0.0      *               255.255.0.0     U     0      0        0 docker_gwbridge
172.21.0.0      *               255.255.0.0     U     0      0        0 br-29f4509ebfd6
172.27.0.0      xenial-101      255.255.255.192 UG    0      0        0 virbr0
172.27.0.0      xenial-101      255.255.0.0     UG    0      0        0 virbr0
172.27.0.0      xenial-100      255.255.0.0     UG    0      0        0 virbr0
192.168.142.0   *               255.255.254.0   U     9      0        0 wlan1
配置Calico节点

首先禁用全互联,查看Calico的BGP选项,如果启用全互联则禁用之:

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# calicoctl get bgpconfig -o yaml > /tmp/bgp.yaml
 
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: BGPConfiguration
  metadata:
    creationTimestamp: 2018-02-14T02:58:56Z
    name: default
    resourceVersion: "790"
    uid: ff92b98a-1132-11e8-937a-deadbeef00a0
  spec:
    asNumber: 65000
    logSeverityScreen: Info
    # 这里设置为false
    nodeToNodeMeshEnabled: false  
kind: BGPConfigurationList
metadata:
  resourceVersion: "826"
# calicoctl replace -f /tmp/bgp.yaml

然后,添加一个全局的Peer,指向先前创建的RR:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: bgppeer-global-1
spec:
  peerIP: 10.0.0.1
  asNumber: 65000
EOF
 
# calicoctl get BGPPeer -o yaml > /tmp/bgpeer.yaml
# calicoctl replace -f /tmp/bgpeer.yaml

现在,登陆到某个Calico节点,查看其配对情况,应该仅仅和10.0.0.1进行了配对:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
# calicoctl node status
 
Calico process is running.
 
IPv4 BGP status
+--------------+-----------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE |  SINCE   |    INFO     |
+--------------+-----------+-------+----------+-------------+
| 10.0.0.1     | global    | up    | 03:43:38 | Established |
+--------------+-----------+-------+----------+-------------+
 
IPv6 BGP status
No IPv6 peers found.

可以尝试在集群内连接某个Pod,如果可以连接,说明配置成功。 

更简单的方法

现在,你可以在任何物理节点上,执行calico node run命令,运行一个容器,将节点加入Calico CNI网络:

Shell
1
sudo calicoctl node run --ip-autodetection-method interface=virbr0

这样的节点可以直接作为路由反射器使用,也可以直连Pod。

集群内RR

从3.3开始,任何Calico节点均可以作为RR来运行,不需要基础设施或外部的专用RR节点。

节点作为RR

最简单的配置,为Node加上routeReflectorClusterID字段即可:

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  name: node-hostname
  # 标签影响配对
  labels:
    routeReflector: 10.0.0.1
spec:
  bgp:
    asNumber: 64512
    ipv4Address: 10.244.0.1/24
    ipv6Address: 2001:db8:85a3::8a2e:370:7334/120
    # 提示此节点是一个RR(同时也是一个普通Calico节点)
    # 将它的BGP Peers看作RR客户端,除非节点具有相同的routeReflectorClusterID,
    # 这会在BGP协议层次上产生一系列影响
    routeReflectorClusterID: 10.0.0.1
配对设置

3.3为BGPPeer资源添加了字段:

  1. nodeSelector:配对应该在该选择器匹配的节点上发生。原先只能指定节点名称
  2. peerSelector:配对应该在该选择器匹配的RR上发生。原先只能指定RR的IP

示例:

YAML
1
2
3
4
5
6
7
8
9
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: cluster1
spec:
  # 所有节点
  nodeSelector: "all()"
  # 所有具有routeReflector的RR
  peerSelector: "has(routeReflector)"

一种典型的BGP拓扑划分方式:

  1. 将节点分组,每个组包含一个RR
  2. 所有RR进行全互联 
配置
BGP对等实体
概念
概念 说明
Node-to-node mesh

使用full node-to-node mesh选项,可以自动化的配置所有Calico节点之间的对等实体。该选项默认启用,每个Calico节点都自动和任何其它节点进行BGP Peering

适用于几十个节点的规模

Global BGP peers 全局BGP Peer是一个BGP代理,它和网络中所有其它Calico节点进行Peering,典型应用场景是中等规模的部署,所有节点运行在同一个L2网络中,每个节点和RR(一个或一组)配对
AS号配置

默认AS号为64512。如果所有节点在一个AS内部但是你需要定制AS号(例如需要同边界路由器进行Peering),执行以下命令:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 检查默认BGP配置资源是否存在
calicoctl get bgpconfig default
 
# 如果不存在,则:
cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
   name: default
spec:
   logSeverityScreen: Info
   nodeToNodeMeshEnabled: false   # 禁用全节点BGP互联。如果没有进行适当配置,一旦禁用立即无法连通现有的Pod
   asNumber: 65000                # 使用另一个AS号
EOF
 
# 如果存在,则先Dump在Replace
calicoctl get bgpconfig default -o yaml > bgp.yaml
calicoctl replace -f bgp.yaml
禁用全互联

修改sepc.nodeToNodeMeshEnabled即可。

如果你准备从零开始构建网络,并且不希望使用全互联,可以禁用之。如果你准备从全互联切换到其它方式,则需要预先配置好Peering然后再禁用全互联,以保证系统持续的提供对外服务。

全局对等实体

如果你的网络拓扑中存在可以和任意Calico节点配对(Peering)的BGP Speakers,这种BGP Speaker被称为全局对等实体(Global Peer)。一旦配置了全局对等实体,Calico就会自动将所有节点与之配对。

全局对等实体以下场景中有价值:

  1. 添加了一个边界路由器,将其配对到全互联网络中
  2. 配置使用一个或两个RR的Calico网络,这种情况下每个节点都应该和RR配对,全互联应该禁用

配置示例:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: bgppeer-global-3040
spec:
  peerIP: 192.20.30.40
  asNumber: 64567
EOF
 
# 移除全局对等实体
calicoctl delete bgppeer bgppeer-global-3040
节点对等实体

BGP网络拓扑更加复杂的情况下,你可能考虑针对每个Calico节点配置对等实体。示例:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: bgppeer-node-aabbff
spec:
  # 将位于AS 64514中的Peer aa:bb::ff 和 Calico节点node1配对
  peerIP: aa:bb::ff
  node: node1
  asNumber: 64514
EOF
 
# 查看配对
calicoctl get bgpPeer bgppeer-node-aabbff
# 移除配对
calicoctl delete bgppeer bgppeer-node-aabbff
检查配对情况

要检查某个节点的BGP Peer,执行命令:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# SSH到node1,然后执行下面的命令,可以看到所有和node1配对的实体
calicoctl node status
 
# Calico process is running.
 
# IPv4 BGP status
# +--------------+-------------------+-------+----------+-------------+
# | PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
# +--------------+-------------------+-------+----------+-------------+
# | 10.0.0.101   | node-to-node mesh | up    | 15:53:18 | Established |
# | 10.0.0.102   | node-to-node mesh | up    | 15:53:18 | Established |
# | 10.0.0.103   | node-to-node mesh | up    | 15:53:18 | Established |
# | 10.0.0.104   | node-to-node mesh | up    | 15:53:18 | Established |
# | 10.0.0.105   | node-to-node mesh | up    | 15:53:18 | Established |
# +--------------+-------------------+-------+----------+-------------+
 
# IPv6 BGP status
# No IPv6 peers found. 
BGP集群选项
YAML
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  # 资源的唯一性名称
  name: default
spec:
  # 全局日志级别:Debug, Info, Warning, Error, Fatal
  logSeverityScreen: Info
  # 是否启用节点全互联
  nodeToNodeMeshEnabled: true
  # AS号
  asNumber: 65000
Felix配置
YAML
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
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
  # 资源的唯一性名称
  name: default
spec:
  # 指定Felix操控内核顶级Iptable规则链的方式
  # Insert 默认,较安全,可以防止Calico的规则被Bypass
  # Append 需要注意规则链中更前面的规则可能导致Calico的规则被跳过
  chainInsertMode: Insert
  # 从工作负载发送到其所属宿主机(通过端点egress策略之后)的流量的默认处理方式,可选值Drop, Return, Accept
  # 默认情况下Calico阻止从工作负载到其宿主机的流量,实现手段是使用Iptables规则的DROP目标
  # Accept:Calico在处理完工作负载端点的Egress Policy之后,无条件的允许这种流量通过
  # Return:使用INPUT链中的其它规则进行处理。Calico默认在INPUT链顶部插入规则,使用该选项后,Calico在处理
  #         完工作负载端点的Egress Policy之后,即把封包归还给INPUT链下一条规则处理
  defaultEndpointToHostAction: Drop
  # UDP/TCP的协议端口对,Felix总是允许这些宿主机端点上这些端口的入站流量
  # 这可以防止意外的错误配置导致宿主机断开和外部的连接,默认允许SSH、etcd、BGP、DHCP
  failsafeInboundHostPorts:
  - protocol: tcp
    port: 22
  - protocol: udp
    port: 68
  - protocol: tcp
    port: 179
  - protocol: tcp
    port: 2379
  - protocol: tcp
    port: 2380
  - protocol: tcp
    port: 6666
  - protocol: tcp
    port: 6667
  # UDP/TCP的协议端口对,Felix总是允许这些宿主机端点上针对这些端口的出站流量
  failsafeOutboundHostPorts:
  - protocol: udp
    port: 53
  - protocol: udp
    port: 67
  - protocol: tcp
    port: 179
  - protocol: tcp
    port: 2379
  - protocol: tcp
    port: 2380
  - protocol: tcp
    port: 6666
  - protocol: tcp
    port: 6667
  # 设置为true则允许Felix运行在具有RPF的系统上
  ignoreLooseRPF: false
  # Felix解析宿主机端点时,需要排除的网络接口列表,逗号分隔
  # 默认值是排除K8S内部使用的设备kube-ipvs0
  interfaceExclude: kube-ipvs0
  # 用于区分工作负载端点和宿主机端点的网络接口名前缀
  interfacePrefix: cali
  # 是否在宿主机上配置一个IPinIP网络接口
  # 如果你通过calico/node或calicoctl配置IPIP-enabled pool会自动设置为true
  ipipEnabled:false
  # 上述隧道接口的MTU
  ipipMTU:1440
  # 是否启用IPv6支持
  ipv6Support: false
HostEndpoint配置
YAML
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
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
  # 宿主机端点名称
  name: some.name
  # 标签,用于应用对应的策略
  labels:
    type: production
spec:
  # 端点对应的网络接口
  interfaceName: eth0
  # 端点所在的宿主机
  node: myhost
  # 期望和此网络接口对应的IP地址
  expectedIPs:
  - 192.168.0.1
  - 192.168.0.2
  # 配置,用于应用对应的策略
  profiles:
  - profile1
  - profile2
  # 命名端口,可以在Policy Rule中引用
  ports:
  - name: some-port
    port: 1234
    protocol: TCP
  - name: another-port
    port: 5432
    protocol: UDP
WorkloadEndpoint
YAML
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
apiVersion: projectcalico.org/v3
kind: WorkloadEndpoint
metadata:
  # 资源名称
  name: node1-k8s-frontend--5gs43-eth0
  # 资源所属名字空间
  namespace: default
  # 资源的标签
  labels:
    app: frontend
    projectcalico.org/namespace: default
    projectcalico.org/orchestrator: k8s
spec:
  # 此端点所属的工作负载的名字
  workload: nginx
  # 工作负载所属的节点
  node: node1
  # 创建此端点的orchestrator
  orchestrator: k8s
  # 容器网络接口名
  endpoint: eth0
  # 工作负载端点的CNI容器ID
  containerID: 1337495556942031415926535
  # 此工作负载端点所在的Pod名称
  pod: my-nginx-b1337a
  # 在宿主机那一端,对接到工作负载的网络接口名
  interfaceName: cali0ef24ba
  # 网络接口的MAC地址
  mac: ca:fe:1d:52:bb:e9
  # 分配到网络接口的CIDR
  ipNetworks:
  - 192.168.0.0/16
  # 此工作负载的出站流量的网关
  ipv4Gateway: 192.168.0.1
  # 分配到此端点的Calico Profile
  profiles:
  - profile1
  # 命名端口列表
  ports:
  - name: some-port
    port: 1234
    protocol: tcp
  - name: another-port
    port: 5432
    protocol: udp
  # 此端点的NAT规则
  ipNATs:
    # 内部IP地址
    internalIP:
    # 外部IP地址
    externalIP:
IPPool配置
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: my.ippool-1
spec:
  # IP地址范围,端点IP从中分配
  cidr: 10.1.0.0/16
  # 何时使用IPinIP模式,Always, CrossSubnet, Never
  ipipMode: CrossSubnet
  # 如果启用,则利用该池中IP的容器的出站流量被IP遮掩
  natOutgoing: true
  # 如果禁用,则Calico IPAM不会从该池中分配IP地址
  disabled: false
Node配置
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  name: node-hostname
spec:
  bgp:
    # 此节点所属的AS,不指定则使用全局默认AS号
    asNumber: 64512
    # 此节点的IP和子网,会导出,作为该节点上的Calico端点的next-hop
    ipv4Address: 10.244.0.1/24
    ipv6Address: 2001:db8:85a3::8a2e:370:7334/120
    # IP-in-IP隧道中此节点的IP地址
    ipv4IPIPTunnelAddr: 192.168.0.1
  OrchRefs:
    - nodeName: node-hostname
      orchestrator: k8s
NetworkPolicy 
YAML
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
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-tcp-6379
  namespace: production
spec:
  # 匹配的端点
  selector: role == 'database'
  # 此策略针对的流量方向
  types:
  - Ingress
  - Egress
  # 入站规则列表(有序)
  ingress:
  # 允许来自frontend的TCP/6379流量
    # 匹配规则时的行为。可选值:Allow, Deny, Log, Pass
  - action: Allow
    # 匹配协议列表,可选值TCP, UDP, ICMP, ICMPv6, SCTP, UDPLite, 1-255
    protocol: TCP
    # 不匹配协议列表,可选值TCP, UDP, ICMP, ICMPv6, SCTP, UDPLite, 1-255
    notProtocol: UDP
    # 源匹配参数
    source:
      # 根据端点选择器匹配
      selector: role == 'frontend'
      # 根据端点所属CIDR匹配
      nets: 172.21.0.0/16
      # 不匹配的CIDR
      notNets: 172.21.0.0/16
      # 根据名字空间匹配,如果指定,则仅仅目标名字空间中的工作负载端点才能匹配
      namespaceSelector: env = 'dev'
      # 根据端点进行匹配
      ports: 0
      notPorts: 0
    # 目的匹配参数
    destination:
      ports:
      - 6379
    # ICMP匹配规则
    icmp:
      type: 0
      code: 0
    # ICMP不匹配规则
    notICMP:
      # ICMP类型, 0-254
      type: 0
      # ICMP代码, 0-255
      code: 0
  # 出站规则列表
  egress:
  - action: Allow

Calico选择器语法:

语法 说明
all() 匹配所有资源
k == ‘v’ 匹配标签k的值为v的资源
k != ‘v’ 匹配具有标签k,且其值不为v的资源
has(k) 匹配具有标签k的资源
!has(k) 匹配不具有标签k的资源
k in { ‘v1’, ‘v2’ } 匹配标签k的值为v1或v2的资源
k not in { ‘v1’, ‘v2’ } 匹配标签k的值不为v1或v2的资源,或者没有标签k的资源
 Profile
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: projectcalico.org/v3
kind: Profile
metadata:
  name: profile1
  # 使用此Profile的端点,自动添加如下标签
  labels:
    profile: profile1
spec:
  # 此Profile的网络策略
  ingress:
  - action: Deny
    source:
      nets:
      - 10.0.20.0/24
  - action: Allow
    source:
      selector: profile == 'profile1'
  egress:
  - action: Allow
calicoctl

calicoctl是一个命令行工具,使用它可以创建、修改、删除Calico对象。你可以在任何能够访问Calico数据库的主机上使用该命令。

安装
Shell
1
2
3
cd /usr/local/bin
curl -O -L https://github.com/projectcalico/calicoctl/releases/download/v2.0.0/calicoctl
chmod +x calicoctl
配置

很多calicoctl命令都需要访问Calico数据库,你需要通过配置文件来指定数据库的信息:

/etc/calico/calicoctl.cfg
YAML
1
2
3
4
5
6
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "etcdv3"
  etcdEndpoints: "http://10.96.232.136:6666"

注意:在Kubeadm部署方式下,Calico不会使用K8S的etcd,而是自己创建一个,执行下面的命令可以查看:

Shell
1
2
kubectl --namespace=kube-system get service
# calico-etcd ClusterIP 10.96.232.136 <none> 6666/TCP 1h

如果配置正确,下面的命令将会返回节点列表:

Shell
1
2
3
4
5
6
7
8
calicoctl get nodes
# NAME        
# xenial-100  
# xenial-101  
# xenial-102  
# xenial-103  
# xenial-104  
# xenial-105
子命令
子命令 说明
create 根据指定的文件名或者从标准输入来创建资源
replace 替换资源
apply 应用资源:如果资源不存在则创建之,如果存在则替换之
delete 删除资源
get

获取资源信息,支持的资源包括:

bgpConfiguration
bgpPeer
felixConfiguration
globalNetworkPolicy
hostEndpoint
ipPool
networkPolicy
node
profile
workloadEndpoint

示例:

Shell
1
2
# 把默认IP池的配置输出为yaml
calicoctl get ippool -o yaml
convert 转换不同API版本的配置文件
ipam IP地址管理器相关命令:
Shell
1
2
3
4
5
# 释放一个原先被IPAM分配的IP地址,释放完毕后此IP地址可以被重用
calicoctl ipam release --ip=192.168.1.2 
 
# 显示一个IP地址的信息,例如是否被分配,是否被用户或IPAM保留
calicoctl ipam show --ip=192.168.1.1
node run

注意:节点的很多配置可以通过环境变量提供

在当前节点上启动一个calico/node容器实例,以提供Calico网络、网络策略的支持:

Shell
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
# ip/ip6 当前节点的路由IP地址,如果不指定,使用node资源上配置的值
#        如果没有对应的node资源,则尝试自动检测IP地址,如果设置为autodetect则在
#        节点每次启动时强制检测
# as     使用的AS号,如果不指定则使用全局AS号
calicoctl node run [--ip=<IP>] [--ip6=<IP6>] [--as=<AS_NUM>]
# 节点名称,默认为主机名
                     [--name=<NAME>]
# IP地址自动检测方法
# first-found 使用第一个发现的IP地址,如果具有多网卡不建议使用。默认
# can-reach=ip/hostname 使用能到达目标的网络接口
# interface=regrex 网络接口名字正则式
# skip-interface=regrex 排除的网络接口名字正则式
# 示例:
#   --ip-autodetection-method interface=eth.*
#   --ip-autodetection-method interface=eth0
                     [--ip-autodetection-method=<IP_AUTODETECTION_METHOD>]
                     [--ip6-autodetection-method=<IP6_AUTODETECTION_METHOD>]
# 日志存储路径,默认/var/log/calico
                     [--log-dir=<LOG_DIR>]
                     [--node-image=<DOCKER_IMAGE_NAME>]
# BGP后端,gobgp目前试验阶段
                     [--backend=(bird|gobgp|none)]
# 指定配置文件,默认/etc/calico/calicoctl.cfg
                     [--config=<CONFIG>]
# 启动时不创建默认IP池
                     [--no-default-ippools]
                     [--dryrun]
# 执行适当的命令,以配合init system
                     [--init-system]
# 禁用Docker网络
                     [--disable-docker-networking]
# Docker容器中网络接口的名字前缀
                     [--docker-networking-ifprefix=<IFPREFIX>]
                     [--use-docker-networking-container-labels]
 
 
# 示例
calicoctl node run --node-image=docker.gmem.cc/calico/node:latest --ip-autodetection-method interface=virbr0
node status 检查节点的状态
node diags 收集Calico节点的诊断信息
node checksystem 检查节点内核,是否可以作为Calico节点
资源类型
资源类型 说明
node

表示运行Calico的节点,当添加一个主机到Calico集群中后,你需要创建相应的Node资源

当启动一个Calico节点时,它的名称必须和此资源的名称一致

默认情况下,启动一个calico/node实例会自动创建Node资源,使用机器的hostname作为节点名称

bgpPeer

BGP Peer资源代表Calico集群中某个节点与之配对的远程BGP Peer

使用BGP Peer你可以将Calico Newtwork和数据中心结构(例如ToR)连接起来

bgpConfiguration

表示集群的BGP相关的选项

felixConfiguration

表示集群的Felix相关的选项

Felix是运行在任何提供端点(Endpoint)的机器(运行VM或容器的节点)上的守护程序,它负责编程式的路由和ACL,以及为机器上端点提供预期连接性所需的任何东西

hostEndpoint

表示运行Calico的主机上的一个网络接口

每个HostEndpoint可以包含一系列的标签、一个Profile列表,Calico基于这些来应用策略到网络接口。如果没有任何标签、Profile则Calico不会应用任何策略

workloadEndpoint

表示将基于Calico实现网络连接的VM、容器,连接到它们的宿主机的网络接口

WorkloadEndpoint是具有名字空间的资源,只有相同名字空间内定义的networkPolicy才能应用到其上

ipPool

表示一个IP集合,工作负载端点的IP从此集合中分配

IP-in-IP隧道可以用在网络结构(network fabric )强制进行Src/Dest地址检查、并丢弃无法识别的地址的流量的场景下。在某些公有云环境下,你可能无法完全控制网络,特别是无法进行网络路由器和Calico节点之间的BGP配对、各Calico节点也不能L2直连,使用IP-in-IP封装可以确保跨工作负载(Inter-workload)流量正常传输

当启用IP-in-IP模式时,Calico在路由到IP池范围内的工作负载IP时,会对IP封包进行一次包装

设置ipipMode=Always,则从任何启用Calico的主机发往任何基于Calico网络的容器、虚拟机的流量,都会进行包装

设置ipipMode=CrossSubnet,则可以在下面的场景下优化性能:

  1. AWS multi-AZ部署
  2. 多组L2直连的Node,通过路由器建立L3连接
globalNetworkPolicy 全局性的网络策略,不具有名字空间,应用到任何名字空间中的工作负载端点、主机端点
networkPolicy

应用到匹配标签选择器的端点的网络策略,网络策略是命名空间内部的资源

网络策略是一个有序的规则的集合,它应用到标签选择器所匹配的端点

profile 包含应用到分配了Profile的单个的端点的网络策略
 常见问题
node run后网络不通

某次操作意外删除了节点上的calico_node容器,重新执行calicoctl node run恢复容器后,发现此节点无法连接到K8S容器网络,无法ping通任何容器地址。

最终发现,是此节点的配置出现问题(可能是calicoctl node  run的参数不对引发),ipv4Address的掩码错误:

YAML
1
2
# 应该是 10.0.0.1/16,32明显错误
ipv4Address: 10.0.0.1/32

除了此节点以外,其上运行的虚拟机出现同样的问题。修复上述掩码后问题消失。

需要注意一点,正常的路由,出口应该是calicoctl node run时检测到的网络接口:

Shell
1
172.27.252.128  radon           255.255.255.192 UG    0      0        0 virbr0

而出现问题时,该节点上的出口从期望的virbr0变成了tunl0。  

分享这篇文章到:
← Kong学习笔记
乡村宴席 →
2 Comments On This Topic
  1. 回复
    Xu hui
    2018/10/23

    写的很好,感谢

    • 回复
      Alex
      2018/10/24

      :D

Leave a Reply Cancel reply

您可以使用以下网站的账户登录:

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Galaxy学习笔记
  • Cilium学习笔记
  • CNI学习笔记
  • Flannel学习笔记
  • IPVS模式下ClusterIP泄露宿主机端口的问题

Recent Posts

  • Terraform快速参考
  • 草缸2021
  • 编写Kubernetes风格的APIServer
  • 记录一次KeyDB缓慢的定位过程
  • eBPF学习笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
  • Istio中的透明代理问题
    为何需要透明代理 Istio的Sidecar作为一个网络代理,它拦截入站、出站的网络流量。拦截入站流量后,会使 ...
  • Cilium学习笔记
    简介 Cilium Cilium是在Docker/K8S之类的容器管理平台下,透明的为应用程序服务提供安全网 ...
  • 彩彩 2020年6月黄崖关

  • 总部远眺 2020年5月深圳

  • 绚丽之花 寻味顺德

  • tuanbolake 团泊湖野餐

TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 88 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • 基于Calico的CNI 27 people like this
  • Ceph学习笔记 26 people like this
  • Three.js学习笔记 24 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
  • 绿色记忆:Nginx知识集锦 on Apache HTTP Server知识集锦
  • NotMeBug on AspectJ编程学习笔记
©2005-2023 Gmem.cc | Powered by WordPress