Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use dash in environment variable names in a pod definition #16863

Closed
johanhaleby opened this issue Nov 5, 2015 · 24 comments
Closed

Cannot use dash in environment variable names in a pod definition #16863

johanhaleby opened this issue Nov 5, 2015 · 24 comments
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. priority/backlog Higher priority than priority/awaiting-more-evidence. sig/node Categorizes an issue or PR as relevant to SIG Node.

Comments

@johanhaleby
Copy link

It's not possible to define a container with an environment variable containing dash. For example:

...
containers:
        - name: my-name
          image: gcr.io/id/name:v1
          ports:
            - containerPort: 8080
          env:
            - name: SOMETHING_WITH-DASH
              value: Something
...

yields the following error:

The ReplicationController "rc-name" is invalid:spec.template.spec.containers[0].env[0].name: invalid value 'SOMETHING_WITH-DASH': must be a C identifier (matching regex [A-Za-z_][A-Za-z0-9_]*): e.g. "my_name" or "MyName"

So why is this needed?

I'm trying to deploy an existing Spring Boot Java application running inside a Docker container. Spring boot allows you to inject configuration using this approach:

@Value("${something.with-dash}")
private String mySomething;

Spring Boot allows you to externalize the configuration in various different ways. For example it maps environment variables like this:

If you use environment variables rather than system properties, most operating systems disallow period-separated key names, but you can use underscores instead (e.g. SPRING_CONFIG_NAME instead of spring.config.name).

So in this case I need to use an environment variable called SOMETHING_WITH-DASH in order for spring to pick it up and map it to something.with-dash.

This works when using tools like Docker Compose. In bash it works when you do like this:

env 'SOMETHING_WITH-DASH=Something' myprogram

It's even more common when using Clojure and the popular environ library that deals with properties. Since Clojure uses Lisp syntax it's very common to name keys using dashes.

Without support for this it'll be harder for me (and presumably others) to sell Kubernetes to my company since we have to make code changes in several projects/services.

I'm using Kubernetes 1.0.6 on Google Container Engine.

@pmorie
Copy link
Member

pmorie commented Nov 8, 2015

Afaik the format requirements of env var names are implementation dependent and the C_IDENTIFIER format is the lowest common denominator. There are a ton of ways to externalize configs for spring - can you use a properties file as a work around instead of environment variables? It does look to me like spring's SystemEnvironmentPropertyLoader only attempts to resolve . to _ in var names (https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/env/SystemEnvironmentPropertySource.java)

Also, it does look like environ has some munging that will get around this for you:

Note that Environ automatically lowercases keys, and replaces the characters "_" and "." with "-". The environment variable DATABASE_URL and the system property database.url are therefore both converted to the same keyword :database-url.

Does the environ support unstick you? Seems like it would also probably be possible to write your own property source that does the resolution you want - this will likely be more portable than depending on the shell to support the values you want.

@johanhaleby
Copy link
Author

Thanks for your reply.

There are a ton of ways to externalize configs for spring - can you use a properties file as a work around instead of environment variables?

While I could do it I don't think it would be optimal for us (please correct me if I'm wrong). We're using continuous delivery and we build one image (containing the spring uberjar for example) but we deploy this image to multiple environments with different configurations. We are currently specifying the configuration in environment variables being read by Spring. We could of course choose to use configuration files instead but afaik we would have to bundle these up with the image (and have one image per environment) or mount a volume and copy the configuration to this location. To me this doesn't sound as simple as the just using environment variables. We're currently using docker-compose and as I mentioned earlier it allows specifying environment variables with dash. Since it's allowed in docker-compose I don't see why it wouldn't be supported in Kubernetes as well? If nothing else it would ease transition from docker-compose to Kubernetes for those who are in the same situation as us.

Note that Environ automatically lowercases keys, and replaces the characters "_" and "." with "-".

Sorry I think I was wrong about environ. Thanks for pointing this out.

