Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • kubernetes-workshop/python-django-template
  • aghozlan/python-django-template
  • tru/python-django-template
3 results
Select Git revision
  • master
1 result
Show changes
Commits on Source (22)
.PHONY: all
all: build push docker_token template deploy
.PHONY: build
build:
docker build -t ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} .
docker tag ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:latest
.PHONY: push
push: build
docker push -- ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls
.PHONY: docker_token
docker_token:
kubectl delete secret registry-gitlab -n ${NAMESPACE} --ignore-not-found=true
kubectl create secret docker-registry -n ${NAMESPACE} registry-gitlab --docker-server=registry-gitlab.pasteur.fr --docker-username=${DEPLOY_USER} --docker-password=${DEPLOY_TOKEN} --docker-email=kubernetes@pasteur.fr
.PHONY: template
template:
envsubst <polls.yaml >> deploy.yaml
.PHONY: deploy
deploy: build template push
kubectl apply -n ${NAMESPACE} -f deploy.yaml
.PHONY: update
update:
kubectl patch deployment -n ${NAMESPACE} polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
.PHONY: delete
delete:
kubectl delete deployment -n ${NAMESPACE} polls
kubectl delete service -n ${NAMESPACE} polls
kubectl delete ingress -n ${NAMESPACE} polls
...@@ -19,6 +19,24 @@ In order to deploy this app on Kubernetes we will need to complete the following ...@@ -19,6 +19,24 @@ In order to deploy this app on Kubernetes we will need to complete the following
* Define a URL in order to access to your application * Define a URL in order to access to your application
* Setup Gitlab CI in order to define the Continuous Delivery (CD) * Setup Gitlab CI in order to define the Continuous Delivery (CD)
## Pre-requisits
### On your computer
* Git ust be installed
* Nice to have : a code editor (Atom, Visual Studio code ....)
* Connected to Pasteur VPN (or you won't be able to use all the tools)
### Gitlab
If you have never used Gitlab before, you will need to add an `ssh key` in your profile or define `HTTP` password in order to fetch the git repository.
Use basic git command :
```
git add .
git commit -m 'My comment'
git push
```
## Step by step guide ## Step by step guide
### Create Docker Registry Access Token ### Create Docker Registry Access Token
...@@ -59,74 +77,99 @@ FROM python:3 ...@@ -59,74 +77,99 @@ FROM python:3
# Here we update the image and add python3 virtualenv # Here we update the image and add python3 virtualenv
RUN apt-get update && apt-get upgrade -y && apt-get install \ RUN apt-get update && apt-get upgrade -y && apt-get install \
-y --no-install-recommends python3 virtualenv -y --no-install-recommends python3
# Create a virtualenv for the application dependencies.
# # If you want to use Python 2, use the -p python2.7 flag.
RUN virtualenv -p python3 /env
ENV PATH /env/bin:$PATH
# Install pip dependencies # Install pip dependencies
ADD requirements.txt /app/requirements.txt ADD requirements.txt /app/requirements.txt
RUN /env/bin/pip install --upgrade pip && /env/bin/pip install -r /app/requirements.txt RUN pip install --default-timeout=100 --upgrade pip && pip install -r /app/requirements.txt
# We add the current content of the git repo in the /app directory # We add the current content of the git repo in the /app directory
ADD . /app ADD . /app
WORKDIR /app
RUN rm -rf .gitlab-ci.yml Dockerfile README.md img solution
# We use the CMD command to start the gunicorn daemon # We use the CMD command to start the gunicorn daemon
# when we start the container. # when we start the container.
# Note the $PORT variable, we will need to define it when we start the container # Note the $PORT variable, we will need to define it when we start the container
CMD gunicorn -b :$PORT mysite.wsgi CMD python manage.py runserver 0.0.0.0:$PORT
``` ```
### Setup Gitlab CI ### Setup Gitlab CI
At the root of your git repository create a `.gitlab-ci.yaml` file. At the root of your git repository create a `.gitlab-ci.yml` file.
> Name it correctly `.gitlab-ci.yml` and not `.gitlab-ci.yaml` !
We will use a special docker image which contain the docker binary. We will use a special docker image which contain the docker binary, we build a docker in a docker :-)
We will attach to the running docker daemon in order to build the image.
What do we do here ?
* We login on the docker registry enbended in Gitlab (a docker registry is the place where we store docker images to redistribute them)
* We build the docker image and we add a `tag`to it (actually the id of the git commit)
* We tag the previously builded docker image with a special tag `latest` (this can be sometime usefull)
* We push the image to the docker registry
```yaml ```yaml
stages: stages:
- build - build
- deploy - deploy
variables:
DOCKER_HOST: tcp://localhost:2375/
services: services:
- docker:dind - docker:dind
variables:
DOCKER_HOST: tcp://localhost:2375
build: build:
image: docker:latest image: docker:latest
stage: build stage: build
script: script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build -t ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} . - docker build -t "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" .
- docker tag ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:latest - docker tag "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:latest"
- docker push -- ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls - docker push "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}"
tags: tags:
- k8s - k8s
``` ```
Save, commit and push; you should be abble to see your first running pipeline Save, commit and push; you should be abble to see your first running pipeline
> For those not familiar with `git` you can just do the following in a terminal
```
git add .
git commit -m 'My comment'
git push
```
![alt text](img/ci_pipeline.png) ![alt text](img/ci_pipeline.png)
Once succesfully completed, you can see the docker image in the `Registry`section on the left pane. Once succesfully completed, you can see the docker image in the `Registry`section on the left pane.
### Create manifest yaml file ### Create manifests yaml files
In order to deploy your application on Kubernetes we need to define how to deploy :
* What is the source of the image ?
* Do I need parameters in order to configure my application ?
* Do I need some storage ?
* What will be it's name ?
* Do I have some "secure" information ? (login, password...)
* What would be it's dns name ?
....
So we are going to create manifest files at the root directory of your git repository and fill it with the following definition.
Create a file `manifest.yaml` at the root directory of your git repository and fill it with the following definition.
> Keep in mind that yaml formating require that you seperate each declaration with `---` line. > Keep in mind that yaml formating require that you seperate each declaration with `---` line.
#### PostgreSQL Server #### PostgreSQL Server
> Create the `postgresql.yaml` file at the root directory of your project
In order to deploy a Postgresql server we need : In order to deploy a Postgresql server we need :
- [ ] Storage - [ ] Storage
- [ ] Configuration - [ ] Configuration
- [ ] Secrets (passwords....)
- [ ] Deployment - [ ] Deployment
- [ ] Service - [ ] Service (Load balancing even if it's for one Pod)
##### Persistent Volume Claim ##### Persistent Volume Claim
...@@ -135,6 +178,7 @@ As a Docker image is immutable, you may need to define some persistent storage. ...@@ -135,6 +178,7 @@ As a Docker image is immutable, you may need to define some persistent storage.
We do this using a `Persistent Volume Claim`. We do this using a `Persistent Volume Claim`.
> You can see that we define an `accessModes`to `ReadWriteOnce`, this mean that the Persistent Volume will only be accessed by one container. > You can see that we define an `accessModes`to `ReadWriteOnce`, this mean that the Persistent Volume will only be accessed by one container.
> Insert this in the `postgresql.yaml` file :
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
...@@ -158,6 +202,7 @@ We are here defining the PostgreSQL basic parameters : username, password and da ...@@ -158,6 +202,7 @@ We are here defining the PostgreSQL basic parameters : username, password and da
![alt text](img/base64.png) ![alt text](img/base64.png)
> Insert this in the `postgresql.yaml` file with `---` line before
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
...@@ -166,20 +211,25 @@ name: postgresql-credentials ...@@ -166,20 +211,25 @@ name: postgresql-credentials
type: Opaque type: Opaque
data: data:
username: cG9sbHNfdXNlcgo= username: cG9sbHNfdXNlcgo=
password: c2xsb3BfYzNiaQo= password: cG9sbHMK
database: cG9sbHMK database: cG9sbHMK
``` ```
##### PostgreSQL Deployment ##### PostgreSQL Deployment
> Insert this in the `postgresql.yaml` file with `---` line before
```yaml ```yaml
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: postgresql name: postgresql
labels: labels:
app: postgresql app: postgresql
spec: spec:
replicas: 1
selector:
matchLabels:
app: postgresql
strategy: strategy:
type: Recreate type: Recreate
template: template:
...@@ -189,8 +239,8 @@ template: ...@@ -189,8 +239,8 @@ template:
tier: postgreSQL tier: postgreSQL
spec: spec:
containers: containers:
- image: postgres:9.6.2-alpine - name: postgresql
name: postgresql image: postgres:9.6.2-alpine
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
valueFrom: valueFrom:
...@@ -210,6 +260,13 @@ template: ...@@ -210,6 +260,13 @@ template:
ports: ports:
- containerPort: 5432 - containerPort: 5432
name: postgresql name: postgresql
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
volumeMounts: volumeMounts:
- name: postgresql - name: postgresql
mountPath: /var/lib/postgresql/data mountPath: /var/lib/postgresql/data
...@@ -220,11 +277,12 @@ template: ...@@ -220,11 +277,12 @@ template:
claimName: postgres-claim claimName: postgres-claim
- name: postgresql-credentials - name: postgresql-credentials
secret: secret:
secretName: postgresql secretName: postgresql-credentials
``` ```
##### PostgreSQL Service ##### PostgreSQL Service
> Insert this in the `postgresql.yaml` file with `---` line before
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
...@@ -238,33 +296,38 @@ ports: ...@@ -238,33 +296,38 @@ ports:
selector: selector:
app: postgresql app: postgresql
tier: postgreSQL tier: postgreSQL
```` ```
#### Django Application #### Django Application
##### Deployment
> Create `polls.yaml` file
##### Deployment
> Insert this in the `polls.yaml` file
```yaml ```yaml
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: polls name: polls
labels: labels:
app: polls app: polls
spec: spec:
replicas: 3 replicas: 1
selector:
matchLabels:
app: polls
template: template:
metadata: metadata:
labels: labels:
app: polls app: polls
spec: spec:
containers: containers:
name: polls-app - name: polls-app
image: ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
# This setting makes nodes pull the docker image every time before
# starting the pod. This is useful when debugging, but should be turned
# off in production.
imagePullPolicy: Always imagePullPolicy: Always
env: env:
- name: DATABASE_HOST
value: postgresql
- name: DATABASE_NAME - name: DATABASE_NAME
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
...@@ -280,16 +343,28 @@ template: ...@@ -280,16 +343,28 @@ template:
secretKeyRef: secretKeyRef:
name: postgresql-credentials name: postgresql-credentials
key: password key: password
- name: PORT
value: "8080"
ports: ports:
- containerPort: 8080 - containerPort: 8080
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
imagePullSecrets:
- name: registry-gitlab
volumes: volumes:
- name: postgresql-credentials - name: postgresql-credentials
secret: secret:
secretName: postgresql secretName: postgresql-credentials
``` ```
##### Service ##### Service
> Insert this in the `polls.yaml` file with `---` line before
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
...@@ -300,14 +375,14 @@ labels: ...@@ -300,14 +375,14 @@ labels:
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:
- port: 80 - port: 8080
targetPort: 8080
selector: selector:
app: polls app: polls
``` ```
##### Ingress Resource ##### Ingress Resource
> Insert this in the `polls.yaml` file with `---` line before
```yaml ```yaml
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
kind: Ingress kind: Ingress
...@@ -319,21 +394,25 @@ labels: ...@@ -319,21 +394,25 @@ labels:
name: polls name: polls
spec: spec:
rules: rules:
- host: https://${CI_PROJECT_NAME}.k8s-dev.pasteur.fr - host: ${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}.k8s-dev.pasteur.fr
http: http:
paths: paths:
- backend: - backend:
serviceName: polls serviceName: polls
servicePort: 80 servicePort: 8080
path: / path: /
``` ```
##### Kubernetes Job ##### Kubernetes Job
Create a file `job.yaml` at the root directory of your git repository and fill it with the following definition.
We will use a `Job` in order to manage django migrations. We will use a `Job` in order to manage django migrations.
> Note: Kubernetes jobs are run only once opposed to `Deployments` that run continiously. > Note: Kubernetes jobs are run only once opposed to `Deployments` that run continiously. We put it in a seperate file because a Job is immutable and cannot be updated.
> Insert this in the `job.yaml` file
```yaml ```yaml
---
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
...@@ -343,9 +422,12 @@ template: ...@@ -343,9 +422,12 @@ template:
spec: spec:
containers: containers:
- name: django - name: django
image: ${CI_REGISTRY}/${CI_PROJECT_NAME}/polls:${CI_COMMIT_SHORT_SHA} image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
command: ['python', 'manage.py', 'migrate'] command: ["/bin/sh","-c"]
args: ["python manage.py makemigrations && python manage.py migrate"]
env: env:
- name: DATABASE_HOST
value: postgresql
- name: DATABASE_NAME - name: DATABASE_NAME
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
...@@ -362,38 +444,93 @@ template: ...@@ -362,38 +444,93 @@ template:
name: postgresql-credentials name: postgresql-credentials
key: password key: password
restartPolicy: Never restartPolicy: Never
imagePullSecrets:
- name: registry-gitlab
volumes:
- name: postgresql-credentials
secret:
secretName: postgresql-credentials
backoffLimit: 5 backoffLimit: 5
``` ```
### Setup Continuous Delivery in Gitlab CI ### Setup Continuous Delivery in Gitlab CI
> Insert this in the `.gitlab-ci.yml` file after the previous part (docker build)
```yaml ```yaml
deploy: deploy:
stage: deploy stage: deploy
image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image
variables: variables:
NAMESPACE: "mynamespace" NAMESPACE: ${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}
environment: environment:
name: mynamespace name: ${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}
url: https://${CI_PROJECT_NAME}.k8s-dev.pasteur.fr url: https://${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}.k8s-dev.pasteur.fr
script: script:
- kubectl delete secret registry-gitlab -n ${NAMESPACE} --ignore-not-found=true - kubectl delete secret registry-gitlab -n ${NAMESPACE} --ignore-not-found=true
- kubectl create secret docker-registry -n ${NAMESPACE} registry-gitlab --docker-server=registry-gitlab.pasteur.fr --docker-username=${DEPLOY_USER} --docker-password=${DEPLOY_TOKEN} --docker-email=kubernetes@pasteur.fr - kubectl create secret docker-registry -n ${NAMESPACE} registry-gitlab --docker-server=registry-gitlab.pasteur.fr --docker-username=${DEPLOY_USER} --docker-password=${DEPLOY_TOKEN} --docker-email=kubernetes@pasteur.fr
- envsubst < polls.yaml | kubectl apply -f - - envsubst < postgresql.yaml | kubectl apply -n ${NAMESPACE} -f -
- kubectl wait --for=condition=available --timeout=600s deployment/postgresql
- kubectl delete job polls-migrations -n ${NAMESPACE} --ignore-not-found=true
- envsubst < job.yaml | kubectl apply -n ${NAMESPACE} -f -
- kubectl wait --for=condition=complete --timeout=600s job/polls-migrations
- envsubst < polls.yaml | kubectl apply -n ${NAMESPACE} -f -
- kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}" - kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
tags: tags:
- k8s - k8s
``` ```
### Take a look at your Gitlab CI pipeline
If everything goes well, you should see that you have a pipeline with two steps:
- build
- deploy
You can see the log output by clicking on each one
### Informations available in Gitlab
Gitlab offer a basic set of features in order to manage your Kubernetes web application.
In the `Operations` section on the left panel you are able to view :
* Metrics : It will display basic memory and cpu graphs
* Environements : It will list all the environements you have created (you can have several deploy stages in your `.gitlab-ci.yml` : dev, stagging, production....) and give direcrt access to :
* Website link
* Monitoring
* Open a remote shell on the container
* Error Tracking : If your application implement error tracking on [sentry]: https://sentry.io/ errors are displayed here.
* Serverless : Feature not available here at Pasteur
## What else ? ## What else ?
### Is my deployed application is working ?
Now we want to know if what we have done is working; to do that just go in `Operations/Environements` and click on the first icon on the right hand side, it should open your web app.
You may have a `404 page not found` error, that's can be unfortunately normal for the first deployement, all you have to do is to restart the deploy job in the CI section of your gitlab project.
### Kubernetes dashboard ### Kubernetes dashboard
#### View your running workload
> We provide a web interface to visualise your workloads you have access to, you can connect to https://console.k8s-dev.pasteur.fr and follow the login process. On the left panel, you will find a drop down list and select your namespace. You will be able to view your Deployements, Pods, Services and so on.
#### Increase the number of replicas #### Increase the number of replicas
If you want to increase the number of replicas of your web application, you can go in the Deployement section and select the 3 dots on the `polls` line; select `Scale`. You can increase or decrease the number of replicas. Kubernetes will automaticaly add or remove Pods.
> You can also update the file `polls.yaml` to change the replicas value (by default 1)
> Kubernetes will automatically load balance the traffic to the n PODS.
#### What happen if I kill a Pod ? #### What happen if I kill a Pod ?
You can try to `Delete` the polls `Pod` using the 3 dots icon and see that Kubernetes will automaticaly restart a new one.
### Grafana : Metrics and Logs ### Grafana : Metrics and Logs
You can log on https://grafana.k8s-dev.pasteur.fr/ and browse the various dashboard available.
### Best Practices ### Best Practices
Always use Gitlab
\ No newline at end of file You git repository must be the source of truth, never change something directly on Kubernetes that needs to be persistent.
Integrate Kubernetes at the beginning of your project, you'll waste less time.
...@@ -82,10 +82,10 @@ DATABASES = { ...@@ -82,10 +82,10 @@ DATABASES = {
# If you are using Cloud SQL for MySQL rather than PostgreSQL, set # If you are using Cloud SQL for MySQL rather than PostgreSQL, set
# 'ENGINE': 'django.db.backends.mysql' instead of the following. # 'ENGINE': 'django.db.backends.mysql' instead of the following.
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.postgresql',
'NAME': 'polls', 'NAME': os.getenv('DATABASE_NAME'),
'USER': os.getenv('DATABASE_USER'), 'USER': os.getenv('DATABASE_USER'),
'PASSWORD': os.getenv('DATABASE_PASSWORD'), 'PASSWORD': os.getenv('DATABASE_PASSWORD'),
'HOST': os.getenv('DATABASE_NAME'), 'HOST': os.getenv('DATABASE_HOST'),
'PORT': '5432', 'PORT': '5432',
} }
} }
......
Django==2.1.5 Django==2.1.5
mysqlclient==1.4.1
wheel==0.32.3 wheel==0.32.3
gunicorn==19.9.0
psycopg2==2.7.7 psycopg2==2.7.7
...@@ -2,6 +2,9 @@ stages: ...@@ -2,6 +2,9 @@ stages:
- build - build
- deploy - deploy
variables:
DOCKER_HOST: tcp://localhost:2375/
services: services:
- docker:dind - docker:dind
...@@ -13,20 +16,26 @@ build: ...@@ -13,20 +16,26 @@ build:
- docker build -t "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" . - docker build -t "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" .
- docker tag "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:latest" - docker tag "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:latest"
- docker push "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}" - docker push "$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}"
tags:
- k8s
deploy: deploy:
stage: deploy stage: deploy
image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image
variables: variables:
NAMESPACE: "tmenard-django" NAMESPACE: ${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}
environment: environment:
name: tmenard-django name: ${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}
url: https://tmenard-django.k8s-dev.pasteur.fr url: https://${GITLAB_USER_LOGIN}-${CI_PROJECT_NAME}.k8s-dev.pasteur.fr
script: script:
- yum install -y gettext
- kubectl delete secret registry-gitlab -n ${NAMESPACE} --ignore-not-found=true - kubectl delete secret registry-gitlab -n ${NAMESPACE} --ignore-not-found=true
- kubectl create secret docker-registry -n ${NAMESPACE} registry-gitlab --docker-server=registry-gitlab.pasteur.fr --docker-username=${DEPLOY_USER} --docker-password=${DEPLOY_TOKEN} --docker-email=kubernetes@pasteur.fr - kubectl create secret docker-registry -n ${NAMESPACE} registry-gitlab --docker-server=registry-gitlab.pasteur.fr --docker-username=${DEPLOY_USER} --docker-password=${DEPLOY_TOKEN} --docker-email=kubernetes@pasteur.fr
- envsubst < manifest.yaml - envsubst < postgresql.yaml | kubectl apply -n ${NAMESPACE} -f -
- envsubst < manifest.yaml | kubectl apply -f - - kubectl wait --for=condition=available --timeout=600s deployment/postgresql
- kubectl delete job polls-migrations -n ${NAMESPACE} --ignore-not-found=true
- envsubst < job.yaml | kubectl apply -n ${NAMESPACE} -f -
- kubectl wait --for=condition=complete --timeout=600s job/polls-migrations
- envsubst < polls.yaml | kubectl apply -n ${NAMESPACE} -f -
- kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}" - kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
tags:
- k8s
...@@ -14,10 +14,17 @@ RUN apt-get update && apt-get upgrade -y && apt-get install \ ...@@ -14,10 +14,17 @@ RUN apt-get update && apt-get upgrade -y && apt-get install \
ADD requirements.txt /app/requirements.txt ADD requirements.txt /app/requirements.txt
RUN pip install --default-timeout=100 --upgrade pip && pip install -r /app/requirements.txt RUN pip install --default-timeout=100 --upgrade pip && pip install -r /app/requirements.txt
RUN addgroup --gid 1001 django && \
useradd --uid 1001 --gid 1001 django
# We add the current content of the git repo in the /app directory # We add the current content of the git repo in the /app directory
ADD . /app ADD . /app
WORKDIR /app
RUN rm -rf .gitlab-ci.yml Dockerfile README.md img RUN rm -rf .gitlab-ci.yml Dockerfile README.md img
# We use the CMD command to start the gunicorn daemon # We use the CMD command to start the gunicorn daemon
# when we start the container. # when we start the container.
# Note the $PORT variable, we will need to define it when we start the container # Note the $PORT variable, we will need to define it when we start the container
USER django
CMD python manage.py runserver 0.0.0.0:$PORT CMD python manage.py runserver 0.0.0.0:$PORT
---
apiVersion: batch/v1
kind: Job
metadata:
name: polls-migrations
spec:
template:
spec:
containers:
- name: django
image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
command: ["/bin/sh","-c"]
args: ["python manage.py makemigrations && python manage.py migrate"]
env:
- name: DATABASE_HOST
value: postgresql
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: database
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: password
restartPolicy: Never
imagePullSecrets:
- name: registry-gitlab
volumes:
- name: postgresql-credentials
secret:
secretName: postgresql-credentials
backoffLimit: 10
apiVersion: apps/v1
kind: Deployment
metadata:
name: polls
labels:
app: polls
spec:
replicas: 1
selector:
matchLabels:
app: polls
template:
metadata:
labels:
app: polls
spec:
containers:
- name: polls-app
image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
imagePullPolicy: Always
env:
- name: DATABASE_HOST
value: postgresql
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: database
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: password
- name: PORT
value: "8080"
ports:
- containerPort: 8080
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
imagePullSecrets:
- name: registry-gitlab
volumes:
- name: postgresql-credentials
secret:
secretName: postgresql-credentials
---
apiVersion: v1
kind: Service
metadata:
name: polls
labels:
app: polls
spec:
type: ClusterIP
ports:
- port: 8080
selector:
app: polls
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
labels:
app: polls
name: polls
spec:
rules:
- host: ${GITLAB_USER_LOGIN}.k8s-dev.pasteur.fr
http:
paths:
- backend:
serviceName: polls
servicePort: 8080
path: /
...@@ -63,6 +63,13 @@ spec: ...@@ -63,6 +63,13 @@ spec:
ports: ports:
- containerPort: 5432 - containerPort: 5432
name: postgresql name: postgresql
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
volumeMounts: volumeMounts:
- name: postgresql - name: postgresql
mountPath: /var/lib/postgresql/data mountPath: /var/lib/postgresql/data
...@@ -87,115 +94,3 @@ spec: ...@@ -87,115 +94,3 @@ spec:
selector: selector:
app: postgresql app: postgresql
tier: postgreSQL tier: postgreSQL
\ No newline at end of file
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: polls
labels:
app: polls
spec:
replicas: 1
selector:
matchLabels:
app: polls
template:
metadata:
labels:
app: polls
spec:
containers:
- name: polls-app
image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
imagePullPolicy: Always
env:
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: database
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: password
- name: PORT
value: "8080"
ports:
- containerPort: 8080
imagePullSecrets:
- name: registry-gitlab
volumes:
- name: postgresql-credentials
secret:
secretName: postgresql-credentials
---
apiVersion: v1
kind: Service
metadata:
name: polls
labels:
app: polls
spec:
type: ClusterIP
ports:
- port: 8080
selector:
app: polls
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
labels:
app: polls
name: polls
spec:
rules:
- host: ${CI_PROJECT_NAME}.k8s-dev.pasteur.fr
http:
paths:
- backend:
serviceName: polls
servicePort: 8080
path: /
---
apiVersion: batch/v1
kind: Job
metadata:
name: polls-migrations
spec:
template:
spec:
containers:
- name: django
image: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/polls:${CI_COMMIT_SHORT_SHA}
command: ['python', 'manage.py', 'migrate']
env:
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: database
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-credentials
key: password
restartPolicy: Never
volumes:
- name: postgresql-credentials
secret:
secretName: postgresql
backoffLimit: 5