Table of Contents
Development Environment
1. Preparing K8S dev
- Setup with cookie-cutter:
1.1 Create project from cookiecutter-django template
Create virtual env
python3 -m venv project_venv source project_venv/bin/activate pip install cookiecutter
Create new project from template:
cookiecutter https://github.com/pydanny/cookiecutter-django.git
Follow cookiecutter-django docs https://cookiecutter-django.readthedocs.io/en/3.0.5-01/project-generation-options.html
1.2 Use minikube docker-env
Make sure minikube is started:
docker info | grep Name Name: localhost.localdomain
Localhost docker context is activated so start minikube:
minikube start --vm-driver=kvm2 --memory='4g'
Using minikube docker context (for each bash console):
eval $(minikube docker-env) docker info | grep Name Name: minikube
1.3 Quick troubleshooting
Logs:
docker-compose -f local.yml logs
Cleanup.
docker stop $(docker ps -a -q)
Remove volume mount and images.
docker-compose -f local.yml down --rmi all -v
docker builder prune docker system prune -a docker-compose -f local.yml build docker-compose -f local.yml up
Local development
1. Build project with docker
Build project:
docker-compose -f local.yml build
Start containers:
docker-compose -f local.yml up
Output from the containers
django | INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) node | [Browsersync] Proxying: http://django:8000 node | [Browsersync] Access URLs: node | ----------------------------------- node | Local: http://localhost:3000 node | External: http://172.19.0.9:3000 node | ----------------------------------- node | UI: http://localhost:3001 node | UI External: http://localhost:3001 node | -----------------------------------
2. Accessing the web page
The containers are started on docker host, which is seen by the containers as localhost. If local docker is used the host ports are forwarded to the containers so localhost 127.0.0.1 is used to access the web page. If minikube docker context is used. We need to figure out the minikube host IP:
kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready master 42h v1.16.2 192.168.39.208 <none> Buildroot 2019.02.6 4.19.76 docker://18.9.9
In this example 192.168.39.208 is the docker host IP. Add this to Django ALLOWED HOSTS.
3. Run command inside the containers
As with any shell command that we wish to run in our container, this is done using the docker-compose -f local.yml run –rm command:
docker-compose -f local.yml run --rm django python manage.py migrate docker-compose -f local.yml run --rm django python manage.py createsuperuser
Run interactive shell:
docker exec -ti django /bin/bash
4. How the containers interact
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a8a9de7b744c django_maxo36_local_node "docker-entrypoint.s…" 31 minutes ago Up 31 minutes 0.0.0.0:3000-3001->3000-3001/tcp node 84204e207978 django_maxo36_local_django "/entrypoint /start" 31 minutes ago Up 31 minutes 0.0.0.0:8000->8000/tcp django 3413c2e66f7f django_maxo36_local_celeryworker "/entrypoint /start-…" 31 minutes ago Up 31 minutes celeryworker d83d03753d78 django_maxo36_local_flower "/entrypoint /start-…" 31 minutes ago Up 31 minutes 0.0.0.0:5555->5555/tcp flower 148ba234b996 django_maxo36_local_celerybeat "/entrypoint /start-…" 31 minutes ago Up 31 minutes celerybeat 0771470a42ce django_maxo36_production_postgres "docker-entrypoint.s…" 18 hours ago Up 31 minutes 5432/tcp postgres 41cad252130a mailhog/mailhog:v1.0.0 "MailHog" 18 hours ago Up 31 minutes 1025/tcp, 0.0.0.0:8025->8025/tcp mailhog ba5e14f8a6a5 redis:5.0 "docker-entrypoint.s…" 18 hours ago Up 31 minutes 6379/tcp redis
5. Volume mount to minikube
Using local docker context we can mount host folders to docker image. This is useful for developing cloud native apps because we don't need to copy source code and rerun container build when the code is updated. Local folder can be mounted as following.
For docker run:
docker run \ --rm \ -it \ --mount \ type=bind,\ source="$(pwd)",\ target="/app" \ django_maxo36_local_django:latest
For docker-compose:
version: '3'
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
services:
django: &django
build:
context: .
dockerfile: ./compose/local/django/Dockerfile
image: django_maxo36_local_django
container_name: django
depends_on:
- postgres
- mailhog
volumes:
# path to source minikube/docker local-path mount
# https://stackoverflow.com/questions/48534980/mount-local-directory-into-pod-in-minikube
- .:/app <------- THIS IS IT
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
ports:
- "8000:8000"
command: /start
The current folder will be mounted as /app in the container. This however only works with local docker context. If the folder should be mounted on a remote docker host or e.g., minikube VM, we need a different way to sync local folders.
5.1 Option 1
For minikube, we can mount the local folder on minikube at a defaul localtion in the minikube VM and use hostPath to mount the VM folder location to the pod / container deployed with minikube docker context.
First, mounting local folder to minikube:
minikube start --mount-string /<host-directory-path>:/<desired-minikube-directory-path> --mount
For an already running minikube you can do the following:
nohup minikube mount /<host-directory-path>:/<desired-minikube-directory-path> &
By default minikube already mount homeDir to the VM:
- on Mac it mounts dir of all users - /Users
- on Linux and Windows just the home of current user - homedir.HomeDir()
The definition of the HomeDir() is: https://godoc.org/k8s.io/client-go/util/homedir
You can always do minikube ssh into the Minikube VM and explore it:
minikube ssh df -hl Filesystem Size Used Avail Use% Mounted on ... /Users 466G 442G 25G 95% /Users
Now we can mount the folder on VM to the pod:
apiVersion: v1
kind: Service
...
---
apiVersion: apps/v1
kind: Deployment
...
spec:
replicas: 1
...
template:
...
spec:
containers:
...
volumeMounts:
- name: someName
mountPath: /<desired-minikube-directory-path>
...
volumes:
- name: someName
hostPath:
path: /<desired-minikube-directory-path>
Or use the VM path in docker-compose yaml.
More information here
5.2 Option 2 - Mutagen.io
The previous approach depends on docker host's local folder, e.g., minikube mount. There are tools to allow syncing directly a local folder with remote pod or containers:
- ksync
- docker-sync
- Mutagen
We will try Mutagen.
5.2.1 Mutagen Design
Mutagen is designed and operated around the concept of individual synchronization and forwarding sessions. Each session operates between two endpoints. In the case of synchronization, these endpoints are file system locations, and in the case of forwarding, these endpoints are network endpoints. What makes Mutagen uniquely powerful is that sessions can combine any pair of endpoints, regardless of their location or access mechanism.
Common usage scenarios include synchronizing source code from your laptop to a remote server or container, or forwarding requests from local TCP endpoints to remote web servers. But Mutagen can also do things like synchronize files between two remote filesystems using the local system as a proxy, or perform reverse tunneling from a remote system to a service running on your laptop. If you have a problem where you need to synchronize files efficiently or forward network traffic flexibly, then Mutagen can most likely be used to solve it.
5.2.2 Installation
wget https://github.com/mutagen-io/mutagen/releases/download/v0.11.4/mutagen_linux_amd64_v0.11.4.tar.gz tar -xvzf mutagen_linux_amd64_v0.11.4.tar.gz mutagen mutagen-agents.tar.gz sudo mv mutagen mutagen-agents.tar.gz /usr/local/bin
It is important to keep the mutagen-agent tar in the same location as mutagen binary. The agent will be extracted and injected to remote container.
5.2.3 Usage
Note: Docker container must be started with the first version of the code first. I.e., Django src must be copied in order for the container to be started.
Create sync session between localhost and docker host
mutagen sync create --name=web-app-code ~/src docker://[<user>@]<container>/<path>
The <user> component is optional and tells Mutagen to act as the specified user inside the container. If unspecified, Mutagen uses the default container user (usually root for Linux containers or ContainerAdministrator for Windows containers).
The <container> component can specify any type of container identifier understood by docker cp and docker exec (for example, a container name or hexidecimal identifier).
Note: named local volume should be used for persisted files across docker (compose) run.
Example, for the following docker-compose yaml we will create mutagen sync session:
code
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
local_django_app: {}
local_node_app: {}
services:
django: &django
build:
context: .
dockerfile: ./compose/local/django/Dockerfile
image: django_maxo36_local_django
container_name: django <--- Mutagen docker transport
depends_on:
- postgres
- mailhog
volumes:
# path to source minikube/docker local-path mount
# https://stackoverflow.com/questions/48534980/mount-local-directory-into-pod-in-minikube
- local_django_app:/app <--- LOCAL and mount point
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
ports:
- "8000:8000"
command: /start
Creating mutagen sync:
mutagen sync create --ignore-vcs --name=maxo36-django-src . docker://django/app Created session sync_6RvzLrjeAz21vecYh1WwlcAA2d0hh2V2tKTeEoChFiB
Managing session:
mutagen sync list
--------------------------------------------------------------------------------
Name: maxo36-django-src
Identifier: sync_6RvzLrjeAz21vecYh1WwlcAA2d0hh2V2tKTeEoChFiB
Labels: None
Alpha:
URL: /data/workspace/73_maxo36/django_maxo36
Connection state: Connected
Beta:
URL: docker://django/app
DOCKER_HOST=tcp://192.168.39.208:2376
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/home/dang/.minikube/certs
Connection state: Connected
Status: Watching for changes
mutagen sync [monitor|pause|resume|flush|reset|terminate] maxo36-django-src
5.2.4 Mutagen ignore
Some problems caused by syncing dot folder, e.g., git. Using –ignore-vcs flag to the create command and on a default basis by including the following configuration in ~/.mutagen.yml:
sync:
defaults:
ignore:
vcs: true
Check:
docker-compose -f local.yml run --rm django bash
5.2.5 Conflict resolution for synced files
Conflicts (which can occur in two-way-safe and one-way-safe modes) can be resolved manually by deleting the content on the endpoint which you wish to have lose the conflict. Once deleted, the conflict will no longer exist since deletions can be overwritten.
docker-compose -f local.yml run --rm django bash rm config/settings/local.py
Mutagen will copy local file to django container.
5.2.6 Rebuild images
Trying to update an existing volume with the contents from a new image does not work.
https://docs.docker.com/engine/tutorials/dockervolumes/#/data-volumes
States:
Changes to a data volume will not be included when you update an image.
In case update to setting make django failed to start (so mutagen can not sync), we need to rebuild image from scratch. This is not working:
docker-compose -f local.yml build --no-cache django
Because named volumes are not removed when rebuilding images, we have to remove the volumes first:
docker-compose -f local.yml down --rmi all -v \ && docker-compose build --no-cache \ && docker-compose -f docker-compose-staging.yml up -d --force-recreate
5.2.7 Similar tools
5.2.8 others
-
5.2.9 CI/CD
-
5.2.9.1 Chat CI CD tools
<code> Sa Pham2:12 PM chắc quen với TF hơn
) ĐẠI ĐẶNG VĂN2:13 PM mình dùng heat openstack nên nhìn quen quen Cloudformation hơn :v Trinh Nguyen2:13 PM
Công Hà Minh2:16 PM Teraform có vẻ gọn gàng dễ đọc hơn Cloud Formation nhỉ các bác. Sa Pham2:17 PM TF ngon hơn Heat :D Công Hà Minh2:19 PM Heat Template dài như cái sớ luôn :( Trinh Nguyen2:22 PM Nice Sa Pham2:25 PM Vậy dev care luôn hạ tầng nhỉ :D ĐẠI ĐẶNG VĂN2:25 PM Hoặc ông hạ tầng phải biết dev :v Công Hà Minh2:26 PM Cái CDK này vẫn phải học xem từng class có ý nghĩa gì, mỗi method trong class có những tham số gì, ý nghĩa của từng tham số là gì các bác nhỉ? Trinh Nguyen2:27 PM kiểu easy hơn nhiều Công à. VD: var loadbalancer = cdk.lb(…) Minh Luân Trần2:27 PM lát có nói về cdktf không luôn vậy mấy bro Sa Pham2:29 PM cho em hỏi là nếu như này thì ở trong code mình có gọi đc thông tin của infras ko ?
Ví dụ tạo db aurora, xong trong code mình import cái CDK để lấy connection string tới DB ?
Cuong Quach Chi2:30 PM
cái Sa hỏi giống “data source” của TF nhỉ
Trinh Nguyen2:32 PM
CDKtf của Luân kìa
nam cxn2:32 PM
session sau không có gì hết )
ĐẠI ĐẶNG VĂN2:32 PM
))
Minh Luân Trần2:32 PM
ngon lành :D
Sa Pham2:34 PM
cái CDKTF thì provider có phải làm gì ko nhỉ? ví dụ bên em phát triển provider cho TF thì có cần thay đổi gì ko để làm việc đc với CDK? hay do nothing :D
Trinh Nguyen2:34 PM
do nothing
Sa Pham2:34 PM
xịn
Trinh Nguyen2:34 PM
cdktf gen ra tf script thôi
Minh Luân Trần2:35 PM
cdk thì only cho aws thôi nhỉ, còn private hay custom thì cdktf
))
Trinh Nguyen2:35 PM
Dùng CDKTF thì làm multicloud
Quang Minh Phạm2:37 PM
cả 2 bạn ơi
))
Minh Luân Trần2:40 PM
em love teraform nhưng ghét python thì sao :1))
Sa Pham2:41 PM
phát triển cái CDK riêng cho ngôn ngữ mình yêu thích
Cuong Quach Chi2:41 PM
nếu mốt CDK phát triển ngon rồi, thì làm sao implement CDK vào quản lý TF code đang có nhỉ :3 . Có vẻ pain in ass :o
nam cxn2:42 PM
bấm nút trên giao diện cho kẻ mạnh mà, terraform làm gì
Sa Pham2:42 PM
terraform destroy → deploy a new one
Minh Luân Trần2:42 PM
em thấy thì cdk generate TF thôi
import của TF vẫn còn đó mà :D
Cuong Quach Chi2:43 PM
đi import lại thì khá là pain in ass again
:v
hy vọng Hashicorp có plan strategy support migrate hoặc implement integration
Minh Luân Trần2:45 PM
thôi thì kêu customer ngưng xài vài bữa :D
đập đi xây lại
Quang Minh Phạm2:45 PM
mình có 1 câu hỏi về IaC mà cụ thể là về phần provision như terraform hay cdk ở trên. Thật ra là để tiếp cận với IaC provision này thì khá mất thời gian và cũng tốn nhân lực. Vậy thì IaC trong việc provisioning sẽ có ý nghĩa với các công ty thế nào khi phần lớn các công ty vừa và nhỏ có hạ tầng không reuse nhiều, hầu hết mỗi thứ chỉ tạo 1 vài lần và cứ thế chạy chứ cũng không có thay đổi quá nhiều. Mình thấy IaC provisioning thì có vẻ phù hợp hơn (effort tìm hiểu < lợi ích mang lại) với các công
Cuong Quach Chi2:45 PM
You2:46 PM
anh em post câu hỏi nhé
Quang Minh Phạm2:46 PM
(tiếp) với các công ty dạng outsource hoặc chuyên về hạ tầng hơn là các công ty product bt
nam cxn2:46 PM
@Quang Minh Phạm tí e chém về vấn đề này với bác :))
Trinh Nguyen2:46 PM
Chuẩn
ĐẠI ĐẶNG VĂN2:47 PM
Ngon cá :v
Trinh Nguyen2:47 PM
Chủ đề hiện tại: Cloud Dev Kit
Minh Luân Trần2:47 PM
hôm nay là ngày của TF :)))
Quang Minh Phạm2:48 PM
@nam cxn: waiting for you
Minh Luân Trần2:51 PM
cho em hỏi là cái cdk này cuối cùng là tạo CFN stack phải không? hay ở trên chỉ là ví dụ thôi?
ĐẠI ĐẶNG VĂN2:56 PM
A @ Luân : Chắc mình hỏi sau anh nha, nốt câu hỏi này ae chuyển sang session mới rồi ạ ạ.
Minh Luân Trần2:57 PM
ok @Đại
Cuong Quach Chi2:58 PM
ok cám ơn Quang
Trinh Nguyen3:00 PM
Quang Phương3:00 PM
bat mic
Công Hà Minh3:06 PM
Các bác cho em hỏi chút, cái teraform này có support AutoScalingGroup cho OpenStack như thằng Heat AutoScalingGroup không nhỉ?
Sa Pham3:07 PM
có nhé Công
à ko
)
dùng với B*Cloud thì có :v
Công Hà Minh3:07 PM
-_-
You3:09 PM
Phương Quang share slides cho bọn mình nhé.
Trinh Nguyen3:16 PM
:D
You3:17 PM
Quang Minh Phạm2:45 PM
mình có 1 câu hỏi về IaC mà cụ thể là về phần provision như terraform hay cdk ở trên. Thật ra là để tiếp cận với IaC provision này thì khá mất thời gian và cũng tốn nhân lực. Vậy thì IaC trong việc provisioning sẽ có ý nghĩa với các công ty thế nào khi phần lớn các công ty vừa và nhỏ có hạ tầng không reuse nhiều, hầu hết mỗi thứ chỉ tạo 1 vài lần và cứ thế chạy chứ cũng không có thay đổi quá nhiều. Mình thấy IaC provisioning thì có vẻ phù hợp hơn (effort tìm hiểu < lợi ích
Quang Minh Phạm3:18 PM
với các công ty dạng outsource hoặc chuyên về hạ tầng hơn là các công ty product bt
Trinh Nguyen3:19 PM
@Son Vu check Q&A
Son Vu Anh3:21 PM
à để bạn ấy trả lời trước nhé, nếu tôi có góp ý tôi rep luôn sau đó cũng đc
lương hữu tuấn3:26 PM
cái này phải để red hat trả lời :D
Trinh Nguyen3:26 PM
kien bui3:29 PM
1 công ty chuyên nghiệp lắm mới có thể có plan hay môi trường chuẩn và ít thay dổi ạ
ĐẠI ĐẶNG VĂN3:30 PM
IaC có thể opensource, các cty khác tái sử dụng chắc ok mà :D
lương hữu tuấn3:31 PM
Đây, redhat trả lời nhé:
Legacy change management processes are commonly ignored, bypassed, or overruled by people who need to get things done. Organizations that are more successful in enforcing these processes are increasingly seeing themselves outrun by more technically nimble competitors.
Legacy change management approaches struggle to cope with the pace of change offered by cloud and automation.
But there is still a need to cope with the ever-growing, continuously changing landscape of sy
Thảo Nguyễn Văn3:31 PM
Cảm ơn Nam
Huy Võ Trung3:31 PM
a Nam xịn quá
vỗ tay vỗ tay
nam cxn3:31 PM
lolz
ve nha di 2 ban :P
Quang Minh Phạm3:31 PM
yeah thank ae, vì mình cũng có 1 thời gian làm TF, thấy công nhận là fancy, sáng đến up hạ tầng lên, chiều về down hết xuống để tiết kiệm chi phí )). nhưng thế mới thấy là mất nhiều thời gian để triển khai các module đấy thật
))
Huy Võ Trung3:31 PM
2021 Open infra tổ chức ở SG thoai
Minh Luân Trần3:32 PM
+1 SG
)))
Huy Võ Trung3:32 PM
+12
+2SG
Mạnh Lê Đức3:32 PM
+1 SG
lương hữu tuấn3:32 PM
cái IAS ấy các ông, các ông phải dùng một thời gian mới thâys được TOC nó giảm như thế nào
Nguyễn Anh Dũng3:33 PM
Các speaker có thể share luôn slide luôn cho mọi người đc ko
Trinh Nguyen3:33 PM
Sau chương trình mình sẽ tổng hợp nha
Nguyễn Anh Dũng3:33 PM
Thanks
Quang Phương3:37 PM
@Quang Minh Phạm đấy là use-case mình có thể nghĩ dùng CDK đấy a ^^ , vừa programming familiar vừa tập trung vào phần business logic
Anh Tuấn3:37 PM
chắc sắp tới sẽ quan tâm nhiều tới cdk hơn :)
Son Vu Anh3:38 PM
IAS là gì vậy a Tuấn
lương hữu tuấn3:39 PM
IAC ông ei, tôi viết nhanh quá nên bị nhầm :P
Vu TRAN3:39 PM
Meeting có record để xem lại không mọi người nhỉ ?
Trinh Nguyen3:39 PM
không bạn ơi
nam cxn3:39 PM
continuous delivery hay la
continuous development
Trinh Nguyen3:40 PM
sáng tháng sau mình sẽ tìm cách nhé Vũ
nam cxn3:40 PM
phải bản trả phí mới có record a TRình
ĐẠI ĐẶNG VĂN3:41 PM
Em tưởng có jenkins X rồi :D
Trinh Nguyen3:41 PM
uhm, chắc lần sau mình setup máy tính rồi record màn hình Nam ơi
lương hữu tuấn3:41 PM
dùng Openshift có cloud native CI/CD các ông nhé :D
Anh Tuấn3:42 PM
dùng CI tool native với cloud provider nhé :D
Vu TRAN3:42 PM
Ok cảm ơn anh Trình
Son Vu Anh3:42 PM
e công nhận, ko phải dùng IaC thì cost cao lên mà nó có lợi ích tương lai
Cuong Nguyen Viet3:43 PM
DroneCI ko thấy có trong bxh nhỉ
Son Vu Anh3:43 PM
nhưng e vẫn không hiểu lắm, nếu cty ko có ai quản lý infra, cứ để mn thay đổi tay tự do thì hơi ảo, dù ko dùng IaC
Huy Võ Trung3:43 PM
Jenkins thấy xài nhiều nhất mà :D
lương hữu tuấn3:43 PM
cái IaC đó: nó chú làm system cũ nhé, xong h chuyển cloud, xong bị áp cái tư tưởng cũ, đâm ra mấy cái infra bị manage theo tư duy cũ, mấy cái policy thông qua các cấp để đc cấp infra vô cùng phức tạp
cho nên move sang IaC nó giamr thiểu những cái manual mà nó ko liên quan đến tech nữa
Thành Lâm3:44 PM
argo CD thấy đang lên cực mạnh :v
lương hữu tuấn3:44 PM
mà mấy cái manual này nó mơis khó để quản lý
Quang Minh Phạm3:44 PM
argoCD ahihi
Anh Tuấn3:45 PM
dùng spinnake đi cho nó khó :))
Quang Minh Phạm3:45 PM
argoCD đang xxx với weave để đẻ ra argo flux =)))
Minh Luân Trần3:45 PM
thảm hoạ spin nắc cơ :D
Quang Minh Phạm3:45 PM
thôi spinaker đao to quá tay cầm ko có nổi =)))
Anh Tuấn3:45 PM
spinnaker và envoy là thấy 2 thằng configuration khó vl
lương hữu tuấn3:46 PM
Hay lăms: Spinnakẻ
dính vào hẹo lúc nào hem biết
nam cxn3:47 PM
1 cty trong top 3 ecommerce to to ở vn đang xài spinneaker :d
Quang Minh Phạm3:48 PM
=)) đúng zồi vì nó to đó bác
chứ cty nhỏ xài giống dao mổ trâu lắm =)))
lương hữu tuấn3:48 PM
trc tớ làm cái project ở Nokia, bọn tớ deloy nhẹ cái spinnaker trong cho nó biến luôn
:D
Trinh Nguyen3:49 PM
cty nhỏ xài Jenkins simple thôi, kết hợp mấy cli tool -> cloud native vô tư
simple
Minh Luân Trần3:49 PM
jenkins + helm :D
Quang Minh Phạm3:49 PM
simple là gitlab ci (vừa quản lý code vừa ci cd ko phải cài thêm gì
Trinh Nguyen3:49 PM
+1
Mạnh Lê Đức3:49 PM
gitlabci + helm =)))
Anh Tuấn3:49 PM
chuẩn bro, thôi em quay lại gitlab ci
Quang Minh Phạm3:49 PM
căng tý thì gitlab ci + argo
Thang Man3:51 PM
How to master X in one week
Huy Võ Trung3:51 PM
:))) me too
Thang Man3:53 PM
slide đẹp :D
Trinh Nguyen3:54 PM
Halloween
Bùi Đăng Chung3:57 PM
Spot instance chứ nhỉ?
Minh Luân Trần3:58 PM
j4f: hotpot nghe thèm lẩu quá :D
Thang Man3:58 PM
có tool CD nào cho K8s mà có thể clean up unused resource một cách đáng tin cậy không mọi người? thấy ArgoCD có tính năng này nhưng thấy status=beta
Anh Tuấn3:58 PM
terraform destroy :))
Quang Minh Phạm3:59 PM
unused resource như là gì?
Thang Man3:59 PM
https://argoproj.github.io/argo-cd/user-guide/orphaned-resources/
Trinh Nguyen4:00 PM
orphaned resources
Quang Phương4:00 PM
clean resources viết script interval auto check sẽ tốt hơn
Quang Minh Phạm4:00 PM
em xài helm trên argo, mỗi lần thay đổi nếu có resource bị xóa khỏi nó thì đã được tự clean roài :-? còn trò orphan kia thì ko tín lắm
Mạnh Lê Đức4:01 PM
mình có share slide sau meeting không các bác nhỉ ?
Trinh Nguyen4:01 PM
Có nha Mạnh
xong BQT sẽ tổng hợp và gửi link trên FB group nha
Mạnh Lê Đức4:02 PM
thanks BQT :D về nghiên cứu dần :v
Quang Minh Phạm4:02 PM
theo em biết là buildkit đã được tích hợp vào docker build từ v18.06, vậy thì nó có thêm nhiều lợi ích để mà cần phải setup riên gko
nam cxn4:03 PM
@Huy Võ Trung thắc mắc gì hỏi đi e
Quang Phương4:03 PM
hotsopt nghe ten cung hay ma :D
Thang Man4:03 PM
@Quang Minh Pham: oh, nếu là gitops style thì là kiểu nếu một manifest file bị deleted khỏi repo thì resources trong file này cũng cần bị xóa khỏi cluster
Le Vinh Vo4:03 PM
Krew
Quang Phương4:04 PM
(like)
Quang Minh Phạm4:04 PM
@Thang Man, đúng rồi bác, nhưng bác không nên quản lý riêng yaml, mà nên dùng thằng ví dụ helm để quản lý thì hơn
Thành Lâm4:04 PM
Có cách nào tối ưu được cái quá trình build Images trên gitlab CI ko a ơi... em build trên server vật lý mất 3p nhưng build bằng runner (docker hoặc shell ) thì mất tới gần 10p, mặc dù đã dùng overlay2 và tối giảm các layer trên dockerfile
Mạnh Lê Đức4:04 PM
chắc bác nói prune-unused plugin phải không
https://krew.sigs.k8s.io/plugins/
nam cxn4:05 PM
theo bạn CD là continuous delivery hay la continuous development ?
Anh Tuấn4:05 PM
@namcxn: cả 2 nhé bạn
Minh Luân Trần4:05 PM
delivery or deployment chứ nhỉ
Le Vinh Vo4:05 PM
Kustomize
Kpt
Helm
Sa Pham4:05 PM
@Mạnh có vẻ ko phải cái krew mà a Vinh nhắc
Quang Minh Phạm4:05 PM
cái thứ 2 là buildpack nó cũng được viết cho dev không chuyên docker lắm, kiểu setup sẵn các thứ ấy, còn nếu mình viết dc docker file xịn thì em nghĩ ko cần lắm nhỉ
(buildpack của heroku, nên dc thiết kế để mọi dev đều có thể dùng được)
Le Vinh Vo4:06 PM
https://krew.sigs.k8s.io/plugins/
Gogo far away4:07 PM
@namcnx cho mình xin slide nhe
Bùi Đăng Chung4:07 PM
Build ci/cd thì rất tốt rồi, tuy nhiên mình làm việc thì thấy anh em developer muốn test code trên pc. Anh em có kinh nghiệm nào cho vụ đó chỉ mình với
Cuong Nguyen Viet4:07 PM
Cho e hỏi như thế nào thì đc tính là unuse nhỉ
Huy Võ Trung4:07 PM
có câu hỏi của bạn Thành Lâm kìa a .
Thành lâm :
Có cách nào tối ưu được cái quá trình build Images trên gitlab CI ko a ơi... em build trên server vật lý mất 3p nhưng build bằng runner (docker hoặc shell ) thì mất tới gần 10p, mặc dù đã dùng overlay2 và tối giảm các layer trên dockerfile
Quang Minh Phạm4:07 PM
@Thành Lâm: bạn nên chạy docker pull image cũ, rồi docker build cache from image cũ
Le Vinh Vo4:08 PM
Skafold
Trinh Nguyen4:08 PM
@Thang: https://codeberg.org/hjacobs/kube-janitor
Le Vinh Vo4:08 PM
https://www.waypointproject.io/
Bùi Đăng Chung4:09 PM
Cảm ơn bạn Vinh Vo
Thành Lâm4:09 PM
mình có dùng –cache-from để cache từ images cũ …mà có vẻ ko cải thiện được mấy
Thang Man4:10 PM
@Quang Minh Pham: Helm thấy focus vào app lifecycle mgmt, nên phần update/delete (một phần) resources trong Helm chart nó làm tốt, mình chỉ ko thích templating language của nó, ví dụ muốn check 1 array có empty hay không, dựa vào đó để create resource mà loay hoay mãi ko làm được, cũng có thể mình chưa tìm ra cách :D
Quang Minh Phạm4:10 PM
@Thành lâm: bạn xem nó đã thực sự cache chưa, và bạn có pull image cũ xuống chưa (cái này quan trọng)
nếu cache rồi thì sẽ là học cách tối ưu dockerfile, chứ ko phải chỉ là giảm hết mức layer (làm nó ko cache dc)
Quang Minh Phạm4:11 PM
- docker pull $IMAGETAG || echo “Building builder from scratch”
- >
docker build
–cache-from $IMAGETAG
- t $IMAGETAG -t $IMAGETAG-$CICOMMITSHORTSHA . - docker push $IMAGETAG
Le Vinh Vo4:11 PM
https://thenewstack.io/how-to-enable-docker-experimental-features-and-encrypt-your-login-credentials/
Thang Man4:11 PM
mình vào trễ nên ko coi phần trình bày về CI, không biết mobile build iOS, Android thì mọi người có recommend nào không
Sa Pham4:12 PM
go build thỉnh thoảng có project em thấy cũng lâu mà :D
nam cxn4:12 PM
go làm gì bằng java :D
Quang Minh Phạm4:13 PM
go module giờ cache xịn rồi mà các bác ))
chia 2 layer ra cache 1 cái cho module 1 cái cho app là dc
Sa Pham4:13 PM
có ông ở cty em phải đổi máy khác để build golang
) trước build trên con máy cũ bị đơ
Cuong Nguyen Viet4:13 PM
Go nhanh hơn java chứ
Le Vinh Vo4:14 PM
Circus CI
Mạnh Lê Đức4:14 PM
vì mình dùng runner trên k8s bằng dind image nên với Dockerfile multi-stage thấy không hiệu quả lắm, không biết có cách nào cải thiện không nhỉ
Le Vinh Vo4:14 PM
https://cirrus-ci.org/
Thang Man4:15 PM
đang tính thử cái Google Firebase cho mobile build, hoặc AWS DeviceFarm
lương hữu tuấn4:15 PM
giờ bảo anh em K8s re-write k8s bằng java thì thấy ngay go vs java
Bang Nguyen4:15 PM
anh có thể so sánh nhanh giữa kustomize và helm dựa trên kinh nghiệm sử dụng không?
Quang Minh Phạm4:15 PM
@mạnh Lê đức: bọn mình cũng xài multistage + dind, thì tạo ra 2 image riêng cho builder và runner, sau đó lần sau thì pull lại rồi cache from, nhanh vồn luôn
Thang Man4:15 PM
thank @Le Vinh Vo
Quang Minh Phạm4:17 PM
@mạnh lê đức: full không che đoạn build của em:
- docker pull $IMAGETAGBUILDER || echo “Building builder from scratch”
- docker pull $IMAGETAG || echo “Building runtime from scratch”
- >
docker build
–target=builder
–cache-from $IMAGETAGBUILDER
-t $IMAGETAGBUILDER
-t $IMAGETAGBUILDER-$CICOMMITSHORTSHA .
- >
docker build --cache-from $IMAGE_TAG --cache-from $IMAGE_TAG_BUILDER -t $IMAGE_TAG -t $IMAGE_TAG-$CI_COMMIT_SHORT_SHA .
- docker push $IMAGETAGBUILDER
Le Vinh Vo4:18 PM
https://github.com/GoogleContainerTools/kpt
lương hữu tuấn4:18 PM
Fan google chính thống đây rồi
:P
Le Vinh Vo4:18 PM
gRPC
Thang Man4:18 PM
nếu chơi kiểu autoscaling CI, các agents create/delete on-demand liên tục, thì việc cache image layers khi chạy các step trong Dockerfile là tại local disk của agent là không thực hiện được. Uber có cái Makisu, mọi người có thể thử, vì nó lưu cache ở private registry (e.g. ECR, GCR, v.v..)
Le Vinh Vo4:18 PM
Kubernetse
Cuong Nguyen Viet4:18 PM
Cloud build luôn cho 99% a
Anh Tuấn Đường4:19 PM
Vào trễ, có link slide ko anh ơi :D
ĐẠI ĐẶNG VĂN4:19 PM
Slide chia sẻ sau trên group a nha
Anh Tuấn Đường4:20 PM
dạ uki thanks anh
Trinh Nguyen4:21 PM
:)) cái gì?
Mạnh Lê Đức4:21 PM
@Quang Minh Phạm: thanks bác )) chắc phải tách mới được rồi :v
Quang Phương4:21 PM
:D
Cuong Nguyen Viet4:21 PM
Có cách nào check lỗi leak memory image trên CI ko a
Quang Minh Phạm4:23 PM
mình thấy giờ việc của CI tool rút lại khá ít khi mà mấy cái task build đã cho hết vào docker build, thì tức là tool CI giờ chỉ cần chạy dc bash docker build là ok, vậy thì tác dụng của những tool CI phức tạp sẽ không có mấy nữa
Anh Tuấn Đường4:23 PM
mới học thì chắc dùng jenkins thui
lâu lâu học travis nữa
Thang Man4:23 PM
cty nhỏ chơi GitHub Actions :D, bên mình dùng nó chạy mấy bước check code lint là điều kiện để trước khi PR được merge, chạy nhiều thì cũng hit free limits
Mạnh Lê Đức4:23 PM
VNG team this team that nữa mà
)
Quoc-Bao Nguyen4:23 PM
VNG nhiều team mà :D
Anh Tuấn4:23 PM
mới học xài gitlab ci thôi :))
Quoc-Bao Nguyen4:23 PM
Có team this team that :D
Sa Pham4:24 PM
FPT dùng jenkins.
chắc FPT là cty to rồi
Trinh Nguyen4:24 PM
)
Mạnh Lê Đức4:24 PM
@Quoc-Bao Nguyen còn làm đó k
)))
Tran Thanh4:24 PM
FPT bé
Quoc-Bao Nguyen4:24 PM
Dạ còn :D
Tran Thanh4:24 PM
Toàn theo dự án ko ah
Cuong Nguyen Viet4:24 PM
Bên e dùng droneCI cho 50 service thấy cũng khá ổn
Mạnh Lê Đức4:25 PM
e cũng thấy Spinnaker cũng ổn
)) bỏ vài tuần đọc docs với apply cũng ok :v
nhiều tính năng
)) không thiếu món
Quang A. Nguyen4:26 PM
những tool CI thường phải để file yaml pipeline trong code (exam Github Actions có .github/workflows) – anh có kinh nghiệm gì để quản lý file này cho công ty có nhiều service repository (~200) ko ạ? ví dụ cần update 1 step trong pipeline thì làm thế nào ạ?
Quang Minh Phạm4:31 PM
các bạn có để ý tới vấn đề phân chia quyền của dev trong các pipeline CI/CD không? ví dụ dev có thể sửa config pipeline để in ra variable chả hạn
Thang Man4:31 PM
https://github.community/t/being-dry-centralized-workflows/16548/3
Chưa hỗ trợ centralize các file workflows của github actions bên mình xài GoCD cho cả CI/CD, có hỗ trợ centralize toàn bộ pipelines của dev lẫn infra Quang A. Nguyen4:33 PM Gịthub Actions ko có include như Gitlab :( Thang Man4:33 PM ngoài ra còn từng xài Gitlab, Jenkins, DroneCI. nói chung mỗi team họ có opinion, requirement, và background quen xài tool nào đó, nên mất thời gian công sức để chuẩn hóa hay ép xài.
Concourse CI </code>
6. Documentation
[OLD] Quickstart
Following 2 scoops book.
- Setup Virtualenv and start virtualenv virtualenv pjs_env # not need no-site-update. Self contained env by default source …
- Boilerplace project folder with cookiescutter
pip install cookiecutter cookiecutter https://github.com/pydanny/cookiecutter-django -c 1.8.7 #1.9.7
“c” option with branch string to checkout. The project will be checked out in ~/.cookiecutter and copy to the location. Follow instruction on https://github.com/pydanny/cookiecutter-django/tree/1.8.7. The project root is ready to be pushed to git.
You can now run the usual Django migrate and runserver commands:
$ python manage.py migrate $ python manage.py runserver
At this point you can take a break from setup and start getting to know the files in the project.
But if you want to go further with setup, read on.
(Note: the following sections still need to be revised) Setting Up Env Vars for Production
Cookiecutter Django uses the excellent django-environ package, which includes a DATABASE_URL environment variable to simplify database configuration in your Django settings.
Rename env.example to .env to begin updating the file with your own environment variables. To add your database, define DATABASE_URL and add it to the .env file, as shown below:
DATABASE_URL="postgres://<pg_user_name>:<pg_user_password>@127.0.0.1:<pg_port>/<pg_database_name>"
Setup your email backend
django-allauth sends an email to verify users (and superusers) after signup and login (if they are still not verified). To send email you need to configure your email backend
In development you can (optionally) use MailHog for email testing. MailHog is built with Go so there are no dependencies. To use MailHog:
Download the latest release for your operating system Rename the executable to mailhog and copy it to the root of your project directory Make sure it is executable (e.g. chmod +x mailhog) Execute mailhog from the root of your project in a new terminal window (e.g. ./mailhog) All emails generated from your django app can be seen on http://127.0.0.1:8025/
Alternatively simply output emails to the console via:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
In production basic email configuration is setup to send emails with Mailgun
Testing Mailhog
- Register user account
- email with confirmation url is output in console
- Click the url!!!
Live reloading and Sass CSS compilation
If you’d like to take advantage of live reloading and Sass / Compass CSS compilation you can do so
Django-cms
Project structure details
Multiple settings files
Instead of having one settings.py le, with this setup you have a settings/ directory containing your settings les. is directory will typically contain something like the following:
settings/ __init__.py base.py local.py staging.py test.py production.py
base.py Settings common to all instances of the project.
local.py This is the settings file that you use when you're working on the project locally. Local development-specific settings include DEBUG mode, log level, and activation of developer tools like django-debug-toolbar. Developers sometimes name this file dev.py.
staging.py Staging version for running a semi-private version of the site on a production server. This is
test.py Settings for running tests including test runners, in-memory database definitions, and log settings.
production.py where managers and clients should be looking before your work is moved to production. This is the settings file used by your live production server(s). That is, the server(s) that host the real live website. This file contains production-level settings only. It is sometimes called prod.py.
Each settings module should have its own corresponding requirements file.
Multiple Files With Continuous Integration Servers
You’ll also want to have a ci.py module containing that server’s settings. Similarly, if it’s a large project and you have other special-purpose servers, you might have custom settings les for each of them.
To start the Python interactive interpreter with Django, using your settings/local.py settings file:
python manage.py shell --settings=twoscoops.settings.local
To run the local development server with your settings/local.py settings file:
python manage.py runserver --settings=twoscoops.settings.local
A great alternative to using the –settings command line option everywhere is to set the DJANGO SETTINGS MODULE and PYTHONPATH environment variable to your desired settings module path. You’d have to set DJANGO SETTINGS MODULE to the corresponding settings module for each environment, of course.
For those with a more comprehensive understanding of virtualenv, another alternative is to set DJANGO SETTINGS MODULE and PYTHONPATH in the postactivate script. en, once the virtualenv is activated, you can just type python from anywhere and import those values into your project. is also means that typing django-admin.py at the command-line works without the –settings option.
Separate Configuration From Code
Here are the bene ts of using environment variables for secret keys:
- Keeping secrets out of settings allows you to store every settings le in version control without
hesitation. All of your Python code really should be stored in version control, including your settings.
- Instead of each developer maintaining an easily-outdated, copy-and-pasted version of the
local settings.py.example le for their own development purposes, everyone shares the same version-controlled settings/local.py .
- System administrators can rapidly deploy the project without having to modify les containing
Python code.
- Most platforms-as-a-service recommend the use of environment variables for con guration
and have built-in features for setting and managing them.
Before you begin setting environment variables, you should have the following:
- A way to manage the secret information you are going to store.
- A good understanding of how bash works with environment variables on servers, or a willing-
ness to have your project hosted by a platform-as-a-service. For more information, see http://2scoops.co/wikipedia-env-variable.
Environment Variables Do Not Work With Apache
How to Set Environment Variables Locally
On Mac and many Linux distributions that use bash for the shell, one can add lines like the following to the end of a .bashrc, .bash pro le, or .pro le. When dealing with multiple projects using the same API but with different keys, you can also place these at the end of your virtualenv’s bin/activate script:
$ export SOME_SECRET_KEY=1c3-cr3am-15-yummy $ export AUDREY_FREEZER_KEY=y34h-r1ght-d0nt-t0uch-my-1c3-cr34m
How to Set Environment Variables in Production
If you’re using your own servers, your exact practices will differ depending on the tools you’re us- ing and the complexity of your setup. For the simplest 1-server setup for test projects, you can set the environment variables manually. But if you’re using scripts or tools for automated server provi- sioning and deployment, your approach may be more complex. Check the documentation for your deployment tools for more information. If your Django project is deployed via a platform-as-a-service, check the documentation for spe- ci c instructions. We’ve included Heroku instructions here so that you can see that it’s similar for platform-as-a-service options. On Heroku, you set environment variables with the following command, executed from your devel- opment machine:
$ heroku config:set SOME_SECRET_KEY=1c3-cr3am-15-yummy
To see how you access environment variables from the Python side, open up a new Python prompt and type:
>>> import os >>> os.environ["SOME_SECRET_KEY"] "1c3-cr3am-15-yummy"
To access environment variables from one of your settings les, you can do something like this:
# Top of settings/production.py import os SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]
Handling Missing Secret Key Exceptions
In the above implementation, if the SECRET KEY isn’t available, it will throw a KeyError , making it impossible to start the project. at’s great, but a KeyError doesn’t tell you that much about what’s actually wrong. Without a more helpful error message, this can be hard to debug, especially under the pressure of deploying to servers while users are waiting and your ice cream is melting. Here’s a useful code snippet that makes it easier to troubleshoot those missing environment variables. If you’re using our recommended environment variable secrets approach, you’ll want to add this to your settings/base.py file:
# settings/base.py
import os
# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured
def get_env_variable(var_name):
"""Get the environment variable or return exception."""
try:
return os.environ[var_name]
except KeyError:
error_msg = "Set the {} environment variable".format(var_name)
raise ImproperlyConfigured(error_msg)
Then, in any of your settings les, you can load secret keys from environment variables as follows:
SOME_SECRET_KEY = get_env_variable("SOME_SECRET_KEY")
WARNING: Don't Import Django Components Into Settings Modules
TIP: Using django-admin.py Instead of manage.py
The official Django documentation says that you should use django-admin.py rather than manage.py when working with multiple settings files: https://docs.djangoproject.com/en/1.8/ref/django-admin/ at being said, if you’re struggling with django-admin.py, it’s perfectly okay to develop and launch your site running it with manage.py.
When You Can't Use Environment Variables
The problem with using environment variables to store secrets is that it doesn’t always work. The most common scenario for this is when using Apache for serving HTTP, but this also happens even in Nginx-based environments where operations wants to do things in a particular way. When this occurs, rather than going back to the local settings anti-pattern, we advocate using non-executable les kept out of version control in a method we like to call the secrets le pattern. To implement the secrets le pattern, follow these three steps:
- Create a secrets le using the con guration format of choice, be it JSON, Con g, YAML, or even XML.
- Add a secrets loader ( JSON-powered example below) to manage the secrets in a cohesive, explicit manner.
- Add the secrets le name to the .gitignore or .hgignore.
Using JSON Files
Our preference is to use shallow JSON les. e JSON format has the advantage of being the format of choice for various Python and non-Python tools. To use the JSON format, first create a secrets.json file:
{
"FILENAME": "secrets.json",
"SECRET_KEY": "I've got a secret!", .
"DATABASES_HOST": "127.0.0.1",
"PORT": "5432"
}
To use the secrets.json file, add the following code to your base settings module.
# settings/base.py
import json
# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured
# JSON-based secrets module
with open("secrets.json") as f:
secrets = json.loads(f.read())
.
def get_secret(setting, secrets=secrets):
"""Get the secret variable or return explicit exception."""
try:
return secrets[setting]
except KeyError:
error_msg = "Set the {0} environment variable".format(setting)
raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_secret("SECRET_KEY")
Using Config, YAML, and XML File Formats
While we prefer the forced simplicity of shallow JSON, others might prefer other le formats. We’ll leave it up to the reader to create additional get secret() alternatives that work with these for- mats. Just remember to be familiar with things like yaml.safe load() and XML bombs. See section 26.9, ‘Defend Against Python Code Injection Attacks.’
Using Multiple Requirements Files
To follow this pattern, recommended to us by Jeff Triplett, rst create a requirements/ directory in the <repository root>. en create ‘.txt’ les that match the contents of your settings directory. results should look something like:
requirements/ base.txt local.txt staging.txt production.txt
In the base.txt le, place the dependencies used in all environments. For example, you might have something like the following in there:
Django==1.8.0 psycopg2==2.6 djangorestframework==3.1.1
Your local.txt le should have dependencies used for local development, such as:
- r base.txt # includes the base.txt requirements file
coverage==3.7.1 django-debug-toolbar==1.3.0
The needs of a continuous integration server might prompt the following for a ci.txt le:
- r base.txt # includes the base.txt requirements file
coverage==3.7.1 django-jenkins==0.16.4
Production installations should be close to what is used in other locations, so production.txt com- monly just calls base.txt:
- r base.txt # includes the base.txt requirements file
Add Package and Version Number to Your Requirements
Using Multiple Requirements Files With Platforms as a Service (PaaS)
Handling File Paths in Settings
Don’t hardcode your paths!
If you really want to set your BASE DIR with the Python standard library’s os.path library, though, this is one way to do it in a way that will account for paths:
# At the top of settings/base.py
from os.path import join, abspath, dirname
here = lambda *dirs: join(abspath(dirname(__file__)), *dirs)
BASE_DIR = here("..", "..")
root = lambda *dirs: join(abspath(BASE_DIR), *dirs)
# Configuring MEDIA_ROOT
MEDIA_ROOT = root("media")
# Configuring STATIC_ROOT
STATIC_ROOT = root("collected_static")
# Additional locations of static files
STATICFILES_DIRS = (
.
root("assets"),
)
# Configuring TEMPLATE_DIRS
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
DIRS = (root("templates"),)
},
]
Source env.local.source
export POSTGRES_PASSWORD=maxopw export POSTGRES_USER=maxo export DJANGO_ADMIN_URL= export DJANGO_SETTINGS_MODULE=config.settings.local #export DJANGO_SECRET_KEY=di60zn#ni9_j)8ek-u+zdcw=0()4=@iq48d3m6ereq1287wdl3 #export DJANGO_ALLOWED_HOSTS=.example.com export DJANGO_AWS_ACCESS_KEY_ID= export DJANGO_AWS_SECRET_ACCESS_KEY= export DJANGO_AWS_STORAGE_BUCKET_NAME= export DJANGO_MAILGUN_API_KEY= export DJANGO_MAILGUN_SERVER_NAME= export DJANGO_SERVER_EMAIL= export DJANGO_SECURE_SSL_REDIRECT=False export DJANGO_SENTRY_DSN= export NEW_RELIC_LICENSE_KEY export DJANGO_OPBEAT_ORGANIZATION_ID export DJANGO_OPBEAT_APP_ID export DJANGO_OPBEAT_SECRET_TOKEN
source env.local.source
Database
Django-environ is used for managing settings in ENV.
https://django-environ.readthedocs.org/en/latest/#django-environ
Install postgres: http://localhost/~dang/wiki/doku.php?id=programming:django:django_tutorial:tut_0_ground_zero#posgre_database
Database
Create postgres database maxoshop_project with user maxo/maxopw.
Edit config.settings.common.py
# DATABASE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
'default': env.db("DATABASE_URL", default="psql://maxo:maxopw@127.0.0.1:5432/maxoshop_project"),
}
DATABASES['default']['ATOMIC_REQUESTS'] = True