使用 Containerlab + Kind 快速部署 Cilium BGP 环境一文中使用Containerlab和Cilium实现了模拟环境下的Cilium BGP网络。它使用Containerlab模拟外部BGP路由器,使用Cilium BGP的CiliumBGPPeeringPolicy与外部路由器建立BGP关系。

containerLab的简单用法

containerLab支持很多节点类型设置,相对比较复杂。实际使用中只需要掌握基本的组网即可

安装

网络布线

如果没有指定网络模式,则使用默认的bridge

container mode用于于其他容器共享网络命名空间

my-node:
kind: linux
sidecar-node:
kind: linux
network-mode: container:my-node #my-node为另一个容器
startup-delay: 10
name: srl02

topology:
kinds:
srl:
type: ixrd3 #srlinux支持的类型,用于模拟硬件
image: ghcr.io/nokia/srlinux #使用的容器镜像
nodes:
srl1: #节点1信息
kind: srl
srl2: #节点2信息
kind: srl links:
- endpoints: ["srl1:e1-1", "srl2:e1-1"] #节点1和节点2的点对点连接信息

上述配置包含两个SR Linux节点srl1srl2,它们通过以下两种方式互通:

  1. 都通过接口mgmt连接到了默认的容器网桥clab(使用docker network ls查看)
  2. 通过接口e1-1进行了点到点连接。点到点连接是通过一对veth实现的。enpoints描述了一对veth,因此数组中有且只能有2个元素

执行如下命令部署网络:

# containerlab deploy -t srl02.clab.yml

生成的容器网络如下:

IPv4: subnet 172.20.20.0/24, gateway 172.20.20.1
IPv6: subnet 2001:172:20:20::/64, gateway 2001:172:20:20::1

配置管理网络

用户自定义网络

一般情况下使用默认默认配置即可,但如果默认的网络于现有网络出现冲突,则可以手动指定网段:

mgmt:
network: custom_mgmt # management network name
ipv4_subnet: 172.100.100.0/24 # ipv4 range
ipv6_subnet: 2001:172:100:100::/80 # ipv6 range (optional) topology:
# the rest of the file is omitted for brevity

可以手动给节点指定特定IP,相当于静态IP,但此时需要给所有容器手动指定IP:

mgmt:
network: fixedips #指定容器网络名称(默认的容器网络名称为clab)
bridge: mybridge #指定网桥名称(默认的网桥名称为 br-<network-id>)
ipv4_subnet: 172.100.100.0/24
ipv6_subnet: 2001:172:100:100::/80 topology:
nodes:
n1:
kind: srl
mgmt_ipv4: 172.100.100.11 # set ipv4 address on management network
mgmt_ipv6: 2001:172:100:100::11 # set ipv6 address on management network
查看拓扑图

执行如下命令可以查看拓扑图:

# containerlab graph -t srl02.clab.yml

重新配置网络

如果修改了配置文件可以使用如下命令重新配置网络:

# containerlab deploy -t srl02.clab.yml --reconfigure

例子

官方给出了很多配置组网的例子。组网中一般涉及两种实例:VM和路由器,后者可以使用FRR组件模拟。

原文配置解析

Kubernetes配置

下面使用kind创建了一个kubernetes集群,其中包含一个控制节点和3个工作节点,并分配和节点IP和pod网段。

注意配置中禁用了默认的CNI,因此使用kind部署之后,节点之间由于无法通信而不会Ready

# cluster.yaml
kind: Cluster
name: clab-bgp-cplane-demo
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true # 禁用默认 CNI
podSubnet: "10.1.0.0/16" # Pod CIDR
nodes:
- role: control-plane # 节点角色
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.1.2 # 节点 IP
node-labels: "rack=rack0" # 节点标签 - role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.2.2
node-labels: "rack=rack0" - role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.3.2
node-labels: "rack=rack1" - role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.4.2
node-labels: "rack=rack1"

Cilium安装

