I want to run two containers on a single pod.
container1
is a test that tries to connect to a SQL Server Database that runs on container2
.
How can I make sure that the sql container (container2
) will run and be ready before container1
starts?
initContainer
won't work here, as it will run before both containers.
This is my compose.yaml:
apiVersion: v1
kind: Pod
metadata:
name: sql-test-pod
labels:
name: sql-test
spec:
restartPolicy: Never
containers:
- name: my-sqldb
image: docker-registry.com/database
imagePullPolicy: Always
resources:
limits:
memory: "4096Mi"
cpu: "750m"
requests:
memory: "4096Mi"
cpu: "750m"
- name: tests
tty: true
stdin: true
image: docker-registry.com/test
imagePullPolicy: Always
resources:
limits:
memory: "4096Mi"
cpu: "750m"
requests:
memory: "4096Mi"
cpu: "750m"
env:
- name: sqlhostname
value: "SqlHostnamePlaceholder"
nodeSelector:
kubernetes.io/os: windows
tolerations:
- key: "windows"
operator: "Equal"
value: "2019"
effect: "NoSchedule"
Another option is to add command and args to the container.
You can add sleep
command if it's known approximate time for another container to start or add some logic within the command (while
loop checking the connection, once it's connected, exit the loop and run main process - example).
Note! Image's entrypoint
will be replaced by this command:
The command and arguments that you define in the configuration file override the default command and arguments provided by the container image
For instance, for nginx
and command container spec
will look like (since entrypoint
is replaced, it's necessary to provide a command to start the nginx server):
containers:
- name: test
image: nginx
command: ["/bin/bash", "-c"]
args: ["sleep 30 ; echo sleep ended ; nginx -g \"daemon off;\""]
More details here Define a Command and Arguments for a Container.
You cannot do that with current implements of kubernetes
: all container in one pod will startup in same time(except the init container).
One solution is to enhance the code in test container
to detect the state of db container
, hold on until is ready.
In order to make sure that container1
will start only after container2
's SQL Server is up the only way I found is to use postStart
container's lifecycle event.
postStart
triggered after after the container is create, it is true that there is no guarantee, that the postStart handler is called before the Container's entrypoint is called, but it turns out that the Kubelet code that starts the container blocks the start of the next container until the post-start handler terminates.
And this is how my new compose file will look like:
apiVersion: v1
kind: Pod
metadata:
name: sql-test-pod
labels:
name: sql-test
spec:
restartPolicy: Never
containers:
- name: my-sqldb
image: docker-registry.com/database
imagePullPolicy: Always
lifecycle:
postStart:
exec:
command: ['powershell.exe', '-command', "$connectionString = 'Server=sql-test-pod;User Id=user;Password=password'; $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $connectionString; $i=0; while($i -lt 6) {Try { $i++;$sqlConnection.Open();$sqlConnection.Close(); return}Catch {Write-Error $_; start-sleep 30}}"]
resources:
limits:
memory: "4096Mi"
cpu: "750m"
requests:
memory: "4096Mi"
cpu: "750m"
- name: tests
tty: true
stdin: true
image: docker-registry.com/test
imagePullPolicy: Always
resources:
limits:
memory: "4096Mi"
cpu: "750m"
requests:
memory: "4096Mi"
cpu: "750m"
env:
- name: sqlhostname
value: "sql-test-pod"
nodeSelector:
kubernetes.io/os: windows
tolerations:
- key: "windows"
operator: "Equal"
value: "2019"
effect: "NoSchedule"
Similar case you can find here