AWS Elastic Beanstalk option_settings not applied - java

I am deploying a Java SE app to Elastic Beanstalk and want to ensure that the option_settings specified in my .ebextensions/otions.config file are applied as described in the docs. I want to adjust the ELB and ASG settings:
option_settings:
- namespace: aws:elb:policies
option_name: ConnectionSettingIdleTimeout
value: 120
- namespace: aws:autoscaling:launchconfiguration
option_name: InstanceType
value: t2.nano
I include this file in the artifact I am deploying to beanstalk. I am deploying a app.zip file with the following structure:
$ unzip -l app.zip
...
72 12-17-15 18:17 Procfile
83199508 12-17-15 18:17 app.jar
0 12-17-15 18:17 .ebextensions/
209 12-17-15 18:17 .ebextensions/options.config
I am using the eb CLI to create/terminate/update my EBS app:
$ eb terminate
$ # .. create app.zip file
$ eb create
$ eb deploy
However, when I create the EBS environment and/or update it, neither the ELB nor the ASG configuration get applied. Is the file at the wrong place? Do you need to change the way I am deploying this to EBS to apply the config properly? My app it

Related

Spring Boot app in Docker receives: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

I have a Spring Boot app in Docker that runs on Heroku.
Recently, after updating Tomcat to 10.1.0-M10, I started getting this error:
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within
60 seconds of launch
The immediate thought of downgrading to lower versions doesn't work due to vulnerabilities in the earlier versions. I have checked possible causes and found Tomcat binding port issue.
I cannot set up fixed config for different ports as I am deploying to Heroku and dependent on their random ports.
My Dockerfile:
FROM azul/zulu-openjdk-alpine:11
ENV PORT=$PORT
COPY /target/app.jar /app.jar
CMD java -Xms256m -Xmx512m \
-Dlog4j2.formatMsgNoLookups=true \
-Djava.security.egd=file:/dev/./urandom \
-Dserver.port=$PORT \
-jar /app.jar
What is the way to solve it? Is there anything I am missing?
UPDATE:
There are more logs from Heroku:
Feb 22 12:50:16 integration-test app/web.1 2022-02-22 20:50:16.057 [main] INFO c.g.s.z.ApplicationKt - Started ApplicationKt in 8.09 seconds (JVM running for 9.062)
Feb 22 12:50:16 integration-test app/web.1 2022-02-22 20:50:16.060 [main] DEBUG o.s.b.a.ApplicationAvailabilityBean - Application availability state LivenessState changed to CORRECT
Feb 22 12:50:16 integration-test app/web.1 2022-02-22 20:50:16.063 [main] DEBUG o.s.b.a.ApplicationAvailabilityBean - Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
Feb 22 12:51:06 integration-test heroku/web.1 Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
I found a solution that wasn't perfect but seemed to work for me.
Downgraded Spring Boot from 2.6.3 to 2.6.1
Downgraded Tomcat from 10.X.X to 9.X.X
Removed dev tools dependencies
I think the two latest did the magic. Dev tools stopped asking for an extra port in the test/prod environment. Tomcat bound the port in the version 9.X.X but not in 10.X.X.
Even though I found the solution, I don't know why it behaved like this, and it isn't perfect security-wise.
from the error message it seems that $PORT is not resolved to any environment variable.
deploying to heroku you must use .env file to define env vars (you can't use docker run -e PORT=1234) see documentation
When you use heroku locally, you can set config vars in a .env file. When heroku local is run .env is read and each name/value pair is set in the environment. You can use this same .env file when using Docker: docker run -p 5000:5000 --env-file .env <image-name>

How to have the pod created run an application (command and args) and at the same time have a deployment and service referring to it?

Context:
Tech: Java, Docker Toolbox, Minikube.
I have a java web application (already packaged as web-tool.jar) that I want to run while having all the benefits of kubernetes.
In order to instruct kubernetes to take the image locally I use an image tag:
docker build -t despot/web-tool:1.0 .
and then make it available for minikube by:
docker save despot/web-tool:1.0 | (eval $(minikube docker-env) && docker load)
The docker file is:
FROM openjdk:11-jre
ADD target/web-tool-1.0-SNAPSHOT.jar app.jar
EXPOSE 1111
EXPOSE 2222
1. How can I have the pod created, run the java application and at the same time have a deployment and service referring to it?
1.1. Can I have a deployment created that will propagate a command and arguments when creating the pod? (best for me as I ensure creating a deployment and a service prior to creating the pod)
1.2. If 1.1. not feasible, can I kubectl apply some pod configuration with a command and args to the already created deployment/pod/service? (worse solution as additional manual steps)
1.3. If 1.2. not feasible, is it possible to create a deployment/service and attach it to an already running pod (that was started with "kubectl run ... java -jar app.jar reg")?
What I tried is:
a) Have a deployment created (that automatically starts a pod) and exposed (service created):
kubectl create deployment reggo --image=despot/web-tool:1.0
With this, a pod is created with a CrashLoopBackoff state as it doesn't have a foreground process running yet.
b) Tried the following in the hope of the deployment accepting a command and args that will propagate to the pod creation (1.1.):
kubectl create deployment reggo --image=despot/web-tool:1.0 -- java -jar app.jar reg
The same outcome of the pod, as the deployment doesn't accept command and args.
c) Tried applying a pod configuration with a command and args after the deployment created the pod, so I ran the command from a), found the id (reggo-858ccdcddd-mswzs) of the pod with (kubectl get pods) and then I executed:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: reggo-858ccdcddd-mswzs
spec:
containers:
- name: reggo-858ccdcddd-mswzs
command: ["java"]
args: ["-jar", "app.jar", "reg"]
EOF
but I got:
Warning: kubectl apply should be used on resource created by either
kubectl create --save-config or kubectl apply The Pod
"reggo-858ccdcddd-mswzs" is invalid:
* spec.containers[0].image: Required value
* spec.containers: Forbidden: pod updates may not add or remove containers
that lets me think that I can't execute the command by applying the command/args configuration.
Solution (using Arghya answer):
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: reggo
spec:
selector:
matchLabels:
app: reggo-label
template:
metadata:
labels:
app: reggo-label
spec:
containers:
- name: reggo
image: "despot/web-tool:1.0"
command: ["java"]
args: ["-jar", "app.jar", "reg"]
ports:
- containerPort: 1111
EOF
and executing:
kubectl expose deployment reggo --type=NodePort --port=1111
You could have the java -jar command as ENTRYPOINT in the docker file itself which tells Docker to run the java application.
FROM openjdk:11-jre
ADD target/web-tool-1.0-SNAPSHOT.jar app.jar
EXPOSE 1111
EXPOSE 2222
ENTRYPOINT ["java", "-jar", "app.jar", "reg"]
Alternatively the same can be achieved via command and args section in a kubernetes yaml
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
command: ["java"]
args: ["-jar", "app.jar", "reg"]
Now coming to the point of Forbidden: pod updates may not add or remove containers error the reason its happening is because you are trying to modify an existing pod object's containers section which is not allowed. Instead of doing that you can get the entire deployment yaml and open it up in an editor and edit it to add the command section and then delete the existing deployment and finally apply the modified deployment yaml to the cluster.
kubectl get deploy reggo -o yaml --export > deployment.yaml
Delete the existing deployment via kubectl delete deploy reggo
Edit deployment.yaml to add right command
Apply the yaml to the cluster kubectl apply -f deployment.yaml
As already mentioned, recommended approach is to add ENTRYPOINT in your Dockerfile with the command that you are willing to use.
However if you want to create a deployment using kubectl command you can run
kubectl run $DEPLOYMENT_NAME --image=despot/web-tool:1.0 --command -- java -jar app.jar reg
Additionally if you want to expose the deployment using same command you can pass:
--expose=true argument which will create a service of type ClusterIP and
--port=$PORT_NUMBER to choose port on which it will exposed.
to change port type to NodePort you have to run:
kubectl run $DEPLOYMENT_NAME --image=despot/web-tool:1.0 --expose=true --service-overrides='{ "spec": { "type": "NodePort" } }' --port=$PORT_NUMBER --command -- java -jar app.jar reg

