はじめに
Azure Kubernetes Service(AKS) をプログラムから操作する必要があり、 KubernetesClient を使えばリソースの作成や更新ができそうだったので試してみた。
認証情報を取得
操作対象は AKS なので、まずは認証情報を取得しておく必要がある。
az aks get-credentials --name <aks-cluster-name> --resource-group <resource-group-name>
実行すると次のようなメッセージが表示された。
Merged "<aks-cluster-name>" as current context in C:\Users\<user>\.kube\config
リソースを作成
名前空間とデプロイメントとサービスを作成。 AKS が HTTP/2 をサポートしていないようで、ハンドシェイク失敗で嵌った。
using k8s; using k8s.Models; var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); // AKS が HTTP/2 をサポートしていないのか、ハンドシェイクで失敗する。 // HTTP/2 を使わないようにしておく。 config.DisableHttp2 = true; var client = new Kubernetes(config); // 名前空間を作成 const string namespaceName = "<your-namespace-name>"; var newNamespace = new V1Namespace { Metadata = new V1ObjectMeta { Name = namespaceName, Labels = new Dictionary<string, string> { ["name"] = namespaceName, }, }, }; await client.CreateNamespaceAsync(newNamespace); // デプロイメントを作成 const string deploymentName = "<your-deployment-name>"; const string imageName = "<your-image-name>"; var newDeployment = new V1Deployment { Metadata = new V1ObjectMeta { Name = deploymentName, NamespaceProperty = namespaceName, Labels = new Dictionary<string, string> { ["app"] = deploymentName }, }, Spec = new V1DeploymentSpec { Replicas = 1, Template = new V1PodTemplateSpec { Metadata = new V1ObjectMeta { Name = deploymentName, Labels = new Dictionary<string, string> { ["app"] = deploymentName, } }, Spec = new V1PodSpec { NodeSelector = new Dictionary<string, string> { ["kubernetes.io/os"] = "windows", }, Containers = new List<V1Container> { new V1Container { Name = deploymentName, Image = imageName, Ports = new List<V1ContainerPort> { new V1ContainerPort { ContainerPort = 443 } } } } } }, Selector = new V1LabelSelector { MatchLabels = new Dictionary<string, string> { ["app"] = deploymentName, } }, } }; await client.CreateNamespacedDeploymentAsync(newDeployment, namespaceName); // サービスを作成 const string serviceName = deploymentName; var newService = new V1Service { Metadata = new V1ObjectMeta { Name = serviceName, NamespaceProperty = namespaceName, }, Spec = new V1ServiceSpec { Selector = new Dictionary<string, string> { ["app"] = deploymentName, }, Ports = new List<V1ServicePort> { new V1ServicePort { Name = "https", Port = 443, TargetPort = 443, }, }, Type = "LoadBalancer", }, }; await client.CreateNamespacedServiceAsync(newService, namespaceName);
リソースを変更
デプロイメントを変更してみる。
// デプロイメントを変更 var deployment = await client.ReadNamespacedDeploymentAsync(deploymentName, namespaceName); var container = deployment.Spec.Template.Spec.Containers.FirstOrDefault(); if (container != null) { const string envVarName = "CONNECTION_STRING"; const string newEnvVarValue = "NewConnectionString"; var env = container.Env ?? new List<V1EnvVar>(); var envVar = env.FirstOrDefault(x => x.Name == envVarName); if (envVar != null) { envVar.Value = newEnvVarValue; } else { env.Add(new V1EnvVar { Name = envVarName, Value = newEnvVarValue, }); } container.Env = env; await client.ReplaceNamespacedDeploymentAsync(deployment, deploymentName, namespaceName); }
リソースを削除
後始末。
// サービスを削除 await client.DeleteNamespacedServiceAsync(serviceName, namespaceName); // デプロイメントを削除 await client.DeleteNamespacedDeploymentAsync(deploymentName, namespaceName); // 名前空間を削除 await client.DeleteNamespaceAsync(namespaceName);
おわりに
Kubernetes で書いていた YAML ファイルと同じ内容を、C# で組み立てればいいだけだったので、 大して難しくはなかった。HTTP/2 回避して以降はスンナリ。
KubernetesClient の API は素直で好印象だった。