But would you rather say that it's an issue with the way Spring handles environment variables? Perhaps it should try to translate "_" to "-" as well as "."?

@thockin
Copy link
Member

thockin commented Nov 9, 2015

I'm a little surprised that env vars are allowed to be non-C-identifiers,
but POSIX does actually allow it. It's completely incompatible with
shells, but I guess it is allowed. I've never ever EVER seen that in 20+
years of futzing with UNIXes.

We should fix it, but document it carefully.

On Sun, Nov 8, 2015 at 10:55 PM, Johan Haleby notifications@github.com
wrote:

Thanks for your reply.

There are a ton of ways to externalize configs for spring - can you use a
properties file as a work around instead of environment variables?

While I could do it I don't think it would be optimal for us (please
correct me if I'm wrong). We're using continuous delivery and we build one
image (containing the spring uberjar for example) but we deploy this image
to multiple environments with different configurations. We are currently
specifying the configuration in environment variables being read from by
Spring. We could of course choose to use configuration files instead but
afaik we would have to bundle these up with the image (and have one image
per environment) or mount a volume and copy the configuration to this
location. To me this doesn't sound as good as the just using environment
variables. We're currently using docker-compose and as I mentioned
earlier it allows specifying environment variables with dash. Since it's
allowed in docker-compose I suppose it ought to work in Kubernetes as
well? If not for anything else it would ease transition to Kubernetes for
those who are in the same situ tation as us.

Note that Environ automatically lowercases keys, and replaces the
characters "_" and "." with "-".

Sorry I think I was wrong about environ. Thanks for pointing this out.

But would you rather say that it's an issue with the way Spring handles
environment variables? Perhaps it should try to translate "_" to "-" as
well as "."?


Reply to this email directly or view it on GitHub
#16863 (comment)
.

@spzala
Copy link
Member

spzala commented May 30, 2017

@johanhaleby @thockin I tested with minikube and see the issue with "-" is still there except that with a modified error message "The Pod "containers" is invalid: spec.containers[0].env[0].name: Invalid value: "x-y": must match the regex [A-Za-z_][A-Za-z0-9_]* (e.g. 'my_name' or 'MY_NAME' or 'MyName')"
I am wondering, can we close this issue as "working as designed"? Did we expect any other document changes?
Thanks!!

@thockin
Copy link
Member

thockin commented May 31, 2017

I'd rather see this get fixed, as weird as it is.

@spzala
Copy link
Member

spzala commented May 31, 2017

:-) sure @thockin !!

@parrisvarney
Copy link

parrisvarney commented Jun 27, 2017

The following use case might be relatively common -

The official documentation for setting up Elastic Search via docker provides a docker-compose.yml file with an environment parameter bootstrap.memory_lock=true. This causes the following error:

Error from server (Invalid): error when creating "kubernetes/elasticsearch1-deployment.yaml": Deployment.apps "elasticsearch1" is invalid: [spec.template.spec.containers[0].env[0].name: Invalid value: "cluster.name": a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name',  or 'MY_NAME',  or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*'), spec.template.spec.containers[0].env[1].name: Invalid value: "bootstrap.memory_lock": a valid C identifier must start with alphabetic character or '_', followed by a string of alphanumeric characters or '_' (e.g. 'my_name',  or 'MY_NAME',  or 'MyName', regex used for validation is '[A-Za-z_][A-Za-z0-9_]*')]

The docker-compose.yml file for the lazy:

version: '2'
services:
  elasticsearch1:
    image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2
    container_name: elasticsearch1
    environment:
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 1g
    volumes:
      - esdata1:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - esnet
  elasticsearch2:
    image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2
    environment:
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - "discovery.zen.ping.unicast.hosts=elasticsearch1"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 1g
    volumes:
      - esdata2:/usr/share/elasticsearch/data
    networks:
      - esnet

volumes:
  esdata1:
    driver: local
  esdata2:
    driver: local

