Home > Back-end >  Adding values in a YAML file via loop
Adding values in a YAML file via loop

Time:02-01

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

CodePudding user response:

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.

CodePudding user response:

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.

CodePudding user response:

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"

  •  Tags:  
  • Related