-2

As a part of the Kubernetes Resource Definition, I want to whitelist certain IPs. The list of IPs can be found by

$ kubectl get nodes -o wide --no-headers | awk '{print $7}'
#This prints something like
51.52.215.214
18.170.74.10
.....

Now, In the Kubernetes deployment file (say deployment.yaml) I want to loop over these values and whitelist them. I know that we can whitelist by adding under loadBalancerSourceRanges like

#part of the deployment.yaml
loadBalancerSourceRanges
 - 51.52.112.111
 - 18.159.75.11

I want to update the above loadBalancerSourceRanges to include the output of $ kubectl get nodes -o wide --no-headers | awk '{print $7}'

How do I go about it? Instead of hardcoding the host IPs, I would like to programatically include via bash or ansible or any other cleaner way possible.

Thanks in advance, JE

java_enthu
  • 2,279
  • 7
  • 44
  • 74
  • Please add more details, the full `deployment` file could be usefull. Using a tool like [tag:yq] this can't be that hard. – 0stone0 Jan 31 '22 at 16:35
  • @java_enthu Already provided 3 answers. Are any of them useful? Consider accepting the answer (https://stackoverflow.com/help/accepted-answer) if it solves your issue. – Andrew Skorkin Feb 01 '22 at 09:10
  • @AndrewSkorkin appreciate your "gentle reminder" :-) . – java_enthu Feb 01 '22 at 10:15

3 Answers3

2

loadBalancerSourceRanges should be a part of Service, not Deployment

You can use the following oneliner to patch your service dynamically:

kubectl patch service YOUR_SERVICE_NAME -p "{\"spec\":{\"loadBalancerSourceRanges\": [$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="InternalIP")]}"{.address}/32",{end}' | sed 's/,*$//g')]}}"

, where you should replace YOUR_SERVICE_NAME with actual service name

To explain what's going on here:

We are using kubectl patch to patch existing resource, in our case - spec.loadBalancerSourceRanges.

  • we are putting our subshell inside [$(..)], since loadBalancerSourceRanges requires array of strings
  • kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="InternalIP")]}"{.address}/32",{end}' - gets InternalIPs from your nodes, adds /32 to each of them, since loadBalancerSourceRanges requires ranges, encloses each range in " and then places coma between each value.
  • sed 's/,*$//g' - removes a trailing comma

Using jsonpath is better thatn awk/cut because we are not dependent on kubectl column ordering and get only relevant for us information from API.

I agree with @Kaffe Myers that you should try using kustomize or helm or other templating engines, since they should be a better suited for this job.

Andrew
  • 3,912
  • 17
  • 28
1

You can use yq

# empty array if necessary
yq -i '.loadBalancerSourceRanges = []' file.yaml

# In my env (AWS EKS) the IP is field 6 (change if needed)
for host in $(kubectl get nodes -o wide --no-headers | awk '{print $6}')
do
  yq -i '.loadBalancerSourceRanges += ["'${host}'"]' file.yaml
done
  1. The -i parameter is to apply the change to the file (like sed)

  2. If "loadBalancerSourceRanges" is inside "config", you can use: ".config.loadBalancerSourceRanges"

Juranir Santos
  • 370
  • 2
  • 6
0

This is a very use-specific thingy, and you might be better off researching kustomize. That being said, you could make a temporary file which you alter before deploy.

cp deployment.yaml temp.yaml
kubectl get nodes -o wide --no-headers |
    awk '{print $7}' |
    xargs -I{} sed -Ei "s/^(\s+)(loadBalancerSourceRanges:)/\1\2\n\1  - {}/" temp.yaml

kubectl apply -f temp.yaml

It looks for the loadBalancerSourceRanges: part of the yaml, which on the "template" shouldn't have any values, then populate it with whatever kubectl get nodes -o wide --no-headers | awk '{print $7}' feeds it with.

Kaffe Myers
  • 424
  • 3
  • 9