async def watch_namespaces():
    async with client.ApiClient() as api:
        v1 = client.CoreV1Api(api)
        async with watch.Watch().stream(v1.list_namespace) as stream:
            async for event in stream:
                etype, obj = event['type'], event['object']
                print("{} namespace {}".format(etype, obj.metadata.name))
Exemple #2
0
    async def setup(self, app):
        await super().setup(app)
        try:
            # Not a coroutine for some reason
            config.load_incluster_config()
        except config.ConfigException:
            await config.load_kube_config()

        self.api_client = client.ApiClient()
        self.core_client = client.CoreV1Api(api_client=self.api_client)
        self.custom_client = client.CustomObjectsApi(
            api_client=self.api_client)

        self.cluster_waiters = defaultdict(Flag)
        self.clusters = {}
        self.username_to_clusters = defaultdict(dict)
        self.queue = WorkQueue()
        self.informer = Informer(
            parent=self,
            name="cluster",
            client=self.custom_client,
            method="list_cluster_custom_object",
            method_kwargs=dict(
                group="gateway.dask.org",
                version=self.crd_version,
                plural="daskclusters",
                label_selector=self.label_selector,
            ),
            on_update=self.on_cluster_event,
            on_delete=self.on_cluster_event,
        )
        await self.informer.start()
        self.sync_task = asyncio.ensure_future(self.sync_clusters_loop())
Exemple #3
0
    async def _watch(self):
        DBSession = self.connector.DBSession

        k8s_config.load_incluster_config()

        async with k8s_client.ApiClient() as api:
            v1 = k8s_client.CoreV1Api(api)
            with open(os.path.join(self.config_dir, 'runner.namespace')) as fp:
                namespace = fp.read().strip()

            # Find existing run pods
            pods = await v1.list_namespaced_pod(
                namespace=namespace,
                label_selector='app=run',
            )
            PROM_RUNS.set(0)
            for pod in pods.items:
                run_id = int(pod.metadata.labels['run'], 10)
                logger.info("Found run pod for %d", run_id)
                PROM_RUNS.inc()
                await self._check_pod(api, run_id, pod)

            # Watch changes
            watch = k8s_watch.Watch()
            f, kwargs = v1.list_namespaced_pod, dict(
                namespace=namespace,
                label_selector='app=run',
            )
            while True:
                try:
                    async for event in watch.stream(f, **kwargs):
                        await self._handle_watch_event(api, DBSession, event)
                except k8s_client.ApiException as e:
                    if e.status != 410:
                        raise
Exemple #4
0
async def k8s() -> K8sAsync:
    configuration = client.Configuration()
    await config.load_kube_config(client_configuration=configuration)
    api_client = client.ApiClient(configuration)

    return K8sAsync(core_client=client.CoreApi(api_client),
                    v1_client=client.CoreV1Api(api_client))
Exemple #5
0
    async def initialize(self, logger: BoundLogger) -> None:
        """Initialize the dependency.

        This must be called during application startup.
        """
        await initialize_kubernetes()
        self._api_client = client.ApiClient()
        self._state = State()
async def watch_pods():
    async with client.ApiClient() as api:
        v1 = client.CoreV1Api(api)
        async with watch.Watch().stream(
                v1.list_pod_for_all_namespaces) as stream:
            async for event in stream:
                evt, obj = event['type'], event['object']
                print("{} pod {} in NS {}".format(evt, obj.metadata.name,
                                                  obj.metadata.namespace))
Exemple #7
0
 def client(self) -> k8s_client.AppsV1Api:
     if self._client is None:
         a_configuration = k8s_client.Configuration(
             host=self.configuration.host,
             api_key={"authorization": self.configuration.token},
         )
         a_configuration.api_key_prefix["authorization"] = "Bearer"
         a_configuration.verify_ssl = False
         self._client = k8s_client.AppsV1Api(k8s_client.ApiClient(a_configuration))
     return self._client
def main():
    # Configs can be set in Configuration class directly or using helper
    # utility. If no argument provided, the config will be loaded from
    # default location.
    await config.load_kube_config()
    k8s_client = client.ApiClient()
    await utils.create_from_yaml(k8s_client, "nginx-deployment.yaml")
    k8s_api = client.ExtensionsV1beta1Api(k8s_client)
    deps = await k8s_api.read_namespaced_deployment("nginx-deployment",
                                                    "default")
    print("Deployment {0} created".format(deps.metadata.name))
