mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-26 15:40:21 +00:00
Compare commits
4
Commits
tutorial
...
feature/demo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d9720a78d | ||
|
|
1f205f8191 | ||
|
|
5a56b71946 | ||
|
|
e3b431bf38 |
@@ -1,29 +1,29 @@
|
|||||||
FROM postgres:9.6
|
FROM postgres:10
|
||||||
MAINTAINER Alexander Kukushkin <[email protected]>
|
MAINTAINER Alexander Kukushkin <[email protected]>
|
||||||
|
|
||||||
RUN export DEBIAN_FRONTEND=noninteractive \
|
RUN export DEBIAN_FRONTEND=noninteractive \
|
||||||
&& echo 'APT::Install-Recommends "0";\nAPT::Install-Suggests "0";' > /etc/apt/apt.conf.d/01norecommend \
|
&& echo 'APT::Install-Recommends "0";\nAPT::Install-Suggests "0";' > /etc/apt/apt.conf.d/01norecommend \
|
||||||
&& apt-get update -y \
|
&& apt-get update -y \
|
||||||
&& apt-get upgrade -y \
|
&& apt-get upgrade -y \
|
||||||
&& apt-get install -y git curl jq python-psycopg2 python-yaml python-requests python-six python-pysocks \
|
&& apt-get install -s patroni | sed -n -e '/^Inst patroni /d' -e 's/^Inst \([^ ]\+\) .*$/\1/p' \
|
||||||
python-dateutil python-pip python-prettytable python-wheel python-psutil python locales \
|
| xargs apt-get install -y curl jq locales git python3-pip python3-wheel \
|
||||||
|
|
||||||
## Make sure we have a en_US.UTF-8 locale available
|
## Make sure we have a en_US.UTF-8 locale available
|
||||||
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \
|
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \
|
||||||
|
|
||||||
&& pip install setuptools pip --upgrade \
|
&& pip3 install setuptools \
|
||||||
&& pip install 'git+https://github.com/zalando/patroni.git#egg=patroni[kubernetes]' \
|
&& pip3 install 'git+https://github.com/zalando/patroni.git#egg=patroni[kubernetes]' \
|
||||||
|
|
||||||
&& mkdir -p /home/postgres \
|
&& mkdir -p /home/postgres \
|
||||||
&& chown postgres:postgres /home/postgres \
|
&& chown postgres:postgres /home/postgres \
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
&& apt-get remove -y git python-pip python-setuptools \
|
&& apt-get remove -y git python3-pip python3-wheel \
|
||||||
&& apt-get autoremove -y \
|
&& apt-get autoremove -y \
|
||||||
&& apt-get clean -y \
|
&& apt-get clean -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* /root/.cache
|
&& rm -rf /var/lib/apt/lists/* /root/.cache
|
||||||
|
|
||||||
ADD entrypoint.sh callback.py /
|
ADD entrypoint.sh /
|
||||||
|
|
||||||
EXPOSE 5432 8008
|
EXPOSE 5432 8008
|
||||||
ENV LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
|
ENV LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
from kubernetes import client as k8s_client, config as k8s_config
|
|
||||||
from urllib3.exceptions import HTTPError
|
|
||||||
from six.moves.http_client import HTTPException
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class CoreV1Api(k8s_client.CoreV1Api):
|
|
||||||
|
|
||||||
def retry(func):
|
|
||||||
def wrapped(*args, **kwargs):
|
|
||||||
count = 0
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
except (HTTPException, HTTPError, socket.error, socket.timeout):
|
|
||||||
if count >= 10:
|
|
||||||
raise
|
|
||||||
logger.info('Throttling API requests...')
|
|
||||||
time.sleep(2 ** count * 0.5)
|
|
||||||
count += 1
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
@retry
|
|
||||||
def patch_namespaced_endpoints(self, *args, **kwargs):
|
|
||||||
return super(CoreV1Api, self).patch_namespaced_endpoints(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def patch_master_endpoint(api, namespace, cluster):
|
|
||||||
addresses = [k8s_client.V1EndpointAddress(ip=os.environ['POD_IP'])]
|
|
||||||
ports = [k8s_client.V1EndpointPort(port=5432)]
|
|
||||||
subsets = [k8s_client.V1EndpointSubset(addresses=addresses, ports=ports)]
|
|
||||||
body = k8s_client.V1Endpoints(subsets=subsets)
|
|
||||||
return api.patch_namespaced_endpoints(cluster, namespace, body)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
|
|
||||||
if len(sys.argv) != 4 or sys.argv[1] not in ('on_start', 'on_stop', 'on_role_change'):
|
|
||||||
sys.exit('Usage: %s <action> <role> <cluster_name>', sys.argv[0])
|
|
||||||
|
|
||||||
action, role, cluster = sys.argv[1:4]
|
|
||||||
|
|
||||||
k8s_config.load_incluster_config()
|
|
||||||
k8s_api = CoreV1Api()
|
|
||||||
|
|
||||||
namespace = os.environ['KUBERNETES_NAMESPACE']
|
|
||||||
|
|
||||||
if role == 'master' and action in ('on_start', 'on_role_change'):
|
|
||||||
patch_master_endpoint(k8s_api, namespace, cluster)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# here you can defind your own alias to minikube
|
||||||
|
lkubectl='kubectl --context=local'
|
||||||
|
|
||||||
|
shopt -s expand_aliases
|
||||||
|
|
||||||
|
alias lkubectl="$lkubectl"
|
||||||
|
labels=application=patroni,cluster-name=patronidemo
|
||||||
|
|
||||||
|
# clean up objects from previous attempts
|
||||||
|
lkubectl delete statefulset,pods,service,endpoints -l $labels
|
||||||
|
|
||||||
|
# clear old panes
|
||||||
|
for pane in {3..1}; do
|
||||||
|
tmux send-keys -t 0.$pane C-c
|
||||||
|
tmux kill-pane -t 0.$pane
|
||||||
|
done
|
||||||
|
|
||||||
|
tmux send-keys -t 0.0 C-c
|
||||||
|
tmux send-keys -t 0.0 C-l
|
||||||
|
|
||||||
|
# split window into 3 panes
|
||||||
|
tmux split-window -h -t 0.0
|
||||||
|
tmux split-window -v -t 0.0
|
||||||
|
tmux split-window -v -t 0.1
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "export PGPASSWORD=zalando" Enter
|
||||||
|
tmux send-keys -t 0.3 "export PGCONNECT_TIMEOUT=1" Enter
|
||||||
|
|
||||||
|
for pane in {0..3}; do
|
||||||
|
tmux send-keys -t 0.$pane "shopt -s expand_aliases" Enter
|
||||||
|
tmux send-keys -t 0.$pane "alias lkubectl='$lkubectl'" Enter
|
||||||
|
tmux send-keys -t 0.$pane C-l
|
||||||
|
done
|
||||||
|
|
||||||
|
# run
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "lkubectl apply -f patroni_k8s.yaml" Enter
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get pods -w -l $labels -L role -o wide" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 C-c
|
||||||
|
#tmux send-keys -t 0.3 C-l
|
||||||
|
#
|
||||||
|
#tmux send-keys -t 0.3 "lkubectl get pods -l $labels -L role -o wide" Enter
|
||||||
|
#
|
||||||
|
#read
|
||||||
|
|
||||||
|
# tail logs from patroni pods
|
||||||
|
for pane in {0..2}; do
|
||||||
|
tmux send-keys -t 0.$pane "lkubectl logs patronidemo-$pane -f" Enter
|
||||||
|
done
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.0
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.0
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.1
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.1
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get pods -l $labels -L role -o wide" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get services -l $labels" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get endpoints -l $labels" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get pods -l $labels -L role -o wide" Enter
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get endpoints patronidemo -o yaml" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get pods -l $labels -L role -o wide" Enter
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
tmux send-keys -t 0.3 "lkubectl describe service patronidemo-repl" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get endpoints patronidemo-config -o yaml" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
MASTERIP=$(lkubectl get service patronidemo -o jsonpath='{.spec.clusterIP}')
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "watch -n 1 \"psql -h $MASTERIP -U postgres -c \\\"select txid_current(), array_agg(application_name||'=>'|| sync_state) AS \\\\\\\"array_agg(application_name||'=>'||sync_state)\\\\\\\" from pg_stat_replication\\\"\"" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
# kill master node
|
||||||
|
lkubectl delete pod patronidemo-0
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.1
|
||||||
|
tmux send-keys -t 0.1 C-b PageUp
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.1 Enter
|
||||||
|
tmux resize-pane -Z -t 0.1
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.2
|
||||||
|
tmux send-keys -t 0.2 PageUp
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.2 Enter
|
||||||
|
tmux resize-pane -Z -t 0.2
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.0 C-c
|
||||||
|
tmux send-keys -t 0.0 "lkubectl logs patronidemo-0 -f" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
tmux send-keys -t 0.3 C-c
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get pods -l $labels -L role -o wide" Enter
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get endpoints -l $labels" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl get endpoints patronidemo -o yaml" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux resize-pane -Z -t 0.3
|
||||||
|
tmux send-keys -t 0.3 C-c
|
||||||
|
tmux send-keys -t 0.3 C-l
|
||||||
|
tmux send-keys -t 0.3 "lkubectl exec -ti patronidemo-0 patronictl switchover patronidemo" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "patronidemo-0" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "y" Enter
|
||||||
|
|
||||||
|
read
|
||||||
|
|
||||||
|
tmux send-keys -t 0.3 "lkubectl exec -ti patronidemo-0 patronictl list patronidemo" Enter
|
||||||
@@ -13,24 +13,11 @@ bootstrap:
|
|||||||
- data-checksums
|
- data-checksums
|
||||||
pg_hba:
|
pg_hba:
|
||||||
- host all all 0.0.0.0/0 md5
|
- host all all 0.0.0.0/0 md5
|
||||||
- host replication ${PATRONI_REPLICATION_USERNAME} ${POD_IP}/16 md5
|
- host replication ${PATRONI_REPLICATION_USERNAME} ${PATRONI_KUBERNETES_POD_IP}/16 md5
|
||||||
restapi:
|
restapi:
|
||||||
connect_address: '${POD_IP}:8008'
|
connect_address: '${PATRONI_KUBERNETES_POD_IP}:8008'
|
||||||
postgresql:
|
postgresql:
|
||||||
connect_address: '${POD_IP}:5432'
|
connect_address: '${PATRONI_KUBERNETES_POD_IP}:5432'
|
||||||
authentication:
|
|
||||||
superuser:
|
|
||||||
password: '${PATRONI_SUPERUSER_PASSWORD}'
|
|
||||||
replication:
|
|
||||||
password: '${PATRONI_REPLICATION_PASSWORD}'
|
|
||||||
callbacks:
|
|
||||||
on_start: /callback.py
|
|
||||||
on_stop: /callback.py
|
|
||||||
on_role_change: /callback.py
|
|
||||||
__EOF__
|
__EOF__
|
||||||
|
|
||||||
unset PATRONI_SUPERUSER_PASSWORD PATRONI_REPLICATION_PASSWORD
|
exec /usr/bin/python3 /usr/local/bin/patroni /home/postgres/patroni.yml
|
||||||
export KUBERNETES_NAMESPACE=$PATRONI_KUBERNETES_NAMESPACE
|
|
||||||
export POD_NAME=$PATRONI_NAME
|
|
||||||
|
|
||||||
exec /usr/bin/python /usr/local/bin/patroni /home/postgres/patroni.yml
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# This manifest (and Docker image) works only with emptyDir volume and are designed for demo purpose.
|
||||||
|
# For production usage please take a look at https://github.com/zalando/spilo/tree/master/postgres-appliance
|
||||||
apiVersion: apps/v1beta1
|
apiVersion: apps/v1beta1
|
||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
@@ -19,6 +21,9 @@ spec:
|
|||||||
- name: *cluster_name
|
- name: *cluster_name
|
||||||
image: patroni # docker build -t patroni .
|
image: patroni # docker build -t patroni .
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
|
# resources:
|
||||||
|
# limits:
|
||||||
|
# cpu: 100m
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8008
|
- containerPort: 8008
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
@@ -28,7 +33,7 @@ spec:
|
|||||||
- mountPath: /home/postgres/pgdata
|
- mountPath: /home/postgres/pgdata
|
||||||
name: pgdata
|
name: pgdata
|
||||||
env:
|
env:
|
||||||
- name: POD_IP
|
- name: PATRONI_KUBERNETES_POD_IP
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
fieldPath: status.podIP
|
fieldPath: status.podIP
|
||||||
@@ -36,6 +41,8 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
fieldPath: metadata.namespace
|
fieldPath: metadata.namespace
|
||||||
|
- name: PATRONI_KUBERNETES_USE_ENDPOINTS
|
||||||
|
value: 'true'
|
||||||
- name: PATRONI_KUBERNETES_LABELS
|
- name: PATRONI_KUBERNETES_LABELS
|
||||||
value: '{application: patroni, cluster-name: patronidemo}'
|
value: '{application: patroni, cluster-name: patronidemo}'
|
||||||
- name: PATRONI_SUPERUSER_USERNAME
|
- name: PATRONI_SUPERUSER_USERNAME
|
||||||
@@ -86,6 +93,7 @@ spec:
|
|||||||
# storage: 5Gi
|
# storage: 5Gi
|
||||||
|
|
||||||
---
|
---
|
||||||
|
# Endpoint for leader elections
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Endpoints
|
kind: Endpoints
|
||||||
metadata:
|
metadata:
|
||||||
@@ -96,6 +104,7 @@ metadata:
|
|||||||
subsets: []
|
subsets: []
|
||||||
|
|
||||||
---
|
---
|
||||||
|
# master Service
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
@@ -110,6 +119,26 @@ spec:
|
|||||||
targetPort: 5432
|
targetPort: 5432
|
||||||
|
|
||||||
---
|
---
|
||||||
|
# replica Service
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: patronidemo-repl
|
||||||
|
labels:
|
||||||
|
application: patroni
|
||||||
|
cluster-name: &cluster_name patronidemo
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
application: patroni
|
||||||
|
cluster-name: *cluster_name
|
||||||
|
role: replica
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: 5432
|
||||||
|
|
||||||
|
---
|
||||||
|
# Secrets (superuser password and replication passwor)
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
Reference in New Issue
Block a user