Skip to content

Commit e61aa35

Browse files
cbandyJonathan S. Katz
authored andcommitted
GCP Marketplace installer
Google Cloud Platform has a Marketplace for Kubernetes Applications that makes it easy for users to install and manage functionality. Issue: [ch6131]
1 parent 134ae43 commit e61aa35

File tree

11 files changed

+718
-4
lines changed

11 files changed

+718
-4
lines changed

ansible/roles/pgo-operator/templates/deployment.json.j2

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"containers": [
2222
{
2323
"name": "apiserver",
24-
"image": "{{ pgo_image_prefix }}/pgo-apiserver:{{ pgo_image_tag }}",
24+
"image": "{% if pgo_apiserver_image | default('') != '' %}{{ pgo_apiserver_image }}
25+
{%- else %}{{ pgo_image_prefix }}/pgo-apiserver:{{ pgo_image_tag }}
26+
{%- endif %}",
2527
"imagePullPolicy": "IfNotPresent",
2628
"ports": [
2729
{
@@ -70,7 +72,9 @@
7072
},
7173
{
7274
"name": "operator",
73-
"image": "{{ pgo_image_prefix }}/postgres-operator:{{ pgo_image_tag }}",
75+
"image": "{% if pgo_image | default('') != '' %}{{ pgo_image }}
76+
{%- else %}{{ pgo_image_prefix }}/postgres-operator:{{ pgo_image_tag }}
77+
{%- endif %}",
7478
"imagePullPolicy": "IfNotPresent",
7579
"readinessProbe": {
7680
"exec": {
@@ -124,7 +128,9 @@
124128
},
125129
{
126130
"name": "scheduler",
127-
"image": "{{ pgo_image_prefix }}/pgo-scheduler:{{ pgo_image_tag }}",
131+
"image": "{% if pgo_scheduler_image | default('') != '' %}{{ pgo_scheduler_image }}
132+
{%- else %}{{ pgo_image_prefix }}/pgo-scheduler:{{ pgo_image_tag }}
133+
{%- endif %}",
128134
"readinessProbe": {
129135
"exec": {
130136
"command": [
@@ -166,7 +172,9 @@
166172
"imagePullPolicy": "IfNotPresent"
167173
}, {
168174
"name": "event",
169-
"image": "{{ pgo_image_prefix }}/pgo-event:{{ pgo_image_tag }}",
175+
"image": "{% if pgo_event_image | default('') != '' %}{{ pgo_event_image }}
176+
{%- else %}{{ pgo_image_prefix }}/pgo-event:{{ pgo_image_tag }}
177+
{%- endif %}",
170178
"env": [
171179
{
172180
"name": "TIMEOUT",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
ARG MARKETPLACE_VERSION
2+
FROM gcr.io/cloud-marketplace-tools/k8s/deployer_envsubst:${MARKETPLACE_VERSION} AS build
3+
4+
# Verify Bash (>= 4.3) has `wait -n`
5+
RUN bash -c 'echo -n & wait -n'
6+
7+
8+
FROM gcr.io/cloud-marketplace-tools/k8s/deployer_envsubst:${MARKETPLACE_VERSION}
9+
10+
RUN install -D /bin/create_manifests.sh /opt/postgres-operator/cloud-marketplace-tools/bin/create_manifests.sh
11+
12+
# https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#latest-releases-via-apt-debian
13+
RUN if [ -f /etc/os-release ] && [ debian = "$(. /etc/os-release; echo $ID)" ] && [ 10 -ge "$(. /etc/os-release; echo $VERSION_ID)" ]; then \
14+
apt-get update && apt-get install -y --no-install-recommends gnupg && rm -rf /var/lib/apt/lists/* && \
15+
wget -qO- 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x93C4A3FD7BB9C367' | apt-key add && \
16+
echo > /etc/apt/sources.list.d/ansible.list deb http://ppa.launchpad.net/ansible/ansible-2.8/ubuntu trusty main ; \
17+
fi
18+
19+
RUN apt-get update \
20+
&& apt-get install -y --no-install-recommends ansible=2.8.* openssh-client \
21+
&& rm -rf /var/lib/apt/lists/*
22+
23+
COPY ansible/* \
24+
/opt/postgres-operator/ansible/
25+
COPY installers/gcp-marketplace/install-job.yaml \
26+
installers/gcp-marketplace/install.sh \
27+
installers/gcp-marketplace/inventory.ini \
28+
/opt/postgres-operator/
29+
30+
COPY installers/gcp-marketplace/install-hook.sh \
31+
/bin/create_manifests.sh
32+
COPY installers/gcp-marketplace/schema.yaml \
33+
/data/
34+
COPY installers/gcp-marketplace/application.yaml \
35+
/data/manifest/
36+
COPY installers/gcp-marketplace/test-pod.yaml \
37+
/data-test/manifest/
38+
39+
ARG PGO_VERSION
40+
RUN for file in \
41+
/data/schema.yaml \
42+
/data/manifest/application.yaml \
43+
; do envsubst '$PGO_VERSION' < "$file" > /tmp/sponge && mv /tmp/sponge "$file" ; done
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.DEFAULT_GOAL := help
2+
3+
DEPLOYER_IMAGE ?= registry.localhost:5000/postgres-operator-gcp-marketplace-deployer:$(PGO_VERSION)
4+
IMAGE_BUILDER ?= buildah
5+
MARKETPLACE_TOOLS ?= gcr.io/cloud-marketplace-tools/k8s/dev:$(MARKETPLACE_VERSION)
6+
MARKETPLACE_VERSION ?= 0.9.4
7+
KUBECONFIG ?= $(HOME)/.kube/config
8+
PARAMETERS ?= {}
9+
PGO_VERSION ?= 4.1.1
10+
11+
IMAGE_BUILD_ARGS = --build-arg MARKETPLACE_VERSION='$(MARKETPLACE_VERSION)' \
12+
--build-arg PGO_VERSION='$(PGO_VERSION)'
13+
14+
MARKETPLACE_TOOLS_DEV = docker run --net=host --rm \
15+
--mount 'type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock,readonly' \
16+
--mount 'type=bind,source=$(KUBECONFIG),target=/mount/config/.kube/config,readonly' \
17+
'$(MARKETPLACE_TOOLS)'
18+
19+
# One does _not_ need to be logged in with gcloud.
20+
.PHONY: doctor
21+
doctor: ## Check development prerequisites
22+
$(MARKETPLACE_TOOLS_DEV) doctor
23+
24+
.PHONY: doctor-fix
25+
doctor-fix:
26+
@# https://github.com/kubernetes-sigs/application/tree/master/config/crds
27+
kubectl 2>/dev/null get crd/applications.app.k8s.io -o jsonpath='{""}' || \
28+
kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/marketplace-k8s-app-tools/master/crd/app-crd.yaml
29+
30+
.PHONY: help
31+
help: ALIGN=14
32+
help: ## Print this message
33+
@awk -F ': ## ' -- "/^[^':]+: ## /"' { printf "'$$(tput bold)'%-$(ALIGN)s'$$(tput sgr0)' %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
34+
35+
.PHONY: image
36+
image: image-$(IMAGE_BUILDER)
37+
38+
.PHONY: image-buildah
39+
image-buildah: ## Build the deployer image with Buildah
40+
sudo buildah bud --file Dockerfile --tag '$(DEPLOYER_IMAGE)' $(IMAGE_BUILD_ARGS) --layers ../..
41+
sudo buildah push '$(DEPLOYER_IMAGE)' docker-daemon:'$(DEPLOYER_IMAGE)'
42+
43+
.PHONY: image-docker
44+
image-docker: ## Build the deployer image with Docker
45+
docker build --file Dockerfile --tag '$(DEPLOYER_IMAGE)' $(IMAGE_BUILD_ARGS) ../..
46+
47+
# PARAMETERS='{"OPERATOR_NAMESPACE": "", "OPERATOR_NAME": "", "OPERATOR_ADMIN_PASSWORD": ""}'
48+
.PHONY: install
49+
install: ## Execute the deployer image in an existing Kubernetes namespace
50+
$(MARKETPLACE_TOOLS_DEV) install --deployer='$(DEPLOYER_IMAGE)' --parameters='$(PARAMETERS)'
51+
52+
# PARAMETERS='{"OPERATOR_ADMIN_PASSWORD": ""}'
53+
.PHONY: verify
54+
verify: ## Execute and test the deployer image in a new (random) Kubernetes namespace then clean up
55+
$(MARKETPLACE_TOOLS_DEV) verify --deployer='$(DEPLOYER_IMAGE)' --parameters='$(PARAMETERS)'
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
2+
This directory contains the files needed to offer the Operator as a
3+
[Google Cloud Platform Marketplace Kubernetes application][gcp-k8s].
4+
5+
The integration centers around a container [image](./Dockerfile) that contains an installation
6+
[schema](./schema.yaml) and an [Application][k8s-app] [manifest](./application.yaml).
7+
Consult the [technical requirements][gcp-k8s-requirements] when making changes.
8+
9+
[k8s-app]: https://github.com/kubernetes-sigs/application/
10+
[gcp-k8s]: https://cloud.google.com/marketplace/docs/kubernetes-apps/
11+
[gcp-k8s-requirements]: https://cloud.google.com/marketplace/docs/partners/kubernetes-solutions/create-app-package
12+
[gcp-k8s-tool-images]: https://console.cloud.google.com/gcr/images/cloud-marketplace-tools
13+
[gcp-k8s-tool-repository]: https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools
14+
15+
16+
# Installation
17+
18+
## Quick install with Google Cloud Marketplace
19+
20+
Install this application to a Google Kubernetes Engine cluster using Google Cloud Marketplace.
21+
22+
## Command line instructions
23+
24+
### Prepare
25+
26+
1. You'll need the following tools in your development environment. If you are using Cloud Shell,
27+
everything is already installed.
28+
29+
- envsubst
30+
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
31+
- [kubectl](https://kubernetes.io/docs/reference/kubectl/overview/)
32+
33+
2. Clone this repository.
34+
35+
```shell
36+
git clone https://github.com/CrunchyData/postgres-operator.git
37+
```
38+
39+
3. Install the [Application][k8s-app] Custom Resource Definition.
40+
41+
```shell
42+
kubectl apply -f 'https://raw.githubusercontent.com/GoogleCloudPlatform/marketplace-k8s-app-tools/master/crd/app-crd.yaml'
43+
```
44+
45+
4. At least one Storage Class is required. Google Kubernetes Engine is preconfigured with a default.
46+
47+
```shell
48+
kubectl get storageclasses
49+
```
50+
51+
### Install the PostgreSQL Operator
52+
53+
1. Configure the installation by setting environment variables.
54+
55+
1. Choose a version to install.
56+
57+
```shell
58+
IMAGE_REPOSITORY=gcr.io/crunchydata-public/postgres-operator
59+
60+
export PGO_VERSION=4.1.1
61+
export INSTALLER_IMAGE=${IMAGE_REPOSITORY}/deployer:${PGO_VERSION}
62+
export OPERATOR_IMAGE=${IMAGE_REPOSITORY}:${PGO_VERSION}
63+
export OPERATOR_IMAGE_API=${IMAGE_REPOSITORY}/pgo-apiserver:${PGO_VERSION}
64+
export OPERATOR_IMAGE_EVENT=${IMAGE_REPOSITORY}/pgo-event:${PGO_VERSION}
65+
export OPERATOR_IMAGE_SCHEDULER=${IMAGE_REPOSITORY}/pgo-scheduler:${PGO_VERSION}
66+
```
67+
68+
2. Choose a namespace and name for the application.
69+
70+
```shell
71+
export OPERATOR_NAMESPACE=pgo OPERATOR_NAME=pgo
72+
```
73+
74+
2. Choose a password for the application admin.
75+
76+
```shell
77+
export OPERATOR_ADMIN_PASSWORD=changethis
78+
```
79+
80+
4. Choose default values for new PostgreSQL clusters.
81+
82+
```shell
83+
export POSTGRES_METRICS=false
84+
export POSTGRES_SERVICE_TYPE=ClusterIP
85+
export POSTGRES_CPU=1000 # mCPU
86+
export POSTGRES_MEM=2 # GiB
87+
export POSTGRES_STORAGE_CAPACITY=1 # GiB
88+
export POSTGRES_STORAGE_CLASS=ssd
89+
export PGBACKREST_STORAGE_CAPACITY=2 # GiB
90+
export PGBACKREST_STORAGE_CLASS=ssd
91+
export BACKUP_STORAGE_CAPACITY=1 # GiB
92+
export BACKUP_STORAGE_CLASS=ssd
93+
```
94+
95+
2. Prepare the Kubernetes namespace.
96+
97+
```shell
98+
export INSTALLER_SERVICE_ACCOUNT=postgres-operator-installer
99+
100+
kubectl create namespace "$OPERATOR_NAMESPACE"
101+
kubectl create serviceaccount -n "$OPERATOR_NAMESPACE" "$INSTALLER_SERVICE_ACCOUNT"
102+
kubectl create clusterrolebinding \
103+
"$OPERATOR_NAMESPACE:$INSTALLER_SERVICE_ACCOUNT:cluster-admin" \
104+
--serviceaccount="$OPERATOR_NAMESPACE:$INSTALLER_SERVICE_ACCOUNT" \
105+
--clusterrole=cluster-admin
106+
```
107+
108+
3. Generate and apply Kubernetes manifests.
109+
110+
```shell
111+
envsubst < application.yaml > "${OPERATOR_NAME}_application.yaml"
112+
envsubst < install-job.yaml > "${OPERATOR_NAME}_install-job.yaml"
113+
envsubst < inventory.ini > "${OPERATOR_NAME}_inventory.ini"
114+
115+
kubectl create -n "$OPERATOR_NAMESPACE" secret generic install-postgres-operator \
116+
--from-file=inventory="${OPERATOR_NAME}_inventory.ini"
117+
118+
kubectl create -n "$OPERATOR_NAMESPACE" -f "${OPERATOR_NAME}_application.yaml"
119+
kubectl create -n "$OPERATOR_NAMESPACE" -f "${OPERATOR_NAME}_install-job.yaml"
120+
```
121+
122+
The application can be seen in Google Cloud Platform Console at [Kubernetes Applications][].
123+
124+
[Kubernetes Applications]: https://console.cloud.google.com/kubernetes/application
125+
126+
127+
# Uninstallation
128+
129+
## Using Google Cloud Platform Console
130+
131+
1. In the Console, open [Kubernetes Applications][].
132+
2. From the list of applications, select _Crunchy PostgreSQL Operator_ then click _Delete_.
133+
134+
## Command line instructions
135+
136+
Delete the Kubernetes resources created during install.
137+
138+
```shell
139+
export OPERATOR_NAMESPACE=pgo OPERATOR_NAME=pgo
140+
141+
kubectl delete -n "$OPERATOR_NAMESPACE" job install-postgres-operator
142+
kubectl delete -n "$OPERATOR_NAMESPACE" secret install-postgres-operator
143+
kubectl delete -n "$OPERATOR_NAMESPACE" application "$OPERATOR_NAME"
144+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
apiVersion: app.k8s.io/v1beta1
2+
kind: Application
3+
metadata:
4+
name: '${OPERATOR_NAME}'
5+
labels:
6+
app.kubernetes.io/name: '${OPERATOR_NAME}'
7+
spec:
8+
selector:
9+
matchLabels:
10+
app.kubernetes.io/name: '${OPERATOR_NAME}'
11+
componentKinds:
12+
- { group: core, kind: ConfigMap }
13+
- { group: core, kind: Secret }
14+
- { group: core, kind: Service }
15+
- { group: apps, kind: Deployment }
16+
- { group: batch, kind: Job }
17+
descriptor:
18+
description: Enterprise PostgreSQL-as-a-Service for Kubernetes
19+
type: Crunchy PostgreSQL Operator
20+
version: '${PGO_VERSION}'
21+
icons:
22+
- src: https://raw.githubusercontent.com/CrunchyData/crunchy-containers/master/images/crunchy_logo.png
23+
maintainers:
24+
- name: Crunchy Data
25+
url: https://www.crunchydata.com/
26+
27+
keywords:
28+
- postgres
29+
- postgresql
30+
- database
31+
- sql
32+
- operator
33+
- crunchy data
34+
links:
35+
- description: Crunchy PostgreSQL for Kubernetes
36+
url: https://www.crunchydata.com/products/crunchy-postgresql-for-kubernetes/
37+
- description: Documentation
38+
url: 'https://access.crunchydata.com/documentation/postgres-operator/${PGO_VERSION}'
39+
- description: GitHub
40+
url: https://github.com/CrunchyData/postgres-operator
41+
42+
info:
43+
- name: Operator API
44+
value: kubectl port-forward --namespace '${OPERATOR_NAMESPACE}' service/postgres-operator 8443
45+
- name: Operator Client
46+
value: 'https://github.com/CrunchyData/postgres-operator/releases/tag/v${PGO_VERSION}'
47+
- name: Operator User
48+
type: Reference
49+
valueFrom: { type: SecretKeyRef, secretKeyRef: { name: pgouser-admin, key: username } }
50+
- name: Operator Password
51+
type: Reference
52+
valueFrom: { type: SecretKeyRef, secretKeyRef: { name: pgouser-admin, key: password } }
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env bash
2+
# vim: set noexpandtab :
3+
set -eu
4+
5+
kc() { kubectl --namespace="$NAMESPACE" "$@"; }
6+
7+
application_metadata="$( kc get "applications.app.k8s.io/$NAME" --output=json )"
8+
application_metadata="$( jq <<< "$application_metadata" '{ metadata: {
9+
labels: { "app.kubernetes.io/name": .metadata.name },
10+
ownerReferences: [{
11+
apiVersion, kind, name: .metadata.name, uid: .metadata.uid
12+
}]
13+
} }' )"
14+
15+
existing="$( kc get deployment/postgres-operator --output=json 2> /dev/null || true )"
16+
17+
if [ -n "$existing" ]; then
18+
>&2 echo ERROR: Crunchy PostgreSQL Operator is already installed in this namespace
19+
exit 1
20+
fi
21+
22+
installer="$( /bin/config_env.py envsubst < /opt/postgres-operator/install-job.yaml )"
23+
inventory="$( /bin/config_env.py envsubst < /opt/postgres-operator/inventory.ini )"
24+
25+
kc create --filename=/dev/stdin <<< "$installer"
26+
kc patch job/install-postgres-operator --type=strategic --patch="$application_metadata"
27+
28+
job_metadata="$( kc get job/install-postgres-operator --output=json )"
29+
job_metadata="$( jq <<< "$job_metadata" '{ metadata: {
30+
labels: { "app.kubernetes.io/name": .metadata.labels["app.kubernetes.io/name"] },
31+
ownerReferences: [{
32+
apiVersion, kind, name: .metadata.name, uid: .metadata.uid
33+
}]
34+
} }' )"
35+
36+
kc create secret generic install-postgres-operator --from-file=inventory=/dev/stdin <<< "$inventory"
37+
kc patch secret/install-postgres-operator --type=strategic --patch="$job_metadata"
38+
39+
# Wait for either status condition then terminate the other.
40+
kc wait --for=condition=complete --timeout=5m job/install-postgres-operator &
41+
kc wait --for=condition=failed --timeout=5m job/install-postgres-operator &
42+
wait -n
43+
kill -s INT %% 2> /dev/null || true
44+
45+
kc logs --selector=job-name=install-postgres-operator --tail=-1
46+
test 'Complete' = "$( kc get job/install-postgres-operator --output=jsonpath='{.status.conditions[*].type}' )"
47+
48+
exec /opt/postgres-operator/cloud-marketplace-tools/bin/create_manifests.sh "$@"

0 commit comments

Comments
 (0)