原文中的验证步骤可能不大合理,应该是先启动kubernetes和cilium,然后再启动containerlab,否则kubernetes因为没有CNI,也无法生成路由。

# values.yaml
tunnel: disabled ipam:
mode: kubernetes ipv4NativeRoutingCIDR: 10.0.0.0/8 # 开启 BGP 功能支持,等同于命令行执行 --enable-bgp-control-plane=true
bgpControlPlane:
enabled: true k8s:
requireIPv4PodCIDR: true
helm repo add cilium https://helm.cilium.io/
helm install -n kube-system cilium cilium/cilium --version v1.12.1 -f values.yaml

完成上述配置之后kubernetes集群就启动了,节点也Ready了,下面进行BGP的配置。

BPG配置

原文中使用frrouting/frr:v8.2.2镜像来实现BGP路由发现。更多参数配置可以参见官方手册。文中的containerlab的topo文件如下:

# topo.yaml
name: bgp-cplane-demo
topology:
kinds:
linux:
cmd: bash
nodes:
router0:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- ip addr add 10.0.0.0/32 dev lo
- ip route add blackhole 10.0.0.0/8
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'router bgp 65000'
-c ' bgp router-id 10.0.0.0'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor ROUTERS default-originate'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor net1 interface peer-group ROUTERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!' tor0:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- ip link del eth0
- ip addr add 10.0.0.1/32 dev lo
- ip addr add 10.0.1.1/24 dev net1
- ip addr add 10.0.2.1/24 dev net2
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- /usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'frr defaults datacenter'
-c 'router bgp 65010'
-c ' bgp router-id 10.0.0.1'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor SERVERS peer-group'
-c ' neighbor SERVERS remote-as internal'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor 10.0.1.2 peer-group SERVERS'
-c ' neighbor 10.0.2.2 peer-group SERVERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!' tor1:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- ip link del eth0
- ip addr add 10.0.0.2/32 dev lo
- ip addr add 10.0.3.1/24 dev net1
- ip addr add 10.0.4.1/24 dev net2
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- /usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'frr defaults datacenter'
-c 'router bgp 65011'
-c ' bgp router-id 10.0.0.2'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor SERVERS peer-group'
-c ' neighbor SERVERS remote-as internal'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor 10.0.3.2 peer-group SERVERS'
-c ' neighbor 10.0.4.2 peer-group SERVERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!' server0:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:control-plane
exec:
- ip addr add 10.0.1.2/24 dev net0
- ip route replace default via 10.0.1.1 server1:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker
exec:
- ip addr add 10.0.2.2/24 dev net0
- ip route replace default via 10.0.2.1 server2:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker2
exec:
- ip addr add 10.0.3.2/24 dev net0
- ip route replace default via 10.0.3.1 server3:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker3
exec:
- ip addr add 10.0.4.2/24 dev net0
- ip route replace default via 10.0.4.1 links:
- endpoints: ["router0:net0", "tor0:net0"]
- endpoints: ["router0:net1", "tor1:net0"]
- endpoints: ["tor0:net1", "server0:net0"]
- endpoints: ["tor0:net2", "server1:net0"]
- endpoints: ["tor1:net1", "server2:net0"]
- endpoints: ["tor1:net2", "server3:net0"]

该topo中涉及3个路由器:router0、tor0、tor1。以及4个普通节点:server0、server1、server2、server3,这4个节点与kubernetes的节点(容器部署)共享相同的网络命名空间。

下面看下各个节点是如何

router0的配置

下面是router0的bgp配置,其地址为10.0.0.0

         vtysh -c 'conf t'
