Kubernetes Calic IPAM 电脑版发表于:2022/11/27 16:41  >#Kubernetes Calico IPAM [TOC] ## IPAM 简介 tn2>CNI的职责包括给 Container 分配网络设备,并且分配IP,IPAM(IP Address Management)就是指IP分配相关的功能和规范。<br/> CNI本身只是一个规范,不同的实现在 IPAM 方面的功能集也不尽相同。下面将首先尝试说明下不同 CNI在这块的实现。<br/> calico开发的IPAM组件叫 calico-ipam, 它使用 calico 的 IP pool resource来管理 IP.。它的主要优势就是可以将 pool 分割成小的 block, 并且可以动态对分配给不同的 node。node 上的 ip 利用率会更高,并且可扩展性也很好。calico 目前也支持给不同的namespace分配不同的 ip pool. 从大的方面来看,其实最终 各个CNI 实现要解决的问题都是类似的,一般区别只是 dataplane 以及具体的 CRD的设计不太一样。所以这些功能很可能(已经有了或者以后会有)出现在其他的 CNI 上面。 ## 设置Calico IPAM tn2>首先需要设置CNI IPAM的配置为`calico-ipam`。 ```bash cd /etc/cni/net.d/ ls cat 10-calico.conflist ```  tn2>关于calico ipam支持的方式有下列几种: <br/> 1.根据拓扑分配地址 2.为pod使用特定地址 3.从一个IP池迁移到另一个 4.使用IP范围与旧式防火墙互操作 5.查看IP地址利用率 6.更改IP地址块大小 ## 根据拓扑分配地址 tn2>简单来讲:我们可以给我们的集群节点服务器打上标签,然后更具这些标签打上不同的ip段。 怎么打? 就在我们ippool里面的selector选标签决定了ip池的范围。  ```bash calicoctl get ippool -o wide ```  >### 简单实践 tn2>首先我们禁用掉原有的`default-ipv4-ippool`。 ```bash calicoctl get ippool -o yaml > default-ipv4-ippool.yaml vim default-ipv4-ippool.yaml # 添加disabled: true calicoctl apply -f default-ipv4-ippool.yaml ``` tn2>禁用掉后我们现在ip池中没有一个可用的ip池,所以新的pod将分配不了IP。 接下来为我们的node打上标签。 ```bash # 为k8s-1打上rack=0的标签 kubectl label nodes k8s-1 rack=0 # 为k8s-2打上rack=0的标签 kubectl label nodes k8s-2 rack=1 ```  tn2>接下来根据不同的节点标签使用不同的IP池子。 ```bash calicoctl create -f -<<EOF apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: rack-0-ippool spec: cidr: 192.168.0.0/24 ipipMode: Always natOutgoing: true nodeSelector: rack == "0" EOF ``` ```bash calicoctl create -f -<<EOF apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: rack-1-ippool spec: cidr: 192.168.1.0/24 ipipMode: Always natOutgoing: true nodeSelector: rack == "1" EOF ``` ```bash calicoctl get ippool -o wide ```  tn2>我们可以看到名为`rack-0-ippool`的IP池子为拥有`rack == "0"`标签的节点使用`192.168.0.0/24`段,`rack-1-ippool`的IP池子为拥有`rack == "1"`标签的节点使用`192.168.1.0/24`段。 我们改一下`cni.yaml`,然后跑一下。 ```bash vim cni.yaml ```  ```bash kubectl apply -f cni.yaml kubectl get pod ```  tn2>我们的两个pod跑起来了,可以发现在k8s-1节点上的IP为`192.168.0.129`,k8s-2节点上的IP为`192.168.1.193`,它们分配的IP是不同的IP池子。 ok,这就是基于拓扑分配IP地址。 ## 为pod使用特定地址 tn2>当我们的Pod需要用到特定的IP地址时,Calico一般采用注释这个IP的方式来做的,下面我们将进行简单的实践。 >### 简单实践 tn2>首先我们删除刚刚创建的ippools。 ```bash calicoctl delete ippool rack-0-ippool rack-1-ippool ``` tn2>创建一个新的IP池,值得注意的是这里的nodeSelector是选择不允许所有的节点`"!all()"`。 ```bash vim net.yaml ``` ```yaml apiversion: projectcalico.org/v3 kind: IPPool metadata: name: staticippool spec: cidr: 172.16.0.0/26 blockSize: 29 ipipMode: Always natOutgoing: true nodeSelector: "!all()" ``` tn2>然后应用一下。 ```bash calicoctl apply -f net.yaml calicoctl get ippool -o wide ```  tn2>然后我们在我们的Pod上打上`cni.projectcalico.org/ipAddrs`标签并设置为我们`staticippool`IP 池中网段下的IP。 ```bash vim calico_static.yaml ``` ```yaml apiVersion: v1 kind: Pod metadata: name: calico-static-pod labels: app: myapp annotations: cni.projectcalico.org/ipAddrs: "[\"172.16.0.2\"]" spec: containers: - name: static-container image: burlyluo/nettoolbox ``` ```bash kubectl apply -f calico_static.yaml kubectl get pod -o wide ```  tn2>这就是为pod使用特定地址。 那要是使用Deployment怎么办? 在`cni.projectcalico.org/ipAddrs`中定义了多少个ip,就可以replicas多少个pod。 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: static-ip spec: selector: matchLabels: app: nginx replicas: 1 # tells deployment to run 1 pods matching the template template: metadata: labels: app: nginx annotations: "cni.projectcalico.org/ipAddrs": "[\"172.16.0.5\"]" spec: containers: - name: nginx image: burlyluo/nettoolbox ``` ## 从一个IP池迁移到另一个 tn2>简单来讲创建一个新的IP Pool,把老的的IP Pool禁用掉,再把Pod一个一个的删除。 这里我就不做多的演示了,自己可以参考文档:https://projectcalico.docs.tigera.io/networking/migrate-pools ## 使用IP范围与旧式防火墙互操作 tn2>简单来讲:与指定Pod特定的IP差不多,都是通过注释的方式进行。 只是这里指定的是IP Pools。 ```bash # ipv4 cni.projectcalico.org/ipv4pools: '["pool-1", "pool-2"]' # ipv6 cni.projectcalico.org/ipv6pools: '["pool-1", "pool-2"]' ``` ## 查看IP地址利用率(地址分配) tn2>打印有关借用IP地址的详细信息。 ```bash calicoctl ipam show --show-borrowed ```  tn2>打印当前IPAM配置。 ```bash calicoctl ipam show --show-configuration ```  tn2>检测ipam的详细信息,以及存在的问题。 ```bash calicoctl ipam check ```  tn2>如果你的IP地址有问题了,比如IP Pool替换更新了,你需要将Pod重新Release一下,怎么做? 首先需要Lock一下,告诉其他人先不要分配IP地址。 ```bash calicoctl datastore migrate lock ``` tn2>然后把IPAM的检测以json的方式导出到`report.json`文件中。 ```bash calicoctl ipam check -o report.json cat report.json ```  tn2>然后我们释放未设置的ip地址。大概会检测20分钟。 ```bash calicoctl ipam release --from-report=report.json ``` tn2>然后我们解锁。 ```bash calicoctl datastore migrate unlock ``` tn2>最后验证一下。 ```bash calicoctl ipam check ```