How to automaticaly add Cloud Firewall to every Linode in LKE cluster?
Is there a way to automatically add Linodes Cloud Firewall to all Linodes? Either when manually changing the size of the cluster or when Cluster Autoscaling is used.
1 Reply
✓ Best Answer
I've tried to automate this by using a container with linode-cli on it that would run once when a new node gets added and so far I got this working to add 1 linode to the firewall:
export FIREWALL_ID=$(linode-cli --text --no-headers firewalls list --label k8s | cut -f1)
export CLUSTER_ID=$(linode-cli --text --no-headers lke clusters-list --tags test | cut -f1)
export LINODE_ID=$(linode-cli --text --no-headers lke pools-list $CLUSTER_ID | cut -f4)
linode-cli firewalls device-create --id $LINODE_ID --type linode $FIREWALL_ID
Now to handle multiple nodes …
For now this should work:
export FIREWALL_ID=$(linode-cli --text --no-headers firewalls list --label k8s | cut -f1)
export CLUSTER_ID=$(linode-cli --text --no-headers lke clusters-list --tags test | cut -f1)
export NODES=$(linode-cli --text --no-headers lke pools-list $CLUSTER_ID)
for LINODE_ID in $NODES; do linode-cli firewalls device-create --id $(echo $LINODE_ID | cut -f4) --type linode $FIREWALL_ID; done
Final version with cronjob that runs every minute. I'm using my own docker image khartahk/linode-cli:latest
based on this Dockerfile
FROM alpine:latest
RUN apk add --no-cache python3 py3-pip
RUN pip install linode-cli
CMD /bin/sh -c "echo 'Python3, py3-pip and linode-cli ready.'"
QUESTION
Perhaps a better approach would be to create an operator that on some event node up
or something runs a job?
I've also cleaned up the linode-cli
usage a bit and used --format ID
flag to get the correct fields instead of relying on piping to cut -f1
.
IMPORTANT
Token in the secret
named linode
in kube-system
does NOT have access to the firewall. That is why I added a new token in a new secret which has access to manipulate the firewall. Took me quite some time to figure that out. Perhaps it's mentioned in Linodes documentation for LKE?
---
apiVersion: v1
kind: Secret
metadata:
name: linode-cli-config-secret
namespace: kube-system
type: Opaque
stringData:
linode-cli: |-
[DEFAULT]
default-user = user
[user]
token = ${LINODE_CLI_TOKEN} # change this
region = eu-central
type = g6-nanode-1
image = linode/ubuntu22.04
---
apiVersion: v1
kind: ConfigMap
metadata:
name: linode-data
namespace: kube-system
data:
linode-firewall: |-
#! /usr/bin/env sh
export FIREWALL_ID=$(linode-cli --text --no-headers --format id firewalls list --label k8s)
export CLUSTER_ID=$(linode-cli --text --no-headers --format id lke clusters-list --tags test)
export NODES=$(linode-cli --text --no-headers --format instance_id lke pools-list $CLUSTER_ID)
IFSold=$IFS
IFS=$'\n'
for LINODE_ID in $NODES; do
linode-cli firewalls device-create --id $(echo $LINODE_ID) --type linode $FIREWALL_ID;
done
IFS=$IFSold
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: linode-cli
namespace: kube-system
labels:
k8s-app: linode-cli
spec:
concurrencyPolicy: Forbid
failedJobsHistoryLimit: 3
schedule: "* * * * *"
successfulJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
restartPolicy: Never
containers:
- name: linode-cli
image: "khartahk/linode-cli:latest"
command: [ "/bin/sh" ]
args: [
"-cx",
"--",
"/scripts/linode-firewall.sh"
]
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- mountPath: "/scripts"
name: linode-firewall-sh
readOnly: true
- mountPath: "/.config"
name: linode-cli-config-secret
readOnly: true
volumes:
- name: linode-firewall-sh
configMap:
name: linode-data
defaultMode: 0777
items:
- key: "linode-firewall"
path: "linode-firewall.sh"
- name: linode-cli-config-secret
secret:
secretName: linode-cli-config-secret