016-K8S-固定Pod IP地址,基于Calico插件

需求:

在某种情况下,创建 Pod 时主动给它分配IP地址,并要求即使重启Pod IP地址也不变。

这里演示 Calico 网络插件环境中,如何给 Pod 分配固定的 IP 地址。

一、确认环境

1. 修改 calico 配置文件

修改配置文件 vim /etc/cni/net.d/10-calico.conflist ,将 ipam 类型修改为 calico-ipam

$ vim /etc/cni/net.d/10-calico.conflist

"ipam": {
          "type": "calico-ipam"
}

image-20250726135707385

2. 安装 calicoctl 工具

二进制方式安装 calicoctl 工具,版本号选择 Calico 相同的版本,这里是 3.26.3

2.1 安装 calicoctl

# 下载 calicoctl 二进制包
$ wget https://github.com/projectcalico/calico/releases/download/v3.26.3/calicoctl-linux-amd64

# 将二进制包放到指定目录
$ mv calicoctl-linux-amd64 /usr/local/bin/calicoctl

# 授权
$ chmod +x /usr/local/bin/calicoctl



# 永久设置环境变量





calicoctl get ippool --show-ip-allocations

2.2 配置 calicoctl

calicoctl 通过读写 calico 的数据存储系统( datastore )进行查看或者其他各类管理操作,通常,它需要提供认证信息经由相应的数据存储完成认证。在使用Kubernetes API 数据存储时,需要使用类似 kubectl 的认证信息完成认证。它可以通过环境变量声明的 DATASTORE_TYPEKUBECONFIG 接入集群,例如以下命令格式运行 calicoctl :

# 临时设置环境变量
$ export CALICO_DATASTORE_TYPE=kubernetes
$ export CALICO_KUBECONFIG=~/.kube/config

# 测试
$ calicoctl get nodes
NAME           
k8s-master01   
k8s-node01     
k8s-node02     
k8s-node03

也可以直接将认证信息等保存于配置文件中,calicoctl 默认加载 /etc/calico/calicoctl.cfg 配置文件读取配置信息,如下所示:

$ cat /etc/calico/calicoctl.cfg 
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"       
  kubeconfig: "/root/.kube/config"

3. 查看 calico 的 CIDR 地址范围

$ calicoctl get ippool
NAME                  CIDR            SELECTOR   
default-ipv4-ippool   171.20.0.0/16   all()

4. 创建 Pod

在 CIDR 地址范围内给 Pod 设定一个 IP 地址。

IP 地址范围:171.20.0.0 到 171.20.255.255

4.1 直接创建 Pod

资源清单1:fixed-pod-ip.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  annotations:
    # 设置Pod固定ip地址
    "cni.projectcalico.org/ipAddrs": "[\"171.20.45.27\"]"
  name: fixed-pod-ip
  namespace: default
spec:
  containers:
    - image: nginx:1.29.0
      imagePullPolicy: IfNotPresent
      name: nginx

执行资源清单

# 执行资源清单,创建Pod
$ kubectl apply -f fixed-pod-ip.yaml

# 查看Pod,使用的正是分配的IP
$ kubectl get pods -o wide -w
NAME           READY   STATUS              RESTARTS   AGE   IP       NODE         NOMINATED NODE   READINESS GATES
fixed-pod-ip   0/1     ContainerCreating   0          3s    <none>   k8s-node01   <none>           <none>
fixed-pod-ip   0/1     ContainerCreating   0          3s    <none>   k8s-node01   <none>           <none>
fixed-pod-ip   1/1     Running             0          7s    171.20.45.27   k8s-node01   <none>           <none>

# 测试访问
$ curl http://171.20.45.27:80
<!DOCTYPE html>
<html>
<body>
<h1>Welcome to nginx!</h1>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

4.2 创建 Deployment

资源清单:fixed-deploy-ip.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fixed-deploy-ip
  labels:
    app: my-deploy
spec:
  selector:
    matchLabels:
      app: fixed-deploy
  template:
    metadata:
      labels:
        app: fixed-deploy
      annotations:
        # 设置Pod固定ip地址
        "cni.projectcalico.org/ipAddrs": "[\"171.20.42.65\"]"
    spec:
      containers:
        - image: nginx:1.29.0
          imagePullPolicy: IfNotPresent
          name: nginx

执行资源清单

# 执行资源清单,创建Pod
$ kubectl apply -f fixed-deploy-ip.yaml

# Pod使用Ip为手动分配的IP
$ kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
fixed-deploy-ip-6fcf56c75b-tk6nb   1/1     Running   0          78s   171.20.42.65   k8s-node01   <none>           <none>

# 删除Pod,重新生成Pod
$ kubectl delete pod fixed-deploy-ip-6fcf56c75b-tk6nb

