Edistynyt taso
Sinulla tulee olla Linuxin, Dockerin, Docker Composen ja Komposen tuntemusta. Python-osaaminen on plussaa.
Rahtin osalta suosimme OpenShiftin komentorivityökalun oc käyttöä
4catin käyttöönotto Rahdissa
Tämä ohje on pitkämuotoinen ja selittää kaikki eri vaiheet, joita tarvittiin 4cat_fi -sovelluksen käyttöönottoon Rahdissa. Tarkoituksena on kertoa, miten eri ongelmat löydettiin ja ratkaistiin. Jokaisella ongelmalla on oma lukunsa, ja toivottavasti ratkaisu on helppo soveltaa myös muihin sovelluksiin, joissa on samankaltaisia oireita. Jätämme pois osan virheellisistä ratkaisuista ja harhapoluista, joita seurasin yrittäessäni alun perin ottaa tätä sovellusta käyttöön, jotta tämä ohje ei kasvaisi eksponentiaalisesti. Pidä kuitenkin mielessä, että tällaiset prosessit ovat harvoin suoraviivaisia ja että ratkaisua etsiessä löytyy yleensä paljon myös ratkaisuja, jotka eivät toimi.
4Cat on datan keruu- ja analyysityökalupakki. Yllä linkitetystä GitHub-sivusta opimme, että työkalua käytetään sosiaalisen median alustojen analysointiin ja että yksi asennustavoista on docker compose. Tämä on hyvä uutinen, koska:
- Voimme testata sovelluksen käyttöönottoa docker composella ja nähdä, miltä se näyttää.
- Meidän ei tarvitse luoda Docker-konttia alusta asti.
- Voimme käyttää docker compose -käyttöönottoa pohjana ja sovittaa sen Kubernetes-käyttöönotoksi komposen avulla. Tämä työkalu on suunniteltu nimenomaan tällaisia muunnoksia varten. Heidän sivustonsa mukaan: "Our conversions are not always 1:1 from Docker Compose to Kubernetes, but we will help get you 99% of the way there!". Se säästääkin paljon työlästä muunnostyötä, mutta siihen työ ei vielä lopu.
Kaikissa esimerkeissä käytetään Linuxia 🐧
Olemme laatineet tämän ohjeen Linux-koneella. Periaatteessa pienellä sovittamisella kaikki nämä komennot toimivat myös Windowsissa ja Macissa, mutta jos olet epävarma, suosittelen, että asennat pienen virtuaalikoneen Poutaan ja käytät sitä tämän ohjeen seuraamiseen. Tämä on hyödyllistä myös Linux-käyttäjille, koska voit asentaa, poistaa tai vaihtaa ohjelmistoja vaarantamatta paikallista asennustasi.
Docker compose
-
Ennen jatkamista tarvitsemme Dockerin ja docker compose -lisäosan asennettuna. Ohjeet docker composen asentamiseen löytyvät täältä:
Debianissa ja Ubuntussa voit asentaa sen näin:
Vaihtoehtoja Dockerille 🐋
Voit käyttää myös podman composea tai vastaavaa, mutta tässä ohjeessa käytämme Dockeria, koska se on yleisin työkalu.
-
Kun docker compose on asennettu, otetaan 4cat käyttöön ja katsotaan, miltä se näyttää ja miten se toimii. Sinun täytyy kloonata repositorio ja suorittaa docker-compose kloonatun kansion sisällä:
Tämä käynnistää sovelluksen käyttöönoton koneella. Kuvien noutaminen ja sovelluksen määrittäminen voi kestää jonkin aikaa. Jos painat
Ctrl+C, sovellus sulkeutuu. Jos haluat ajaa sen taustalla, lisää docker-compose-komentoon-dtai--detach.
Hetken kuluttua sovellus on saatavilla portissa
80(PUBLIC_PORT):
Analyysi
docker-compose.yml -tiedosto on seuraava:
services:
db:
container_name: 4cat_db
image: postgres:${POSTGRES_TAG}
restart: unless-stopped
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_HOST_AUTH_METHOD=${POSTGRES_HOST_AUTH_METHOD}
volumes:
- 4cat_db:/var/lib/postgresql/data/
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER}" ]
interval: 5s
timeout: 5s
retries: 5
backend:
image: digitalmethodsinitiative/4cat:${DOCKER_TAG}
container_name: 4cat_backend
restart: unless-stopped
env_file:
- .env
depends_on:
db:
condition: service_healthy
ports:
- ${PUBLIC_API_PORT}:4444
volumes:
- 4cat_data:/usr/src/app/data/
- 4cat_config:/usr/src/app/config/
- 4cat_logs:/usr/src/app/logs/
entrypoint: docker/docker-entrypoint.sh
frontend:
image: digitalmethodsinitiative/4cat:${DOCKER_TAG}
container_name: 4cat_frontend
restart: unless-stopped
env_file:
- .env
depends_on:
- db
- backend
ports:
- ${PUBLIC_PORT}:500
- ${TELEGRAM_PORT}:443
volumes:
- 4cat_data:/usr/src/app/data/
- 4cat_config:/usr/src/app/config/
- 4cat_logs:/usr/src/app/logs/
command: ["docker/wait-for-backend.sh"]
volumes:
4cat_db:
name: ${DOCKER_DB_VOL}
4cat_data:
name: ${DOCKER_DATA_VOL}
4cat_config:
name: ${DOCKER_CONFIG_VOL}
4cat_logs:
name: ${DOCKER_LOGS_VOL}
Katsotaan myös .env -tiedostoa:
# 4CAT Version: Update with latest release tag or 'latest'
# https://hub.docker.com/repository/docker/digitalmethodsinitiative/4cat/tags?page=1&ordering=last_updated
DOCKER_TAG=stable
# You can select Postrgres Docker image tags here to suit your needs: https://hub.docker.com/_/postgres
POSTGRES_TAG=latest
# Database setup
POSTGRES_USER=fourcat
POSTGRES_PASSWORD=supers3cr3t
POSTGRES_DB=fourcat
POSTGRES_HOST_AUTH_METHOD=trust
# POSTGRES_HOST should correspond with the database container name set in docker-compose.yml
POSTGRES_HOST=db
POSTGRES_PORT=5432 # Docker postgres image uses port 5432
# Server information
# SERVER_NAME is only used on first run; afterwards it can be set in the frontend
SERVER_NAME=localhost
PUBLIC_PORT=80
# Backend API
# API_HOST is used by the frontend; in Docker it should be the backend container name
# (or "localhost" if front and backend are running together in one container
API_HOST=backend
PUBLIC_API_PORT=4444
# Telegram apparently needs its own port
TELEGRAM_PORT=443
# Docker Volume Names
DOCKER_DB_VOL=4cat_4cat_db
DOCKER_DATA_VOL=4cat_4cat_data
DOCKER_CONFIG_VOL=4cat_4cat_config
DOCKER_LOGS_VOL=4cat_4cat_logs
# Gunicorn settings
worker_tmp_dir=/dev/shm
workers=4
threads=4
worker_class=gthread
log_level=debug
Kuten näet, tämä docker-compose.yml-tiedosto on YAML -tiedosto, jossa on kaksi pääosiota: services ja volumes. Siinä on 3 services-määrittelyä ja 4 volumes-määrittelyä. Kubernetesissa tämä tarkoittaa 3:a Deployment-resurssia ja 4:ää PersistentVolumeClaim-resurssia (PVC). Palvelun tärkeimmät kentät ovat:
imageon kuva, jonka Docker noutaa ja suorittaa jokaiselle palvelulle. Tässä tapauksessa meillä on kaksi eri kuvaa:postgres-kuva (tunnettu tietokanta) ja4cat_fi-kuva.Frontendjabackendkäyttävät samaa kuvaa, mutta niillä on eri komento/entry point. Koska docker compose toimii, tiedämme, että molemmat kuvat ovat olemassa ja ne voidaan noutaa ilman ongelmia.environmentjaenv_filemäärittelevät ympäristömuuttujat, joilla palvelut konfiguroidaan. EsimerkiksiPOSTGRES_PASSWORD-muuttujaa käytetään tietokannan salasanan välittämiseen.volumeskertoo Dockerille, mitkä taltiot liitetään palveluun ja mihin kansioon ne liitetään.portskertoo julkiset portit, sisäiset portit ja niiden välisen kartoituksen. Merkintätapa on<external_port>:<internal_port>.entrypointjacommandovat komennot, jotka suoritetaan, kun kuva käynnistetään. Postgresilla ei ole kumpaakaan, koska käytämme kuvan oletus-command/entrypoint-määrityksiä.
Taltiot-osio on yksinkertaisempi ja sisältää vain nimiluettelon. Docker composen "volume" on tavallinen Docker-taltio eikä sisällä kokoa. Tämä johtuu siitä, että se käyttää paikallista levyä, jolloin koko määräytyy paikallisen levyn kapasiteetin mukaan. Kubernetesin taltioilla on koko, ja meidän täytyy ottaa se huomioon muunnosta tehdessä.
.env-tiedosto sisältää oletusarvot sovelluksen oikeaan käyttöönottoon. Esimerkiksi PUBLIC_PORT on asetettu arvoon 80.
Kompose
Kompose antaa meille mahdollisuuden muuntaa docker-compose.yaml-tiedoston joukoksi Kubernetesin YAML-tiedostoja.
-
Meillä täytyy olla kompose asennettuna. Voit seurata ohjeita täältä:
Koska Docker on jo asennettu, voimme käyttää Docker-menetelmää, joka rakentaa kuvan lähdekoodista:
-
Suorita kompose (edelleen 4cat_fi-kansiossa):
$ docker run --rm -it -v $PWD:/opt kompose sh -c "cd /opt && kompose convert" WARN The "DOCKER_CONFIG_VOL" variable is not set. Defaulting to a blank string. WARN The "DOCKER_LOGS_VOL" variable is not set. Defaulting to a blank string. WARN The "DOCKER_DB_VOL" variable is not set. Defaulting to a blank string. WARN The "DOCKER_DATA_VOL" variable is not set. Defaulting to a blank string. WARN The "PUBLIC_PORT" variable is not set. Defaulting to a blank string. WARN The "TELEGRAM_PORT" variable is not set. Defaulting to a blank string. WARN The "DOCKER_TAG" variable is not set. Defaulting to a blank string. WARN The "POSTGRES_TAG" variable is not set. Defaulting to a blank string. WARN The "POSTGRES_USER" variable is not set. Defaulting to a blank string. WARN The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string. WARN The "POSTGRES_DB" variable is not set. Defaulting to a blank string. WARN The "POSTGRES_HOST_AUTH_METHOD" variable is not set. Defaulting to a blank string. WARN The "PUBLIC_API_PORT" variable is not set. Defaulting to a blank string. WARN The "DOCKER_TAG" variable is not set. Defaulting to a blank string. WARN Restart policy 'unless-stopped' in service frontend is not supported, convert it to 'always' WARN Restart policy 'unless-stopped' in service db is not supported, convert it to 'always' WARN Restart policy 'unless-stopped' in service backend is not supported, convert it to 'always' WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/data: no such file or directory WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/config: no such file or directory WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/logs: no such file or directory WARN Service "db" won't be created because 'ports' is not specified WARN File don't exist or failed to check if the directory is empty: stat :/var/lib/postgresql/data: no such file or directory WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/data: no such file or directory WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/config: no such file or directory WARN File don't exist or failed to check if the directory is empty: stat :/usr/src/app/logs: no such file or directory INFO Kubernetes file "backend-service.yaml" created INFO Kubernetes file "frontend-service.yaml" created INFO Kubernetes file "backend-deployment.yaml" created INFO Kubernetes file "env-configmap.yaml" created INFO Kubernetes file "4cat-data-persistentvolumeclaim.yaml" created INFO Kubernetes file "4cat-config-persistentvolumeclaim.yaml" created INFO Kubernetes file "4cat-logs-persistentvolumeclaim.yaml" created INFO Kubernetes file "db-deployment.yaml" created INFO Kubernetes file "4cat-db-persistentvolumeclaim.yaml" created INFO Kubernetes file "frontend-deployment.yaml" created -
Sinulla pitäisi nyt olla muutama uusi tiedosto:
- "backend-service.yaml"
- "frontend-service.yaml"
- "backend-deployment.yaml"
- "env-configmap.yaml"
- "4cat-data-persistentvolumeclaim.yaml"
- "4cat-config-persistentvolumeclaim.yaml"
- "4cat-logs-persistentvolumeclaim.yaml"
- "db-deployment.yaml"
- "4cat-db-persistentvolumeclaim.yaml"
- "frontend-deployment.yaml"
Analyysi
Työkalu on luonut neljänlaisia tiedostoja: service, deployment, configmap ja persistentvolumeclaim. Aloitetaan yksinkertaisimmista:
-
persistentvolumeclaim-tiedostot ovat taltioiden määrittelyjä. Jokaisesta docker compose -tiedostonvolume-määrittelystä syntyy yksi tiedosto. Katsotaan esimerkkiä ja olennaisten rivien merkitystä:apiVersion: v1 kind: PersistentVolumeClaim metadata: labels: io.kompose.service: 4cat-logs name: 4cat-logs spec: accessModes: - ReadWriteOnce resources: requests: storage: 100MiNäemme, että
nameon säilytetty compose-määrittelystä (kohdassametadata > name).accessModeon asetettu arvoonReadWriteOnce, mikä tarkoittaa, että taltio voidaan liittää vain kerran. Lopuksi koko on oletuksena100Mi(kohdassaspec > resources > request > storage). -
configmap-tiedosto(t) tallentavat konfiguraation. Meidän tapauksessamme.env-tiedostossa määritellyt (ei docker-compose-spesifiset) muuttujat on muunnettu tiedostoonenv-configmap.yaml.nameon asetettu arvoonenv, ja muuttujat on määritelty kohdandataalle. -
service-tiedostot määrittelevät "vakaat verkkoidentiteetit", jotka toimivat kuormantasaajina. Jokaiselledeployment-resurssille luodaan palvelu, ja se vie ulos kaikki portit, joita käyttöönotto tarjoaa. Esimerkiksi tiedostossafrontend-service.yaml:apiVersion: v1 kind: Service metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.34.0 (cbf2835db) labels: io.kompose.service: frontend name: frontend spec: ports: - name: "5000" port: 5000 targetPort: 5000 - name: "443" port: 443 targetPort: 443 selector: io.kompose.service: frontendKaksi olennaista kohtaa ovat
selectorjaports. Ensimmäinen yhdistää palvelundeployment-resurssiin ja toinen listaa portit, jotka tämä palvelu vie ulos. Katso lisätietoja palveluista. -
deploymenton monimutkaisin luotu määritys. Voimme yrittää kartoittaadocker-compose.yaml-tiedoston asetukset näihin tiedostoihin. Esimerkiksi käyttämällä lyhintä luotua tiedostoa:apiVersion: apps/v1 kind: Deployment metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.34.0 (cbf2835db) labels: io.kompose.service: db name: db spec: replicas: 1 selector: matchLabels: io.kompose.service: db strategy: type: Recreate template: metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.34.0 (cbf2835db) labels: io.kompose.service: db spec: containers: - env: - name: POSTGRES_DB - name: POSTGRES_HOST_AUTH_METHOD - name: POSTGRES_PASSWORD - name: POSTGRES_USER image: 'postgres:' livenessProbe: exec: command: - pg_isready -U ${POSTGRES_USER} failureThreshold: 5 periodSeconds: 5 timeoutSeconds: 5 name: 4cat-db volumeMounts: - mountPath: /var/lib/postgresql/data name: 4cat-db restartPolicy: Always volumes: - name: 4cat-db persistentVolumeClaim: claimName: 4cat-dbimageon määritelty kohdassaspec > template > spec > containers > image, ja tässä tapauksessa se onpostgres:. Tämä on virhe, koska tagilatestpuuttuu. Korjaamme tämän myöhemmin.environmenton määritelty kohdassaspec > template > spec > containers > env, mutta myös arvot puuttuvat.volumeson määritelty kohdissaspec > template > spec > volumesjaspec > template > spec > containers > volumeMounts.portson määritelty kohdassaspec > template > spec > containers > portssekä jo mainituissa vastaavissaservice-tiedostoissa.- Lopuksi
commandon määritelty kohdassaspec > template > spec > containers > command(näet esimerkin tiedostossabackend-deployment.yaml).
Kuten näet, luodut YAML-tiedostot eivät ole täydellisiä, mutta ne toimivat hyvänä pohjana käyttöönoton jatkamiselle.
Käyttöönotto Rahdissa
Otamme nykyiset muokkaamattomat YAML-tiedostot ja otamme ne käyttöön yksi kerrallaan. Ensin sinun täytyy asentaa oc ja kirjautua Rahtiin. Sen jälkeen sinun täytyy luoda Rahti-projekti. Varmista lopuksi, että olet oikeassa projektissa: oc project <project_name>.
Taltiot, ConfigMapit ja palvelut
Nämä kolme tyyppiä ovat suoraviivaisia eikä niiden pitäisi aiheuttaa ongelmia.
-
Voimme aloittaa luomalla
volumes-resurssit yksi kerrallaan:$ oc create -f 4cat-config-persistentvolumeclaim.yaml persistentvolumeclaim/4cat-config created $ oc create -f 4cat-data-persistentvolumeclaim.yaml persistentvolumeclaim/4cat-data created $ oc create -f 4cat-db-persistentvolumeclaim.yaml persistentvolumeclaim/4cat-db created $ oc create -f 4cat-logs-persistentvolumeclaim.yaml persistentvolumeclaim/4cat-logs createdTämä luo 4 taltiota tilaan
Pending. Ne pysyvät tilassaPending, kunnes otammedeployments-resurssit käyttöön. Tämä on odotettua. -
Luomme myös
configMap-resurssin:$ oc create -f env-configmap.yaml configmap/env created $ oc get cm NAME DATA AGE env 22 5s kube-root-ca.crt 1 5m45s openshift-service-ca.crt 1 5m45sKaksi muuta merkintää (
kube-root-cs.crtjaopenshift-service-ca.crt) ovat valmiiksi luotuja Kubernetesin ja OpenShiftin perus-ConfigMap-resursseja. -
Emme odota virheitä
services-resurssien luomisessa (db-palvelu puuttuu, koska docker compose -tiedostossa ei mainittu portteja, ja meidän täytyy luoda se itse myöhemmin):$ oc create -f frontend-service.yaml service/frontend created $ oc create -f backend-service.yaml service/backend created $ oc get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 172.30.109.120 <none> 4444/TCP 21h frontend ClusterIP 172.30.139.56 <none> 5000/TCP,443/TCP 21hTulos on backendin osalta odotettu, koska kartoitus oli
4444:4444. Frontendin osalta ei, koska alkuperäinen oli80:5000. Tämä ei ole suuri ongelma, koska jotta palveluun pääsee Rahdin ulkopuolelta, käytämmeRoute-resurssia, jaRoutemahdollistaa minkä tahansa portin muuntamisen ja julkaisemisen vakioporteissa 80/443. Jätämme sen siis ennalleen.
Tietokannan Deploymentit
Lopuksi luomme deploymentit. Meillä on 3 deploymentia, ja aloitamme tietokannan deploymentista.
-
Luodaan ensin nykyinen versio:
-
Tämä on odotettua, koska tagi
latestpuuttui kuvan nimestä. Korjataan se ja yritetään uudelleen. Muokkaa siis tiedostoadb-deployment.yamlja lisäälatestkuvan arvoon niin, että se näyttää tältä:postgres:latest,ja luo deployment uudelleen / korvaa se:
$ oc replace -f db-deployment.yaml deployment.apps/db replaced $ oc get pods NAME READY STATUS RESTARTS AGE db-76fcbdc9d8-dgmqr 0/1 CrashLoopBackOff 1 (1s ago) 24sYAML-tiedostot
Teemme muutokset
YAML-tiedostoihin, jotta voimme myöhemmin luoda koko käyttöönoton uudelleen. Voit myös lisätä tiedostot Git-repositorioon ja tehdä commitin jokaisesta muutoksesta, jolloin muutosten historia ja perustelut säilyvät selkeästi commit-historiassa. -
Deployment ei toimi, mutta eri syystä. Katsotaan miksi:
$ oc logs db-76fcbdc9d8-dgmqr chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted chmod: changing permissions of '/var/run/postgresql': Operation not permitted Error: Database is uninitialized and superuser password is not specified. You must specify POSTGRES_PASSWORD to a non-empty value for the superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run". You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all connections without a password. This is *not* recommended. See PostgreSQL documentation about "trust": https://www.postgresql.org/docs/current/auth-trust.htmlTämä näyttää kahdenlaisia virheitä: kansioiden käyttöoikeusvirheitä ja puuttuvia muuttujia. Yritetään toistaa virhe paikallisesti omalla koneellamme. Komento on:
docker run -it --rm -u 1000 postgres:latest chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted chmod: changing permissions of '/var/run/postgresql': Operation not permitted Error: Database is uninitialized and superuser password is not specified. You must specify POSTGRES_PASSWORD to a non-empty value for the superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run". You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all connections without a password. This is *not* recommended. See PostgreSQL documentation about "trust": https://www.postgresql.org/docs/current/auth-trust.htmlYllä olevassa esimerkissä lisäsimme
-u 1000, jotta UID vaihdetaan ei-root-käyttäjäksi ja voimme toistaa saman virheen, jonka Rahti näyttää. Mikä tahansa satunnainen UID käy; näin Rahti suorittaa kuvia (satunnaisilla UID:illa). Toistetaan tämä niin, ettäPOSTGRES_PASSWORD-muuttuja on määritelty ehdotuksen mukaisesti:$ podman run -it --rm -u 1000 -e POSTGRES_PASSWORD=password postgres:latest WARN[0000] Error validating CNI config file /home/galvaro/.config/cni/net.d/4cat_default.conflist: [plugin firewall does not support config version "1.0.0"] chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted chmod: changing permissions of '/var/run/postgresql': Operation not permitted The files belonging to this database system will be owned by user "1000". This user must also own the server process. The database cluster will be initialized with locale "en_US.utf8". The default database encoding has accordingly been set to "UTF8". The default text search configuration will be set to "english". Data page checksums are disabled. fixing permissions on existing directory /var/lib/postgresql/data ... initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permittedTässä tapauksessa näemme, että tämä konttikuva ei koskaan toimi Rahdissa, koska sen täytyy pystyä muuttamaan kansioiden käyttöoikeuksia. Onneksi Rahti/OpenShift tarjoaa PostgreSQL-mallin, joka on saatavilla ohjelmistoluettelossa.

