how to mount a path as non root user in kubernetes - kubernetes

I deployed a mysql monitor application image in kubernetes cluster which run as non root user. When I tried to mount a path to make the data persistent,its overriding the directory(creates a new directory by deleting everything inside that path) in which my application configuration files has to be present.Even I tried using init container still,i am not able to mount it.
my docker file:
FROM centos:7
ENV DIR /binaries
ENV PASS admin
WORKDIR ${DIR}
COPY libstdc++-4.8.5-39.el7.x86_64.rpm ${DIR}
COPY numactl-libs-2.0.12-3.el7.x86_64.rpm ${DIR}
COPY mysqlmonitor-8.0.18.1217-linux-x86_64-installer.bin ${DIR}
RUN yum install -y libaio && yum -y install gcc && yum -y install gcc-c++ && yum -y install compat-libstdc++-33 && yum -y install libstdc++-devel && yum -y install elfutils-libelf-devel && yum -y install glibc-devel && yum -y install libaio-devel && yum -y install sysstat
RUN yum install -y gcc && yum install -y make && yum install -y apr-devel && yum install -y openssl-devel && yum install -y java
RUN rpm -ivh numactl-libs-2.0.12-3.el7.x86_64.rpm
RUN useradd sql
RUN chown sql ${DIR}
RUN chmod 777 ${DIR}
RUN chmod 755 /home/sql
USER sql
WORKDIR ${DIR}
RUN ./mysqlmonitor-8.0.18.1217-linux-x86_64-installer.bin --installdir /home/sql/mysql/enterprise/monitor --mode unattended --tomcatport 18080 --tomcatsslport 18443 --adminpassword ### --dbport 13306
RUN rm -rf /binaries/*
VOLUME /home/mysql/mysql/enterprise/monitor/mysql/data
ENTRYPOINT ["/bin/bash", "-c", "/home/sql/mysql/enterprise/monitor/mysqlmonitorctl.sh start && tail -f /home/sql/mysql/enterprise/monitor/apache-tomcat/logs/mysql-monitor.log"]
my deployment file
apiVersion: apps/v1
kind: Deployment
metadata:
name: mypod
spec:
replicas: 1
selector:
matchLabels:
app: mem
template:
metadata:
labels:
app: mem
spec:
containers:
- name: mem
image: 22071997/mem
command:
volumeMounts:
- mountPath: /home/sql/mysql/enterprise/monitor/mysql/data
name: volume
volumes:
- name: volume
persistentVolumeClaim:
claimName: mem-pvc1
initContainers:
- name: permissionsfix
image: alpine:latest
command: ["/bin/sh", "-c"]
args:
- chown -R 1000:1000 /home/sql/mysql/enterprise/monitor/ && chmod -R 777 /home/sql/mysql/enterprise/monitor/ ;
volumeMounts:
- name: volume
mountPath: /home/sql/mysql/enterprise/monitor
output:
[sql#mypod-775764db45-bzs8n enterprise]$ cd monitor/mysql
[sql#mypod-775764db45-bzs8n mysql]$ ls
LICENSE LICENSE.router README.meb bin docs lib my-large.cnf my-small.cnf new runtime support-files var
LICENSE.meb README README.router data include man my-medium.cnf my.cnf run share tmp
[sql#mypod-775764db45-bzs8n mysql]$ cd data
[sql#mypod-775764db45-bzs8n data]$ ls
mypod-775764db45-bzs8n.err

This doesn't seem related to mounting as a non-root user, but more so that mounting a volume over an existing directory will result in that directory looking as if it is empty (or containing whatever happens to be on the volume already). If you have configuration stored on a non-volume that you would like to be on the volume, then you will need to mount the volume to a different location (so it doesn't overwrite your local configuration) and copy that configuration to the mounted volume location. You can do this in an init container, but be careful not to overwrite the volume contents on every startup of the container.

Related

How can I start Tortoise-ORM in a celery docker container?

I have an application in which I use a postgresql and celery database. Each element is running in a different container, in the celery container I am already connected to the postgres database, however I don't know how I could configure tortoise-orm to start in the celery container, since I have a task in which I want to interact with the database using tortoise.
This is my docker compose:
version: '3.8'
services:
web:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_web
# '/start' is the shell script used to run the service
command: /start
# this volume is used to map the files and folders on the host to the container
# so if we change code on the host, code in the docker container will also be changed
volumes:
- .:/app
ports:
- 8010:8000
env_file:
- .env/.dev-sample
depends_on:
- redis
- db
db:
image: postgres:14-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=fastapi_celery
- POSTGRES_USER=fastapi_celery
- POSTGRES_PASSWORD=fastapi_celery
redis:
image: redis:7-alpine
celery_worker:
build:
context: .
dockerfile: ./compose/local/fastapi/Dockerfile
image: fastapi_celery_example_celery_worker
command: /start-celeryworker
volumes:
- .:/app
env_file:
- .env/.dev-sample
depends_on:
- redis
- db
This is my dockerfile:
FROM python:3.10-slim-buster
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
RUN apt-get update \
# dependencies for building Python packages
&& apt-get install -y build-essential \
# psycopg2 dependencies
&& apt-get install -y libpq-dev \
# Additional dependencies
&& apt-get install -y telnet netcat \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*
# Requirements are installed here to ensure they will be cached.
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./compose/local/fastapi/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint
COPY ./compose/local/fastapi/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start
COPY ./compose/local/fastapi/celery/worker/start /start-celeryworker
RUN sed -i 's/\r$//g' /start-celeryworker
RUN chmod +x /start-celeryworker
COPY ./compose/local/fastapi/celery/beat/start /start-celerybeat
RUN sed -i 's/\r$//g' /start-celerybeat
RUN chmod +x /start-celerybeat
COPY ./compose/local/fastapi/celery/flower/start /start-flower
RUN sed -i 's/\r$//g' /start-flower
RUN chmod +x /start-flower
WORKDIR /app
ENTRYPOINT ["/entrypoint"]
The task:
#shared_task()
def task_send_welcome_email(user_pk):
from project.users.models import User
user = User.filter(id=user_pk).first()
logger.info(f'send email to {user.email} {user.id}')

/bin/bash: line 123: kubectl: command not found

This is my first time using GitLab for EKS and I feel so lost. I've been following the docs and so far I
Created a project on GitLab that contains my kubernetes manifest files
Created a config.yaml in that project in the directory .gitlab/agents/stockagent
Here's the config.yaml, my project name is "Stock-Market-API-K8s" and my k8s manifests are in the root directory of that project
ci_access:
projects:
- id: "root/Stock-Market-API-K8s"
In my root directory of my project, I also have a .gitlab-ci.yml file and here's the contents of that
deploy:
image:
name: mpriv32/stock-api:latest
entrypoint: ['']
script:
- kubectl config get-contexts
- kubectl config use-context .gitlab/agents/stockagent
- kubectl get pods
Using the default example from the docs, it seems that the get-contexts script is the one that failed. Here's the full error from my logs
Executing "step_script" stage of the job script
00:01
Using docker image sha256:58ddf823e9d7ee4c0e75779b7e01dab9b11ac0d985d1b2d2fe6c6b95a849573d for mpriv32/stock-api:latest with digest mpriv32/stock-api#sha256:a2e79a2c3a57327f93e36ec55297a606626e4dc8d72e469dd4dc2f3c1f589bac ...
$ kubectl config get-contexts
/bin/bash: line 123: kubectl: command not found
Cleaning up project directory and file based variables
00:00
ERROR: Job failed: exit code 1
Here's my job.yaml file for my kubernetes pod, just in case it plays a factor at all
apiVersion: v1
kind: Pod
metadata:
name: stock-api
labels:
app: stock-api
spec:
containers:
- name: stock-api
image: mpriv32/stock-api:latest
envFrom:
- secretRef:
name: api-credentials
restartPolicy: Never
In your case, I guess the image(mpriv32/stock-api:latest) that you are using doesn't have a dependency kubectl as a global executable, please use an image as an example - bitnami/kubectl which "contains" kubectl
deploy:
image:
name: bitnami/kubectl
the image keyword is the name of the Docker image the Docker executor uses to run CI/CD jobs.
For more information https://docs.gitlab.com/ee/ci/docker/using_docker_images.html
Or you can build your docker image on top of bitnami/kubectl
FROM bitnami/kubectl:1.20.9 as kubectl
FROM ubuntu-or-whatever-image:tag
# Do whatever you need to with the
# ubuntu-or-whatever-image:tag image, then:
COPY --from=kubectl /opt/bitnami/kubectl/bin/kubectl /usr/local/bin/
Or you can go with the approach of building an image from the scratch by
installing there the dependencies that you are using
smth like
FROM ubuntu:18.10
WORKDIR /root
COPY bootstrap.sh ./
RUN apt-get update && apt-get -y install --no-install-recommends \
gnupg \
curl \
wget \
git \
apt-transport-https \
ca-certificates \
zsh \
&& rm -rf /var/lib/apt/lists/*
ENV SHELL /usr/bin/zsh
# Install kubectl
RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list && \
apt-get update && apt-get -y install --no-install-recommends kubectl

Connection refused inside kubernetes cron jobs using snx vpn and paramiko sftp

I run a python script to download file via sftp using vpn snx vpn and sftp paramiko. I invoke the script via cronjobs,
Here are my cronjobs script:
apiVersion: batch/v1
kind: CronJob
metadata:
name: file-uploader-a
labels:
app: file-uploader
spec:
schedule: "*/1 0-10 * * *"
jobTemplate:
spec:
parallelism: 1 # How many pods will be instantiated at once.
completions: 1 # How many containers of the job are instantiated one after the other (sequentially) inside the pod.
backoffLimit: 5 # Maximum pod restarts in case of failure
template:
spec:
containers:
- name: file-uploader-a
image: image-a
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: file-env
- secretRef:
name: file-secret
securityContext:
capabilities:
add:
- CAP_NET_ADMIN
- CAP_SYS_MODULE
command:
- sh
- "-c"
- ". /root/.venv/bin/activate && python -m python.module.a"
restartPolicy: OnFailure
terminationGracePeriodSeconds: 8
My Docker file
FROM ubuntu:18.04
ADD scripts/snx_install_800010013.sh /root
ADD scripts/SINAR33-exp-13May2022.pfx /root
ADD scripts/post_install.sh /root
ADD scripts/init_snx.sh /root
ADD requirements.txt /root
RUN cd root && mkdir bss_uploader
RUN cd root/bss_uploader && mkdir temp
ADD bss_uploader /root/bss_uploader
ARG SNX_SERVER
ARG FTP_HOST
ARG DEBIAN_FRONTEND=noninteractive
RUN dpkg --add-architecture i386 && apt-get update && \
apt-get install bzip2 kmod libstdc++5:i386 \
libpam0g:i386 libx11-6:i386 expect iptables \
net-tools iputils-ping iproute2 python3-venv \
linux-modules-5.4.0-1063-aws python3-pip \
software-properties-common tmux openssh-client -y
RUN cd /usr/bin && ln -s python3 python
WORKDIR /root
RUN bash -x snx_install_800010013.sh
RUN bash -x post_install.sh $SNX_SERVER $FTP_HOST
post_install.sh script
#!/bin/bash
SNX_SERVER=$1
FTP_HOST=$2
mkdir ~/.ssh && touch ~/.ssh/config
echo -e "Host $FTP_HOST\n\tStrictHostKeyChecking no\n\nHost $SNX_SERVER\n\tStrictHostKeyChecking no" >> ~/.ssh/config
chmod 644 ~/.ssh/config
uname=$(uname -r)
mkdir /lib/modules/$uname
# move kernel modules installed to current
cp -a /lib/modules/5.4.0-1063-aws/. /lib/modules/$uname/
modprobe tun
python -m venv .venv
. .venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt
init_snx.sh script to init on first run
#!/bin/bash
iptables -t nat -A POSTROUTING -o tunsnx -j MASQUERADE
iptables -A FORWARD -i eth0 -j ACCEPT
SNX_SERVER=$1
SNX_PASSWORD=$2
SNX_COMMAND="snx -s $SNX_SERVER -c /root/SINAR33-exp-13May2022.pfx -g"
/usr/bin/expect <<EOF
spawn $SNX_COMMAND
expect "*?assword:"
send "$SNX_PASSWORD\r"
expect "*Do you accept*"
send "y\r"
expect "SNX - connected."
spawn sleep 4
expect "Waiting up to*"
spawn snx -d
expect "SNX - Disconnecting*"
spawn sleep 2
expect "Waiting up to*"
EOF
When I try to run the script via CronJobs, I got connection refused error while connecting to SFTP.
But when i try to run manualy from docker-container (via cli docker container) i got succeed
docker run --name xt_up --cap-add=ALL -t -d image:latest
I already tried to add networkPolicies.egress but still got no luck
could you please help me regarding this ?
thank you and sorry for my bad english

