Calico 是一个高性能的网络和网络安全解决方案,用于 Kubernetes 和其他容器平台。calicoctl
是 Calico 提供的命令行工具,允许用户管理和配置 Calico 的网络资源。
您可以从 Calico 官方网站下载 calicoctl
。以下是一个示例脚本,可以在 Linux 和 macOS 上下载 calicoctl
:
# 下载 calicoctl
curl -o calicoctl -O -L https://github.com/projectcalico/calico/releases/download/v3.28.0/calicoctl-linux-amd64
# 添加执行权限
chmod +x calicoctl
# 将 calicoctl 移动到您的 PATH 中的目录,例如 /usr/local/bin
sudo mv calicoctl /usr/local/bin/
# 验证安装
root@master1:~# calicoctl version
Client Version: v3.28.0
Git commit: 413e6f559
Cluster Version: v3.28.0
Cluster Type: typha,kdd,k8s,operator,bgp,kubeadm
对于 Windows 用户,可以使用 PowerShell 进行下载:
Invoke-WebRequest -Uri https://github.com/projectcalico/calico/releases/download/v3.25.0/calicoctl-windows-amd64.exe -OutFile calicoctl.exe
# 将 calicoctl.exe 移动到您的 PATH 中的目录,例如 C:\Windows\System32
Move-Item calicoctl.exe C:\Windows\System32\
在使用 calicoctl
之前,需要将其配置为连接到 etcd 或 Kubernetes API 服务器。通过命令行配置运行:
DATASTORE_TYPE=kubernetes KUBECONFIG=~/.kube/config calicoctl get nodes
以下是一个连接到 Kubernetes API 服务器为例,创建一个配置文件,例如 calicoctl.cfg
:
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
datastoreType: "kubernetes"
kubeconfig: "/etc/kubernetes/admin.conf"
然后可以使用以下命令将配置文件路径导入环境变量:
export CALICOCTL_CFG=/path/to/calicoctl.cfg
除了自定义配置文件路径外,calicoctl默认加载 /etc/calico/calicoctl.cfg
配置文件读取配置信息,也可以将上述配置文件放到该路径下。
以下是一些常用的 calicoctl
命令:
calicoctl get nodes
cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: my-ippool
spec:
cidr: 172.16.0.0/12
ipipMode: Always
natOutgoing: true
EOF
calicoctl get ippools
# yaml格式输出
calicoctl get ipPool -o yaml
calicoctl delete ippool my-ippool
cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-tcp-and-udp
spec:
selector: all()
ingress:
- action: Allow
protocol: TCP
source:
nets:
- 192.168.0.0/16
- action: Allow
protocol: UDP
source:
nets:
- 192.168.0.0/16
egress:
- action: Allow
protocol: TCP
- action: Allow
protocol: UDP
EOF
calicoctl get globalnetworkpolicies
calicoctl delete globalnetworkpolicy allow-tcp-and-udp
使用busybox创建2个pod:
# yaml文件
root@master1:~/ingress-nginx# cat busybox-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox-deployment
spec:
replicas: 2
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "while true; do echo Hello Kubernetes!; sleep 3600; done"]
resources:
limits:
cpu: "100m"
memory: "128Mi"
requests:
cpu: "50m"
memory: "64Mi"
root@master1:~# kubectl create -f busybox-deploy.yaml
root@master1:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-deployment-6fc58dd5f-5wjqk 1/1 Running 0 6m20s 10.244.44.9 node2 <none> <none>
busybox-deployment-6fc58dd5f-nzmsg 1/1 Running 0 6m20s 10.244.154.10 node1 <none> <none>
# 此时两个pod之间可以互相ping通
root@master1:~/ingress-nginx# kubectl exec -it busybox-deployment-6fc58dd5f-5wjqk sh
/ # ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue qlen 1000
link/ether ee:a9:3a:3c:9c:51 brd ff:ff:ff:ff:ff:ff
inet 10.244.44.9/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::eca9:3aff:fe3c:9c51/64 scope link
valid_lft forever preferred_lft forever
/ # ping 10.244.154.10
PING 10.244.154.10 (10.244.154.10): 56 data bytes
64 bytes from 10.244.154.10: seq=0 ttl=62 time=1.607 ms
64 bytes from 10.244.154.10: seq=1 ttl=62 time=1.016 ms
创建全局网络策略,阻断入方向源地址为10.244.44.9的icmp流量:
root@master1:~# cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: icmp-deny
spec:
selector: all()
ingress:
- action: Deny
protocol: ICMP
source:
nets:
- 10.244.44.9/32
egress:
- action: Allow
protocol: TCP
- action: Allow
protocol: UDP
EOF
Successfully applied 1 'GlobalNetworkPolicy' resource(s)
root@master1:~# calicoctl get globalnetworkpolicies
NAME
icmp-deny
# 再次测试ping已阻断
/ # ping 10.244.154.10
PING 10.244.154.10 (10.244.154.10): 56 data bytes
^C
--- 10.244.154.10 ping statistics ---
29 packets transmitted, 0 packets received, 100% packet loss
# 删除策略后,ping恢复
root@master1:~# calicoctl delete globalnetworkpolicies icmp-deny
Successfully deleted 1 'GlobalNetworkPolicy' resource(s)
cat <<EOF | calicoctl apply -f -
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: default
spec:
selector: all()
ingress:
- action: Allow
source:
selector: app == 'frontend'
EOF
calicoctl get networkpolicies -n default
calicoctl delete networkpolicy allow-ingress -n default
为了测试 allow-ingress
网络策略,您可以创建几个示例资源,包括一个前端应用(frontend
)和一个后端应用(backend
)。allow-ingress
网络策略将允许 frontend
应用访问 backend
应用。以下是完整的资源 YAML 配置文件,包括两个 Deployment 和一个 Service 以及网络策略。
Deployment 和 Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: busybox
command: ["sh", "-c", "while true; do echo frontend; sleep 3600; done"]
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 8080
Deployment 和 Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: busybox
command: ["sh", "-c", "while true; do nc -l -p 8080 -e echo backend; done"]
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 8080
targetPort: 8080
网络策略
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: default
spec:
selector: app == 'backend'
ingress:
- action: Allow
source:
selector: app == 'frontend'
这个网络策略的目的是允许具有标签 app=frontend
的 Pod 访问具有标签 app=backend
的 Pod。其他没有标签 app=frontend
的 Pod 将无法与 backend
Pod 通信。
将这些 YAML 文件分别保存为 frontend.yaml
、backend.yaml
和 network-policy.yaml
,并使用 kubectl
命令进行部署:
kubectl apply -f frontend.yaml
kubectl apply -f backend.yaml
# 创建网络策略
calicoctl apply -f network-policy.yaml
说明:
由于Calico 的 NetworkPolicy CRD(Custom Resource Definitions)没有创建,直接使用kubectl创建会报资源不存在。此处network-policy使用calicoctl创建。
确保所有 Pod 都在运行状态:
kubectl get pods
进入 frontend
Pod 并尝试连接 backend
服务:
# 获取 frontend Pod 的名称
FRONTEND_POD=$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}')
# 进入 frontend Pod
kubectl exec -it $FRONTEND_POD -- sh
# 在 frontend Pod 内尝试连接 backend 服务
nc -zv backend 8080
如果网络策略配置正确,您应该能够在 frontend
Pod 内成功连接到 backend
服务的 8080 端口,并且可以看到 backend
的响应。
为了进一步验证网络策略,可以尝试从非 frontend
Pod 进行相同的连接测试,应该会被拒绝。例如,创建一个临时 Pod 进行测试:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
labels:
name: test-pod
spec:
containers:
- name: test-container
image: busybox
command: ["sh", "-c", "sleep 3600"]
应用这个临时 Pod 并尝试连接 backend
服务:
kubectl apply -f test-pod.yaml
# 获取 test-pod 的名称
TEST_POD=$(kubectl get pods -l name=test-pod -o jsonpath='{.items[0].metadata.name}')
# 进入 test-pod
kubectl exec -it $TEST_POD -- sh
# 在 test-pod 内尝试连接 backend 服务
nc -zv backend 8080
如果网络策略生效,test-pod
应该无法连接到 backend
服务的 8080 端口。
calicoctl node status
# 测试环境输出
root@master1:~# calicoctl node status
Calico process is running.
IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+--------------+-------------------+-------+----------+-------------+
| 192.168.0.62 | node-to-node mesh | up | 23:33:51 | Established |
| 192.168.0.63 | node-to-node mesh | up | 02:24:05 | Established |
+--------------+-------------------+-------+----------+-------------+
IPv6 BGP status
No IPv6 peers found.
calicoctl get profiles
calicoctl get hostendpoints
calicoctl get workloadendpoints
# 测试环境输出
root@master1:~# calicoctl get workloadendpoints
WORKLOAD NODE NETWORKS INTERFACE
busybox-deployment-6fc58dd5f-5wjqk node2 10.244.44.9/32 cali3a6efabcaed
busybox-deployment-6fc58dd5f-nzmsg node1 10.244.154.10/32 cali707aea5e012
my-nginx-55557d45d6-kjgdn node1 10.244.154.8/32 cali649981d3fac
my-nginx-5db89fc655-qjrr5 node1 10.244.154.7/32 calib9bdb0d79db
calicoctl
提供了丰富的命令集来管理和配置 Calico 的网络资源。熟练掌握这些命令可以帮助您更好地管理 Kubernetes 集群中的网络和安全策略。