How to copy executable file to Docker container using Testcontainers

I'm trying to copy an executable initialization bash script init.sh to the Localstack Docker container created with Testcontainers (1.13.0) using the JUnit 5 module:
#Container
static LocalStackContainer localStack = new LocalStackContainer("0.10.0")
.withServices(S3)
.withCopyFileToContainer(MountableFile.forClasspathResource("init.sh"), "/docker-entrypoint-initaws.d/init.sh");
But inside the created Docker container the file lacks the execute permission (checked with looking at the file permission using docker exec -it ID /bin/sh).
On my machine the file has the following permission:
$ ls -al
total 16
drwxr-xr-x 4 xyz staff 128 Apr 16 20:51 .
drwxr-xr-x 4 xyz staff 128 Apr 16 08:43 ..
-rw-r--r-- 1 xyz staff 135 Apr 16 20:14 application.yml
-rwxr-xr-x 1 xyz staff 121 Apr 16 20:51 init.sh
I also tried copying this file with .withClasspathResourceMapping() but this takes a binding mode which only offers READ_ONLY or READ_WRITE.
You can use another builder of MountableFile class, which takes the mode argument with a posix file mode value to change permission. For example, making the script executable only for the owner:
...
.withCopyFileToContainer(MountableFile.forClasspathResource("init.sh", 0744), "/docker-entrypoint-initaws.d/init.sh");
0744 is an octal file mode literal which corresponds to -rwxr--r-- permission.
However I tried the same configuration with Localstack 0.10.8 and initialisation works without even making the script executable.