-c 'router bgp 65000'
-c ' bgp router-id 10.0.0.0'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor ROUTERS default-originate'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor net1 interface peer-group ROUTERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!'
  • vtysh -c 'conf t':通过vtysh命令进入交互界面,然后进入配置界面
  • 'router bgp 65000':配置BGP路由器的ASN(AS number),BGP协议使用该数值来判断BGP连接的是内部还是外部。输入该命令之后就可以执行BGP命令。
  • 'bgp router-id 10.0.0.0':指定router-ID,用于标识路由器。此处使用IP作为路由标识
  • 'no bgp ebgp-requires-policy':不需要使用策略来交换路由信息。
  • 'neighbor ROUTERS peer-group':定义一个peer group,用于交换路由,一个peer group中可以有多个peer
  • 'neighbor ROUTERS remote-as external':router0的邻居为tor0和tor1,它们都使用不同的ASN,因此将tor0和tor1作为EBGP,EBGP会在传播路由的时候修改下一跳。参考:EBGP vs IBGP
  • 'neighbor ROUTERS default-originate':将默认路由0.0.0.0发送给邻居。
  • 'neighbor net0 interface peer-group ROUTERS'/'neighbor net0 interface peer-group ROUTERS':将对端绑定到一个peer group。这里的对端可以是接口名称或是邻居标签
  • 'address-family ipv4 unicast':进入IPv4单播配置界面
  • 'redistribute connected':将路由从其他协议重新分发到BGP,此处为系统的直连路由。
  • 'exit-address-family':退出地址族配置。

上述配置中,为router0添加了邻居net0(连接到tor0)和net1(连接到tor1),并在BGP中引入了ipv4的直连路由。此时组网如下:

tor0配置
         vtysh -c 'conf t'
-c 'frr defaults datacenter'
-c 'router bgp 65010'
-c ' bgp router-id 10.0.0.1'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor SERVERS peer-group'
-c ' neighbor SERVERS remote-as internal'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor 10.0.1.2 peer-group SERVERS'
-c ' neighbor 10.0.2.2 peer-group SERVERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'

此处配置与router0大体相同,它同样创建了一个EBGP类型的peer group ROUTERS,将net0(连接到router0)作为邻居。同时它创建一个IBGP类型的peer group SERVERS,并将server0server1的地址作为邻居。

tor1tor0的配置类似,此处不再详述。最后的组网如下。其中tor0tor1router0建立了邻居关系。另外需要注意的是,containerlab网络中的server0~3分别与kubernetes的对应节点共享网络命名空间。

router0上查看bgp邻居关系,可以看到router0tor0(net0)、tor1(net1)建立了邻居关系:

router0# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.0.0.0, local AS number 65000 vrf-id 0
BGP table version 8
RIB entries 15, using 2760 bytes of memory
Peers 2, using 1433 KiB of memory
Peer groups 1, using 64 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
net0 4 65010 15 15 0 0 0 00:00:20 3 9 N/A
net1 4 65011 15 15 0 0 0 00:00:20 3 9 N/A Total number of neighbors 2

tor0上查看邻居关系,可以看到,tor0并没有与kubernetes节点建立邻居关系,因此无法获取kubernetes pod节点的路由信息。

tor0# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.0.0.1, local AS number 65010 vrf-id 0
BGP table version 9
RIB entries 15, using 2760 bytes of memory
Peers 3, using 2149 KiB of memory
Peer groups 2, using 128 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
router0(net0) 4 65000 19 20 0 0 0 00:00:33 6 9 N/A
10.0.1.2 4 0 0 0 0 0 0 never Active 0 N/A
10.0.2.2 4 0 0 0 0 0 0 never Active 0 N/ Total number of neighbors 3

router0上查看bgp发现的路由,可以看到不存在pod网段(10.1.0.0/16)的路由

router0# show bgp ipv4 all

For address family: IPv4 Unicast
BGP table version is 8, local router ID is 10.0.0.0, vrf id 0
Default local pref 100, local AS 65000
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path
*> 10.0.0.0/32 0.0.0.0 0 32768 ?
*> 10.0.0.1/32 net0 0 0 65010 ?
*> 10.0.0.2/32 net1 0 0 65011 ?
*> 10.0.1.0/24 net0 0 0 65010 ?
*> 10.0.2.0/24 net0 0 0 65010 ?
*> 10.0.3.0/24 net1 0 0 65011 ?
*> 10.0.4.0/24 net1 0 0 65011 ?
*> 172.20.20.0/24 0.0.0.0 0 32768 ? Displayed 8 routes and 8 total paths