Mallin kuvauksessa näemme linkin GitHub-sivulle https://github.com/sclorg/postgresql-container/. Sivulla näkyy lista kaikista saatavilla olevista kuvista. Valitsemme quay.io/sclorg/postgresql-15-c9s -kuvan, koska se on uusin saatavilla oleva versio ja käyttää CentOS 9:ää pohjana.
-
Kun kuva on vaihdettu (
postgres:latest→quay.io/sclorg/postgresql-15-c9s:latest), lokit näyttävät tältä:$ oc logs db-747df6885c-sh289 For general container run, you must either specify the following environment variables: POSTGRESQL_USER POSTGRESQL_PASSWORD POSTGRESQL_DATABASE Or the following environment variable: POSTGRESQL_ADMIN_PASSWORD Or both. To migrate data from different PostgreSQL container: POSTGRESQL_MIGRATION_REMOTE_HOST (hostname or IP address) POSTGRESQL_MIGRATION_ADMIN_PASSWORD (password of remote 'postgres' user) And optionally: POSTGRESQL_MIGRATION_IGNORE_ERRORS=yes (default is 'no') Optional settings: POSTGRESQL_MAX_CONNECTIONS (default: 100) POSTGRESQL_MAX_PREPARED_TRANSACTIONS (default: 0) POSTGRESQL_SHARED_BUFFERS (default: 32MB) For more information see /usr/share/container-scripts/postgresql/README.md within the container or visit https://github.com/sclorg/postgresql-container.Muuttujien nimet ovat erilaiset, mutta ne on helppo muuntaa. Otamme myös arvot
env-configMap-resurssista:containers: - env: - - name: POSTGRES_DB - - name: POSTGRES_HOST_AUTH_METHOD - - name: POSTGRES_PASSWORD - - name: POSTGRES_USER - image: 'postgres:' + - name: POSTGRESQL_DATABASE + valueFrom: + configMapKeyRef: + key: POSTGRES_DATABASE + name: env + - name: POSTGRESQL_PASSWORD + valueFrom: + configMapKeyRef: + key: POSTGRES_PASSWORD + name: env + - name: POSTGRESQL_USER + valueFrom: + configMapKeyRef: + key: POSTGRES_USER + name: env + image: 'quay.io/sclorg/postgresql-15-c9s' livenessProbe: exec:Tämä viimeinen muutos ratkaisi ongelman, ja Pod on nyt käynnissä odotetusti:
Backend-deployment
Tämä deployment tarvitsee myös muutamia muutoksia. Käydään ne läpi toivottavasti hieman ketterämmin:
-
Korjaa kuvan nimi. Virhe:
Ratkaisu:
-
Lisää db-palvelu ratkaistaksesi tämän ongelman:
Tämä edellyttää db-palvelun luomista:
-
Seuraava virhe liittyy salasana-autentikointiin:
Password for user fourcat: psql: error: connection to server at "db" (172.30.154.239), port 5432 failed: fe_sendauth: no password suppliedTämä johtuu siitä, että vaikka määrittelemme
POSTGRESQL_PASSWORD, sovellus odottaa muuttujaaPGPASSWPRD. Tämä tarkoittaa, että korjaus on: -
Backend-Podin tuloste on nyt paljon pidempi, mutta päättyy tähän virheeseen:
During handling of the above exception, another exception occurred: Traceback (most recent call last): File "helper-scripts/migrate.py", line 336, in <module> finish(args, logger, no_pip=pip_ran) File "helper-scripts/migrate.py", line 122, in finish check_for_nltk() File "helper-scripts/migrate.py", line 74, in check_for_nltk nltk.download('punkt_tab', quiet=True) File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 774, in download for msg in self.incr_download(info_or_id, download_dir, force): File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 642, in incr_download yield from self._download_package(info, download_dir, force) File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 698, in _download_package os.makedirs(download_dir, exist_ok=True) File "/usr/local/lib/python3.8/os.py", line 223, in makedirs mkdir(name, mode) PermissionError: [Errno 13] Permission denied: '/nltk_data'Meidän täytyy tehdä kansiosta
/nltk_datakirjoitettava sovellusta ajavalle käyttäjälle. Jos palaamme tarkistamaan docker compose -määritystä, tätä kansiota ei mainittu siellä. Koska kontit ovat tilattomia, tämä tarkoittaa, että kansioon kirjoitettu data ei säily konttia uudelleenkäynnistettäessä. Helpoin tapa toteuttaa tämä on liittää ephemeral storage -kansio (taiemptyDir). Tämä on nopea väliaikainen tallennustila, joka poistetaan, kun Pod lopetetaan, eli sama toimintatapa kuin docker composessa. Muutos on seuraava: -
Seuraava virhe liittyy jälleen ympäristömuuttujiin:
Creating config/config.ini file Traceback (most recent call last): File "/usr/local/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/local/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/usr/src/app/docker/docker_setup.py", line 88, in <module> update_config_from_environment(CONFIG_FILE, config_parser) File "/usr/src/app/docker/docker_setup.py", line 35, in update_config_from_environment config_parser['DATABASE']['db_password'] = os.environ['POSTGRES_PASSWORD'] File "/usr/local/lib/python3.8/os.py", line 675, in __getitem__ raise KeyError(key) from None KeyError: 'POSTGRES_PASSWORD'Tämä ympäristömuuttuja on kovakoodattu sovelluksen lähdekoodiin. Voisimme paikata koodin, mutta silloin kuva pitäisi rakentaa uudelleen ja paikkausta pitäisi ylläpitää jokaiselle uudelle kuvan versiolle. Kustannustehokkain ratkaisu on määritellä muuttuja kahdesti. Jos muistat, tämän luvun vaiheessa 3 vaihdoimme muuttujan nimen tyydyttääksemme toista osaa koodista.
-
Edistymme, mutta emme ole vielä valmiita. Uusi virhe on:
$ oc logs backend-7f9c9dbfbb-78sh8 -f Waiting for postgres... PostgreSQL started Database already created 4CAT migration agent ------------------------------------------ Interactive: no Pull latest release: no Pull branch: no Restart after migration: no Repository URL: https://github.com/digitalmethodsinitiative/4cat.git .current-version path: config/.current-version Current Datetime: 2024-12-12 07:00:22 WARNING: Migration can take quite a while. 4CAT will not be available during migration. If 4CAT is still running, it will be shut down now (forcibly if necessary). - No PID file found, assuming 4CAT is not running - Version last migrated to: 1.46 - Code version: 1.46 ...already up to date. Migration finished. You can now safely restart 4CAT. Creating config/config.ini file Created config/config.ini file Starting app 4CAT is accessible at: http://localhost Starting 4CAT Backend Daemon... ...error while starting 4CAT Backend Daemon (pidfile not found). tail: cannot open 'logs/backend_4cat.log' for reading: No such file or directory tail: no files remainingTämän ongelman ratkaisemiseksi meillä on taas kaksi vaihtoehtoa: voimme arvata tai käyttää
oc debug-työkalua.oc debugmahdollistaa epäonnistuneen podin käynnistämisen interaktiiviseen istuntoon ilman, että Podin alkuperäistä komentoa suoritetaan.$ oc debug backend-7f9c9dbfbb-78sh8 Starting pod/backend-7f9c9dbfbb-78sh8-debug-vcb6f, command was: docker/docker-entrypoint.sh Pod IP: 10.129.12.120 If you don't see a command prompt, try pressing enter. $ ls logs 4cat.stderr lost+found migrate-backend.log $ df -h Filesystem Size Used Avail Use% Mounted on overlay 1.2T 435G 766G 37% / tmpfs 64M 0 64M 0% /dev shm 64M 0 64M 0% /dev/shm tmpfs 22G 91M 22G 1% /etc/passwd /dev/sda4 90G 17G 73G 19% /nltk_data /dev/sdr 974M 24K 958M 1% /usr/src/app/data /dev/sds 974M 36K 958M 1% /usr/src/app/config /dev/sdq 974M 168K 958M 1% /usr/src/app/logs tmpfs 1.0G 24K 1.0G 1% /run/secrets/kubernetes.io/serviceaccount devtmpfs 4.0M 0 4.0M 0% /proc/keys $Näemme siis, että
logs-kansio on pysyvä taltio eikä lokitiedostoa todellakaan ole siellä. Ratkaisu voisi olla yksinkertaisesti tiedoston luominen, kun olemme vielä debug-istunnossa:On outoa, ettei sovellus luo tiedostoa itse ja ettei tämä ollut ongelma compose-lähestymistavassa. Se on epäilyttävää, mutta jatkamme ja katsomme, aiheuttaako tämä myöhemmin ongelmia. Jotta näemme, ratkaisiko tämä ongelman, meidän täytyy poistaa Pod, jotta uusi luodaan:
-
Katsotaan sitten, epäonnistuuko Pod edelleen:
$ oc get pods NAME READY STATUS RESTARTS AGE backend-7f9c9dbfbb-sznxl 1/1 Running 0 3m22s db-545945c9b8-tkbwc 1/1 Running 0 17hSe on ollut käynnissä muutaman minuutin kaatumatta, mikä on hyvä. Loki näyttää kuitenkin nyt uuden virheen, mikä ei ole yhtä hyvä:
$ oc logs backend-7f9c9dbfbb-sznxl [...] Starting 4CAT Backend Daemon... ...error while starting 4CAT Backend Daemon (pidfile not found).Oletamme, että sovellus yrittää kirjoittaa PID-tiedoston (tiedosto, jossa on prosessin numero; yleinen käytäntö Unixissa) kansioon, johon voi kirjoittaa vain
root. Tämä on tyypillinen virhe tällaisissa muunnoksissa. Loki ei kerro, missä PID-tiedoston pitäisi olla, joten meidän täytyy selvittää se itse. Koska Pod on käynnissä, voimme käyttääoc rsh-työkalua, jolla avataan etäkuori. Tämä toimii vain käynnissä oleviin Podeihin:$ oc rsh deploy/backend $ grep 'pidfile not' -C 4 -nR * 4cat-daemon.py-144- else: 4cat-daemon.py-145- time.sleep(0.1) 4cat-daemon.py-146- 4cat-daemon.py-147- if not pidfile.is_file(): 4cat-daemon.py:148: print("...error while starting 4CAT Backend Daemon (pidfile not found).") 4cat-daemon.py-149- return False 4cat-daemon.py-150- 4cat-daemon.py-151- else: 4cat-daemon.py-152- with pidfile.open() as infile: $ grep pidfile 4cat-daemon.py pidfile = config.get('PATH_ROOT').joinpath(config.get('PATH_LOCKFILE'), "4cat.pid") # pid file location if pidfile.is_file(): with pidfile.open() as infile:Grep-työkalu
Käytimme
grep-työkalua löytääksemme virheilmoituksen koodista ja sitten uudelleen nähdäksemme, missä ja mitenpidfile-muuttuja oli määritelty. Olisimme voineet käyttää paikallista tekstieditoria tai suoraan GitHub-hakua. Mielestänigrepon kuitenkin erinomainen työkalu, ja kaikkien kannattaa opetella sen käyttöä.Nyt tiedämme, että PID-tiedosto tallennetaan kansioon, joka on määritelty muuttujalla
PATH_LOCKFILE. Tarkistetaan, löytyykö seconfig.ini-tiedostosta:$ oc rsh deploy/backend $ grep path -i config/config.ini [PATHS] path_images = data path_data = data path_lockfile = backend path_sessions = config/sessions path_logs = logs/ $ ls -alh backend total 24K drwxr-xr-x. 1 root root 108 Oct 14 10:52 . drwxr-xr-x. 1 root root 30 Dec 12 07:22 .. -rw-r--r--. 1 root root 919 Oct 14 10:52 README.md -rw-r--r--. 1 root root 92 Oct 14 10:52 __init__.py -rw-r--r--. 1 root root 3.4K Oct 14 10:52 bootstrap.py -rw-r--r--. 1 root root 4.7K Oct 14 10:52 database.sql drwxr-xr-x. 2 root root 157 Oct 14 10:52 lib drwxr-xr-x. 2 root root 4.0K Oct 14 10:52 workersTämä oli luultavasti yksi vaikeimmista korjattavista ongelmista ja vaati eniten arvailua. Ratkaisuna muutamme ensin asetuksen
path_lockfiletoiseen arvoon. Esimerkiksipid, joka on mielestäni kuvaava nimi kansiolle. Koskaconfig.inion taltiolla, voimme muuttaa arvon suoraan Podissa (sed -i 's#path_lockfile = backend#path_lockfile = pid#' config/config.ini) tai kopioida tiedoston paikalliselle koneelle (katsooc cp), muokata sitä tekstieditorilla ja kopioida takaisin. Toiseksi lisäämmepid-kansionemptyDir-taltiona: -
Seuraava virhe on tämä:
$ oc logs backend-65cb8dc8dd-8thwg 12-12-2024 12:40:44 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 seconds 12-12-2024 12:40:54 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 seconds 12-12-2024 12:41:04 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 seconds 12-12-2024 12:41:14 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 seconds 12-12-2024 12:41:24 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 seconds 12-12-2024 12:41:34 | INFO at api.py:54: Could not open port 4444 yet ([Errno 99] Cannot assign requested address), retrying in 10 secondsTässä tapauksessa saamme tiedoston ja rivin, jossa virhe tapahtuu:
app.pyrivi 54. Olennaiset osat tiedostosta app.py ovat nämä:Rivillä
50oleva funktio yrittää sitoa portin annettuun isäntänimeen. Compose-lähestymistavassa isäntänimi onbackend, mutta Kubernetesissa tämä ei pidä paikkaansa, koska Podeilla on (osittain) satunnainen nimi. Voisimme muuttaa asetuksen arvostabackendarvoon0.0.0.0, jolloin backend toimisi. Valitettavasti frontend käyttää samaa asetustiedostoa, koska ne jakavat saman taltion.Konfiguraatio taltiolla
Konfiguraatioiden tallentaminen taltiolle ja niiden jakaminen deploymentien välillä on huono käytäntö. Konfiguraatiotiedostoja ei pitäisi muuttaa lennossa. Lisäksi eri deploymentit saattavat tarvita eri konfiguraation.
Tällaisissa sovelluskäyttöönotossa on valitettavasti usein parasta muuttaa mahdollisimman vähän, jotta päivityksiä voidaan edelleen saada upstreamista. Tässä tapauksessa yritämme kopioida konfiguraatiotaltion: yksi frontendille ja toinen backendille (ja "teeskentelemme, ettemme koskaan nähneet tätä"):
$ cp 4cat-config-persistentvolumeclaim.yaml 4cat-config-front-persistentvolumeclaim.yaml $ diff 4cat-config-persistentvolumeclaim.yaml 4cat-config-front-persistentvolumeclaim.yaml -U 2 --- 4cat-config-persistentvolumeclaim.yaml 2024-12-10 15:48:29.123813479 +0200 +++ 4cat-config-front-persistentvolumeclaim.yaml 2024-12-12 15:55:41.207227320 +0200 @@ -4,5 +4,5 @@ labels: io.kompose.service: 4cat-config - name: 4cat-config + name: 4cat-config-front spec: accessModes: $ oc create -f 4cat-config-front-persistentvolumeclaim.yaml persistentvolumeclaim/4cat-config-front createdMeidän täytyy myös muokata
env-configMap-resurssia, koska backend ylikirjoittaaconfig.ini-tiedoston ConfigMapin arvoilla käynnistyessään (toinen asia, josta en erityisesti pidä):
Tämän pitäisi olla kaikki backendiin tarvittavat muutokset:
Frontend-deployment
Tämä on viimeinen korjattava osa.
-
Ennen frontendin käyttöönottoa meidän täytyy muuttaa deployment-tiedostoa käyttämään uutta taltiota:
-
Otetaan nyt frontend käyttöön ja katsotaan tulos:
$ oc create -f frontend-deployment.yaml deployment.apps/frontend created $ oc get pods NAME READY STATUS RESTARTS AGE backend-7f9c9dbfbb-sznxl 1/1 Running 0 125m db-545945c9b8-tkbwc 1/1 Running 0 19h frontend-6b99c94fff-fv5wd 0/1 InvalidImageName 0 2s...saamme tutun virheen, johon on tuttu ratkaisu:
-
Nyt Pod käynnistyy vihdoin, mutta se ei saa yhteyttä backendiin:
$ oc replace -f frontend-deployment.yaml deployment.apps/frontend replaced $ oc get pods NAME READY STATUS RESTARTS AGE backend-7f9c9dbfbb-sznxl 1/1 Running 0 127m db-545945c9b8-tkbwc 1/1 Running 0 19h frontend-9ffbcf6b-wfg98 1/1 Running 0 4s $ oc logs frontend-9ffbcf6b-wfg98 -f Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleeping Backend has not started - sleepingJos katsomme frontendin konfiguraatiokansiota (
/usr/src/app/config/), se on tyhjä. Tämä on helppo ratkaista: kopioimme asetustiedoston backend-kansiosta käyttäenoc cp:Muokkaa tiedostoa vaihtamalla
api_hostpalvelun nimeksi:Kopioi muokattu tiedosto uuteen kansioon:
-
Ratkaisun jälkeen saamme virheen, jonka näimme myös backendissä:
During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.8/runpy.py", line 185, in _run_module_as_main mod_name, mod_spec, code = _get_module_details(mod_name, _Error) File "/usr/local/lib/python3.8/runpy.py", line 111, in _get_module_details __import__(pkg_name) File "/usr/src/app/helper-scripts/migrate.py", line 336, in <module> finish(args, logger, no_pip=pip_ran) File "/usr/src/app/helper-scripts/migrate.py", line 122, in finish check_for_nltk() File "/usr/src/app/helper-scripts/migrate.py", line 74, in check_for_nltk nltk.download('punkt_tab', quiet=True) File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 774, in download for msg in self.incr_download(info_or_id, download_dir, force): File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 642, in incr_download yield from self._download_package(info, download_dir, force) File "/usr/local/lib/python3.8/site-packages/nltk/downloader.py", line 698, in _download_package os.makedirs(download_dir, exist_ok=True) File "/usr/local/lib/python3.8/os.py", line 223, in makedirs mkdir(name, mode) PermissionError: [Errno 13] Permission denied: '/nltk_data'Tämä ratkaistaan samalla tavalla:
-
Lopulta frontend käynnistyy. Näemme, että se kuuntelee porttia
5000, kuten odotettua:[2024-12-13 05:53:41 +0000] [35] [INFO] Starting gunicorn 23.0.0 [2024-12-13 05:53:41 +0000] [35] [DEBUG] Arbiter booted [2024-12-13 05:53:41 +0000] [35] [INFO] Listening at: http://0.0.0.0:5000 (35) [2024-12-13 05:53:41 +0000] [35] [INFO] Using worker: gthread [2024-12-13 05:53:41 +0000] [37] [INFO] Booting worker with pid: 37 [2024-12-13 05:53:41 +0000] [39] [INFO] Booting worker with pid: 39 [2024-12-13 05:53:41 +0000] [41] [INFO] Booting worker with pid: 41 [2024-12-13 05:53:41 +0000] [43] [INFO] Booting worker with pid: 43 [2024-12-13 05:53:41 +0000] [35] [DEBUG] 4 workers -
Pian tämän jälkeen saamme kuitenkin käyttöoikeusvirheen:
Kansiolla
/usr/src/app/webtool/static/css/on käyttöoikeudetdrwxr-xr-x. Tämä tarkoittaa, että vain omistaja (root) voi kirjoittaa siihen. Emme voi käyttää tässäemptyDir-ratkaisua, koska kansio ei ole alkuperäisessä kuvassa tyhjä:root@5878384231b9:/usr/src/app# ls webtool/static/css/ -alh total 160K drwxr-xr-x 2 root root 4.0K Oct 14 10:52 . drwxr-xr-x 7 root root 4.0K Oct 14 10:52 .. -rw-r--r-- 1 root root 569 Oct 14 10:52 colours.css.template -rw-r--r-- 1 root root 4.6K Oct 14 10:52 control-panel.css -rw-r--r-- 1 root root 13K Oct 14 10:52 dataset-page.css -rw-r--r-- 1 root root 8.7K Oct 14 10:52 explorer.css -rw-r--r-- 1 root root 13K Oct 14 10:52 flags.css -rw-r--r-- 1 root root 428 Oct 14 10:52 flowchart.css -rw-r--r-- 1 root root 1.2K Oct 14 10:52 jquery-jsonviewer.css -rw-r--r-- 1 root root 50K Oct 14 10:52 progress.css -rw-r--r-- 1 root root 1.1K Oct 14 10:52 reset.css -rw-r--r-- 1 root root 4.6K Oct 14 10:52 sigma_network.css -rw-r--r-- 1 root root 21K Oct 14 10:52 stylesheet.cssYksinkertaisin käytettävissä oleva ratkaisu on siis luoda oma kuva paikkaamalla nykyistä kuvaa. Käytämme tätä
Dockerfile-tiedostoa:FROM docker.io/digitalmethodsinitiative/4cat:stable RUN chmod g+w /usr/src/app/webtool/static/css/ RUN chmod g+w /usr/src/app/webtool/static/img/favicon/Rahti voi rakentaa sen puolestamme, jos suoritamme tämän komennon:
$ oc new-build -D $'FROM docker.io/digitalmethodsinitiative/4cat:stable RUN chmod g+w /usr/src/app/webtool/static/css/\ RUN chmod g+w /usr/src/app/webtool/static/img/favicon/' \ --to 4cat --> Found container image ca4511d (8 weeks old) from docker.io for "docker.io/digitalmethodsinitiative/4cat:stable" * An image stream tag will be created as "4cat:stable" that will track the source image * A Docker build using a predefined Dockerfile will be created * The resulting image will be pushed to image stream tag "4cat:latest" * Every time "4cat:stable" changes a new build will be triggered --> Creating resources with label build=4cat ... imagestream.image.openshift.io "4cat" created imagestreamtag.image.openshift.io "4cat:latest" created buildconfig.build.openshift.io "4cat" created --> SuccessKäytimme inline Dockerfile -menetelmää, koska
Dockerfileon vain 3 riviä pitkä. Hetken kuluttua meillä on uusi kuva nimeltä 4cat Rahdin sisäisessä rekisterissä. Sisäinen URL onimage-registry.openshift-image-registry.svc:5000/4cat-2/4cat:latest, missä4cat-2on tämän dokumentaation kirjoittamiseen käyttämäni projektin nimi. -
Kun URL on vaihdettu, kaikki näyttää hyvältä 🤞. Meidän täytyy enää julkaista frontend-palvelu Internetiin:
Jos vierailemme URL-osoitteessa http://frontend-4cat-2.2.rahtiapp.fi, näemme vihdoin sovelluksen.

