首页
视频
资源
登录
原
Kubernetes .Net6 集群管理(一)
4454
人阅读
2022/7/5 17:56
总访问:
2594178
评论:
0
收藏:
0
手机
分类:
容器编排
![Kubernetes](https://img.tnblog.net/arcimg/hb/274ef6f115de4c9b8e40ded5deb2f4c2.jpg "Kubernetes") >#Kubernetes .Net6 集群管理(一) [TOC] tn2>对于Kubernetes集群的管理,.net提供了`KubernetesClient`库,可以对k8s集群通过简单的代码进行管理。其底层是通过找到本地的KuberConfig对集群发起的API请求。 安装 ------------ tn2>安装相关依赖库。 ![](https://img.tnblog.net/arcimg/hb/4ab4161b429c4bc18843b86ee9fbbe05.png) ```xml <PackageReference Include="KubernetesClient" Version="8.0.12" /> <!-- 解析库 --> <PackageReference Include="JsonPatch.Net" Version="1.1.2" /> ``` Demo展示 ------------ >### 初始化 tn2>通过`KubernetesClientConfiguration.BuildDefaultConfig();`方法可以获取到我们的本地的KUBECONFIG文件信息,它会先去环境变量中去找`KUBECONFIG`的地址,若没有该环境变量,便去用户名称下的`.kube`目录下去找该文件,如果还没有就判断自己本身是不是在集群里面,是就会通过集群中的`ServiceAccount`拿到相关权限,还不是就返回本地的`8080`的配置。(相关代码如图所示) 接着我们将初始化`Kubernetes`的实例. ```csharp KubernetesClientConfiguration k8sConfig; Kubernetes kubeClient; public TestKubernetesClient() { // 使用凭据构建一个客户端 k8sConfig = KubernetesClientConfiguration.BuildDefaultConfig(); // k8s 实例 kubeClient = new Kubernetes(k8sConfig); } ``` ![](https://img.tnblog.net/arcimg/hb/6e5f066af304420485f6f368375ffb72.png) ![](https://img.tnblog.net/arcimg/hb/4d5de515f3ed467285d02043d071c81b.png) ![](https://img.tnblog.net/arcimg/hb/38e1e4f704954993aadc363d4217bc72.png) 创建pod ------------ tn2>可以通过定义`V1Pod`实例执行`CreateNamespacedPodAsync`方法进行创建相关Pod。 这里我们在`default`命名空间下创建一个镜像为`burlyluo/nettoolbox`名为`busybox`的pod,并为它添加`run=busybox`标签。 ```csharp [DataTestMethod] [DataRow("default", "busybox", "burlyluo/nettoolbox", "run=busybox")] public async Task TestCreatePod(string mynamespace, string Podname,string image,string labels) { #region 创建一个pod var pod = new V1Pod() { ApiVersion = "v1", Kind = "Pod", Spec = new V1PodSpec() { Containers = new List<V1Container>() }, Metadata = new V1ObjectMeta() { Labels = new Dictionary<string, string>() } }; // 取名 pod.Metadata.Name = Podname; // 标记标签 if (!string.IsNullOrEmpty(labels)) { var labelsDictionary = labels.Split(',').Select(x => x.Split('=')).ToDictionary(x => x[0], y => y[1]); foreach (var item in labelsDictionary) { pod.Metadata.Labels[item.Key] = item.Value; } } // 创建一个容器 var container = new V1Container(Podname) { // Command // Args // Env // Ports // 定义镜像 Image = image, // 拉取镜像策略 ImagePullPolicy = "IfNotPresent" }; pod.Spec.Containers.Add(container); #endregion // 创建pod await kubeClient.CreateNamespacedPodAsync(pod, mynamespace).ConfigureAwait(false); } ``` tn2>执行该测试方法后,我们通过命令查看已经创建成功了。 ```bash kubectl get pod ``` ![](https://img.tnblog.net/arcimg/hb/53db4429bdba47119800c89bdaec6c29.png) 获取Pod信息 ------------ tn2>我们这里我们通过`ListNamespacedPodAsync`方法找到label相匹配的所有pod信息,输出了Pod的名称以及它的IP。 ```csharp [DataTestMethod] [DataRow("default", "run=busybox")] public async Task TestGetPod(string mynamespace,string labels) { // 获取现有的Pod var pods = await kubeClient.ListNamespacedPodAsync(mynamespace, null, null, null, labels); foreach (var pod in pods.Items) { Debug.WriteLine($"现有的 Lable[{labels}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}"); } } ``` ![](https://img.tnblog.net/arcimg/hb/baca759504834946bc6250c2efeb4ac0.png) tn2>我们还可以通过服务的方式去找到相关的Pod。方法为找到相关服务,获取服务所选取的标签再拿这些标签去找到相关Pod。 ```csharp /// <summary> /// 通过服务获取pod /// </summary> /// <param name="mynamespace"></param> /// <param name="labels"></param> /// <returns></returns> [DataTestMethod] [DataRow("swprinter", "swpapi")] public async Task TestGetServicePod(string mynamespace, string servicename) { var myservice = await kubeClient.ReadNamespacedServiceAsync(servicename, mynamespace); var labels = myservice.Spec.Selector.Select(x => $"{x.Key}={x.Value}") .ToArray() ; var labelString = string.Join(',', labels); // 获取现有的Pod var pods = await kubeClient.ListNamespacedPodAsync(mynamespace, null, null, null, labelString); foreach (var pod in pods.Items) { Debug.WriteLine($"现有的 Lable[{labelString}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}"); } } ``` ![](https://img.tnblog.net/arcimg/hb/b93a88007e5149358365aaa30b0fab27.png) 添加标签 ------------ tn2>我们为默认名称空间下的带有`run=busybox`标签的Pod,添加新的的标签`name=busybox`,注意在修改完成后通过`PatchNamespacedPodAsync`方法进行保存修改。 ```csharp [DataTestMethod] [DataRow("default", "run=busybox", "name=busybox")] public async Task TestSetPod(string mynamespace, string searchlabels, string nowlabels) { // 获取现有的Pod var pods = await kubeClient.ListNamespacedPodAsync(mynamespace, null, null, null, searchlabels); // label分割 var _nowlabels = nowlabels.Split(',') .Select(x => x.Split('=')) .ToDictionary(x => x[0], y => y[1]); // 获取共有部分 var all_labels = pods.Items.SelectMany(x => x.Metadata.Labels.Keys).Union(_nowlabels.Keys); // 获取差的部分 foreach (V1Pod pod in pods.Items) { // 修改前 Debug.WriteLine($"修改前 Label--[{Newtonsoft.Json.JsonConvert.SerializeObject(pod.Metadata.Labels)}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}"); var old = JsonSerializer.SerializeToDocument(pod); foreach (var label in _nowlabels) { var boolvalue = pod.Metadata.Labels.TryAdd(label.Key, label.Value); } var expected = JsonSerializer.SerializeToDocument(pod); var patch = old.CreatePatch(expected); var patchn = new V1Patch(patch, V1Patch.PatchType.JsonPatch); await kubeClient.PatchNamespacedPodAsync(patchn, pod.Name(), mynamespace); // 修改后 Debug.WriteLine($"修改后 Label--[{Newtonsoft.Json.JsonConvert.SerializeObject(pod.Metadata.Labels)}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}"); } } ``` ![](https://img.tnblog.net/arcimg/hb/652bfcb93fa741eab6daf94d0dab81f5.png) ![](https://img.tnblog.net/arcimg/hb/83fe6c70ae234196aa49bcbad0ee2ef0.png) tn2>删除就是Remove什么的就不讲了。。。 监控事件情况 ------------ tn2>我们通过下面的代码可以监控Pod的事件,其实这里就是一个`Watch`方法内部带了委托,然后上了个锁防止程序退出。我们先执行,然后打开窗口执行删除pod的命令。 ```csharp /// <summary> /// 监控命名空间下pod的情况与事件 /// 监听新创建的Pod /// </summary> /// <param name="mynamespace"></param> /// <returns></returns> [DataTestMethod] [DataRow("default")] public async Task TestWatchPod(string mynamespace) { // 获取现有的Pod消息任务 using var listTask = await kubeClient.CoreV1.ListNamespacedPodWithHttpMessagesAsync(mynamespace, watch: true).ConfigureAwait(false); var connectionClosed = new AsyncManualResetEvent(); // 监听新的pod创建情况 listTask.Watch<V1Pod, V1PodList>( (type, item) => { // 过滤掉Add类型并不新创建的pod情况 if (type == WatchEventType.Added && !string.IsNullOrEmpty(item?.Metadata.Name)) { return; } Debug.WriteLine($"监视到事件 '{type}',相关 Pod: {item!.Metadata.Name}"); }, error => { Debug.WriteLine($"监视到错误 '{error.GetType().FullName}'"); }, connectionClosed.Set); Debug.WriteLine("等待新的 Pod 事件..."); await connectionClosed.WaitAsync(); } ``` ```bash kubectl delete pod/busybox ``` ![](https://img.tnblog.net/arcimg/hb/47f4e30700384a3e9d63a6b6546583c7.png) 在集群中监控 ------------ ![](https://img.tnblog.net/arcimg/hb/b58b08f58f2141eab2dafb886b652916.png) tn2>首先我们创建一个K8sWatch的控制台项目,安装相关依赖包,然后将我们刚刚的代码放入到Program.cs中。 ```csharp using k8s; using k8s.Models; using Nito.AsyncEx; // 使用凭据构建一个客户端 var k8sConfig = KubernetesClientConfiguration.BuildDefaultConfig(); // k8s 实例 var kubeClient = new Kubernetes(k8sConfig); // 获取现有的Pod消息任务 using var listTask = await kubeClient.CoreV1.ListNamespacedPodWithHttpMessagesAsync("default", watch: true).ConfigureAwait(false); var connectionClosed = new AsyncManualResetEvent(); // 监听新的pod创建情况 listTask.Watch<V1Pod, V1PodList>( (type, item) => { // 过滤掉Add类型并不新创建的pod情况 if (type == WatchEventType.Added && !string.IsNullOrEmpty(item?.Metadata.Name)) { return; } Console.WriteLine($"监视到事件 '{type}',相关 Pod: {item!.Metadata.Name}"); }, error => { Console.WriteLine($"监视到错误 '{error.GetType().FullName}'"); }, connectionClosed.Set); Console.WriteLine("等待新的 Pod 事件..."); await connectionClosed.WaitAsync(); ``` tn2>然后通过以下命令发布Linux的可执行程序。 ```csharp dotnet publish -r linux-x64 -p:PublishSingleFile=true ``` ![](https://img.tnblog.net/arcimg/hb/7930d7a2483c4964b0b455e13fdd49d9.png) tn2>然后我们在`rbac-good-permission.yaml`文件下定义相关的`ServiceAccount`以及`Role`使我们需要运行的程序具有一定的权限,这里权限我们给得不多,只给了对pod的`get`、`list`、`watch`三个权限。 ```yaml kind: ServiceAccount apiVersion: v1 metadata: name: pod-operator namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-operator-role namespace: default rules: - apiGroups: [ "" ] resources: [ "pods", "pods/exec" ] verbs: [ "get", "list", "watch" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-operator-role namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-operator-role subjects: - kind: ServiceAccount name: pod-operator namespace: default ``` ```bash kubectl create -f .\rbac-good-permission.yaml ``` tn2>接着我们编写一个测试的Pod文件(`test-pod.yaml`),并执行。 ```csharp apiVersion: v1 kind: Pod metadata: labels: app: test name: test-pod spec: serviceAccountName: pod-operator containers: - image: mcr.microsoft.com/dotnet/runtime:6.0 imagePullPolicy: IfNotPresent name: tester args: - infinity command: - sleep ``` ```bash kubectl create -f .\test-pod.yaml ``` tn2>然后将我们程序放入到该pod中,并执行。随后打开另一个窗口添加新的pod进行测试监控,发现没有问题。 ```csharp # 到发布的路径下 cd D:\Learning\k8sPlugs\K8sWatch\bin\Debug\net6.0\linux-x64\publish\ # -c 表示指定的容器 kubectl cp K8sWatch default/test-pod:/home/ -c tester # 进入容器 kubectl exec -it test-pod -c tester -- /bin/bash cd /home chmod +x ./K8sWatch ./K8sWatch ``` ```csharp kubectl run busybox --image=burlyluo/nettoolbox ``` ![](https://img.tnblog.net/arcimg/hb/525b2af8eed94f38b928d457a9cc4dbf.png) tn2>然后我们退出,创建一个`rbac-no-permission.yaml`并更新`pod-operator-role`角色的权限使它没有任何访问权限。 ```bash --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-operator-role namespace: default rules: - apiGroups: [ "" ] resources: [ "pods" ] verbs: [ "" ] ``` ```bash kubectl delete role/pod-operator-role kubectl apply -f rbac-no-permission.yaml ``` tn2>再次运行它将报错。 ![](https://img.tnblog.net/arcimg/hb/e6bbb0702e44459d9fd411890d608117.png)
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
👈{{preArticle.title}}
👉{{nextArticle.title}}
评价
{{titleitem}}
{{titleitem}}
{{item.content}}
{{titleitem}}
{{titleitem}}
{{item.content}}
尘叶心繁
这一世以无限游戏为使命!
博主信息
排名
6
文章
6
粉丝
16
评论
8
文章类别
.net后台框架
168篇
linux
17篇
linux中cve
1篇
windows中cve
0篇
资源分享
10篇
Win32
3篇
前端
28篇
传说中的c
4篇
Xamarin
9篇
docker
15篇
容器编排
101篇
grpc
4篇
Go
15篇
yaml模板
1篇
理论
2篇
更多
Sqlserver
4篇
云产品
39篇
git
3篇
Unity
1篇
考证
2篇
RabbitMq
23篇
Harbor
1篇
Ansible
8篇
Jenkins
17篇
Vue
1篇
Ids4
18篇
istio
1篇
架构
2篇
网络
7篇
windbg
4篇
AI
18篇
threejs
2篇
人物
1篇
嵌入式
2篇
python
13篇
HuggingFace
8篇
pytorch
9篇
opencv
6篇
最新文章
最新评价
{{item.articleTitle}}
{{item.blogName}}
:
{{item.content}}
关于我们
ICP备案 :
渝ICP备18016597号-1
网站信息:
2018-2024
TNBLOG.NET
技术交流:
群号656732739
联系我们:
contact@tnblog.net
欢迎加群
欢迎加群交流技术