PHP 怎么K8s控制器

wen PHP项目 3

本文目录导读:

PHP 怎么K8s控制器

  1. 使用 Kubernetes PHP 客户端库
  2. 使用 Symfony K8s 客户端
  3. 使用 REST API 直接调用
  4. 高级控制器功能
  5. 实际应用场景
  6. 最佳实践
  7. 重要提示

我来详细介绍 PHP 项目中如何使用 Kubernetes 控制器。

使用 Kubernetes PHP 客户端库

安装官方客户端

composer require kubernetes/client

基础控制器示例

<?php
use Kubernetes\Client\Config;
use Kubernetes\Client\Kubernetes;
class K8sController {
    private $kubernetes;
    public function __construct() {
        $config = new Config([
            'base_uri' => getenv('K8S_API_SERVER'), // 如 https://kubernetes.default.svc
            'token' => $this->getServiceAccountToken(),
            'verify' => false
        ]);
        $this->kubernetes = new Kubernetes($config);
    }
    // 获取 Service Account Token
    private function getServiceAccountToken() {
        if (file_exists('/var/run/secrets/kubernetes.io/serviceaccount/token')) {
            return file_get_contents('/var/run/secrets/kubernetes.io/serviceaccount/token');
        }
        return getenv('K8S_TOKEN');
    }
    // 创建 Deployment
    public function createDeployment() {
        $deployment = [
            'apiVersion' => 'apps/v1',
            'kind' => 'Deployment',
            'metadata' => [
                'name' => 'php-app',
                'namespace' => 'default'
            ],
            'spec' => [
                'replicas' => 3,
                'selector' => [
                    'matchLabels' => ['app' => 'php-app']
                ],
                'template' => [
                    'metadata' => ['labels' => ['app' => 'php-app']],
                    'spec' => [
                        'containers' => [[
                            'name' => 'php-app',
                            'image' => 'your-image:latest',
                            'ports' => [['containerPort' => 80]]
                        ]]
                    ]
                ]
            ]
        ];
        $result = $this->kubernetes->createDeployment($deployment);
        return $result;
    }
}

使用 Symfony K8s 客户端

<?php
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\Yaml\Yaml;
class SymfonyK8sController {
    private $client;
    private $baseUrl;
    public function __construct() {
        $this->baseUrl = getenv('KUBERNETES_SERVICE_HOST') . ':' . getenv('KUBERNETES_SERVICE_PORT');
        $this->client = HttpClient::create([
            'base_uri' => "https://{$this->baseUrl}",
            'headers' => [
                'Authorization' => 'Bearer ' . $this->getToken(),
            ],
            'verify_peer' => false,
            'verify_host' => false
        ]);
    }
    private function getToken() {
        // 从 ServiceAccount 读取 token
        $token = file_get_contents('/var/run/secrets/kubernetes.io/serviceaccount/token');
        return trim($token);
    }
    // 获取所有 Pods
    public function listPods() {
        $response = $this->client->request('GET', '/api/v1/namespaces/default/pods');
        return $response->toArray();
    }
    // 创建一个 Service
    public function createService($name, $port) {
        $service = [
            'apiVersion' => 'v1',
            'kind' => 'Service',
            'metadata' => ['name' => $name],
            'spec' => [
                'selector' => ['app' => $name],
                'ports' => [[
                    'port' => $port,
                    'targetPort' => 80
                ]]
            ]
        ];
        $response = $this->client->request('POST', '/api/v1/namespaces/default/services', [
            'json' => $service
        ]);
        return $response->toArray();
    }
}

使用 REST API 直接调用

<?php
class DirectApiController {
    private $ch;
    private $baseUrl;
    public function __construct() {
        $this->baseUrl = 'https://' . getenv('KUBERNETES_SERVICE_HOST') . ':' . getenv('KUBERNETES_SERVICE_PORT');
        $this->ch = curl_init();
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->getToken(),
            'Content-Type: application/json'
        ]);
    }
    private function getToken() {
        return file_get_contents('/var/run/secrets/kubernetes.io/serviceaccount/token');
    }
    public function getPods() {
        curl_setopt($this->ch, CURLOPT_URL, $this->baseUrl . '/api/v1/pods');
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($this->ch);
        return json_decode($response, true);
    }
    public function scaleDeployment($name, $replicas) {
        $url = $this->baseUrl . "/apis/apps/v1/namespaces/default/deployments/{$name}/scale";
        $data = json_encode([
            'spec' => ['replicas' => $replicas]
        ]);
        curl_setopt($this->ch, CURLOPT_URL, $url);
        curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        return curl_exec($this->ch);
    }
}

高级控制器功能

