Hyppää sisältöön

Docs CSC now features an automatic Finnish translation. Click here for more information.

Warning!

Puhti and Mahti will be decommissioned after Roihu becomes available. Users should clean up unnecessary files and move any required data by the end of August 2026. See the Roihu data preparation instructions for details.

Puhti scratch is very full: keep only active data there and move or delete everything else. No new Puhti scratch quota will be granted.

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ä opas on pitkämuotoinen: siinä selitetään 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 mihin tahansa muuhun sovellukseen, jossa on samankaltaisia oireita. Jätämme pois joitakin virheellisiä ratkaisuja ja harhapolkuja, joita seurasin yrittäessäni alun perin ottaa tätä sovellusta käyttöön, jotta tämä opas 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:

  1. Voimme testata sovelluksen käyttöönottoa docker composella ja nähdä, miltä se näyttää.
  2. Meidän ei tarvitse luoda docker-konttia alusta asti.
  3. Voimme käyttää docker compose -käyttöönottoa pohjana ja sovittaa sen Kubernetes-käyttöönotoksi kompose -työkalulla. Tämä työkalu on suunniteltu erityisesti 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!". Ja se todella säästää paljon työlästä muunnosaikaa, mutta siihen työ ei vielä lopu.

Linux 🐧 on käytössä kaikissa esimerkeissä

Olemme valmistelleet tämän oppaan 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ä oppaan seuraamiseen. Tämä on hyödyllistä myös Linux-käyttäjille, koska voit asentaa, poistaa tai vaihtaa ohjelmistoja ilman riskiä paikallisen asennuksesi rikkoutumisesta.

Docker compose

  1. Ennen jatkamista tarvitsemme dockerin ja docker compose -liitännäisen asennettuna. Ohjeet docker composen asentamiseen löytyvät täältä:

    Debianissa ja Ubuntussa voit asentaa sen näin:

    sudo apt-get update
    sudo apt-get install docker.io docker-compose
    

    Vaihtoehdot dockerille 🐋

    Voit käyttää myös podman composea tai vastaavaa, mutta käytämme dockeria, koska se on yleisin työkalu.

  2. 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 kloonatussa kansiossa:

    git clone https://github.com/uh-dcm/4cat_fi
    cd 4cat_fi
    sudo docker compose up
    

    Tämä käynnistää sovelluksen käyttöönoton koneella. Levykuvien noutaminen ja sovelluksen konfigurointi voi kestää jonkin aikaa. Jos painat Ctrl+C, sovellus sulkeutuu. Jos haluat ajaa sen taustalla, lisää vain -d tai --detach docker-compose-komentoon.

    docker-compose output

    Hetken kuluttua sovellus on saatavilla portissa 80 (PUBLIC_PORT):

    4cat first run

Analyysi

Tiedosto docker-compose.yml 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 tiedosto .env:

# 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:

  • image on levykuva, jonka docker noutaa ja suorittaa jokaiselle palvelulle. Meidän tapauksessamme käytössä on kaksi eri levykuvaa: postgres-levykuva (tunnettu tietokanta) ja 4cat_fi-levykuva. Frontend ja backend käyttävät samaa levykuvaa, mutta niillä on eri command/entry point. Koska docker compose toimii, tiedämme, että molemmat levykuvat ovat olemassa ja ne voidaan noutaa ilman ongelmia.
  • environment ja env_file määrittelevät ympäristömuuttujat, joilla palvelut konfiguroidaan. Esimerkiksi POSTGRES_PASSWORD-muuttujaa käytetään tietokannan salasanan välittämiseen.
  • volumes kertoo dockerille, mitkä taltiot pitää liittää palveluun ja mihin kansioon ne pitää liittää.
  • ports kertoo julkiset portit, sisäiset portit ja niiden välisen kartoituksen. Merkintätapa on <external_port>:<internal_port>.
  • entrypoint ja command ovat komennot, jotka suoritetaan, kun levykuva käynnistetään. Postgresilla ei ole kumpaakaan, koska käytämme levykuvassa määriteltyä oletus-command/entrypoint-asetusta.