How to use PersistentVolume for PostgreSQL data in Kubernetes

We are developing Web-server by Flask & DB-server by PostgreSQL in Kubernetes, and considering to use PersistentVolume in order to make data persistent.
However, for the directory specified as Volume, the ownership is forced to become ‘root’ user.
In PostgreSQL, if the user and owner do not match, the server can not be set up.
And, we can not set up a server under the user=‘root’.
So, we can not make PostgreSQL server data persistent.
Dockerfile
FROM ubuntu:latest
ARG project_dir=/app/
WORKDIR $project_dir
RUN apt update
RUN apt install --yes python3 python3-pip postgresql-9.5
RUN apt clean
RUN ln -s /usr/bin/python3 /usr/bin/python
RUN ln -s /usr/bin/pip3 /usr/bin/pip
RUN pip install flask
RUN pip install flask_sqlalchemy
RUN pip install psycopg2
ADD app.py $project_dir
ADD templates/ $project_dir/templates/
USER postgres
RUN /etc/init.d/postgresql start && \
psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" && \
createdb -O docker docker
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.5/main/pg_hba.conf
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.5/main/postgresql.conf
EXPOSE 5000
CMD /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.5/main -c config_file=/etc/postgresql/9.5/main/postgresql.conf & python /app/app.py
development.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: dummyproject
labels:
app: dummyproject
spec:
replicas: 1
selector:
matchLabels:
app: dummyproject
template:
metadata:
labels:
app: dummyproject
spec:
containers:
- name: dummyproject
image: dummyproject:0.1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
volumeMounts:
- mountPath: /var/lib/postgresql/
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: nfs-claim1
Please let me know if you know the solution.
Feel free to run PostgreSQL as root. Root in the container is not the same as root on a bare Linux machine. UID==0 doesn't imply superpowers anymore. Nowadays user access is controlled with the mechanism of capabilities, and your container won't have any dangerous capabilities by default (unless you explicitly ask Kubernetes for some).
You have 2 options here:
Set UID to 0 in the container, as #Alexandr Lurye told above. That is more or less secure now.
You can use InitContainer to change the owner. That is my answer how to do it - https://serverfault.com/questions/906083/how-to-mount-volume-with-specific-uid-in-kubernetes-pod/907160#907160