与kubernetes建立BGP

上述配置中,tor0tor1已经将kubernetes的节点作为IBGP,下面进行kubernetes侧BPG配置。cilium的CiliumBGPPeeringPolicy CRD中可以配置BGP peer信息。

apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
name: rack0
spec:
nodeSelector:
matchLabels:
rack: rack0
virtualRouters:
- localASN: 65010
exportPodCIDR: true # 自动宣告 Pod CIDR
neighbors:
- peerAddress: "10.0.0.1/32" # tor0 的 IP 地址
peerASN: 65010
---
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
name: rack1
spec:
nodeSelector:
matchLabels:
rack: rack1
virtualRouters:
- localASN: 65011
exportPodCIDR: true
neighbors:
- peerAddress: "10.0.0.2/32" # tor1 的 IP 地址
peerASN: 65011

上述配置中将标签为rack=rack0的节点(即control-planeworker)与tor0建立邻居,将标签为rack=rack1的节点(即workerworker2)与tor1建立邻居:

# k get node -l rack=rack0
NAME STATUS ROLES AGE VERSION
clab-bgp-cplane-demo-control-plane Ready control-plane 2d11h v1.24.0
clab-bgp-cplane-demo-worker Ready <none> 2d11h v1.24.0
# k get node -l rack=rack1
NAME STATUS ROLES AGE VERSION
clab-bgp-cplane-demo-worker2 Ready <none> 2d11h v1.24.0
clab-bgp-cplane-demo-worker3 Ready <none> 2d11h v1.24.0

CiliumBGPPeeringPolicy各个字段的说明如下

nodeSelector: Nodes which are selected by this label selector will apply the given policy

 virtualRouters: One or more peering configurations outlined below. Each peering configuration can be thought of as a BGP router instance.

    virtualRouters[*].localASN: The local ASN for this peering configuration

    virtualRouters[*].exportPodCIDR: Whether to export the private pod CIDR block to the listed neighbors

    virtualRouters[*].neighbors: A list of neighbors to peer with
neighbors[*].peerAddress: The address of the peer neighbor
neighbors[*].peerASN: The ASN of the peer

完成上述配置之后,containerlab的router0tor0tor1就学习到了kubernetes的路由信息:

查看tor0的bgp邻居,可以看到它与clab-bgp-cplane-demo-control-plane(10.0.1.2)clab-bgp-cplane-demo-worker(10.0.2.2)成功建立了邻居关系:

tor0# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.0.0.1, local AS number 65010 vrf-id 0
BGP table version 13
RIB entries 23, using 4232 bytes of memory
Peers 3, using 2149 KiB of memory
Peer groups 2, using 128 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
router0(net0) 4 65000 1430 1431 0 0 0 01:10:58 8 13 N/A
clab-bgp-cplane-demo-control-plane(10.0.1.2) 4 65010 46 52 0 0 0 00:02:12 1 11 N/A
clab-bgp-cplane-demo-worker(10.0.2.2) 4 65010 47 53 0 0 0 00:02:15 1 11 N/A Total number of neighbors 3

查看tor1的bgp邻居,可以看到它与clab-bgp-cplane-demo-worker2(10.0.3.2)clab-bgp-cplane-demo-worker3(10.0.4.2)成功建立了邻居关系:

tor1# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.0.0.2, local AS number 65011 vrf-id 0
BGP table version 13
RIB entries 23, using 4232 bytes of memory
Peers 3, using 2149 KiB of memory
Peer groups 2, using 128 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
router0(net0) 4 65000 1436 1437 0 0 0 01:11:15 8 13 N/A
clab-bgp-cplane-demo-worker2(10.0.3.2) 4 65011 53 60 0 0 0 00:02:31 1 11 N/A
clab-bgp-cplane-demo-worker3(10.0.4.2) 4 65011 54 61 0 0 0 00:02:33 1 11 N/A Total number of neighbors 3