Volumes-osio on yksinkertaisempi ja sisältää vain nimilistan. 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 rajan mukaan. Kubernetesin taltioilla on koko, ja meidän täytyy ottaa se huomioon muunnosta tehdessä.

.env-tiedosto sisältää oletusarvot sovelluksen oikeaa käyttöönottoa varten. Esimerkiksi PUBLIC_PORT on asetettu arvoon 80.

Kompose

Kompose antaa meille mahdollisuuden muuntaa docker-compose.yaml-tiedoston joukoksi Kubernetes YAML -tiedostoja.

  1. Meillä täytyy olla kompose asennettuna. Voit seurata ohjeita täältä:

    Koska docker on jo asennettu, voimme käyttää docker-menetelmää, joka rakentaa levykuvan lähdekoodista:

    sudo docker build -t kompose https://github.com/kubernetes/kompose.git\#main
    
  2. Suorita kompose (kun olet 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
    
  3. Sinulla pitäisi nyt olla muutama uusi tiedosto luotuna:

    • "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 4 tyyppisiä tiedostoja: service, deployment, configmap ja persistentvolumeclaim. Aloitetaan yksinkertaisimmista:

  • persistentvolumeclaim-tiedostot ovat taltioiden määritelmiä. Jokaisesta docker compose -tiedoston volume-määrittelystä tulee 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: 100Mi
    

    Näemme, että name on säilytetty compose-määrittelystä (kohdassa metadata > name). accessMode on asetettu arvoon ReadWriteOnce, mikä tarkoittaa, että taltio voidaan liittää vain kerran. Lopuksi koko on oletuksena 100Mi (kohdassa spec > resources > request > storage).

  • configmap-tiedosto(t) tallentavat konfiguraation. Meidän tapauksessamme .env-tiedostossa määritellyt (ei docker-compose-spesifiset) muuttujat on muunnettu tiedostoon env-configmap.yaml. name on asetettu arvoon env, ja muuttujat on määritelty data-osion alla.

  • service-tiedostot määrittelevät "vakaat verkkoidentiteetit", jotka toimivat kuormantasaajina. Jokaiselle deployment-resurssille luodaan palvelu, ja se vie ulos kaikki portit, joita käyttöönotto tarjoaa. Esimerkiksi tiedostossa frontend-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: frontend
    

    Kaksi olennaista osaa ovat selector ja ports. Ensimmäinen yhdistää palvelun deployment-resurssiin ja toinen listaa portit, jotka tämä palvelu vie ulos. Katso lisätietoja palveluista.

  • deployment on monimutkaisin luotu konfiguraatio. Voimme yrittää kartoittaa docker-compose.yaml-tiedoston konfiguraation 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-db
    
    • image on määritelty kohdassa spec > template > spec > containers > image, ja tässä tapauksessa se on postgres:. Tämä on virhe, koska tagi latest puuttuu; korjaamme tämän myöhemmin.
    • environment on määritelty kohdassa spec > template > spec > containers > env, mutta myös arvot puuttuvat.
    • volumes on määritelty kohdissa spec > template > spec > volumes ja spec > template > spec > containers > volumeMounts.
    • ports on määritelty kohdassa spec > template > spec > containers > ports sekä jo mainituissa vastaavissa service-tiedostoissa.
    • Lopuksi command on määritelty kohdassa spec > template > spec > containers > command (näet esimerkin tiedostossa backend-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ä 3 tyyppiä ovat suoraviivaisia eikä niiden pitäisi aiheuttaa ongelmia.

  1. 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 created
    

    Tämä luo 4 taltiota tilaan Pending. Ne pysyvät tilassa Pending, kunnes otamme deployments-resurssit käyttöön. Tämä on odotettua.

  2. 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      5m45s
    

    Kaksi muuta merkintää (kube-root-cs.crt ja openshift-service-ca.crt) ovat valmiiksi luotuja Kubernetesin ja OpenShiftin perus-ConfigMap-resursseja.

  3. 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   21h
    

    Tulos on backendin osalta odotettu, koska kartoitus oli 4444:4444. Frontendin osalta ei, koska alkuperäinen oli 80:5000. Tämä ei ole iso ongelma, koska jotta palveluun pääsee Rahdin ulkopuolelta, käytämme Route-resurssia, ja Route mahdollistaa minkä tahansa portin muuntamisen ja julkaisemisen vakioportteihin 80/443. Jätämme sen sellaiseksi.

Tietokannan Deployments-resurssit

Lopuksi luomme deployments-resurssit. Meillä on 3 deployment-resurssia, ja aloitamme tietokannan deploymentista.

  1. Luodaan ensin nykyinen versio:

    $ oc create -f db-deployment.yaml
    deployment.apps/db created
    
    $ oc get pods
    NAME                  READY   STATUS             RESTARTS   AGE
    db-66db46fb89-vzqrz   0/1     InvalidImageName   0          26s
    
  2. Tämä on odotettua, koska tagi latest puuttui levykuvan nimestä. Korjataan se ja yritetään uudelleen. Muokkaa siis tiedostoa db-deployment.yaml, lisää latest levykuvan arvoon niin, että se näyttää tältä: postgres:latest,

                 - name: POSTGRES_USER
    -          image: 'postgres:'
    +          image: 'postgres:latest'
               livenessProbe:
                 exec:
    

    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)   24s
    

    YAML-tiedostot

    Teemme muutokset YAML-tiedostoihin, jotta voimme myöhemmin luoda koko käyttöönoton uudelleen. Voit myös lisätä tiedostot Git-repositorioon ja commitoida jokaisen muutoksen, jolloin muutosten historia ja perustelut näkyvät myöhemmin selkeästi commit-historiassa.

  3. 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.html
    

    Tä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.html
    

    Yllä olevassa esimerkissä lisäsimme -u 1000, jotta UID vaihdetaan ei-root-UID:ksi ja voimme toistaa saman virheen, jonka Rahti näyttää. Mikä tahansa satunnainen UID käy; näin Rahti suorittaa levykuvia (satunnaisilla UID:illa). Toistetaan tämä niin, että POSTGRES_PASSWORD-muuttuja on määritelty ehdotetulla tavalla:

    $ 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 permitted
    

    Tässä tapauksessa näemme, että tämä konttilevykuva ei koskaan toimi Rahdissa, koska sen täytyy pystyä muuttamaan kansioiden käyttöoikeuksia. Onneksi Rahti/OpenShift tarjoaa PostgreSQL-mallin, joka on saatavilla ohjelmistokatalogissa.

    Developer Catalog

    Mallin kuvauksessa näemme linkin GitHub-sivulle https://github.com/sclorg/postgresql-container/. Sivulla näkyy lista kaikista saatavilla olevista levykuvista. Valitsemme quay.io/sclorg/postgresql-15-c9s, koska se on uusin saatavilla oleva versio ja käyttää CentOS 9:ää pohjana.

  4. Kun levykuva on vaihdettu (postgres:latestquay.io/sclorg/postgresql-15-c9s:latest), lokit ovat:

    $ 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 toimii nyt odotetusti:

    $ oc get pods
    NAME                  READY   STATUS    RESTARTS   AGE
    db-58947cf497-p4vnq   1/1     Running   0          66s
    

Backend-deployment

Tämä deployment tarvitsee myös muutamia muutoksia. Käydään ne läpi toivottavasti hieman ketterämmin:

  1. Korjaa levykuvan nimi. Virhe:

    $ oc get pods
    NAME                       READY   STATUS             RESTARTS   AGE
    backend-7f47d4c5d4-zrxjp   0/1     InvalidImageName   0          41s
    

    Ratkaisu:

                       key: workers
                       name: env
    -          image: 'digitalmethodsinitiative/4cat:'
    +          image: 'digitalmethodsinitiative/4cat:stable'
               name: 4cat-backend
               ports:
    
  2. Lisää DB-palvelu ratkaistaksesi tämän ongelman:

    db: forward host lookup failed: Unknown host
    

    Tämä vaatii, että luomme db-palvelun:

    $ oc expose deploy/db --port 5432
    service/db exposed
    
  3. 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 supplied
    

    Tämä johtuu siitä, että vaikka määrittelemme POSTGRESQL_PASSWORD, sovellus odottaa muuttujaa PGPASSWPRD. Tämä tarkoittaa, että korjaus on:

                       key: POSTGRES_HOST_AUTH_METHOD
                       name: env
    -            - name: POSTGRES_PASSWORD
    +            - name: PGPASSWORD
                   valueFrom:
                     configMapKeyRef:
    
  4. 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_data kirjoitettava sovellusta ajavalle käyttäjälle. Jos palaamme tarkistamaan docker composea, tätä kansiota ei mainittu. Koska kontit ovat tilattomia, tämä tarkoittaa, että kansioon kirjoitettu data ei säily käynnistysten yli. Helpoin tapa toteuttaa tämä on liittää ephemeral storage -kansio (tai emptyDir). Tämä on nopea väliaikainen tallennustila, joka poistetaan, kun Pod lopetetaan, eli sama toiminta kuin docker compose -ratkaisussa. Muutos on seuraava:

                   protocol: TCP
               volumeMounts:
    +            - mountPath: /nltk_data
    +              name: nltk-data
                 - mountPath: /usr/src/app/data
                   name: 4cat-data
    @@ -151,4 +153,6 @@
           restartPolicy: Always
           volumes:
    +        - name: nltk-data
    +          emptyDir: {}
             - name: 4cat-data
               persistentVolumeClaim:
    
  5. Seuraava virhe liittyy taas 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 koodiin. Voisimme paikata koodin, mutta se tarkoittaisi levykuvan uudelleenrakentamista ja koodin paikkaamista jokaiselle uudelle levykuvaversiolle. Kustannustehokkain ratkaisu on määritellä muuttuja kahdesti. Jos muistat, tämän luvun vaiheessa 3 muutimme muuttujan nimeä tyydyttääksemme toista osaa koodista.

                       key: POSTGRES_PASSWORD
                       name: env
    +            - name: POSTGRES_PASSWORD
    +              valueFrom:
    +                configMapKeyRef:
    +                  key: POSTGRES_PASSWORD
    +                  name: env
                 - name: POSTGRES_PORT
                   valueFrom:
    
  6. 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 remaining
    

    Tämän ongelman ratkaisemiseksi meillä on taas kaksi vaihtoehtoa: voimme arvata tai käyttää oc debug -työkalua. oc debug antaa mahdollisuuden käynnistää epäonnistunut pod interaktiivisessa istunnossa 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 samalla kun olemme debug-istunnossa:

    $ touch logs/backend_4cat.log
    

    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, muodostuuko tästä myöhemmin ongelma. Jotta näemme, ratkaisiko korjaus ongelman, meidän täytyy poistaa Pod, jotta uusi luodaan:

    $ oc get pods
    NAME                       READY   STATUS    RESTARTS        AGE
    backend-7f9c9dbfbb-78sh8   1/1     Running   7 (7m49s ago)   21m
    db-545945c9b8-tkbwc        1/1     Running   0               17h
    
    $ oc delete pod backend-7f9c9dbfbb-78sh8
    pod "backend-7f9c9dbfbb-78sh8" deleted
    
  7. Ja 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          17h
    

    Se on ollut käynnissä muutaman minuutin kaatumatta, mikä on hyvä. Mutta loki näyttää 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 miten pidfile-muuttuja oli määritelty. Olisimme voineet käyttää paikallista tekstieditoria tai suoraan GitHub-hakua. Minusta grep on vain erinomainen työkalu, ja kaikkien kannattaa osata käyttää sitä.

    Nyt tiedämme, että PID-tiedosto tallennetaan kansioon, joka on määritelty muuttujalla PATH_LOCKFILE. Tarkistetaan, löytyykö se config.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 workers
    

    Tämä oli luultavasti yksi vaikeimmista korjattavista ongelmista ja se, joka vaati eniten arvailua. Ratkaisuna muutamme ensin konfiguraation path_lockfile-arvon toiseksi. Esimerkiksi pid, joka on mielestäni kuvaava nimi kansiolle. Koska config.ini on taltiolla, voimme muuttaa arvon suoraan Podissa (sed -i 's#path_lockfile = backend#path_lockfile = pid#' config/config.ini) tai kopioida tiedoston paikalliselle koneelle (katso oc cp), muokata sitä tekstieditorilla ja kopioida takaisin. Toiseksi lisäämme pid-kansion emptyDir-resurssina:

    @@ -150,4 +150,6 @@
                 - mountPath: /nltk_data
                   name: nltk-data
    +            - mountPath: /usr/src/app/pid
    +              name: pid
                 - mountPath: /usr/src/app/data
                   name: 4cat-data
    @@ -160,4 +162,6 @@
             - name: nltk-data
               emptyDir: {}
    +        - name: pid
    +          emptyDir: {}
             - name: 4cat-data
               persistentVolumeClaim:
    
  8. Seuraava virheemme on seuraava:

    $ 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 seconds
    

    Tässä tapauksessa saamme tiedoston ja rivin, jossa virhe tapahtuu: app.py rivi 54. Olennaiset osat tiedostosta app.py ovat nämä:

      host = config.get('API_HOST')
      port = config.get('API_PORT')
    
    while has_time:
            has_time = start_trying > time.time() - 300  # stop trying after 5 minutes
            try:
                server.bind((self.host, self.port))
                break
            except OSError as e:
                if has_time and not self.interrupted:
                    self.manager.log.info("Could not open port %i yet (%s), retrying in 10 seconds" % (self.port, e))
                    time.sleep(10.0)  # wait a few seconds before retrying
                    continue
                self.manager.log.error("Port %s is already in use! Local API not available. Check if a residual 4CAT process may still be listening at the port." % self.port)
                return
            except ConnectionRefusedError:
                self.manager.log.error("OS refused listening at port %i! Local API not available." % self.port)
                return
    

    Rivillä 50 oleva funktio yrittää sitoa portin annettuun isäntänimeen. Compose-lähestymistavassa isäntänimi on backend, mutta Kubernetesissa tämä ei pidä paikkaansa, koska Podeilla on (osittain) satunnainen nimi. Voisimme muuttaa konfiguraation arvosta backend arvoon 0.0.0.0, jolloin backend toimisi. Valitettavasti frontend käyttää samaa konfiguraatiotiedostoa, 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 voimme edelleen saada päivityksiä upstreamista. Tässä tapauksessa yritämme kahdentaa konfiguraatiotaltion: yksi frontendille ja yksi 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 created
    

    Meidän täytyy myös muokata env-configMap-resurssia, koska backend ylikirjoittaa config.ini-tiedoston ConfigMapin perusteella käynnistyessään (toinen asia, josta en erityisemmin pidä):

     apiVersion: v1
     data:
    -  API_HOST: backend
    +  API_HOST: 0.0.0.0
       DOCKER_CONFIG_VOL: 4cat_4cat_config
       DOCKER_DATA_VOL: 4cat_4cat_data
    
    $ oc replace -f env-configmap.yaml
    configmap/env replaced
    

Tämän pitäisi olla kaikki backendiin tarvittavat muutokset:

12-12-2024 14:03:30 | INFO at api.py:65: Local API listening for requests at 0.0.0.0:4444

Frontend-deployment

Tämä on viimeinen korjattava osa.

  1. Ennen frontendin käyttöönottoa meidän täytyy muuttaa deployment-tiedostoa käyttämään uutta taltiota:

    @@ -158,5 +168,5 @@
             - name: 4cat-config
               persistentVolumeClaim:
    -            claimName: 4cat-config
    +            claimName: 4cat-config-front
             - name: 4cat-logs
               persistentVolumeClaim:
    
  2. 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:

                       key: workers
                       name: env
    -          image: 'digitalmethodsinitiative/4cat:'
    +          image: 'digitalmethodsinitiative/4cat:stable'
               name: 4cat-frontend
               ports:
    
  3. Nyt Podit käynnistyvät vihdoin, mutta frontend 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 - sleeping
    

    Jos katsomme frontendin config-kansiota (/usr/src/app/config/), se on tyhjä. Tämä on helppo ratkaista: kopioimme konfiguraatiotiedoston backend-kansiosta käyttäen oc cp -komentoa:

    $ oc cp backend-65cb8dc8dd-nxq6p:config/config.ini config.ini
    

    Muokkaa tiedostoa vaihtamalla api_host palvelun nimeksi:

         [API]
     api_port = 4444
    -api_host = 0.0.0.0
    +api_host = backend
    
     [PATHS]
    

    Kopioi muokattu tiedosto uuteen kansioon:

    $ oc cp config.ini frontend-79864b8548-pvh8z:config/
    
  4. 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:

    @@ -145,4 +155,6 @@
                   protocol: TCP
               volumeMounts:
    +            - mountPath: /nltk_data
    +              name: nltk-data
                 - mountPath: /usr/src/app/data
                   name: 4cat-data
    @@ -153,4 +165,6 @@
           restartPolicy: Always
           volumes:
    +        - name: nltk-data
    +          emptyDir: {}
             - name: 4cat-data
               persistentVolumeClaim:
    
  5. 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
    
  6. Mutta pian tämän jälkeen saamme käyttöoikeusvirheen:

    PermissionError: [Errno 13] Permission denied: '/usr/src/app/webtool/static/css/colours.css'
    

    Kansiolla /usr/src/app/webtool/static/css/ on oikeudet drwxr-xr-x. Tämä tarkoittaa, että vain omistaja (root) voi kirjoittaa siihen. Emme voi käyttää tällä kertaa emptyDir-ratkaisua, koska kansio ei ole alkuperäisessä levykuvassa 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.css
    

    Yksinkertaisin saatavilla oleva ratkaisu on siis luoda oma levykuva paikkaamalla nykyistä. 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
      --> Success
    

    Käytimme inline Dockerfile -menetelmää, koska Dockerfile on vain 3 riviä pitkä. Hetken kuluttua meillä on uusi levykuva nimeltä 4cat Rahdin sisäisessä rekisterissä. Sisäinen URL on image-registry.openshift-image-registry.svc:5000/4cat-2/4cat:latest, missä 4cat-2 on tämän dokumentaation kirjoittamiseen käyttämäni projektin nimi.

                       key: workers
                       name: env
    -          image: 'digitalmethodsinitiative/4cat:'
    +          image: 'image-registry.openshift-image-registry.svc:5000/4cat-2/4cat:latest'
               name: 4cat-frontend
               ports:
    
  7. Kun URL on vaihdettu, kaikki näyttää hyvältä 🤞. Meidän täytyy enää julkaista frontend-palvelu Internetiin:

    $ oc expose svc/frontend
    route/frontend exposed
    
    $ oc get route
    NAME       HOST/PORT                       PATH   SERVICES   PORT   TERMINATION   WILDCARD
    frontend   frontend-4cat-2.2.rahtiapp.fi          frontend   5000                 None
    

Jos vierailemme URL-osoitteessa http://frontend-4cat-2.2.rahtiapp.fi, näemme vihdoin sovelluksen.

4cat in Rahti

Yhteenveto

Kuten näet, tämän sovelluksen käyttöönotto Rahdissa oli pitkä prosessi. Käytimme kaikkia mahdollisia keinoja, mutta saimme sen lopulta toimimaan Rahdissa. Toivon, että kaikki tekniikat ja perustelut ovat tässä vaiheessa sinulle selviä. Otimme joitakin uskonloikkia intuition ja kokemuksen perusteella, mutta uskonloikkia ja kokemusta on vaikea kirjoittaa paperille. Jos seuraat tätä opasta oman sovelluksesi kanssa ja sinulla on kysyttävää, älä epäröi ottaa meihin yhteyttä osoitteessa 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 oppaaseen.

Oppaan lopussa sinulla pitäisi olla deployment-YAML-tiedostot kaikkine tarvittavine muutoksineen. Yksi tapa jatkaa oppimista ja jäsentää nämä YAML-tiedostot on paketoida ne Helm chartiksi seuraamalla Helm chart -opastamme. Näin voit ottaa sovelluksen käyttöön useita kertoja useissa projekteissa (tuotanto, testaus, kehitys, ...) yhdellä komennolla ja johdonmukaisesti.

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta