✓ Solved

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

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct