Calico quickstart guide
This quickstart guide shows you how to install Calico, secure a cluster with network policy, and monitor network traffic with Calico Whisker.
Before you beginβ
You'll need to install a few tools to complete this tutorial:
kind
. This is what you'll use to create a cluster on your workstation. For installation instructions, see thekind
documentation.- Docker Engine or Docker Desktop.
This is required to run containers for the
kind
utility. For installation instructions, see the Docker documentation. kubectl
. This is the tool you'll use to interact with your cluster. For installation instructions, see the Kubernetes documentation
Step 1: Create a clusterβ
In this step, you will:
- Create a cluster: Use
kind
to create a Kubernetes cluster. - Verify the cluster: Check that the cluster is running and ready.
-
Create a file called
config.yaml
and give it the following content:kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
networking:
disableDefaultCNI: true
podSubnet: 192.168.0.0/16This configuration file tells
kind
to create a cluster with one control-plane node and two worker nodes. It instructskind
to create the cluster without a CNI. ThepodSubnet
range defines the IP addresses that Kubernetes will use for pods. -
Start your Kubernetes cluster with the configuration file by running the following command:
kind create cluster --name=calico-cluster --config=config.yaml
kind
reads your configuration file and creates a cluster in a few minutes.Expected outputCreating cluster "calico-cluster" ...
β Ensuring node image (kindest/node:v1.29.2) πΌ
β Preparing nodes π¦ π¦ π¦
β Writing configuration π
β Starting control-plane πΉοΈ
β Installing StorageClass πΎ
β Joining worker nodes π
Set kubectl context to "kind-calico-cluster"
You can now use your cluster with:
kubectl cluster-info --context kind-calico-cluster
Thanks for using kind! π -
To verify that your cluster is working, run the following command:
kubectl get nodes
You should see three nodes with the name you gave the cluster.
Expected outputNAME STATUS ROLES AGE VERSION
calico-cluster-control-plane NotReady control-plane 5m46s v1.29.2
calico-cluster-worker NotReady <none> 5m23s v1.29.2
calico-cluster-worker2 NotReady <none> 5m22s v1.29.2Don't wait for the nodes to get a
Ready
status. They remain in aNotReady
status until you configure networking in the next step.
Step 2. Install Calicoβ
In this step, you will install Calico in your cluster.
-
Install the Tigera operator and custom resource definitions.
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/tigera-operator.yaml
Expected outputnamespace/tigera-operator created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator-secrets created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
rolebinding.rbac.authorization.k8s.io/tigera-operator-secrets created
deployment.apps/tigera-operator created -
Install Calico by creating the necessary custom resources.
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.0/manifests/custom-resources.yaml
Expected outputinstallation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created
goldmane.operator.tigera.io/default created
whisker.operator.tigera.io/default created -
Monitor the deployment by running the following command:
watch kubectl get tigerastatus
After a few minutes, all the Calico components display
True
in theAVAILABLE
column.Expected outputNAME AVAILABLE PROGRESSING DEGRADED SINCE
apiserver True False False 4m9s
calico True False False 3m29s
goldmane True False False 3m39s
ippools True False False 6m4s
whisker True False False 3m19s
Step 3. Monitor network traffic in Calico Whiskerβ
The Whisker web console deploys automatically, but it is not accessible from outside the cluster by default. To view the web console, you need to allow access.
In this step, you will:
- Set up port forwarding: This allows you to access the Whisker web console from your browser.
- Open the Whisker web console: View the network traffic logs in real time.
-
From your terminal, run the following command:
kubectl port-forward -n calico-system service/whisker 8081:8081
Expected outputForwarding from 127.0.0.1:8081 -> 8081
Forwarding from [::1]:8081 -> 8081Keep this terminal open throughout the rest of this tutorial. The Whisker web console needs the port forwarding to be active to receive logs.
-
To open Calico Whisker, open your browser and go to
localhost:8081
. You won't see any flows at the beginning. But in a few moments, as the console receives flow logs, you'll begin to see a list of connections.Figure 1: Whisker web console with allowed flows for core Kubernetes services.
The web console accumulates flow logs in real time. Keep this window open through the rest of the tutorial to see logs of the connections your pods are making.
Step 4. Deploy NGINX and BusyBox to generate trafficβ
Now it's time to generate some network traffic. We'll do this first by deploying an NGINX server and exposing it as a service in the cluster. Then we'll make HTTP requests from another pod in the cluster to the NGINX server and to an external website. For this we'll use the BusyBox utility.
In this step, you will:
- Create a server: Deploy an NGINX web server in your Kubernetes cluster.
- Expose the server: Make the NGINX server accessible within the cluster.
- Test connectivity: Use a BusyBox pod to verify connections to the NGINX server and the public internet.
-
Create a namespace for your application:
kubectl create namespace quickstart
Expected outputnamespace/quickstart created
-
Deploy an NGINX web server in the
quickstart
namespace:kubectl create deployment --namespace=quickstart nginx --image=nginx
Expected outputdeployment.apps/nginx created
-
Expose the NGINX deployment to make it accessible within the cluster:
kubectl expose --namespace=quickstart deployment nginx --port=80
Expected outputservice/nginx exposed
-
Start a BusyBox session to test whether you can access the NGINX server.
kubectl run --namespace=quickstart access --rm -ti --image busybox /bin/sh
This command creates a BusyBox pod inside the
quickstart
namespace and starts a shell session inside the pod.Expected outputIf you don't see a command prompt, try pressing enter.
/ # -
In the BusyBox shell, run the following command to test communication with the NGINX server:
wget -qO- http://nginx
You should see the HTML content of the NGINX welcome page.
Expected output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>This confirms that the BusyBox pod can access the NGINX server.
-
In the Busybox shell, run the following command test communication with the public internet:
wget -qO- https://docs.tigera.io/pod-connection-test.txt
You should see the content of the file
pod-connectivity-test.txt
.Expected outputYou successfully connected to https://docs.tigera.io/pod-connection-test.txt.
This confirms that the BusyBox pod can access the public internet.
-
Return to your browser to see the connection appear in the Whisker web console. You should see three new connection types: one to
coredns
one tonginx
, and another toPUBLIC NETWORK
.Figure 2: Whisker web console showing allowed flows to NGINX server and
https://docs.tigera.io
.
Step 5. Restrict all traffic with a default deny policyβ
To effectively secure your cluster, it's best to start by denying all traffic, and then gradually allowing only the necessary traffic. We'll do this by applying a Global Calico Network Policy that denies all ingress and egress traffic by default.
In this step, you will:
- Implement a global default deny policy: Use a Global Calico Network Policy to deny all ingress and egress traffic by default.
- Verify access is denied: Use your BusyBox pod to confirm that the policy is working as expected.
-
Create a Global Calico Network Policy to deny all traffic except for the necessary system namespaces:
kubectl create -f - <<EOF
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-deny
spec:
selector: projectcalico.org/namespace not in {'kube-system', 'calico-system', 'calico-apiserver'}
types:
- Ingress
- Egress
EOFExpected outputglobalnetworkpolicy.projectcalico.org/default-deny created
-
Now go back to your BusyBox shell and test access to the NGINX server again:
wget -qO- http://nginx
You should see the following output, indicating that access is denied:
Expected outputwget: bad address 'nginx'
-
Test access to the public internet again:
wget -qO- https://docs.tigera.io/pod-connection-test.txt
You should see the following output, indicating that egress traffic is also denied:
Expected outputwget: bad address 'docs.tigera.io'
-
Return to your browser to see the denied flow logs appear in the Whisker web console. You should see two denied flows to
coredns
.Figure 3: Whisker web console showing denied flows to NGINX server and
https://docs.tigera.io
.By following these steps, you have successfully implemented a global default deny policy and verified that it is working as expected.
Step 6. Create targeted network policy for allowed trafficβ
Now that you have a default deny policy in place, you need to create specific policies to allow only the necessary traffic for your applications to function.
The default-deny
policy blocks all ingress and egress traffic for pods not in system namespaces, including our access
(BusyBox) and nginx
pods in the quickstart
namespace.
In this step, you will:
- Allow egress traffic from BusyBox Create a network policy to allow egress traffic from the BusyBox pod to the public internet.
- Allow ingress traffic to NGINX Create a network policy to allow ingress traffic to the NGINX server.
-
Create a Calico network policy in the
quickstart
namespace that selects theaccess
pod and allows all egress traffic from it.kubectl create -f - <<EOF
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-busybox-egress
namespace: quickstart
spec:
selector: run == 'access'
types:
- Egress
egress:
- action: Allow
EOFExpected outputnetworkpolicy.projectcalico.org/allow-busybox-egress created
-
Back in the BusyBox shell, test access to the public internet again. Because egress traffic is now allowed from this pod, this should succeed:
wget -qO- https://docs.tigera.io/pod-connection-test.txt
Expected outputYou successfully connected to https://docs.tigera.io/pod-connection-test.txt.
-
Test access to the NGINX server again. Egress from the
access
pod is allowed by the new policy, but ingress to thenginx
pod is still blocked by thedefault-deny
policy. This request should fail.wget -qO- http://nginx
Expected outputwget: bad address 'nginx'
-
Create another Calico network policy in the
quickstart
namespace. This policy selects thenginx
pods (using the labelapp=nginx
) and allows ingress traffic specifically from pods with the labelrun=access
.kubectl create -f - <<EOF
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-nginx-ingress
namespace: quickstart
spec:
selector: app == 'nginx'
types:
- Ingress
ingress:
- action: Allow
source:
selector: run == 'access'
EOFExpected outputnetworkpolicy.org/allow-nginx-ingress created
-
Test access to the NGINX server again. From the BusyBox shell, test access to the NGINX server one more time:
wget -qO- http://nginx
Now that both egress from
access
and ingress tonginx
(fromaccess
) are allowed, the connection should succeed. You'll see the NGINX welcome page:Expected output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
You have now successfully implemented a default deny policy and then created targeted allow policies to restore connectivity only for your applications.
Step 7. Clean upβ
-
To remove the
kind
cluster, run the following command:kind delete cluster --name calico-cluster
Expected outputDeleting cluster "calico-cluster" ...
Deleted nodes: ["calico-cluster-control-plane" "calico-cluster-worker2" "calico-cluster-worker"]
Additional resourcesβ
- Want to dive deeper? Explore this free, interactive workshop to learn Calico basics, Kubernetes observability with Whisker, and moreβright in your browser.