# 新的Pod ip 依旧是手动分配的IP
$ kubectl get pods -o wide -w
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
fixed-deploy-ip-6fcf56c75b-25pxm   1/1     Running   0          11s   171.20.42.65   k8s-node02   <none>           <none>

注意: 使用 Deployment 自动分配IP, replicas 副本数必须是1,多个Pod会存在IP冲突问题,如下:

$ kubectl describe pod fixed-deploy-ip-6fcf56c75b-cgksd
Name:             fixed-deploy-ip-6fcf56c75b-cgksd
Namespace:        default
Priority:         0
Service Account:  default
Node:             k8s-node01/10.20.1.140
Start Time:       Mon, 28 Jul 2025 10:59:27 +0800
Labels:           app=fixed-deploy
                  pod-template-hash=6fcf56c75b
Annotations:      cni.projectcalico.org/ipAddrs: ["171.20.42.65"]
                  cni.projectcalico.org/podIP: 
                  cni.projectcalico.org/podIPs: 
Status:           Pending
IP:               
IPs:              <none>
Controlled By:    ReplicaSet/fixed-deploy-ip-6fcf56c75b
Containers:
  nginx:
    Container ID:   
    Image:          nginx:1.29.0
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-dd6zw (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   False 
  Initialized                 True 
  Ready                       False 
  ContainersReady             False 
  PodScheduled                True 
Volumes:
  kube-api-access-dd6zw:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason                  Age               From               Message
  ----     ------                  ----              ----               -------
  Normal   Scheduled               28s               default-scheduler  Successfully assigned default/fixed-deploy-ip-6fcf56c75b-cgksd to k8s-node01
  Warning  FailedCreatePodSandBox  24s               kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "f1b3f4fc77eeca1672a1ddd935bdbda2d7a1dbd237a5be89b7422a56a315dc0a" network for pod "fixed-deploy-ip-6fcf56c75b-cgksd": networkPlugin cni failed to set up pod "fixed-deploy-ip-6fcf56c75b-cgksd_default" network: plugin type="calico" failed (add): error getting IP from IPAM: resource already exists: 171.20.42.65
  Warning  FailedCreatePodSandBox  20s               kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "bf2d21340a820b55b1f202d2f89f68d42523859dacd1e1c9a5d757e814fc34b4" network for pod "fixed-deploy-ip-6fcf56c75b-cgksd": networkPlugin cni failed to set up pod "fixed-deploy-ip-6fcf56c75b-cgksd_default" network: plugin type="calico" failed (add): error getting IP from IPAM: resource already exists: 171.20.42.65
  Warning  FailedCreatePodSandBox  16s               kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "230660cce4caaf260bfb2079479d8885aa19059441759246db3ef8ac5f93ba6c" network for pod "fixed-deploy-ip-6fcf56c75b-cgksd": networkPlugin cni failed to set up pod "fixed-deploy-ip-6fcf56c75b-cgksd_default" network: plugin type="calico" failed (add): error getting IP from IPAM: resource already exists: 171.20.42.65
  Warning  FailedCreatePodSandBox  11s               kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "7b28648e2799adc7c5e73f5038279586ac36226f157349ae8054b0048953f41c" network for pod "fixed-deploy-ip-6fcf56c75b-cgksd": networkPlugin cni failed to set up pod "fixed-deploy-ip-6fcf56c75b-cgksd_default" network: plugin type="calico" failed (add): error getting IP from IPAM: resource already exists: 171.20.42.65
  Warning  FailedCreatePodSandBox  5s                kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "2eed3030e3bfecbc5668a1621454a26dfd67688c5d152e638c86b58baa66b826" network for pod "fixed-deploy-ip-6fcf56c75b-cgksd": networkPlugin cni failed to set up pod "fixed-deploy-ip-6fcf56c75b-cgksd_default" network: plugin type="calico" failed (add): error getting IP from IPAM: resource already exists: 171.20.42.65

5. 手动释放IP

在使用过程中可能会遇到 IP 没有释放等问题导致 pod 启动失败,导致这种原因可能是 pod 被删除后,使用的 IP 地址未被释放,所以需要使用以下命令对地址池的 IP 进行释放,才能够被 pod 重新使用

$ calicoctl ipam release --ip 171.20.42.65

参考链接

https://blog.csdn.net/weixin_48711696/article/details/136049633?csdn_share_tail=%7B%22type%22:%22blog%22,%22rType%22:%22article%22,%22rId%22:%22136049633%22,%22source%22:%22weixin_48711696%22%7D

https://blog.csdn.net/weixin_48711696/article/details/135749305

https://www.cnblogs.com/chuanzhang053/p/17584488.html


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com