<?php
class AdvancedK8sController {
    private $kubernetes;
    private $cache;
    public function __construct() {
        $this->kubernetes = $this->initK8sClient();
        $this->cache = $this->setupCache();
    }
    // 监控资源变更(使用 Watch API)
    public function watchResources() {
        $watchOptions = [
            'resourceVersion' => $this->getLastResourceVersion(),
            'timeoutSeconds' => 300
        ];
        while (true) {
            try {
                $watcher = $this->kubernetes->watch('/api/v1/pods', $watchOptions);
                foreach ($watcher as $event) {
                    $this->handlePodEvent($event);
                }
            } catch (Exception $e) {
                error_log("Watch error: " . $e->getMessage());
                sleep(5);
                continue;
            }
        }
    }
    private function handlePodEvent($event) {
        switch ($event['type']) {
            case 'ADDED':
                $this->onPodAdded($event['object']);
                break;
            case 'MODIFIED':
                $this->onPodModified($event['object']);
                break;
            case 'DELETED':
                $this->onPodDeleted($event['object']);
                break;
            case 'ERROR':
                $this->handleWatchError($event);
                break;
        }
    }
    // 自定义控制器逻辑
    public function reconcileRequestedResources() {
        // 获取想要的资源状态
        $desiredState = $this->getDesiredResourcesFromDB();
        // 获取当前资源状态
        $currentState = $this->getCurrentResources();
        // 对比并调整
        foreach ($desiredState as $item) {
            if (!isset($currentState[$item['name']])) {
                $this->createResource($item);
            } else {
                $this->updateResource($item);
            }
        }
        // 删除多余的资源
        foreach ($currentState as $key => $resource) {
            if (!isset($desiredState[$key])) {
                $this->deleteResource($resource);
            }
        }
    }
    // 优雅关闭处理
    public function gracefulShutdown() {
        if (file_exists('/var/run/secrets/kubernetes.io/serviceaccount/namespace')) {
            $namespace = file_get_contents('/var/run/secrets/kubernetes.io/serviceaccount/namespace');
            // 标记自身为 Terminating
            $this->updateSelfStatus($namespace, 'Terminating');
            // 等待当前请求完成
            $this->waitForRunningRequests();
            // 清理资源
            $this->cleanupResources();
        }
    }
    private function setupCache() {
        // 使用 Redis 作为缓存
        return new \Redis();
    }
    private function getLastResourceVersion() {
        // 从缓存获取最后处理的版本号
        return $this->cache->get('last_resource_version');
    }
}

实际应用场景

<?php
class DeploymentController extends BaseController {
    // 自动扩缩容
    public function autoScale() {
        $cpuUsage = $this->getMetricsCollector()->getCpuUsage();
        $currentReplicas = $this->getCurrentReplicas();
        if ($cpuUsage > 80 && $currentReplicas < 10) {
            $this->scaleResource('deployments/my-app', $currentReplicas + 1);
        } elseif ($cpuUsage < 20 && $currentReplicas > 1) {
            $this->scaleResource('deployments/my-app', $currentReplicas - 1);
        }
    }
    // 健康检查与故障恢复
    public function checkHealthAndRecover() {
        // 检查 Pod 健康状况
        $unhealthyPods = $this->getUnhealthyPods();
        foreach ($unhealthyPods as $pod) {
            $podName = $pod['metadata']['name'];
            $nodeName = $pod['spec']['nodeName'];
            // 记录故障
            $this->logFault($podName, $nodeName, 'Pod unhealthy');
            // 删除故障 Pod,让 Kubernetes 自动重建
            $this->deletePod($podName);
            // 如果需要,将节点标记为 NoSchedule
            if ($this->isNodeFaulty($nodeName)) {
                $this->cordonNode($nodeName);
            }
        }
    }
    // 配置管理
    public function syncConfigMaps() {
        $configs = $this->getConfigFromDB();
        foreach ($configs as $key => $value) {
            $configMap = [
                'apiVersion' => 'v1',
                'kind' => 'ConfigMap',
                'metadata' => ['name' => "app-config-{$key}"],
                'data' => ['value' => json_encode($value)]
            ];
            $this->createOrUpdateConfigMap($configMap);
        }
    }
}

最佳实践

<?php
class K8sControllerTrait {
    // 重试机制
    private function retryOperation($operation, $maxRetries = 3) {
        $attempts = 0;
        while ($attempts < $maxRetries) {
            try {
                return $operation();
            } catch (KubernetesException $e) {
                $attempts++;
                if ($attempts >= $maxRetries) {
                    throw $e;
                }
                // 指数退避
                sleep(pow(2, $attempts));
            }
        }
    }
    // 日志记录
    private function logK8sOperation($operation, $resource, $result) {
        $logData = [
            'timestamp' => date('c'),
            'operation' => $operation,
            'resource' => $resource,
            'result' => $result,
            'user' => $this->getCurrentUser()
        ];
        // 发送到日志系统
        $this->logService->send($logData, 'k8s_operations');
    }
    // RBAC 检查
    private function checkPermission($namespace, $resource, $verb) {
        $rbacApi = $this->kubernetes->rbacApi();
        $permissions = $rbacApi->checkAccess([
            'namespace' => $namespace,
            'resource' => $resource,
            'verb' => $verb
        ]);
        return $permissions['allowed'] ?? false;
    }
}

重要提示

  1. 安全性:永远不要在代码中硬编码凭证,使用 Kubernetes Secrets
  2. 错误处理:妥善处理 API 限流和超时
  3. 资源清理:实现优雅关闭和资源释放
  4. 测试:Mock Kubernetes API 进行单元测试

需要根据你的具体使用场景(如自动化部署、监控、扩缩容等)选择合适的方法。

抱歉,评论功能暂时关闭!