From 7f6ec62af5eaa95a52882193ebb1d3e4f47522a3 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Sun, 22 Sep 2024 15:53:55 +0300 Subject: [PATCH 1/3] k8s migration --- content/en/hosting/kubernetes-vs-docker.md | 496 +++++++++++++++++++++ 1 file changed, 496 insertions(+) diff --git a/content/en/hosting/kubernetes-vs-docker.md b/content/en/hosting/kubernetes-vs-docker.md index 1cdd945b0..4590d4cd5 100644 --- a/content/en/hosting/kubernetes-vs-docker.md +++ b/content/en/hosting/kubernetes-vs-docker.md @@ -33,6 +33,7 @@ The main components of a Kubernetes deployment include: * A CHT HAProxy pod. * Upgrade Service pod. * CHT-Sentinel pod. + ## Docker Compose The Docker Compose based CHT Core deployment was Medic's first attempt to make CHT 4.x cloud native. The Compose files work quite well for application developer setups on laptops and the like (check out the [Docker Helper]({{< relref "hosting/4.x/app-developer#cht-docker-helper-for-4x" >}})!). Additionally, we have existing published guides on how to deploy single and multi-node Compose based solutions. For small, low use instances, likely the single node Compose deployments will be fine. We do not recommend setting up a multi-node deployment on Compose with an overlay network. Please use Kubernetes instead for a more stable and [horizontally scalable]({{< relref "hosting/vertical-vs-horizontal" >}}) solution. @@ -48,3 +49,498 @@ Like Kubernetes above, Docker Compose deploys the same services but adds an addi * Upgrade Service service. * A CHT Sentinel service. * An nginx service to act as a reverse proxy and terminate TLS connections + +## Migrating from docker to kubernetes + +### Using kubectl + +This guide is oriented towards migrating a docker compose CHT instance hosted on a single machine into a kubernetes cluster. The machine will be enjoined as a node to the cluster. + +Optional: + +When using K3S to run your kubernetes cluster, install it on the node using this command: +```shell +curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" INSTALL_K3S_EXEC="agent" INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -s - --docker --token {{cluster_token}} --server https://:6443 +``` + +1. Create a namespace for your project + +```shell +kubectl create namespace my_cht_project_namespace +``` + +2. Setup Credentials + +```shell +kubectl -n y_cht_project_namespace apply -f credentials.yaml +``` +With credentials.yaml as: +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: cht-couchdb-credentials +type: Opaque +stringData: + COUCHDB_PASSWORD: + COUCHDB_SECRET: + COUCHDB_USER: + COUCHDB_UUID: + COUCH_URL: http://:@haproxy.y_cht_project_namespace.svc.cluster.local:5984/medic +``` + +3. Create Roles & RoleBindings + +```shell +kubectl -n my_cht_project_namespace apply -f roles.yaml +``` +With roles.yaml as: +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: deployment-manager +rules: +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - update + - watch + - patch + - list +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - update + - watch + - patch + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: deployment-manager-cht +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: deployment-manager +subjects: +- apiGroup: "" + kind: ServiceAccount + name: cht-upgrade-service-user +``` + +4. Create Services + +```shell +kubectl -n my_cht_project_namespace apply -f services.yaml +``` +With services.yaml as +```yaml +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: couchdb + name: couchdb +spec: + ports: + - name: couchdb-service + port: 5984 + protocol: TCP + targetPort: 5984 + - name: epmd + port: 4369 + protocol: TCP + targetPort: 4369 + - name: erlang + port: 9100 + protocol: TCP + targetPort: 9100 + selector: + cht.service: couchdb +--- +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: api + name: api +spec: + ports: + - port: 5988 + targetPort: 5988 + selector: + cht.service: api +--- +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: haproxy + name: haproxy +spec: + ports: + - name: "5984" + port: 5984 + targetPort: 5984 + selector: + cht.service: haproxy +--- +apiVersion: v1 +kind: Service +metadata: + name: healthcheck +spec: + selector: + cht.service: healthcheck + ports: + - protocol: TCP + port: 5555 + targetPort: 5555 +--- +apiVersion: v1 +kind: Service +metadata: + name: upgrade-service +spec: + selector: + cht.service: upgrade-service + ports: + - name: upgrade-service + port: 5008 + protocol: TCP + targetPort: 5008 + type: ClusterIP +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cht-upgrade-service-user +``` + +5. Setup single-node CouchDB deployment + +```shell +kubectl -n my_cht_project_namespace apply -f couchdb-single-deployment.yaml +``` +With couchdb-single-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: couchdb + name: cht-couchdb +spec: + replicas: 1 + selector: + matchLabels: + cht.service: couchdb + strategy: + type: Recreate + template: + metadata: + labels: + cht.service: couchdb + spec: + #tolerations: + # - key: test-echistraining-4 + #operator: Equals + #value: "true" + #effect: NoSchedule + nodeSelector: + kubernetes.io/hostname: {{ .Values.hostname }} + containers: + - env: + - name: COUCHDB_LOG_LEVEL + value: info + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SECRET + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_SECRET + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + - name: COUCHDB_UUID + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_UUID + - name: SVC_NAME + value: couchdb.{{ .Values.namespace }}.svc.cluster.local + image: public.ecr.aws/medic/cht-couchdb:4.2.2 + name: cht-couchdb + ports: + - containerPort: 5984 + resources: {} + volumeMounts: + - mountPath: /opt/couchdb/data + name: local-volume + #subPath: data + subPath: couchdb + # I think we need to use subPath couchdb here since our directory on disk is /home/echisadmin/cht/couchdb. We will want the hostPath + # below to be one-level up, so effectively subPath maps to "couchdb" folder. This allows local.d to work, if we mount local.d inside couchdb's data directory + # it will error the couchdb installation. + - mountPath: /opt/couchdb/etc/local.d + name: local-volume + subPath: local.d + restartPolicy: Always + volumes: + - name: local-volume + hostPath: + path: /home/echisadmin/cht/ +``` + +6. Create HAproxy deployment + +```shell +kubectl -n my_cht_project_namespace apply -f haproxy-deployment.yaml +``` +With haproxy-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: haproxy + name: cht-haproxy +spec: + replicas: 1 + selector: + matchLabels: + cht.service: haproxy + strategy: {} + template: + metadata: + labels: + cht.service: haproxy + spec: + nodeSelector: + kubernetes.io/hostname: {{ .Values.hostname }} + containers: + - env: + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SERVERS + valueFrom: + configMapKeyRef: + name: couchdb-servers-configmap + key: COUCHDB_SERVERS + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + - name: HAPROXY_IP + value: 0.0.0.0 + - name: HAPROXY_PORT + value: "5984" + - name: HEALTHCHECK_ADDR + value: healthcheck.{{ .Values.namespace }}.svc.cluster.local + image: public.ecr.aws/medic/cht-haproxy:4.2.2 + name: cht-haproxy + ports: + - containerPort: 5984 + resources: {} + hostname: haproxy + restartPolicy: Always +``` + +7. Create Healthcheck deployment + +```shell +kubectl -n my_cht_project_namespace apply -f healthcheck-deployment.yaml +``` +With healthcheck-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: healthcheck + name: cht-haproxy-healthcheck +spec: + replicas: 1 + selector: + matchLabels: + cht.service: healthcheck + strategy: {} + template: + metadata: + labels: + cht.service: healthcheck + spec: + nodeSelector: + kubernetes.io/hostname: {{ .Values.hostname }} + containers: + - env: + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SERVERS + valueFrom: + configMapKeyRef: + name: couchdb-servers-configmap + key: COUCHDB_SERVERS + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + image: public.ecr.aws/medic/cht-haproxy-healthcheck:4.2.2 + name: cht-haproxy-healthcheck + resources: {} + ports: + - containerPort: 5555 + restartPolicy: Always +``` + +8. Create CHT API deployment + +```shell +kubectl -n my_cht_project_namespace apply -f api-deployment.yaml +``` +With api-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: api + name: cht-api +spec: + replicas: 1 + selector: + matchLabels: + cht.service: api + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + labels: + cht.service: api + spec: + nodeSelector: + kubernetes.io/hostname: {{ .Values.hostname }} + containers: + - env: + - name: BUILDS_URL + value: "https://staging.dev.medicmobile.org/_couch/builds_4" + - name: COUCH_URL + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCH_URL + - name: UPGRADE_SERVICE_URL + value: http://upgrade-service.{{ .Values.namespace }}.svc.cluster.local:5008 + - name: API_PORT + value: "5988" + image: public.ecr.aws/medic/cht-api:4.2.2 + name: cht-api + ports: + - containerPort: 5988 + resources: {} + restartPolicy: Always +``` + +9. Create CHT Sentinel deployment + +```shell +kubectl -n my_cht_project_namespace apply -f sentinel-deployment.yaml +``` +With sentinel-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: sentinel + name: cht-sentinel +spec: + replicas: 1 + selector: + matchLabels: + cht.service: sentinel + strategy: {} + template: + metadata: + labels: + cht.service: sentinel + spec: + containers: + - env: + - name: API_HOST + value: api.{{ .Values.namespace }}.svc.cluster.local + - name: COUCH_URL + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCH_URL + - name: API_PORT + value: '5988' + image: public.ecr.aws/medic/cht-sentinel:4.2.2 + name: cht-sentinel + resources: {} + restartPolicy: Always +status: {} +``` + +10. Create Ingress + +```shell +kubectl -n my_cht_project_namespace apply -f ingress.yaml +``` +With ingress.yaml as: +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: api-ingress +spec: + rules: + - host: {{ .Values.county }}.echis.go.ke + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: api + port: + number: 5988 + - host: {{ .Values.county }}-echis.health.go.ke + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: api + port: + number: 5988 +``` + +### USing Helm \ No newline at end of file From fe0467fe1c485535c0d0da5aa13c2d310c931ef9 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Wed, 25 Sep 2024 09:55:15 +0300 Subject: [PATCH 2/3] Update yaml files --- content/en/hosting/kubernetes-vs-docker.md | 31 ++++++++-------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/content/en/hosting/kubernetes-vs-docker.md b/content/en/hosting/kubernetes-vs-docker.md index 4590d4cd5..922809277 100644 --- a/content/en/hosting/kubernetes-vs-docker.md +++ b/content/en/hosting/kubernetes-vs-docker.md @@ -250,13 +250,8 @@ spec: labels: cht.service: couchdb spec: - #tolerations: - # - key: test-echistraining-4 - #operator: Equals - #value: "true" - #effect: NoSchedule nodeSelector: - kubernetes.io/hostname: {{ .Values.hostname }} + kubernetes.io/hostname: containers: - env: - name: COUCHDB_LOG_LEVEL @@ -282,7 +277,7 @@ spec: name: cht-couchdb-credentials key: COUCHDB_UUID - name: SVC_NAME - value: couchdb.{{ .Values.namespace }}.svc.cluster.local + value: couchdb.my_cht_project_namespace.svc.cluster.local image: public.ecr.aws/medic/cht-couchdb:4.2.2 name: cht-couchdb ports: @@ -291,11 +286,7 @@ spec: volumeMounts: - mountPath: /opt/couchdb/data name: local-volume - #subPath: data subPath: couchdb - # I think we need to use subPath couchdb here since our directory on disk is /home/echisadmin/cht/couchdb. We will want the hostPath - # below to be one-level up, so effectively subPath maps to "couchdb" folder. This allows local.d to work, if we mount local.d inside couchdb's data directory - # it will error the couchdb installation. - mountPath: /opt/couchdb/etc/local.d name: local-volume subPath: local.d @@ -331,7 +322,7 @@ spec: cht.service: haproxy spec: nodeSelector: - kubernetes.io/hostname: {{ .Values.hostname }} + kubernetes.io/hostname: containers: - env: - name: COUCHDB_PASSWORD @@ -354,7 +345,7 @@ spec: - name: HAPROXY_PORT value: "5984" - name: HEALTHCHECK_ADDR - value: healthcheck.{{ .Values.namespace }}.svc.cluster.local + value: healthcheck.my_cht_project_namespace.svc.cluster.local image: public.ecr.aws/medic/cht-haproxy:4.2.2 name: cht-haproxy ports: @@ -389,7 +380,7 @@ spec: cht.service: healthcheck spec: nodeSelector: - kubernetes.io/hostname: {{ .Values.hostname }} + kubernetes.io/hostname: containers: - env: - name: COUCHDB_PASSWORD @@ -444,7 +435,7 @@ spec: cht.service: api spec: nodeSelector: - kubernetes.io/hostname: {{ .Values.hostname }} + kubernetes.io/hostname: containers: - env: - name: BUILDS_URL @@ -455,7 +446,7 @@ spec: name: cht-couchdb-credentials key: COUCH_URL - name: UPGRADE_SERVICE_URL - value: http://upgrade-service.{{ .Values.namespace }}.svc.cluster.local:5008 + value: http://upgrade-service.my_cht_project_namespace.svc.cluster.local:5008 - name: API_PORT value: "5988" image: public.ecr.aws/medic/cht-api:4.2.2 @@ -493,7 +484,7 @@ spec: containers: - env: - name: API_HOST - value: api.{{ .Values.namespace }}.svc.cluster.local + value: api.my_cht_project_namespace.svc.cluster.local - name: COUCH_URL valueFrom: secretKeyRef: @@ -521,7 +512,7 @@ metadata: name: api-ingress spec: rules: - - host: {{ .Values.county }}.echis.go.ke + - host: http: paths: - pathType: Prefix @@ -531,7 +522,7 @@ spec: name: api port: number: 5988 - - host: {{ .Values.county }}-echis.health.go.ke + - host: http: paths: - pathType: Prefix @@ -543,4 +534,4 @@ spec: number: 5988 ``` -### USing Helm \ No newline at end of file +### Using Helm \ No newline at end of file From 5c43e691d8b7dfe050e098e2198cbee92383b1ec Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Wed, 9 Oct 2024 11:59:00 +0300 Subject: [PATCH 3/3] Move to 4.x hosting --- .../en/hosting/4.x/docker-k8s-migration.md | 496 ++++++++++++++++++ content/en/hosting/kubernetes-vs-docker.md | 488 +---------------- 2 files changed, 497 insertions(+), 487 deletions(-) create mode 100644 content/en/hosting/4.x/docker-k8s-migration.md diff --git a/content/en/hosting/4.x/docker-k8s-migration.md b/content/en/hosting/4.x/docker-k8s-migration.md new file mode 100644 index 000000000..fc21db611 --- /dev/null +++ b/content/en/hosting/4.x/docker-k8s-migration.md @@ -0,0 +1,496 @@ +--- +title: "Migration from Docker to Kubernetes for v4.x" +linkTitle: "Migration from Docker to Kubernetes" +weight: 1 +aliases: + - /apps/guides/hosting/4.x/docker-kubernetes-migration +description: > + Guide to migrate CHT 4.x instances from Docker to Kubernetes +relatedContent: > +--- + +## Migrating from docker to kubernetes + +### Using kubectl + +This guide is oriented towards migrating a docker compose CHT instance hosted on a single machine into a kubernetes cluster. The machine will be enjoined as a node to the cluster. + +Optional: + +When using K3S to run your kubernetes cluster, install it on the node using this command: +```shell +curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" INSTALL_K3S_EXEC="agent" INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -s - --docker --token {{cluster_token}} --server https://:6443 +``` + +1. Create a namespace for your project + +```shell +kubectl create namespace my_cht_project_namespace +``` + +2. Setup Credentials + +```shell +kubectl -n y_cht_project_namespace apply -f credentials.yaml +``` +With credentials.yaml as: +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: cht-couchdb-credentials +type: Opaque +stringData: + COUCHDB_PASSWORD: + COUCHDB_SECRET: + COUCHDB_USER: + COUCHDB_UUID: + COUCH_URL: http://:@haproxy.y_cht_project_namespace.svc.cluster.local:5984/medic +``` + +3. Create Roles & RoleBindings + +```shell +kubectl -n my_cht_project_namespace apply -f roles.yaml +``` +With roles.yaml as: +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: deployment-manager +rules: +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - update + - watch + - patch + - list +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - update + - watch + - patch + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: deployment-manager-cht +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: deployment-manager +subjects: +- apiGroup: "" + kind: ServiceAccount + name: cht-upgrade-service-user +``` + +4. Create Services + +```shell +kubectl -n my_cht_project_namespace apply -f services.yaml +``` +With services.yaml as +```yaml +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: couchdb + name: couchdb +spec: + ports: + - name: couchdb-service + port: 5984 + protocol: TCP + targetPort: 5984 + - name: epmd + port: 4369 + protocol: TCP + targetPort: 4369 + - name: erlang + port: 9100 + protocol: TCP + targetPort: 9100 + selector: + cht.service: couchdb +--- +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: api + name: api +spec: + ports: + - port: 5988 + targetPort: 5988 + selector: + cht.service: api +--- +apiVersion: v1 +kind: Service +metadata: + labels: + cht.service: haproxy + name: haproxy +spec: + ports: + - name: "5984" + port: 5984 + targetPort: 5984 + selector: + cht.service: haproxy +--- +apiVersion: v1 +kind: Service +metadata: + name: healthcheck +spec: + selector: + cht.service: healthcheck + ports: + - protocol: TCP + port: 5555 + targetPort: 5555 +--- +apiVersion: v1 +kind: Service +metadata: + name: upgrade-service +spec: + selector: + cht.service: upgrade-service + ports: + - name: upgrade-service + port: 5008 + protocol: TCP + targetPort: 5008 + type: ClusterIP +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cht-upgrade-service-user +``` + +5. Setup single-node CouchDB deployment + +```shell +kubectl -n my_cht_project_namespace apply -f couchdb-single-deployment.yaml +``` +With couchdb-single-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: couchdb + name: cht-couchdb +spec: + replicas: 1 + selector: + matchLabels: + cht.service: couchdb + strategy: + type: Recreate + template: + metadata: + labels: + cht.service: couchdb + spec: + nodeSelector: + kubernetes.io/hostname: + containers: + - env: + - name: COUCHDB_LOG_LEVEL + value: info + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SECRET + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_SECRET + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + - name: COUCHDB_UUID + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_UUID + - name: SVC_NAME + value: couchdb.my_cht_project_namespace.svc.cluster.local + image: public.ecr.aws/medic/cht-couchdb:4.2.2 + name: cht-couchdb + ports: + - containerPort: 5984 + resources: {} + volumeMounts: + - mountPath: /opt/couchdb/data + name: local-volume + subPath: couchdb + - mountPath: /opt/couchdb/etc/local.d + name: local-volume + subPath: local.d + restartPolicy: Always + volumes: + - name: local-volume + hostPath: + path: /home/echisadmin/cht/ +``` + +6. Create HAproxy deployment + +```shell +kubectl -n my_cht_project_namespace apply -f haproxy-deployment.yaml +``` +With haproxy-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: haproxy + name: cht-haproxy +spec: + replicas: 1 + selector: + matchLabels: + cht.service: haproxy + strategy: {} + template: + metadata: + labels: + cht.service: haproxy + spec: + nodeSelector: + kubernetes.io/hostname: + containers: + - env: + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SERVERS + valueFrom: + configMapKeyRef: + name: couchdb-servers-configmap + key: COUCHDB_SERVERS + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + - name: HAPROXY_IP + value: 0.0.0.0 + - name: HAPROXY_PORT + value: "5984" + - name: HEALTHCHECK_ADDR + value: healthcheck.my_cht_project_namespace.svc.cluster.local + image: public.ecr.aws/medic/cht-haproxy:4.2.2 + name: cht-haproxy + ports: + - containerPort: 5984 + resources: {} + hostname: haproxy + restartPolicy: Always +``` + +7. Create Healthcheck deployment + +```shell +kubectl -n my_cht_project_namespace apply -f healthcheck-deployment.yaml +``` +With healthcheck-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: healthcheck + name: cht-haproxy-healthcheck +spec: + replicas: 1 + selector: + matchLabels: + cht.service: healthcheck + strategy: {} + template: + metadata: + labels: + cht.service: healthcheck + spec: + nodeSelector: + kubernetes.io/hostname: + containers: + - env: + - name: COUCHDB_PASSWORD + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_PASSWORD + - name: COUCHDB_SERVERS + valueFrom: + configMapKeyRef: + name: couchdb-servers-configmap + key: COUCHDB_SERVERS + - name: COUCHDB_USER + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCHDB_USER + image: public.ecr.aws/medic/cht-haproxy-healthcheck:4.2.2 + name: cht-haproxy-healthcheck + resources: {} + ports: + - containerPort: 5555 + restartPolicy: Always +``` + +8. Create CHT API deployment + +```shell +kubectl -n my_cht_project_namespace apply -f api-deployment.yaml +``` +With api-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: api + name: cht-api +spec: + replicas: 1 + selector: + matchLabels: + cht.service: api + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + labels: + cht.service: api + spec: + nodeSelector: + kubernetes.io/hostname: + containers: + - env: + - name: BUILDS_URL + value: "https://staging.dev.medicmobile.org/_couch/builds_4" + - name: COUCH_URL + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCH_URL + - name: UPGRADE_SERVICE_URL + value: http://upgrade-service.my_cht_project_namespace.svc.cluster.local:5008 + - name: API_PORT + value: "5988" + image: public.ecr.aws/medic/cht-api:4.2.2 + name: cht-api + ports: + - containerPort: 5988 + resources: {} + restartPolicy: Always +``` + +9. Create CHT Sentinel deployment + +```shell +kubectl -n my_cht_project_namespace apply -f sentinel-deployment.yaml +``` +With sentinel-deployment.yaml as: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cht.service: sentinel + name: cht-sentinel +spec: + replicas: 1 + selector: + matchLabels: + cht.service: sentinel + strategy: {} + template: + metadata: + labels: + cht.service: sentinel + spec: + containers: + - env: + - name: API_HOST + value: api.my_cht_project_namespace.svc.cluster.local + - name: COUCH_URL + valueFrom: + secretKeyRef: + name: cht-couchdb-credentials + key: COUCH_URL + - name: API_PORT + value: '5988' + image: public.ecr.aws/medic/cht-sentinel:4.2.2 + name: cht-sentinel + resources: {} + restartPolicy: Always +status: {} +``` + +10. Create Ingress + +```shell +kubectl -n my_cht_project_namespace apply -f ingress.yaml +``` +With ingress.yaml as: +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: api-ingress +spec: + rules: + - host: + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: api + port: + number: 5988 + - host: + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: api + port: + number: 5988 +``` + +### Using Helm \ No newline at end of file diff --git a/content/en/hosting/kubernetes-vs-docker.md b/content/en/hosting/kubernetes-vs-docker.md index c3ffe4b5d..170395e1b 100644 --- a/content/en/hosting/kubernetes-vs-docker.md +++ b/content/en/hosting/kubernetes-vs-docker.md @@ -48,490 +48,4 @@ Like Kubernetes above, Docker Compose deploys the same services but adds an addi * HAProxy service. * Upgrade Service service. * A CHT Sentinel service. -* An nginx service to act as a reverse proxy and terminate TLS connections - -## Migrating from docker to kubernetes - -### Using kubectl - -This guide is oriented towards migrating a docker compose CHT instance hosted on a single machine into a kubernetes cluster. The machine will be enjoined as a node to the cluster. - -Optional: - -When using K3S to run your kubernetes cluster, install it on the node using this command: -```shell -curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" INSTALL_K3S_EXEC="agent" INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -s - --docker --token {{cluster_token}} --server https://:6443 -``` - -1. Create a namespace for your project - -```shell -kubectl create namespace my_cht_project_namespace -``` - -2. Setup Credentials - -```shell -kubectl -n y_cht_project_namespace apply -f credentials.yaml -``` -With credentials.yaml as: -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: cht-couchdb-credentials -type: Opaque -stringData: - COUCHDB_PASSWORD: - COUCHDB_SECRET: - COUCHDB_USER: - COUCHDB_UUID: - COUCH_URL: http://:@haproxy.y_cht_project_namespace.svc.cluster.local:5984/medic -``` - -3. Create Roles & RoleBindings - -```shell -kubectl -n my_cht_project_namespace apply -f roles.yaml -``` -With roles.yaml as: -```yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: deployment-manager -rules: -- apiGroups: - - apps - resources: - - deployments - verbs: - - get - - update - - watch - - patch - - list -- apiGroups: - - "" - resources: - - pods - verbs: - - get - - update - - watch - - patch - - list ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: deployment-manager-cht -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: deployment-manager -subjects: -- apiGroup: "" - kind: ServiceAccount - name: cht-upgrade-service-user -``` - -4. Create Services - -```shell -kubectl -n my_cht_project_namespace apply -f services.yaml -``` -With services.yaml as -```yaml -apiVersion: v1 -kind: Service -metadata: - labels: - cht.service: couchdb - name: couchdb -spec: - ports: - - name: couchdb-service - port: 5984 - protocol: TCP - targetPort: 5984 - - name: epmd - port: 4369 - protocol: TCP - targetPort: 4369 - - name: erlang - port: 9100 - protocol: TCP - targetPort: 9100 - selector: - cht.service: couchdb ---- -apiVersion: v1 -kind: Service -metadata: - labels: - cht.service: api - name: api -spec: - ports: - - port: 5988 - targetPort: 5988 - selector: - cht.service: api ---- -apiVersion: v1 -kind: Service -metadata: - labels: - cht.service: haproxy - name: haproxy -spec: - ports: - - name: "5984" - port: 5984 - targetPort: 5984 - selector: - cht.service: haproxy ---- -apiVersion: v1 -kind: Service -metadata: - name: healthcheck -spec: - selector: - cht.service: healthcheck - ports: - - protocol: TCP - port: 5555 - targetPort: 5555 ---- -apiVersion: v1 -kind: Service -metadata: - name: upgrade-service -spec: - selector: - cht.service: upgrade-service - ports: - - name: upgrade-service - port: 5008 - protocol: TCP - targetPort: 5008 - type: ClusterIP ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cht-upgrade-service-user -``` - -5. Setup single-node CouchDB deployment - -```shell -kubectl -n my_cht_project_namespace apply -f couchdb-single-deployment.yaml -``` -With couchdb-single-deployment.yaml as: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - cht.service: couchdb - name: cht-couchdb -spec: - replicas: 1 - selector: - matchLabels: - cht.service: couchdb - strategy: - type: Recreate - template: - metadata: - labels: - cht.service: couchdb - spec: - nodeSelector: - kubernetes.io/hostname: - containers: - - env: - - name: COUCHDB_LOG_LEVEL - value: info - - name: COUCHDB_PASSWORD - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_PASSWORD - - name: COUCHDB_SECRET - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_SECRET - - name: COUCHDB_USER - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_USER - - name: COUCHDB_UUID - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_UUID - - name: SVC_NAME - value: couchdb.my_cht_project_namespace.svc.cluster.local - image: public.ecr.aws/medic/cht-couchdb:4.2.2 - name: cht-couchdb - ports: - - containerPort: 5984 - resources: {} - volumeMounts: - - mountPath: /opt/couchdb/data - name: local-volume - subPath: couchdb - - mountPath: /opt/couchdb/etc/local.d - name: local-volume - subPath: local.d - restartPolicy: Always - volumes: - - name: local-volume - hostPath: - path: /home/echisadmin/cht/ -``` - -6. Create HAproxy deployment - -```shell -kubectl -n my_cht_project_namespace apply -f haproxy-deployment.yaml -``` -With haproxy-deployment.yaml as: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - cht.service: haproxy - name: cht-haproxy -spec: - replicas: 1 - selector: - matchLabels: - cht.service: haproxy - strategy: {} - template: - metadata: - labels: - cht.service: haproxy - spec: - nodeSelector: - kubernetes.io/hostname: - containers: - - env: - - name: COUCHDB_PASSWORD - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_PASSWORD - - name: COUCHDB_SERVERS - valueFrom: - configMapKeyRef: - name: couchdb-servers-configmap - key: COUCHDB_SERVERS - - name: COUCHDB_USER - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_USER - - name: HAPROXY_IP - value: 0.0.0.0 - - name: HAPROXY_PORT - value: "5984" - - name: HEALTHCHECK_ADDR - value: healthcheck.my_cht_project_namespace.svc.cluster.local - image: public.ecr.aws/medic/cht-haproxy:4.2.2 - name: cht-haproxy - ports: - - containerPort: 5984 - resources: {} - hostname: haproxy - restartPolicy: Always -``` - -7. Create Healthcheck deployment - -```shell -kubectl -n my_cht_project_namespace apply -f healthcheck-deployment.yaml -``` -With healthcheck-deployment.yaml as: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - cht.service: healthcheck - name: cht-haproxy-healthcheck -spec: - replicas: 1 - selector: - matchLabels: - cht.service: healthcheck - strategy: {} - template: - metadata: - labels: - cht.service: healthcheck - spec: - nodeSelector: - kubernetes.io/hostname: - containers: - - env: - - name: COUCHDB_PASSWORD - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_PASSWORD - - name: COUCHDB_SERVERS - valueFrom: - configMapKeyRef: - name: couchdb-servers-configmap - key: COUCHDB_SERVERS - - name: COUCHDB_USER - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCHDB_USER - image: public.ecr.aws/medic/cht-haproxy-healthcheck:4.2.2 - name: cht-haproxy-healthcheck - resources: {} - ports: - - containerPort: 5555 - restartPolicy: Always -``` - -8. Create CHT API deployment - -```shell -kubectl -n my_cht_project_namespace apply -f api-deployment.yaml -``` -With api-deployment.yaml as: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - cht.service: api - name: cht-api -spec: - replicas: 1 - selector: - matchLabels: - cht.service: api - strategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 0 - maxUnavailable: 1 - template: - metadata: - labels: - cht.service: api - spec: - nodeSelector: - kubernetes.io/hostname: - containers: - - env: - - name: BUILDS_URL - value: "https://staging.dev.medicmobile.org/_couch/builds_4" - - name: COUCH_URL - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCH_URL - - name: UPGRADE_SERVICE_URL - value: http://upgrade-service.my_cht_project_namespace.svc.cluster.local:5008 - - name: API_PORT - value: "5988" - image: public.ecr.aws/medic/cht-api:4.2.2 - name: cht-api - ports: - - containerPort: 5988 - resources: {} - restartPolicy: Always -``` - -9. Create CHT Sentinel deployment - -```shell -kubectl -n my_cht_project_namespace apply -f sentinel-deployment.yaml -``` -With sentinel-deployment.yaml as: -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - cht.service: sentinel - name: cht-sentinel -spec: - replicas: 1 - selector: - matchLabels: - cht.service: sentinel - strategy: {} - template: - metadata: - labels: - cht.service: sentinel - spec: - containers: - - env: - - name: API_HOST - value: api.my_cht_project_namespace.svc.cluster.local - - name: COUCH_URL - valueFrom: - secretKeyRef: - name: cht-couchdb-credentials - key: COUCH_URL - - name: API_PORT - value: '5988' - image: public.ecr.aws/medic/cht-sentinel:4.2.2 - name: cht-sentinel - resources: {} - restartPolicy: Always -status: {} -``` - -10. Create Ingress - -```shell -kubectl -n my_cht_project_namespace apply -f ingress.yaml -``` -With ingress.yaml as: -```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: api-ingress -spec: - rules: - - host: - http: - paths: - - pathType: Prefix - path: "/" - backend: - service: - name: api - port: - number: 5988 - - host: - http: - paths: - - pathType: Prefix - path: "/" - backend: - service: - name: api - port: - number: 5988 -``` - -### Using Helm \ No newline at end of file +* An nginx service to act as a reverse proxy and terminate TLS connections \ No newline at end of file