networks:
  esnet:

@dweidenfeld
Copy link

+1 same issue with elastic here

@adam-sandor
Copy link

I managed to solve this for Spring by replacing dots with underscores. I'm running the PetClinic example in Kubernetes like with these env params:

env:
        - name: "spring_profiles_active"
          value: "mysql"
        - name: "spring_datasource_url"
          value: "jdbc:mysql://mysql/petclinic"
        - name: "spring_datasource_username"
          value: root
        - name: "spring_datasource_password"
          value: "password"
        - name: "spring_datasource_initialize"
          value: "true"

@alahijani
Copy link

I was able to sidestep this issue in .Net Core by replacing colons with double underscores.

env:
- name: "Logging__LogLevel__Default"
  value: "Debug"

@patrickf55places
Copy link

Also running into this issue using an environment variable that begins with a number.

@ttindell2
Copy link

Any updates on this issue?

@mr-falken
Copy link

Following this one: can't seem to run elastic cluster in openshift due to this restriction.. :(

@montyontherun
Copy link

+1

@dguettler
Copy link

@mr-falken @parrisvarney did you find a way to run elasticsearch?
I'm currently trying to deploy it on OpenShift Container platform and ran into this restrictions.

@mr-falken
Copy link

@dguettler, I just gave up and deployed elk cluster on vms.. :)

@brandonramirez
Copy link

What happens if you define the environment variables via a configmap?

@dguettler
Copy link

Haven't tried but I would expect the same outcome as the validation fails on the name of the environment variable so I'd expect

          env:
            - name: name.with.dots
              valueFrom:
                configMapKeyRef:
                  name: {{ .Release.Name }}-config
                  key: NAME

to fail with the same validation error as

          env:
            - name: name.with.dots
              value: SOME_VALUE

Looks like Kubernetes 1.8 will allow for above though. So in my case OpenShift 3.9 was just released which is running Kubernetes 1.9
Currently we're running OpenShift 3.7 which is on Kubernetes 1.7

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jul 16, 2018
@fejta-bot
Copy link

Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Aug 15, 2018
@fejta-bot
Copy link

Rotten issues close after 30d of inactivity.
Reopen the issue with /reopen.
Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/close

@k8s-ci-robot
Copy link
Contributor

@fejta-bot: Closing this issue.

In response to this:

Rotten issues close after 30d of inactivity.
Reopen the issue with /reopen.
Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/close

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@gunnarmorling
Copy link

gunnarmorling commented Oct 11, 2018

For the sake of others trying to run Elasticsearch on K18S/Openshift and running into this issue, this is how you can handle it:

  • Use elasticsearch.yml to configure the required options

  • Use a config map to inject that file into the container; e.g. that's what I'm doing on Openshift to do so:

    oc create configmap es-config --from-file=elasticsearch.yml
    oc volume dc/elasticsearch --overwrite --add -t configmap \
      -m /usr/share/elasticsearch/config/elasticsearch.yml \
      --sub-path=elasticsearch.yml \
      --name=es-config --configmap-name=es-config
    

@DevOps-Airwallex
Copy link

I managed to solve this for Spring by replacing dots with underscores. I'm running the PetClinic example in Kubernetes like with these env params:

env:
        - name: "spring_profiles_active"
          value: "mysql"
        - name: "spring_datasource_url"
          value: "jdbc:mysql://mysql/petclinic"
        - name: "spring_datasource_username"
          value: root
        - name: "spring_datasource_password"
          value: "password"
        - name: "spring_datasource_initialize"
          value: "true"

thanks for the answer. Just wondering how do you handle, when the property itself have _

e.g.

spring:
    abc:
        cd_ef:
           eg: xxxxxxx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. priority/backlog Higher priority than priority/awaiting-more-evidence. sig/node Categorizes an issue or PR as relevant to SIG Node.
Projects
None yet
Development

No branches or pull requests