Unable to install Jetty9 as a service in Ubuntu

I've followed the docs in order to install Jetty9 as a service but whenever I run
service jetty start
It would fail with no messages, my JETTY_HOME is /opt/jetty9, contains the home distribution for version 9.4.14. I've also created my JETTY_BASE at /usr/share/jetty9 with my webapp and modules.
Both Jetty Home and Base are owned by the user jetty. I've then symlinked to my init.d folder as:
ln -s /opt/jetty9/bin/jetty.sh /etc/init.d/jetty
Then I created a /etc/default/jetty file with the following content:
# change to 1 to prevent Jetty from starting
NO_START=0
# change to 'no' or uncomment to use the default setting in /etc/default/rcS
VERBOSE=yes
# Run Jetty as this user ID (default: jetty)
# Set this to an empty string to prevent Jetty from starting automatically
JETTY_USER=jetty
# The home directory of the Java Runtime Environment (JRE). You need at least
# Java 6. If JAVA_HOME is not set, some common directories for OpenJDK and
# the Oracle JDK are tried.
#JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
# Extra options to pass to the JVM
#JAVA_OPTIONS="-Xmx256m -Djava.awt.headless=true"
# Timeout in seconds for the shutdown of all webapps
#JETTY_SHUTDOWN=30
# Additional arguments to pass to Jetty
#JETTY_ARGS=
# Jetty uses a directory to store temporary files like unpacked webapps
TMPDIR=/opt/jetty9/tmp
JETTY_HOME=/opt/jetty9
JETTY_BASE=/usr/share/jetty9
# Default for number of days to keep old log files in /var/log/jetty9/
#LOGFILE_DAYS=14
# If you run Jetty on port numbers that are all higher than 1023, then you # do not need authbind. It is used for binding Jetty to lower port numbers.
# (yes/no, default: no)
#AUTHBIND=yes
JETTY_HOST=0.0.0.0
If I start Jetty using java -jar $JETTY_HOME/start.jar in my base folder it would work with no problem. Also, if I run
service jetty supervise
It would also run with no issues, but when I call start it fails with:
root#app:/usr/share/jetty9# service jetty start
Job for jetty.service failed because the control process exited with error code.
See "systemctl status jetty.service" and "journalctl -xe" for details.
root#app:/usr/share/jetty9# service jetty status
● jetty.service - LSB: Jetty start script.
Loaded: loaded (/etc/init.d/jetty; generated)
Active: failed (Result: exit-code) since Mon 2018-12-03 15:05:26 UTC; 14s ago
Docs: man:systemd-sysv-generator(8)
Process: 21162 ExecStop=/etc/init.d/jetty stop (code=exited, status=0/SUCCESS)
Process: 21202 ExecStart=/etc/init.d/jetty start (code=exited, status=1/FAILURE)
Dec 03 15:05:22 app systemd[1]: Stopped LSB: Jetty start script..
Dec 03 15:05:22 app systemd[1]: Starting LSB: Jetty start script....
Dec 03 15:05:26 app jetty[21202]: Starting Jetty: FAILED Mon Dec 3 15:05:26 UTC 2018
Dec 03 15:05:26 app systemd[1]: jetty.service: Control process exited, code=exited status=1
Dec 03 15:05:26 app systemd[1]: jetty.service: Failed with result 'exit-code'.
Dec 03 15:05:26 app systemd[1]: Failed to start LSB: Jetty start script..
This is the output of service jetty check:
root#app:/usr/share/jetty9# service jetty check
Jetty NOT running
JAVA = /usr/bin/java
JAVA_OPTIONS = -Djetty.home=/opt/jetty9 -Djetty.base=/usr/share/jetty9 -Djava.io.tmpdir=/opt/jetty9/tmp
JETTY_HOME = /opt/jetty9
JETTY_BASE = /usr/share/jetty9
START_D = /usr/share/jetty9/start.d
START_INI = /usr/share/jetty9/start.ini
JETTY_START = /opt/jetty9/start.jar
JETTY_CONF = /opt/jetty9/etc/jetty.conf
JETTY_ARGS = jetty.state=/usr/share/jetty9/jetty.state jetty-started.xml
JETTY_RUN = /var/run/jetty
JETTY_PID = /var/run/jetty/jetty.pid
JETTY_START_LOG = /var/run/jetty/jetty-start.log
JETTY_STATE = /usr/share/jetty9/jetty.state
JETTY_START_TIMEOUT = 60
RUN_CMD = /usr/bin/java -Djetty.home=/opt/jetty9 -Djetty.base=/usr/share/jetty9 -Djava.io.tmpdir=/opt/jetty9/tmp -jar /opt/jetty9/start.jar jetty.state=/usr/share/jetty9/jetty.state jetty-started.xml
Any ideas?
UPDATE
Changing the user in /etc/default/jetty to root would solve the issue, but this is not a solution, isn't it?
# Run Jetty as this user ID (default: jetty)
# Set this to an empty string to prevent Jetty from starting automatically
JETTY_USER=root
I finally got this working, the jetty user should have permissions to the following folders and /usr/sbin/nologin as shell as described here.
JETTY_HOME
JETTY_BASE
/var/run/jetty <-- couldn't find a reference to this folder in the docs
And add the following to your /etc/default/jetty:
JETTY_SHELL=/bin/sh
JETTY_LOGS=/usr/share/jetty9/logs
JETTY_START_LOG=/usr/share/jetty9/logs/jetty-start-log.log
Also you should double check that there are no remaining log files owned by other user than jetty in your folders.