Yhteenveto
Kuten näet, tämän sovelluksen käyttöönotto Rahdissa oli pitkä prosessi. Käytimme kaikkia mahdollisia keinoja, mutta onnistuimme saamaan sen toimimaan Rahdissa. Toivon, että kaikki tekniikat ja perustelut ovat tässä vaiheessa sinulle selviä. Teimme joitakin uskonvaraisia hyppyjä intuition ja kokemuksen perusteella, mutta niitä on vaikea kirjoittaa paperille. Jos seuraat tätä ohjetta oman sovelluksesi kanssa ja sinulla on kysyttävää, ota rohkeasti yhteyttä osoitteeseen servicedesk@csc.fi. Ota yhteyttä myös, jos käytät jotakin muuta tekniikkaa, jota emme tässä käsittele; lisäämme sen tähän ohjeeseen.
Ohjeen lopussa sinulla pitäisi olla deploymentien YAML-tiedostot kaikkine tarvittavine muutoksineen. Yksi tapa jatkaa oppimista ja jäsentää nämä YAML-tiedostot on paketoida ne Helm chartiksi seuraamalla Helm chart -ohjettamme. Näin voit ottaa sovelluksen käyttöön useita kertoja useissa projekteissa (tuotanto, testi, kehitys, ...) yhdellä komennolla ja johdonmukaisesti.