From 7f6ec62af5eaa95a52882193ebb1d3e4f47522a3 Mon Sep 17 00:00:00 2001 From: Elijah Gichinga Date: Sun, 22 Sep 2024 15:53:55 +0300 Subject: [PATCH 1/5] 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 1cdd945b05..4590d4cd5e 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/5] 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 4590d4cd5e..9228092773 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/5] 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 0000000000..fc21db6113 --- /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 c3ffe4b5d6..170395e1b4 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 From 6fccc4e9d38c770dd8bf1d028064593e47d7b4db Mon Sep 17 00:00:00 2001 From: mrjones-plip Date: Thu, 8 May 2025 16:18:11 -0700 Subject: [PATCH 4/5] revert change to unrelated doc --- content/en/hosting/kubernetes-vs-docker.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/en/hosting/kubernetes-vs-docker.md b/content/en/hosting/kubernetes-vs-docker.md index a23235147f..b66b77f49e 100644 --- a/content/en/hosting/kubernetes-vs-docker.md +++ b/content/en/hosting/kubernetes-vs-docker.md @@ -34,7 +34,6 @@ 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. Use Kubernetes instead for a more stable and [horizontally scalable]({{< relref "hosting/vertical-vs-horizontal" >}}) solution. @@ -47,4 +46,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 \ No newline at end of file +* An nginx service to act as a reverse proxy and terminate TLS connections From 89f005de0b0c93868c4089e8d46d2b6190734a7f Mon Sep 17 00:00:00 2001 From: mrjones-plip Date: Thu, 8 May 2025 16:27:21 -0700 Subject: [PATCH 5/5] move guide to correct migration folder, headline tweaks, remove optional line --- content/en/hosting/4.x/migration/_index.md | 1 + .../data-migration-docker-k8s.md} | 24 +++++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) rename content/en/hosting/4.x/{docker-k8s-migration.md => migration/data-migration-docker-k8s.md} (94%) diff --git a/content/en/hosting/4.x/migration/_index.md b/content/en/hosting/4.x/migration/_index.md index 68b662d793..92688ea13b 100644 --- a/content/en/hosting/4.x/migration/_index.md +++ b/content/en/hosting/4.x/migration/_index.md @@ -11,6 +11,7 @@ weight: 20 {{< cards >}} {{< card link="data-migration-3x-docker-to-4x-k3s-multi" title="To K3s Multi-node" subtitle="Guide to migrate existing data from CHT 3.x Docker Compose deployment to CHT 4.x clustered K3s deployment with 3 CouchDB nodes" icon="kubernetes" >}} {{< card link="data-migration-3x-docker-to-4x-k3s-single" title="To K3s Single-node" icon="kubernetes" subtitle="Guide on how to migrate existing data from CHT 3.x Docker Compose deployment to CHT 4.x single-node K3s deployment" >}} + {{< card link="data-migration-docker-k8s" title="To K8s Single-node" icon="kubernetes" subtitle="Guide on how to migrate existing data from CHT 4.x Docker Compose deployment to CHT 4.x single-node K8s deployment" >}} {{< card link="migration-to-4x-docker" title="To Docker Single-Node" subtitle="Guide to migrate existent data from CHT 3.x to CHT 4.x" icon="docker" >}} {{< /cards >}} diff --git a/content/en/hosting/4.x/docker-k8s-migration.md b/content/en/hosting/4.x/migration/data-migration-docker-k8s.md similarity index 94% rename from content/en/hosting/4.x/docker-k8s-migration.md rename to content/en/hosting/4.x/migration/data-migration-docker-k8s.md index fc21db6113..359a13692f 100644 --- a/content/en/hosting/4.x/docker-k8s-migration.md +++ b/content/en/hosting/4.x/migration/data-migration-docker-k8s.md @@ -1,27 +1,19 @@ --- -title: "Migration from Docker to Kubernetes for v4.x" -linkTitle: "Migration from Docker to Kubernetes" -weight: 1 +title: "Migration from Docker Compose CHT 4.x to Single-Node CHT 4.x on Kubernetes" +linkTitle: "To Single-Node Kubernetes" +weight: 100 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 +{{< hextra/hero-subtitle >}} +Guide on how to migrate existing data from CHT 4.x Docker Compose deployment to CHT 4.x single-node Kubernetes deployment +{{< /hextra/hero-subtitle >}} -### 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 @@ -493,4 +485,4 @@ spec: number: 5988 ``` -### Using Helm \ No newline at end of file +### Using Helm