查看route0的配置可以发现其获取到了Pod的路由信息:

router0# show bgp ipv4 all

For address family: IPv4 Unicast
BGP table version is 12, local router ID is 10.0.0.0, vrf id 0
Default local pref 100, local AS 65000
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path
*> 10.0.0.0/32 0.0.0.0 0 32768 ?
*> 10.0.0.1/32 net0 0 0 65010 ?
*> 10.0.0.2/32 net1 0 0 65011 ?
*> 10.0.1.0/24 net0 0 0 65010 ?
*> 10.0.2.0/24 net0 0 0 65010 ?
*> 10.0.3.0/24 net1 0 0 65011 ?
*> 10.0.4.0/24 net1 0 0 65011 ?
*> 10.1.0.0/24 net0 0 65010 i
*> 10.1.1.0/24 net1 0 65011 i
*> 10.1.2.0/24 net0 0 65010 i
*> 10.1.3.0/24 net1 0 65011 i
*> 172.20.20.0/24 0.0.0.0 0 32768 ? Displayed 12 routes and 12 total paths

kubernetes的Pod网络

本环境下,kubernetes的Pod通过分别连接到pod命名空间和系统命名空间的一对veth实现互通,当报文从pod命名空间传递到系统命名空间之后就会通过系统路由进行报文分发。

思考

如果将router0tor0tor1和kubernetes的所有节点作为一个IBGP会怎么样(即所有的ASN都相同,都是internal类型的)?

答:此时由于tor0tor1无法将学习到的路由转发给router0,将导致router0缺少pod路由,进而导致网络tor0tor1不通

EBGP和IBGP在技术实现上的第三个区别在路由转发的行为上。通过IBGP学习到的路由,不能传递给其他的IBGP。这么作是为了防止路由环路(loop)。EBGP通过BGP协议里面的AS_PATH和其他元素过滤来自于自己的路由,但是IBGP运行在一个AS内部,没有AS_PATH,所以IBGP干脆不转发来自于其他IBGP的路由。

由于不能转发路由,这要求所有的IBGP router两两相连,组成一个full-mesh的网络。Full-mesh的连接数与节点的关系是n*(n-1),连接数随着节点数的增加而迅速增加,这给配置和管理带来了问题。

参考

TIPs:

  • BGP简单调试:首先使用show bgp summary查看本节点与邻居是否协商成功,然后使用show bgp ipv4 wide查看本节点学习到的路由即可
  • 此外还可以通过show bgp neighbor查看邻居状态,以及通过show bgp peer-group查看peer group的信息,使用show bgp nexthop查看下一跳表