How to persist data using a postgres database, Docker, and Kubernetes?

I am trying to mount a persistent disk on my container which runs a Postgres custom image. I am using Kubernetes and following this tutorial.
This is my db_pod.yaml file:
apiVersion: v1
kind: Pod
metadata:
name: lp-db
labels:
name: lp-db
spec:
containers:
- image: my_username/my-db
name: my-db
ports:
- containerPort: 5432
name: my-db
volumeMounts:
- name: pg-data
mountPath: /var/lib/postgresql/data
volumes:
- name: pg-data
gcePersistentDisk:
pdName: my-db-disk
fsType: ext4
I create the disk using the command gcloud compute disks create --size 200GB my-db-disk.
However, when I run the pod, delete it, and then run it again (like in the tutorial) my data is not persisted.
I tried multiple versions of this file, including with PersistentVolumes and PersistentVolumeClaims, I tried changing the mountPath, but to no success.
Edit
Dockerfile for creating the Postgres image:
FROM ubuntu:trusty
RUN rm /bin/sh && \
ln -s /bin/bash /bin/sh
# Get Postgres
RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main" >> /etc/apt/sources.list.d/pgdg.list
RUN apt-get update && \
apt-get install -y wget
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# Install virtualenv (will be needed later)
RUN apt-get update && \
apt-get install -y \
libjpeg-dev \
libpq-dev \
postgresql-9.4 \
python-dev \
python-pip \
python-virtualenv \
strace \
supervisor
# Grab gosu for easy step-down from root
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \
&& gpg --verify /usr/local/bin/gosu.asc \
&& rm /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& apt-get purge -y --auto-remove ca-certificates wget
# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
# Adjust PostgreSQL configuration so that remote connections to the database are possible.
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.4/main/pg_hba.conf
# And add ``listen_addresses`` to ``/etc/postgresql/9.4/main/postgresql.conf``
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.4/main/postgresql.conf
RUN echo "log_directory='/var/log/postgresql'" >> /etc/postgresql/9.4/main/postgresql.conf
# Add all code from the project and all config files
WORKDIR /home/projects/my-project
COPY . .
# Add VOLUMEs to allow backup of config, logs and databases
ENV PGDATA /var/lib/postgresql/data
VOLUME /var/lib/postgresql/data
# Expose an entrypoint and a port
RUN chmod +x scripts/sh/*
EXPOSE 5432
ENTRYPOINT ["scripts/sh/entrypoint-postgres.sh"]
And entrypoint script:
echo " I am " && gosu postgres whoami
gosu postgres /etc/init.d/postgresql start && echo 'Started postgres'
gosu postgres psql --command "CREATE USER myuser WITH SUPERUSER PASSWORD 'mypassword';" && echo 'Created user'
gosu postgres createdb -O myuser mydb && echo 'Created db'
# This just keeps the container alive.
tail -F /var/log/postgresql/postgresql-9.4-main.log
In the end, it seems that the real problem was the fact that I was trying to create the database from my entrypoint script.
Things such as creating a db or a user should be done at container creation time so I ended up using the standard Postgres image, which actually provides a simple and easy way to create an user and a db.
This is the fully functional configuration file for Postgres.
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
name: postgres
spec:
containers:
- name: postgres
image: postgres
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
value: myuser
- name: POSTGRES_PASSWORD
value: mypassword
- name: POSTGRES_DB
value: mydb
ports:
- containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: pg-data
volumes:
- name: pg-data
persistentVolumeClaim:
claimName: pg-data-claim
Thanks to all those who helped me :)
does your custom postgresql persist data at /var/lib/postgresql/data?
are you able to get logs from your postgresql container and spot anything interesting?
when your pod is running, can you see the mountpoints inside your container and check the persistent disk is there?
I followed this scenario and I was able to persist my data by changing the mountPath to /var/lib/postgresql and also reproduced using cassandra (i.e. /var/lib/cassandra for mountPath)
I was able to delete/restart pods from different nodes/hosts and still see my "users" table and the data I previously entered. However, I was not using a custom image, I just used standard docker images.