2017-06-21 1 views
1

Ich schicke meine Phoenix-App zum Testen über GitLab an einen Kubernetes-Cluster. Ich möchte mix ecto.migrate in meinem Skript gitlab-ci.yml ausführen können, sobald meine App und der Postgres-Dienst bereit sind. Hier ist ein Ausschnitt aus der gitlab-ci.yml Datei:GitLab CI/Kubernetes - Postgres-Migration für Test-Env ausführen (keine Produktion)

review: 
    stage: review 
    image: dtzar/helm-kubectl 

    environment: 
    name: review/$CI_COMMIT_REF_NAME 
    url: https://$CI_PROJECT_NAME-${CI_ENVIRONMENT_SLUG}.$KUBE_DOMAIN 
    on_stop: stop_review 

    before_script: 
    - command deploy/kinit.sh 

    script: 
    - helm upgrade --install db --wait --set postgresDatabase=app_db stable/postgresql 
    - helm upgrade --install app ./deploy/app_chart --wait --set env.DATABASE_URL="${DATABASE_URL}" 

    - export POD_NAME=`kubectl get pod -l "app=${CI_ENVIRONMENT_SLUG}" -o jsonpath='{.items[0].metadata.name}'` 
    - kubectl exec $POD_NAME -- mix ecto.migrate 

Von dem, was ich verstehe, die --wait Parameter bedeuten, dass jeder Einsatz (in ihrer Gesamtheit) beenden, bevor Sie fortfahren. Was ich finde, ist, dass, obwohl die postgres-Bereitstellung abgeschlossen ist, das nicht bedeutet, dass der postgres-Server bereit ist.

Mehr als oft nicht, wenn der kubectl exec Befehl ausgeführt wird, erhalte ich folgende Fehlermeldung:

** (exit) exited in: :gen_server.call(#PID<0.183.0>, {:checkout, #Reference<0.0.1.2678>, true, :infinity}, 5000) 
    ** (EXIT) time out 
    (db_connection) lib/db_connection/poolboy.ex:112: DBConnection.Poolboy.checkout/3 
    (db_connection) lib/db_connection.ex:919: DBConnection.checkout/2 
    (db_connection) lib/db_connection.ex:741: DBConnection.run/3 
    (db_connection) lib/db_connection.ex:1132: DBConnection.run_meter/3 
    (db_connection) lib/db_connection.ex:584: DBConnection.prepare_execute/4 
    (ecto) lib/ecto/adapters/postgres/connection.ex:93: Ecto.Adapters.Postgres.Connection.execute/4 
    (ecto) lib/ecto/adapters/sql.ex:243: Ecto.Adapters.SQL.sql_call/6 
    (ecto) lib/ecto/adapters/sql.ex:193: Ecto.Adapters.SQL.query!/5 

Als ich im Kubernetes ui aussehen, kann ich folgende Fehlermeldung gegen mein Postgres pod sehen:

SchedulerPredicates failed due to PersistentVolumeClaim is not bound: "db-postgresql", which is unexpected. 

Nachdem ich diese Nachricht gesehen habe, überwache ich die Pods und alles kommt gut. Aber nicht bevor mein Deployment-Skript fehlschlägt.

Mein erster Gedanke ist, dass ich eine initContainer für meine App erstellen konnte, die psql verwendet, um erfolgreich eine Verbindung zum Server herzustellen und das Vorhandensein der Datenbank "app_db" zu überprüfen. Auf diese Weise muss ich mir keine Gedanken darüber machen, meinen eigenen Code für Timeouts und Wiederholungen zu schreiben - ich kann einfach den integrierten Mechanismus von Kubernetes nutzen.

Ich möchte dies jedoch nicht in meiner Produktionsumgebung (Ich möchte mix ecto.migrate auf dem Produktionssystem manuell ausführen). In diesem Fall dient die initContainer einfach als Verschwendung von Systemressourcen.

Gibt es eine robuste Möglichkeit, die ich durch das gitlab-ci.yml Skript erreichen kann?

Antwort

1

Aus konzeptioneller Sicht würde ich:

  1. Konfigurieren ein readiness probe auf meinem Postgres Behälter, so dass der Pod nicht „Running“ betrachtet, bis der Motor ist.

    # in the Pod template: 
    # spec.containers['postgres'] 
    
    readinessProbe: 
        exec: 
        command: 
        - psql 
        - -U 
        - postgres 
        - -c 
        - 'SELECT 1' 
        initialDelaySeconds: 5 
        periodSeconds: 5 
    
  2. Warten Sie die Pod auf einen Zustand „Running“ zu überführen, bevor meine Mix Aufgabe ausgeführt wird.

    # in gitlab-ci.yml, before "mix ecto.migrate" 
    
    - | 
        while [ "$(kubectl get pod $POD_NAME -o jsonpath='{$.status.phase}')" != "Running" ]; do 
         sleep 1; 
        done 
    
+0

, die wie eine gute Idee klingt. Ich starte nur den 'postgres'-Server in meiner Staging-Umgebung, daher ist es sinnvoll, dass der' postgres'-Pod den Test/Probe hat, der den "running" -Zustand steuert. In der Vergangenheit habe ich diese Lösung vermieden, weil ich das Standardhelmdiagramm verwenden wollte. Leider bietet es [https://github.com/sapcc/helm-charts/blob/master/common/postgresql/templates/deployment.yaml] keine Möglichkeit, die Bereitschaftssonde neu zu konfigurieren. Was bedeutet, dass ich es abzweigen und pflegen muss. Nicht das Ende der Welt, aber es wäre schön gewesen – Mitkins

+0

Ich sehe das Diagramm verwendet den 'pg_isready' Befehl, es sollte auch eine zuverlässige genug Sonde sein, ist es nicht in der Praxis? –

+0

Wenn ich mich nicht irre mit dem Verhalten des Steuerelements '--wait' Parameter - nein, es scheint nicht genug zu sein. Ich könnte versuchen, den 'get pod' Befehl zu verwenden, den Sie vorgeschlagen haben und sehen, ob das einen Unterschied macht – Mitkins