使用containerlab搭建cilium BGP环境解析的更多相关文章

  1. Windows下搭建PHP开发环境

    PHP集成开发环境有很多,如XAMPP.AppServ......只要一键安装就把PHP环境给搭建好了.但这种安装方式不够灵活,软件的自由组合不方便,同时也不利于学习.所以我还是喜欢手工搭建PHP开发 ...

  2. 使用Apache+Dreamweaver(或者H-builder)搭建php开发环境

    使用得工具说明 php+Apache服务器+Dreamweaver+mysql数据库 下载安装好wamp,可以在网上直接百度下载,为了方便,我给放个百度云的链接.wamp下载:链接:http://pa ...

  3. mac搭建PHP开发环境

    在Mac系统上搭建Php服务器环境: LAMP: Linux Apache MySQL PHP MAMP: MACOS APACHE(自带) MYSQL(需自己安装) PHP(自带) 一.APACHE ...

  4. (一)Windows下搭建PHP开发环境及相关注意事项

    PHP集成开发环境有很多,如XAMPP.AppServ......只要一键安装就把PHP环境给搭建好了.但这种安装方式不够灵活,软件的自由组合不方便,同时也不利于学习.所以我还是喜欢手工搭建PHP开发 ...

  5. [转]Windows下搭建PHP开发环境

    原文:http://www.cnblogs.com/pharen/archive/2012/02/06/2340628.html PHP集成开发环境有很多,如XAMPP.AppServ......只要 ...

  6. docker 搭建 web 服务环境

    docker容器虽然早就听说过,但是本人还真的没去用过,刚好看到相关的文章,就分享了下,有机会可以实践下...... 做过开发的人对开发环境的安装.配置应该都不会太陌生,不管你做什么开发,对开发环境都 ...

  7. 使用IntelliJ IDEA和Maven管理搭建Web开发环境(以Spring MVC为例)(二)

    前言:在使用IntelliJ IDEA和Maven管理搭建Web开发环境(以Spring MVC为例)(一)中已经介绍了如何对web基础环境进行搭建,这里主要演示,如何对spring环境进行搭建,然后 ...

  8. [转载]使用VS2015搭建Lua开发环境

    参考原文请看: Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境(一) Lua学习笔记2:Windows7下使用VS2015搭建Lua开发环境(二) 本篇主要分以下几个部分: 一 ...

  9. 如何在 Windows 10 中搭建 Node.js 环境?

    [编者按]本文作者为 Szabolcs Kurdi,主要通过生动的实例介绍如何在 Windows 10 中搭建 Node.js 环境.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 在本文中 ...

随机推荐

  1. NC207040 丢手绢

    NC207040 丢手绢 题目 题目描述 "丢丢丢手绢,轻轻地放在小朋友的后面,大家不要告诉她,快点快点抓住她,快点快点抓住她." 牛客幼儿园的小朋友们围成了一个圆圈准备玩丢手绢的 ...

  2. mongodb 数据块迁移的源码分析

    1. 简介 上一篇我们聊到了mongodb数据块的基本概念,和数据块迁移的主要流程,这篇文章我们聊聊源码实现部分. 2. 迁移序列图 数据块迁移的请求是从配置服务器(config server)发给( ...

  3. 【ASP.NET Core】自定义的配置源

    本文的主题是简单说说如何实现 IConfigurationSource.IConfigurationProvider 接口来自定义一个配置信息的来源,后面老周给的示例是实现用 CSV 文件进行应用配置 ...

  4. 业务可视化-让你的流程图"Run"起来(2.问题与改进)

    前言 首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来]的支持. 分享一下近期我对这个项目的一些改进. 问题&改进 问题1: 流程运行开始后,异步执行,无 ...

  5. 【每天学一点-04】使用脚手架搭建 React+TypeScript+umi.js+Antd 项目

    一.使用脚手架搭建项目框架 1.首先使用脚手架搭建React项目(React+TypeScript+Umi.js) 在控制台输入命令:yarn create @umijs/umi-app 2.引入An ...

  6. 基于二进制安装Cloudera Manager集群

    一.环境准备 参考链接:https://www.cnblogs.com/zhangzhide/p/11108472.html 二.安装jdk(三台主机都要做) 下载jdk安装包并解压:tar xvf ...

  7. web前端要学些什么,学习思路

    有没有Web前端大神给个意见 我已学了 html  css JS 马上要学Vue或React不知道那个好 需不需要先了解一下jQuery 还需要学些什么

  8. 业务可视化-让你的流程图"Run"起来(6.定时任务&Spring-Batch的集成)

    前言 首先,感谢大家对上一篇文章[业务可视化-让你的流程图"Run"起来(5.SpringBoot集成&微服务编排)]的支持. 分享一下近期我对这个项目的一些改进. 在项目 ...

  9. DolphinScheduler & K8s 在优路科技的实践

    T 摘要 · 本文通过介绍DolphinScheduler on Kubernetes 在优路科技的实践,阐述了DolphinScheduler如何在云原生时代,更好地助力企业实现高效的数据调度解决方 ...

  10. Docker 02 基本命令

    参考源 https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0 https://www.bilibili.com/vid ...