How to patch container env variable in deployment with kubectl? - json

When I want to exctract the current value of some container env variabe I could use jsonpath with syntax like:
kubectl get pods -l component='somelabel' -n somenamespace -o \
jsonpath='{.items[*].spec.containers[*].env[?(#.name=="SOME_ENV_VARIABLE")].value}')
That will return me the value of env varialbe with the name SOME_ENV_VARIABLE. Pod section with container env variables in json will look like this:
"spec": {
"containers": [
{
"env": [
{
"name": "SOME_ENV_VARIABLE",
"value": "some_value"
},
{
"name": "ANOTHER_ENV_VARIABLE",
"value": "another_value"
}
],
When I want to patch some value in my deployment I'm using commands with syntax like:
kubectl -n kube-system patch svc kubernetes-dashboard --type='json' -p="[{'op': 'replace', 'path': '/spec/ports/0/nodePort', 'value': $PORT}]"
But how can I patch a variable with 'op': 'replace' in cases where I need to use expression like env[?(#.name=="SOME_ENV_VARIABLE")]? Which syntax I should use?

Rather than kubectl patch command, you can make use of kubectl set env to update environment variable of k8s deployment.
envvalue=$(kubectl get pods -l component='somelabel' -n somenamespace -o jsonpath='{.items[*].spec.containers[*].env[?(#.name=="SOME_ENV_VARIABLE")].value}')
kubectl set env deployment/my-app-deploy op=$envvalue
Hope this helps.

Most of them haven't provide proper commands just use as simple as it is =>
kubectl set env deployment/deploy_name APP_VERSION=value -n namespace

op: replace
path: /spec/template/spec/containers/0/env/0/name
value: YOUR_VARIABLE_NAME
op: replace
path: /spec/template/spec/containers/0/env/0/value
value: YOUR_VARIABLE_VALUE

Related

Get ca-cert.pem field of a kubernetes secret

In my istio-system namespace, I have the following secret
▶ k get secret istio-ca-secret -o yaml
apiVersion: v1
data:
ca-cert.pem: LS0tLS1CR...
ca-key.pem: LS0..
cert-chain.pem: ""
key.pem: ""
root-cert.pem: ""
While the following query works:
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data}"
{"ca-cert.pem":"LS0t=...","ca-key.pem":"LS0tLS1","cert-chain.pem":"","key.pem":"","root-cert.pem":""}%
the following, which I execute trying to get only the ca-cert.pem value returns nothing
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data.ca-cert.pem}"
why is that?
you need to escape the dot in "ca-cert.pem" to work.
like this
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data.ca-cert\.pem}"

How do I convert this JSON code into YAML?

I am currently studying AWS. I'm creating a CloudFormation Template. And I'm stuck with this problem.
I need to convert this JSON code below into YAML and add it to a template.
And the converters in google say
"Unexpected Token : In JSON At Position 10".
"Fn::Join": [
"\n",
[
"#!/bin/bash",
"yum -y update",
"echo 1 > /proc/sys/net/ipv4/ip_forward",
"echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects",
"/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j
MASQUERADE",
"/sbin/iptables-save > /etc/sysconfig/iptables",
"mkdir -p /etc/sysctl.d/",
"cat <<EOF > /etc/sysctl.d/nat.conf",
"net.ipv4.ip_forward = 1",
"net.ipv4.conf.eth0.send_redirects = 0",
"EOF \n"
]
]
I need to then add it to this YAML code below.
NatInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: !Ref AmazonLinuxAMIID
SubnetId: !Ref PublicSubnet1
SecurityGroupIds:
- !Ref AppSecurityGroup
IamInstanceProfile: !Ref InstanceProfile
Tags:
- Key: Name
Value: NAT Instance

How can I resolve the "error decoding from json: illegal base64 data at input byte 0" for Kubernetes secrets?

I currently am working on adding a new secret for our project which usually stores secrets in Kubernetes. I pretty much mimicked all the other secrets that I could find, so it would seem that everything should be correct. However, it's not working and giving me for: "kubernetes/template/secrets.yml": error decoding from json: illegal base64 data at input byte 0. I'm not sure if this is an issue from within Kubernetes or from my script.
The secrets file looks something like this:
secrets.yml
apiVersion: v1
kind: Secret
metadata:
…
type: Opaque
data:
SECRET_A: {SECRET_A}
SECRET_B: {SECRET_B}
deployk8.sh
set -e
sed -i "s,{SECRET_A},${SECRET_A},g" kubernetes/template/secrets.yml
sed -i "s,{SECRET_B},${SECRET_B},g" kubernetes/template/secrets.yml # The new one
kubectl --record --namespace=${...} --token ${...} --cluster ${...} apply -f kubernetes/template/secrets.yml
When I run kubectl get secret my-secret -o json, I get something similar to this:
{
"apiVersion": "v1",
"data": {
"SECRET_A": "abcdefghijklmnopqrstuvwxyz123456",
"SECRET_B": "abcdefghijklmnopqrstuvwxyz1234567890abcd"
},
"kind": "Secret",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"SECRET_A\":\"abcdefghijklmnopqrstuvwxyz123456\"},\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/change-cause\":\"kubectl apply --record=true --namespace=ns --token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --cluster=my_cluster --filename=kubernetes/template/secrets.yml\"},\"labels\":{\"app\":\"my-app\",\"env\":\"dev\"},\"name\":\"my-app-dev\",\"namespace\":\"ns\"},\"type\":\"Opaque\"}\n",
"kubernetes.io/change-cause": "kubectl apply --record=true --namespace=ns --token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx--cluster=my_cluster --filename=kubernetes/template/secrets.yml"
},
"creationTimestamp": "20XX-XX-XXTXX:XX:XXZ",
"labels": {
"app": "my-app",
"env": "dev"
},
"name": "my-app-dev",
"namespace": "ns",
"resourceVersion": "0000000000",
"selfLink": "/api/v1/namespaces/ns/secrets/my-app-dev",
"uid": "00000000-0000-0000-0000-000000000000"
},
"type": "Opaque"
}
The entire error looks something like this:
kubectl --record --namespace=${...} --token ${...} --cluster ${...} apply -f
kubernetes/template/secrets.yml
Error from server: error when applying patch:
[inset output from above, but with:
{\"SECRET_A\":\"abcdefghijklmnopqrstuvwxyz123456\",\"SECRET_B\":\"$SECRET_B\"}]
to:
[transformed output from above, but with:
Object: &{map["apiVersion":"v1" "data":map["SECRET_A":"abcdefghijklmnopqrstuvwxyz123456\" "SECRET_B":"abcdefghijklmnopqrstuvwxyz1234567890abcd"]]
I would really appreciate any help in figuring this out!
I think I found a resolution to my issue. It turns out that my environmental variable that I was pulling from that changed (i.e. SECRET_B should have been just been B). So, technically, SECRET_B didn't exist. Changing this managed to fix my issue. Thank you to everyone who tried to help!
You could use the stringData field like described here. That way you do not have to base64 the input. Note the field is write-only.

Openshift - Correlation between confimap and pods

there's a quick way/oc command to get which deployement use one or more configmap ?
In my case, I need to know which deployment I need to rollout to apply configmap update.
No evidence on dc YAML file.
Thanks in advance!
From guide in OpenShift 3.9
In DeploymentConfig this is the Stanza to pull all environment variables from a ConfigMap.
spec:
containers:
...
envFrom:
- configMapRef:
name: env-config
...
In might be worth grepping all your deploymentConfigs for the keyword configMap in a particular namespace/project to check you've got configMaps attached
$ oc get dc -o json -n $(oc project -q) | grep -A2 configMap
"configMapRef": {
"name": "printenv-config"
}
Assuming injecting environment variables from configmaps, there might be an easier way of doing this? - but you could also pipe into jq and filter based on the envFrom array key being not null
oc get dc -o json | jq -r '[.items[] | select(.spec.template.spec.containers[].envFrom[]? != null)]' | jq -c '.[] | {namespace: .metadata.namespace, dcname: .metadata.name, configMap: .spec.template.spec.containers[].envFrom[].configMapRef.name}'
Results in:
{"namespace":"aps-env","dcname":"openshift-tasks","configMap":"another-config-map"}
{"namespace":"aps-env","dcname":"printenv","configMap":"printenv-config"}
Alternatively you might be mounting your configMap via a volume mount, in which case the Stanza is different, and you'd need to adjust the above accordingly
"volumes": [
...
{
"configMap": {
"defaultMode": 420,
"name": "gogs"
},
"name": "config-volume"
}
...
Different Query based on Volume mounted configMap
$ oc get dc -o json | jq -r '[.items[] | select(.spec.template.spec.volumes[]?.configMap != null)]' | jq -c '.[] | {dcname: .metadata.name, configMapName: .spec.template.spec.volumes[].configMap.name}' | grep -v null
Results in:
{"dcname":"gogs","configMapName":"gogs-configmap"}

Openshift templates with array parameters

I am trying to create an Openshift template for a Job that passes the job's command line arguments in a template parameter using the following template:
apiVersion: v1
kind: Template
metadata:
name: test-template
objects:
- apiVersion: batch/v2alpha1
kind: Job
metadata:
name: "${JOB_NAME}"
spec:
parallelism: 1
completions: 1
autoSelector: true
template:
metadata:
name: "${JOB_NAME}"
spec:
containers:
- name: "app"
image: "batch-poc/sample-job:latest"
args: "${{JOB_ARGS}}"
parameters:
- name: JOB_NAME
description: "Job Name"
required: true
- name: JOB_ARGS
description: "Job command line parameters"
Because the 'args' need to be an array, I am trying to set the template parameter using JSON syntax, e.g. from the command line:
oc process -o=yaml test-template -v=JOB_NAME=myjob,JOB_ARGS='["A","B"]'
or programmatically through the Spring Cloud Launcher OpenShift Client:
OpenShiftClient client;
Map<String,String> templateParameters = new HashMap<String,String>();
templateParameters.put("JOB_NAME", jobId);
templateParameters.put("JOB_ARGS", "[ \"A\", \"B\", \"C\" ]");
KubernetesList processed = client.templates()
.inNamespace(client.getNamespace())
.withName("test-template")
.process(templateParameters);
In both cases, it seems to fail because Openshift is interpreting the comma after the first array element as a delimiter and not parsing the remainder of the string.
The oc process command sets the parameter value to '["A"' and reports an error: "invalid parameter assignment in "test-template": "\"B\"]"".
The Java version throws an exception:
Error executing: GET at: https://kubernetes.default.svc/oapi/v1/namespaces/batch-poc/templates/test-template. Cause: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token\n at [Source: N/A; line: -1, column: -1] (through reference chain: io.fabric8.openshift.api.model.Template[\"objects\"]->java.util.ArrayList[0]->io.fabric8.kubernetes.api.model.Job[\"spec\"]->io.fabric8.kubernetes.api.model.JobSpec[\"template\"]->io.fabric8.kubernetes.api.model.PodTemplateSpec[\"spec\"]->io.fabric8.kubernetes.api.model.PodSpec[\"containers\"]->java.util.ArrayList[0]->io.fabric8.kubernetes.api.model.Container[\"args\"])
I believe this is due to a known Openshift issue.
I was wondering if anyone has a workaround or an alternative way of setting the job's parameters?
Interestingly, if I go to the OpenShift web console, click 'Add to Project' and choose test-template, it prompts me to enter a value for the JOB_ARGS parameter. If I enter a literal JSON array there, it works, so I figure there must be a way to do this programmatically.
We worked out how to do it; template snippet:
spec:
securityContext:
supplementalGroups: "${{SUPPLEMENTAL_GROUPS}}"
parameters:
- description: Supplemental linux groups
name: SUPPLEMENTAL_GROUPS
value: "[14051, 14052, 48, 65533, 9050]"
In our case we have 3 files :
- environment configuration,
- template yaml
- sh file which run oc process.
And working case looks like this :
environment file :
#-- CORS ---------------------------------------------------------
cors_origins='["*"]'
cors_acceptable_headers='["*","Authorization"]'
template yaml :
- apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: plugin-common-cors
annotations:
kubernetes.io/ingress.class: ${ingress_class}
config:
origins: "${{origins}}"
headers: "${{acceptable_headers}}"
credentials: true
max_age: 3600
plugin: cors
sh file running oc :
if [ -f templates/kong-plugins-template.yaml ]; then
echo "++ Applying Global Plugin Template ..."
oc process -f templates/kong-plugins-template.yaml \
-p ingress_class="${kong_ingress_class}" \
-p origins=${cors_origins} \
-p acceptable_headers=${cors_acceptable_headers} \
-p request_per_second=${kong_throttling_request_per_second:-100} \
-p request_per_minute=${kong_throttling_request_per_minute:-2000} \
-p rate_limit_by="${kong_throttling_limit_by:-ip}" \
-o yaml \
> yaml.tmp && \
cat yaml.tmp | oc $param_mode -f -
[ $? -ne 0 ] && [ "$param_mode" != "delete" ] && exit 1
rm -f *.tmp
fi
The sh file should read environment file.