Exemple #9
0
    async def get(cls) -> CustomObjectsApi:
        if cls.k8s_custom_object_api:
            return cls.k8s_custom_object_api
        else:
            try:
                try:
                    await config.load_kube_config()
                except FileNotFoundError:
                    config.load_incluster_config()

                cls.k8s_custom_object_api = client.CustomObjectsApi(client.ApiClient())
                return cls.k8s_custom_object_api
            except Exception:
                logger.exception(f'Failed to initialize {cls.__name__}')
                raise
Exemple #10
0
    async def init(cls, in_cluster: bool,
                   task_runner_service: TaskRunnerService) -> K8sClient:
        if in_cluster:
            # auth inside k8s cluster
            config.load_incluster_config()
            configuration = client.Configuration()
        else:
            # local auth (from kubectl config)
            configuration = client.Configuration()
            await config.load_kube_config(client_configuration=configuration)

        api_client = client.ApiClient(configuration)
        core_client = client.CoreApi(api_client)
        v1_client = client.CoreV1Api(api_client)

        return cls(core_client=core_client,
                   v1_client=v1_client,
                   task_runner_service=task_runner_service)
Exemple #11
0
 async def load(self) -> None:
     self.loader = await config.load_kube_config(
         context=self.context, client_configuration=self.config, persist_config=False
     )
     self.reload_task = asyncio.create_task(
         config.refresh_token(self.loader, self.config)
     )
     self.api = client.ApiClient(configuration=self.config)
     self.core_v1 = client.CoreV1Api(self.api)
     # Build an HTTPX client that can talk to kube-apiserver.
     client_cert = None
     if self.config.cert_file:
         client_cert = (self.config.cert_file, self.config.key_file)
     ssl_context = httpx.create_ssl_context(
         verify=self.config.verify_ssl,
         cert=client_cert,
     )
     if self.config.ssl_ca_cert:
         ssl_context.load_verify_locations(cafile=self.config.ssl_ca_cert)
     self.client = httpx.AsyncClient(
         auth=KubernetesAuth(self.config),
         base_url=urljoin(self.config.host, "api/"),
         verify=ssl_context,
     )
Exemple #12
0
    async def setup(self):
        # Register signal handlers
        loop = asyncio.get_event_loop()
        for s in (signal.SIGTERM, signal.SIGINT):
            loop.add_signal_handler(s, self.handle_shutdown_signal, s)

        # Rate limiter for k8s api calls
        self.rate_limiter = RateLimiter(rate=self.k8s_api_rate_limit,
                                        burst=self.k8s_api_rate_limit_burst)

        # Initialize the kubernetes clients
        try:
            config.load_incluster_config()
        except config.ConfigException:
            await config.load_kube_config()
        self.api_client = client.ApiClient()
        self.core_client = RateLimitedClient(
            client.CoreV1Api(api_client=self.api_client), self.rate_limiter)
        self.custom_client = RateLimitedClient(
            client.CustomObjectsApi(api_client=self.api_client),
            self.rate_limiter)

        # Local state
        self.cluster_info = collections.defaultdict(ClusterInfo)
        self.stopped_clusters = {}

        # Initialize queue and informers
        self.queue = WorkQueue(
            backoff=Backoff(base_delay=self.backoff_base_delay,
                            max_delay=self.backoff_max_delay))
        endpoints_selector = (self.label_selector +
                              ",app.kubernetes.io/component=dask-scheduler")
        self.informers = {
            "cluster":
            Informer(
                parent=self,
                name="cluster",
                client=self.custom_client,
                method="list_cluster_custom_object",
                method_kwargs=dict(
                    group="gateway.dask.org",
                    version=self.crd_version,
                    plural="daskclusters",
                    label_selector=self.label_selector,
                ),
                on_update=self.on_cluster_update,
                on_delete=self.on_cluster_delete,
            ),
            "pod":
            Informer(
                parent=self,
                name="pod",
                client=self.core_client,
                method="list_pod_for_all_namespaces",
                method_kwargs=dict(label_selector=self.label_selector),
                on_update=self.on_pod_update,
                on_delete=self.on_pod_delete,
            ),
            "endpoints":
            Informer(
                parent=self,
                name="endpoints",
                client=self.core_client,
                method="list_endpoints_for_all_namespaces",
                method_kwargs=dict(label_selector=endpoints_selector),
                on_update=self.on_endpoints_update,
                on_delete=self.on_endpoints_delete,
            ),
        }
        await asyncio.wait([i.start() for i in self.informers.values()])
        self.log.debug("All informers started")

        # Initialize reconcilers
        self.reconcilers = [
            asyncio.ensure_future(self.reconciler_loop())
            for _ in range(self.parallelism)
        ]

        # Start background tasks
        self.task_pool = TaskPool()
        self.task_pool.spawn(self.cleanup_expired_cluster_records_loop())

        # Start the aiohttp application
        self.runner = web.AppRunner(
            self.app,
            handle_signals=False,
            access_log_class=AccessLogger,
            access_log=self.log,
        )
        await self.runner.setup()

        host, port = self.address.split(":")
        port = int(port)
        site = web.TCPSite(self.runner,
                           host,
                           port,
                           shutdown_timeout=15.0,
                           backlog=128)
        await site.start()
        self.log.info("%s started!", self.name)
        self.log.info("API listening at http://%s", self.address)
 def __init__(self, return_type=None):
     self._raw_return_type = return_type
     self._stop = False
     self._api_client = client.ApiClient()
     self.resource_version = 0
     self.resp = None
