Make the CA bundle configurable for in-cluster Kubernetes config (#2025)

Close https://github.com/zalando/patroni/issues/1758
This commit is contained in:
Aron Parsons
2021-08-17 16:15:39 +02:00
committed by GitHub
parent db12051a5b
commit 313adb61ec
3 changed files with 10 additions and 5 deletions
+1
View File
@@ -106,6 +106,7 @@ Kubernetes
- **PATRONI\_KUBERNETES\_USE\_ENDPOINTS**: (optional) if set to true, Patroni will use Endpoints instead of ConfigMaps to run leader elections and keep cluster state.
- **PATRONI\_KUBERNETES\_POD\_IP**: (optional) IP address of the pod Patroni is running in. This value is required when `PATRONI_KUBERNETES_USE_ENDPOINTS` is enabled and is used to populate the leader endpoint subsets when the pod's PostgreSQL is promoted.
- **PATRONI\_KUBERNETES\_PORTS**: (optional) if the Service object has the name for the port, the same name must appear in the Endpoint object, otherwise service won't work. For example, if your service is defined as ``{Kind: Service, spec: {ports: [{name: postgresql, port: 5432, targetPort: 5432}]}}``, then you have to set ``PATRONI_KUBERNETES_PORTS='[{"name": "postgresql", "port": 5432}]'`` and Patroni will use it for updating subsets of the leader Endpoint. This parameter is used only if `PATRONI_KUBERNETES_USE_ENDPOINTS` is set.
- **PATRONI\_KUBERNETES\_CACERT**: (optional) Specifies the file with the CA_BUNDLE file with certificates of trusted CAs to use while verifying Kubernetes API SSL certs. If not provided, patroni will use the value provided by the ServiceAccount secret.
Raft
----
+1
View File
@@ -205,6 +205,7 @@ Kubernetes
- **use\_endpoints**: (optional) if set to true, Patroni will use Endpoints instead of ConfigMaps to run leader elections and keep cluster state.
- **pod\_ip**: (optional) IP address of the pod Patroni is running in. This value is required when `use_endpoints` is enabled and is used to populate the leader endpoint subsets when the pod's PostgreSQL is promoted.
- **ports**: (optional) if the Service object has the name for the port, the same name must appear in the Endpoint object, otherwise service won't work. For example, if your service is defined as ``{Kind: Service, spec: {ports: [{name: postgresql, port: 5432, targetPort: 5432}]}}``, then you have to set ``kubernetes.ports: [{"name": "postgresql", "port": 5432}]`` and Patroni will use it for updating subsets of the leader Endpoint. This parameter is used only if `kubernetes.use_endpoints` is set.
- **cacert**: (optional) Specifies the file with the CA_BUNDLE file with certificates of trusted CAs to use while verifying Kubernetes API SSL certs. If not provided, patroni will use the value provided by the ServiceAccount secret.
.. _raft_settings:
+8 -5
View File
@@ -55,16 +55,19 @@ class K8sConfig(object):
if token:
self._headers['authorization'] = 'Bearer ' + token
def load_incluster_config(self):
def load_incluster_config(self, ca_certs=SERVICE_CERT_FILENAME):
if SERVICE_HOST_ENV_NAME not in os.environ or SERVICE_PORT_ENV_NAME not in os.environ:
raise self.ConfigException('Service host/port is not set.')
if not os.environ[SERVICE_HOST_ENV_NAME] or not os.environ[SERVICE_PORT_ENV_NAME]:
raise self.ConfigException('Service host/port is set but empty.')
if not os.path.isfile(SERVICE_CERT_FILENAME):
if not os.path.isfile(ca_certs):
raise self.ConfigException('Service certificate file does not exists.')
with open(SERVICE_CERT_FILENAME) as f:
with open(ca_certs) as f:
if not f.read():
raise self.ConfigException('Cert file exists but empty.')
self.pool_config['ca_certs'] = ca_certs
if not os.path.isfile(SERVICE_TOKEN_FILENAME):
raise self.ConfigException('Service token file does not exists.')
with open(SERVICE_TOKEN_FILENAME) as f:
@@ -72,7 +75,6 @@ class K8sConfig(object):
if not token:
raise self.ConfigException('Token file exists but empty.')
self._make_headers(token=token)
self.pool_config['ca_certs'] = SERVICE_CERT_FILENAME
self._server = uri('https', (os.environ[SERVICE_HOST_ENV_NAME], os.environ[SERVICE_PORT_ENV_NAME]))
@staticmethod
@@ -613,13 +615,14 @@ class Kubernetes(AbstractDCS):
self._label_selector = ','.join('{0}={1}'.format(k, v) for k, v in self._labels.items())
self._namespace = config.get('namespace') or 'default'
self._role_label = config.get('role_label', 'role')
self._ca_certs = os.environ.get('PATRONI_KUBERNETES_CACERT', config.get('cacert')) or SERVICE_CERT_FILENAME
config['namespace'] = ''
super(Kubernetes, self).__init__(config)
self._retry = Retry(deadline=config['retry_timeout'], max_delay=1, max_tries=-1,
retry_exceptions=KubernetesRetriableException)
self._ttl = None
try:
k8s_config.load_incluster_config()
k8s_config.load_incluster_config(ca_certs=self._ca_certs)
except k8s_config.ConfigException:
k8s_config.load_kube_config(context=config.get('context', 'local'))