System environment variables in Jetty application

How to configure system environment variables inside one Jetty application?
e.g. For database connection details, putting it in file and checking it into cvs is bad idea. For that reason using system environment is one way to go. While the system environment variables are defined in /etc/environments file or .bashrc/.zshrc file , in Jetty application, doing System.getenv("variable_name") won't give anything. It will result in null.
I have read this question: Configuring a Jetty application with env variables which concludes that which tells that Jetty doesn't support System.getenv() and not even in start.ini file.
And jetty and etc environment on ubuntu 12.10 which says In the jetty.sh script you can source the /etc/environment file and they will be present. which I tried and didn't get the values as expected meaning it gave me only null.
If I can't use the default System.getenv() or in any .ini file then how to specify credentials such as Database connection etc ?
Not supporting System.getenv() is not a Jetty thing, but a Java thing.
There are ton of restrictions around System.getenv() and your environment, making it nearly useless in all but the most naive and basic test case. (eg: multiline values are not supported. multiline entries can break parsing. keys without values are not supported. keys without values can often merge with next key during parsing. entries with non US-ASCII characters are not supported. entries with control characters are not supported.)
The common technique when using System Environment variables with Java programs is to use the shell specific techniques to obtain the values and inject them either on the command line, or into a ini file format for Jetty to then use.
Depending on your technique, these values would either show up as Jetty properties, or as Java System Properties.
Just created a project to demonstrate 4 ways to accomplish this at
https://github.com/jetty-project/jetty-external-config
External Configuration Properties with Jetty
Demonstration of how to configure simple properties that can be accessed
by Servlets within Jetty.
This demonstration shows 4 different ways to configure a property
at runtime, that can then be read by the Servlet running within
Jetty.
The props.war
This is a simple war file with a single HttpServlet and a WEB-INF/web.xml
[jetty-external-config]$ jar -tvf target/props.war
0 Mon Feb 23 09:02:14 MST 2015 META-INF/
131 Mon Feb 23 09:02:14 MST 2015 META-INF/MANIFEST.MF
0 Mon Feb 23 09:02:14 MST 2015 WEB-INF/
0 Mon Feb 23 09:02:14 MST 2015 WEB-INF/classes/
0 Mon Feb 23 09:02:14 MST 2015 WEB-INF/classes/org/
0 Mon Feb 23 09:02:14 MST 2015 WEB-INF/classes/org/eclipse/
0 Mon Feb 23 09:02:14 MST 2015 WEB-INF/classes/org/eclipse/demo/
2188 Mon Feb 23 09:02:12 MST 2015 WEB-INF/classes/org/eclipse/demo/PropsServlet.class
572 Mon Feb 23 08:45:22 MST 2015 WEB-INF/web.xml
See PropsServlet.java for details of behavior.
Just compile the top level and the war file will be built and placed in all of the demo jetty.base locations for this project.
Example #1: Basic Command Line
The /base-command-line project contains a simple start.ini which starts jetty on port 9090, and deploys the webapp. no extra configuration is done by the on-disk configuration.
If you start it up like so ...
[base-command-line]$ java -jar /path/to/jetty-distribution-9.2.7.v20150116/start.jar
2015-02-23 09:15:46.088:INFO::main: Logging initialized #290ms
2015-02-23 09:15:46.222:INFO:oejs.Server:main: jetty-9.2.7.v20150116
2015-02-23 09:15:46.235:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/home/joakim/code/stackoverflow/jetty-external-config/base-command-line/webapps/] at interval 1
2015-02-23 09:15:46.325:INFO:oejw.StandardDescriptorProcessor:main: NO JSP Support for /props, did not find org.eclipse.jetty.jsp.JettyJspServlet
2015-02-23 09:15:46.343:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#6e7f61a3{/props,file:/tmp/jetty-0.0.0.0-9090-props.war-_props-any-27537844855769703.dir/webapp/,AVAILABLE}{/props.war}
2015-02-23 09:15:46.353:INFO:oejs.ServerConnector:main: Started ServerConnector#67cd35c5{HTTP/1.1}{0.0.0.0:9090}
2015-02-23 09:15:46.353:INFO:oejs.Server:main: Started #555ms
you'll see that it has started up and deployed to the /props context path.
From here you can test for properties in the servlet via tooling like wget or curl.
Example:
$ curl http://localhost:9090/props/props
[java.runtime.name] = Java(TM) SE Runtime Environment
[sun.boot.library.path] = /home/joakim/java/jvm/jdk-7u75-x64/jre/lib/amd64
[java.vm.version] = 24.75-b04
[java.vm.vendor] = Oracle Corporation
[java.vendor.url] = http://java.oracle.com/
...
[file.separator] = /
[java.vendor.url.bug] = http://bugreport.sun.com/bugreport/
[sun.io.unicode.encoding] = UnicodeLittle
[sun.cpu.endian] = little
[sun.desktop] = gnome
[sun.cpu.isalist] =
You can even request a specific property ..
$ curl http://localhost:9090/props/props/user.timezone
[user.timezone] = America/Phoenix
Lets stop the server and run it with a system property of our choice.
Notice the -Dfoo=bar ?
[base-command-line]$ java -Dfoo=bar -jar /path/to/jetty-distribution-9.2.7.v20150116/start.jar
2015-02-23 09:15:46.088:INFO::main: Logging initialized #290ms
2015-02-23 09:15:46.222:INFO:oejs.Server:main: jetty-9.2.7.v20150116
2015-02-23 09:15:46.235:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/home/joakim/code/stackoverflow/jetty-external-config/base-command-line/webapps/] at interval 1
2015-02-23 09:15:46.325:INFO:oejw.StandardDescriptorProcessor:main: NO JSP Support for /props, did not find org.eclipse.jetty.jsp.JettyJspServlet
2015-02-23 09:15:46.343:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#6e7f61a3{/props,file:/tmp/jetty-0.0.0.0-9090-props.war-_props-any-27537844855769703.dir/webapp/,AVAILABLE}{/props.war}
2015-02-23 09:15:46.353:INFO:oejs.ServerConnector:main: Started ServerConnector#67cd35c5{HTTP/1.1}{0.0.0.0:9090}
2015-02-23 09:15:46.353:INFO:oejs.Server:main: Started #555ms
and look for it via curl ...
$ curl http://localhost:9090/props/props/foo
[foo] = bar
That demonstrates access of a property that was specified via the command line, now lets look at the other choices.
Example #2: Using start.ini
The /base-startini project contains a simple start.ini which starts jetty on port 9090, and deploys the webapp.
This start.ini also contains a foo.ish property.
Lets start up Jetty and try our props servlet access again ...
[base-startini]$ java -jar /path/to/jetty-distribution-9.2.7.v20150116/start.jar
2015-02-23 09:16:46.088:INFO::main: Logging initialized #290ms
2015-02-23 09:16:46.222:INFO:oejs.Server:main: jetty-9.2.7.v20150116
and request it via curl ...
$ curl http://localhost:9090/props/props/foo.ish
[foo.ish] = bar
Example #3: Using start.d optional ini
The /base-startd project contains a simple start.ini which starts jetty on port 9090, and deploys the webapp.
This start.ini also contains no extra properties that we are interested in.
The start.d/myconf.ini contains a property called foo.d that we are interested in.
Lets start up Jetty and try our props servlet access again ...
[base-startd]$ java -jar /path/to/jetty-distribution-9.2.7.v20150116/start.jar
2015-02-23 09:19:46.088:INFO::main: Logging initialized #290ms
2015-02-23 09:19:46.222:INFO:oejs.Server:main: jetty-9.2.7.v20150116
and request it via curl ...
$ curl http://localhost:9090/props/props/foo.d
[foo.d] = over here
Example #4: Using --include-jetty-dir optional config
The /base-jettyinclude project contains a new start.ini which starts jetty on port 9090, and deploys the webapp.
This start.ini also contains no extra properties that we are interested in.
However, the start.ini uses the --include-jetty-dir=../jettydir optional configuration that points to an entirely new interrim jetty.base configuration source.
The ../jettydir/start.ini contains a property called foo.jetty.dir that we are interested in.
Lets start up Jetty and try our props servlet access again ...
[base-jettyinclude]$ java -jar /path/to/jetty-distribution-9.2.7.v20150116/start.jar
2015-02-23 09:24:46.088:INFO::main: Logging initialized #290ms
2015-02-23 09:24:46.222:INFO:oejs.Server:main: jetty-9.2.7.v20150116
and request it via curl ...
$ curl http://localhost:9090/props/props/foo.jetty.dir
[foo.jetty.dir] = more of the same

Categories

Resources