Exemple #14
0
    async def run_inner(self, run_info):
        run_id = run_info['id']
        del run_info

        # This does not run the experiment, it schedules a runner pod by
        # talking to the Kubernetes API. That pod will run the experiment and
        # update the database directly

        k8s_config.load_incluster_config()

        name = self._pod_name(run_id)

        # Load configuration from configmap volume
        with open(os.path.join(self.config_dir, 'runner.pod_spec')) as fp:
            pod_spec = yaml.safe_load(fp)
        with open(os.path.join(self.config_dir, 'runner.namespace')) as fp:
            namespace = fp.read().strip()

        # Make required changes
        for container in pod_spec['containers']:
            if container['name'] == 'runner':
                container['args'] += [str(run_id)]

                # This is mostly used by Tilt
                if os.environ.get('OVERRIDE_RUNNER_IMAGE'):
                    container['image'] = os.environ['OVERRIDE_RUNNER_IMAGE']

        async with k8s_client.ApiClient() as api:
            # Create a Kubernetes pod to run
            v1 = k8s_client.CoreV1Api(api)
            pod = k8s_client.V1Pod(
                api_version='v1',
                kind='Pod',
                metadata=k8s_client.V1ObjectMeta(
                    name=name,
                    labels={
                        'app': 'run',
                        'run': str(run_id),
                    },
                ),
                spec=pod_spec,
            )
            await v1.create_namespaced_pod(
                namespace=namespace,
                body=pod,
            )
            logger.info("Pod created: %s", name)
            PROM_RUNS.inc()

            # Create a service for proxy connections
            svc = k8s_client.V1Service(
                api_version='v1',
                kind='Service',
                metadata=k8s_client.V1ObjectMeta(
                    name=name,
                    labels={
                        'app': 'run',
                        'run': str(run_id),
                    },
                ),
                spec=k8s_client.V1ServiceSpec(
                    selector={
                        'app': 'run',
                        'run': str(run_id),
                    },
                    ports=[
                        k8s_client.V1ServicePort(
                            protocol='TCP',
                            port=5597,
                        ),
                    ],
                ),
            )
            await v1.create_namespaced_service(
                namespace=namespace,
                body=svc,
            )
            logger.info("Service created: %s", name)
Exemple #15
0
Convenience functions for creating pod templates.
"""
from collections import namedtuple
import copy
from kubernetes_asyncio import client
import json

try:
    import yaml
except ImportError:
    yaml = False

# FIXME: ApiClient provides us serialize / deserialize methods,
# but unfortunately also starts a threadpool for no reason! This
# takes up resources, so we try to not make too many.
SERIALIZATION_API_CLIENT = client.ApiClient()


def _set_k8s_attribute(obj, attribute, value):
    """
    Set a specific value on a kubernetes object's attribute

    obj
        an object from Kubernetes Python API client
    attribute
        Should be a Kubernetes API style attribute (with camelCase)
    value
        Can be anything (string, list, dict, k8s objects) that can be
        accepted by the k8s python client
    """
    current_value = None
 def __init__(self, return_type=None):
     self._raw_return_type = return_type
     self._stop = False
     self._api_client = client.ApiClient()