diff --git a/Vagrantfile b/Vagrantfile index d7206c9950..35866755b3 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -7,7 +7,7 @@ Vagrant.configure("2") do |config| config.vm.define "rhel8" do |target| target.vm.box = "generic/rhel8" end - + config.vm.define "centos7" do |target| target.vm.box = "boxomatic/centos-7" end @@ -15,7 +15,7 @@ Vagrant.configure("2") do |config| config.vm.define "centos8" do |target| target.vm.box = "boxomatic/centos-8" end - + config.vm.define "ubuntu" do |target| target.vm.box = "boxomatic/ubuntu-20.04" end @@ -31,13 +31,13 @@ Vagrant.configure("2") do |config| config.vm.hostname = "zarf-test" config.vm.synced_folder '.', '/vagrant', disabled: true config.vm.synced_folder 'build', '/opt/zarf', SharedFoldersEnableSymlinksCreate: false - + config.vm.network "forwarded_port", guest: 80, host: 8080 config.vm.network "forwarded_port", guest: 443, host: 8443 config.vm.disk :disk, size: "20GB", primary: true config.ssh.insert_key = false - + config.vm.provider "virtualbox" do |vb| vb.check_guest_additions = false vb.cpus = 6 @@ -47,7 +47,7 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: <<-SHELL cd /opt/zarf # Airgap images please - echo "0.0.0.0 charts.helm.sh repo1.dso.mil github.com registry.dso.mil registry1.dso.mil index.docker.io auth.docker.io registry-1.docker.io dseasb33srnrn.cloudfront.net production.cloudflare.docker.com" >> /etc/hosts + echo "0.0.0.0 charts.helm.sh repo1.dso.mil github.com registry.dso.mil registry1.dso.mil index.docker.io auth.docker.io registry-1.docker.io dseasb33srnrn.cloudfront.net production.cloudflare.docker.com registry.opensource.zalan.do" >> /etc/hosts # ./zarf init --confirm --host=localhost SHELL diff --git a/examples/Makefile b/examples/Makefile index d52ace4142..fa11dc218f 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -19,4 +19,5 @@ package-examples: cd data-injection && $(ZARF_BIN) package create --confirm && mv zarf*.tar ../../build cd game && $(ZARF_BIN) package create --confirm && mv zarf*.tar.zst ../../build cd single-big-bang-package && $(ZARF_BIN) package create --confirm && mv zarf*.tar.zst ../../build - cd tiny-kafka && $(ZARF_BIN) package create --confirm && mv zarf*.tar.zst ../../build \ No newline at end of file + cd tiny-kafka && $(ZARF_BIN) package create --confirm && mv zarf*.tar.zst ../../build + cd postgres-operator && $(ZARF_BIN) package create --confirm && mv zarf*.tar.zst ../../build diff --git a/examples/postgres-operator/README.md b/examples/postgres-operator/README.md new file mode 100644 index 0000000000..f8a625c8b8 --- /dev/null +++ b/examples/postgres-operator/README.md @@ -0,0 +1,34 @@ +# Zarf Postgres Operator Example + +This example demonstrates deploying a performant and highly available PostgreSQL database to a Zarf airgap cluster. It uses Zalando's [postgres-operator](https://github.com/zalando/postgres-operator) and provides the Postgres Operator UI and a deployment of PGAdmin for demo purposes. + +## Tool Choice + +After looking at several alternatives, Zalando's postgres operator felt like the best choice. Other tools that were close runners-up were the postgres-operator by [CrunchyData](https://github.com/CrunchyData/postgres-operator) and [KubeDB](https://github.com/kubedb/operator). + +## Instructions + +1. Create a Zarf cluster as outlined in the main [README](../../README.md#2-create-the-zarf-cluster) +2. Follow [step 3](../../README.md#3-add-resources-to-the-zarf-cluster) using the `zarf.yaml` config in this folder +3. The Postgres Operator UI will be available at [https://postgres-operator-ui.localhost:8443](https://postgres-operator-ui.localhost:8443) and PGAdmin will be available at [https://pgadmin.localhost:8443](https://pgadmin.localhost:8443). +4. Set up a server in PGAdmin: + - General // Name: `acid-zarf-test` + - General // Server group: `Servers` + - Connection // Host: (the URL in the table below) + - Connection // Port: `5432` + - Connection // Maintenance database: `postgres` + - Connection // Username: `zarf` + - Connection // Password: (run the command in the table below) + - SSL // SSL mode: `Require` + +## Logins + +| Service | URL | Username | Password | +| ------------------------- | ------------------------------------------------------------------------------------------ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Postgres Operator UI | [https://postgres-operator-ui.localhost:8443](https://postgres-operator-ui.localhost:8443) | N/A | N/A | +| PGAdmin | [https://pgadmin.localhost:8443](https://pgadmin.localhost:8443) | `zarf@example.local` | Run: `zarf tools get-admin-password` | +| Example Postgres Database | `acid-zarf-test.postgres-operator.svc.cluster.local` | `zarf` | Run: `echo $(kubectl get secret zarf.acid-zarf-test.credentials.postgresql.acid.zalan.do -n postgres-operator --template={{.data.password}} \| base64 -d)` | + +## References +- https://blog.flant.com/comparing-kubernetes-operators-for-postgresql/ +- https://blog.flant.com/our-experience-with-postgres-operator-for-kubernetes-by-zalando/ diff --git a/examples/postgres-operator/manifests/cluster.yaml b/examples/postgres-operator/manifests/cluster.yaml new file mode 100644 index 0000000000..d295dc86b1 --- /dev/null +++ b/examples/postgres-operator/manifests/cluster.yaml @@ -0,0 +1,26 @@ +apiVersion: "acid.zalan.do/v1" +kind: "postgresql" +metadata: + name: "acid-zarf-test" + namespace: "postgres-operator" + labels: + team: acid +spec: + teamId: "acid" + postgresql: + version: "13" + numberOfInstances: 3 + enableConnectionPooler: true + volume: + size: "2Gi" + users: + zarf: [] + databases: + zarf: zarf + resources: + requests: + cpu: 100m + memory: 100Mi + limits: + cpu: 500m + memory: 500Mi diff --git a/examples/postgres-operator/manifests/namespace.yaml b/examples/postgres-operator/manifests/namespace.yaml new file mode 100644 index 0000000000..bfebd8ac2f --- /dev/null +++ b/examples/postgres-operator/manifests/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: postgres-operator diff --git a/examples/postgres-operator/manifests/operator-ui.yaml b/examples/postgres-operator/manifests/operator-ui.yaml new file mode 100644 index 0000000000..5b68e58738 --- /dev/null +++ b/examples/postgres-operator/manifests/operator-ui.yaml @@ -0,0 +1,48 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChart +metadata: + name: postgres-operator-ui + namespace: postgres-operator +spec: + chart: https://%{KUBERNETES_API}%/static/charts/postgres-operator-ui-1.7.0.tgz + targetNamespace: postgres-operator + # https://github.com/zalando/postgres-operator/blob/v1.7.0/charts/postgres-operator-ui/values.yaml + valuesContent: |- + # image: + # registry: registry1.dso.mil + # repository: ?? + # tag: ?? + resources: + requests: + cpu: "100m" + memory: "100Mi" + limits: + cpu: "200m" + memory: "200Mi" + envs: + # IMPORTANT: While operator chart and UI chart are idendependent, this is the interface between + # UI and operator API. Insert the service name of the operator API here! + operatorApiUrl: "http://postgres-operator:8080" + operatorClusterNameLabel: "cluster-name" + resourcesVisible: "False" + targetNamespace: "postgres-operator" + teams: + - "acid" + # We are defining our own Ingress manifest + ingress: + enabled: false +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: postgres-operator-ui-ingressroute + namespace: postgres-operator +spec: + entryPoints: + - websecure + routes: + - match: Host(`postgres-operator-ui.localhost`) + kind: Rule + services: + - name: postgres-operator-ui + port: 80 diff --git a/examples/postgres-operator/manifests/operator.yaml b/examples/postgres-operator/manifests/operator.yaml new file mode 100644 index 0000000000..95e7775158 --- /dev/null +++ b/examples/postgres-operator/manifests/operator.yaml @@ -0,0 +1,48 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChart +metadata: + name: postgres-operator + namespace: postgres-operator +spec: + chart: https://%{KUBERNETES_API}%/static/charts/postgres-operator-1.7.0.tgz + targetNamespace: postgres-operator + # https://github.com/zalando/postgres-operator/blob/v1.7.0/charts/postgres-operator/values.yaml + valuesContent: |- + # image: + # Eventually we'll need this to come from Iron Bank + # registry: registry1.dso.mil + # repository: ?? + # tag: ?? + # configGeneral: + # docker_image: registry1.dso.mil/.../spilo-13:2.1-p1 + configPostgresPodResources: + default_cpu_request: "100m" + default_memory_request: "100Mi" + default_cpu_limit: "500m" + default_memory_limit: "500Mi" + min_cpu_limit: "250m" + min_memory_limit: "250Mi" + # configLogicalBackup: + # logical_backup_docker_image: "registry1.dso.mil/.../logical-backup:v1.7.0" + # logical_backup_s3_endpoint: "" + # logical_backup_s3_access_key_id: "" + # logical_backup_s3_secret_access_key : "" + # logical_backup_schedule: "30 00 * * *" + configConnectionPooler: + # connection_pooler_image: "registry1.dso.mil/.../pgbouncer:master-18" + connection_pooler_default_cpu_request: "100m" + connection_pooler_default_cpu_limit: "500m" + connection_pooler_default_memory_request: "100Mi" + connection_pooler_default_memory_limit: "100Mi" + resources: + requests: + cpu: "100m" + memory: "250Mi" + limits: + cpu: "500m" + memory: "500Mi" + securityContext: + runAsUser: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false diff --git a/examples/postgres-operator/manifests/pgadmin.yaml b/examples/postgres-operator/manifests/pgadmin.yaml new file mode 100644 index 0000000000..ed101fc37a --- /dev/null +++ b/examples/postgres-operator/manifests/pgadmin.yaml @@ -0,0 +1,43 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChart +metadata: + name: pgadmin4 + namespace: postgres-operator +spec: + chart: https://%{KUBERNETES_API}%/static/charts/pgadmin4-1.7.2.tgz + targetNamespace: postgres-operator + # https://github.com/rowanruseler/helm-charts/blob/master/charts/pgadmin4/values.yaml + valuesContent: |- + # image: + # registry: registry1.dso.mil + # repository: ?? + # tag: ?? + serviceAccount: + create: true + persistentVolume: + size: 2Gi + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + env: + email: "zarf@example.local" + password: "###ZARF_SECRET###" +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: pgadmin-ingressroute + namespace: postgres-operator +spec: + entryPoints: + - websecure + routes: + - match: Host(`pgadmin.localhost`) + kind: Rule + services: + - name: pgadmin4 + port: 80 diff --git a/examples/postgres-operator/zarf.yaml b/examples/postgres-operator/zarf.yaml new file mode 100644 index 0000000000..4fbf68fc28 --- /dev/null +++ b/examples/postgres-operator/zarf.yaml @@ -0,0 +1,26 @@ +kind: ZarfPackageConfig +metadata: + name: postgres-operator-demo + description: "Demo of prod-like Postgres database(s) on an edge cluster" + +local: + manifests: manifests + + charts: + - name: postgres-operator + url: https://opensource.zalando.com/postgres-operator/charts/postgres-operator + version: 1.7.0 + - name: postgres-operator-ui + url: https://opensource.zalando.com/postgres-operator/charts/postgres-operator-ui + version: 1.7.0 + - name: pgadmin4 + url: https://helm.runix.net + version: 1.7.2 + + images: + - registry.opensource.zalan.do/acid/postgres-operator:v1.7.0 + - registry.opensource.zalan.do/acid/spilo-13:2.1-p1 + - registry.opensource.zalan.do/acid/logical-backup:v1.7.0 + - registry.opensource.zalan.do/acid/pgbouncer:master-18 + - registry.opensource.zalan.do/acid/postgres-operator-ui:v1.7.0 + - docker.io/dpage/pgadmin4:5.5