k8s/client
Composer 安装命令:
composer require k8s/client
包简介
A Kubernetes client for PHP.
关键字:
README 文档
README
k8s-client is a Kubernetes API client for PHP.
- HTTP Client agnostic (supports any PSR-18 compatible HTTP Client)
- Supports all major API operations (read, watch, list, patch, delete, exec, attach, logs, port-forward, proxy, etc)
- Supports all Kinds from the Kubernetes API (via auto-generated Kind models with annotations and type-hints).
- Pluggable websocket adapter support (For executing commands in pods, attaching, port-forwarding, etc)
The Kind models are auto-generated nightly for the last 10 versions of the Kubernetes API.
- Installation
- Examples
- List All Pods
- Watch All Deployments in a Namespace
- Create a Pod
- Create a Deployment
- Patch a Deployment
- Get Logs for a Pod
- Follow Logs for a Pod
- Execute a Command in a Pod
- Attach to the Running Process of a Pod
- Download Files from a Pod
- Upload Files to a Pod
- Port Forwarding from a Pod
- Proxy HTTP Requests to a Pod
Installation
Install using composer:
# Install the base client composer require k8s/client # Plan on using the Symfony HttpClient? Install the auto-configuration helper for it. composer require k8s/http-symfony # Plan on needing to use things like executing commands, port-forwarding? # Install a websocket adapter. composer require k8s/ws-ratchet
This library requires a PSR-18 compatible HTTP Client, such as Guzzle or Symfony's HttpClient. It can also be given a PSR-16 compatible Simple Cache implementation to help speed up the library.
Using a Specific Kubernetes API version
Each Kubernetes version may have different resources and operations. If you require a specific version, then you can
require the version of the k8s/api library that you need to use. That library contains all the API specific versions
and models that are consumed by this library.
For instance, to use API version 1.18:
composer require k8s/api:"~1.18.0"
Note: The version of k8s/api does not exactly reflect the version of the Kubernetes API. The patch version of
Kubernetes may not be the same as the k8s/api patch version.
Installing a Websocket Adapter
Certain Kuberenetes API endpoints (such as exec, to run commands in a container) require websockets to communicate. If you need support for this, install one of these adapters:
-
ReactPHP based websocket adapter (https://github.com/k8s-client/ws-ratchet):
composer require k8s/ws-ratchet
-
Swoole based websocket adapter (https://github.com/k8s-client/ws-swoole):
composer require k8s/ws-swoole
See each library's readme for more configuration information.
Constructing the Client Automatically
The easiest way to construct the client is from a pre-defined KubeConfig:
use K8s\Client\K8sFactory; # Attempt to load the default kubeconfig file: $k8s = (new K8sFactory())->loadFromKubeConfig(); # Attempt to load a specific kubeconfig file from a full file path: $k8s = (new K8sFactory())->loadFromKubeConfigFile('/my/special/.kube/config'); # Load a kubeconfig from string kubeconfig data: $k8s = (new K8sFactory())->loadFromKubeConfigData($kubeConfigData);
Note: This requires the use of an HttpClient factory helper. Install one of these packages:
k8s/http-symfony(Symfony based HttpClient)k8s/http-guzzle(Guzzle based HttpClient)
Constructing the Client Manually
Construct the client with your needed options:
use K8s\Client\K8s; use K8s\Client\Options; # Supply the base path to the Kubernetes API endpoint: $options = new Options('https://127.0.0.1:8443'); # To use an API token for authentication, set it in the options: $options->setToken('some-secret-token-value-goes-here'); $k8s = new K8s($options);
Note: If you need to perform certificate based authentication, check the options for the HttpClient you are using. Also check the configuration for the websocket adapter you are using.
Examples
List all Pods
use K8s\Api\Model\Api\Core\v1\Pod; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); /** @var Pod $pod */ foreach ($k8s->listAll(Pod::class) as $pod) { echo sprintf( "%s\t%s\t%s", $pod->getPodIP(), $pod->getNamespace(), $pod->getName() ) . PHP_EOL; }
Watch all Deployments in a Namespace
use K8s\Api\Model\Api\Apps\v1\Deployment; use K8s\Api\Model\ApiMachinery\Apis\Meta\v1\WatchEvent; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $count = 0; # This will watch all deployments in the default namespace. # Change the namespace either in the Options above or as a parameter to the watchNamespaced method below. $k8s->watchNamespaced(function (WatchEvent $event) use (&$count) { $count++; /** @var Deployment $object */ $object = $event->getObject(); echo sprintf( "%s\t%s\t%s\t%s", $event->getType(), $object->getName(), $object->getReplicas(), implode(',', (array)$object->getLabels()) ) . PHP_EOL; # Return false if some condition is met to stop watching. if ($count >= 5) { return false; } }, Deployment::class);
Create a Pod
Using model classes:
use K8s\Api\Model\Api\Core\v1\Container; use K8s\Api\Model\Api\Core\v1\Pod; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Create a pod with the name "web" using the nginx:latest image... $pod = new Pod( 'web', [new Container('web', 'nginx:latest')] ); # Create will return the updated Pod object after creation in this instance... $pod = $k8s->create($pod); var_dump($pod);
Using array data:
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Create a pod with the name "web" using the nginx:latest image... # Create will return the updated Pod object after creation in this instance... $pod = $k8s->create($k8s->newKind([ 'apiVersion' => 'v1', 'kind' => 'Pod', 'metadata' => [ 'name' => 'web', ], 'spec' => [ 'containers' => [ [ 'image' => 'nginx:latest', 'name' => 'web', ], ] ], ])); var_dump($pod);
Create a Deployment
Using model classes:
use K8s\Api\Model\Api\Apps\v1\Deployment; use K8s\Api\Model\ApiMachinery\Apis\Meta\v1\LabelSelector; use K8s\Api\Model\Api\Core\v1\Container; use K8s\Api\Model\Api\Core\v1\PodTemplateSpec; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # All deployments need a "template" that describes the Pod spec $template = new PodTemplateSpec( 'frontend', [new Container('frontend', 'nginx:latest')] ); # The template must have a label that matches the label selector below $template->setLabels(['app' => 'web']); # Create a deployment called "frontend" with the given template. $deployment = new Deployment( 'frontend', new LabelSelector([], ['app' => 'web']), $template ); $result = $k8s->create($deployment); # Create for a deployment will return a Status object for the creation var_dump($result);
Using array data:
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Create a deployment with the given array data matching what you want. $result = $k8s->create($k8s->newKind([ 'apiVersion' => 'apps/v1', 'kind' => 'Deployment', 'metadata' => [ 'name' => 'frontend', 'labels' => [ 'app' => 'web', ] ], 'spec' => [ 'selector' => [ 'matchLabels' => [ 'app' => 'web', ] ], 'template' => [ 'metadata' => [ 'labels' => [ 'app' => 'web', ] ], 'spec' => [ 'containers' => [ [ 'image' => 'nginx:latest', 'name' => 'frontend', ], ], ], ], ], ])); # Create for a deployment will return a Status object for the creation var_dump($result);
Proxy HTTP requests to a Pod
The proxy method sends an HTTP request to a path of a pod, service, or node. It makes no assumptions about what type of HTTP request you want to send, so it accepts a standard PSR-7 RequestInterface and returns a ResponseInterface.
use Http\Discovery\Psr17FactoryDiscovery; use K8s\Api\Model\Api\Core\v1\Pod; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Get the pod you want to proxy to first $pod = $k8s->read('web', Pod::class); # Create the HTTP request you'd like to send to it $requestFactory = Psr17FactoryDiscovery::findRequestFactory(); $request = $requestFactory->createRequest('GET', '/'); # Send the request to proxy, dump the results # The result will be the raw PSR-7 ResultInterface class. $result = $k8s->proxy($pod, $request); echo (string)$result->getBody().PHP_EOL;
Get Logs for a Pod
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Read logs from a pod called "web". # Also append all log entries with a timestamp (ISO8601) $log = $k8s->logs('web') ->withTimestamps() ->read(); var_dump($log);
Follow Logs for a Pod
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $count = 0; # Follow logs from a pod called "web". # Also append all log entries with a timestamp (ISO8601) $k8s->logs('web') ->withTimestamps() ->follow(function (string $log) use (&$count) { $count++; var_dump($log); # Return false at any point to stop following the logs. if ($count >= 5) { return false; } });
Execute a command in a Pod container
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Print the result of "whoami". $k8s->exec('web', '/usr/bin/whoami') ->useStdout() ->run(function (string $channel, string $data) { echo sprintf( '%s => %s', $channel, $data ) . PHP_EOL; });
Attach to the running process of a container in a Pod
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); # Attaches to the main running process of the container in the Pod $k8s->attach('my-pod') # You must specify at least one of useStdout(), useStderr(), useStdin() ->useStdout() # Prints out any STDOUT from the main running process # Can also pass it an instance of ContainerExecInterface ->run(function (string $channel, string $data) { echo sprintf( "%s => %s", $channel, $data ) . PHP_EOL; });
Patch a Deployment
use K8s\Api\Model\Api\Apps\v1\Deployment; use K8s\Client\Patch\JsonPatch; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $patch = new JsonPatch(); # Since labels are an array, this actually replaces existing labels $patch->add('/metadata/labels', ['app' => 'web']); # Replaces the current replica value with 2 $patch->replace('/spec/replicas', 2); # We first need to read the deployment we want to patch. $deployment = $k8s->read('frontend', Deployment::class); # Now we patch the deployment using the patch object. The returned value will be the updated deployment. $deployment = $k8s->patch($deployment, $patch); echo sprintf( 'Replicas: %s, Labels: %s', $deployment->getReplicas(), implode(',', $deployment->getLabels()) ) . PHP_EOL;
Upload Files to a Pod
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $k8s->uploader('my-pod') # Add files from paths. # The first argument is the source location, the second is the destination for it on the container. ->addFile('/path/to/local/file.txt', '/tmp/file.txt') # Add files from string data. # The first argument is the destination path on the container. The second is the file contents as a string. ->addFileFromString('/tmp/hi.txt', 'Oh, hi Mark.') # This actually initiates the upload process. ->upload();
Download Files from a Pod
use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $archive = $k8s->downloader('my-pod') # Optionally choose to compress the downloaded files (gzip -- tar.gz) ->compress() # The file(s) or directory to download. Can be an array of files, or just a single directory or file. ->from('/etc') # If you don't specify to() it will download to a temp file. ->to(__DIR__ . '/' . 'podFiles.tar.gz') # Initiate the download process. ->download(); # The full path to the downloaded files archive.. echo (string)$archive . PHP_EOL; # Extract the downloaded files to a directory called "podFiles" in the current directory.. mkdir(__DIR__ . '/podFiles'); $archive->extractTo(__DIR__ . '/podFiles');
Port Forwarding from a Pod
Note: The below example assumes a pod called portforward-example exists with port 80 serving HTTP (such as a base nginx image).
Create a class that reacts to port forwarding events:
namespace App; use K8s\Client\Websocket\Contract\PortChannelInterface; use K8s\Client\Websocket\Contract\PortForwardInterface; use K8s\Client\Websocket\PortChannels; class PortForwarder implements PortForwardInterface { /** * @var PortChannels */ private $portChannels; /** * @inheritDoc */ public function onInitialize(PortChannels $portChannels) : void { $this->portChannels = $portChannels; # On initialize, send this HTTP request across. # Due to "Connection: close" HTTP instruction, the websocket will close after the response is received. # In a more realistic situation, you'd probably want to keep this open, and react in the onDataReceived method. $data = "GET / HTTP/1.1\r\n"; $data .= "Host: 127.0.0.1\r\n"; $data .= "Connection: close\r\n"; $data .= "Accept: */*\r\n"; $data .= "\r\n"; $this->portChannels->writeToPort(80, $data); } /** * @inheritDoc */ public function onDataReceived(string $data, PortChannelInterface $portChannel) : void { echo sprintf( 'Received data on port %s:', $portChannel->getPortNumber() ) . PHP_EOL; echo $data . PHP_EOL; } /** * @inheritDoc */ public function onErrorReceived(string $data, PortChannelInterface $portChannel) : void { echo sprintf( 'Received error on port %s: %s', $portChannel->getPortNumber(), $data ) . PHP_EOL; } /** * @inheritDoc */ public function onClose() : void { # Do something here to clean-up resources when the connection is closed... } }
Use the above class as a handler for the port forward process:
use App\PortForwarder; use K8s\Client\K8sFactory; $k8s = (new K8sFactory())->loadFromKubeConfig(); $handler = new PortForwarder(); # Assuming a Pod with a basic HTTP port 80 exposed... $k8s->portforward('portforward-example', 80) ->start($handler);
k8s/client 适用场景与选型建议
k8s/client 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.95k 次下载、GitHub Stars 达 23, 最近一次更新时间为 2021 年 01 月 15 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「kubernetes」 「k8s」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 k8s/client 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 k8s/client 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 k8s/client 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Generates Kubernetes API objects from the OpenAPI spec.
Just a simple port of renoki-co/php-k8s for easier access in Laravel.
Add health checks to your Craft website, useful when running inside of Docker
Runtime library to be used with other SDK generated from OpenAPI docs
Deployment command
Production-ready Symfony bundle for comprehensive application health checks with database, Redis, S3, and HTTP endpoint monitoring. Security-first design with auto-tagging support.
统计信息
- 总下载量: 1.95k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 23
- 点击次数: 11
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2021-01-15