Merge "Add HTTPS support to K8s API healthchecks"
This commit is contained in:
commit
ffc19f0df2
kuryr_kubernetes
@ -11,14 +11,15 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import requests
|
|
||||||
from six.moves import http_client as httplib
|
from six.moves import http_client as httplib
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from pyroute2 import IPDB
|
from pyroute2 import IPDB
|
||||||
|
|
||||||
from kuryr.lib._i18n import _
|
from kuryr.lib._i18n import _
|
||||||
|
from kuryr_kubernetes import clients
|
||||||
from kuryr_kubernetes.cni import utils
|
from kuryr_kubernetes.cni import utils
|
||||||
|
from kuryr_kubernetes import exceptions as exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ class CNIHealthServer(object):
|
|||||||
|
|
||||||
def readiness_status(self):
|
def readiness_status(self):
|
||||||
data = 'ok'
|
data = 'ok'
|
||||||
k8s_conn, k8s_status = self.verify_k8s_connection()
|
k8s_conn = self.verify_k8s_connection()
|
||||||
|
|
||||||
if not _has_cap(CAP_NET_ADMIN, EFFECTIVE_CAPS):
|
if not _has_cap(CAP_NET_ADMIN, EFFECTIVE_CAPS):
|
||||||
error_message = 'NET_ADMIN capabilities not present.'
|
error_message = 'NET_ADMIN capabilities not present.'
|
||||||
@ -117,7 +118,7 @@ class CNIHealthServer(object):
|
|||||||
if not k8s_conn:
|
if not k8s_conn:
|
||||||
error_message = 'Error when processing k8s healthz request.'
|
error_message = 'Error when processing k8s healthz request.'
|
||||||
LOG.error(error_message)
|
LOG.error(error_message)
|
||||||
return error_message, k8s_status, self.headers
|
return error_message, httplib.INTERNAL_SERVER_ERROR, self.headers
|
||||||
|
|
||||||
LOG.info('CNI driver readiness verified.')
|
LOG.info('CNI driver readiness verified.')
|
||||||
return data, httplib.OK, self.headers
|
return data, httplib.OK, self.headers
|
||||||
@ -160,8 +161,10 @@ class CNIHealthServer(object):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def verify_k8s_connection(self):
|
def verify_k8s_connection(self):
|
||||||
path = '/healthz'
|
k8s = clients.get_kubernetes_client()
|
||||||
address = CONF.kubernetes.api_root
|
try:
|
||||||
url = address + path
|
k8s.get('/healthz', json=False, headers={'Connection': 'close'})
|
||||||
resp = requests.get(url, headers={'Connection': 'close'})
|
except exc.K8sClientException:
|
||||||
return resp.content == 'ok', resp.status_code
|
LOG.exception('Exception when trying to reach Kubernetes API.')
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
@ -12,18 +12,21 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from six.moves import http_client as httplib
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from keystoneauth1 import exceptions as k_exc
|
from keystoneauth1 import exceptions as k_exc
|
||||||
from keystoneclient import client as keystone_client
|
from keystoneclient import client as keystone_client
|
||||||
from kuryr.lib._i18n import _
|
from kuryr.lib._i18n import _
|
||||||
from kuryr.lib import config as kuryr_config
|
from kuryr.lib import config as kuryr_config
|
||||||
from kuryr.lib import utils
|
from kuryr.lib import utils
|
||||||
|
from kuryr_kubernetes import clients
|
||||||
|
from kuryr_kubernetes import exceptions as exc
|
||||||
from kuryr_kubernetes.handlers import health as h_health
|
from kuryr_kubernetes.handlers import health as h_health
|
||||||
import os
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log as logging
|
|
||||||
import requests
|
|
||||||
from six.moves import http_client as httplib
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@ -65,11 +68,11 @@ class HealthServer(object):
|
|||||||
LOG.error(error_message)
|
LOG.error(error_message)
|
||||||
return error_message, httplib.NOT_FOUND, self.headers
|
return error_message, httplib.NOT_FOUND, self.headers
|
||||||
|
|
||||||
k8s_conn, status = self.verify_k8s_connection()
|
k8s_conn = self.verify_k8s_connection()
|
||||||
if not k8s_conn:
|
if not k8s_conn:
|
||||||
error_message = 'Error when processing k8s healthz request.'
|
error_message = 'Error when processing k8s healthz request.'
|
||||||
LOG.error(error_message)
|
LOG.error(error_message)
|
||||||
return error_message, status, self.headers
|
return error_message, httplib.INTERNAL_SERVER_ERROR, self.headers
|
||||||
try:
|
try:
|
||||||
self.verify_keystone_connection()
|
self.verify_keystone_connection()
|
||||||
except k_exc.http.HttpError as h_ex:
|
except k_exc.http.HttpError as h_ex:
|
||||||
@ -109,11 +112,13 @@ class HealthServer(object):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def verify_k8s_connection(self):
|
def verify_k8s_connection(self):
|
||||||
path = '/healthz'
|
k8s = clients.get_kubernetes_client()
|
||||||
address = CONF.kubernetes.api_root
|
try:
|
||||||
url = address + path
|
k8s.get('/healthz', json=False, headers={'Connection': 'close'})
|
||||||
resp = requests.get(url, headers={'Connection': 'close'})
|
except exc.K8sClientException:
|
||||||
return resp.content == 'ok', resp.status_code
|
LOG.exception('Exception when trying to reach Kubernetes API.')
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def verify_keystone_connection(self):
|
def verify_keystone_connection(self):
|
||||||
conf_group = kuryr_config.neutron_group.name
|
conf_group = kuryr_config.neutron_group.name
|
||||||
|
@ -65,18 +65,21 @@ class K8sClient(object):
|
|||||||
else:
|
else:
|
||||||
self.verify_server = ca_crt_file
|
self.verify_server = ca_crt_file
|
||||||
|
|
||||||
def get(self, path):
|
def get(self, path, json=True, headers=None):
|
||||||
LOG.debug("Get %(path)s", {'path': path})
|
LOG.debug("Get %(path)s", {'path': path})
|
||||||
url = self._base_url + path
|
url = self._base_url + path
|
||||||
header = {}
|
header = {}
|
||||||
if self.token:
|
if self.token:
|
||||||
header.update({'Authorization': 'Bearer %s' % self.token})
|
header.update({'Authorization': 'Bearer %s' % self.token})
|
||||||
|
if headers:
|
||||||
|
header.update(headers)
|
||||||
response = requests.get(url, cert=self.cert,
|
response = requests.get(url, cert=self.cert,
|
||||||
verify=self.verify_server,
|
verify=self.verify_server,
|
||||||
headers=header)
|
headers=header)
|
||||||
if not response.ok:
|
if not response.ok:
|
||||||
raise exc.K8sClientException(response.text)
|
raise exc.K8sClientException(response.text)
|
||||||
return response.json()
|
result = response.json() if json else response.text
|
||||||
|
return result
|
||||||
|
|
||||||
def _get_url_and_header(self, path):
|
def _get_url_and_header(self, path):
|
||||||
url = self._base_url + path
|
url = self._base_url + path
|
||||||
|
@ -54,9 +54,9 @@ class TestCNIHealthServer(base.TestCase):
|
|||||||
'verify_k8s_connection')
|
'verify_k8s_connection')
|
||||||
def test_readiness_status_k8s_error(self, m_verify_k8s_conn, cap_tester):
|
def test_readiness_status_k8s_error(self, m_verify_k8s_conn, cap_tester):
|
||||||
cap_tester.return_value = True
|
cap_tester.return_value = True
|
||||||
m_verify_k8s_conn.return_value = False, 503
|
m_verify_k8s_conn.return_value = False
|
||||||
resp = self.test_client.get('/ready')
|
resp = self.test_client.get('/ready')
|
||||||
self.assertEqual(503, resp.status_code)
|
self.assertEqual(500, resp.status_code)
|
||||||
|
|
||||||
@mock.patch('pyroute2.IPDB.release')
|
@mock.patch('pyroute2.IPDB.release')
|
||||||
def test_liveness_status(self, m_ipdb):
|
def test_liveness_status(self, m_ipdb):
|
||||||
|
@ -65,11 +65,11 @@ class TestHealthServer(base.TestCase):
|
|||||||
@mock.patch('os.path.exists')
|
@mock.patch('os.path.exists')
|
||||||
def test_read_k8s_error(self, m_exist, m_verify_k8s_conn):
|
def test_read_k8s_error(self, m_exist, m_verify_k8s_conn):
|
||||||
m_exist.return_value = True
|
m_exist.return_value = True
|
||||||
m_verify_k8s_conn.return_value = False, 503
|
m_verify_k8s_conn.return_value = False
|
||||||
resp = self.test_client.get('/ready')
|
resp = self.test_client.get('/ready')
|
||||||
|
|
||||||
m_verify_k8s_conn.assert_called_once()
|
m_verify_k8s_conn.assert_called_once()
|
||||||
self.assertEqual(503, resp.status_code)
|
self.assertEqual(500, resp.status_code)
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.controller.managers.health.HealthServer.'
|
@mock.patch('kuryr_kubernetes.controller.managers.health.HealthServer.'
|
||||||
'verify_keystone_connection')
|
'verify_keystone_connection')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user