diff --git a/src/kube_deploy/blocks.clj b/src/kube_deploy/blocks.clj index 4ab7301..0babf39 100644 --- a/src/kube_deploy/blocks.clj +++ b/src/kube_deploy/blocks.clj @@ -1,7 +1,6 @@ (ns kube-deploy.blocks (:require [clojure.java.io :as io] [kube-deploy.helpers :as lkh] - [lambdakube.core :as lk])) (def resources-mini @@ -22,115 +21,216 @@ :limits {:cpu "200m" :memory "1Gi"}}) +(defn mosquitto-mqtt [kube-injector] + (-> kube-injector + (lk/rule :mosquitto-master-rule [] + (fn [] + (-> (lk/pod + :mosquitto-master + {:app :footprint :role :master :env :production :tier :database}) + (lk/add-container :mosquitto "eclipse-mosquitto" + (-> {} + (lkh/add-to-spec :resources resources-mini) + (lkh/add-readiness-probe-cmd ["pg_isready"]) + (lkh/add-liveness-probe-cmd ["pg_isready"]) + (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) + (lk/deployment 1) + (lk/expose-cluster-ip :mosquitto-master + (lk/port :mosquitto :mosquitto 1883 1883))))))) -(defn postgres +(defn postgres ([kube-injector] (postgres kube-injector {})) ([kube-injector settings] (let [app-name (get settings :app-name "postgres") app-pod-name (str app-name "-pod") app-rule-name (str app-name "-rule") - app-container-name (str app-name "-container") + app-container-name (keyword (str app-name "-container")) + app-service-name (keyword (str app-name "-service")) app-dependencies (get settings :dependencies []) app-containers 1 app-labels (get settings :labels {:app "postgres"}) app-image (get settings :image "postgres") - app-resources (get settings :resources resources-small)] - (-> kube-injector - (lk/rule :postgres-master-rule [] - (fn [] - (-> (lk/pod - app-pod-name - app-labels - ) - (lk/add-container app-container-name app-image - (-> {} - (lkh/add-to-spec :resources app-resources) - (lkh/add-readiness-probe-cmd ["pg_isready"]) - (lkh/add-liveness-probe-cmd ["pg_isready"]) - (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) - (lk/stateful-set 1) + app-resources (get settings :resources resources-small)] + (-> kube-injector + (lk/rule :postgres-rule [] + (fn [] + (-> (lk/pod + app-pod-name + app-labels) + (lk/add-container app-container-name app-image + (-> {} + (lkh/add-to-spec :resources app-resources) + (lkh/add-readiness-probe-cmd ["pg_isready"]) + (lkh/add-liveness-probe-cmd ["pg_isready"]) + (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]))) + (lk/stateful-set 1) - (lk/add-volume-claim-template :postgres-volume - {:accessModes ["ReadWriteOnce"] - :resources {:requests {:storage "1Gi"}}} - {:bar "/var/lib/postgresql/data"}) - (lk/expose-cluster-ip app-pod-name - (lk/port :postgres :postgres 5432 5432))))))))) + (lk/add-volume-claim-template :postgres-volume + {:accessModes ["ReadWriteOnce"] + :resources {:requests {:storage "1Gi"}}} + {:bar "/var/lib/postgresql/data"}) + (lk/expose-cluster-ip app-service-name ;app-name + (lk/port app-container-name :postgres 5432 5432))))))))) - -(defn django-gunicorn +(defn gunicorn ([kube-injector] - (django-gunicorn kube-injector {})) + (gunicorn kube-injector {})) ([kube-injector settings] - (let [app-name (get settings :app-name "django-gunicorn") - app-pod-name (str app-name "-pod") + (let [app-name (get settings :app-name "gunicorn") + app-pod-name (keyword (str app-name "-pod")) app-rule-name (str app-name "-rule") - app-gunicorn-container-name (str app-name "-container") - app-nginx-container-name (str app-name "-nginx-container") + app-gunicorn-container-name (keyword (str app-name "-container")) + app-nginx-container-name (keyword (str app-name "-nginx-container")) + app-nginx-pod-name (str app-name "-pod") + app-annotations (get settings :annotations {}) app-dependencies (get settings :dependencies []) app-containers 1 - app-labels (get settings :labels {:app "django-gunicorn"}) + app-labels (get settings :labels {:app app-name}) app-image (get settings :image "python:3") - app-resources (get settings :resources resources-small)] + app-resources (get settings :resources resources-small) + app-service-name "gunicorn-service" + app-nginx-service-name "nginx-service" + app-serve-static (get settings :serve-static true)] (-> kube-injector (lk/rule (keyword (str app-name "-rule")) app-dependencies (fn [] - (-> (lk/pod - app-pod-name - app-labels - {:imagePullSecrets [{:name "docker-registry"}]}) + (as-> (lk/pod + app-pod-name + app-labels + {:imagePullSecrets [{:name "docker-registry"}]}) + pod ; Add containers to the pod, one for frontend assets and one for backend - (lk/add-container - app-gunicorn-container-name - app-image - {:resources app-resources - :imagePullPolicy "Always" - :command (get settings :command ["/usr/bin/gunicorn" - "wsgi" - "--workers" "2" - "-k" "gevent" - "--worker-connections" "100" - "--max-requests" "300" - "--keep-alive" "1000" - "-b" "0.0.0.0:5000" - "--chdir=/app"]) - :ports [{:containerPort 5000 :name "gunicorn-port"}] - :envFrom [{:secretRef {:name "environment"}}] - #_(lkh/add-readiness-probe-cmd ["wget" "127.0.0.1:5000"]) - #_(lkh/add-liveness-probe-cmd ["wget" "127.0.0.1:5000"])}) + (lk/add-annotation pod :linkerd.io/inject "enabled") + (lk/add-container + pod + app-gunicorn-container-name + app-image + {:resources app-resources + :imagePullPolicy "Always" + :command (get settings :command ["/usr/bin/gunicorn" + "wsgi" + "--workers" "2" + "-k" "gevent" + "--worker-connections" "100" + "--max-requests" "300" + "--keep-alive" "1000" + "-b" "0.0.0.0:5000" + "--chdir=/app"]) + ;:ports [{:containerPort 5000 :name "gunicorn-port"}] + :envFrom [{:secretRef {:name "environment"}}] + #_(lkh/add-readiness-probe-cmd ["wget" "127.0.0.1:5000"]) + #_(lkh/add-liveness-probe-cmd ["wget" "127.0.0.1:5000"])}) + + (lk/add-init-container + pod + (keyword (str app-name "-init-migrations")) + app-image + (-> {} + (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]) + (lkh/add-to-spec :command ["./manage.py" "migrate"]))) + + (lk/add-init-container + pod + (keyword (str app-name "-init-static-files")) + app-image + (-> {} + (lkh/add-to-spec :envFrom [{:secretRef {:name "environment"}}]) + (lkh/add-to-spec :command ["./manage.py" "collectstatic"]))) + + (if (nil? app-serve-static) + pod + (-> pod + (lk/add-container + app-nginx-container-name + "nginx:alpine" + (-> {} + (lkh/add-to-spec :resources resources-mini) + (lkh/add-to-spec :imagePullPolicy "Always") + ;(lkh/add-to-spec :ports [{:containerPort 80 :name "nginx-port"}]) + #_(lkh/add-readiness-probe-get "127.0.0.1/static/images/favicon.ico" 80) + (lkh/add-liveness-probe-get "http://127.0.0.1/static/admin/css/responsive.css" 80))) + (lk/add-volume :static-files + {:emptyDir {}} + {app-nginx-container-name "/usr/share/nginx/html/static/" + app-gunicorn-container-name "/app/staticfiles"}) + + +;{:mountPath "/usr/share/nginx/html/static/" +; :readOnly true} + + + #_(lk/expose-cluster-ip app-nginx-service-name + (lk/port app-nginx-container-name :nginx-port 80 80)))) - (lk/add-volume "static-files" {:emptyDir {}} - {app-pod-name "/app/staticfiles"}) ; order does matter here, deployment after initcontainers ;(lku/wait-for-service-port postgres :postgres) ;(lku/wait-for-service-port redis :redis) + + #_(lk/add-volume :static-files {:configMap {:name :static-files-config-map}} + {app-nginx-container-name "/app/staticfiles"} + app-gunicorn-container-name "/app/staticfiles") ; wrap in a deployment - (lk/deployment app-containers) - (lk/expose-cluster-ip app-gunicorn-container-name - (lk/port app-pod-name :gunicorn-port 5000 5000)) - (lk/expose-cluster-ip app-nginx-container-name - (lk/port app-pod-name :nginx-port 80 80))))) + (lk/deployment pod 1) + (if (nil? app-serve-static) + pod + (lk/expose-cluster-ip + pod + app-nginx-service-name + (lk/port app-nginx-container-name :nginx-port 80 80))) + + (lk/expose-cluster-ip + pod + app-service-name + (lk/port app-gunicorn-container-name :gunicorn-port 5000 5000)) + #_(lk/expose-cluster-ip app-name + (lk/port app-nginx-container-name :nginx-port 80 80))))) ; inject the ingress required to serve to gunicorn app (lk/rule (keyword (str app-name "-ingress-rule")) [] (fn [] - (let [ingress-name (str app-name "-ingress")] + (let [ingress-name (str app-name "-ingress") + paths []] (-> (lkh/ingress ingress-name {:app :nginx-ingress :env :production :tier :ingress}) (lkh/add-spec :tls [{:hosts [(:ingress-host settings)] - :secretName "letsencrypt-production"}]) + :secretName (str app-name "-tls")}]) (lkh/add-spec :rules [{:host (:ingress-host settings) :http {:paths - [{:path "/" - :backend - {:serviceName "gunicorn-port" - :servicePort 5000}} - {:path "/static/" - :backend - {:serviceName "nginx-port" - :servicePort 80}}]}}]) - (lk/add-annotation :certmanager.k8s.io/cluster-issuer "letsencrypt-production") + (remove nil? + [{:path "/" + :backend + {:serviceName app-service-name + :servicePort 5000}} + (when app-serve-static + {:path "/static/" + :backend + {:serviceName app-nginx-service-name + :servicePort 80}})])}}]) + (lk/add-annotation :kubernetes.io/tls-acme "true") +; (lk/add-annotation :certmanager.k8s.io/cluster-issuer "letsencrypt-production") (lk/add-annotation :kubernetes.io/ingress.class "nginx"))))))))) + +;; (into [] (flatten ["c" [:b 2]] )) + + +;; ;; (bulk-add ) +;; ;; (apply lk/add-annotation (list ["a"] (first {:a 1 :b 2}))) + +;; ;; (defn bulk-add [func obj values] +;; ;; (println (first func)) +;; ;; (if (= 0 (count values)) +;; ;; (recur +;; ;; func +;; ;; (apply func (into [] (flatten [obj (first values)]))) +;; ;; (rest values)) +;; ;; obj)) + +;; ;; (as-> (lk/pod :foo {}) +;; ;; pod +;; ;; (bulk-add lk/add-annotation pod {:a 1 :b 2})) + + +;; ;(apply lk/add-annotation pod (first {:a 1 :b 2})) diff --git a/src/kube_deploy/core.clj b/src/kube_deploy/core.clj index 28e5f05..d5d7cd3 100644 --- a/src/kube_deploy/core.clj +++ b/src/kube_deploy/core.clj @@ -425,7 +425,7 @@ (-> (lk/injector) (make-namespace namespace) lk/standard-descs - (lk/get-deployable config) + (lk/get-deployable deployment-config) (lkh/to-yaml-store (str namespace "-store.yaml")) (kube-apply (io/file (str namespace "-deploy.yaml")) nil kube-config)) @@ -481,17 +481,19 @@ (defn apply-blocks [kube-injector func settings] + (println (first func)) + (println kube-injector) (if (= 0 (count func)) - kube-injector - (recur + kube-injector + (recur (case (first func) - "database" (database kube-injector) - "postgres" (block/postgres kube-injector) - "django-gunicorn" (block/django-gunicorn kube-injector (get-in settings [(keyword (first func))])) + :database (database kube-injector) + :postgres (block/postgres kube-injector) + :mosquitto (block/mosquitto-mqtt kube-injector) + :django-gunicorn (block/gunicorn kube-injector (get-in settings [(keyword (first func))])) kube-injector) - (rest func) - settings - ))) + (rest func) + settings))) (defn build [{:keys [config namespace blocks] :as service}] @@ -501,7 +503,7 @@ (create-namespace-if-not-exists service) (let [injector (lk/injector)] (-> injector - ;(make-environment-secrets :environment (:vars @conf)) + (make-environment-secrets :environment (:vars @conf)) ;(make-registry-secrets :docker-registry {:.dockerconfigjson (:registry @conf)}) ;; make-ingress-hackspace ;; database